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