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