gdiplus: Added GdipSetPageScale/GdipGetPageScale.
[wine] / dlls / ntdll / actctx.c
1 /*
2  * Activation contexts
3  *
4  * Copyright 2004 Jon Griffiths
5  * Copyright 2007 Eric Pouech
6  * Copyright 2007 Jacek Caban for CodeWeavers
7  * Copyright 2007 Alexandre Julliard
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28 #include <stdio.h>
29
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "winternl.h"
35 #include "ntdll_misc.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
40
41 #define ACTCTX_FLAGS_ALL (\
42  ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
43  ACTCTX_FLAG_LANGID_VALID |\
44  ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
45  ACTCTX_FLAG_RESOURCE_NAME_VALID |\
46  ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
47  ACTCTX_FLAG_APPLICATION_NAME_VALID |\
48  ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
49  ACTCTX_FLAG_HMODULE_VALID )
50
51 #define ACTCTX_MAGIC       0xC07E3E11
52
53 /* we don't want to include winuser.h */
54 #define RT_MANIFEST                        ((ULONG_PTR)24)
55 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
56
57 typedef struct
58 {
59     const char*         ptr;
60     unsigned int        len;
61 } xmlstr_t;
62
63 typedef struct
64 {
65     const char*         ptr;
66     const char*         end;
67 } xmlbuf_t;
68
69 struct file_info
70 {
71     ULONG               type;
72     WCHAR              *info;
73 };
74
75 struct version
76 {
77     USHORT              major;
78     USHORT              minor;
79     USHORT              build;
80     USHORT              revision;
81 };
82
83 enum assembly_id_type
84 {
85     TYPE_NONE,
86     TYPE_WIN32
87 };
88
89 struct assembly_identity
90 {
91     WCHAR                *name;
92     WCHAR                *arch;
93     WCHAR                *public_key;
94     WCHAR                *language;
95     struct version        version;
96     enum assembly_id_type type;
97     BOOL                  optional;
98 };
99
100 struct entity
101 {
102     DWORD kind;
103     union
104     {
105         struct
106         {
107             WCHAR *tlbid;
108             WCHAR *version;
109             WCHAR *helpdir;
110         } typelib;
111         struct
112         {
113             WCHAR *clsid;
114         } comclass;
115         struct {
116             WCHAR *iid;
117             WCHAR *name;
118         } proxy;
119         struct
120         {
121             WCHAR *name;
122         } class;
123         struct
124         {
125             WCHAR *name;
126             WCHAR *clsid;
127         } clrclass;
128         struct
129         {
130             WCHAR *name;
131             WCHAR *clsid;
132         } clrsurrogate;
133     } u;
134 };
135
136 struct entity_array
137 {
138     struct entity        *base;
139     unsigned int          num;
140     unsigned int          allocated;
141 };
142
143 struct dll_redirect
144 {
145     WCHAR                *name;
146     WCHAR                *hash;
147     struct entity_array   entities;
148 };
149
150 enum assembly_type
151 {
152     APPLICATION_MANIFEST,
153     ASSEMBLY_MANIFEST
154 };
155
156 struct assembly
157 {
158     enum assembly_type       type;
159     struct assembly_identity id;
160     struct file_info         manifest;
161     BOOL                     no_inherit;
162     struct dll_redirect     *dlls;
163     unsigned int             num_dlls;
164     unsigned int             allocated_dlls;
165     struct entity_array      entities;
166 };
167
168 typedef struct _ACTIVATION_CONTEXT
169 {
170     ULONG               magic;
171     int                 ref_count;
172     struct file_info    config;
173     struct file_info    appdir;
174     struct assembly    *assemblies;
175     unsigned int        num_assemblies;
176     unsigned int        allocated_assemblies;
177 } ACTIVATION_CONTEXT;
178
179 struct actctx_loader
180 {
181     ACTIVATION_CONTEXT       *actctx;
182     struct assembly_identity *dependencies;
183     unsigned int              num_dependencies;
184     unsigned int              allocated_dependencies;
185 };
186
187 #define ASSEMBLY_ELEM                   "assembly"
188 #define ASSEMBLYIDENTITY_ELEM           "assemblyIdentity"
189 #define BINDINGREDIRECT_ELEM            "bindingRedirect"
190 #define CLRCLASS_ELEM                   "clrClass"
191 #define CLRSURROGATE_ELEM               "clrSurrogate"
192 #define COMCLASS_ELEM                   "comClass"
193 #define COMINTERFACEEXTERNALPROXYSTUB_ELEM "comInterfaceExternalProxyStub"
194 #define COMINTERFACEPROXYSTUB_ELEM      "comInterfaceProxyStub"
195 #define DEPENDENCY_ELEM                 "dependency"
196 #define DEPENDENTASSEMBLY_ELEM          "dependentAssembly"
197 #define DESCRIPTION_ELEM                "description"
198 #define FILE_ELEM                       "file"
199 #define HASH_ELEM                       "asmv2:hash"
200 #define NOINHERIT_ELEM                  "noInherit"
201 #define NOINHERITABLE_ELEM              "noInheritable"
202 #define TYPELIB_ELEM                    "typelib"
203 #define WINDOWCLASS_ELEM                "windowClass"
204
205 #define ELEM_END(elem) "/" elem
206
207 #define CLSID_ATTR                      "clsid"
208 #define HASH_ATTR                       "hash"
209 #define HASHALG_ATTR                    "hashalg"
210 #define HELPDIR_ATTR                    "helpdir"
211 #define IID_ATTR                        "iid"
212 #define LANGUAGE_ATTR                   "language"
213 #define MANIFESTVERSION_ATTR            "manifestVersion"
214 #define NAME_ATTR                       "name"
215 #define NEWVERSION_ATTR                 "newVersion"
216 #define OLDVERSION_ATTR                 "oldVersion"
217 #define OPTIONAL_ATTR                   "optional"
218 #define PROCESSORARCHITECTURE_ATTR      "processorArchitecture"
219 #define PUBLICKEYTOKEN_ATTR             "publicKeyToken"
220 #define TLBID_ATTR                      "tlbid"
221 #define TYPE_ATTR                       "type"
222 #define VERSION_ATTR                    "version"
223 #define XMLNS_ATTR                      "xmlns"
224
225 #define MANIFESTV1_NAMESPACE            "urn:schemas-microsoft-com:asm.v1"
226 #define MANIFESTV3_NAMESPACE            "urn:schemas-microsoft-com:asm.v3"
227
228 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
229
230
231 static WCHAR *strdupW(const WCHAR* str)
232 {
233     WCHAR*      ptr;
234
235     if (!str) return NULL;
236     if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
237         return NULL;
238     return strcpyW(ptr, str);
239 }
240
241 static WCHAR *xmlstrdupW(const xmlstr_t* str)
242 {
243     WCHAR *strW;
244     int len = wine_utf8_mbstowcs( 0, str->ptr, str->len, NULL, 0 );
245
246     if (len == -1) return NULL;
247     if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
248     {
249         wine_utf8_mbstowcs( 0, str->ptr, str->len, strW, len );
250         strW[len] = 0;
251     }
252     return strW;
253 }
254
255 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const char* str)
256 {
257     return !strncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
258 }
259
260 static inline BOOL isxmlspace( char ch )
261 {
262     return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
263 }
264
265 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
266 {
267     return debugstr_an(str->ptr, str->len);
268 }
269
270 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
271 {
272     struct assembly *assembly;
273
274     if (actctx->num_assemblies == actctx->allocated_assemblies)
275     {
276         void *ptr;
277         unsigned int new_count;
278         if (actctx->assemblies)
279         {
280             new_count = actctx->allocated_assemblies * 2;
281             ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
282                                      actctx->assemblies, new_count * sizeof(*assembly) );
283         }
284         else
285         {
286             new_count = 4;
287             ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
288         }
289         if (!ptr) return NULL;
290         actctx->assemblies = ptr;
291         actctx->allocated_assemblies = new_count;
292     }
293
294     assembly = &actctx->assemblies[actctx->num_assemblies++];
295     assembly->type = at;
296     return assembly;
297 }
298
299 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
300 {
301     if (assembly->num_dlls == assembly->allocated_dlls)
302     {
303         void *ptr;
304         unsigned int new_count;
305         if (assembly->dlls)
306         {
307             new_count = assembly->allocated_dlls * 2;
308             ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
309                                      assembly->dlls, new_count * sizeof(*assembly->dlls) );
310         }
311         else
312         {
313             new_count = 4;
314             ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
315         }
316         if (!ptr) return NULL;
317         assembly->dlls = ptr;
318         assembly->allocated_dlls = new_count;
319     }
320     return &assembly->dlls[assembly->num_dlls++];
321 }
322
323 static void free_assembly_identity(struct assembly_identity *ai)
324 {
325     RtlFreeHeap( GetProcessHeap(), 0, ai->name );
326     RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
327     RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
328     RtlFreeHeap( GetProcessHeap(), 0, ai->language );
329 }
330
331 static struct entity* add_entity(struct entity_array *array, DWORD kind)
332 {
333     struct entity*      entity;
334
335     if (array->num == array->allocated)
336     {
337         void *ptr;
338         unsigned int new_count;
339         if (array->base)
340         {
341             new_count = array->allocated * 2;
342             ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
343                                      array->base, new_count * sizeof(*array->base) );
344         }
345         else
346         {
347             new_count = 4;
348             ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
349         }
350         if (!ptr) return NULL;
351         array->base = ptr;
352         array->allocated = new_count;
353     }
354     entity = &array->base[array->num++];
355     entity->kind = kind;
356     return entity;
357 }
358
359 static void free_entity_array(struct entity_array *array)
360 {
361     unsigned int i;
362     for (i = 0; i < array->num; i++)
363     {
364         struct entity *entity = &array->base[i];
365         switch (entity->kind)
366         {
367         case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
368             RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
369             break;
370         case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
371             RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
372             RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.name);
373             break;
374         case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
375             RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
376             RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.version);
377             RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
378             break;
379         case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
380             RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
381             break;
382         case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
383             RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.name);
384             RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.clsid);
385             break;
386         case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
387             RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
388             RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
389             break;
390         default:
391             FIXME("Unknown entity kind %d\n", entity->kind);
392         }
393     }
394     RtlFreeHeap( GetProcessHeap(), 0, array->base );
395 }
396
397 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
398                                       struct assembly_identity* ai)
399 {
400     /* FIXME: should check that the passed ai isn't already in the list */
401     if (acl->num_dependencies == acl->allocated_dependencies)
402     {
403         void *ptr;
404         unsigned int new_count;
405         if (acl->dependencies)
406         {
407             new_count = acl->allocated_dependencies * 2;
408             ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
409                                     new_count * sizeof(acl->dependencies[0]));
410         }
411         else
412         {
413             new_count = 4;
414             ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
415         }
416         if (!ptr) return FALSE;
417         acl->dependencies = ptr;
418         acl->allocated_dependencies = new_count;
419     }
420     acl->dependencies[acl->num_dependencies++] = *ai;
421
422     return TRUE;
423 }
424
425 static void free_depend_manifests(struct actctx_loader* acl)
426 {
427     unsigned int i;
428     for (i = 0; i < acl->num_dependencies; i++)
429         free_assembly_identity(&acl->dependencies[i]);
430     RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
431 }
432
433 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
434 {
435     ACTIVATION_CONTEXT *actctx = h;
436
437     if (!h || h == INVALID_HANDLE_VALUE) return NULL;
438     switch (actctx->magic)
439     {
440     case ACTCTX_MAGIC:
441         return actctx;
442     default:
443         return NULL;
444     }
445 }
446
447 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
448 {
449     interlocked_xchg_add( &actctx->ref_count, 1 );
450 }
451
452 static void actctx_release( ACTIVATION_CONTEXT *actctx )
453 {
454     if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
455     {
456         unsigned int i, j;
457
458         for (i = 0; i < actctx->num_assemblies; i++)
459         {
460             struct assembly *assembly = &actctx->assemblies[i];
461             for (j = 0; j < assembly->num_dlls; j++)
462             {
463                 struct dll_redirect *dll = &assembly->dlls[j];
464                 free_entity_array( &dll->entities );
465                 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
466                 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
467             }
468             RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
469             RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
470             free_entity_array( &assembly->entities );
471             free_assembly_identity(&assembly->id);
472         }
473         RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
474         RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
475         RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
476         actctx->magic = 0;
477         RtlFreeHeap( GetProcessHeap(), 0, actctx );
478     }
479 }
480
481 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
482                           BOOL* error, BOOL* end)
483 {
484     const char* ptr;
485
486     *error = TRUE;
487
488     while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
489         xmlbuf->ptr++;
490
491     if (xmlbuf->ptr == xmlbuf->end) return FALSE;
492
493     if (*xmlbuf->ptr == '/')
494     {
495         xmlbuf->ptr++;
496         if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
497             return FALSE;
498
499         xmlbuf->ptr++;
500         *end = TRUE;
501         *error = FALSE;
502         return FALSE;
503     }
504
505     if (*xmlbuf->ptr == '>')
506     {
507         xmlbuf->ptr++;
508         *error = FALSE;
509         return FALSE;
510     }
511
512     ptr = xmlbuf->ptr;
513     while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
514
515     if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
516
517     name->ptr = xmlbuf->ptr;
518     name->len = ptr-xmlbuf->ptr;
519     xmlbuf->ptr = ptr;
520
521     ptr++;
522     if (ptr == xmlbuf->end || *ptr != '\"') return FALSE;
523
524     value->ptr = ++ptr;
525     if (ptr == xmlbuf->end) return FALSE;
526
527     ptr = memchr(ptr, '\"', xmlbuf->end - ptr);
528     if (!ptr)
529     {
530         xmlbuf->ptr = xmlbuf->end;
531         return FALSE;
532     }
533
534     value->len = ptr - value->ptr;
535     xmlbuf->ptr = ptr + 1;
536
537     if (xmlbuf->ptr == xmlbuf->end) return FALSE;
538
539     *error = FALSE;
540     return TRUE;
541 }
542
543 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
544 {
545     const char* ptr;
546
547     for (;;)
548     {
549         ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
550         if (!ptr)
551         {
552             xmlbuf->ptr = xmlbuf->end;
553             return FALSE;
554         }
555         ptr++;
556         if (ptr + 3 < xmlbuf->end && !strncmp( ptr, "!--", 3 )) /* skip comment */
557         {
558             for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
559                 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
560
561             if (ptr + 3 > xmlbuf->end)
562             {
563                 xmlbuf->ptr = xmlbuf->end;
564                 return FALSE;
565             }
566             xmlbuf->ptr = ptr + 3;
567         }
568         else break;
569     }
570
571     xmlbuf->ptr = ptr;
572     while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
573         ptr++;
574
575     elem->ptr = xmlbuf->ptr;
576     elem->len = ptr - xmlbuf->ptr;
577     xmlbuf->ptr = ptr;
578     return xmlbuf->ptr != xmlbuf->end;
579 }
580
581 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
582 {
583     /* FIXME: parse attributes */
584     const char *ptr;
585
586     for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
587     {
588         if (ptr[0] == '?' && ptr[1] == '>')
589         {
590             xmlbuf->ptr = ptr + 2;
591             return TRUE;
592         }
593     }
594     return FALSE;
595 }
596
597 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
598 {
599     const char *ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
600
601     if (!ptr) return FALSE;
602
603     content->ptr = xmlbuf->ptr;
604     content->len = ptr - xmlbuf->ptr;
605     xmlbuf->ptr = ptr;
606
607     return TRUE;
608 }
609
610 static BOOL parse_version(const xmlstr_t *str, struct version *version)
611 {
612     unsigned int ver[4];
613     unsigned int pos;
614     const char *curr;
615
616     /* major.minor.build.revision */
617     ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
618     for (curr = str->ptr; curr < str->ptr + str->len; curr++)
619     {
620         if (*curr >= '0' && *curr <= '9')
621         {
622             ver[pos] = ver[pos] * 10 + *curr - '0';
623             if (ver[pos] >= 0x10000) goto error;
624         }
625         else if (*curr == '.')
626         {
627             if (++pos >= 4) goto error;
628         }
629         else goto error;
630     }
631     version->major = ver[0];
632     version->minor = ver[1];
633     version->build = ver[2];
634     version->revision = ver[3];
635     return TRUE;
636
637 error:
638     FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
639     return FALSE;
640 }
641
642 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const char* name)
643 {
644     xmlstr_t    elem;
645     if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
646     if (xmlstr_cmp(&elem, name)) return TRUE;
647     FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
648     return FALSE;
649 }
650
651 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
652 {
653     xmlstr_t    attr_name, attr_value;
654     BOOL        error;
655
656     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
657     {
658         WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
659              debugstr_xmlstr(&attr_value));
660     }
661     return !error;
662 }
663
664 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
665 {
666     BOOL end = FALSE;
667     return parse_expect_no_attr(xmlbuf, &end) && !end;
668 }
669
670 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
671 {
672     xmlstr_t attr_name, attr_value, elem;
673     BOOL end = FALSE, error, ret = TRUE;
674
675     while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
676     if(error || end) return end;
677
678     while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
679     {
680         if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
681            !strncmp(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
682             break;
683         else
684             ret = parse_unknown_elem(xmlbuf, &elem);
685     }
686
687     return ret && parse_end_element(xmlbuf);
688 }
689
690 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
691                                          struct assembly_identity* ai)
692 {
693     xmlstr_t    attr_name, attr_value;
694     BOOL        end = FALSE, error;
695
696     TRACE("\n");
697
698     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
699     {
700         if (xmlstr_cmp(&attr_name, NAME_ATTR))
701         {
702             if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
703         }
704         else if (xmlstr_cmp(&attr_name, TYPE_ATTR))
705         {
706             if (!xmlstr_cmp(&attr_value, "win32"))
707             {
708                 FIXME("wrong type attr %s\n", debugstr_xmlstr(&attr_value));
709                 return FALSE;
710             }
711             ai->type = TYPE_WIN32;
712         }
713         else if (xmlstr_cmp(&attr_name, VERSION_ATTR))
714         {
715             if (!parse_version(&attr_value, &ai->version)) return FALSE;
716         }
717         else if (xmlstr_cmp(&attr_name, PROCESSORARCHITECTURE_ATTR))
718         {
719             if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
720         }
721         else if (xmlstr_cmp(&attr_name, PUBLICKEYTOKEN_ATTR))
722         {
723             if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
724         }
725         else if (xmlstr_cmp(&attr_name, LANGUAGE_ATTR))
726         {
727             WARN("Unsupported yet language attribute (%s)\n",
728                  debugstr_xmlstr(&attr_value));
729             if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
730         }
731         else
732         {
733             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
734                  debugstr_xmlstr(&attr_value));
735         }
736     }
737
738     if (error || end) return end;
739     return parse_expect_elem(xmlbuf, ELEM_END(ASSEMBLYIDENTITY_ELEM)) && parse_end_element(xmlbuf);
740 }
741
742 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
743 {
744     xmlstr_t    attr_name, attr_value;
745     BOOL        end = FALSE, error;
746     struct entity*      entity;
747
748     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
749         return FALSE;
750
751     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
752     {
753         if (xmlstr_cmp(&attr_name, CLSID_ATTR))
754         {
755             if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
756         }
757         else
758         {
759             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
760         }
761     }
762
763     if (error || end) return end;
764     return parse_expect_elem(xmlbuf, ELEM_END(COMCLASS_ELEM)) && parse_end_element(xmlbuf);
765 }
766
767 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
768 {
769     xmlstr_t    attr_name, attr_value;
770     BOOL        end = FALSE, error;
771     struct entity*      entity;
772
773     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
774         return FALSE;
775
776     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
777     {
778         if (xmlstr_cmp(&attr_name, IID_ATTR))
779         {
780             if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
781         }
782         if (xmlstr_cmp(&attr_name, NAME_ATTR))
783         {
784             if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
785         }
786         else
787         {
788             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
789         }
790     }
791
792     if (error || end) return end;
793     return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEPROXYSTUB_ELEM)) && parse_end_element(xmlbuf);
794 }
795
796 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
797 {
798     xmlstr_t    attr_name, attr_value;
799     BOOL        end = FALSE, error;
800     struct entity*      entity;
801
802     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
803         return FALSE;
804
805     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
806     {
807         if (xmlstr_cmp(&attr_name, TLBID_ATTR))
808         {
809             if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
810         }
811         if (xmlstr_cmp(&attr_name, VERSION_ATTR))
812         {
813             if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
814         }
815         if (xmlstr_cmp(&attr_name, HELPDIR_ATTR))
816         {
817             if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
818         }
819         else
820         {
821             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
822         }
823     }
824
825     if (error || end) return end;
826     return parse_expect_elem(xmlbuf, ELEM_END(TYPELIB_ELEM)) && parse_end_element(xmlbuf);
827 }
828
829 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
830 {
831     xmlstr_t    elem, content;
832     BOOL        end = FALSE, ret = TRUE;
833     struct entity*      entity;
834
835     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
836         return FALSE;
837
838     if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
839     if (end) return FALSE;
840
841     if (!parse_text_content(xmlbuf, &content)) return FALSE;
842
843     if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
844
845     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
846     {
847         if (xmlstr_cmp(&elem, ELEM_END(WINDOWCLASS_ELEM)))
848         {
849             ret = parse_end_element(xmlbuf);
850             break;
851         }
852         else
853         {
854             WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
855             ret = parse_unknown_elem(xmlbuf, &elem);
856         }
857     }
858
859     return ret;
860 }
861
862 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
863 {
864     xmlstr_t    attr_name, attr_value;
865     BOOL        end = FALSE, error;
866
867     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
868     {
869         if (xmlstr_cmp(&attr_name, OLDVERSION_ATTR))
870         {
871             FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
872         }
873         else if (xmlstr_cmp(&attr_name, NEWVERSION_ATTR))
874         {
875             FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
876         }
877         else
878         {
879             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
880         }
881     }
882
883     if (error || end) return end;
884     return parse_expect_elem(xmlbuf, ELEM_END(BINDINGREDIRECT_ELEM)) && parse_end_element(xmlbuf);
885 }
886
887 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
888 {
889     xmlstr_t    elem, content;
890     BOOL        end = FALSE, ret = TRUE;
891
892     if (!parse_expect_no_attr(xmlbuf, &end) || end ||
893         !parse_text_content(xmlbuf, &content))
894         return FALSE;
895
896     TRACE("Got description %s\n", debugstr_xmlstr(&content));
897
898     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
899     {
900         if (xmlstr_cmp(&elem, ELEM_END(DESCRIPTION_ELEM)))
901         {
902             ret = parse_end_element(xmlbuf);
903             break;
904         }
905         else
906         {
907             WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
908             ret = parse_unknown_elem(xmlbuf, &elem);
909         }
910     }
911
912     return ret;
913 }
914
915 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
916                                                          struct assembly* assembly)
917 {
918     xmlstr_t            attr_name, attr_value;
919     BOOL                end = FALSE, error;
920     struct entity*      entity;
921
922     entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
923     if (!entity) return FALSE;
924
925     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
926     {
927         if (xmlstr_cmp(&attr_name, IID_ATTR))
928         {
929             if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
930         }
931         if (xmlstr_cmp(&attr_name, NAME_ATTR))
932         {
933             if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
934         }
935         else
936         {
937             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
938         }
939     }
940
941     if (error || end) return end;
942     return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEEXTERNALPROXYSTUB_ELEM)) &&
943         parse_end_element(xmlbuf);
944 }
945
946 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
947 {
948     xmlstr_t    attr_name, attr_value;
949     BOOL        end = FALSE, error;
950     struct entity*      entity;
951
952     entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
953     if (!entity) return FALSE;
954
955     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
956     {
957         if (xmlstr_cmp(&attr_name, NAME_ATTR))
958         {
959             if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
960         }
961         else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
962         {
963             if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
964         }
965         else
966         {
967             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
968         }
969     }
970
971     if (error || end) return end;
972     return parse_expect_elem(xmlbuf, ELEM_END(CLRCLASS_ELEM)) && parse_end_element(xmlbuf);
973 }
974
975 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
976 {
977     xmlstr_t    attr_name, attr_value;
978     BOOL        end = FALSE, error;
979     struct entity*      entity;
980
981     entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
982     if (!entity) return FALSE;
983
984     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
985     {
986         if (xmlstr_cmp(&attr_name, NAME_ATTR))
987         {
988             if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
989         }
990         else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
991         {
992             if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
993         }
994         else
995         {
996             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
997         }
998     }
999
1000     if (error || end) return end;
1001     return parse_expect_elem(xmlbuf, ELEM_END(CLRSURROGATE_ELEM)) && parse_end_element(xmlbuf);
1002 }
1003
1004 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1005 {
1006     struct assembly_identity    ai;
1007     xmlstr_t                    elem;
1008     BOOL                        end = FALSE, ret = TRUE;
1009
1010     if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1011
1012     memset(&ai, 0, sizeof(ai));
1013     ai.optional = optional;
1014
1015     if (!parse_expect_elem(xmlbuf, ASSEMBLYIDENTITY_ELEM) ||
1016         !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1017         return FALSE;
1018
1019     TRACE( "adding %s\n", debugstr_w(ai.name) );
1020
1021     /* store the newly found identity for later loading */
1022     if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1023
1024     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1025     {
1026         if (xmlstr_cmp(&elem, ELEM_END(DEPENDENTASSEMBLY_ELEM)))
1027         {
1028             ret = parse_end_element(xmlbuf);
1029             break;
1030         }
1031         else if (xmlstr_cmp(&elem, BINDINGREDIRECT_ELEM))
1032         {
1033             ret = parse_binding_redirect_elem(xmlbuf);
1034         }
1035         else
1036         {
1037             WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1038             ret = parse_unknown_elem(xmlbuf, &elem);
1039         }
1040     }
1041
1042     return ret;
1043 }
1044
1045 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1046 {
1047     xmlstr_t attr_name, attr_value, elem;
1048     BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1049
1050     TRACE("\n");
1051
1052     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1053     {
1054         if (xmlstr_cmp(&attr_name, OPTIONAL_ATTR))
1055         {
1056             optional = xmlstr_cmp( &attr_value, "yes" );
1057             TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
1058         }
1059         else
1060         {
1061             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1062         }
1063     }
1064
1065     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1066     {
1067         if (xmlstr_cmp(&elem, ELEM_END(DEPENDENCY_ELEM)))
1068         {
1069             ret = parse_end_element(xmlbuf);
1070             break;
1071         }
1072         else if (xmlstr_cmp(&elem, DEPENDENTASSEMBLY_ELEM))
1073         {
1074             ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1075         }
1076         else
1077         {
1078             WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1079             ret = parse_unknown_elem(xmlbuf, &elem);
1080         }
1081     }
1082
1083     return ret;
1084 }
1085
1086 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1087 {
1088     BOOL end = FALSE;
1089
1090     if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1091     return end ||
1092         (parse_expect_elem(xmlbuf, ELEM_END(NOINHERIT_ELEM)) && parse_end_element(xmlbuf));
1093 }
1094
1095 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1096 {
1097     BOOL end = FALSE;
1098
1099     if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1100     return end ||
1101         (parse_expect_elem(xmlbuf, ELEM_END(NOINHERITABLE_ELEM)) && parse_end_element(xmlbuf));
1102 }
1103
1104 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1105 {
1106     xmlstr_t    attr_name, attr_value, elem;
1107     BOOL        end = FALSE, error, ret = TRUE;
1108     struct dll_redirect* dll;
1109
1110     if (!(dll = add_dll_redirect(assembly))) return FALSE;
1111
1112     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1113     {
1114         if (xmlstr_cmp(&attr_name, NAME_ATTR))
1115         {
1116             if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1117             TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1118         }
1119         else if (xmlstr_cmp(&attr_name, HASH_ATTR))
1120         {
1121             if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1122         }
1123         else if (xmlstr_cmp(&attr_name, HASHALG_ATTR))
1124         {
1125             if (!xmlstr_cmp(&attr_value, "SHA1"))
1126                 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
1127         }
1128         else
1129         {
1130             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1131         }
1132     }
1133
1134     if (error || !dll->name) return FALSE;
1135     if (end) return TRUE;
1136
1137     while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1138     {
1139         if (xmlstr_cmp(&elem, ELEM_END(FILE_ELEM)))
1140         {
1141             ret = parse_end_element(xmlbuf);
1142             break;
1143         }
1144         else if (xmlstr_cmp(&elem, COMCLASS_ELEM))
1145         {
1146             ret = parse_com_class_elem(xmlbuf, dll);
1147         }
1148         else if (xmlstr_cmp(&elem, COMINTERFACEPROXYSTUB_ELEM))
1149         {
1150             ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1151         }
1152         else if (xmlstr_cmp(&elem, HASH_ELEM))
1153         {
1154             WARN(HASH_ELEM " (undocumented) not supported\n");
1155             ret = parse_unknown_elem(xmlbuf, &elem);
1156         }
1157         else if (xmlstr_cmp(&elem, TYPELIB_ELEM))
1158         {
1159             ret = parse_typelib_elem(xmlbuf, dll);
1160         }
1161         else if (xmlstr_cmp(&elem, WINDOWCLASS_ELEM))
1162         {
1163             ret = parse_window_class_elem(xmlbuf, dll);
1164         }
1165         else
1166         {
1167             WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1168             ret = parse_unknown_elem( xmlbuf, &elem );
1169         }
1170     }
1171
1172     return ret;
1173 }
1174
1175 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1176                                 struct assembly* assembly,
1177                                 struct assembly_identity* expected_ai)
1178 {
1179     xmlstr_t    attr_name, attr_value, elem;
1180     BOOL        end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1181
1182     TRACE("(%p)\n", xmlbuf);
1183
1184     while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1185     {
1186         if (xmlstr_cmp(&attr_name, MANIFESTVERSION_ATTR))
1187         {
1188             if (!xmlstr_cmp(&attr_value, "1.0"))
1189             {
1190                 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
1191                 return FALSE;
1192             }
1193             version = TRUE;
1194         }
1195         else if (xmlstr_cmp(&attr_name, XMLNS_ATTR))
1196         {
1197             if (!xmlstr_cmp(&attr_value, MANIFESTV1_NAMESPACE) &&
1198                 !xmlstr_cmp(&attr_value, MANIFESTV3_NAMESPACE))
1199             {
1200                 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
1201                 return FALSE;
1202             }
1203             xmlns = TRUE;
1204         }
1205         else
1206         {
1207             WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1208         }
1209     }
1210
1211     if (error || end || !xmlns || !version) return FALSE;
1212     if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1213
1214     if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, NOINHERIT_ELEM))
1215     {
1216         if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1217             return FALSE;
1218         assembly->no_inherit = TRUE;
1219     }
1220
1221     if (xmlstr_cmp(&elem, NOINHERITABLE_ELEM))
1222     {
1223         if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1224             return FALSE;
1225     }
1226     else if (assembly->type == ASSEMBLY_MANIFEST && assembly->no_inherit)
1227         return FALSE;
1228
1229     if (xmlstr_cmp(&elem, ASSEMBLYIDENTITY_ELEM))
1230     {
1231         if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
1232         ret = next_xml_elem(xmlbuf, &elem);
1233
1234         if (expected_ai)
1235         {
1236             /* FIXME: more tests */
1237             if (assembly->type == ASSEMBLY_MANIFEST &&
1238                 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
1239             {
1240                 FIXME("wrong version\n");
1241                 return FALSE;
1242             }
1243         }
1244     }
1245
1246     while (ret)
1247     {
1248         if (xmlstr_cmp(&elem, ELEM_END(ASSEMBLY_ELEM)))
1249         {
1250             ret = parse_end_element(xmlbuf);
1251             break;
1252         }
1253         else if (xmlstr_cmp(&elem, DESCRIPTION_ELEM))
1254         {
1255             ret = parse_description_elem(xmlbuf);
1256         }
1257         else if (xmlstr_cmp(&elem, COMINTERFACEEXTERNALPROXYSTUB_ELEM))
1258         {
1259             ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1260         }
1261         else if (xmlstr_cmp(&elem, DEPENDENCY_ELEM))
1262         {
1263             ret = parse_dependency_elem(xmlbuf, acl);
1264         }
1265         else if (xmlstr_cmp(&elem, FILE_ELEM))
1266         {
1267             ret = parse_file_elem(xmlbuf, assembly);
1268         }
1269         else if (xmlstr_cmp(&elem, CLRCLASS_ELEM))
1270         {
1271             ret = parse_clr_class_elem(xmlbuf, assembly);
1272         }
1273         else if (xmlstr_cmp(&elem, CLRSURROGATE_ELEM))
1274         {
1275             ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1276         }
1277         else
1278         {
1279             WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1280             ret = parse_unknown_elem(xmlbuf, &elem);
1281         }
1282         if (ret) ret = next_xml_elem(xmlbuf, &elem);
1283     }
1284
1285     return ret;
1286 }
1287
1288 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1289                                 LPCWSTR filename, xmlbuf_t* xmlbuf )
1290 {
1291     xmlstr_t            elem;
1292     struct assembly*    assembly;
1293
1294     TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) );
1295
1296     if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
1297         return STATUS_SXS_CANT_GEN_ACTCTX;
1298
1299     if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
1300     assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1301                                                       : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1302
1303     if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1304
1305     if (xmlstr_cmp(&elem, "?xml") &&
1306         (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1307         return STATUS_SXS_CANT_GEN_ACTCTX;
1308
1309     if (!xmlstr_cmp(&elem, ASSEMBLY_ELEM))
1310     {
1311         FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
1312         return STATUS_SXS_CANT_GEN_ACTCTX;
1313     }
1314
1315     if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1316     {
1317         FIXME("failed to parse manifest %s\n", debugstr_w(filename) );
1318         return STATUS_SXS_CANT_GEN_ACTCTX;
1319     }
1320
1321     if (next_xml_elem(xmlbuf, &elem))
1322     {
1323         FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
1324         return STATUS_SXS_CANT_GEN_ACTCTX;
1325     }
1326
1327     if (xmlbuf->ptr != xmlbuf->end)
1328     {
1329         FIXME("parse error\n");
1330         return STATUS_SXS_CANT_GEN_ACTCTX;
1331     }
1332     return STATUS_SUCCESS;
1333 }
1334
1335 static NTSTATUS open_nt_file( HANDLE handle, UNICODE_STRING *name )
1336 {
1337     OBJECT_ATTRIBUTES attr;
1338     IO_STATUS_BLOCK io;
1339
1340     attr.Length = sizeof(attr);
1341     attr.RootDirectory = 0;
1342     attr.Attributes = OBJ_CASE_INSENSITIVE;
1343     attr.ObjectName = name;
1344     attr.SecurityDescriptor = NULL;
1345     attr.SecurityQualityOfService = NULL;
1346     return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
1347 }
1348
1349 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
1350 {
1351     NTSTATUS status;
1352     ULONG magic;
1353     LDR_MODULE *pldr;
1354
1355     LdrLockLoaderLock(0, NULL, &magic);
1356     status = LdrFindEntryForAddress( module, &pldr );
1357     if (status == STATUS_SUCCESS)
1358     {
1359         if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1360                                             pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1361         {
1362             memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1363             str->Length = pldr->FullDllName.Length;
1364             str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1365         }
1366         else status = STATUS_NO_MEMORY;
1367     }
1368     LdrUnlockLoaderLock(0, magic);
1369     return status;
1370 }
1371
1372 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1373                                         LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang )
1374 {
1375     NTSTATUS status;
1376     UNICODE_STRING nameW;
1377     LDR_RESOURCE_INFO info;
1378     const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1379     void *ptr;
1380
1381     TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), hModule, debugstr_w(filename) );
1382
1383     if (!resname) return STATUS_INVALID_PARAMETER;
1384
1385     info.Type = RT_MANIFEST;
1386     info.Language = lang;
1387     if (!((ULONG_PTR)resname >> 16))
1388     {
1389         info.Name = (ULONG_PTR)resname;
1390         status = LdrFindResource_U(hModule, &info, 3, &entry);
1391     }
1392     else if (resname[0] == '#')
1393     {
1394         ULONG value;
1395         RtlInitUnicodeString(&nameW, resname + 1);
1396         if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1397             return STATUS_INVALID_PARAMETER;
1398         info.Name = value;
1399         status = LdrFindResource_U(hModule, &info, 3, &entry);
1400     }
1401     else
1402     {
1403         RtlCreateUnicodeString(&nameW, resname);
1404         RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1405         info.Name = (ULONG_PTR)nameW.Buffer;
1406         status = LdrFindResource_U(hModule, &info, 3, &entry);
1407         RtlFreeUnicodeString(&nameW);
1408     }
1409     if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1410
1411     if (status == STATUS_SUCCESS)
1412     {
1413         xmlbuf_t buf;
1414         buf.ptr = ptr;
1415         buf.end = buf.ptr + entry->Size;
1416         status = parse_manifest(acl, ai, filename, &buf);
1417     }
1418     return status;
1419 }
1420
1421 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1422                                          LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang )
1423 {
1424     HANDLE              mapping;
1425     OBJECT_ATTRIBUTES   attr;
1426     LARGE_INTEGER       size;
1427     LARGE_INTEGER       offset;
1428     NTSTATUS            status;
1429     SIZE_T              count;
1430     void               *base;
1431
1432     TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
1433
1434     attr.Length                   = sizeof(attr);
1435     attr.RootDirectory            = 0;
1436     attr.ObjectName               = NULL;
1437     attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1438     attr.SecurityDescriptor       = NULL;
1439     attr.SecurityQualityOfService = NULL;
1440
1441     size.QuadPart = 0;
1442     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1443                               &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1444     if (status != STATUS_SUCCESS) return status;
1445
1446     offset.QuadPart = 0;
1447     count = 0;
1448     base = NULL;
1449     status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1450                                  &count, ViewShare, 0, PAGE_READONLY );
1451     NtClose( mapping );
1452     if (status != STATUS_SUCCESS) return status;
1453
1454     if (RtlImageNtHeader(base)) /* we got a PE file */
1455     {
1456         HANDLE module = (HMODULE)((ULONG_PTR)base | 1);  /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1457         status = get_manifest_in_module( acl, ai, filename, module, resname, lang );
1458     }
1459     else status = STATUS_INVALID_IMAGE_FORMAT;
1460
1461     NtUnmapViewOfSection( GetCurrentProcess(), base );
1462     return status;
1463 }
1464
1465 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1466                                                LPCWSTR filename, HANDLE file )
1467 {
1468     HANDLE              mapping;
1469     OBJECT_ATTRIBUTES   attr;
1470     LARGE_INTEGER       size;
1471     LARGE_INTEGER       offset;
1472     NTSTATUS            status;
1473     SIZE_T              count;
1474     void               *base;
1475     xmlbuf_t            buf;
1476
1477     TRACE( "loading manifest file %s\n", debugstr_w(filename) );
1478
1479     attr.Length                   = sizeof(attr);
1480     attr.RootDirectory            = 0;
1481     attr.ObjectName               = NULL;
1482     attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1483     attr.SecurityDescriptor       = NULL;
1484     attr.SecurityQualityOfService = NULL;
1485
1486     size.QuadPart = 0;
1487     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1488                               &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1489     if (status != STATUS_SUCCESS) return status;
1490
1491     offset.QuadPart = 0;
1492     count = 0;
1493     base = NULL;
1494     status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1495                                  &count, ViewShare, 0, PAGE_READONLY );
1496     NtClose( mapping );
1497     if (status != STATUS_SUCCESS) return status;
1498
1499     buf.ptr = base;
1500     buf.end = buf.ptr + count;
1501     status = parse_manifest(acl, ai, filename, &buf);
1502
1503     NtUnmapViewOfSection( GetCurrentProcess(), base );
1504     return status;
1505 }
1506
1507 /* try to load the .manifest file associated to the file */
1508 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1509                                                      LPCWSTR filename, HMODULE module, LPCWSTR resname )
1510 {
1511     static const WCHAR fmtW[] = { '.','%','l','u',0 };
1512     WCHAR *buffer;
1513     NTSTATUS status;
1514     UNICODE_STRING nameW;
1515     HANDLE file;
1516     ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
1517
1518     if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1519
1520     TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
1521
1522     if (module) /* use the module filename */
1523     {
1524         UNICODE_STRING name;
1525
1526         if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1527         {
1528             if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1529             strcatW( name.Buffer, dotManifestW );
1530             if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1531                 status = STATUS_NO_SUCH_FILE;
1532             RtlFreeUnicodeString( &name );
1533         }
1534         if (status) return status;
1535     }
1536     else
1537     {
1538         if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1539                                         (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1540             return STATUS_NO_MEMORY;
1541         strcpyW( buffer, filename );
1542         if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1543         strcatW( buffer, dotManifestW );
1544         RtlInitUnicodeString( &nameW, buffer );
1545     }
1546
1547     status = open_nt_file( &file, &nameW );
1548     if (status == STATUS_SUCCESS)
1549     {
1550         status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1551         NtClose( file );
1552     }
1553     RtlFreeUnicodeString( &nameW );
1554     return status;
1555 }
1556
1557 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
1558 {
1559     static const WCHAR lookup_fmtW[] =
1560         {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1561          '*', /* FIXME */
1562          '.','m','a','n','i','f','e','s','t',0};
1563
1564     WCHAR *lookup, *ret = NULL;
1565     UNICODE_STRING lookup_us;
1566     IO_STATUS_BLOCK io;
1567     unsigned int data_pos = 0, data_len;
1568     char buffer[8192];
1569
1570     if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
1571                                     (strlenW(ai->arch) + strlenW(ai->name)
1572                                      + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
1573                                     + sizeof(lookup_fmtW) )))
1574         return NULL;
1575
1576     sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
1577     RtlInitUnicodeString( &lookup_us, lookup );
1578
1579     NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1580                           FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
1581     if (io.u.Status == STATUS_SUCCESS)
1582     {
1583         FILE_BOTH_DIR_INFORMATION *dir_info;
1584         WCHAR *tmp;
1585         ULONG build, revision;
1586
1587         data_len = io.Information;
1588
1589         for (;;)
1590         {
1591             if (data_pos >= data_len)
1592             {
1593                 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1594                                       FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
1595                 if (io.u.Status != STATUS_SUCCESS) break;
1596                 data_len = io.Information;
1597                 data_pos = 0;
1598             }
1599             dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
1600
1601             if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
1602             else data_pos = data_len;
1603
1604             tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
1605             build = atoiW(tmp);
1606             if (build < ai->version.build) continue;
1607             tmp = strchrW(tmp, '.') + 1;
1608             revision = atoiW(tmp);
1609             if (build == ai->version.build && revision < ai->version.revision)
1610                 continue;
1611             ai->version.build = build;
1612             ai->version.revision = revision;
1613             if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
1614             {
1615                 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
1616                 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
1617             }
1618             break;
1619         }
1620     }
1621     else WARN("no matching file for %s\n", debugstr_w(lookup));
1622     RtlFreeHeap( GetProcessHeap(), 0, lookup );
1623     return ret;
1624 }
1625
1626 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
1627 {
1628     struct assembly_identity    sxs_ai;
1629     UNICODE_STRING              path_us;
1630     OBJECT_ATTRIBUTES           attr;
1631     IO_STATUS_BLOCK             io;
1632     WCHAR *path, *file = NULL;
1633     HANDLE handle;
1634
1635     static const WCHAR manifest_dirW[] =
1636         {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
1637
1638     if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
1639
1640     if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, windows_dir.Length + sizeof(manifest_dirW) )))
1641         return STATUS_NO_MEMORY;
1642
1643     memcpy( path, windows_dir.Buffer, windows_dir.Length );
1644     memcpy( path + windows_dir.Length/sizeof(WCHAR), manifest_dirW, sizeof(manifest_dirW) );
1645
1646     if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
1647     {
1648         RtlFreeHeap( GetProcessHeap(), 0, path );
1649         return STATUS_NO_SUCH_FILE;
1650     }
1651     RtlFreeHeap( GetProcessHeap(), 0, path );
1652
1653     attr.Length = sizeof(attr);
1654     attr.RootDirectory = 0;
1655     attr.Attributes = OBJ_CASE_INSENSITIVE;
1656     attr.ObjectName = &path_us;
1657     attr.SecurityDescriptor = NULL;
1658     attr.SecurityQualityOfService = NULL;
1659
1660     if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1661                      FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
1662     {
1663         sxs_ai = *ai;
1664         file = lookup_manifest_file( handle, &sxs_ai );
1665         NtClose( handle );
1666     }
1667     if (!file)
1668     {
1669         RtlFreeUnicodeString( &path_us );
1670         return STATUS_NO_SUCH_FILE;
1671     }
1672
1673     /* append file name to directory path */
1674     if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
1675                                     path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
1676     {
1677         RtlFreeHeap( GetProcessHeap(), 0, file );
1678         RtlFreeUnicodeString( &path_us );
1679         return STATUS_NO_MEMORY;
1680     }
1681
1682     path[path_us.Length/sizeof(WCHAR)] = '\\';
1683     strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
1684     RtlFreeHeap( GetProcessHeap(), 0, file );
1685     RtlInitUnicodeString( &path_us, path );
1686
1687     if (!open_nt_file( &handle, &path_us ))
1688     {
1689         io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, handle);
1690         NtClose( handle );
1691     }
1692     else io.u.Status = STATUS_NO_SUCH_FILE;
1693
1694     RtlFreeUnicodeString( &path_us );
1695     return io.u.Status;
1696 }
1697
1698 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
1699                                 struct assembly_identity* ai)
1700 {
1701     static const WCHAR dotDllW[] = {'.','d','l','l',0};
1702     unsigned int i;
1703     WCHAR *buffer, *p;
1704     NTSTATUS status;
1705     UNICODE_STRING nameW;
1706     HANDLE file;
1707
1708     if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
1709
1710     /* FIXME: add support for language specific lookup */
1711
1712     nameW.Buffer = NULL;
1713     if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1714                                     (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1715         return STATUS_NO_MEMORY;
1716
1717     /* lookup in appdir\name.dll
1718      *           appdir\name.manifest
1719      *           appdir\name\name.dll
1720      *           appdir\name\name.manifest
1721      */
1722     strcpyW( buffer, acl->actctx->appdir.info );
1723     p = buffer + strlenW(buffer);
1724     for (i = 0; i < 2; i++)
1725     {
1726         *p++ = '\\';
1727         strcpyW( p, ai->name );
1728         p += strlenW(p);
1729
1730         strcpyW( p, dotDllW );
1731         if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1732         {
1733             status = open_nt_file( &file, &nameW );
1734             if (!status)
1735             {
1736                 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file,
1737                                                   (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
1738                 NtClose( file );
1739                 break;
1740             }
1741             RtlFreeUnicodeString( &nameW );
1742         }
1743
1744         strcpyW( p, dotManifestW );
1745         if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1746         {
1747             status = open_nt_file( &file, &nameW );
1748             if (!status)
1749             {
1750                 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1751                 NtClose( file );
1752                 break;
1753             }
1754             RtlFreeUnicodeString( &nameW );
1755         }
1756     }
1757     RtlFreeUnicodeString( &nameW );
1758     return STATUS_SXS_ASSEMBLY_NOT_FOUND;
1759 }
1760
1761 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
1762 {
1763     NTSTATUS status = STATUS_SUCCESS;
1764     unsigned int i;
1765
1766     for (i = 0; i < acl->num_dependencies; i++)
1767     {
1768         if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
1769         {
1770             if (!acl->dependencies[i].optional)
1771             {
1772                 FIXME( "Could not find dependent assembly %s\n", debugstr_w(acl->dependencies[i].name) );
1773                 status = STATUS_SXS_CANT_GEN_ACTCTX;
1774                 break;
1775             }
1776         }
1777     }
1778     /* FIXME should now iterate through all refs */
1779     return status;
1780 }
1781
1782
1783 /***********************************************************************
1784  * RtlCreateActivationContext (NTDLL.@)
1785  *
1786  * Create an activation context.
1787  *
1788  * FIXME: function signature/prototype is wrong
1789  */
1790 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
1791 {
1792     const ACTCTXW *pActCtx = ptr;  /* FIXME: not the right structure */
1793     ACTIVATION_CONTEXT *actctx;
1794     UNICODE_STRING nameW;
1795     struct assembly *assembly;
1796     ULONG lang = 0;
1797     NTSTATUS status = STATUS_NO_MEMORY;
1798     HANDLE file = 0;
1799     struct actctx_loader acl;
1800
1801     TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
1802
1803     if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx) ||
1804         (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
1805         return STATUS_INVALID_PARAMETER;
1806
1807     if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
1808         return STATUS_NO_MEMORY;
1809
1810     actctx->magic = ACTCTX_MAGIC;
1811     actctx->ref_count = 1;
1812
1813     if (!(assembly = add_assembly( actctx, APPLICATION_MANIFEST ))) goto error;
1814     if (!(assembly->id.name = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) )))
1815         goto error;
1816     assembly->id.version.major = 1;
1817     assembly->id.version.minor = 0;
1818     assembly->id.version.build = 0;
1819     assembly->id.version.revision = 0;
1820     assembly->manifest.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1821     assembly->manifest.info = NULL;
1822
1823     actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1824     actctx->config.info = NULL;
1825     actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1826     if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
1827     {
1828         if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
1829     }
1830     else
1831     {
1832         UNICODE_STRING dir;
1833         WCHAR *p;
1834
1835         if ((status = get_module_filename( NtCurrentTeb()->Peb->ImageBaseAddress, &dir, 0 )))
1836             goto error;
1837         if ((p = strrchrW( dir.Buffer, '\\' ))) *p = 0;
1838         actctx->appdir.info = dir.Buffer;
1839     }
1840
1841     nameW.Buffer = NULL;
1842     if (pActCtx->lpSource)
1843     {
1844         if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
1845         {
1846             status = STATUS_NO_SUCH_FILE;
1847             goto error;
1848         }
1849         status = open_nt_file( &file, &nameW );
1850         if (status)
1851         {
1852             RtlFreeUnicodeString( &nameW );
1853             goto error;
1854         }
1855     }
1856
1857     acl.actctx = actctx;
1858     acl.dependencies = NULL;
1859     acl.num_dependencies = 0;
1860     acl.allocated_dependencies = 0;
1861
1862     if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
1863
1864     if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
1865     {
1866         /* if we have a resource it's a PE file */
1867         if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
1868         {
1869             status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule,
1870                                              pActCtx->lpResourceName, lang );
1871             if (status)
1872                 /* FIXME: what to do if pActCtx->lpSource is set */
1873                 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule,
1874                                                               pActCtx->lpResourceName );
1875         }
1876         else if (pActCtx->lpSource)
1877         {
1878             status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file,
1879                                               pActCtx->lpResourceName, lang );
1880             if (status)
1881                 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL,
1882                                                               pActCtx->lpResourceName );
1883         }
1884         else status = STATUS_INVALID_PARAMETER;
1885     }
1886     else
1887     {
1888         status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file );
1889     }
1890
1891     if (file) NtClose( file );
1892     RtlFreeUnicodeString( &nameW );
1893
1894     if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
1895     free_depend_manifests( &acl );
1896
1897     if (status == STATUS_SUCCESS) *handle = actctx;
1898     else actctx_release( actctx );
1899     return status;
1900
1901 error:
1902     if (file) NtClose( file );
1903     actctx_release( actctx );
1904     return status;
1905 }
1906
1907
1908 /***********************************************************************
1909  *              RtlAddRefActivationContext (NTDLL.@)
1910  */
1911 void WINAPI RtlAddRefActivationContext( HANDLE handle )
1912 {
1913     ACTIVATION_CONTEXT *actctx;
1914
1915     if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
1916 }
1917
1918
1919 /******************************************************************
1920  *              RtlReleaseActivationContext (NTDLL.@)
1921  */
1922 void WINAPI RtlReleaseActivationContext( HANDLE handle )
1923 {
1924     ACTIVATION_CONTEXT *actctx;
1925
1926     if ((actctx = check_actctx( handle ))) actctx_release( actctx );
1927 }
1928
1929
1930 /******************************************************************
1931  *              RtlActivateActivationContext (NTDLL.@)
1932  */
1933 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, ULONG_PTR *cookie )
1934 {
1935     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1936
1937     TRACE( "%p %p\n", handle, cookie );
1938
1939     if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
1940         return STATUS_NO_MEMORY;
1941
1942     frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1943     frame->ActivationContext = handle;
1944     frame->Flags = 0;
1945     NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
1946     RtlAddRefActivationContext( handle );
1947
1948     *cookie = (ULONG_PTR)frame;
1949     return STATUS_SUCCESS;
1950 }
1951
1952
1953 /***********************************************************************
1954  *              RtlDeactivateActivationContext (NTDLL.@)
1955  */
1956 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
1957 {
1958     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
1959
1960     TRACE( "%x %lx\n", flags, cookie );
1961
1962     /* find the right frame */
1963     top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1964     for (frame = top; frame; frame = frame->Previous)
1965         if ((ULONG_PTR)frame == cookie) break;
1966
1967     if (!frame)
1968         RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
1969
1970     if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
1971         RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
1972
1973     /* pop everything up to and including frame */
1974     NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
1975
1976     while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
1977     {
1978         frame = top->Previous;
1979         RtlReleaseActivationContext( top->ActivationContext );
1980         RtlFreeHeap( GetProcessHeap(), 0, top );
1981         top = frame;
1982     }
1983 }
1984
1985
1986 /******************************************************************
1987  *              RtlFreeThreadActivationContextStack (NTDLL.@)
1988  */
1989 void WINAPI RtlFreeThreadActivationContextStack(void)
1990 {
1991     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1992
1993     frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1994     while (frame)
1995     {
1996         RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
1997         RtlReleaseActivationContext( frame->ActivationContext );
1998         RtlFreeHeap( GetProcessHeap(), 0, frame );
1999         frame = prev;
2000     }
2001     NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
2002 }
2003
2004
2005 /******************************************************************
2006  *              RtlGetActiveActivationContext (NTDLL.@)
2007  */
2008 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
2009 {
2010     if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2011     {
2012         *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2013         RtlAddRefActivationContext( *handle );
2014     }
2015     else
2016         *handle = 0;
2017
2018     return STATUS_SUCCESS;
2019 }
2020
2021
2022 /******************************************************************
2023  *              RtlIsActivationContextActive (NTDLL.@)
2024  */
2025 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
2026 {
2027     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2028
2029     for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
2030         if (frame->ActivationContext == handle) return TRUE;
2031     return FALSE;
2032 }