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