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