xref: /reactos/sdk/lib/rtl/actctx.c (revision 6a31fe6c)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Runtime Library
4  * PURPOSE:         Activation Context Support
5  * FILE:            lib/rtl/actctx.c
6  * PROGRAMERS:
7  *                  Jon Griffiths
8  *                  Eric Pouech
9  *                  Jacek Caban for CodeWeavers
10  *                  Alexandre Julliard
11  *                  Stefan Ginsberg (stefan.ginsberg@reactos.org)
12  *                  Samuel Serapión
13  */
14 
15 /* Based on Wine 3.2-37c98396 */
16 
17 #include <rtl.h>
18 #include <ntstrsafe.h>
19 #include <compat_undoc.h>
20 
21 #define NDEBUG
22 #include <debug.h>
23 
24 #include <wine/unicode.h>
25 
26 BOOLEAN RtlpNotAllowingMultipleActivation;
27 
28 #define ACTCTX_FLAGS_ALL (\
29  ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
30  ACTCTX_FLAG_LANGID_VALID |\
31  ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
32  ACTCTX_FLAG_RESOURCE_NAME_VALID |\
33  ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
34  ACTCTX_FLAG_APPLICATION_NAME_VALID |\
35  ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
36  ACTCTX_FLAG_HMODULE_VALID )
37 
38 #define STRSECTION_MAGIC   0x64487353 /* dHsS */
39 #define GUIDSECTION_MAGIC  0x64487347 /* dHsG */
40 
41 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
42 
43 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
44 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
45 
46 #define MAX_NAMESPACES 64
47 
48 typedef struct
49 {
50     const WCHAR        *ptr;
51     unsigned int        len;
52 } xmlstr_t;
53 
54 struct xml_elem
55 {
56     xmlstr_t            name;
57     xmlstr_t            ns;
58     int                 ns_pos;
59 };
60 
61 struct xml_attr
62 {
63     xmlstr_t            name;
64     xmlstr_t            value;
65 };
66 
67 typedef struct
68 {
69     const WCHAR        *ptr;
70     const WCHAR        *end;
71     struct xml_attr     namespaces[MAX_NAMESPACES];
72     int                 ns_pos;
73     BOOL                error;
74 } xmlbuf_t;
75 
76 struct file_info
77 {
78     ULONG               type;
79     WCHAR              *info;
80 };
81 
82 struct assembly_version
83 {
84     USHORT              major;
85     USHORT              minor;
86     USHORT              build;
87     USHORT              revision;
88 };
89 
90 struct assembly_identity
91 {
92     WCHAR                *name;
93     WCHAR                *arch;
94     WCHAR                *public_key;
95     WCHAR                *language;
96     WCHAR                *type;
97     struct assembly_version version;
98     BOOL                  optional;
99     BOOL                  delayed;
100 };
101 
102 struct strsection_header
103 {
104     DWORD magic;
105     ULONG size;
106     DWORD unk1[3];
107     ULONG count;
108     ULONG index_offset;
109     DWORD unk2[2];
110     ULONG global_offset;
111     ULONG global_len;
112 };
113 
114 struct string_index
115 {
116     ULONG hash;        /* key string hash */
117     ULONG name_offset;
118     ULONG name_len;
119     ULONG data_offset; /* redirect data offset */
120     ULONG data_len;
121     ULONG rosterindex;
122 };
123 
124 struct guidsection_header
125 {
126     DWORD magic;
127     ULONG size;
128     DWORD unk[3];
129     ULONG count;
130     ULONG index_offset;
131     DWORD unk2;
132     ULONG names_offset;
133     ULONG names_len;
134 };
135 
136 struct guid_index
137 {
138     GUID  guid;
139     ULONG data_offset;
140     ULONG data_len;
141     ULONG rosterindex;
142 };
143 
144 struct wndclass_redirect_data
145 {
146     ULONG size;
147     DWORD res;
148     ULONG name_len;
149     ULONG name_offset;  /* versioned name offset */
150     ULONG module_len;
151     ULONG module_offset;/* container name offset */
152 };
153 
154 struct dllredirect_data
155 {
156     ULONG size;
157     ULONG unk;
158     DWORD res[3];
159 };
160 
161 struct tlibredirect_data
162 {
163     ULONG  size;
164     DWORD  res;
165     ULONG  name_len;
166     ULONG  name_offset;
167     LANGID langid;
168     WORD   flags;
169     ULONG  help_len;
170     ULONG  help_offset;
171     WORD   major_version;
172     WORD   minor_version;
173 };
174 
175 enum comclass_threadingmodel
176 {
177     ThreadingModel_Apartment = 1,
178     ThreadingModel_Free      = 2,
179     ThreadingModel_No        = 3,
180     ThreadingModel_Both      = 4,
181     ThreadingModel_Neutral   = 5
182 };
183 
184 enum comclass_miscfields
185 {
186     MiscStatus          = 1,
187     MiscStatusIcon      = 2,
188     MiscStatusContent   = 4,
189     MiscStatusThumbnail = 8,
190     MiscStatusDocPrint  = 16
191 };
192 
193 struct comclassredirect_data
194 {
195     ULONG size;
196     BYTE  res;
197     BYTE  miscmask;
198     BYTE  res1[2];
199     DWORD model;
200     GUID  clsid;
201     GUID  alias;
202     GUID  clsid2;
203     GUID  tlbid;
204     ULONG name_len;
205     ULONG name_offset;
206     ULONG progid_len;
207     ULONG progid_offset;
208     ULONG clrdata_len;
209     ULONG clrdata_offset;
210     DWORD miscstatus;
211     DWORD miscstatuscontent;
212     DWORD miscstatusthumbnail;
213     DWORD miscstatusicon;
214     DWORD miscstatusdocprint;
215 };
216 
217 enum ifaceps_mask
218 {
219     NumMethods = 1,
220     BaseIface  = 2
221 };
222 
223 struct ifacepsredirect_data
224 {
225     ULONG size;
226     DWORD mask;
227     GUID  iid;
228     ULONG nummethods;
229     GUID  tlbid;
230     GUID  base;
231     ULONG name_len;
232     ULONG name_offset;
233 };
234 
235 struct clrsurrogate_data
236 {
237     ULONG size;
238     DWORD res;
239     GUID  clsid;
240     ULONG version_offset;
241     ULONG version_len;
242     ULONG name_offset;
243     ULONG name_len;
244 };
245 
246 struct clrclass_data
247 {
248     ULONG size;
249     DWORD res[2];
250     ULONG module_len;
251     ULONG module_offset;
252     ULONG name_len;
253     ULONG name_offset;
254     ULONG version_len;
255     ULONG version_offset;
256     DWORD res2[2];
257 };
258 
259 struct progidredirect_data
260 {
261     ULONG size;
262     DWORD reserved;
263     ULONG clsid_offset;
264 };
265 
266 /*
267 
268    Sections structure.
269 
270    Sections are accessible by string or guid key, that defines two types of sections.
271    All sections of each type have same magic value and header structure, index
272    data could be of two possible types too. So every string based section uses
273    the same index format, same applies to guid sections - they share same guid index
274    format.
275 
276    - window class redirection section is a plain buffer with following format:
277 
278    <section header>
279    <index[]>
280    <data[]> --- <original name>
281                 <redirect data>
282                 <versioned name>
283                 <module name>
284 
285    Header is fixed length structure - struct strsection_header,
286    contains redirected classes count;
287 
288    Index is an array of fixed length index records, each record is
289    struct string_index.
290 
291    All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
292 
293    Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
294    others are relative to section itself.
295 
296    - dll redirect section format:
297 
298    <section header>
299    <index[]>
300    <data[]> --- <dll name>
301                 <data>
302 
303    This section doesn't seem to carry any payload data except dll names.
304 
305    - typelib section format:
306 
307    <section header>
308    <module names[]>
309    <index[]>
310    <data[]> --- <data>
311                 <helpstring>
312 
313    Header is fixed length, index is an array of fixed length 'struct guid_index'.
314    All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
315    4-bytes aligned as a whole.
316 
317    Module name offsets are relative to section, helpstring offset is relative to data
318    structure itself.
319 
320    - comclass section format:
321 
322    <section header>
323    <module names[]>
324    <index[]>
325    <data[]> --- <data>   --- <data>
326                 <progid>     <clrdata>
327                              <name>
328                              <version>
329                              <progid>
330 
331    This section uses two index records per comclass, one entry contains original guid
332    as specified by context, another one has a generated guid. Index and strings handling
333    is similar to typelib sections.
334 
335    For CLR classes additional data is stored after main COM class data, it contains
336    class name and runtime version string, see 'struct clrclass_data'.
337 
338    Module name offsets are relative to section, progid offset is relative to data
339    structure itself.
340 
341    - COM interface section format:
342 
343    <section header>
344    <index[]>
345    <data[]> --- <data>
346                 <name>
347 
348    Interface section contains data for proxy/stubs and external proxy/stubs. External
349    ones are defined at assembly level, so this section has no module information.
350    All records are indexed with 'iid' value from manifest. There an exception for
351    external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
352    redirect data, but index is still 'iid' from manifest.
353 
354    Interface name offset is relative to data structure itself.
355 
356    - CLR surrogates section format:
357 
358    <section header>
359    <index[]>
360    <data[]> --- <data>
361                 <name>
362                 <version>
363 
364     There's nothing special about this section, same way to store strings is used,
365     no modules part as it belongs to assembly level, not a file.
366 
367    - ProgID section format:
368 
369    <section header>
370    <guids[]>
371    <index[]>
372    <data[]> --- <progid>
373                 <data>
374 
375    This sections uses generated alias guids from COM server section. This way
376    ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
377    is stored too, aligned.
378 */
379 
380 struct progids
381 {
382     WCHAR        **progids;
383     unsigned int   num;
384     unsigned int   allocated;
385 };
386 
387 struct entity
388 {
389     DWORD kind;
390     union
391     {
392         struct
393         {
394             WCHAR *tlbid;
395             WCHAR *helpdir;
396             WORD   flags;
397             WORD   major;
398             WORD   minor;
399 	} typelib;
400         struct
401         {
402             WCHAR *clsid;
403             WCHAR *tlbid;
404             WCHAR *progid;
405             WCHAR *name;    /* clrClass: class name */
406             WCHAR *version; /* clrClass: CLR runtime version */
407             DWORD  model;
408             DWORD  miscstatus;
409             DWORD  miscstatuscontent;
410             DWORD  miscstatusthumbnail;
411             DWORD  miscstatusicon;
412             DWORD  miscstatusdocprint;
413             struct progids progids;
414 	} comclass;
415 	struct {
416             WCHAR *iid;
417             WCHAR *base;
418             WCHAR *tlib;
419             WCHAR *name;
420             WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
421             DWORD  mask;
422             ULONG  nummethods;
423 	} ifaceps;
424         struct
425         {
426             WCHAR *name;
427             BOOL   versioned;
428         } class;
429         struct
430         {
431             WCHAR *name;
432             WCHAR *clsid;
433             WCHAR *version;
434         } clrsurrogate;
435         struct
436         {
437             WCHAR *name;
438             WCHAR *value;
439             WCHAR *ns;
440         } settings;
441     } u;
442 };
443 
444 struct entity_array
445 {
446     struct entity        *base;
447     unsigned int          num;
448     unsigned int          allocated;
449 };
450 
451 struct dll_redirect
452 {
453     WCHAR                *name;
454     WCHAR                *hash;
455     struct entity_array   entities;
456 };
457 
458 enum assembly_type
459 {
460     APPLICATION_MANIFEST,
461     ASSEMBLY_MANIFEST,
462     ASSEMBLY_SHARED_MANIFEST,
463 };
464 
465 struct assembly
466 {
467     enum assembly_type             type;
468     struct assembly_identity       id;
469     struct file_info               manifest;
470     WCHAR                         *directory;
471     BOOL                           no_inherit;
472     struct dll_redirect           *dlls;
473     unsigned int                   num_dlls;
474     unsigned int                   allocated_dlls;
475     struct entity_array            entities;
476     COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
477     ULONG                          num_compat_contexts;
478     ACTCTX_REQUESTED_RUN_LEVEL     run_level;
479     ULONG                          ui_access;
480 };
481 
482 enum context_sections
483 {
484     WINDOWCLASS_SECTION    = 1,
485     DLLREDIRECT_SECTION    = 2,
486     TLIBREDIRECT_SECTION   = 4,
487     SERVERREDIRECT_SECTION = 8,
488     IFACEREDIRECT_SECTION  = 16,
489     CLRSURROGATES_SECTION  = 32,
490     PROGIDREDIRECT_SECTION = 64
491 };
492 
493 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
494 {
495     ULONG Flags;
496     UNICODE_STRING DosPath;
497     HANDLE Handle;
498 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;
499 
500 typedef struct _ASSEMBLY_STORAGE_MAP
501 {
502     ULONG Flags;
503     ULONG AssemblyCount;
504     PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray;
505 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
506 
507 typedef struct _ACTIVATION_CONTEXT
508 {
509     LONG RefCount;
510     ULONG Flags;
511     LIST_ENTRY Links;
512     PACTIVATION_CONTEXT_DATA ActivationContextData;
513     PVOID NotificationRoutine;
514     PVOID NotificationContext;
515     ULONG SentNotifications[8];
516     ULONG DisabledNotifications[8];
517     ASSEMBLY_STORAGE_MAP StorageMap;
518     PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries;
519     ULONG StackTraceIndex;
520     PVOID StackTraces[4][4];
521     struct file_info config;
522     struct file_info appdir;
523     struct assembly *assemblies;
524     unsigned int num_assemblies;
525     unsigned int allocated_assemblies;
526     /* section data */
527     DWORD sections;
528     struct strsection_header *wndclass_section;
529     struct strsection_header *dllredirect_section;
530     struct strsection_header *progid_section;
531     struct guidsection_header *tlib_section;
532     struct guidsection_header *comserver_section;
533     struct guidsection_header *ifaceps_section;
534     struct guidsection_header *clrsurrogate_section;
535 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
536 
537 struct actctx_loader
538 {
539     ACTIVATION_CONTEXT       *actctx;
540     struct assembly_identity *dependencies;
541     unsigned int              num_dependencies;
542     unsigned int              allocated_dependencies;
543 };
544 
545 static const xmlstr_t empty_xmlstr;
546 
547 #ifdef __i386__
548 static const WCHAR current_archW[] = {'x','8','6',0};
549 #elif defined __x86_64__
550 static const WCHAR current_archW[] = {'a','m','d','6','4',0};
551 #elif defined __arm__
552 static const WCHAR current_archW[] = {'a','r','m',0};
553 #elif defined __aarch64__
554 static const WCHAR current_archW[] = {'a','r','m','6','4',0};
555 #else
556 static const WCHAR current_archW[] = {'n','o','n','e',0};
557 #endif
558 
559 static const WCHAR asmv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
560 static const WCHAR asmv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
561 static const WCHAR asmv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
562 
563 typedef struct _ACTIVATION_CONTEXT_WRAPPED
564 {
565     PVOID MagicMarker;
566     ACTIVATION_CONTEXT ActivationContext;
567 } ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED;
568 
569 VOID
570 NTAPI
571 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx,
572                             IN ULONG FailureCode)
573 {
574     EXCEPTION_RECORD ExceptionRecord;
575 
576     /* Fatal SxS exception header */
577     ExceptionRecord.ExceptionRecord = NULL;
578     ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
579     ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
580 
581     /* With SxS-specific information plus the context itself */
582     ExceptionRecord.ExceptionInformation[0] = 1;
583     ExceptionRecord.ExceptionInformation[1] = FailureCode;
584     ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
585     ExceptionRecord.NumberParameters = 3;
586 
587     /* Raise it */
588     RtlRaiseException(&ExceptionRecord);
589 }
590 
591 FORCEINLINE
592 VOID
593 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx)
594 {
595     PACTIVATION_CONTEXT_WRAPPED pActual;
596 
597     /* Get the caller-opaque header */
598     pActual = CONTAINING_RECORD(ActCtx,
599                                 ACTIVATION_CONTEXT_WRAPPED,
600                                 ActivationContext);
601 
602     /* Check if the header matches as expected */
603     if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
604     {
605         /* Nope, print out a warning, assert, and then throw an exception */
606         DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
607                  "     This means someone stepped on the allocation, or someone is using a\n"
608                  "     deallocated activation context\n",
609                  __FUNCTION__,
610                  pActual->MagicMarker,
611                  ActCtx);
612         ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER);
613         RtlpSxsBreakOnInvalidMarker(ActCtx, 1);
614     }
615 }
616 
617 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
618 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
619 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
620 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
621 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
622 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
623 static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
624 static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
625 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
626 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
627 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
628 static const WCHAR fileW[] = {'f','i','l','e',0};
629 static const WCHAR hashW[] = {'h','a','s','h',0};
630 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
631 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
632 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
633 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
634 
635 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
636 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
637 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
638 static const WCHAR iidW[] = {'i','i','d',0};
639 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
640 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
641 static const WCHAR g_nameW[] = {'n','a','m','e',0};
642 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
643 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
644 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
645 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
646 static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
647 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
648 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
649 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
650 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
651 static const WCHAR typeW[] = {'t','y','p','e',0};
652 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
653 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
654 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
655 static const WCHAR yesW[] = {'y','e','s',0};
656 static const WCHAR noW[] = {'n','o',0};
657 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
658 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
659 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
660 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
661 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
662 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
663 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
664 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
665 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
666 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
667 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
668 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
669 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
670 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
671 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
672 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
673 
674 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
675 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
676 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
677 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
678 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
679 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
680 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
681 static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
682 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
683 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
684 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
685 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
686 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
687 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
688 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
689 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
690 static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
691 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
692 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
693 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
694 static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
695 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
696 
697 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
698 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
699 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
700 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
701 static const WCHAR IdW[] = {'I','d',0};
702 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
703 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
704 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
705 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
706 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
707 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
708 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
709 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0};
710 static const WCHAR windowsSettings2005NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
711 static const WCHAR windowsSettings2011NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
712 static const WCHAR windowsSettings2016NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
713 static const WCHAR windowsSettings2017NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
714 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
715 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
716 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
717 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
718 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
719 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
720 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0};
721 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
722 
723 struct olemisc_entry
724 {
725     const WCHAR *name;
726     OLEMISC value;
727 };
728 
729 static const struct olemisc_entry olemisc_values[] =
730 {
731     { activatewhenvisibleW,          OLEMISC_ACTIVATEWHENVISIBLE },
732     { actslikebuttonW,               OLEMISC_ACTSLIKEBUTTON },
733     { actslikelabelW,                OLEMISC_ACTSLIKELABEL },
734     { alignableW,                    OLEMISC_ALIGNABLE },
735     { alwaysrunW,                    OLEMISC_ALWAYSRUN },
736     { canlinkbyole1W,                OLEMISC_CANLINKBYOLE1 },
737     { cantlinkinsideW,               OLEMISC_CANTLINKINSIDE },
738     { ignoreactivatewhenvisibleW,    OLEMISC_IGNOREACTIVATEWHENVISIBLE },
739     { imemodeW,                      OLEMISC_IMEMODE },
740     { insertnotreplaceW,             OLEMISC_INSERTNOTREPLACE },
741     { insideoutW,                    OLEMISC_INSIDEOUT },
742     { invisibleatruntimeW,           OLEMISC_INVISIBLEATRUNTIME },
743     { islinkobjectW,                 OLEMISC_ISLINKOBJECT },
744     { nouiactivateW,                 OLEMISC_NOUIACTIVATE },
745     { onlyiconicW,                   OLEMISC_ONLYICONIC },
746     { recomposeonresizeW,            OLEMISC_RECOMPOSEONRESIZE },
747     { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
748     { setclientsitefirstW,           OLEMISC_SETCLIENTSITEFIRST },
749     { simpleframeW,                  OLEMISC_SIMPLEFRAME },
750     { staticW,                       OLEMISC_STATIC },
751     { supportsmultilevelundoW,       OLEMISC_SUPPORTSMULTILEVELUNDO },
752     { wantstomenumergeW,             OLEMISC_WANTSTOMENUMERGE }
753 };
754 
755 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
756 static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
757 static const WCHAR manifestv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
758 static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
759 
760 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
761 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
762 static const WCHAR wildcardW[] = {'*',0};
763 
764 static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } };
765 static ACTIVATION_CONTEXT *process_actctx = &system_actctx.ActivationContext;
766 static ACTIVATION_CONTEXT *implicit_actctx = &system_actctx.ActivationContext;
767 
768 static WCHAR *strdupW(const WCHAR* str)
769 {
770     WCHAR*      ptr;
771 
772     if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
773         return NULL;
774     return strcpyW(ptr, str);
775 }
776 
777 static WCHAR *xmlstrdupW(const xmlstr_t* str)
778 {
779     WCHAR *strW;
780 
781     if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
782     {
783         memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
784         strW[str->len] = 0;
785     }
786     return strW;
787 }
788 
789 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
790 {
791     return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
792 }
793 
794 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
795 {
796     return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
797 }
798 
799 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
800 {
801     return (xmlstr->len && xmlstr->ptr[0] == '/' &&
802             !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
803 }
804 
805 static inline BOOL xml_attr_cmp(const struct xml_attr* attr, const WCHAR *str)
806 {
807     return xmlstr_cmp(&attr->name, str);
808 }
809 
810 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
811 {
812     return (elem1->name.len == elem2->name.len &&
813             elem1->ns.len == elem2->ns.len &&
814             !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
815             !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
816 }
817 
818 static inline BOOL xml_elem_cmp(const struct xml_elem* elem, const WCHAR *str, const WCHAR *namespace)
819 {
820     if (!xmlstr_cmp( &elem->name, str )) return FALSE;
821     if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
822     if (!wcscmp( namespace, asmv1W ))
823     {
824         if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
825         if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
826     }
827     else if (!wcscmp( namespace, asmv2W ))
828     {
829         if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
830     }
831     return FALSE;
832 }
833 
834 static inline BOOL isxmlspace( WCHAR ch )
835 {
836     return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
837 }
838 
839 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
840 {
841     struct assembly *assembly;
842 
843     DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
844 
845     if (actctx->num_assemblies == actctx->allocated_assemblies)
846     {
847         void *ptr;
848         unsigned int new_count;
849         if (actctx->assemblies)
850         {
851             new_count = actctx->allocated_assemblies * 2;
852             ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
853                                      actctx->assemblies, new_count * sizeof(*assembly) );
854         }
855         else
856         {
857             new_count = 4;
858             ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
859         }
860         if (!ptr) return NULL;
861         actctx->assemblies = ptr;
862         actctx->allocated_assemblies = new_count;
863     }
864 
865     assembly = &actctx->assemblies[actctx->num_assemblies++];
866     assembly->type = at;
867     return assembly;
868 }
869 
870 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
871 {
872     DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
873 
874     if (assembly->num_dlls == assembly->allocated_dlls)
875     {
876         void *ptr;
877         unsigned int new_count;
878         if (assembly->dlls)
879         {
880             new_count = assembly->allocated_dlls * 2;
881             ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
882                                      assembly->dlls, new_count * sizeof(*assembly->dlls) );
883         }
884         else
885         {
886             new_count = 4;
887             ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
888         }
889         if (!ptr) return NULL;
890         assembly->dlls = ptr;
891         assembly->allocated_dlls = new_count;
892     }
893     return &assembly->dlls[assembly->num_dlls++];
894 }
895 
896 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
897 {
898     void *ptr;
899     if (assembly->num_compat_contexts)
900     {
901         unsigned int new_count = assembly->num_compat_contexts + 1;
902         ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
903                                  assembly->compat_contexts,
904                                  new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
905     }
906     else
907     {
908         ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
909     }
910     if (!ptr) return NULL;
911     assembly->compat_contexts = ptr;
912     return &assembly->compat_contexts[assembly->num_compat_contexts++];
913 }
914 
915 static void free_assembly_identity(struct assembly_identity *ai)
916 {
917     RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
918     RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
919     RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
920     RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
921     RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
922 }
923 
924 static struct entity* add_entity(struct entity_array *array, DWORD kind)
925 {
926     struct entity*      entity;
927 
928     if (array->num == array->allocated)
929     {
930         void *ptr;
931         unsigned int new_count;
932         if (array->base)
933         {
934             new_count = array->allocated * 2;
935             ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
936                                      array->base, new_count * sizeof(*array->base) );
937         }
938         else
939         {
940             new_count = 4;
941             ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
942         }
943         if (!ptr) return NULL;
944         array->base = ptr;
945         array->allocated = new_count;
946     }
947     entity = &array->base[array->num++];
948     entity->kind = kind;
949     return entity;
950 }
951 
952 static void free_entity_array(struct entity_array *array)
953 {
954     unsigned int i, j;
955     for (i = 0; i < array->num; i++)
956     {
957         struct entity *entity = &array->base[i];
958         switch (entity->kind)
959         {
960         case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
961             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
962             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
963             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
964             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
965             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
966             for (j = 0; j < entity->u.comclass.progids.num; j++)
967                 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
968             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
969             break;
970         case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
971             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
972             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
973             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
974             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
975             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
976             break;
977         case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
978             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
979             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
980             break;
981         case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
982             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
983             break;
984         case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
985             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
986             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
987             RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
988             break;
989         default:
990             DPRINT1("Unknown entity kind %u\n", entity->kind);
991         }
992     }
993     RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
994 }
995 
996 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
997 {
998     if (!str1) return !str2;
999     return str2 && !strcmpiW( str1, str2 );
1000 }
1001 
1002 static BOOL is_matching_identity( const struct assembly_identity *id1,
1003                                   const struct assembly_identity *id2 )
1004 {
1005     if (!is_matching_string( id1->name, id2->name )) return FALSE;
1006     if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1007     if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1008 
1009     if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
1010     {
1011         if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
1012             return FALSE;
1013     }
1014     if (id1->version.major != id2->version.major) return FALSE;
1015     if (id1->version.minor != id2->version.minor) return FALSE;
1016     if (id1->version.build > id2->version.build) return FALSE;
1017     if (id1->version.build == id2->version.build &&
1018         id1->version.revision > id2->version.revision) return FALSE;
1019     return TRUE;
1020 }
1021 
1022 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
1023                                       struct assembly_identity* ai)
1024 {
1025     unsigned int i;
1026 
1027     /* check if we already have that assembly */
1028 
1029     for (i = 0; i < acl->actctx->num_assemblies; i++)
1030         if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1031         {
1032             DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
1033                    ai->name, ai->arch, ai->version.major, ai->version.minor,
1034                    ai->version.build, ai->version.revision );
1035             return TRUE;
1036         }
1037 
1038     for (i = 0; i < acl->num_dependencies; i++)
1039         if (is_matching_identity( ai, &acl->dependencies[i] ))
1040         {
1041             DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
1042                    ai->name, ai->arch, ai->version.major, ai->version.minor,
1043                    ai->version.build, ai->version.revision );
1044             return TRUE;
1045         }
1046 
1047     if (acl->num_dependencies == acl->allocated_dependencies)
1048     {
1049         void *ptr;
1050         unsigned int new_count;
1051         if (acl->dependencies)
1052         {
1053             new_count = acl->allocated_dependencies * 2;
1054             ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
1055                                     new_count * sizeof(acl->dependencies[0]));
1056         }
1057         else
1058         {
1059             new_count = 4;
1060             ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1061         }
1062         if (!ptr) return FALSE;
1063         acl->dependencies = ptr;
1064         acl->allocated_dependencies = new_count;
1065     }
1066     acl->dependencies[acl->num_dependencies++] = *ai;
1067 
1068     return TRUE;
1069 }
1070 
1071 static void free_depend_manifests(struct actctx_loader* acl)
1072 {
1073     unsigned int i;
1074     for (i = 0; i < acl->num_dependencies; i++)
1075         free_assembly_identity(&acl->dependencies[i]);
1076     RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
1077 }
1078 
1079 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1080 {
1081     static const WCHAR undW[] = {'_',0};
1082     static const WCHAR noneW[] = {'n','o','n','e',0};
1083     static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1084 
1085     const WCHAR *arch = ai->arch ? ai->arch : noneW;
1086     const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1087     const WCHAR *lang = ai->language ? ai->language : noneW;
1088     const WCHAR *name = ai->name ? ai->name : noneW;
1089     SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1090 		    strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1091     WCHAR *ret;
1092 
1093     if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1094 
1095     strcpyW( ret, arch );
1096     strcatW( ret, undW );
1097     strcatW( ret, name );
1098     strcatW( ret, undW );
1099     strcatW( ret, key );
1100     strcatW( ret, undW );
1101     sprintfW( ret + strlenW(ret), version_formatW,
1102               ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1103     strcatW( ret, undW );
1104     strcatW( ret, lang );
1105     strcatW( ret, undW );
1106     strcatW( ret, mskeyW );
1107     return ret;
1108 }
1109 
1110 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1111 {
1112     WCHAR *p = buffer;
1113 
1114     if (!str) return;
1115     strcatW( buffer, prefix );
1116     p += strlenW(p);
1117     *p++ = '"';
1118     strcpyW( p, str );
1119     p += strlenW(p);
1120     *p++ = '"';
1121     *p = 0;
1122 }
1123 
1124 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1125 {
1126     static const WCHAR archW[] =
1127         {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1128     static const WCHAR public_keyW[] =
1129         {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1130     static const WCHAR typeW2[] =
1131         {',','t','y','p','e','=',0};
1132     static const WCHAR versionW2[] =
1133         {',','v','e','r','s','i','o','n','=',0};
1134 
1135     WCHAR version[64], *ret;
1136     SIZE_T size = 0;
1137 
1138     sprintfW( version, version_formatW,
1139               ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1140     if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1141     if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1142     if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1143     if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1144     size += strlenW(versionW2) + strlenW(version) + 2;
1145 
1146     if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1147         return NULL;
1148 
1149     if (ai->name) strcpyW( ret, ai->name );
1150     else *ret = 0;
1151     append_string( ret, archW, ai->arch );
1152     append_string( ret, public_keyW, ai->public_key );
1153     append_string( ret, typeW2, ai->type );
1154     append_string( ret, versionW2, version );
1155     return ret;
1156 }
1157 
1158 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1159 {
1160     ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1161     PACTIVATION_CONTEXT_WRAPPED pActual;
1162 
1163     if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1164     _SEH2_TRY
1165     {
1166         if (actctx)
1167         {
1168             pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1169             if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1170         }
1171     }
1172     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1173     {
1174         DPRINT1("Invalid activation context handle!\n");
1175     }
1176     _SEH2_END;
1177     return ret;
1178 }
1179 
1180 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1181 {
1182     InterlockedExchangeAdd( &actctx->RefCount, 1 );
1183 }
1184 
1185 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1186 {
1187     PACTIVATION_CONTEXT_WRAPPED pActual;
1188 
1189     if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1190     {
1191         unsigned int i, j;
1192 
1193         for (i = 0; i < actctx->num_assemblies; i++)
1194         {
1195             struct assembly *assembly = &actctx->assemblies[i];
1196             for (j = 0; j < assembly->num_dlls; j++)
1197             {
1198                 struct dll_redirect *dll = &assembly->dlls[j];
1199                 free_entity_array( &dll->entities );
1200                 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1201                 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1202             }
1203             RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1204             RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1205             RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1206             RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts );
1207             free_entity_array( &assembly->entities );
1208             free_assembly_identity(&assembly->id);
1209         }
1210         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1211         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1212         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1213         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1214         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1215         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1216         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1217         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1218         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1219         RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1220 
1221         pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1222         pActual->MagicMarker = 0;
1223         RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1224     }
1225 }
1226 
1227 static BOOL set_error(xmlbuf_t* xmlbuf)
1228 {
1229     xmlbuf->error = TRUE;
1230     return FALSE;
1231 }
1232 
1233 static BOOL is_xmlns_attr(const struct xml_attr *attr)
1234 {
1235     const int len = wcslen( xmlnsW );
1236     if (attr->name.len < len) return FALSE;
1237     if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1238     return (attr->name.len == len || attr->name.ptr[len] == ':');
1239 }
1240 
1241 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1242 {
1243     const int len = wcslen( xmlnsW );
1244     struct xml_attr *ns;
1245 
1246     if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1247     {
1248         // FIXME( "too many namespaces in manifest\n" );
1249         set_error( xmlbuf );
1250         return;
1251     }
1252     ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1253     ns->value = attr->value;
1254     if (attr->name.len > len)
1255     {
1256         ns->name.ptr = attr->name.ptr + len + 1;
1257         ns->name.len = attr->name.len - len - 1;
1258     }
1259     else ns->name = empty_xmlstr;
1260 }
1261 
1262 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1263 {
1264     int i;
1265 
1266     for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1267     {
1268         if (xmlbuf->namespaces[i].name.len == name->len &&
1269             !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1270             return xmlbuf->namespaces[i].value;
1271     }
1272 
1273     return empty_xmlstr;
1274 }
1275 
1276 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, struct xml_attr* attr, BOOL* end)
1277 {
1278     const WCHAR* ptr;
1279     WCHAR quote;
1280 
1281     if (xmlbuf->error) return FALSE;
1282 
1283     while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1284         xmlbuf->ptr++;
1285 
1286     if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1287 
1288     if (*xmlbuf->ptr == '/')
1289     {
1290         xmlbuf->ptr++;
1291         if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1292             return set_error( xmlbuf );
1293 
1294         xmlbuf->ptr++;
1295         *end = TRUE;
1296         return FALSE;
1297     }
1298 
1299     if (*xmlbuf->ptr == '>')
1300     {
1301         xmlbuf->ptr++;
1302         return FALSE;
1303     }
1304 
1305     ptr = xmlbuf->ptr;
1306     while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1307 
1308     if (ptr == xmlbuf->end) return set_error( xmlbuf );
1309 
1310     attr->name.ptr = xmlbuf->ptr;
1311     attr->name.len = ptr-xmlbuf->ptr;
1312     xmlbuf->ptr = ptr;
1313 
1314     /* skip spaces before '=' */
1315     while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1316     if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1317 
1318     /* skip '=' itself */
1319     ptr++;
1320     if (ptr == xmlbuf->end) return set_error( xmlbuf );
1321 
1322     /* skip spaces after '=' */
1323     while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1324 
1325     if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1326 
1327     quote = *ptr++;
1328     attr->value.ptr = ptr;
1329     if (ptr == xmlbuf->end) return set_error( xmlbuf );
1330 
1331     while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1332     if (ptr == xmlbuf->end)
1333     {
1334         xmlbuf->ptr = xmlbuf->end;
1335         return set_error( xmlbuf );
1336     }
1337 
1338     attr->value.len = ptr - attr->value.ptr;
1339     xmlbuf->ptr = ptr + 1;
1340     if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1341 
1342     return set_error( xmlbuf );
1343 }
1344 
1345 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1346 {
1347     const WCHAR* ptr = xmlbuf->ptr;
1348 
1349     elem->ns = empty_xmlstr;
1350     elem->name.ptr = ptr;
1351     while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1352     {
1353         if (*ptr == ':')
1354         {
1355             elem->ns.ptr = elem->name.ptr;
1356             elem->ns.len = ptr - elem->ns.ptr;
1357             elem->name.ptr = ptr + 1;
1358         }
1359         ptr++;
1360     }
1361     elem->name.len = ptr - elem->name.ptr;
1362     xmlbuf->ptr = ptr;
1363 }
1364 
1365 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1366 {
1367     const WCHAR* ptr;
1368     struct xml_attr attr;
1369     xmlbuf_t attr_buf;
1370     BOOL end = FALSE;
1371 
1372     xmlbuf->ns_pos = parent->ns_pos;  /* restore namespace stack to parent state */
1373 
1374     if (xmlbuf->error) return FALSE;
1375 
1376     for (;;)
1377     {
1378         for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1379         if (ptr == xmlbuf->end)
1380         {
1381             xmlbuf->ptr = xmlbuf->end;
1382             return set_error( xmlbuf );
1383         }
1384         ptr++;
1385         if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1386         {
1387             for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1388                 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1389 
1390             if (ptr + 3 > xmlbuf->end)
1391             {
1392                 xmlbuf->ptr = xmlbuf->end;
1393                 return set_error( xmlbuf );
1394             }
1395             xmlbuf->ptr = ptr + 3;
1396         }
1397         else break;
1398     }
1399 
1400     xmlbuf->ptr = ptr;
1401     /* check for element terminating the parent element */
1402     if (ptr < xmlbuf->end && *ptr == '/')
1403     {
1404         xmlbuf->ptr++;
1405         read_xml_elem( xmlbuf, elem );
1406         elem->ns = find_xmlns( xmlbuf, &elem->ns );
1407         if (!xml_name_cmp( elem, parent ))
1408         {
1409             /*ERR( "wrong closing element %s for %s\n",
1410                  debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));*/
1411             return set_error( xmlbuf );
1412         }
1413         while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1414         if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1415         return FALSE;
1416     }
1417 
1418     read_xml_elem( xmlbuf, elem );
1419 
1420     /* parse namespace attributes */
1421     attr_buf = *xmlbuf;
1422     while (next_xml_attr( &attr_buf, &attr, &end ))
1423     {
1424         if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1425     }
1426     elem->ns = find_xmlns( xmlbuf, &elem->ns );
1427     elem->ns_pos = xmlbuf->ns_pos;
1428 
1429     if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1430 
1431     return set_error( xmlbuf );
1432 }
1433 
1434 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1435 {
1436     /* FIXME: parse attributes */
1437     const WCHAR *ptr;
1438 
1439     for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1440     {
1441         if (ptr[0] == '?' && ptr[1] == '>')
1442         {
1443             xmlbuf->ptr = ptr + 2;
1444             return TRUE;
1445         }
1446     }
1447     return FALSE;
1448 }
1449 
1450 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1451 {
1452     const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1453 
1454     if (!ptr) return FALSE;
1455 
1456     content->ptr = xmlbuf->ptr;
1457     content->len = ptr - xmlbuf->ptr;
1458     xmlbuf->ptr = ptr;
1459 
1460     return TRUE;
1461 }
1462 
1463 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1464 {
1465     unsigned int ver[4];
1466     unsigned int pos;
1467     const WCHAR *curr;
1468 
1469     /* major.minor.build.revision */
1470     ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1471     for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1472     {
1473         if (*curr >= '0' && *curr <= '9')
1474         {
1475             ver[pos] = ver[pos] * 10 + *curr - '0';
1476             if (ver[pos] >= 0x10000) goto error;
1477         }
1478         else if (*curr == '.')
1479         {
1480             if (++pos >= 4) goto error;
1481         }
1482         else goto error;
1483     }
1484     version->major = ver[0];
1485     version->minor = ver[1];
1486     version->build = ver[2];
1487     version->revision = ver[3];
1488     return TRUE;
1489 
1490 error:
1491     return FALSE;
1492 }
1493 
1494 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1495 {
1496     struct xml_attr attr;
1497 
1498     while (next_xml_attr(xmlbuf, &attr, end))
1499     {
1500         // TODO: report error
1501         // if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1502     }
1503 }
1504 
1505 static void parse_expect_end_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1506 {
1507     struct xml_elem elem;
1508 
1509     if (next_xml_elem(xmlbuf, &elem, parent))
1510     {
1511         // FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1512         set_error( xmlbuf );
1513     }
1514 }
1515 
1516 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1517 {
1518     struct xml_elem elem;
1519     struct xml_attr attr;
1520     BOOL end = FALSE;
1521 
1522     while (next_xml_attr(xmlbuf, &attr, &end));
1523     if (end) return;
1524 
1525     while (next_xml_elem(xmlbuf, &elem, parent))
1526         parse_unknown_elem(xmlbuf, &elem);
1527 }
1528 
1529 static void parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1530                                          struct assembly_identity* ai, const struct xml_elem *parent)
1531 {
1532     struct xml_attr attr;
1533     BOOL end = FALSE;
1534 
1535     while (next_xml_attr(xmlbuf, &attr, &end))
1536     {
1537         if (xml_attr_cmp(&attr, g_nameW))
1538         {
1539             if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1540         }
1541         else if (xml_attr_cmp(&attr, typeW))
1542         {
1543             if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1544         }
1545         else if (xml_attr_cmp(&attr, versionW))
1546         {
1547             if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1548         }
1549         else if (xml_attr_cmp(&attr, processorArchitectureW))
1550         {
1551             if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1552         }
1553         else if (xml_attr_cmp(&attr, publicKeyTokenW))
1554         {
1555             if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1556         }
1557         else if (xml_attr_cmp(&attr, languageW))
1558         {
1559             if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1560         }
1561     }
1562 
1563     if (!end) parse_expect_end_elem(xmlbuf, parent);
1564 }
1565 
1566 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1567 {
1568     static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1569     static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1570     static const WCHAR freeW[] = {'F','r','e','e',0};
1571     static const WCHAR bothW[] = {'B','o','t','h',0};
1572 
1573     if (value->len == 0) return ThreadingModel_No;
1574     if (xmlstr_cmp(value, apartW))
1575         return ThreadingModel_Apartment;
1576     else if (xmlstr_cmp(value, freeW))
1577         return ThreadingModel_Free;
1578     else if (xmlstr_cmp(value, bothW))
1579         return ThreadingModel_Both;
1580     else if (xmlstr_cmp(value, neutralW))
1581         return ThreadingModel_Neutral;
1582     else
1583         return ThreadingModel_No;
1584 };
1585 
1586 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1587 {
1588     int min, max;
1589 
1590     min = 0;
1591     max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1592 
1593     while (min <= max)
1594     {
1595         int n, c;
1596 
1597         n = (min+max)/2;
1598 
1599         c = strncmpW(olemisc_values[n].name, str, len);
1600         if (!c && !olemisc_values[n].name[len])
1601             return olemisc_values[n].value;
1602 
1603         if (c >= 0)
1604             max = n-1;
1605         else
1606             min = n+1;
1607     }
1608 
1609     DPRINT1("unknown flag %S\n", str);
1610     return 0;
1611 }
1612 
1613 static DWORD parse_com_class_misc(const xmlstr_t *value)
1614 {
1615     const WCHAR *str = value->ptr, *start;
1616     DWORD flags = 0;
1617     int i = 0;
1618 
1619     /* it's comma separated list of flags */
1620     while (i < value->len)
1621     {
1622         start = str;
1623         while (*str != ',' && (i++ < value->len)) str++;
1624 
1625         flags |= get_olemisc_value(start, str-start);
1626 
1627         /* skip separator */
1628         str++;
1629         i++;
1630     }
1631 
1632     return flags;
1633 }
1634 
1635 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1636 {
1637     struct progids *progids = &entity->u.comclass.progids;
1638 
1639     if (progids->allocated == 0)
1640     {
1641         progids->allocated = 4;
1642         if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1643     }
1644 
1645     if (progids->allocated == progids->num)
1646     {
1647         WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1648                                                 2 * progids->allocated * sizeof(WCHAR*));
1649         if (!new_progids) return FALSE;
1650         progids->allocated *= 2;
1651         progids->progids = new_progids;
1652     }
1653 
1654     if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1655     progids->num++;
1656 
1657     return TRUE;
1658 }
1659 
1660 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1661 {
1662     xmlstr_t content;
1663     BOOL end = FALSE;
1664 
1665     parse_expect_no_attr(xmlbuf, &end);
1666     if (end) set_error( xmlbuf );
1667     if (!parse_text_content(xmlbuf, &content)) return;
1668 
1669     if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1670     parse_expect_end_elem(xmlbuf, parent);
1671 }
1672 
1673 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1674                                   const struct xml_elem *parent )
1675 {
1676     struct xml_elem elem;
1677     struct xml_attr attr;
1678     BOOL end = FALSE;
1679     struct entity*      entity;
1680 
1681     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1682     {
1683         set_error( xmlbuf );
1684         return;
1685     }
1686 
1687     while (next_xml_attr(xmlbuf, &attr, &end))
1688     {
1689         if (xml_attr_cmp(&attr, clsidW))
1690         {
1691             if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1692         }
1693         else if (xml_attr_cmp(&attr, progidW))
1694         {
1695             if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1696         }
1697         else if (xml_attr_cmp(&attr, tlbidW))
1698         {
1699             if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1700         }
1701         else if (xml_attr_cmp(&attr, threadingmodelW))
1702         {
1703             entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1704         }
1705         else if (xml_attr_cmp(&attr, miscstatusW))
1706         {
1707             entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1708         }
1709         else if (xml_attr_cmp(&attr, miscstatuscontentW))
1710         {
1711             entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1712         }
1713         else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1714         {
1715             entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1716         }
1717         else if (xml_attr_cmp(&attr, miscstatusiconW))
1718         {
1719             entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1720         }
1721         else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1722         {
1723             entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1724         }
1725         else if (xml_attr_cmp(&attr, descriptionW))
1726         {
1727             /* not stored */
1728         }
1729     }
1730 
1731     acl->actctx->sections |= SERVERREDIRECT_SECTION;
1732     if (entity->u.comclass.progid)
1733         acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1734 
1735     if (end) return;
1736 
1737     while (next_xml_elem(xmlbuf, &elem, parent))
1738     {
1739         if (xml_elem_cmp(&elem, progidW, asmv1W))
1740         {
1741             parse_com_class_progid(xmlbuf, entity, &elem);
1742         }
1743         else
1744         {
1745             parse_unknown_elem(xmlbuf, &elem);
1746         }
1747     }
1748 
1749     if (entity->u.comclass.progids.num)
1750         acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1751 }
1752 
1753 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1754 {
1755     const WCHAR *curr;
1756     ULONG num = 0;
1757 
1758     for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1759     {
1760         if (*curr >= '0' && *curr <= '9')
1761             num = num * 10 + *curr - '0';
1762         else
1763         {
1764             // DPRINT1("wrong numeric value %wZ\n", &strU);
1765             return FALSE;
1766         }
1767     }
1768     entity->u.ifaceps.nummethods = num;
1769 
1770     return TRUE;
1771 }
1772 
1773 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1774         struct actctx_loader *acl, WCHAR *clsid )
1775 {
1776     struct entity *entity;
1777     WCHAR *str;
1778 
1779     if (!clsid) return;
1780 
1781     if (!(str = strdupW(clsid)))
1782     {
1783         set_error( xmlbuf );
1784         return;
1785     }
1786 
1787     if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1788     {
1789         RtlFreeHeap(RtlGetProcessHeap(), 0, str);
1790         set_error( xmlbuf );
1791         return;
1792     }
1793 
1794     entity->u.comclass.clsid = str;
1795     entity->u.comclass.model = ThreadingModel_Both;
1796 
1797     acl->actctx->sections |= SERVERREDIRECT_SECTION;
1798 }
1799 
1800 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1801                                                 struct actctx_loader *acl, const struct xml_elem *parent )
1802 {
1803     WCHAR *psclsid = NULL;
1804     struct entity *entity;
1805     struct xml_attr attr;
1806     BOOL end = FALSE;
1807 
1808     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1809     {
1810         set_error( xmlbuf );
1811         return;
1812     }
1813 
1814     while (next_xml_attr(xmlbuf, &attr, &end))
1815     {
1816         if (xml_attr_cmp(&attr, iidW))
1817         {
1818             if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1819         }
1820         else if (xml_attr_cmp(&attr, g_nameW))
1821         {
1822             if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1823         }
1824         else if (xml_attr_cmp(&attr, baseInterfaceW))
1825         {
1826             if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1827             entity->u.ifaceps.mask |= BaseIface;
1828         }
1829         else if (xml_attr_cmp(&attr, nummethodsW))
1830         {
1831             if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1832             entity->u.ifaceps.mask |= NumMethods;
1833         }
1834         else if (xml_attr_cmp(&attr, tlbidW))
1835         {
1836             if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1837         }
1838         else if (xml_attr_cmp(&attr, proxyStubClsid32W))
1839         {
1840             if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1841         }
1842         /* not used */
1843         else if (xml_attr_cmp(&attr, threadingmodelW))
1844         {
1845         }
1846     }
1847 
1848     acl->actctx->sections |= IFACEREDIRECT_SECTION;
1849     if (!end) parse_expect_end_elem(xmlbuf, parent);
1850 
1851     parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1852 
1853     RtlFreeHeap(RtlGetProcessHeap(), 0, psclsid);
1854 }
1855 
1856 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1857 {
1858     WORD *flags = &entity->u.typelib.flags;
1859     const WCHAR *str = value->ptr, *start;
1860     int i = 0;
1861 
1862     *flags = 0;
1863 
1864     /* it's comma separated list of flags */
1865     while (i < value->len)
1866     {
1867         start = str;
1868         while (*str != ',' && (i++ < value->len)) str++;
1869 
1870         if (!strncmpiW(start, restrictedW, str-start))
1871             *flags |= LIBFLAG_FRESTRICTED;
1872         else if (!strncmpiW(start, controlW, str-start))
1873             *flags |= LIBFLAG_FCONTROL;
1874         else if (!strncmpiW(start, hiddenW, str-start))
1875             *flags |= LIBFLAG_FHIDDEN;
1876         else if (!strncmpiW(start, hasdiskimageW, str-start))
1877             *flags |= LIBFLAG_FHASDISKIMAGE;
1878         else
1879         {
1880             // DPRINT1("unknown flags value %wZ\n", &valueU);
1881             return FALSE;
1882         }
1883 
1884         /* skip separator */
1885         str++;
1886         i++;
1887     }
1888 
1889     return TRUE;
1890 }
1891 
1892 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1893 {
1894     unsigned int ver[2];
1895     unsigned int pos;
1896     const WCHAR *curr;
1897 
1898     /* major.minor */
1899     ver[0] = ver[1] = pos = 0;
1900     for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1901     {
1902         if (*curr >= '0' && *curr <= '9')
1903         {
1904             ver[pos] = ver[pos] * 10 + *curr - '0';
1905             if (ver[pos] >= 0x10000) goto error;
1906         }
1907         else if (*curr == '.')
1908         {
1909             if (++pos >= 2) goto error;
1910         }
1911         else goto error;
1912     }
1913     entity->u.typelib.major = ver[0];
1914     entity->u.typelib.minor = ver[1];
1915     return TRUE;
1916 
1917 error:
1918     return FALSE;
1919 }
1920 
1921 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1922                                 struct actctx_loader *acl, const struct xml_elem *parent )
1923 {
1924     struct xml_attr attr;
1925     BOOL end = FALSE;
1926     struct entity*      entity;
1927 
1928     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1929     {
1930         set_error( xmlbuf );
1931         return;
1932     }
1933 
1934     while (next_xml_attr(xmlbuf, &attr, &end))
1935     {
1936         if (xml_attr_cmp(&attr, tlbidW))
1937         {
1938             if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1939         }
1940         else if (xml_attr_cmp(&attr, versionW))
1941         {
1942             if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1943         }
1944         else if (xml_attr_cmp(&attr, helpdirW))
1945         {
1946             if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1947         }
1948         else if (xml_attr_cmp(&attr, flagsW))
1949         {
1950             if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1951         }
1952     }
1953 
1954     acl->actctx->sections |= TLIBREDIRECT_SECTION;
1955     if (!end) parse_expect_end_elem(xmlbuf, parent);
1956 }
1957 
1958 static inline int aligned_string_len(int len)
1959 {
1960     return (len + 3) & ~3;
1961 }
1962 
1963 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1964 {
1965     static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1966     struct assembly_version *ver = &assembly->id.version;
1967     WCHAR buff[25];
1968 
1969     if (!ret) ret = buff;
1970     return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1971 }
1972 
1973 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1974                                      struct actctx_loader *acl, const struct xml_elem *parent )
1975 {
1976     struct xml_elem elem;
1977     struct xml_attr attr;
1978     xmlstr_t content;
1979     BOOL end = FALSE;
1980     struct entity*      entity;
1981 
1982     if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1983     {
1984         set_error( xmlbuf );
1985         return;
1986     }
1987     entity->u.class.versioned = TRUE;
1988     while (next_xml_attr(xmlbuf, &attr, &end))
1989     {
1990         if (xml_attr_cmp(&attr, versionedW))
1991         {
1992             if (xmlstr_cmpi(&attr.value, noW))
1993                 entity->u.class.versioned = FALSE;
1994             else if (!xmlstr_cmpi(&attr.value, yesW))
1995                 set_error( xmlbuf );
1996         }
1997     }
1998 
1999     if (end) return;
2000 
2001     if (!parse_text_content(xmlbuf, &content)) return;
2002     if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
2003 
2004     acl->actctx->sections |= WINDOWCLASS_SECTION;
2005 
2006     while (next_xml_elem(xmlbuf, &elem, parent))
2007     {
2008         parse_unknown_elem(xmlbuf, &elem);
2009     }
2010 }
2011 
2012 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2013 {
2014     struct xml_attr attr;
2015     BOOL end = FALSE;
2016 
2017     while (next_xml_attr(xmlbuf, &attr, &end))
2018     {
2019         if (xml_attr_cmp(&attr, oldVersionW))
2020         {
2021             // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2022         }
2023         else if (xml_attr_cmp(&attr, newVersionW))
2024         {
2025             // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2026         }
2027     }
2028 
2029     if (!end) parse_expect_end_elem(xmlbuf, parent);
2030 }
2031 
2032 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2033 {
2034     struct xml_elem elem;
2035     struct xml_attr attr;
2036     xmlstr_t content;
2037     BOOL end = FALSE;
2038 
2039     while (next_xml_attr(xmlbuf, &attr, &end));
2040 
2041     if (end) return;
2042     if (!parse_text_content(xmlbuf, &content)) return;
2043 
2044     while (next_xml_elem(xmlbuf, &elem, parent))
2045     {
2046         parse_unknown_elem(xmlbuf, &elem);
2047     }
2048 }
2049 
2050 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2051                                                          struct assembly* assembly,
2052                                                          struct actctx_loader* acl,
2053                                                          const struct xml_elem *parent)
2054 {
2055     struct xml_attr attr;
2056     BOOL end = FALSE;
2057     struct entity*      entity;
2058 
2059     if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2060     {
2061         set_error( xmlbuf );
2062         return;
2063     }
2064 
2065     while (next_xml_attr(xmlbuf, &attr, &end))
2066     {
2067         if (xml_attr_cmp(&attr, iidW))
2068         {
2069             if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2070         }
2071         else if (xml_attr_cmp(&attr, g_nameW))
2072         {
2073             if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2074         }
2075         else if (xml_attr_cmp(&attr, baseInterfaceW))
2076         {
2077             if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2078             entity->u.ifaceps.mask |= BaseIface;
2079         }
2080         else if (xml_attr_cmp(&attr, nummethodsW))
2081         {
2082             if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2083             entity->u.ifaceps.mask |= NumMethods;
2084         }
2085         else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2086         {
2087             if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2088         }
2089         else if (xml_attr_cmp(&attr, tlbidW))
2090         {
2091             if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2092         }
2093     }
2094 
2095     acl->actctx->sections |= IFACEREDIRECT_SECTION;
2096     if (!end) parse_expect_end_elem(xmlbuf, parent);
2097 }
2098 
2099 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2100                                   struct actctx_loader *acl, const struct xml_elem *parent )
2101 
2102 {
2103     struct xml_elem elem;
2104     struct xml_attr attr;
2105     BOOL end = FALSE;
2106     struct entity*      entity;
2107 
2108     if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2109     {
2110         set_error( xmlbuf );
2111         return;
2112     }
2113 
2114     while (next_xml_attr(xmlbuf, &attr, &end))
2115     {
2116         if (xml_attr_cmp(&attr, g_nameW))
2117         {
2118             if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2119         }
2120         else if (xml_attr_cmp(&attr, clsidW))
2121         {
2122             if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2123         }
2124         else if (xml_attr_cmp(&attr, progidW))
2125         {
2126             if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2127         }
2128         else if (xml_attr_cmp(&attr, tlbidW))
2129         {
2130             if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2131         }
2132         else if (xml_attr_cmp(&attr, threadingmodelW))
2133         {
2134             entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2135         }
2136         else if (xml_attr_cmp(&attr, runtimeVersionW))
2137         {
2138             if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2139         }
2140     }
2141 
2142     acl->actctx->sections |= SERVERREDIRECT_SECTION;
2143     if (entity->u.comclass.progid)
2144         acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2145     if (end) return;
2146 
2147     while (next_xml_elem(xmlbuf, &elem, parent))
2148     {
2149         if (xml_elem_cmp(&elem, progidW, asmv1W))
2150         {
2151             parse_com_class_progid(xmlbuf, entity, &elem);
2152         }
2153         else
2154         {
2155             parse_unknown_elem(xmlbuf, &elem);
2156         }
2157     }
2158 
2159     if (entity->u.comclass.progids.num)
2160         acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2161 }
2162 
2163 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2164                                       struct actctx_loader *acl, const struct xml_elem *parent )
2165 {
2166     struct xml_attr attr;
2167     BOOL end = FALSE;
2168     struct entity*      entity;
2169 
2170     if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2171     {
2172         set_error( xmlbuf );
2173         return;
2174     }
2175 
2176     while (next_xml_attr(xmlbuf, &attr, &end))
2177     {
2178         if (xml_attr_cmp(&attr, g_nameW))
2179         {
2180             if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2181         }
2182         else if (xml_attr_cmp(&attr, clsidW))
2183         {
2184             if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2185         }
2186         else if (xml_attr_cmp(&attr, runtimeVersionW))
2187         {
2188             if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2189         }
2190     }
2191 
2192     acl->actctx->sections |= CLRSURROGATES_SECTION;
2193     if (!end) parse_expect_end_elem(xmlbuf, parent);
2194 }
2195 
2196 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2197                                            const struct xml_elem *parent, BOOL optional )
2198 {
2199     struct xml_elem elem;
2200     struct xml_attr attr;
2201     struct assembly_identity    ai;
2202     BOOL end = FALSE;
2203 
2204     memset(&ai, 0, sizeof(ai));
2205     ai.optional = optional;
2206 
2207     while (next_xml_attr(xmlbuf, &attr, &end))
2208     {
2209         static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2210         static const WCHAR trueW[] = {'t','r','u','e',0};
2211 
2212         if (xml_attr_cmp(&attr, allowDelayedBindingW))
2213             ai.delayed = xmlstr_cmp(&attr.value, trueW);
2214     }
2215 
2216     if (end) return;
2217 
2218     while (next_xml_elem(xmlbuf, &elem, parent))
2219     {
2220         if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2221         {
2222             parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2223             /* store the newly found identity for later loading */
2224             if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2225             if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2226         }
2227         else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2228         {
2229             parse_binding_redirect_elem(xmlbuf, &elem);
2230         }
2231         else
2232         {
2233             parse_unknown_elem(xmlbuf, &elem);
2234         }
2235     }
2236 }
2237 
2238 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2239                                    const struct xml_elem *parent )
2240 
2241 {
2242     struct xml_elem elem;
2243     struct xml_attr attr;
2244     BOOL end = FALSE, optional = FALSE;
2245 
2246     while (next_xml_attr(xmlbuf, &attr, &end))
2247     {
2248         if (xml_attr_cmp(&attr, optionalW))
2249         {
2250             optional = xmlstr_cmpi( &attr.value, yesW );
2251         }
2252     }
2253 
2254     while (next_xml_elem(xmlbuf, &elem, parent))
2255     {
2256         if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2257         {
2258             parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2259         }
2260         else
2261         {
2262             parse_unknown_elem(xmlbuf, &elem);
2263         }
2264     }
2265 }
2266 
2267 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2268 {
2269     BOOL end = FALSE;
2270 
2271     parse_expect_no_attr(xmlbuf, &end);
2272     if (!end) parse_expect_end_elem(xmlbuf, parent);
2273 }
2274 
2275 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2276 {
2277     BOOL end = FALSE;
2278 
2279     parse_expect_no_attr(xmlbuf, &end);
2280     if (!end) parse_expect_end_elem(xmlbuf, parent);
2281 }
2282 
2283 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2284                              struct actctx_loader* acl, const struct xml_elem *parent )
2285 {
2286     struct xml_elem elem;
2287     struct xml_attr attr;
2288     BOOL end = FALSE;
2289     struct dll_redirect* dll;
2290 
2291     if (!(dll = add_dll_redirect(assembly)))
2292     {
2293         set_error( xmlbuf );
2294         return;
2295     }
2296 
2297     while (next_xml_attr(xmlbuf, &attr, &end))
2298     {
2299         if (xml_attr_cmp(&attr, g_nameW))
2300         {
2301             if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2302         }
2303         else if (xml_attr_cmp(&attr, hashW))
2304         {
2305             if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2306         }
2307         else if (xml_attr_cmp(&attr, hashalgW))
2308         {
2309             static const WCHAR sha1W[] = {'S','H','A','1',0};
2310             if (!xmlstr_cmpi(&attr.value, sha1W)) {
2311                 //FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2312             }
2313         }
2314     }
2315 
2316     if (!dll->name) set_error( xmlbuf );
2317 
2318     acl->actctx->sections |= DLLREDIRECT_SECTION;
2319 
2320     if (end) return;
2321 
2322     while (next_xml_elem(xmlbuf, &elem, parent))
2323     {
2324         if (xml_elem_cmp(&elem, comClassW, asmv1W))
2325         {
2326             parse_com_class_elem(xmlbuf, dll, acl, &elem);
2327         }
2328         else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2329         {
2330             parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2331         }
2332         else if (xml_elem_cmp(&elem, hashW, asmv2W))
2333         {
2334             parse_unknown_elem(xmlbuf, &elem);
2335         }
2336         else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2337         {
2338             parse_typelib_elem(xmlbuf, dll, acl, &elem);
2339         }
2340         else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2341         {
2342             parse_window_class_elem(xmlbuf, dll, acl, &elem);
2343         }
2344         else
2345         {
2346             parse_unknown_elem( xmlbuf, &elem );
2347         }
2348     }
2349 }
2350 
2351 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2352                                     struct actctx_loader *acl, const struct xml_elem *parent )
2353 {
2354     struct xml_attr attr;
2355     BOOL end = FALSE;
2356 
2357     while (next_xml_attr(xmlbuf, &attr, &end))
2358     {
2359         if (xml_attr_cmp(&attr, IdW))
2360         {
2361             COMPATIBILITY_CONTEXT_ELEMENT *compat;
2362             UNICODE_STRING str;
2363             GUID compat_id;
2364 
2365             str.Buffer = (PWSTR)attr.value.ptr;
2366             str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2367             if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2368             {
2369                 if (!(compat = add_compat_context(assembly)))
2370                 {
2371                     set_error( xmlbuf );
2372                     return;
2373                 }
2374                 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2375                 compat->Id = compat_id;
2376             }
2377         }
2378     }
2379 
2380     if (!end) parse_expect_end_elem(xmlbuf, parent);
2381 }
2382 
2383 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2384                                                  struct actctx_loader* acl, const struct xml_elem *parent)
2385 {
2386     struct xml_elem elem;
2387 
2388     while (next_xml_elem(xmlbuf, &elem, parent))
2389     {
2390         if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2391         {
2392             parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2393         }
2394         else
2395         {
2396             parse_unknown_elem(xmlbuf, &elem);
2397         }
2398     }
2399 }
2400 
2401 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2402                                      struct actctx_loader* acl, const struct xml_elem *parent)
2403 {
2404     struct xml_elem elem;
2405 
2406     while (next_xml_elem(xmlbuf, &elem, parent))
2407     {
2408         if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2409         {
2410             parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2411         }
2412         else
2413         {
2414             parse_unknown_elem(xmlbuf, &elem);
2415         }
2416     }
2417 }
2418 
2419 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2420                                  struct xml_elem *parent )
2421 {
2422     struct xml_elem elem;
2423     struct xml_attr attr;
2424     xmlstr_t content;
2425     BOOL end = FALSE;
2426     struct entity *entity;
2427 
2428     while (next_xml_attr( xmlbuf, &attr, &end ))
2429     {
2430     }
2431 
2432     if (end) return;
2433 
2434     if (!parse_text_content( xmlbuf, &content )) return;
2435 
2436     entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2437     if (!entity)
2438     {
2439         set_error( xmlbuf );
2440         return;
2441     }
2442     entity->u.settings.name = xmlstrdupW( &parent->name );
2443     entity->u.settings.value = xmlstrdupW( &content );
2444     entity->u.settings.ns = xmlstrdupW( &parent->ns );
2445 
2446     while (next_xml_elem(xmlbuf, &elem, parent))
2447     {
2448         parse_unknown_elem( xmlbuf, &elem );
2449     }
2450 }
2451 
2452 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2453                                          struct actctx_loader *acl, const struct xml_elem *parent )
2454 {
2455     struct xml_elem elem;
2456 
2457     while (next_xml_elem( xmlbuf, &elem, parent ))
2458     {
2459         if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2460             xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2461             xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2462             xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2463             xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2464             xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2465             xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2466             xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2467             xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2468             xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2469             xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2470         {
2471             parse_settings_elem( xmlbuf, assembly, acl, &elem );
2472         }
2473         else
2474         {
2475             parse_unknown_elem( xmlbuf, &elem );
2476         }
2477     }
2478 }
2479 
2480 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2481                                     struct actctx_loader *acl, const struct xml_elem *parent )
2482 {
2483     struct xml_elem elem;
2484 
2485     while (next_xml_elem( xmlbuf, &elem, parent ))
2486     {
2487         if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2488         {
2489             parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2490         }
2491         else
2492         {
2493             parse_unknown_elem( xmlbuf, &elem );
2494         }
2495     }
2496 }
2497 
2498 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2499                                                   struct actctx_loader *acl, const struct xml_elem *parent )
2500 {
2501     static const WCHAR levelW[] = {'l','e','v','e','l',0};
2502     static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2503     static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2504     static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2505     static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2506     static const WCHAR falseW[] = {'f','a','l','s','e',0};
2507     static const WCHAR trueW[] = {'t','r','u','e',0};
2508 
2509     struct xml_elem elem;
2510     struct xml_attr attr;
2511     BOOL end = FALSE;
2512 
2513     /* Multiple requestedExecutionLevel elements are not supported. */
2514     if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2515 
2516     while (next_xml_attr(xmlbuf, &attr, &end))
2517     {
2518         if (xml_attr_cmp(&attr, levelW))
2519         {
2520             if (xmlstr_cmpi(&attr.value, asInvokerW))
2521                 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2522             else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2523                 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2524             else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2525                 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2526         }
2527         else if (xml_attr_cmp(&attr, uiAccessW))
2528         {
2529             if (xmlstr_cmpi(&attr.value, falseW))
2530                 assembly->ui_access = FALSE;
2531             else if (xmlstr_cmpi(&attr.value, trueW))
2532                 assembly->ui_access = TRUE;
2533         }
2534     }
2535 
2536     if (end) return;
2537 
2538     while (next_xml_elem(xmlbuf, &elem, parent))
2539     {
2540         parse_unknown_elem(xmlbuf, &elem);
2541     }
2542 }
2543 
2544 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2545                                              struct actctx_loader *acl, const struct xml_elem *parent )
2546 {
2547     struct xml_elem elem;
2548 
2549     while (next_xml_elem(xmlbuf, &elem, parent))
2550     {
2551         if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2552         {
2553             parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2554         }
2555         else
2556         {
2557             parse_unknown_elem(xmlbuf, &elem);
2558         }
2559     }
2560 }
2561 
2562 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2563                                  struct actctx_loader *acl, const struct xml_elem *parent )
2564 {
2565     struct xml_elem elem;
2566 
2567     while (next_xml_elem(xmlbuf, &elem, parent))
2568     {
2569         if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2570         {
2571             parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2572         }
2573         else
2574         {
2575             parse_unknown_elem(xmlbuf, &elem);
2576         }
2577     }
2578 }
2579 
2580 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2581                                    struct actctx_loader *acl, const struct xml_elem *parent )
2582 {
2583     struct xml_elem elem;
2584 
2585     while (next_xml_elem(xmlbuf, &elem, parent))
2586     {
2587         if (xml_elem_cmp(&elem, securityW, asmv1W))
2588         {
2589             parse_security_elem(xmlbuf, assembly, acl, &elem);
2590         }
2591         else
2592         {
2593             parse_unknown_elem(xmlbuf, &elem);
2594         }
2595     }
2596 }
2597 
2598 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2599                                  struct actctx_loader* acl, const struct xml_elem *parent,
2600                                  struct assembly_identity* expected_ai)
2601 {
2602     struct xml_elem elem;
2603     struct xml_attr attr;
2604     BOOL end = FALSE, version = FALSE;
2605 
2606     while (next_xml_attr(xmlbuf, &attr, &end))
2607     {
2608         if (xml_attr_cmp(&attr, manifestVersionW))
2609         {
2610             static const WCHAR v10W[] = {'1','.','0',0};
2611             if (!xmlstr_cmp(&attr.value, v10W))
2612             {
2613                 break;
2614             }
2615             version = TRUE;
2616         }
2617     }
2618 
2619     if (end || !version)
2620     {
2621         set_error( xmlbuf );
2622         return;
2623     }
2624 
2625     while (next_xml_elem(xmlbuf, &elem, parent))
2626     {
2627         if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2628         {
2629             parse_noinherit_elem(xmlbuf, &elem);
2630             assembly->no_inherit = TRUE;
2631         }
2632         else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2633         {
2634             parse_noinheritable_elem(xmlbuf, &elem);
2635         }
2636         else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2637         {
2638             parse_description_elem(xmlbuf, &elem);
2639         }
2640         else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2641         {
2642             parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2643         }
2644         else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2645         {
2646             parse_dependency_elem(xmlbuf, acl, &elem);
2647         }
2648         else if (xml_elem_cmp(&elem, fileW, asmv1W))
2649         {
2650             parse_file_elem(xmlbuf, assembly, acl, &elem);
2651         }
2652         else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2653         {
2654             parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2655         }
2656         else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2657         {
2658             parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2659         }
2660         else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2661         {
2662             parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2663         }
2664         else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2665         {
2666             parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2667 
2668             if (!xmlbuf->error && expected_ai)
2669             {
2670                 /* FIXME: more tests */
2671                 if (assembly->type == ASSEMBLY_MANIFEST &&
2672                     memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2673                 {
2674                     set_error( xmlbuf );
2675                 }
2676                 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2677                          (assembly->id.version.major != expected_ai->version.major ||
2678                           assembly->id.version.minor != expected_ai->version.minor ||
2679                           assembly->id.version.build < expected_ai->version.build ||
2680                           (assembly->id.version.build == expected_ai->version.build &&
2681                            assembly->id.version.revision < expected_ai->version.revision)))
2682                 {
2683                     set_error( xmlbuf );
2684                 }
2685             }
2686         }
2687         else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2688         {
2689             parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2690         }
2691         else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2692         {
2693             parse_application_elem(xmlbuf, assembly, acl, &elem);
2694         }
2695         else
2696         {
2697             parse_unknown_elem(xmlbuf, &elem);
2698         }
2699     }
2700 
2701     if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2702         assembly->no_inherit)
2703     {
2704         set_error( xmlbuf );
2705     }
2706 }
2707 
2708 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2709                                        struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2710 {
2711     struct xml_elem elem;
2712     struct xml_elem parent = {0};
2713 
2714     xmlbuf->error = FALSE;
2715     xmlbuf->ns_pos = 0;
2716 
2717     if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2718 
2719     if (xmlstr_cmp(&elem.name, g_xmlW) &&
2720         (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2721         return STATUS_SXS_CANT_GEN_ACTCTX;
2722 
2723     if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2724     {
2725         return STATUS_SXS_CANT_GEN_ACTCTX;
2726     }
2727 
2728     parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2729     if (xmlbuf->error)
2730     {
2731         return STATUS_SXS_CANT_GEN_ACTCTX;
2732     }
2733 
2734     if (next_xml_elem(xmlbuf, &elem, &parent))
2735     {
2736         return STATUS_SXS_CANT_GEN_ACTCTX;
2737     }
2738 
2739     if (xmlbuf->ptr != xmlbuf->end)
2740     {
2741         return STATUS_SXS_CANT_GEN_ACTCTX;
2742     }
2743     return STATUS_SUCCESS;
2744 }
2745 
2746 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2747                                 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2748                                 const void *buffer, SIZE_T size )
2749 {
2750     xmlbuf_t xmlbuf;
2751     NTSTATUS status;
2752     struct assembly *assembly;
2753     int unicode_tests;
2754 
2755     DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2756 
2757     if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2758         return STATUS_SXS_CANT_GEN_ACTCTX;
2759 
2760     if (directory && !(assembly->directory = strdupW(directory)))
2761         return STATUS_NO_MEMORY;
2762 
2763     if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2764     assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2765                                                       : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2766 
2767     unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2768     if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2769     {
2770         xmlbuf.ptr = buffer;
2771         xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2772         status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2773     }
2774     else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2775     {
2776         const WCHAR *buf = buffer;
2777         WCHAR *new_buff;
2778         unsigned int i;
2779 
2780         if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2781             return STATUS_NO_MEMORY;
2782         for (i = 0; i < size / sizeof(WCHAR); i++)
2783             new_buff[i] = RtlUshortByteSwap( buf[i] );
2784         xmlbuf.ptr = new_buff;
2785         xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2786         status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2787         RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2788     }
2789     else
2790     {
2791         /* TODO: this doesn't handle arbitrary encodings */
2792         WCHAR *new_buff;
2793         ULONG sizeU;
2794 
2795         status = RtlMultiByteToUnicodeSize(&sizeU, buffer, size);
2796         if (!NT_SUCCESS(status))
2797         {
2798             DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2799             return STATUS_SXS_CANT_GEN_ACTCTX;
2800         }
2801 
2802         new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2803         if (!new_buff)
2804             return STATUS_NO_MEMORY;
2805 
2806         status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2807         if (!NT_SUCCESS(status))
2808         {
2809             DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2810             return STATUS_SXS_CANT_GEN_ACTCTX;
2811         }
2812 
2813         xmlbuf.ptr = new_buff;
2814         xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2815         status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2816         RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2817     }
2818     return status;
2819 }
2820 
2821 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2822 {
2823     OBJECT_ATTRIBUTES attr;
2824     IO_STATUS_BLOCK io;
2825 
2826     attr.Length = sizeof(attr);
2827     attr.RootDirectory = 0;
2828     attr.Attributes = OBJ_CASE_INSENSITIVE;
2829     attr.ObjectName = name;
2830     attr.SecurityDescriptor = NULL;
2831     attr.SecurityQualityOfService = NULL;
2832     return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2833 }
2834 
2835 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
2836 {
2837     NTSTATUS status;
2838     ULONG_PTR magic;
2839     LDR_DATA_TABLE_ENTRY *pldr;
2840 
2841     LdrLockLoaderLock(0, NULL, &magic);
2842     status = LdrFindEntryForAddress( module, &pldr );
2843     if (status == STATUS_SUCCESS)
2844     {
2845         if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2846                                             pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2847         {
2848             memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2849             str->Length = pldr->FullDllName.Length;
2850             str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2851         }
2852         else status = STATUS_NO_MEMORY;
2853     }
2854     LdrUnlockLoaderLock(0, magic);
2855     return status;
2856 }
2857 
2858 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2859                                         LPCWSTR filename, LPCWSTR directory, BOOL shared,
2860                                         HANDLE hModule, LPCWSTR resname, ULONG lang )
2861 {
2862     NTSTATUS status;
2863     UNICODE_STRING nameW;
2864     LDR_RESOURCE_INFO info;
2865     IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2866     void *ptr;
2867 
2868     //DPRINT( "looking for res %s in module %p %s\n", resname,
2869     //                hModule, filename );
2870     DPRINT("get_manifest_in_module %p\n", hModule);
2871 
2872 #if 0
2873     if (TRACE_ON(actctx))
2874     {
2875         if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2876         {
2877             DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2878                    hModule, debugstr_w(nameW.Buffer) );
2879             RtlFreeUnicodeString( &nameW );
2880         }
2881         else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2882                     hModule, debugstr_w(filename) );
2883     }
2884 #endif
2885 
2886     if (!resname) return STATUS_INVALID_PARAMETER;
2887 
2888     info.Type = (ULONG_PTR)RT_MANIFEST;
2889     info.Language = lang;
2890     if (!((ULONG_PTR)resname >> 16))
2891     {
2892         info.Name = (ULONG_PTR)resname;
2893         status = LdrFindResource_U(hModule, &info, 3, &entry);
2894     }
2895     else if (resname[0] == '#')
2896     {
2897         ULONG value;
2898         RtlInitUnicodeString(&nameW, resname + 1);
2899         if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2900             return STATUS_INVALID_PARAMETER;
2901         info.Name = value;
2902         status = LdrFindResource_U(hModule, &info, 3, &entry);
2903     }
2904     else
2905     {
2906         RtlCreateUnicodeString(&nameW, resname);
2907         RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2908         info.Name = (ULONG_PTR)nameW.Buffer;
2909         status = LdrFindResource_U(hModule, &info, 3, &entry);
2910         RtlFreeUnicodeString(&nameW);
2911     }
2912     if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2913 
2914     if (status == STATUS_SUCCESS)
2915         status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2916 
2917     return status;
2918 }
2919 
2920 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
2921                                              LPCWSTR name, void *root,
2922                                              int want_dir );
2923 
2924 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
2925                                             void *root, int want_dir );
2926 
2927 
2928 static IMAGE_RESOURCE_DIRECTORY *find_first_id_entry( IMAGE_RESOURCE_DIRECTORY *dir,
2929                                            void *root, int want_dir )
2930 {
2931     const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
2932     int pos;
2933 
2934     for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
2935     {
2936         if (!entry[pos].DataIsDirectory == !want_dir)
2937             return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
2938     }
2939     return NULL;
2940 }
2941 
2942 
2943 static NTSTATUS search_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2944                                        LPCWSTR filename, LPCWSTR directory, BOOL shared,
2945                                        HANDLE hModule, ULONG lang )
2946 {
2947     ULONG size;
2948     PVOID root, ptr;
2949     IMAGE_RESOURCE_DIRECTORY *resdirptr;
2950     IMAGE_RESOURCE_DATA_ENTRY *entry;
2951     NTSTATUS status;
2952 
2953     root = RtlImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size);
2954     if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
2955     if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
2956     resdirptr = root;
2957 
2958     if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1)))
2959         return STATUS_RESOURCE_TYPE_NOT_FOUND;
2960 
2961     resdirptr = ptr;
2962     if (!(ptr = find_first_id_entry(resdirptr, root, 1)))
2963         return STATUS_RESOURCE_TYPE_NOT_FOUND;
2964 
2965     resdirptr = ptr;
2966     if (!(ptr = find_first_entry(resdirptr, root, 0)))
2967         return STATUS_RESOURCE_TYPE_NOT_FOUND;
2968 
2969     entry = ptr;
2970     status = LdrAccessResource(hModule, entry, &ptr, NULL);
2971 
2972     if (status == STATUS_SUCCESS)
2973         status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2974 
2975     return status;
2976 }
2977 
2978 
2979 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2980                                          LPCWSTR filename, LPCWSTR directory, BOOL shared,
2981                                          HANDLE file, LPCWSTR resname, ULONG lang )
2982 {
2983     HANDLE              mapping;
2984     OBJECT_ATTRIBUTES   attr;
2985     LARGE_INTEGER       size;
2986     LARGE_INTEGER       offset;
2987     NTSTATUS            status;
2988     SIZE_T              count;
2989     void               *base;
2990     WCHAR resnameBuf[20];
2991     LPCWSTR resptr = resname;
2992 
2993     if ((!((ULONG_PTR)resname >> 16)))
2994     {
2995         sprintfW(resnameBuf, L"#%u", PtrToUlong(resname));
2996         resptr = resnameBuf;
2997     }
2998 
2999     DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>");
3000 
3001     attr.Length                   = sizeof(attr);
3002     attr.RootDirectory            = 0;
3003     attr.ObjectName               = NULL;
3004     attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3005     attr.SecurityDescriptor       = NULL;
3006     attr.SecurityQualityOfService = NULL;
3007 
3008     size.QuadPart = 0;
3009     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3010                               &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3011     if (status != STATUS_SUCCESS) return status;
3012 
3013     offset.QuadPart = 0;
3014     count = 0;
3015     base = NULL;
3016     status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
3017                                  &count, ViewShare, 0, PAGE_READONLY );
3018     NtClose( mapping );
3019     if (status != STATUS_SUCCESS) return status;
3020 
3021     if (RtlImageNtHeader(base)) /* we got a PE file */
3022     {
3023         HANDLE module = (HMODULE)((ULONG_PTR)base | 1);  /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3024         if (resname)
3025             status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3026         else
3027             status = search_manifest_in_module(acl, ai, filename, directory, shared, module, lang);
3028     }
3029     else status = STATUS_INVALID_IMAGE_FORMAT;
3030 
3031     NtUnmapViewOfSection( NtCurrentProcess(), base );
3032     return status;
3033 }
3034 
3035 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3036                                                LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3037 {
3038     FILE_STANDARD_INFORMATION info;
3039     IO_STATUS_BLOCK io;
3040     HANDLE              mapping;
3041     OBJECT_ATTRIBUTES   attr;
3042     LARGE_INTEGER       size;
3043     LARGE_INTEGER       offset;
3044     NTSTATUS            status;
3045     SIZE_T              count;
3046     void               *base;
3047 
3048     DPRINT( "loading manifest file %S\n", filename );
3049 
3050     attr.Length                   = sizeof(attr);
3051     attr.RootDirectory            = 0;
3052     attr.ObjectName               = NULL;
3053     attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3054     attr.SecurityDescriptor       = NULL;
3055     attr.SecurityQualityOfService = NULL;
3056 
3057     size.QuadPart = 0;
3058     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3059                               &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3060 
3061     if (status != STATUS_SUCCESS) return status;
3062 
3063     offset.QuadPart = 0;
3064     count = 0;
3065     base = NULL;
3066     status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
3067                                  &count, ViewShare, 0, PAGE_READONLY );
3068     NtClose( mapping );
3069     if (status != STATUS_SUCCESS) return status;
3070 
3071     /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
3072     status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
3073 
3074     if (status == STATUS_SUCCESS)
3075         status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
3076 
3077     NtUnmapViewOfSection( NtCurrentProcess(), base );
3078     return status;
3079 }
3080 
3081 /* try to load the .manifest file associated to the file */
3082 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3083                                                      LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3084 {
3085     static const WCHAR fmtW[] = { '.','%','l','u',0 };
3086     WCHAR *buffer;
3087     NTSTATUS status;
3088     UNICODE_STRING nameW;
3089     HANDLE file;
3090     ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
3091 
3092     if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3093 
3094     DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
3095 
3096     if (module) /* use the module filename */
3097     {
3098         UNICODE_STRING name;
3099 
3100         if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3101         {
3102             if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3103             strcatW( name.Buffer, dotManifestW );
3104             if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3105                 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3106             RtlFreeUnicodeString( &name );
3107         }
3108         if (status) return status;
3109     }
3110     else
3111     {
3112         if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3113                                         (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3114             return STATUS_NO_MEMORY;
3115         strcpyW( buffer, filename );
3116         if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3117         strcatW( buffer, dotManifestW );
3118         RtlInitUnicodeString( &nameW, buffer );
3119     }
3120 
3121     if (!open_nt_file( &file, &nameW ))
3122     {
3123         status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3124         NtClose( file );
3125     }
3126     else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3127     RtlFreeUnicodeString( &nameW );
3128     return status;
3129 }
3130 
3131 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3132 {
3133     static const WCHAR lookup_fmtW[] =
3134         {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3135          '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3136     static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3137 
3138     WCHAR *lookup, *ret = NULL;
3139     UNICODE_STRING lookup_us;
3140     IO_STATUS_BLOCK io;
3141     const WCHAR *lang = ai->language;
3142     unsigned int data_pos = 0, data_len;
3143     char buffer[8192];
3144 
3145     if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3146                                     (strlenW(ai->arch) + strlenW(ai->name)
3147                                      + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
3148                                     + sizeof(lookup_fmtW) )))
3149         return NULL;
3150 
3151     if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3152     sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3153               ai->version.major, ai->version.minor, lang );
3154     RtlInitUnicodeString( &lookup_us, lookup );
3155 
3156     if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3157                                FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3158     {
3159         ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3160         FILE_BOTH_DIR_INFORMATION *dir_info;
3161         WCHAR *tmp;
3162         ULONG build, revision;
3163 
3164         data_len = (ULONG)io.Information;
3165 
3166         for (;;)
3167         {
3168             if (data_pos >= data_len)
3169             {
3170                 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3171                                           FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3172                     break;
3173                 data_len = (ULONG)io.Information;
3174                 data_pos = 0;
3175             }
3176             dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3177 
3178             if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3179             else data_pos = data_len;
3180 
3181             tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
3182             build = atoiW(tmp);
3183             if (build < min_build) continue;
3184             tmp = strchrW(tmp, '.') + 1;
3185             revision = atoiW(tmp);
3186             if (build == min_build && revision < min_revision) continue;
3187             tmp = strchrW(tmp, '_') + 1;
3188             tmp = strchrW(tmp, '_') + 1;
3189             if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3190                 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3191             {
3192                 /* prefer a non-Wine manifest if we already have one */
3193                 /* we'll still load the builtin dll if specified through DllOverrides */
3194                 if (ret) continue;
3195             }
3196             else
3197             {
3198                 min_build = build;
3199                 min_revision = revision;
3200             }
3201             ai->version.build = build;
3202             ai->version.revision = revision;
3203             RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
3204             if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3205             {
3206                 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3207                 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3208             }
3209         }
3210     }
3211     else DPRINT1("no matching file for %S\n", lookup);
3212     RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
3213     return ret;
3214 }
3215 
3216 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3217 {
3218     struct assembly_identity    sxs_ai;
3219     UNICODE_STRING              path_us;
3220     OBJECT_ATTRIBUTES           attr;
3221     IO_STATUS_BLOCK             io;
3222     WCHAR *path, *file = NULL;
3223     HANDLE handle;
3224 
3225     static const WCHAR manifest_dirW[] =
3226         {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3227 
3228     if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3229 
3230     if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3231                                   ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
3232         return STATUS_NO_MEMORY;
3233 
3234     memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
3235     memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
3236 
3237     if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3238     {
3239         RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3240         return STATUS_NO_SUCH_FILE;
3241     }
3242     RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3243 
3244     attr.Length = sizeof(attr);
3245     attr.RootDirectory = 0;
3246     attr.Attributes = OBJ_CASE_INSENSITIVE;
3247     attr.ObjectName = &path_us;
3248     attr.SecurityDescriptor = NULL;
3249     attr.SecurityQualityOfService = NULL;
3250 
3251     if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3252                      FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3253     {
3254         sxs_ai = *ai;
3255         file = lookup_manifest_file( handle, &sxs_ai );
3256         NtClose( handle );
3257     }
3258     if (!file)
3259     {
3260         RtlFreeUnicodeString( &path_us );
3261         return STATUS_NO_SUCH_FILE;
3262     }
3263 
3264     /* append file name to directory path */
3265     if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
3266                                     path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3267     {
3268         RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3269         RtlFreeUnicodeString( &path_us );
3270         return STATUS_NO_MEMORY;
3271     }
3272 
3273     path[path_us.Length/sizeof(WCHAR)] = '\\';
3274     strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3275     RtlInitUnicodeString( &path_us, path );
3276     *strrchrW(file, '.') = 0;  /* remove .manifest extension */
3277 
3278     if (!open_nt_file( &handle, &path_us ))
3279     {
3280         io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3281         NtClose( handle );
3282     }
3283     else io.Status = STATUS_NO_SUCH_FILE;
3284 
3285     RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3286     RtlFreeUnicodeString( &path_us );
3287     return io.Status;
3288 }
3289 
3290 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3291                                 struct assembly_identity* ai)
3292 {
3293     static const WCHAR dotDllW[] = {'.','d','l','l',0};
3294     unsigned int i;
3295     WCHAR *buffer, *p, *directory;
3296     NTSTATUS status;
3297     UNICODE_STRING nameW;
3298     HANDLE file;
3299     DWORD len;
3300 
3301     DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
3302             ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
3303 
3304     if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3305 
3306     /* FIXME: add support for language specific lookup */
3307 
3308     len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3309         strlenW(acl->actctx->appdir.info));
3310 
3311     nameW.Buffer = NULL;
3312     if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3313                                     (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3314         return STATUS_NO_MEMORY;
3315 
3316     if (!(directory = build_assembly_dir( ai )))
3317     {
3318         RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3319         return STATUS_NO_MEMORY;
3320     }
3321 
3322     /* Lookup in <dir>\name.dll
3323      *           <dir>\name.manifest
3324      *           <dir>\name\name.dll
3325      *           <dir>\name\name.manifest
3326      *
3327      * First 'appdir' is used as <dir>, if that failed
3328      * it tries application manifest file path.
3329      */
3330     strcpyW( buffer, acl->actctx->appdir.info );
3331     p = buffer + strlenW(buffer);
3332     for (i = 0; i < 4; i++)
3333     {
3334         if (i == 2)
3335         {
3336             struct assembly *assembly = acl->actctx->assemblies;
3337             if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3338         }
3339         else *p++ = '\\';
3340 
3341         strcpyW( p, ai->name );
3342         p += strlenW(p);
3343 
3344         strcpyW( p, dotDllW );
3345         if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3346         {
3347             status = open_nt_file( &file, &nameW );
3348             if (!status)
3349             {
3350                 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3351                                                   (LPCWSTR)0, 0 );
3352                 NtClose( file );
3353                 break;
3354             }
3355             RtlFreeUnicodeString( &nameW );
3356         }
3357 
3358         strcpyW( p, dotManifestW );
3359         if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3360         {
3361             status = open_nt_file( &file, &nameW );
3362             if (!status)
3363             {
3364                 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3365                 NtClose( file );
3366                 break;
3367             }
3368             RtlFreeUnicodeString( &nameW );
3369         }
3370         status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3371     }
3372     RtlFreeUnicodeString( &nameW );
3373     RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
3374     RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3375     return status;
3376 }
3377 
3378 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3379 {
3380     NTSTATUS status = STATUS_SUCCESS;
3381     unsigned int i;
3382 
3383     for (i = 0; i < acl->num_dependencies; i++)
3384     {
3385         if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3386         {
3387             if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3388             {
3389                 const struct assembly_version *ver = &acl->dependencies[i].version;
3390                 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3391                     acl->dependencies[i].name,
3392                     ver->major, ver->minor, ver->build, ver->revision );
3393                 status = STATUS_SXS_CANT_GEN_ACTCTX;
3394                 break;
3395             }
3396         }
3397     }
3398     /* FIXME should now iterate through all refs */
3399     return status;
3400 }
3401 
3402 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3403 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3404 {
3405     NTSTATUS status = STATUS_SUCCESS;
3406 
3407     if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT)
3408     {
3409         if (*handle) return STATUS_INVALID_PARAMETER;
3410 
3411         if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
3412             *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
3413     }
3414     else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE))
3415     {
3416         ULONG_PTR magic;
3417         LDR_DATA_TABLE_ENTRY *pldr;
3418 
3419         if (!*handle) return STATUS_INVALID_PARAMETER;
3420 
3421         LdrLockLoaderLock( 0, NULL, &magic );
3422         if (!LdrFindEntryForAddress( *handle, &pldr ))
3423         {
3424             if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase)
3425                 status = STATUS_DLL_NOT_FOUND;
3426             else
3427                 *handle = pldr->EntryPointActivationContext;
3428         }
3429         else status = STATUS_DLL_NOT_FOUND;
3430         LdrUnlockLoaderLock( 0, magic );
3431     }
3432     else if (!*handle && (class != ActivationContextBasicInformation))
3433         *handle = process_actctx;
3434 
3435     return status;
3436 }
3437 
3438 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3439 {
3440     unsigned int i, j, total_len = 0, dll_count = 0;
3441     struct strsection_header *header;
3442     struct dllredirect_data *data;
3443     struct string_index *index;
3444     ULONG name_offset;
3445 
3446     DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies);
3447 
3448     /* compute section length */
3449     for (i = 0; i < actctx->num_assemblies; i++)
3450     {
3451         struct assembly *assembly = &actctx->assemblies[i];
3452         for (j = 0; j < assembly->num_dlls; j++)
3453         {
3454             struct dll_redirect *dll = &assembly->dlls[j];
3455 
3456             /* each entry needs index, data and string data */
3457             total_len += sizeof(*index);
3458             total_len += sizeof(*data);
3459             total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3460 
3461             DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name);
3462         }
3463 
3464         dll_count += assembly->num_dlls;
3465     }
3466 
3467     total_len += sizeof(*header);
3468 
3469     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3470     if (!header) return STATUS_NO_MEMORY;
3471 
3472     memset(header, 0, sizeof(*header));
3473     header->magic = STRSECTION_MAGIC;
3474     header->size  = sizeof(*header);
3475     header->count = dll_count;
3476     header->index_offset = sizeof(*header);
3477     index = (struct string_index*)((BYTE*)header + header->index_offset);
3478     name_offset = header->index_offset + header->count*sizeof(*index);
3479 
3480     for (i = 0; i < actctx->num_assemblies; i++)
3481     {
3482         struct assembly *assembly = &actctx->assemblies[i];
3483 
3484         DPRINT("assembly->num_dlls %d\n", assembly->num_dlls);
3485 
3486         for (j = 0; j < assembly->num_dlls; j++)
3487         {
3488             struct dll_redirect *dll = &assembly->dlls[j];
3489             UNICODE_STRING str;
3490             WCHAR *ptrW;
3491 
3492             DPRINT("%d: dll name %S\n", j, dll->name);
3493             /* setup new index entry */
3494             str.Buffer = dll->name;
3495             str.Length = (USHORT)strlenW(dll->name)*sizeof(WCHAR);
3496             str.MaximumLength = str.Length + sizeof(WCHAR);
3497             /* hash original class name */
3498             RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3499 
3500             index->name_offset = name_offset;
3501             index->name_len = str.Length;
3502             index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3503             index->data_len = sizeof(*data);
3504             index->rosterindex = i + 1;
3505 
3506             /* setup data */
3507             data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3508             data->size = sizeof(*data);
3509             data->unk = 2; /* FIXME: seems to be constant */
3510             memset(data->res, 0, sizeof(data->res));
3511 
3512             /* dll name */
3513             ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3514             memcpy(ptrW, dll->name, index->name_len);
3515             ptrW[index->name_len/sizeof(WCHAR)] = 0;
3516 
3517             name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3518 
3519             index++;
3520         }
3521     }
3522 
3523     *section = header;
3524 
3525     return STATUS_SUCCESS;
3526 }
3527 
3528 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3529 {
3530     struct string_index *iter, *index = NULL;
3531     ULONG hash = 0, i;
3532 
3533     DPRINT("section %p, name %wZ\n", section, name);
3534     RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3535     iter = (struct string_index*)((BYTE*)section + section->index_offset);
3536 
3537     for (i = 0; i < section->count; i++)
3538     {
3539         DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash);
3540         DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset));
3541         if (iter->hash == hash)
3542         {
3543             const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3544 
3545             if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) &&
3546                 wcslen(nameW) == name->Length / sizeof(WCHAR))
3547             {
3548                 index = iter;
3549                 break;
3550             }
3551             else
3552                 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3553         }
3554         iter++;
3555     }
3556 
3557     return index;
3558 }
3559 
3560 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3561 {
3562     struct guid_index *iter, *index = NULL;
3563     ULONG i;
3564 
3565     iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3566 
3567     for (i = 0; i < section->count; i++)
3568     {
3569         if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3570         {
3571             index = iter;
3572             break;
3573         }
3574         iter++;
3575     }
3576 
3577     return index;
3578 }
3579 
3580 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3581 {
3582     return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3583 }
3584 
3585 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3586                                      PACTCTX_SECTION_KEYED_DATA data)
3587 {
3588     struct dllredirect_data *dll;
3589     struct string_index *index;
3590 
3591     DPRINT("sections: 0x%08X\n", actctx->sections);
3592     if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3593 
3594     DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section);
3595     if (!actctx->dllredirect_section)
3596     {
3597         struct strsection_header *section;
3598 
3599         NTSTATUS status = build_dllredirect_section(actctx, &section);
3600         if (status) return status;
3601 
3602         if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3603             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3604     }
3605 
3606     index = find_string_index(actctx->dllredirect_section, name);
3607     DPRINT("index: %d\n", index);
3608     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3609 
3610     if (data)
3611     {
3612         dll = get_dllredirect_data(actctx, index);
3613 
3614         data->ulDataFormatVersion = 1;
3615         data->lpData = dll;
3616         data->ulLength = dll->size;
3617         data->lpSectionGlobalData = NULL;
3618         data->ulSectionGlobalDataLength = 0;
3619         data->lpSectionBase = actctx->dllredirect_section;
3620         data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
3621         data->hActCtx = NULL;
3622 
3623         if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3624             data->ulAssemblyRosterIndex = index->rosterindex;
3625     }
3626 
3627     return STATUS_SUCCESS;
3628 }
3629 
3630 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3631 {
3632     return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3633 }
3634 
3635 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3636 {
3637     return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3638 }
3639 
3640 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3641 {
3642     unsigned int i, j, k, total_len = 0, class_count = 0;
3643     struct wndclass_redirect_data *data;
3644     struct strsection_header *header;
3645     struct string_index *index;
3646     ULONG name_offset;
3647 
3648     /* compute section length */
3649     for (i = 0; i < actctx->num_assemblies; i++)
3650     {
3651         struct assembly *assembly = &actctx->assemblies[i];
3652         for (j = 0; j < assembly->num_dlls; j++)
3653         {
3654             struct dll_redirect *dll = &assembly->dlls[j];
3655             for (k = 0; k < dll->entities.num; k++)
3656             {
3657                 struct entity *entity = &dll->entities.base[k];
3658                 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3659                 {
3660                     int class_len = strlenW(entity->u.class.name) + 1;
3661                     int len;
3662 
3663                     /* each class entry needs index, data and string data */
3664                     total_len += sizeof(*index);
3665                     total_len += sizeof(*data);
3666                     /* original name is stored separately */
3667                     total_len += aligned_string_len(class_len*sizeof(WCHAR));
3668                     /* versioned name and module name are stored one after another */
3669                     if (entity->u.class.versioned)
3670                         len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3671                     else
3672                         len = class_len;
3673                     len += strlenW(dll->name) + 1;
3674                     total_len += aligned_string_len(len*sizeof(WCHAR));
3675 
3676                     class_count++;
3677                 }
3678             }
3679         }
3680     }
3681 
3682     total_len += sizeof(*header);
3683 
3684     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3685     if (!header) return STATUS_NO_MEMORY;
3686 
3687     memset(header, 0, sizeof(*header));
3688     header->magic = STRSECTION_MAGIC;
3689     header->size  = sizeof(*header);
3690     header->count = class_count;
3691     header->index_offset = sizeof(*header);
3692     index = (struct string_index*)((BYTE*)header + header->index_offset);
3693     name_offset = header->index_offset + header->count*sizeof(*index);
3694 
3695     for (i = 0; i < actctx->num_assemblies; i++)
3696     {
3697         struct assembly *assembly = &actctx->assemblies[i];
3698         for (j = 0; j < assembly->num_dlls; j++)
3699         {
3700             struct dll_redirect *dll = &assembly->dlls[j];
3701             for (k = 0; k < dll->entities.num; k++)
3702             {
3703                 struct entity *entity = &dll->entities.base[k];
3704                 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3705                 {
3706                     static const WCHAR exclW[] = {'!',0};
3707                     ULONG versioned_len, module_len;
3708                     UNICODE_STRING str;
3709                     WCHAR *ptrW;
3710 
3711                     /* setup new index entry */
3712                     str.Buffer = entity->u.class.name;
3713                     str.Length = (USHORT)strlenW(entity->u.class.name)*sizeof(WCHAR);
3714                     str.MaximumLength = str.Length + sizeof(WCHAR);
3715                     /* hash original class name */
3716                     RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3717 
3718                     /* include '!' separator too */
3719                     if (entity->u.class.versioned)
3720                         versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3721                     else
3722                         versioned_len = str.Length;
3723                     module_len = strlenW(dll->name)*sizeof(WCHAR);
3724 
3725                     index->name_offset = name_offset;
3726                     index->name_len = str.Length;
3727                     index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3728                     index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3729                     index->rosterindex = i + 1;
3730 
3731                     /* setup data */
3732                     data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3733                     data->size = sizeof(*data);
3734                     data->res = 0;
3735                     data->name_len = versioned_len;
3736                     data->name_offset = sizeof(*data);
3737                     data->module_len = module_len;
3738                     data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3739 
3740                     /* original class name */
3741                     ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3742                     memcpy(ptrW, entity->u.class.name, index->name_len);
3743                     ptrW[index->name_len/sizeof(WCHAR)] = 0;
3744 
3745                     /* module name */
3746                     ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3747                     memcpy(ptrW, dll->name, data->module_len);
3748                     ptrW[data->module_len/sizeof(WCHAR)] = 0;
3749 
3750                     /* versioned name */
3751                     ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3752                     if (entity->u.class.versioned)
3753                     {
3754                         get_assembly_version(assembly, ptrW);
3755                         strcatW(ptrW, exclW);
3756                         strcatW(ptrW, entity->u.class.name);
3757                     }
3758                     else
3759                     {
3760                         memcpy(ptrW, entity->u.class.name, index->name_len);
3761                         ptrW[index->name_len/sizeof(WCHAR)] = 0;
3762                     }
3763 
3764                     name_offset += sizeof(*data);
3765                     name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3766 
3767                     index++;
3768                 }
3769             }
3770         }
3771     }
3772 
3773     *section = header;
3774 
3775     return STATUS_SUCCESS;
3776 }
3777 
3778 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3779                                   PACTCTX_SECTION_KEYED_DATA data)
3780 {
3781     struct string_index *iter, *index = NULL;
3782     struct wndclass_redirect_data *class;
3783     ULONG hash;
3784     int i;
3785 
3786     if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3787 
3788     if (!actctx->wndclass_section)
3789     {
3790         struct strsection_header *section;
3791 
3792         NTSTATUS status = build_wndclass_section(actctx, &section);
3793         if (status) return status;
3794 
3795         if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3796             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3797     }
3798 
3799     hash = 0;
3800     RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3801     iter = get_wndclass_first_index(actctx);
3802 
3803     for (i = 0; i < actctx->wndclass_section->count; i++)
3804     {
3805         if (iter->hash == hash)
3806         {
3807             const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3808 
3809             if (!strcmpiW(nameW, name->Buffer))
3810             {
3811                 index = iter;
3812                 break;
3813             }
3814             else
3815                 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3816         }
3817         iter++;
3818     }
3819 
3820     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3821 
3822     if (data)
3823     {
3824         class = get_wndclass_data(actctx, index);
3825 
3826         data->ulDataFormatVersion = 1;
3827         data->lpData = class;
3828         /* full length includes string length with nulls */
3829         data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3830         data->lpSectionGlobalData = NULL;
3831         data->ulSectionGlobalDataLength = 0;
3832         data->lpSectionBase = actctx->wndclass_section;
3833         data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
3834         data->hActCtx = NULL;
3835 
3836         if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3837             data->ulAssemblyRosterIndex = index->rosterindex;
3838     }
3839 
3840     return STATUS_SUCCESS;
3841 }
3842 
3843 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3844 {
3845     unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3846     struct guidsection_header *header;
3847     ULONG module_offset, data_offset;
3848     struct tlibredirect_data *data;
3849     struct guid_index *index;
3850 
3851     /* compute section length */
3852     for (i = 0; i < actctx->num_assemblies; i++)
3853     {
3854         struct assembly *assembly = &actctx->assemblies[i];
3855         for (j = 0; j < assembly->num_dlls; j++)
3856         {
3857             struct dll_redirect *dll = &assembly->dlls[j];
3858             for (k = 0; k < dll->entities.num; k++)
3859             {
3860                 struct entity *entity = &dll->entities.base[k];
3861                 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3862                 {
3863                     /* each entry needs index, data and string data for module name and help string */
3864                     total_len += sizeof(*index);
3865                     total_len += sizeof(*data);
3866                     /* help string is stored separately */
3867                     if (*entity->u.typelib.helpdir)
3868                         total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3869 
3870                     /* module names are packed one after another */
3871                     names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3872 
3873                     tlib_count++;
3874                 }
3875             }
3876         }
3877     }
3878 
3879     total_len += aligned_string_len(names_len);
3880     total_len += sizeof(*header);
3881 
3882     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3883     if (!header) return STATUS_NO_MEMORY;
3884 
3885     memset(header, 0, sizeof(*header));
3886     header->magic = GUIDSECTION_MAGIC;
3887     header->size  = sizeof(*header);
3888     header->count = tlib_count;
3889     header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3890     index = (struct guid_index*)((BYTE*)header + header->index_offset);
3891     module_offset = sizeof(*header);
3892     data_offset = header->index_offset + tlib_count*sizeof(*index);
3893 
3894     for (i = 0; i < actctx->num_assemblies; i++)
3895     {
3896         struct assembly *assembly = &actctx->assemblies[i];
3897         for (j = 0; j < assembly->num_dlls; j++)
3898         {
3899             struct dll_redirect *dll = &assembly->dlls[j];
3900             for (k = 0; k < dll->entities.num; k++)
3901             {
3902                 struct entity *entity = &dll->entities.base[k];
3903                 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3904                 {
3905                     ULONG module_len, help_len;
3906                     UNICODE_STRING str;
3907                     WCHAR *ptrW;
3908 
3909                     if (*entity->u.typelib.helpdir)
3910                         help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3911                     else
3912                         help_len = 0;
3913 
3914                     module_len = strlenW(dll->name)*sizeof(WCHAR);
3915 
3916                     /* setup new index entry */
3917                     RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3918                     RtlGUIDFromString(&str, &index->guid);
3919                     index->data_offset = data_offset;
3920                     index->data_len = sizeof(*data) + aligned_string_len(help_len);
3921                     index->rosterindex = i + 1;
3922 
3923                     /* setup data */
3924                     data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3925                     data->size = sizeof(*data);
3926                     data->res = 0;
3927                     data->name_len = module_len;
3928                     data->name_offset = module_offset;
3929                     /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3930                     data->langid = 0;
3931                     data->flags = entity->u.typelib.flags;
3932                     data->help_len = help_len;
3933                     data->help_offset = sizeof(*data);
3934                     data->major_version = entity->u.typelib.major;
3935                     data->minor_version = entity->u.typelib.minor;
3936 
3937                     /* module name */
3938                     ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3939                     memcpy(ptrW, dll->name, data->name_len);
3940                     ptrW[data->name_len/sizeof(WCHAR)] = 0;
3941 
3942                     /* help string */
3943                     if (data->help_len)
3944                     {
3945                         ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3946                         memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3947                         ptrW[data->help_len/sizeof(WCHAR)] = 0;
3948                     }
3949 
3950                     data_offset += sizeof(*data);
3951                     if (help_len)
3952                         data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3953 
3954                     module_offset += module_len + sizeof(WCHAR);
3955 
3956                     index++;
3957                 }
3958             }
3959         }
3960     }
3961 
3962     *section = header;
3963 
3964     return STATUS_SUCCESS;
3965 }
3966 
3967 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3968 {
3969     return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3970 }
3971 
3972 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3973 {
3974     struct guid_index *index = NULL;
3975     struct tlibredirect_data *tlib;
3976 
3977     if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3978 
3979     if (!actctx->tlib_section)
3980     {
3981         struct guidsection_header *section;
3982 
3983         NTSTATUS status = build_tlib_section(actctx, &section);
3984         if (status) return status;
3985 
3986         if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3987             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3988     }
3989 
3990     index = find_guid_index(actctx->tlib_section, guid);
3991     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3992 
3993     tlib = get_tlib_data(actctx, index);
3994 
3995     data->ulDataFormatVersion = 1;
3996     data->lpData = tlib;
3997     /* full length includes string length with nulls */
3998     data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3999     data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
4000     data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
4001     data->lpSectionBase = actctx->tlib_section;
4002     data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
4003     data->hActCtx = NULL;
4004 
4005     if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4006         data->ulAssemblyRosterIndex = index->rosterindex;
4007 
4008     return STATUS_SUCCESS;
4009 }
4010 
4011 static void generate_uuid(ULONG *seed, GUID *guid)
4012 {
4013     ULONG *ptr = (ULONG*)guid;
4014     int i;
4015 
4016     /* GUID is 16 bytes long */
4017     for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
4018         *ptr = RtlUniform(seed);
4019 
4020     guid->Data3 &= 0x0fff;
4021     guid->Data3 |= (4 << 12);
4022     guid->Data4[0] &= 0x3f;
4023     guid->Data4[0] |= 0x80;
4024 }
4025 
4026 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4027     unsigned int *count, unsigned int *len, unsigned int *module_len)
4028 {
4029     unsigned int i;
4030 
4031     for (i = 0; i < entities->num; i++)
4032     {
4033         struct entity *entity = &entities->base[i];
4034         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4035         {
4036             /* each entry needs two index entries, extra one goes for alias GUID */
4037             *len += 2*sizeof(struct guid_index);
4038             /* To save some memory we don't allocated two data structures,
4039                instead alias index and normal index point to the same data structure. */
4040             *len += sizeof(struct comclassredirect_data);
4041 
4042             /* for clrClass store some more */
4043             if (entity->u.comclass.name)
4044             {
4045                 unsigned int str_len;
4046 
4047                 /* all string data is stored together in aligned block */
4048                 str_len = strlenW(entity->u.comclass.name)+1;
4049                 if (entity->u.comclass.progid)
4050                     str_len += strlenW(entity->u.comclass.progid)+1;
4051                 if (entity->u.comclass.version)
4052                     str_len += strlenW(entity->u.comclass.version)+1;
4053 
4054                 *len += sizeof(struct clrclass_data);
4055                 *len += aligned_string_len(str_len*sizeof(WCHAR));
4056 
4057                 /* module name is forced to mscoree.dll, and stored two times with different case */
4058                 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4059             }
4060             else
4061             {
4062                 /* progid string is stored separately */
4063                 if (entity->u.comclass.progid)
4064                     *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4065 
4066                 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
4067             }
4068 
4069             *count += 1;
4070         }
4071     }
4072 }
4073 
4074 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4075     const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4076     ULONG *seed, ULONG rosterindex)
4077 {
4078     unsigned int i;
4079 
4080     for (i = 0; i < entities->num; i++)
4081     {
4082         struct entity *entity = &entities->base[i];
4083         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4084         {
4085             ULONG module_len, progid_len, str_len = 0;
4086             struct comclassredirect_data *data;
4087             struct guid_index *alias_index;
4088             struct clrclass_data *clrdata;
4089             UNICODE_STRING str;
4090             WCHAR *ptrW;
4091 
4092             if (entity->u.comclass.progid)
4093                 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4094             else
4095                 progid_len = 0;
4096 
4097             module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4098 
4099             /* setup new index entry */
4100             RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4101             RtlGUIDFromString(&str, &(*index)->guid);
4102 
4103             (*index)->data_offset = *data_offset;
4104             (*index)->data_len = sizeof(*data); /* additional length added later */
4105             (*index)->rosterindex = rosterindex;
4106 
4107             /* Setup new index entry for alias guid. Alias index records are placed after
4108                normal records, so normal guids are hit first on search. Note that class count
4109                is doubled. */
4110             alias_index = (*index) + section->count/2;
4111             generate_uuid(seed, &alias_index->guid);
4112             alias_index->data_offset = (*index)->data_offset;
4113             alias_index->data_len = 0;
4114             alias_index->rosterindex = (*index)->rosterindex;
4115 
4116             /* setup data */
4117             data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4118             data->size = sizeof(*data);
4119             data->res = 0;
4120             data->res1[0] = 0;
4121             data->res1[1] = 0;
4122             data->model = entity->u.comclass.model;
4123             data->clsid = (*index)->guid;
4124             data->alias = alias_index->guid;
4125             data->clsid2 = data->clsid;
4126             if (entity->u.comclass.tlbid)
4127             {
4128                 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4129                 RtlGUIDFromString(&str, &data->tlbid);
4130             }
4131             else
4132                 memset(&data->tlbid, 0, sizeof(data->tlbid));
4133             data->name_len = module_len;
4134             data->name_offset = *module_offset;
4135             data->progid_len = progid_len;
4136             data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4137             data->clrdata_len = 0; /* will be set later */
4138             data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4139             data->miscstatus = entity->u.comclass.miscstatus;
4140             data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4141             data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4142             data->miscstatusicon = entity->u.comclass.miscstatusicon;
4143             data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4144 
4145             /* mask describes which misc* data is available */
4146             data->miscmask = 0;
4147             if (data->miscstatus)
4148                 data->miscmask |= MiscStatus;
4149             if (data->miscstatuscontent)
4150                 data->miscmask |= MiscStatusContent;
4151             if (data->miscstatusthumbnail)
4152                 data->miscmask |= MiscStatusThumbnail;
4153             if (data->miscstatusicon)
4154                 data->miscmask |= MiscStatusIcon;
4155             if (data->miscstatusdocprint)
4156                 data->miscmask |= MiscStatusDocPrint;
4157 
4158             if (data->clrdata_offset)
4159             {
4160                 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4161 
4162                 clrdata->size = sizeof(*clrdata);
4163                 clrdata->res[0] = 0;
4164                 clrdata->res[1] = 2; /* FIXME: unknown field */
4165                 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4166                 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4167                 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4168                 clrdata->name_offset = clrdata->size;
4169                 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4170                 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4171                 clrdata->res2[0] = 0;
4172                 clrdata->res2[1] = 0;
4173 
4174                 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4175 
4176                 /* module name */
4177                 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4178                 memcpy(ptrW, mscoree2W, clrdata->module_len);
4179                 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4180 
4181                 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4182                 memcpy(ptrW, mscoreeW, data->name_len);
4183                 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4184 
4185                 /* class name */
4186                 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4187                 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4188                 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4189 
4190                 /* runtime version, optional */
4191                 if (clrdata->version_len)
4192                 {
4193                     data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4194 
4195                     ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4196                     memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4197                     ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4198                 }
4199 
4200                 if (data->progid_len)
4201                     data->progid_offset += data->clrdata_len;
4202                 (*index)->data_len += sizeof(*clrdata);
4203             }
4204             else
4205             {
4206                 clrdata = NULL;
4207 
4208                 /* module name */
4209                 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4210                 memcpy(ptrW, dll->name, data->name_len);
4211                 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4212             }
4213 
4214             /* progid string */
4215             if (data->progid_len)
4216             {
4217                 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4218                 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4219                 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4220             }
4221 
4222             /* string block length */
4223             str_len = 0;
4224             if (clrdata)
4225             {
4226                 str_len += clrdata->name_len + sizeof(WCHAR);
4227                 if (clrdata->version_len)
4228                     str_len += clrdata->version_len + sizeof(WCHAR);
4229             }
4230             if (progid_len)
4231                 str_len += progid_len + sizeof(WCHAR);
4232 
4233             (*index)->data_len += aligned_string_len(str_len);
4234             alias_index->data_len = (*index)->data_len;
4235 
4236             /* move to next data record */
4237             (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4238             (*module_offset) += module_len + sizeof(WCHAR);
4239 
4240             if (clrdata)
4241             {
4242                 (*data_offset) += sizeof(*clrdata);
4243                 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4244             }
4245             (*index) += 1;
4246         }
4247     }
4248 }
4249 
4250 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4251 {
4252     unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4253     struct guidsection_header *header;
4254     ULONG module_offset, data_offset;
4255     struct guid_index *index;
4256     ULONG seed;
4257 
4258     /* compute section length */
4259     for (i = 0; i < actctx->num_assemblies; i++)
4260     {
4261         struct assembly *assembly = &actctx->assemblies[i];
4262         get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4263         for (j = 0; j < assembly->num_dlls; j++)
4264         {
4265             struct dll_redirect *dll = &assembly->dlls[j];
4266             get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4267         }
4268     }
4269 
4270     total_len += aligned_string_len(names_len);
4271     total_len += sizeof(*header);
4272 
4273     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4274     if (!header) return STATUS_NO_MEMORY;
4275 
4276     memset(header, 0, sizeof(*header));
4277     header->magic = GUIDSECTION_MAGIC;
4278     header->size  = sizeof(*header);
4279     header->count = 2*class_count;
4280     header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4281     index = (struct guid_index*)((BYTE*)header + header->index_offset);
4282     module_offset = sizeof(*header);
4283     data_offset = header->index_offset + 2*class_count*sizeof(*index);
4284 
4285     seed = NtGetTickCount();
4286     for (i = 0; i < actctx->num_assemblies; i++)
4287     {
4288         struct assembly *assembly = &actctx->assemblies[i];
4289         add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4290         for (j = 0; j < assembly->num_dlls; j++)
4291         {
4292             struct dll_redirect *dll = &assembly->dlls[j];
4293             add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4294         }
4295     }
4296 
4297     *section = header;
4298 
4299     return STATUS_SUCCESS;
4300 }
4301 
4302 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4303 {
4304     return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4305 }
4306 
4307 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4308 {
4309     struct comclassredirect_data *comclass;
4310     struct guid_index *index = NULL;
4311 
4312     if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4313 
4314     if (!actctx->comserver_section)
4315     {
4316         struct guidsection_header *section;
4317 
4318         NTSTATUS status = build_comserver_section(actctx, &section);
4319         if (status) return status;
4320 
4321         if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4322             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4323     }
4324 
4325     index = find_guid_index(actctx->comserver_section, guid);
4326     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4327 
4328     comclass = get_comclass_data(actctx, index);
4329 
4330     data->ulDataFormatVersion = 1;
4331     data->lpData = comclass;
4332     /* full length includes string length with nulls */
4333     data->ulLength = comclass->size + comclass->clrdata_len;
4334     if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4335     data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4336     data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4337     data->lpSectionBase = actctx->comserver_section;
4338     data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
4339     data->hActCtx = NULL;
4340 
4341     if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4342         data->ulAssemblyRosterIndex = index->rosterindex;
4343 
4344     return STATUS_SUCCESS;
4345 }
4346 
4347 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4348 {
4349     unsigned int i;
4350 
4351     for (i = 0; i < entities->num; i++)
4352     {
4353         struct entity *entity = &entities->base[i];
4354         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4355         {
4356             *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4357             if (entity->u.ifaceps.name)
4358                 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4359             *count += 1;
4360         }
4361     }
4362 }
4363 
4364 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4365     struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4366 {
4367     unsigned int i;
4368 
4369     for (i = 0; i < entities->num; i++)
4370     {
4371         struct entity *entity = &entities->base[i];
4372         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4373         {
4374             struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4375             UNICODE_STRING str;
4376             ULONG name_len;
4377 
4378             if (entity->u.ifaceps.name)
4379                 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4380             else
4381                 name_len = 0;
4382 
4383             /* setup index */
4384             RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4385             RtlGUIDFromString(&str, &(*index)->guid);
4386             (*index)->data_offset = *data_offset;
4387             (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4388             (*index)->rosterindex = rosterindex;
4389 
4390             /* setup data record */
4391             data->size = sizeof(*data);
4392             data->mask = entity->u.ifaceps.mask;
4393 
4394             /* proxyStubClsid32 value is only stored for external PS,
4395                if set it's used as iid, otherwise 'iid' attribute value is used */
4396             if (entity->u.ifaceps.ps32)
4397             {
4398                 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4399                 RtlGUIDFromString(&str, &data->iid);
4400             }
4401             else
4402                 data->iid = (*index)->guid;
4403 
4404             data->nummethods = entity->u.ifaceps.nummethods;
4405 
4406             if (entity->u.ifaceps.tlib)
4407             {
4408                 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4409                 RtlGUIDFromString(&str, &data->tlbid);
4410             }
4411             else
4412                 memset(&data->tlbid, 0, sizeof(data->tlbid));
4413 
4414             if (entity->u.ifaceps.base)
4415             {
4416                 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4417                 RtlGUIDFromString(&str, &data->base);
4418             }
4419             else
4420                 memset(&data->base, 0, sizeof(data->base));
4421 
4422             data->name_len = name_len;
4423             data->name_offset = data->name_len ? sizeof(*data) : 0;
4424 
4425             /* name string */
4426             if (data->name_len)
4427             {
4428                 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4429                 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4430                 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4431             }
4432 
4433             /* move to next record */
4434             (*index) += 1;
4435             *data_offset += sizeof(*data);
4436             if (data->name_len)
4437                 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4438         }
4439     }
4440 }
4441 
4442 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4443 {
4444     unsigned int i, j, total_len = 0, count = 0;
4445     struct guidsection_header *header;
4446     struct guid_index *index;
4447     ULONG data_offset;
4448 
4449     /* compute section length */
4450     for (i = 0; i < actctx->num_assemblies; i++)
4451     {
4452         struct assembly *assembly = &actctx->assemblies[i];
4453 
4454         get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4455         for (j = 0; j < assembly->num_dlls; j++)
4456         {
4457             struct dll_redirect *dll = &assembly->dlls[j];
4458             get_ifaceps_datalen(&dll->entities, &count, &total_len);
4459         }
4460     }
4461 
4462     total_len += sizeof(*header);
4463 
4464     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4465     if (!header) return STATUS_NO_MEMORY;
4466 
4467     memset(header, 0, sizeof(*header));
4468     header->magic = GUIDSECTION_MAGIC;
4469     header->size  = sizeof(*header);
4470     header->count = count;
4471     header->index_offset = sizeof(*header);
4472     index = (struct guid_index*)((BYTE*)header + header->index_offset);
4473     data_offset = header->index_offset + count*sizeof(*index);
4474 
4475     for (i = 0; i < actctx->num_assemblies; i++)
4476     {
4477         struct assembly *assembly = &actctx->assemblies[i];
4478 
4479         add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4480         for (j = 0; j < assembly->num_dlls; j++)
4481         {
4482             struct dll_redirect *dll = &assembly->dlls[j];
4483             add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4484         }
4485     }
4486 
4487     *section = header;
4488 
4489     return STATUS_SUCCESS;
4490 }
4491 
4492 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4493 {
4494     return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4495 }
4496 
4497 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4498 {
4499     struct ifacepsredirect_data *iface;
4500     struct guid_index *index = NULL;
4501 
4502     if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4503 
4504     if (!actctx->ifaceps_section)
4505     {
4506         struct guidsection_header *section;
4507 
4508         NTSTATUS status = build_ifaceps_section(actctx, &section);
4509         if (status) return status;
4510 
4511         if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4512             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4513     }
4514 
4515     index = find_guid_index(actctx->ifaceps_section, guid);
4516     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4517 
4518     iface = get_ifaceps_data(actctx, index);
4519 
4520     data->ulDataFormatVersion = 1;
4521     data->lpData = iface;
4522     data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4523     data->lpSectionGlobalData = NULL;
4524     data->ulSectionGlobalDataLength = 0;
4525     data->lpSectionBase = actctx->ifaceps_section;
4526     data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
4527     data->hActCtx = NULL;
4528 
4529     if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4530         data->ulAssemblyRosterIndex = index->rosterindex;
4531 
4532     return STATUS_SUCCESS;
4533 }
4534 
4535 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4536 {
4537     unsigned int i, j, total_len = 0, count = 0;
4538     struct guidsection_header *header;
4539     struct clrsurrogate_data *data;
4540     struct guid_index *index;
4541     ULONG data_offset;
4542 
4543     /* compute section length */
4544     for (i = 0; i < actctx->num_assemblies; i++)
4545     {
4546         struct assembly *assembly = &actctx->assemblies[i];
4547         for (j = 0; j < assembly->entities.num; j++)
4548         {
4549             struct entity *entity = &assembly->entities.base[j];
4550             if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4551             {
4552                 ULONG len;
4553 
4554                 total_len += sizeof(*index) + sizeof(*data);
4555                 len = strlenW(entity->u.clrsurrogate.name) + 1;
4556                 if (entity->u.clrsurrogate.version)
4557                    len += strlenW(entity->u.clrsurrogate.version) + 1;
4558                 total_len += aligned_string_len(len*sizeof(WCHAR));
4559 
4560                 count++;
4561             }
4562         }
4563     }
4564 
4565     total_len += sizeof(*header);
4566 
4567     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4568     if (!header) return STATUS_NO_MEMORY;
4569 
4570     memset(header, 0, sizeof(*header));
4571     header->magic = GUIDSECTION_MAGIC;
4572     header->size  = sizeof(*header);
4573     header->count = count;
4574     header->index_offset = sizeof(*header);
4575     index = (struct guid_index*)((BYTE*)header + header->index_offset);
4576     data_offset = header->index_offset + count*sizeof(*index);
4577 
4578     for (i = 0; i < actctx->num_assemblies; i++)
4579     {
4580         struct assembly *assembly = &actctx->assemblies[i];
4581         for (j = 0; j < assembly->entities.num; j++)
4582         {
4583             struct entity *entity = &assembly->entities.base[j];
4584             if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4585             {
4586                 ULONG version_len, name_len;
4587                 UNICODE_STRING str;
4588                 WCHAR *ptrW;
4589 
4590                 if (entity->u.clrsurrogate.version)
4591                     version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4592                 else
4593                     version_len = 0;
4594                 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4595 
4596                 /* setup new index entry */
4597                 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4598                 RtlGUIDFromString(&str, &index->guid);
4599 
4600                 index->data_offset = data_offset;
4601                 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4602                 index->rosterindex = i + 1;
4603 
4604                 /* setup data */
4605                 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4606                 data->size = sizeof(*data);
4607                 data->res = 0;
4608                 data->clsid = index->guid;
4609                 data->version_offset = version_len ? data->size : 0;
4610                 data->version_len = version_len;
4611                 data->name_offset = data->size + version_len;
4612                 if (version_len)
4613                     data->name_offset += sizeof(WCHAR);
4614                 data->name_len = name_len;
4615 
4616                 /* surrogate name */
4617                 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4618                 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4619                 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4620 
4621                 /* runtime version */
4622                 if (data->version_len)
4623                 {
4624                     ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4625                     memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4626                     ptrW[data->version_len/sizeof(WCHAR)] = 0;
4627                 }
4628 
4629                 data_offset += index->data_offset;
4630                 index++;
4631             }
4632         }
4633     }
4634 
4635     *section = header;
4636 
4637     return STATUS_SUCCESS;
4638 }
4639 
4640 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4641 {
4642     return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4643 }
4644 
4645 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4646 {
4647     struct clrsurrogate_data *surrogate;
4648     struct guid_index *index = NULL;
4649 
4650     if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4651 
4652     if (!actctx->clrsurrogate_section)
4653     {
4654         struct guidsection_header *section;
4655 
4656         NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4657         if (status) return status;
4658 
4659         if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4660             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4661     }
4662 
4663     index = find_guid_index(actctx->clrsurrogate_section, guid);
4664     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4665 
4666     surrogate = get_surrogate_data(actctx, index);
4667 
4668     data->ulDataFormatVersion = 1;
4669     data->lpData = surrogate;
4670     /* full length includes string length with nulls */
4671     data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4672     if (surrogate->version_len)
4673         data->ulLength += surrogate->version_len + sizeof(WCHAR);
4674 
4675     data->lpSectionGlobalData = NULL;
4676     data->ulSectionGlobalDataLength = 0;
4677     data->lpSectionBase = actctx->clrsurrogate_section;
4678     data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
4679     data->hActCtx = NULL;
4680 
4681     if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4682         data->ulAssemblyRosterIndex = index->rosterindex;
4683 
4684     return STATUS_SUCCESS;
4685 }
4686 
4687 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4688 {
4689     unsigned int i, j, single_len;
4690 
4691     single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4692     for (i = 0; i < entities->num; i++)
4693     {
4694         struct entity *entity = &entities->base[i];
4695         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4696         {
4697             if (entity->u.comclass.progid)
4698             {
4699                 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4700                 *count += 1;
4701             }
4702 
4703             for (j = 0; j < entity->u.comclass.progids.num; j++)
4704                 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4705 
4706             *total_len += single_len*entity->u.comclass.progids.num;
4707             *count += entity->u.comclass.progids.num;
4708         }
4709     }
4710 }
4711 
4712 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4713     struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4714 {
4715     struct progidredirect_data *data;
4716     UNICODE_STRING str;
4717     GUID *guid_ptr;
4718     WCHAR *ptrW;
4719 
4720     /* setup new index entry */
4721 
4722     /* hash progid name */
4723     RtlInitUnicodeString(&str, progid);
4724     RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4725 
4726     (*index)->name_offset = *data_offset;
4727     (*index)->name_len = str.Length;
4728     (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4729     (*index)->data_len = sizeof(*data);
4730     (*index)->rosterindex = rosterindex;
4731 
4732     *data_offset += aligned_string_len(str.MaximumLength);
4733 
4734     /* setup data structure */
4735     data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4736     data->size = sizeof(*data);
4737     data->reserved = 0;
4738     data->clsid_offset = *global_offset;
4739 
4740     /* write progid string */
4741     ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4742     memcpy(ptrW, progid, (*index)->name_len);
4743     ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4744 
4745     /* write guid to global area */
4746     guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4747     *guid_ptr = *alias;
4748 
4749     /* to next entry */
4750     *global_offset += sizeof(GUID);
4751     *data_offset += data->size;
4752     (*index) += 1;
4753 }
4754 
4755 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4756     struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4757 {
4758     unsigned int i, j;
4759 
4760     for (i = 0; i < entities->num; i++)
4761     {
4762         struct entity *entity = &entities->base[i];
4763         if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4764         {
4765             const struct progids *progids = &entity->u.comclass.progids;
4766             struct comclassredirect_data *comclass;
4767             struct guid_index *guid_index;
4768             UNICODE_STRING str;
4769             GUID clsid;
4770 
4771             RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4772             RtlGUIDFromString(&str, &clsid);
4773 
4774             guid_index = find_guid_index(actctx->comserver_section, &clsid);
4775             comclass = get_comclass_data(actctx, guid_index);
4776 
4777             if (entity->u.comclass.progid)
4778                 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4779                      index, data_offset, global_offset, rosterindex);
4780 
4781             for (j = 0; j < progids->num; j++)
4782                 write_progid_record(section, progids->progids[j], &comclass->alias,
4783                      index, data_offset, global_offset, rosterindex);
4784         }
4785     }
4786 }
4787 
4788 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4789 {
4790     unsigned int i, j, total_len = 0, count = 0;
4791     struct strsection_header *header;
4792     ULONG data_offset, global_offset;
4793     struct string_index *index;
4794 
4795     /* compute section length */
4796     for (i = 0; i < actctx->num_assemblies; i++)
4797     {
4798         struct assembly *assembly = &actctx->assemblies[i];
4799 
4800         get_progid_datalen(&assembly->entities, &count, &total_len);
4801         for (j = 0; j < assembly->num_dlls; j++)
4802         {
4803             struct dll_redirect *dll = &assembly->dlls[j];
4804             get_progid_datalen(&dll->entities, &count, &total_len);
4805         }
4806     }
4807 
4808     total_len += sizeof(*header);
4809 
4810     header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4811     if (!header) return STATUS_NO_MEMORY;
4812 
4813     memset(header, 0, sizeof(*header));
4814     header->magic = STRSECTION_MAGIC;
4815     header->size  = sizeof(*header);
4816     header->count = count;
4817     header->global_offset = header->size;
4818     header->global_len = count*sizeof(GUID);
4819     header->index_offset = header->size + header->global_len;
4820 
4821     index = (struct string_index*)((BYTE*)header + header->index_offset);
4822     data_offset = header->index_offset + count*sizeof(*index);
4823     global_offset = header->global_offset;
4824 
4825     for (i = 0; i < actctx->num_assemblies; i++)
4826     {
4827         struct assembly *assembly = &actctx->assemblies[i];
4828 
4829         add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4830         for (j = 0; j < assembly->num_dlls; j++)
4831         {
4832             struct dll_redirect *dll = &assembly->dlls[j];
4833             add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4834         }
4835     }
4836 
4837     *section = header;
4838 
4839     return STATUS_SUCCESS;
4840 }
4841 
4842 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4843 {
4844     return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4845 }
4846 
4847 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4848                                      PACTCTX_SECTION_KEYED_DATA data)
4849 {
4850     struct progidredirect_data *progid;
4851     struct string_index *index;
4852 
4853     if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4854 
4855     if (!actctx->comserver_section)
4856     {
4857         struct guidsection_header *section;
4858 
4859         NTSTATUS status = build_comserver_section(actctx, &section);
4860         if (status) return status;
4861 
4862         if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4863             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4864     }
4865 
4866     if (!actctx->progid_section)
4867     {
4868         struct strsection_header *section;
4869 
4870         NTSTATUS status = build_progid_section(actctx, &section);
4871         if (status) return status;
4872 
4873         if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4874             RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4875     }
4876 
4877     index = find_string_index(actctx->progid_section, name);
4878     if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4879 
4880     if (data)
4881     {
4882         progid = get_progid_data(actctx, index);
4883 
4884         data->ulDataFormatVersion = 1;
4885         data->lpData = progid;
4886         data->ulLength = progid->size;
4887         data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4888         data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4889         data->lpSectionBase = actctx->progid_section;
4890         data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
4891         data->hActCtx = NULL;
4892 
4893         if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4894             data->ulAssemblyRosterIndex = index->rosterindex;
4895     }
4896 
4897     return STATUS_SUCCESS;
4898 }
4899 
4900 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4901                             const UNICODE_STRING *section_name,
4902                             DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4903 {
4904     NTSTATUS status;
4905 
4906     switch (section_kind)
4907     {
4908     case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION:
4909         DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4910         return STATUS_SXS_KEY_NOT_FOUND;
4911     case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4912         status = find_dll_redirection(actctx, section_name, data);
4913         break;
4914     case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4915         status = find_window_class(actctx, section_name, data);
4916         break;
4917     case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4918         status = find_progid_redirection(actctx, section_name, data);
4919         break;
4920     case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4921         DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4922         return STATUS_SXS_SECTION_NOT_FOUND;
4923     default:
4924         DPRINT1("Unknown section_kind %x\n", section_kind);
4925         return STATUS_SXS_SECTION_NOT_FOUND;
4926     }
4927 
4928     if (status != STATUS_SUCCESS) return status;
4929 
4930     if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4931     {
4932         actctx_addref(actctx);
4933         data->hActCtx = actctx;
4934     }
4935     return STATUS_SUCCESS;
4936 }
4937 
4938 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4939                           const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4940 {
4941     NTSTATUS status;
4942 
4943     switch (section_kind)
4944     {
4945     case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4946         status = find_tlib_redirection(actctx, guid, data);
4947         break;
4948     case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4949         status = find_comserver_redirection(actctx, guid, data);
4950         break;
4951     case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4952         status = find_cominterface_redirection(actctx, guid, data);
4953         break;
4954     case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4955         status = find_clr_surrogate(actctx, guid, data);
4956         break;
4957     default:
4958         DPRINT("Unknown section_kind %x\n", section_kind);
4959         return STATUS_SXS_SECTION_NOT_FOUND;
4960     }
4961 
4962     if (status != STATUS_SUCCESS) return status;
4963 
4964     if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4965     {
4966         actctx_addref(actctx);
4967         data->hActCtx = actctx;
4968     }
4969     return STATUS_SUCCESS;
4970 }
4971 
4972 /* initialize the activation context for the current process */
4973 void actctx_init(PVOID* pOldShimData)
4974 {
4975     ACTCTXW ctx;
4976     HANDLE handle;
4977     WCHAR buffer[1024];
4978     NTSTATUS Status;
4979 
4980     ctx.cbSize   = sizeof(ctx);
4981     ctx.lpSource = NULL;
4982     ctx.dwFlags  = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4983     ctx.hModule  = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
4984     ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4985 
4986     if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle)))
4987     {
4988         process_actctx = check_actctx(handle);
4989     }
4990 
4991     /* ReactOS specific:
4992        Now that we have found the process_actctx we can initialize the process compat subsystem */
4993     LdrpInitializeProcessCompat(process_actctx, pOldShimData);
4994 
4995 
4996     ctx.dwFlags  = 0;
4997     ctx.hModule  = NULL;
4998     ctx.lpResourceName = NULL;
4999     ctx.lpSource = buffer;
5000     RtlStringCchCopyW(buffer, RTL_NUMBER_OF(buffer), SharedUserData->NtSystemRoot);
5001 
5002     if (RosGetProcessCompatVersion())
5003     {
5004         RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\forwardcompatible.manifest");
5005     }
5006     else
5007     {
5008         RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\systemcompatible.manifest");
5009     }
5010 
5011     Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle);
5012     if (NT_SUCCESS(Status))
5013     {
5014         implicit_actctx = check_actctx(handle);
5015     }
5016     else
5017     {
5018         DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status);
5019     }
5020 }
5021 
5022 /* FUNCTIONS ***************************************************************/
5023 
5024 /***********************************************************************
5025  * RtlCreateActivationContext (NTDLL.@)
5026  *
5027  * Create an activation context.
5028  */
5029 NTSTATUS
5030 NTAPI
5031 RtlCreateActivationContext(IN ULONG Flags,
5032                            IN PACTIVATION_CONTEXT_DATA ActivationContextData,
5033                            IN ULONG ExtraBytes,
5034                            IN PVOID NotificationRoutine,
5035                            IN PVOID NotificationContext,
5036                            OUT PACTIVATION_CONTEXT *ActCtx)
5037 {
5038     const ACTCTXW *pActCtx = (PVOID)ActivationContextData;
5039     const WCHAR *directory = NULL;
5040     PACTIVATION_CONTEXT_WRAPPED ActualActCtx;
5041     ACTIVATION_CONTEXT *actctx;
5042     UNICODE_STRING nameW;
5043     ULONG lang = 0;
5044     NTSTATUS status = STATUS_NO_MEMORY;
5045     HANDLE file = 0;
5046     struct actctx_loader acl;
5047 
5048     DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule);
5049 
5050     if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5051         (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5052         return STATUS_INVALID_PARAMETER;
5053 
5054 
5055     if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx))))
5056         return STATUS_NO_MEMORY;
5057 
5058     ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER;
5059 
5060     actctx = &ActualActCtx->ActivationContext;
5061     actctx->RefCount = 1;
5062     actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5063     actctx->config.info = NULL;
5064     actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5065     if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5066     {
5067         if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5068     }
5069     else
5070     {
5071         UNICODE_STRING dir;
5072         WCHAR *p;
5073         HMODULE module;
5074 
5075         if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5076         else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
5077 
5078         status = get_module_filename( module, &dir, 0 );
5079         if (!NT_SUCCESS(status)) goto error;
5080         if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
5081         actctx->appdir.info = dir.Buffer;
5082     }
5083 
5084     nameW.Buffer = NULL;
5085 
5086     /* open file only if it's going to be used */
5087     if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5088                                (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5089     {
5090         WCHAR *source = NULL;
5091         BOOLEAN ret;
5092 
5093         if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5094             RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative)
5095         {
5096             DWORD dir_len, source_len;
5097 
5098             dir_len = strlenW(pActCtx->lpAssemblyDirectory);
5099             source_len = strlenW(pActCtx->lpSource);
5100             if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5101             {
5102                 status = STATUS_NO_MEMORY;
5103                 goto error;
5104             }
5105 
5106             memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5107             source[dir_len] = '\\';
5108             memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5109         }
5110 
5111         ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5112         RtlFreeHeap( RtlGetProcessHeap(), 0, source );
5113         if (!ret)
5114         {
5115             status = STATUS_NO_SUCH_FILE;
5116             goto error;
5117         }
5118         status = open_nt_file( &file, &nameW );
5119         if (!NT_SUCCESS(status))
5120         {
5121             RtlFreeUnicodeString( &nameW );
5122             goto error;
5123         }
5124     }
5125 
5126     acl.actctx = actctx;
5127     acl.dependencies = NULL;
5128     acl.num_dependencies = 0;
5129     acl.allocated_dependencies = 0;
5130 
5131     if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5132     if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5133 
5134     if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5135     {
5136         /* if we have a resource it's a PE file */
5137         if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5138         {
5139             status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5140                                              pActCtx->lpResourceName, lang );
5141             if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5142                 /* FIXME: what to do if pActCtx->lpSource is set */
5143                 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5144                                                               pActCtx->hModule, pActCtx->lpResourceName );
5145         }
5146         else if (pActCtx->lpSource && pActCtx->lpResourceName)
5147         {
5148             status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5149                                               file, pActCtx->lpResourceName, lang );
5150             if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5151                 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5152                                                               NULL, pActCtx->lpResourceName );
5153         }
5154         else status = STATUS_INVALID_PARAMETER;
5155     }
5156     else
5157     {
5158         status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5159     }
5160 
5161     if (file) NtClose( file );
5162     RtlFreeUnicodeString( &nameW );
5163 
5164     if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl);
5165     free_depend_manifests( &acl );
5166 
5167     if (NT_SUCCESS(status))
5168         *ActCtx = actctx;
5169     else actctx_release( actctx );
5170     return status;
5171 
5172 error:
5173     if (file) NtClose( file );
5174     actctx_release( actctx );
5175     return status;
5176 }
5177 
5178 #if 0
5179 #define ACT_CTX_VALID(p)    ((((ULONG_PTR)p - 1) | 7) != -1)
5180 
5181 VOID
5182 NTAPI
5183 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle)
5184 {
5185     PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle;
5186     LONG OldRefCount, NewRefCount;
5187 
5188     if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
5189     {
5190         RtlpValidateActCtx(ActCtx);
5191 
5192         while (TRUE)
5193         {
5194             OldRefCount = ActCtx->RefCount;
5195             ASSERT(OldRefCount > 0);
5196 
5197             if (OldRefCount == LONG_MAX) break;
5198 
5199             NewRefCount = OldRefCount + 1;
5200             if (InterlockedCompareExchange(&ActCtx->RefCount,
5201                                            NewRefCount,
5202                                            OldRefCount) == OldRefCount)
5203             {
5204                 break;
5205             }
5206         }
5207 
5208         NewRefCount = LONG_MAX;
5209         ASSERT(NewRefCount > 0);
5210     }
5211 }
5212 
5213 VOID
5214 NTAPI
5215 RtlReleaseActivationContext( HANDLE handle )
5216 {
5217     PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle;
5218 
5219     if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
5220     {
5221         RtlpValidateActCtx(ActCtx);
5222 
5223         actctx_release(ActCtx);
5224     }
5225 }
5226 #else
5227 
5228 /***********************************************************************
5229  *		RtlAddRefActivationContext (NTDLL.@)
5230  */
5231 VOID NTAPI RtlAddRefActivationContext( HANDLE handle )
5232 {
5233     ACTIVATION_CONTEXT *actctx;
5234 
5235     if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5236 }
5237 
5238 
5239 /******************************************************************
5240  *		RtlReleaseActivationContext (NTDLL.@)
5241  */
5242 VOID NTAPI RtlReleaseActivationContext( HANDLE handle )
5243 {
5244     ACTIVATION_CONTEXT *actctx;
5245 
5246     if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5247 }
5248 
5249 #endif
5250 
5251 /******************************************************************
5252  *              RtlZombifyActivationContext (NTDLL.@)
5253  *
5254  */
5255 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context)
5256 {
5257     UNIMPLEMENTED;
5258 
5259     if (Context == ACTCTX_FAKE_HANDLE)
5260         return STATUS_SUCCESS;
5261 
5262     return STATUS_NOT_IMPLEMENTED;
5263 }
5264 
5265 NTSTATUS
5266 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
5267 {
5268     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5269 
5270     if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
5271         return STATUS_NO_MEMORY;
5272 
5273     frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
5274     frame->ActivationContext = handle;
5275     frame->Flags = 0;
5276 
5277     DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5278         tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame,
5279         frame, handle);
5280 
5281     tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
5282     RtlAddRefActivationContext( handle );
5283 
5284     *cookie = (ULONG_PTR)frame;
5285     DPRINT( "%p cookie=%lx\n", handle, *cookie );
5286     return STATUS_SUCCESS;
5287 }
5288 
5289 /******************************************************************
5290  *		RtlActivateActivationContext (NTDLL.@)
5291  */
5292 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
5293 {
5294     return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
5295 }
5296 
5297 /***********************************************************************
5298  *		RtlDeactivateActivationContext (NTDLL.@)
5299  */
5300 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5301 {
5302     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5303 
5304     DPRINT( "%x cookie=%lx\n", flags, cookie );
5305 
5306     /* find the right frame */
5307     top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5308     for (frame = top; frame; frame = frame->Previous)
5309         if ((ULONG_PTR)frame == cookie) break;
5310 
5311     if (!frame)
5312         RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5313 
5314     if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION))
5315         RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5316 
5317     DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5318         NtCurrentTeb()->ActivationContextStackPointer,
5319         NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame,
5320         frame->Previous);
5321 
5322     /* pop everything up to and including frame */
5323     NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
5324 
5325     while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5326     {
5327         frame = top->Previous;
5328         RtlReleaseActivationContext( top->ActivationContext );
5329         RtlFreeHeap( RtlGetProcessHeap(), 0, top );
5330         top = frame;
5331     }
5332 
5333     return STATUS_SUCCESS;
5334 }
5335 
5336 VOID
5337 NTAPI
5338 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
5339 {
5340     PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
5341 
5342     /* Nothing to do if there is no stack */
5343     if (!Stack) return;
5344 
5345     /* Get the current active frame */
5346     ActiveFrame = Stack->ActiveFrame;
5347 
5348     /* Go through them in backwards order and release */
5349     while (ActiveFrame)
5350     {
5351         PrevFrame = ActiveFrame->Previous;
5352         RtlReleaseActivationContext(ActiveFrame->ActivationContext);
5353         RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
5354         ActiveFrame = PrevFrame;
5355     }
5356 
5357     /* Zero out the active frame */
5358     Stack->ActiveFrame = NULL;
5359 
5360     /* TODO: Empty the Frame List Cache */
5361     ASSERT(IsListEmpty(&Stack->FrameListCache));
5362 
5363     /* Free activation stack memory */
5364     RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
5365 }
5366 
5367 /******************************************************************
5368  *		RtlFreeThreadActivationContextStack (NTDLL.@)
5369  */
5370 VOID NTAPI RtlFreeThreadActivationContextStack(VOID)
5371 {
5372     RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
5373     NtCurrentTeb()->ActivationContextStackPointer = NULL;
5374 }
5375 
5376 
5377 /******************************************************************
5378  *		RtlGetActiveActivationContext (NTDLL.@)
5379  */
5380 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle )
5381 {
5382     if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5383     {
5384         *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
5385         RtlAddRefActivationContext( *handle );
5386     }
5387     else
5388         *handle = 0;
5389 
5390     return STATUS_SUCCESS;
5391 }
5392 
5393 
5394 /******************************************************************
5395  *		RtlIsActivationContextActive (NTDLL.@)
5396  */
5397 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle )
5398 {
5399     RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5400 
5401     for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
5402         if (frame->ActivationContext == handle) return TRUE;
5403     return FALSE;
5404 }
5405 
5406 
5407 /***********************************************************************
5408  *		RtlQueryInformationActivationContext (NTDLL.@)
5409  *
5410  * Get information about an activation context.
5411  * FIXME: function signature/prototype may be wrong
5412  */
5413 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5414                                                      ULONG class, PVOID buffer,
5415                                                      SIZE_T bufsize, SIZE_T *retlen )
5416 {
5417     ACTIVATION_CONTEXT *actctx;
5418     NTSTATUS status;
5419 
5420     DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle,
5421           subinst, class, buffer, bufsize, retlen);
5422 
5423     if (retlen) *retlen = 0;
5424     if ((status = find_query_actctx( &handle, flags, class ))) return status;
5425 
5426     switch (class)
5427     {
5428     case ActivationContextBasicInformation:
5429         {
5430             ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5431 
5432             if (retlen) *retlen = sizeof(*info);
5433             if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5434 
5435             info->hActCtx = handle;
5436             info->dwFlags = 0;  /* FIXME */
5437             if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle);
5438         }
5439         break;
5440 
5441     case ActivationContextDetailedInformation:
5442         {
5443             ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5444             struct assembly *assembly = NULL;
5445             SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5446             LPWSTR ptr;
5447 
5448             if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5449 
5450             if (actctx->num_assemblies) assembly = actctx->assemblies;
5451 
5452             if (assembly && assembly->manifest.info)
5453                 manifest_len = strlenW(assembly->manifest.info) + 1;
5454             if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5455             if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5456             len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5457 
5458             if (retlen) *retlen = len;
5459             if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5460 
5461             acdi->dwFlags = 0;
5462             acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5463             acdi->ulAssemblyCount = actctx->num_assemblies;
5464             acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5465             acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
5466             acdi->ulRootConfigurationPathType = actctx->config.type;
5467             acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
5468             acdi->ulAppDirPathType = actctx->appdir.type;
5469             acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
5470             ptr = (LPWSTR)(acdi + 1);
5471             if (manifest_len)
5472             {
5473                 acdi->lpRootManifestPath = ptr;
5474                 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5475                 ptr += manifest_len;
5476             }
5477             else acdi->lpRootManifestPath = NULL;
5478             if (config_len)
5479             {
5480                 acdi->lpRootConfigurationPath = ptr;
5481                 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5482                 ptr += config_len;
5483             }
5484             else acdi->lpRootConfigurationPath = NULL;
5485             if (appdir_len)
5486             {
5487                 acdi->lpAppDirPath = ptr;
5488                 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5489             }
5490             else acdi->lpAppDirPath = NULL;
5491         }
5492         break;
5493 
5494     case AssemblyDetailedInformationInActivationContext:
5495         {
5496             ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5497             struct assembly *assembly;
5498             WCHAR *assembly_id;
5499             DWORD index;
5500             SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5501             LPWSTR ptr;
5502 
5503             if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5504             if (!subinst) return STATUS_INVALID_PARAMETER;
5505 
5506             index = *(DWORD*)subinst;
5507             if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5508 
5509             assembly = &actctx->assemblies[index - 1];
5510 
5511             if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5512             id_len = strlenW(assembly_id) + 1;
5513             if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5514 
5515             if (assembly->manifest.info &&
5516                 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5517                 path_len  = strlenW(assembly->manifest.info) + 1;
5518 
5519             len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5520 
5521             if (retlen) *retlen = len;
5522             if (!buffer || bufsize < len)
5523             {
5524                 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5525                 return STATUS_BUFFER_TOO_SMALL;
5526             }
5527 
5528             afdi->ulFlags = 0;  /* FIXME */
5529             afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
5530             afdi->ulManifestPathType = assembly->manifest.type;
5531             afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
5532             /* FIXME afdi->liManifestLastWriteTime = 0; */
5533             afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5534             afdi->ulPolicyPathLength = 0;
5535             /* FIXME afdi->liPolicyLastWriteTime = 0; */
5536             afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5537             afdi->ulManifestVersionMajor = 1;
5538             afdi->ulManifestVersionMinor = 0;
5539             afdi->ulPolicyVersionMajor = 0; /* FIXME */
5540             afdi->ulPolicyVersionMinor = 0; /* FIXME */
5541             afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
5542             ptr = (LPWSTR)(afdi + 1);
5543             afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5544             memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5545             ptr += id_len;
5546             if (path_len)
5547             {
5548                 afdi->lpAssemblyManifestPath = ptr;
5549                 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5550                 ptr += path_len;
5551             } else afdi->lpAssemblyManifestPath = NULL;
5552             afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5553             if (ad_len)
5554             {
5555                 afdi->lpAssemblyDirectoryName = ptr;
5556                 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5557             }
5558             else afdi->lpAssemblyDirectoryName = NULL;
5559             RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5560         }
5561         break;
5562 
5563     case FileInformationInAssemblyOfAssemblyInActivationContext:
5564         {
5565             const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5566             ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5567             struct assembly *assembly;
5568             struct dll_redirect *dll;
5569             SIZE_T len, dll_len = 0;
5570             LPWSTR ptr;
5571 
5572             if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5573             if (!acqi) return STATUS_INVALID_PARAMETER;
5574 
5575             if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5576                 return STATUS_INVALID_PARAMETER;
5577             assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5578 
5579             if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5580                 return STATUS_INVALID_PARAMETER;
5581             dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5582 
5583             if (dll->name) dll_len = strlenW(dll->name) + 1;
5584             len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5585 
5586             if (!buffer || bufsize < len)
5587             {
5588                 if (retlen) *retlen = len;
5589                 return STATUS_BUFFER_TOO_SMALL;
5590             }
5591             if (retlen) *retlen = 0; /* yes that's what native does !! */
5592             afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5593             afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
5594             afdi->ulPathLength = 0; /* FIXME */
5595             ptr = (LPWSTR)(afdi + 1);
5596             if (dll_len)
5597             {
5598                 afdi->lpFileName = ptr;
5599                 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5600             } else afdi->lpFileName = NULL;
5601             afdi->lpFilePath = NULL; /* FIXME */
5602         }
5603         break;
5604 
5605     case CompatibilityInformationInActivationContext:
5606         {
5607             /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5608             COMPATIBILITY_CONTEXT_ELEMENT *elements;
5609             struct assembly *assembly = NULL;
5610             ULONG num_compat_contexts = 0, n;
5611             SIZE_T len;
5612 
5613             if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5614 
5615             if (actctx->num_assemblies) assembly = actctx->assemblies;
5616 
5617             if (assembly)
5618                 num_compat_contexts = assembly->num_compat_contexts;
5619             len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5620 
5621             if (retlen) *retlen = len;
5622             if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5623 
5624             *acci = num_compat_contexts;
5625             elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5626             for (n = 0; n < num_compat_contexts; ++n)
5627             {
5628                 elements[n] = assembly->compat_contexts[n];
5629             }
5630         }
5631         break;
5632 
5633     case RunlevelInformationInActivationContext:
5634         {
5635             ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5636             struct assembly *assembly;
5637             SIZE_T len;
5638 
5639             if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5640 
5641             len = sizeof(*acrli);
5642             if (retlen) *retlen = len;
5643             if (!buffer || bufsize < len)
5644                 return STATUS_BUFFER_TOO_SMALL;
5645 
5646             assembly = actctx->assemblies;
5647 
5648             acrli->ulFlags  = 0;
5649             acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5650             acrli->UiAccess = assembly ? assembly->ui_access : 0;
5651         }
5652         break;
5653 
5654     default:
5655         DPRINT( "class %u not implemented\n", class );
5656         return STATUS_NOT_IMPLEMENTED;
5657     }
5658     return STATUS_SUCCESS;
5659 }
5660 
5661 NTSTATUS
5662 NTAPI
5663 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
5664                                            PVOID pvBuffer,
5665                                            SIZE_T cbBuffer OPTIONAL,
5666                                            SIZE_T *pcbWrittenOrRequired OPTIONAL)
5667 {
5668     return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT,
5669                                                 NULL,
5670                                                 NULL,
5671                                                 ulInfoClass,
5672                                                 pvBuffer,
5673                                                 cbBuffer,
5674                                                 pcbWrittenOrRequired);
5675 }
5676 
5677 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5678 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5679 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5680 
5681 NTSTATUS
5682 NTAPI
5683 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
5684                                                   const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
5685 {
5686     /* Check general parameter combinations */
5687     if (!section_name ||  !section_name->Buffer ||
5688         (flags & ~FIND_ACTCTX_VALID_MASK) ||
5689         ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
5690         (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
5691     {
5692         DPRINT1("invalid parameter\n");
5693         return STATUS_INVALID_PARAMETER;
5694     }
5695 
5696     /* TODO */
5697     if (flags & FIND_ACTCTX_RETURN_FLAGS ||
5698         flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5699     {
5700         DPRINT1("unknown flags %08x\n", flags);
5701         return STATUS_INVALID_PARAMETER;
5702     }
5703 
5704     return STATUS_SUCCESS;
5705 }
5706 
5707 /***********************************************************************
5708  *		RtlFindActivationContextSectionString (NTDLL.@)
5709  *
5710  * Find information about a string in an activation context.
5711  * FIXME: function signature/prototype may be wrong
5712  */
5713 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5714                                                       const UNICODE_STRING *section_name, PVOID ptr )
5715 {
5716     PACTCTX_SECTION_KEYED_DATA data = ptr;
5717     NTSTATUS status;
5718 
5719     DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr);
5720     status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
5721     if (!NT_SUCCESS(status))
5722     {
5723         DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status);
5724         return status;
5725     }
5726 
5727     status = STATUS_SXS_KEY_NOT_FOUND;
5728 
5729     /* if there is no data, but params are valid,
5730        we return that sxs key is not found to be at least somehow compatible */
5731     if (!data)
5732     {
5733         DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status);
5734         return status;
5735     }
5736 
5737     ASSERT(NtCurrentTeb());
5738     ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
5739 
5740     DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame);
5741     if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5742     {
5743         ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5744         if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5745     }
5746 
5747     DPRINT("status %x\n", status);
5748     if (status != STATUS_SUCCESS)
5749         status = find_string( process_actctx, section_kind, section_name, flags, data );
5750 
5751     if (status != STATUS_SUCCESS)
5752         status = find_string( implicit_actctx, section_kind, section_name, flags, data );
5753 
5754     DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status);
5755     return status;
5756 }
5757 
5758 /***********************************************************************
5759  *		RtlFindActivationContextSectionGuid (NTDLL.@)
5760  *
5761  * Find information about a GUID in an activation context.
5762  * FIXME: function signature/prototype may be wrong
5763  */
5764 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5765                                                      const GUID *guid, void *ptr )
5766 {
5767     ACTCTX_SECTION_KEYED_DATA *data = ptr;
5768     NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5769 
5770     if (extguid)
5771     {
5772         DPRINT1("expected extguid == NULL\n");
5773         return STATUS_INVALID_PARAMETER;
5774     }
5775 
5776     if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5777     {
5778         DPRINT1("unknown flags %08x\n", flags);
5779         return STATUS_INVALID_PARAMETER;
5780     }
5781 
5782     if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5783         return STATUS_INVALID_PARAMETER;
5784 
5785     if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5786     {
5787         ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5788         if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5789     }
5790 
5791     if (status != STATUS_SUCCESS)
5792         status = find_guid( process_actctx, section_kind, guid, flags, data );
5793 
5794     if (status != STATUS_SUCCESS)
5795         status = find_guid( implicit_actctx, section_kind, guid, flags, data );
5796 
5797     return status;
5798 }
5799 
5800 /* Stubs */
5801 
5802 NTSTATUS
5803 NTAPI
5804 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
5805 {
5806     PACTIVATION_CONTEXT_STACK ContextStack;
5807 
5808     /* Check if it's already allocated */
5809     if (*Stack) return STATUS_SUCCESS;
5810 
5811     /* Allocate space for the context stack */
5812     ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK));
5813     if (!ContextStack)
5814     {
5815         return STATUS_NO_MEMORY;
5816     }
5817 
5818     /* Initialize the context stack */
5819     ContextStack->Flags = 0;
5820     ContextStack->ActiveFrame = NULL;
5821     InitializeListHead(&ContextStack->FrameListCache);
5822     ContextStack->NextCookieSequenceNumber = 1;
5823     ContextStack->StackId = 1; //TODO: Timer-based
5824 
5825     *Stack = ContextStack;
5826 
5827     return STATUS_SUCCESS;
5828 }
5829 
5830 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5831 FASTCALL
5832 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
5833                                        IN PVOID Context)
5834 {
5835     RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame;
5836     RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
5837 
5838     /* Get the current active frame */
5839     ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5840 
5841     DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5842         NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame,
5843         &Frame->Frame, Context);
5844 
5845     /* Ensure it's in the right format and at least fits basic info */
5846     ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5847     ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5848 
5849     /* Set debug info if size allows*/
5850     if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5851     {
5852         Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame);
5853         Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context);
5854         //Frame->Extra3 = ...;
5855     }
5856 
5857     if (ActiveFrame)
5858     {
5859         /*ASSERT((ActiveFrame->Flags &
5860             (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5861              RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5862              RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5863 
5864         if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED))
5865         {
5866             // TODO: Perform some additional checks if it was not heap allocated
5867         }
5868     }
5869 
5870     /* Save pointer to the new activation frame */
5871     NewFrame = &Frame->Frame;
5872 
5873     /* Actually activate it */
5874     Frame->Frame.Previous = ActiveFrame;
5875     Frame->Frame.ActivationContext = Context;
5876     Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED;
5877 
5878     /* Check if we can activate this context */
5879     if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
5880         Context)
5881     {
5882         /* Set new active frame */
5883         DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame);
5884         NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5885         return NewFrame;
5886     }
5887 
5888     /* We can get here only one way: it was already activated */
5889     DPRINT("Trying to activate already activated activation context\n");
5890 
5891     /* Activate only if we are allowing multiple activation */
5892 #if 0
5893     if (!RtlpNotAllowingMultipleActivation)
5894     {
5895         Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED;
5896         NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5897     }
5898 #else
5899     // Activate it anyway
5900     NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5901 #endif
5902 
5903     /* Return pointer to the activation frame */
5904     return NewFrame;
5905 }
5906 
5907 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5908 FASTCALL
5909 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
5910 {
5911     PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame;
5912 
5913     ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5914 
5915     /* Ensure it's in the right format and at least fits basic info */
5916     ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5917     ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5918 
5919     /* Make sure it is not deactivated and it is activated */
5920     ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0);
5921     ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
5922     ASSERT((Frame->Frame.Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
5923 
5924     /* Check debug info if it is present */
5925     if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5926     {
5927         ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous));
5928         ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext));
5929         //Frame->Extra3 = ...;
5930     }
5931 
5932     if (ActiveFrame)
5933     {
5934         // TODO: Perform some additional checks here
5935     }
5936 
5937     /* Special handling for not-really-activated */
5938     if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)
5939     {
5940         DPRINT1("Deactivating not really activated activation context\n");
5941         Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5942         return &Frame->Frame;
5943     }
5944 
5945     /* find the right frame */
5946     NewFrame = &Frame->Frame;
5947     if (ActiveFrame != NewFrame)
5948     {
5949         DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame);
5950     }
5951 
5952     DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5953         NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous);
5954 
5955     /* Pop everything up to and including frame */
5956     NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous;
5957 
5958     Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5959     return NewFrame->Previous;
5960 }
5961