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