ReactOS  0.4.15-dev-1187-g119f102
actctx.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Runtime Library
4  * PURPOSE: Activation Context Support
5  * FILE: lib/rtl/actctx.c
6  * PROGRAMERS:
7  * Jon Griffiths
8  * Eric Pouech
9  * Jacek Caban for CodeWeavers
10  * Alexandre Julliard
11  * Stefan Ginsberg (stefan.ginsberg@reactos.org)
12  * Samuel SerapiĆ³n
13  */
14 
15 /* Based on Wine 3.2-37c98396 */
16 
17 #include <rtl.h>
18 #include <ntstrsafe.h>
19 #include <compat_undoc.h>
20 
21 #define NDEBUG
22 #include <debug.h>
23 
24 #include <wine/unicode.h>
25 
27 
28 #define ACTCTX_FLAGS_ALL (\
29  ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
30  ACTCTX_FLAG_LANGID_VALID |\
31  ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
32  ACTCTX_FLAG_RESOURCE_NAME_VALID |\
33  ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
34  ACTCTX_FLAG_APPLICATION_NAME_VALID |\
35  ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
36  ACTCTX_FLAG_HMODULE_VALID )
37 
38 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
39 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
40 
41 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
42 
43 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
44 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
45 
46 #define MAX_NAMESPACES 64
47 
48 typedef struct
49 {
50  const WCHAR *ptr;
51  unsigned int len;
52 } xmlstr_t;
53 
54 struct xml_elem
55 {
58  int ns_pos;
59 };
60 
61 struct xml_attr
62 {
65 };
66 
67 typedef struct
68 {
69  const WCHAR *ptr;
70  const WCHAR *end;
71  struct xml_attr namespaces[MAX_NAMESPACES];
72  int ns_pos;
74 } xmlbuf_t;
75 
76 struct file_info
77 {
80 };
81 
83 {
88 };
89 
91 {
100 };
101 
102 struct strsection_header
103 {
104  DWORD magic;
105  ULONG size;
106  DWORD unk1[3];
107  ULONG count;
109  DWORD unk2[2];
112 };
113 
114 struct string_index
115 {
116  ULONG hash; /* key string hash */
118  ULONG name_len;
119  ULONG data_offset; /* redirect data offset */
120  ULONG data_len;
122 };
123 
124 struct guidsection_header
125 {
126  DWORD magic;
127  ULONG size;
128  DWORD unk[3];
129  ULONG count;
131  DWORD unk2;
134 };
135 
136 struct guid_index
137 {
138  GUID guid;
140  ULONG data_len;
142 };
143 
145 {
146  ULONG size;
147  DWORD res;
148  ULONG name_len;
149  ULONG name_offset; /* versioned name offset */
151  ULONG module_offset;/* container name offset */
152 };
153 
154 struct dllredirect_data
155 {
156  ULONG size;
157  ULONG unk;
158  DWORD res[3];
159 };
160 
161 struct tlibredirect_data
162 {
163  ULONG size;
164  DWORD res;
165  ULONG name_len;
167  LANGID langid;
168  WORD flags;
169  ULONG help_len;
173 };
174 
176 {
182 };
183 
185 {
191 };
192 
194 {
195  ULONG size;
196  BYTE res;
197  BYTE miscmask;
198  BYTE res1[2];
199  DWORD model;
200  GUID clsid;
201  GUID alias;
202  GUID clsid2;
203  GUID tlbid;
204  ULONG name_len;
215 };
216 
218 {
221 };
222 
224 {
225  ULONG size;
226  DWORD mask;
227  GUID iid;
229  GUID tlbid;
230  GUID base;
231  ULONG name_len;
233 };
234 
235 struct clrsurrogate_data
236 {
237  ULONG size;
238  DWORD res;
239  GUID clsid;
243  ULONG name_len;
244 };
245 
246 struct clrclass_data
247 {
248  ULONG size;
249  DWORD res[2];
252  ULONG name_len;
256  DWORD res2[2];
257 };
258 
259 struct progidredirect_data
260 {
261  ULONG size;
262  DWORD reserved;
264 };
265 
266 /*
267 
268  Sections structure.
269 
270  Sections are accessible by string or guid key, that defines two types of sections.
271  All sections of each type have same magic value and header structure, index
272  data could be of two possible types too. So every string based section uses
273  the same index format, same applies to guid sections - they share same guid index
274  format.
275 
276  - window class redirection section is a plain buffer with following format:
277 
278  <section header>
279  <index[]>
280  <data[]> --- <original name>
281  <redirect data>
282  <versioned name>
283  <module name>
284 
285  Header is fixed length structure - struct strsection_header,
286  contains redirected classes count;
287 
288  Index is an array of fixed length index records, each record is
289  struct string_index.
290 
291  All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
292 
293  Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
294  others are relative to section itself.
295 
296  - dll redirect section format:
297 
298  <section header>
299  <index[]>
300  <data[]> --- <dll name>
301  <data>
302 
303  This section doesn't seem to carry any payload data except dll names.
304 
305  - typelib section format:
306 
307  <section header>
308  <module names[]>
309  <index[]>
310  <data[]> --- <data>
311  <helpstring>
312 
313  Header is fixed length, index is an array of fixed length 'struct guid_index'.
314  All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
315  4-bytes aligned as a whole.
316 
317  Module name offsets are relative to section, helpstring offset is relative to data
318  structure itself.
319 
320  - comclass section format:
321 
322  <section header>
323  <module names[]>
324  <index[]>
325  <data[]> --- <data> --- <data>
326  <progid> <clrdata>
327  <name>
328  <version>
329  <progid>
330 
331  This section uses two index records per comclass, one entry contains original guid
332  as specified by context, another one has a generated guid. Index and strings handling
333  is similar to typelib sections.
334 
335  For CLR classes additional data is stored after main COM class data, it contains
336  class name and runtime version string, see 'struct clrclass_data'.
337 
338  Module name offsets are relative to section, progid offset is relative to data
339  structure itself.
340 
341  - COM interface section format:
342 
343  <section header>
344  <index[]>
345  <data[]> --- <data>
346  <name>
347 
348  Interface section contains data for proxy/stubs and external proxy/stubs. External
349  ones are defined at assembly level, so this section has no module information.
350  All records are indexed with 'iid' value from manifest. There an exception for
351  external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
352  redirect data, but index is still 'iid' from manifest.
353 
354  Interface name offset is relative to data structure itself.
355 
356  - CLR surrogates section format:
357 
358  <section header>
359  <index[]>
360  <data[]> --- <data>
361  <name>
362  <version>
363 
364  There's nothing special about this section, same way to store strings is used,
365  no modules part as it belongs to assembly level, not a file.
366 
367  - ProgID section format:
368 
369  <section header>
370  <guids[]>
371  <index[]>
372  <data[]> --- <progid>
373  <data>
374 
375  This sections uses generated alias guids from COM server section. This way
376  ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
377  is stored too, aligned.
378 */
379 
380 struct progids
381 {
383  unsigned int num;
384  unsigned int allocated;
385 };
386 
387 struct entity
388 {
390  union
391  {
392  struct
393  {
399  } typelib;
400  struct
401  {
403  WCHAR *tlbid;
405  WCHAR *name; /* clrClass: class name */
406  WCHAR *version; /* clrClass: CLR runtime version */
413  struct progids progids;
414  } comclass;
415  struct {
419  WCHAR *name;
420  WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
423  } ifaceps;
424  struct
425  {
426  WCHAR *name;
428  } class;
429  struct
430  {
431  WCHAR *name;
432  WCHAR *clsid;
433  WCHAR *version;
434  } clrsurrogate;
435  struct
436  {
437  WCHAR *name;
440  } settings;
441  } u;
442 };
443 
445 {
446  struct entity *base;
447  unsigned int num;
448  unsigned int allocated;
449 };
450 
452 {
456 };
457 
459 {
463 };
464 
465 struct assembly
466 {
473  unsigned int num_dlls;
474  unsigned int allocated_dlls;
476  COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
478  ACTCTX_REQUESTED_RUN_LEVEL run_level;
480 };
481 
483 {
491 };
492 
494 {
499 
500 typedef struct _ASSEMBLY_STORAGE_MAP
501 {
506 
507 typedef struct _ACTIVATION_CONTEXT
508 {
512  PACTIVATION_CONTEXT_DATA ActivationContextData;
524  unsigned int num_assemblies;
525  unsigned int allocated_assemblies;
526  /* section data */
536 
538 {
541  unsigned int num_dependencies;
543 };
544 
545 static const xmlstr_t empty_xmlstr;
546 
547 #ifdef __i386__
548 static const WCHAR current_archW[] = {'x','8','6',0};
549 #elif defined __x86_64__
550 static const WCHAR current_archW[] = {'a','m','d','6','4',0};
551 #elif defined __arm__
552 static const WCHAR current_archW[] = {'a','r','m',0};
553 #elif defined __aarch64__
554 static const WCHAR current_archW[] = {'a','r','m','6','4',0};
555 #else
556 static const WCHAR current_archW[] = {'n','o','n','e',0};
557 #endif
558 
559 static const WCHAR asmv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
560 static const WCHAR asmv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
561 static const WCHAR asmv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
562 
564 {
568 
569 VOID
570 NTAPI
572  IN ULONG FailureCode)
573 {
574  EXCEPTION_RECORD ExceptionRecord;
575 
576  /* Fatal SxS exception header */
577  ExceptionRecord.ExceptionRecord = NULL;
578  ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
579  ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
580 
581  /* With SxS-specific information plus the context itself */
582  ExceptionRecord.ExceptionInformation[0] = 1;
583  ExceptionRecord.ExceptionInformation[1] = FailureCode;
584  ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
585  ExceptionRecord.NumberParameters = 3;
586 
587  /* Raise it */
588  RtlRaiseException(&ExceptionRecord);
589 }
590 
592 VOID
594 {
596 
597  /* Get the caller-opaque header */
598  pActual = CONTAINING_RECORD(ActCtx,
600  ActivationContext);
601 
602  /* Check if the header matches as expected */
603  if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
604  {
605  /* Nope, print out a warning, assert, and then throw an exception */
606  DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
607  " This means someone stepped on the allocation, or someone is using a\n"
608  " deallocated activation context\n",
609  __FUNCTION__,
610  pActual->MagicMarker,
611  ActCtx);
614  }
615 }
616 
617 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
618 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
619 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
620 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
621 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
622 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
623 static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
624 static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
625 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
626 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
627 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
628 static const WCHAR fileW[] = {'f','i','l','e',0};
629 static const WCHAR hashW[] = {'h','a','s','h',0};
630 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
631 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
632 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
633 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
634 
635 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
636 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
637 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
638 static const WCHAR iidW[] = {'i','i','d',0};
639 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
640 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
641 static const WCHAR g_nameW[] = {'n','a','m','e',0};
642 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
643 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
644 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
645 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
646 static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
647 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
648 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
649 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
650 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
651 static const WCHAR typeW[] = {'t','y','p','e',0};
652 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
653 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
654 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
655 static const WCHAR yesW[] = {'y','e','s',0};
656 static const WCHAR noW[] = {'n','o',0};
657 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
658 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
659 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
660 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
661 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
662 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
663 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
664 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
665 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
666 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
667 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
668 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
669 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
670 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
671 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
672 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
673 
674 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
675 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
676 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
677 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
678 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
679 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
680 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
681 static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
682 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
683 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
684 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
685 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
686 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
687 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
688 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
689 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
690 static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
691 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
692 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
693 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
694 static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
695 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
696 
697 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
698 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
699 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
700 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
701 static const WCHAR IdW[] = {'I','d',0};
702 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
703 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
704 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
705 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
706 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
707 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
708 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
709 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0};
710 static const WCHAR windowsSettings2005NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
711 static const WCHAR windowsSettings2011NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
712 static const WCHAR windowsSettings2016NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
713 static const WCHAR windowsSettings2017NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
714 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
715 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
716 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
717 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
718 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
719 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
720 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0};
721 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
722 
724 {
725  const WCHAR *name;
726  OLEMISC value;
727 };
728 
729 static const struct olemisc_entry olemisc_values[] =
730 {
731  { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
732  { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
733  { actslikelabelW, OLEMISC_ACTSLIKELABEL },
734  { alignableW, OLEMISC_ALIGNABLE },
735  { alwaysrunW, OLEMISC_ALWAYSRUN },
736  { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
737  { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
738  { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
739  { imemodeW, OLEMISC_IMEMODE },
740  { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
741  { insideoutW, OLEMISC_INSIDEOUT },
742  { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
743  { islinkobjectW, OLEMISC_ISLINKOBJECT },
744  { nouiactivateW, OLEMISC_NOUIACTIVATE },
745  { onlyiconicW, OLEMISC_ONLYICONIC },
746  { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
747  { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
748  { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
749  { simpleframeW, OLEMISC_SIMPLEFRAME },
750  { staticW, OLEMISC_STATIC },
751  { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
752  { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
753 };
754 
755 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
756 static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
757 static const WCHAR manifestv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
758 static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
759 
760 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
761 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
762 static const WCHAR wildcardW[] = {'*',0};
763 
767 
768 static WCHAR *strdupW(const WCHAR* str)
769 {
770  WCHAR* ptr;
771 
772  if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
773  return NULL;
774  return strcpyW(ptr, str);
775 }
776 
777 static WCHAR *xmlstrdupW(const xmlstr_t* str)
778 {
779  WCHAR *strW;
780 
781  if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
782  {
783  memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
784  strW[str->len] = 0;
785  }
786  return strW;
787 }
788 
789 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
790 {
791  return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
792 }
793 
794 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
795 {
796  return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
797 }
798 
799 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
800 {
801  return (xmlstr->len && xmlstr->ptr[0] == '/' &&
802  !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
803 }
804 
805 static inline BOOL xml_attr_cmp(const struct xml_attr* attr, const WCHAR *str)
806 {
807  return xmlstr_cmp(&attr->name, str);
808 }
809 
810 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
811 {
812  return (elem1->name.len == elem2->name.len &&
813  elem1->ns.len == elem2->ns.len &&
814  !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
815  !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
816 }
817 
818 static inline BOOL xml_elem_cmp(const struct xml_elem* elem, const WCHAR *str, const WCHAR *namespace)
819 {
820  if (!xmlstr_cmp( &elem->name, str )) return FALSE;
821  if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
822  if (!wcscmp( namespace, asmv1W ))
823  {
824  if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
825  if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
826  }
827  else if (!wcscmp( namespace, asmv2W ))
828  {
829  if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
830  }
831  return FALSE;
832 }
833 
834 static inline BOOL isxmlspace( WCHAR ch )
835 {
836  return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
837 }
838 
840 {
841  struct assembly *assembly;
842 
843  DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
844 
845  if (actctx->num_assemblies == actctx->allocated_assemblies)
846  {
847  void *ptr;
848  unsigned int new_count;
849  if (actctx->assemblies)
850  {
851  new_count = actctx->allocated_assemblies * 2;
852  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
853  actctx->assemblies, new_count * sizeof(*assembly) );
854  }
855  else
856  {
857  new_count = 4;
858  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
859  }
860  if (!ptr) return NULL;
861  actctx->assemblies = ptr;
862  actctx->allocated_assemblies = new_count;
863  }
864 
865  assembly = &actctx->assemblies[actctx->num_assemblies++];
866  assembly->type = at;
867  return assembly;
868 }
869 
871 {
872  DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
873 
875  {
876  void *ptr;
877  unsigned int new_count;
878  if (assembly->dlls)
879  {
880  new_count = assembly->allocated_dlls * 2;
881  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
882  assembly->dlls, new_count * sizeof(*assembly->dlls) );
883  }
884  else
885  {
886  new_count = 4;
887  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
888  }
889  if (!ptr) return NULL;
890  assembly->dlls = ptr;
891  assembly->allocated_dlls = new_count;
892  }
893  return &assembly->dlls[assembly->num_dlls++];
894 }
895 
896 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
897 {
898  void *ptr;
900  {
901  unsigned int new_count = assembly->num_compat_contexts + 1;
902  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
904  new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
905  }
906  else
907  {
908  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
909  }
910  if (!ptr) return NULL;
913 }
914 
916 {
917  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
918  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
919  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
920  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
921  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
922 }
923 
924 static struct entity* add_entity(struct entity_array *array, DWORD kind)
925 {
926  struct entity* entity;
927 
928  if (array->num == array->allocated)
929  {
930  void *ptr;
931  unsigned int new_count;
932  if (array->base)
933  {
934  new_count = array->allocated * 2;
935  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
936  array->base, new_count * sizeof(*array->base) );
937  }
938  else
939  {
940  new_count = 4;
941  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
942  }
943  if (!ptr) return NULL;
944  array->base = ptr;
945  array->allocated = new_count;
946  }
947  entity = &array->base[array->num++];
948  entity->kind = kind;
949  return entity;
950 }
951 
953 {
954  unsigned int i, j;
955  for (i = 0; i < array->num; i++)
956  {
957  struct entity *entity = &array->base[i];
958  switch (entity->kind)
959  {
960  case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
961  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
962  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
963  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
964  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
965  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
966  for (j = 0; j < entity->u.comclass.progids.num; j++)
967  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
968  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
969  break;
970  case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
971  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
972  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
973  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
974  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
975  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
976  break;
977  case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
978  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
979  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
980  break;
981  case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
982  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
983  break;
984  case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
985  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
986  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
987  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
988  break;
989  default:
990  DPRINT1("Unknown entity kind %u\n", entity->kind);
991  }
992  }
993  RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
994 }
995 
996 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
997 {
998  if (!str1) return !str2;
999  return str2 && !strcmpiW( str1, str2 );
1000 }
1001 
1002 static BOOL is_matching_identity( const struct assembly_identity *id1,
1003  const struct assembly_identity *id2 )
1004 {
1005  if (!is_matching_string( id1->name, id2->name )) return FALSE;
1006  if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1007  if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1008 
1009  if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
1010  {
1011  if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
1012  return FALSE;
1013  }
1014  if (id1->version.major != id2->version.major) return FALSE;
1015  if (id1->version.minor != id2->version.minor) return FALSE;
1016  if (id1->version.build > id2->version.build) return FALSE;
1017  if (id1->version.build == id2->version.build &&
1018  id1->version.revision > id2->version.revision) return FALSE;
1019  return TRUE;
1020 }
1021 
1023  struct assembly_identity* ai)
1024 {
1025  unsigned int i;
1026 
1027  /* check if we already have that assembly */
1028 
1029  for (i = 0; i < acl->actctx->num_assemblies; i++)
1030  if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1031  {
1032  DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
1033  ai->name, ai->arch, ai->version.major, ai->version.minor,
1034  ai->version.build, ai->version.revision );
1035  return TRUE;
1036  }
1037 
1038  for (i = 0; i < acl->num_dependencies; i++)
1039  if (is_matching_identity( ai, &acl->dependencies[i] ))
1040  {
1041  DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
1042  ai->name, ai->arch, ai->version.major, ai->version.minor,
1043  ai->version.build, ai->version.revision );
1044  return TRUE;
1045  }
1046 
1047  if (acl->num_dependencies == acl->allocated_dependencies)
1048  {
1049  void *ptr;
1050  unsigned int new_count;
1051  if (acl->dependencies)
1052  {
1053  new_count = acl->allocated_dependencies * 2;
1054  ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
1055  new_count * sizeof(acl->dependencies[0]));
1056  }
1057  else
1058  {
1059  new_count = 4;
1060  ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1061  }
1062  if (!ptr) return FALSE;
1063  acl->dependencies = ptr;
1064  acl->allocated_dependencies = new_count;
1065  }
1066  acl->dependencies[acl->num_dependencies++] = *ai;
1067 
1068  return TRUE;
1069 }
1070 
1071 static void free_depend_manifests(struct actctx_loader* acl)
1072 {
1073  unsigned int i;
1074  for (i = 0; i < acl->num_dependencies; i++)
1076  RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
1077 }
1078 
1080 {
1081  static const WCHAR undW[] = {'_',0};
1082  static const WCHAR noneW[] = {'n','o','n','e',0};
1083  static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1084 
1085  const WCHAR *arch = ai->arch ? ai->arch : noneW;
1086  const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1087  const WCHAR *lang = ai->language ? ai->language : noneW;
1088  const WCHAR *name = ai->name ? ai->name : noneW;
1089  SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1090  strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1091  WCHAR *ret;
1092 
1093  if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1094 
1095  strcpyW( ret, arch );
1096  strcatW( ret, undW );
1097  strcatW( ret, name );
1098  strcatW( ret, undW );
1099  strcatW( ret, key );
1100  strcatW( ret, undW );
1102  ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1103  strcatW( ret, undW );
1104  strcatW( ret, lang );
1105  strcatW( ret, undW );
1106  strcatW( ret, mskeyW );
1107  return ret;
1108 }
1109 
1110 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1111 {
1112  WCHAR *p = buffer;
1113 
1114  if (!str) return;
1115  strcatW( buffer, prefix );
1116  p += strlenW(p);
1117  *p++ = '"';
1118  strcpyW( p, str );
1119  p += strlenW(p);
1120  *p++ = '"';
1121  *p = 0;
1122 }
1123 
1124 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1125 {
1126  static const WCHAR archW[] =
1127  {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1128  static const WCHAR public_keyW[] =
1129  {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1130  static const WCHAR typeW2[] =
1131  {',','t','y','p','e','=',0};
1132  static const WCHAR versionW2[] =
1133  {',','v','e','r','s','i','o','n','=',0};
1134 
1135  WCHAR version[64], *ret;
1136  SIZE_T size = 0;
1137 
1139  ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1140  if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1141  if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1142  if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1143  if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1144  size += strlenW(versionW2) + strlenW(version) + 2;
1145 
1146  if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1147  return NULL;
1148 
1149  if (ai->name) strcpyW( ret, ai->name );
1150  else *ret = 0;
1151  append_string( ret, archW, ai->arch );
1152  append_string( ret, public_keyW, ai->public_key );
1153  append_string( ret, typeW2, ai->type );
1154  append_string( ret, versionW2, version );
1155  return ret;
1156 }
1157 
1159 {
1162 
1163  if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1164  _SEH2_TRY
1165  {
1166  if (actctx)
1167  {
1168  pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1169  if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1170  }
1171  }
1173  {
1174  DPRINT1("Invalid activation context handle!\n");
1175  }
1176  _SEH2_END;
1177  return ret;
1178 }
1179 
1181 {
1182  InterlockedExchangeAdd( &actctx->RefCount, 1 );
1183 }
1184 
1186 {
1188 
1189  if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1190  {
1191  unsigned int i, j;
1192 
1193  for (i = 0; i < actctx->num_assemblies; i++)
1194  {
1195  struct assembly *assembly = &actctx->assemblies[i];
1196  for (j = 0; j < assembly->num_dlls; j++)
1197  {
1198  struct dll_redirect *dll = &assembly->dlls[j];
1199  free_entity_array( &dll->entities );
1200  RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1201  RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1202  }
1203  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1204  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1205  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1206  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts );
1209  }
1210  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1211  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1212  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1213  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1214  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1215  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1216  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1217  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1218  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1219  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1220 
1221  pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1222  pActual->MagicMarker = 0;
1223  RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1224  }
1225 }
1226 
1227 static BOOL set_error(xmlbuf_t* xmlbuf)
1228 {
1229  xmlbuf->error = TRUE;
1230  return FALSE;
1231 }
1232 
1233 static BOOL is_xmlns_attr(const struct xml_attr *attr)
1234 {
1235  const int len = wcslen( xmlnsW );
1236  if (attr->name.len < len) return FALSE;
1237  if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1238  return (attr->name.len == len || attr->name.ptr[len] == ':');
1239 }
1240 
1241 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1242 {
1243  const int len = wcslen( xmlnsW );
1244  struct xml_attr *ns;
1245 
1246  if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1247  {
1248  // FIXME( "too many namespaces in manifest\n" );
1249  set_error( xmlbuf );
1250  return;
1251  }
1252  ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1253  ns->value = attr->value;
1254  if (attr->name.len > len)
1255  {
1256  ns->name.ptr = attr->name.ptr + len + 1;
1257  ns->name.len = attr->name.len - len - 1;
1258  }
1259  else ns->name = empty_xmlstr;
1260 }
1261 
1262 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1263 {
1264  int i;
1265 
1266  for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1267  {
1268  if (xmlbuf->namespaces[i].name.len == name->len &&
1269  !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1270  return xmlbuf->namespaces[i].value;
1271  }
1272 
1273  return empty_xmlstr;
1274 }
1275 
1276 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, struct xml_attr* attr, BOOL* end)
1277 {
1278  const WCHAR* ptr;
1279  WCHAR quote;
1280 
1281  if (xmlbuf->error) return FALSE;
1282 
1283  while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1284  xmlbuf->ptr++;
1285 
1286  if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1287 
1288  if (*xmlbuf->ptr == '/')
1289  {
1290  xmlbuf->ptr++;
1291  if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1292  return set_error( xmlbuf );
1293 
1294  xmlbuf->ptr++;
1295  *end = TRUE;
1296  return FALSE;
1297  }
1298 
1299  if (*xmlbuf->ptr == '>')
1300  {
1301  xmlbuf->ptr++;
1302  return FALSE;
1303  }
1304 
1305  ptr = xmlbuf->ptr;
1306  while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1307 
1308  if (ptr == xmlbuf->end) return set_error( xmlbuf );
1309 
1310  attr->name.ptr = xmlbuf->ptr;
1311  attr->name.len = ptr-xmlbuf->ptr;
1312  xmlbuf->ptr = ptr;
1313 
1314  /* skip spaces before '=' */
1315  while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1316  if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1317 
1318  /* skip '=' itself */
1319  ptr++;
1320  if (ptr == xmlbuf->end) return set_error( xmlbuf );
1321 
1322  /* skip spaces after '=' */
1323  while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1324 
1325  if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1326 
1327  quote = *ptr++;
1328  attr->value.ptr = ptr;
1329  if (ptr == xmlbuf->end) return set_error( xmlbuf );
1330 
1331  while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1332  if (ptr == xmlbuf->end)
1333  {
1334  xmlbuf->ptr = xmlbuf->end;
1335  return set_error( xmlbuf );
1336  }
1337 
1338  attr->value.len = ptr - attr->value.ptr;
1339  xmlbuf->ptr = ptr + 1;
1340  if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1341 
1342  return set_error( xmlbuf );
1343 }
1344 
1345 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1346 {
1347  const WCHAR* ptr = xmlbuf->ptr;
1348 
1349  elem->ns = empty_xmlstr;
1350  elem->name.ptr = ptr;
1351  while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1352  {
1353  if (*ptr == ':')
1354  {
1355  elem->ns.ptr = elem->name.ptr;
1356  elem->ns.len = ptr - elem->ns.ptr;
1357  elem->name.ptr = ptr + 1;
1358  }
1359  ptr++;
1360  }
1361  elem->name.len = ptr - elem->name.ptr;
1362  xmlbuf->ptr = ptr;
1363 }
1364 
1365 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1366 {
1367  const WCHAR* ptr;
1368  struct xml_attr attr;
1369  xmlbuf_t attr_buf;
1370  BOOL end = FALSE;
1371 
1372  xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1373 
1374  if (xmlbuf->error) return FALSE;
1375 
1376  for (;;)
1377  {
1378  for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1379  if (ptr == xmlbuf->end)
1380  {
1381  xmlbuf->ptr = xmlbuf->end;
1382  return set_error( xmlbuf );
1383  }
1384  ptr++;
1385  if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1386  {
1387  for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1388  if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1389 
1390  if (ptr + 3 > xmlbuf->end)
1391  {
1392  xmlbuf->ptr = xmlbuf->end;
1393  return set_error( xmlbuf );
1394  }
1395  xmlbuf->ptr = ptr + 3;
1396  }
1397  else break;
1398  }
1399 
1400  xmlbuf->ptr = ptr;
1401  /* check for element terminating the parent element */
1402  if (ptr < xmlbuf->end && *ptr == '/')
1403  {
1404  xmlbuf->ptr++;
1405  read_xml_elem( xmlbuf, elem );
1406  elem->ns = find_xmlns( xmlbuf, &elem->ns );
1407  if (!xml_name_cmp( elem, parent ))
1408  {
1409  /*ERR( "wrong closing element %s for %s\n",
1410  debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));*/
1411  return set_error( xmlbuf );
1412  }
1413  while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1414  if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1415  return FALSE;
1416  }
1417 
1418  read_xml_elem( xmlbuf, elem );
1419 
1420  /* parse namespace attributes */
1421  attr_buf = *xmlbuf;
1422  while (next_xml_attr( &attr_buf, &attr, &end ))
1423  {
1424  if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1425  }
1426  elem->ns = find_xmlns( xmlbuf, &elem->ns );
1427  elem->ns_pos = xmlbuf->ns_pos;
1428 
1429  if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1430 
1431  return set_error( xmlbuf );
1432 }
1433 
1435 {
1436  /* FIXME: parse attributes */
1437  const WCHAR *ptr;
1438 
1439  for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1440  {
1441  if (ptr[0] == '?' && ptr[1] == '>')
1442  {
1443  xmlbuf->ptr = ptr + 2;
1444  return TRUE;
1445  }
1446  }
1447  return FALSE;
1448 }
1449 
1451 {
1452  const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1453 
1454  if (!ptr) return FALSE;
1455 
1456  content->ptr = xmlbuf->ptr;
1457  content->len = ptr - xmlbuf->ptr;
1458  xmlbuf->ptr = ptr;
1459 
1460  return TRUE;
1461 }
1462 
1464 {
1465  unsigned int ver[4];
1466  unsigned int pos;
1467  const WCHAR *curr;
1468 
1469  /* major.minor.build.revision */
1470  ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1471  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1472  {
1473  if (*curr >= '0' && *curr <= '9')
1474  {
1475  ver[pos] = ver[pos] * 10 + *curr - '0';
1476  if (ver[pos] >= 0x10000) goto error;
1477  }
1478  else if (*curr == '.')
1479  {
1480  if (++pos >= 4) goto error;
1481  }
1482  else goto error;
1483  }
1484  version->major = ver[0];
1485  version->minor = ver[1];
1486  version->build = ver[2];
1487  version->revision = ver[3];
1488  return TRUE;
1489 
1490 error:
1491  return FALSE;
1492 }
1493 
1494 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1495 {
1496  struct xml_attr attr;
1497 
1498  while (next_xml_attr(xmlbuf, &attr, end))
1499  {
1500  // TODO: report error
1501  // if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1502  }
1503 }
1504 
1505 static void parse_expect_end_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1506 {
1507  struct xml_elem elem;
1508 
1509  if (next_xml_elem(xmlbuf, &elem, parent))
1510  {
1511  // FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1512  set_error( xmlbuf );
1513  }
1514 }
1515 
1516 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1517 {
1518  struct xml_elem elem;
1519  struct xml_attr attr;
1520  BOOL end = FALSE;
1521 
1522  while (next_xml_attr(xmlbuf, &attr, &end));
1523  if (end) return;
1524 
1525  while (next_xml_elem(xmlbuf, &elem, parent))
1526  parse_unknown_elem(xmlbuf, &elem);
1527 }
1528 
1530  struct assembly_identity* ai, const struct xml_elem *parent)
1531 {
1532  struct xml_attr attr;
1533  BOOL end = FALSE;
1534 
1535  while (next_xml_attr(xmlbuf, &attr, &end))
1536  {
1537  if (xml_attr_cmp(&attr, g_nameW))
1538  {
1539  if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1540  }
1541  else if (xml_attr_cmp(&attr, typeW))
1542  {
1543  if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1544  }
1545  else if (xml_attr_cmp(&attr, versionW))
1546  {
1547  if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1548  }
1550  {
1551  if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1552  }
1553  else if (xml_attr_cmp(&attr, publicKeyTokenW))
1554  {
1555  if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1556  }
1557  else if (xml_attr_cmp(&attr, languageW))
1558  {
1559  if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1560  }
1561  }
1562 
1563  if (!end) parse_expect_end_elem(xmlbuf, parent);
1564 }
1565 
1567 {
1568  static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1569  static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1570  static const WCHAR freeW[] = {'F','r','e','e',0};
1571  static const WCHAR bothW[] = {'B','o','t','h',0};
1572 
1573  if (value->len == 0) return ThreadingModel_No;
1574  if (xmlstr_cmp(value, apartW))
1575  return ThreadingModel_Apartment;
1576  else if (xmlstr_cmp(value, freeW))
1577  return ThreadingModel_Free;
1578  else if (xmlstr_cmp(value, bothW))
1579  return ThreadingModel_Both;
1580  else if (xmlstr_cmp(value, neutralW))
1581  return ThreadingModel_Neutral;
1582  else
1583  return ThreadingModel_No;
1584 };
1585 
1586 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1587 {
1588  int min, max;
1589 
1590  min = 0;
1591  max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1592 
1593  while (min <= max)
1594  {
1595  int n, c;
1596 
1597  n = (min+max)/2;
1598 
1600  if (!c && !olemisc_values[n].name[len])
1601  return olemisc_values[n].value;
1602 
1603  if (c >= 0)
1604  max = n-1;
1605  else
1606  min = n+1;
1607  }
1608 
1609  DPRINT1("unknown flag %S\n", str);
1610  return 0;
1611 }
1612 
1614 {
1615  const WCHAR *str = value->ptr, *start;
1616  DWORD flags = 0;
1617  int i = 0;
1618 
1619  /* it's comma separated list of flags */
1620  while (i < value->len)
1621  {
1622  start = str;
1623  while (*str != ',' && (i++ < value->len)) str++;
1624 
1626 
1627  /* skip separator */
1628  str++;
1629  i++;
1630  }
1631 
1632  return flags;
1633 }
1634 
1636 {
1637  struct progids *progids = &entity->u.comclass.progids;
1638 
1639  if (progids->allocated == 0)
1640  {
1641  progids->allocated = 4;
1642  if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1643  }
1644 
1645  if (progids->allocated == progids->num)
1646  {
1647  WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1648  2 * progids->allocated * sizeof(WCHAR*));
1649  if (!new_progids) return FALSE;
1650  progids->allocated *= 2;
1651  progids->progids = new_progids;
1652  }
1653 
1654  if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1655  progids->num++;
1656 
1657  return TRUE;
1658 }
1659 
1660 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1661 {
1662  xmlstr_t content;
1663  BOOL end = FALSE;
1664 
1665  parse_expect_no_attr(xmlbuf, &end);
1666  if (end) set_error( xmlbuf );
1667  if (!parse_text_content(xmlbuf, &content)) return;
1668 
1669  if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1670  parse_expect_end_elem(xmlbuf, parent);
1671 }
1672 
1673 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1674  const struct xml_elem *parent )
1675 {
1676  struct xml_elem elem;
1677  struct xml_attr attr;
1678  BOOL end = FALSE;
1679  struct entity* entity;
1680 
1681  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1682  {
1683  set_error( xmlbuf );
1684  return;
1685  }
1686 
1687  while (next_xml_attr(xmlbuf, &attr, &end))
1688  {
1689  if (xml_attr_cmp(&attr, clsidW))
1690  {
1691  if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1692  }
1693  else if (xml_attr_cmp(&attr, progidW))
1694  {
1695  if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1696  }
1697  else if (xml_attr_cmp(&attr, tlbidW))
1698  {
1699  if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1700  }
1701  else if (xml_attr_cmp(&attr, threadingmodelW))
1702  {
1704  }
1705  else if (xml_attr_cmp(&attr, miscstatusW))
1706  {
1707  entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1708  }
1709  else if (xml_attr_cmp(&attr, miscstatuscontentW))
1710  {
1711  entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1712  }
1714  {
1715  entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1716  }
1717  else if (xml_attr_cmp(&attr, miscstatusiconW))
1718  {
1719  entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1720  }
1722  {
1723  entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1724  }
1725  else if (xml_attr_cmp(&attr, descriptionW))
1726  {
1727  /* not stored */
1728  }
1729  }
1730 
1732  if (entity->u.comclass.progid)
1734 
1735  if (end) return;
1736 
1737  while (next_xml_elem(xmlbuf, &elem, parent))
1738  {
1739  if (xml_elem_cmp(&elem, progidW, asmv1W))
1740  {
1741  parse_com_class_progid(xmlbuf, entity, &elem);
1742  }
1743  else
1744  {
1745  parse_unknown_elem(xmlbuf, &elem);
1746  }
1747  }
1748 
1749  if (entity->u.comclass.progids.num)
1751 }
1752 
1754 {
1755  const WCHAR *curr;
1756  ULONG num = 0;
1757 
1758  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1759  {
1760  if (*curr >= '0' && *curr <= '9')
1761  num = num * 10 + *curr - '0';
1762  else
1763  {
1764  // DPRINT1("wrong numeric value %wZ\n", &strU);
1765  return FALSE;
1766  }
1767  }
1768  entity->u.ifaceps.nummethods = num;
1769 
1770  return TRUE;
1771 }
1772 
1774  struct actctx_loader *acl, WCHAR *clsid )
1775 {
1776  struct entity *entity;
1777  WCHAR *str;
1778 
1779  if (!clsid) return;
1780 
1781  if (!(str = strdupW(clsid)))
1782  {
1783  set_error( xmlbuf );
1784  return;
1785  }
1786 
1787  if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1788  {
1789  RtlFreeHeap(RtlGetProcessHeap(), 0, str);
1790  set_error( xmlbuf );
1791  return;
1792  }
1793 
1794  entity->u.comclass.clsid = str;
1796 
1798 }
1799 
1801  struct actctx_loader *acl, const struct xml_elem *parent )
1802 {
1803  WCHAR *psclsid = NULL;
1804  struct entity *entity;
1805  struct xml_attr attr;
1806  BOOL end = FALSE;
1807 
1808  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1809  {
1810  set_error( xmlbuf );
1811  return;
1812  }
1813 
1814  while (next_xml_attr(xmlbuf, &attr, &end))
1815  {
1816  if (xml_attr_cmp(&attr, iidW))
1817  {
1818  if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1819  }
1820  else if (xml_attr_cmp(&attr, g_nameW))
1821  {
1822  if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1823  }
1824  else if (xml_attr_cmp(&attr, baseInterfaceW))
1825  {
1826  if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1827  entity->u.ifaceps.mask |= BaseIface;
1828  }
1829  else if (xml_attr_cmp(&attr, nummethodsW))
1830  {
1831  if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1832  entity->u.ifaceps.mask |= NumMethods;
1833  }
1834  else if (xml_attr_cmp(&attr, tlbidW))
1835  {
1836  if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1837  }
1838  else if (xml_attr_cmp(&attr, proxyStubClsid32W))
1839  {
1840  if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1841  }
1842  /* not used */
1843  else if (xml_attr_cmp(&attr, threadingmodelW))
1844  {
1845  }
1846  }
1847 
1849  if (!end) parse_expect_end_elem(xmlbuf, parent);
1850 
1851  parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1852 
1853  RtlFreeHeap(RtlGetProcessHeap(), 0, psclsid);
1854 }
1855 
1857 {
1858  WORD *flags = &entity->u.typelib.flags;
1859  const WCHAR *str = value->ptr, *start;
1860  int i = 0;
1861 
1862  *flags = 0;
1863 
1864  /* it's comma separated list of flags */
1865  while (i < value->len)
1866  {
1867  start = str;
1868  while (*str != ',' && (i++ < value->len)) str++;
1869 
1871  *flags |= LIBFLAG_FRESTRICTED;
1872  else if (!strncmpiW(start, controlW, str-start))
1873  *flags |= LIBFLAG_FCONTROL;
1874  else if (!strncmpiW(start, hiddenW, str-start))
1875  *flags |= LIBFLAG_FHIDDEN;
1876  else if (!strncmpiW(start, hasdiskimageW, str-start))
1877  *flags |= LIBFLAG_FHASDISKIMAGE;
1878  else
1879  {
1880  // DPRINT1("unknown flags value %wZ\n", &valueU);
1881  return FALSE;
1882  }
1883 
1884  /* skip separator */
1885  str++;
1886  i++;
1887  }
1888 
1889  return TRUE;
1890 }
1891 
1893 {
1894  unsigned int ver[2];
1895  unsigned int pos;
1896  const WCHAR *curr;
1897 
1898  /* major.minor */
1899  ver[0] = ver[1] = pos = 0;
1900  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1901  {
1902  if (*curr >= '0' && *curr <= '9')
1903  {
1904  ver[pos] = ver[pos] * 10 + *curr - '0';
1905  if (ver[pos] >= 0x10000) goto error;
1906  }
1907  else if (*curr == '.')
1908  {
1909  if (++pos >= 2) goto error;
1910  }
1911  else goto error;
1912  }
1913  entity->u.typelib.major = ver[0];
1914  entity->u.typelib.minor = ver[1];
1915  return TRUE;
1916 
1917 error:
1918  return FALSE;
1919 }
1920 
1921 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1922  struct actctx_loader *acl, const struct xml_elem *parent )
1923 {
1924  struct xml_attr attr;
1925  BOOL end = FALSE;
1926  struct entity* entity;
1927 
1928  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1929  {
1930  set_error( xmlbuf );
1931  return;
1932  }
1933 
1934  while (next_xml_attr(xmlbuf, &attr, &end))
1935  {
1936  if (xml_attr_cmp(&attr, tlbidW))
1937  {
1938  if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1939  }
1940  else if (xml_attr_cmp(&attr, versionW))
1941  {
1942  if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1943  }
1944  else if (xml_attr_cmp(&attr, helpdirW))
1945  {
1946  if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1947  }
1948  else if (xml_attr_cmp(&attr, flagsW))
1949  {
1950  if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1951  }
1952  }
1953 
1955  if (!end) parse_expect_end_elem(xmlbuf, parent);
1956 }
1957 
1958 static inline int aligned_string_len(int len)
1959 {
1960  return (len + 3) & ~3;
1961 }
1962 
1964 {
1965  static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1966  struct assembly_version *ver = &assembly->id.version;
1967  WCHAR buff[25];
1968 
1969  if (!ret) ret = buff;
1970  return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1971 }
1972 
1973 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1974  struct actctx_loader *acl, const struct xml_elem *parent )
1975 {
1976  struct xml_elem elem;
1977  struct xml_attr attr;
1978  xmlstr_t content;
1979  BOOL end = FALSE;
1980  struct entity* entity;
1981 
1982  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1983  {
1984  set_error( xmlbuf );
1985  return;
1986  }
1987  entity->u.class.versioned = TRUE;
1988  while (next_xml_attr(xmlbuf, &attr, &end))
1989  {
1990  if (xml_attr_cmp(&attr, versionedW))
1991  {
1992  if (xmlstr_cmpi(&attr.value, noW))
1993  entity->u.class.versioned = FALSE;
1994  else if (!xmlstr_cmpi(&attr.value, yesW))
1995  set_error( xmlbuf );
1996  }
1997  }
1998 
1999  if (end) return;
2000 
2001  if (!parse_text_content(xmlbuf, &content)) return;
2002  if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
2003 
2005 
2006  while (next_xml_elem(xmlbuf, &elem, parent))
2007  {
2008  parse_unknown_elem(xmlbuf, &elem);
2009  }
2010 }
2011 
2012 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2013 {
2014  struct xml_attr attr;
2015  BOOL end = FALSE;
2016 
2017  while (next_xml_attr(xmlbuf, &attr, &end))
2018  {
2019  if (xml_attr_cmp(&attr, oldVersionW))
2020  {
2021  // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2022  }
2023  else if (xml_attr_cmp(&attr, newVersionW))
2024  {
2025  // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2026  }
2027  }
2028 
2029  if (!end) parse_expect_end_elem(xmlbuf, parent);
2030 }
2031 
2032 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2033 {
2034  struct xml_elem elem;
2035  struct xml_attr attr;
2036  xmlstr_t content;
2037  BOOL end = FALSE;
2038 
2039  while (next_xml_attr(xmlbuf, &attr, &end));
2040 
2041  if (end) return;
2042  if (!parse_text_content(xmlbuf, &content)) return;
2043 
2044  while (next_xml_elem(xmlbuf, &elem, parent))
2045  {
2046  parse_unknown_elem(xmlbuf, &elem);
2047  }
2048 }
2049 
2051  struct assembly* assembly,
2052  struct actctx_loader* acl,
2053  const struct xml_elem *parent)
2054 {
2055  struct xml_attr attr;
2056  BOOL end = FALSE;
2057  struct entity* entity;
2058 
2059  if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2060  {
2061  set_error( xmlbuf );
2062  return;
2063  }
2064 
2065  while (next_xml_attr(xmlbuf, &attr, &end))
2066  {
2067  if (xml_attr_cmp(&attr, iidW))
2068  {
2069  if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2070  }
2071  else if (xml_attr_cmp(&attr, g_nameW))
2072  {
2073  if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2074  }
2075  else if (xml_attr_cmp(&attr, baseInterfaceW))
2076  {
2077  if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2078  entity->u.ifaceps.mask |= BaseIface;
2079  }
2080  else if (xml_attr_cmp(&attr, nummethodsW))
2081  {
2082  if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2083  entity->u.ifaceps.mask |= NumMethods;
2084  }
2085  else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2086  {
2087  if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2088  }
2089  else if (xml_attr_cmp(&attr, tlbidW))
2090  {
2091  if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2092  }
2093  }
2094 
2096  if (!end) parse_expect_end_elem(xmlbuf, parent);
2097 }
2098 
2099 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2100  struct actctx_loader *acl, const struct xml_elem *parent )
2101 
2102 {
2103  struct xml_elem elem;
2104  struct xml_attr attr;
2105  BOOL end = FALSE;
2106  struct entity* entity;
2107 
2108  if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2109  {
2110  set_error( xmlbuf );
2111  return;
2112  }
2113 
2114  while (next_xml_attr(xmlbuf, &attr, &end))
2115  {
2116  if (xml_attr_cmp(&attr, g_nameW))
2117  {
2118  if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2119  }
2120  else if (xml_attr_cmp(&attr, clsidW))
2121  {
2122  if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2123  }
2124  else if (xml_attr_cmp(&attr, progidW))
2125  {
2126  if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2127  }
2128  else if (xml_attr_cmp(&attr, tlbidW))
2129  {
2130  if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2131  }
2132  else if (xml_attr_cmp(&attr, threadingmodelW))
2133  {
2135  }
2136  else if (xml_attr_cmp(&attr, runtimeVersionW))
2137  {
2138  if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2139  }
2140  }
2141 
2143  if (entity->u.comclass.progid)
2145  if (end) return;
2146 
2147  while (next_xml_elem(xmlbuf, &elem, parent))
2148  {
2149  if (xml_elem_cmp(&elem, progidW, asmv1W))
2150  {
2151  parse_com_class_progid(xmlbuf, entity, &elem);
2152  }
2153  else
2154  {
2155  parse_unknown_elem(xmlbuf, &elem);
2156  }
2157  }
2158 
2159  if (entity->u.comclass.progids.num)
2161 }
2162 
2163 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2164  struct actctx_loader *acl, const struct xml_elem *parent )
2165 {
2166  struct xml_attr attr;
2167  BOOL end = FALSE;
2168  struct entity* entity;
2169 
2170  if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2171  {
2172  set_error( xmlbuf );
2173  return;
2174  }
2175 
2176  while (next_xml_attr(xmlbuf, &attr, &end))
2177  {
2178  if (xml_attr_cmp(&attr, g_nameW))
2179  {
2180  if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2181  }
2182  else if (xml_attr_cmp(&attr, clsidW))
2183  {
2184  if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2185  }
2186  else if (xml_attr_cmp(&attr, runtimeVersionW))
2187  {
2188  if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2189  }
2190  }
2191 
2193  if (!end) parse_expect_end_elem(xmlbuf, parent);
2194 }
2195 
2196 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2197  const struct xml_elem *parent, BOOL optional )
2198 {
2199  struct xml_elem elem;
2200  struct xml_attr attr;
2201  struct assembly_identity ai;
2202  BOOL end = FALSE;
2203 
2204  memset(&ai, 0, sizeof(ai));
2205  ai.optional = optional;
2206 
2207  while (next_xml_attr(xmlbuf, &attr, &end))
2208  {
2209  static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2210  static const WCHAR trueW[] = {'t','r','u','e',0};
2211 
2212  if (xml_attr_cmp(&attr, allowDelayedBindingW))
2213  ai.delayed = xmlstr_cmp(&attr.value, trueW);
2214  }
2215 
2216  if (end) return;
2217 
2218  while (next_xml_elem(xmlbuf, &elem, parent))
2219  {
2221  {
2222  parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2223  /* store the newly found identity for later loading */
2224  if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2225  if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2226  }
2228  {
2230  }
2231  else
2232  {
2233  parse_unknown_elem(xmlbuf, &elem);
2234  }
2235  }
2236 }
2237 
2238 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2239  const struct xml_elem *parent )
2240 
2241 {
2242  struct xml_elem elem;
2243  struct xml_attr attr;
2244  BOOL end = FALSE, optional = FALSE;
2245 
2246  while (next_xml_attr(xmlbuf, &attr, &end))
2247  {
2248  if (xml_attr_cmp(&attr, optionalW))
2249  {
2251  }
2252  }
2253 
2254  while (next_xml_elem(xmlbuf, &elem, parent))
2255  {
2257  {
2259  }
2260  else
2261  {
2262  parse_unknown_elem(xmlbuf, &elem);
2263  }
2264  }
2265 }
2266 
2267 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2268 {
2269  BOOL end = FALSE;
2270 
2271  parse_expect_no_attr(xmlbuf, &end);
2272  if (!end) parse_expect_end_elem(xmlbuf, parent);
2273 }
2274 
2275 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2276 {
2277  BOOL end = FALSE;
2278 
2279  parse_expect_no_attr(xmlbuf, &end);
2280  if (!end) parse_expect_end_elem(xmlbuf, parent);
2281 }
2282 
2283 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2284  struct actctx_loader* acl, const struct xml_elem *parent )
2285 {
2286  struct xml_elem elem;
2287  struct xml_attr attr;
2288  BOOL end = FALSE;
2289  struct dll_redirect* dll;
2290 
2291  if (!(dll = add_dll_redirect(assembly)))
2292  {
2293  set_error( xmlbuf );
2294  return;
2295  }
2296 
2297  while (next_xml_attr(xmlbuf, &attr, &end))
2298  {
2299  if (xml_attr_cmp(&attr, g_nameW))
2300  {
2301  if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2302  }
2303  else if (xml_attr_cmp(&attr, hashW))
2304  {
2305  if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2306  }
2307  else if (xml_attr_cmp(&attr, hashalgW))
2308  {
2309  static const WCHAR sha1W[] = {'S','H','A','1',0};
2310  if (!xmlstr_cmpi(&attr.value, sha1W)) {
2311  //FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2312  }
2313  }
2314  }
2315 
2316  if (!dll->name) set_error( xmlbuf );
2317 
2319 
2320  if (end) return;
2321 
2322  while (next_xml_elem(xmlbuf, &elem, parent))
2323  {
2325  {
2326  parse_com_class_elem(xmlbuf, dll, acl, &elem);
2327  }
2329  {
2331  }
2332  else if (xml_elem_cmp(&elem, hashW, asmv2W))
2333  {
2334  parse_unknown_elem(xmlbuf, &elem);
2335  }
2336  else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2337  {
2338  parse_typelib_elem(xmlbuf, dll, acl, &elem);
2339  }
2340  else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2341  {
2342  parse_window_class_elem(xmlbuf, dll, acl, &elem);
2343  }
2344  else
2345  {
2346  parse_unknown_elem( xmlbuf, &elem );
2347  }
2348  }
2349 }
2350 
2351 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2352  struct actctx_loader *acl, const struct xml_elem *parent )
2353 {
2354  struct xml_attr attr;
2355  BOOL end = FALSE;
2356 
2357  while (next_xml_attr(xmlbuf, &attr, &end))
2358  {
2359  if (xml_attr_cmp(&attr, IdW))
2360  {
2361  COMPATIBILITY_CONTEXT_ELEMENT *compat;
2363  GUID compat_id;
2364 
2365  str.Buffer = (PWSTR)attr.value.ptr;
2366  str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2367  if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2368  {
2369  if (!(compat = add_compat_context(assembly)))
2370  {
2371  set_error( xmlbuf );
2372  return;
2373  }
2374  compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2375  compat->Id = compat_id;
2376  }
2377  }
2378  }
2379 
2380  if (!end) parse_expect_end_elem(xmlbuf, parent);
2381 }
2382 
2384  struct actctx_loader* acl, const struct xml_elem *parent)
2385 {
2386  struct xml_elem elem;
2387 
2388  while (next_xml_elem(xmlbuf, &elem, parent))
2389  {
2391  {
2392  parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2393  }
2394  else
2395  {
2396  parse_unknown_elem(xmlbuf, &elem);
2397  }
2398  }
2399 }
2400 
2402  struct actctx_loader* acl, const struct xml_elem *parent)
2403 {
2404  struct xml_elem elem;
2405 
2406  while (next_xml_elem(xmlbuf, &elem, parent))
2407  {
2409  {
2411  }
2412  else
2413  {
2414  parse_unknown_elem(xmlbuf, &elem);
2415  }
2416  }
2417 }
2418 
2419 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2420  struct xml_elem *parent )
2421 {
2422  struct xml_elem elem;
2423  struct xml_attr attr;
2424  xmlstr_t content;
2425  BOOL end = FALSE;
2426  struct entity *entity;
2427 
2428  while (next_xml_attr( xmlbuf, &attr, &end ))
2429  {
2430  }
2431 
2432  if (end) return;
2433 
2434  if (!parse_text_content( xmlbuf, &content )) return;
2435 
2436  entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2437  if (!entity)
2438  {
2439  set_error( xmlbuf );
2440  return;
2441  }
2442  entity->u.settings.name = xmlstrdupW( &parent->name );
2443  entity->u.settings.value = xmlstrdupW( &content );
2444  entity->u.settings.ns = xmlstrdupW( &parent->ns );
2445 
2446  while (next_xml_elem(xmlbuf, &elem, parent))
2447  {
2448  parse_unknown_elem( xmlbuf, &elem );
2449  }
2450 }
2451 
2453  struct actctx_loader *acl, const struct xml_elem *parent )
2454 {
2455  struct xml_elem elem;
2456 
2457  while (next_xml_elem( xmlbuf, &elem, parent ))
2458  {
2470  {
2471  parse_settings_elem( xmlbuf, assembly, acl, &elem );
2472  }
2473  else
2474  {
2475  parse_unknown_elem( xmlbuf, &elem );
2476  }
2477  }
2478 }
2479 
2480 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2481  struct actctx_loader *acl, const struct xml_elem *parent )
2482 {
2483  struct xml_elem elem;
2484 
2485  while (next_xml_elem( xmlbuf, &elem, parent ))
2486  {
2488  {
2489  parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2490  }
2491  else
2492  {
2493  parse_unknown_elem( xmlbuf, &elem );
2494  }
2495  }
2496 }
2497 
2499  struct actctx_loader *acl, const struct xml_elem *parent )
2500 {
2501  static const WCHAR levelW[] = {'l','e','v','e','l',0};
2502  static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2503  static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2504  static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2505  static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2506  static const WCHAR falseW[] = {'f','a','l','s','e',0};
2507  static const WCHAR trueW[] = {'t','r','u','e',0};
2508 
2509  struct xml_elem elem;
2510  struct xml_attr attr;
2511  BOOL end = FALSE;
2512 
2513  /* Multiple requestedExecutionLevel elements are not supported. */
2514  if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2515 
2516  while (next_xml_attr(xmlbuf, &attr, &end))
2517  {
2518  if (xml_attr_cmp(&attr, levelW))
2519  {
2520  if (xmlstr_cmpi(&attr.value, asInvokerW))
2521  assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2522  else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2523  assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2524  else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2525  assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2526  }
2527  else if (xml_attr_cmp(&attr, uiAccessW))
2528  {
2529  if (xmlstr_cmpi(&attr.value, falseW))
2531  else if (xmlstr_cmpi(&attr.value, trueW))
2532  assembly->ui_access = TRUE;
2533  }
2534  }
2535 
2536  if (end) return;
2537 
2538  while (next_xml_elem(xmlbuf, &elem, parent))
2539  {
2540  parse_unknown_elem(xmlbuf, &elem);
2541  }
2542 }
2543 
2545  struct actctx_loader *acl, const struct xml_elem *parent )
2546 {
2547  struct xml_elem elem;
2548 
2549  while (next_xml_elem(xmlbuf, &elem, parent))
2550  {
2552  {
2554  }
2555  else
2556  {
2557  parse_unknown_elem(xmlbuf, &elem);
2558  }
2559  }
2560 }
2561 
2562 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2563  struct actctx_loader *acl, const struct xml_elem *parent )
2564 {
2565  struct xml_elem elem;
2566 
2567  while (next_xml_elem(xmlbuf, &elem, parent))
2568  {
2570  {
2572  }
2573  else
2574  {
2575  parse_unknown_elem(xmlbuf, &elem);
2576  }
2577  }
2578 }
2579 
2580 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2581  struct actctx_loader *acl, const struct xml_elem *parent )
2582 {
2583  struct xml_elem elem;
2584 
2585  while (next_xml_elem(xmlbuf, &elem, parent))
2586  {
2588  {
2589  parse_security_elem(xmlbuf, assembly, acl, &elem);
2590  }
2591  else
2592  {
2593  parse_unknown_elem(xmlbuf, &elem);
2594  }
2595  }
2596 }
2597 
2598 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2599  struct actctx_loader* acl, const struct xml_elem *parent,
2600  struct assembly_identity* expected_ai)
2601 {
2602  struct xml_elem elem;
2603  struct xml_attr attr;
2604  BOOL end = FALSE, version = FALSE;
2605 
2606  while (next_xml_attr(xmlbuf, &attr, &end))
2607  {
2609  {
2610  static const WCHAR v10W[] = {'1','.','0',0};
2611  if (!xmlstr_cmp(&attr.value, v10W))
2612  {
2613  break;
2614  }
2615  version = TRUE;
2616  }
2617  }
2618 
2619  if (end || !version)
2620  {
2621  set_error( xmlbuf );
2622  return;
2623  }
2624 
2625  while (next_xml_elem(xmlbuf, &elem, parent))
2626  {
2628  {
2629  parse_noinherit_elem(xmlbuf, &elem);
2631  }
2632  else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2633  {
2634  parse_noinheritable_elem(xmlbuf, &elem);
2635  }
2636  else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2637  {
2638  parse_description_elem(xmlbuf, &elem);
2639  }
2641  {
2643  }
2644  else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2645  {
2646  parse_dependency_elem(xmlbuf, acl, &elem);
2647  }
2648  else if (xml_elem_cmp(&elem, fileW, asmv1W))
2649  {
2650  parse_file_elem(xmlbuf, assembly, acl, &elem);
2651  }
2652  else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2653  {
2654  parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2655  }
2656  else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2657  {
2658  parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2659  }
2660  else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2661  {
2662  parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2663  }
2665  {
2666  parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2667 
2668  if (!xmlbuf->error && expected_ai)
2669  {
2670  /* FIXME: more tests */
2671  if (assembly->type == ASSEMBLY_MANIFEST &&
2672  memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2673  {
2674  set_error( xmlbuf );
2675  }
2676  else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2677  (assembly->id.version.major != expected_ai->version.major ||
2678  assembly->id.version.minor != expected_ai->version.minor ||
2679  assembly->id.version.build < expected_ai->version.build ||
2680  (assembly->id.version.build == expected_ai->version.build &&
2681  assembly->id.version.revision < expected_ai->version.revision)))
2682  {
2683  set_error( xmlbuf );
2684  }
2685  }
2686  }
2688  {
2689  parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2690  }
2691  else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2692  {
2693  parse_application_elem(xmlbuf, assembly, acl, &elem);
2694  }
2695  else
2696  {
2697  parse_unknown_elem(xmlbuf, &elem);
2698  }
2699  }
2700 
2703  {
2704  set_error( xmlbuf );
2705  }
2706 }
2707 
2709  struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2710 {
2711  struct xml_elem elem;
2712  struct xml_elem parent = {0};
2713 
2714  xmlbuf->error = FALSE;
2715  xmlbuf->ns_pos = 0;
2716 
2717  if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2718 
2719  if (xmlstr_cmp(&elem.name, g_xmlW) &&
2720  (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2722 
2723  if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2724  {
2726  }
2727 
2728  parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2729  if (xmlbuf->error)
2730  {
2732  }
2733 
2734  if (next_xml_elem(xmlbuf, &elem, &parent))
2735  {
2737  }
2738 
2739  if (xmlbuf->ptr != xmlbuf->end)
2740  {
2742  }
2743  return STATUS_SUCCESS;
2744 }
2745 
2746 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2748  const void *buffer, SIZE_T size )
2749 {
2750  xmlbuf_t xmlbuf;
2751  NTSTATUS status;
2752  struct assembly *assembly;
2753  int unicode_tests;
2754 
2755  DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2756 
2759 
2761  return STATUS_NO_MEMORY;
2762 
2763  if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2764  assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2765  : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2766 
2768  if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2769  {
2770  xmlbuf.ptr = buffer;
2771  xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2772  status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2773  }
2774  else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2775  {
2776  const WCHAR *buf = buffer;
2777  WCHAR *new_buff;
2778  unsigned int i;
2779 
2780  if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2781  return STATUS_NO_MEMORY;
2782  for (i = 0; i < size / sizeof(WCHAR); i++)
2783  new_buff[i] = RtlUshortByteSwap( buf[i] );
2784  xmlbuf.ptr = new_buff;
2785  xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2786  status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2787  RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2788  }
2789  else
2790  {
2791  /* TODO: this doesn't handle arbitrary encodings */
2792  WCHAR *new_buff;
2793  ULONG sizeU;
2794 
2796  if (!NT_SUCCESS(status))
2797  {
2798  DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2800  }
2801 
2802  new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2803  if (!new_buff)
2804  return STATUS_NO_MEMORY;
2805 
2806  status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2807  if (!NT_SUCCESS(status))
2808  {
2809  DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2811  }
2812 
2813  xmlbuf.ptr = new_buff;
2814  xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2815  status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2816  RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2817  }
2818  return status;
2819 }
2820 
2822 {
2825 
2826  attr.Length = sizeof(attr);
2827  attr.RootDirectory = 0;
2828  attr.Attributes = OBJ_CASE_INSENSITIVE;
2829  attr.ObjectName = name;
2830  attr.SecurityDescriptor = NULL;
2831  attr.SecurityQualityOfService = NULL;
2833 }
2834 
2836 {
2837  NTSTATUS status;
2838  ULONG_PTR magic;
2839  LDR_DATA_TABLE_ENTRY *pldr;
2840 
2842  status = LdrFindEntryForAddress( module, &pldr );
2843  if (status == STATUS_SUCCESS)
2844  {
2845  if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2846  pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2847  {
2848  memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2849  str->Length = pldr->FullDllName.Length;
2850  str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2851  }
2852  else status = STATUS_NO_MEMORY;
2853  }
2855  return status;
2856 }
2857 
2860  HANDLE hModule, LPCWSTR resname, ULONG lang )
2861 {
2862  NTSTATUS status;
2866  void *ptr;
2867 
2868  //DPRINT( "looking for res %s in module %p %s\n", resname,
2869  // hModule, filename );
2870  DPRINT("get_manifest_in_module %p\n", hModule);
2871 
2872 #if 0
2873  if (TRACE_ON(actctx))
2874  {
2875  if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2876  {
2877  DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2878  hModule, debugstr_w(nameW.Buffer) );
2880  }
2881  else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2883  }
2884 #endif
2885 
2886  if (!resname) return STATUS_INVALID_PARAMETER;
2887 
2888  info.Type = (ULONG_PTR)RT_MANIFEST;
2889  info.Language = lang;
2890  if (!((ULONG_PTR)resname >> 16))
2891  {
2892  info.Name = (ULONG_PTR)resname;
2894  }
2895  else if (resname[0] == '#')
2896  {
2897  ULONG value;
2898  RtlInitUnicodeString(&nameW, resname + 1);
2900  return STATUS_INVALID_PARAMETER;
2901  info.Name = value;
2903  }
2904  else
2905  {
2906  RtlCreateUnicodeString(&nameW, resname);
2908  info.Name = (ULONG_PTR)nameW.Buffer;
2911  }
2913 
2914  if (status == STATUS_SUCCESS)
2915  status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2916 
2917  return status;
2918 }
2919 
2921  LPCWSTR name, void *root,
2922  int want_dir );
2923 
2925  void *root, int want_dir );
2926 
2927 
2929  void *root, int want_dir )
2930 {
2932  int pos;
2933 
2934  for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
2935  {
2936  if (!entry[pos].DataIsDirectory == !want_dir)
2937  return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
2938  }
2939  return NULL;
2940 }
2941 
2942 
2946 {
2947  ULONG size;
2948  PVOID root, ptr;
2949  IMAGE_RESOURCE_DIRECTORY *resdirptr;
2951  NTSTATUS status;
2952 
2954  if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
2955  if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
2956  resdirptr = root;
2957 
2958  if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1)))
2960 
2961  resdirptr = ptr;
2962  if (!(ptr = find_first_id_entry(resdirptr, root, 1)))
2964 
2965  resdirptr = ptr;
2966  if (!(ptr = find_first_entry(resdirptr, root, 0)))
2968 
2969  entry = ptr;
2971 
2972  if (status == STATUS_SUCCESS)
2973  status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2974 
2975  return status;
2976 }
2977 
2978 
2981  HANDLE file, LPCWSTR resname, ULONG lang )
2982 {
2983  HANDLE mapping;
2987  NTSTATUS status;
2988  SIZE_T count;
2989  void *base;
2990  WCHAR resnameBuf[20];
2991  LPCWSTR resptr = resname;
2992 
2993  if ((!((ULONG_PTR)resname >> 16)))
2994  {
2995  sprintfW(resnameBuf, L"#%u", PtrToUlong(resname));
2996  resptr = resnameBuf;
2997  }
2998 
2999  DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>");
3000 
3001  attr.Length = sizeof(attr);
3002  attr.RootDirectory = 0;
3003  attr.ObjectName = NULL;
3004  attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3005  attr.SecurityDescriptor = NULL;
3006  attr.SecurityQualityOfService = NULL;
3007 
3008  size.QuadPart = 0;
3011  if (status != STATUS_SUCCESS) return status;
3012 
3013  offset.QuadPart = 0;
3014  count = 0;
3015  base = NULL;
3017  &count, ViewShare, 0, PAGE_READONLY );
3018  NtClose( mapping );
3019  if (status != STATUS_SUCCESS) return status;
3020 
3021  if (RtlImageNtHeader(base)) /* we got a PE file */
3022  {
3023  HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3024  if (resname)
3025  status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3026  else
3028  }
3030 
3032  return status;
3033 }
3034 
3037 {
3040  HANDLE mapping;
3044  NTSTATUS status;
3045  SIZE_T count;
3046  void *base;
3047 
3048  DPRINT( "loading manifest file %S\n", filename );
3049 
3050  attr.Length = sizeof(attr);
3051  attr.RootDirectory = 0;
3052  attr.ObjectName = NULL;
3053  attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3054  attr.SecurityDescriptor = NULL;
3055  attr.SecurityQualityOfService = NULL;
3056 
3057  size.QuadPart = 0;
3060 
3061  if (status != STATUS_SUCCESS) return status;
3062 
3063  offset.QuadPart = 0;
3064  count = 0;
3065  base = NULL;
3067  &count, ViewShare, 0, PAGE_READONLY );
3068  NtClose( mapping );
3069  if (status != STATUS_SUCCESS) return status;
3070 
3071  /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
3073 
3074  if (status == STATUS_SUCCESS)
3075  status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
3076 
3078  return status;
3079 }
3080 
3081 /* try to load the .manifest file associated to the file */
3084 {
3085  static const WCHAR fmtW[] = { '.','%','l','u',0 };
3086  WCHAR *buffer;
3087  NTSTATUS status;
3089  HANDLE file;
3091 
3092  if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3093 
3094  DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
3095 
3096  if (module) /* use the module filename */
3097  {
3099 
3100  if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3101  {
3102  if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3103  strcatW( name.Buffer, dotManifestW );
3104  if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3107  }
3108  if (status) return status;
3109  }
3110  else
3111  {
3112  if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3113  (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3114  return STATUS_NO_MEMORY;
3115  strcpyW( buffer, filename );
3116  if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3119  }
3120 
3121  if (!open_nt_file( &file, &nameW ))
3122  {
3124  NtClose( file );
3125  }
3128  return status;
3129 }
3130 
3132 {
3133  static const WCHAR lookup_fmtW[] =
3134  {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3135  '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3136  static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3137 
3138  WCHAR *lookup, *ret = NULL;
3139  UNICODE_STRING lookup_us;
3141  const WCHAR *lang = ai->language;
3142  unsigned int data_pos = 0, data_len;
3143  char buffer[8192];
3144 
3145  if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3146  (strlenW(ai->arch) + strlenW(ai->name)
3147  + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
3148  + sizeof(lookup_fmtW) )))
3149  return NULL;
3150 
3151  if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3152  sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3153  ai->version.major, ai->version.minor, lang );
3154  RtlInitUnicodeString( &lookup_us, lookup );
3155 
3156  if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3157  FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3158  {
3159  ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3160  FILE_BOTH_DIR_INFORMATION *dir_info;
3161  WCHAR *tmp;
3162  ULONG build, revision;
3163 
3164  data_len = (ULONG)io.Information;
3165 
3166  for (;;)
3167  {
3168  if (data_pos >= data_len)
3169  {
3170  if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3171  FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3172  break;
3173  data_len = (ULONG)io.Information;
3174  data_pos = 0;
3175  }
3176  dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3177 
3178  if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3179  else data_pos = data_len;
3180 
3181  tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
3182  build = atoiW(tmp);
3183  if (build < min_build) continue;
3184  tmp = strchrW(tmp, '.') + 1;
3185  revision = atoiW(tmp);
3186  if (build == min_build && revision < min_revision) continue;
3187  tmp = strchrW(tmp, '_') + 1;
3188  tmp = strchrW(tmp, '_') + 1;
3189  if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3190  !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3191  {
3192  /* prefer a non-Wine manifest if we already have one */
3193  /* we'll still load the builtin dll if specified through DllOverrides */
3194  if (ret) continue;
3195  }
3196  else
3197  {
3198  min_build = build;
3199  min_revision = revision;
3200  }
3201  ai->version.build = build;
3202  ai->version.revision = revision;
3203  RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
3204  if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3205  {
3206  memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3207  ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3208  }
3209  }
3210  }
3211  else DPRINT1("no matching file for %S\n", lookup);
3212  RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
3213  return ret;
3214 }
3215 
3217 {
3218  struct assembly_identity sxs_ai;
3219  UNICODE_STRING path_us;
3222  WCHAR *path, *file = NULL;
3223  HANDLE handle;
3224 
3225  static const WCHAR manifest_dirW[] =
3226  {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3227 
3228  if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3229 
3230  if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3231  ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
3232  return STATUS_NO_MEMORY;
3233 
3234  memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
3235  memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
3236 
3237  if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3238  {
3239  RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3240  return STATUS_NO_SUCH_FILE;
3241  }
3242  RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3243 
3244  attr.Length = sizeof(attr);
3245  attr.RootDirectory = 0;
3246  attr.Attributes = OBJ_CASE_INSENSITIVE;
3247  attr.ObjectName = &path_us;
3248  attr.SecurityDescriptor = NULL;
3249  attr.SecurityQualityOfService = NULL;
3250 
3253  {
3254  sxs_ai = *ai;
3255  file = lookup_manifest_file( handle, &sxs_ai );
3256  NtClose( handle );
3257  }
3258  if (!file)
3259  {
3260  RtlFreeUnicodeString( &path_us );
3261  return STATUS_NO_SUCH_FILE;
3262  }
3263 
3264  /* append file name to directory path */
3265  if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
3266  path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3267  {
3268  RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3269  RtlFreeUnicodeString( &path_us );
3270  return STATUS_NO_MEMORY;
3271  }
3272 
3273  path[path_us.Length/sizeof(WCHAR)] = '\\';
3274  strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3275  RtlInitUnicodeString( &path_us, path );
3276  *strrchrW(file, '.') = 0; /* remove .manifest extension */
3277 
3278  if (!open_nt_file( &handle, &path_us ))
3279  {
3280  io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3281  NtClose( handle );
3282  }
3283  else io.Status = STATUS_NO_SUCH_FILE;
3284 
3285  RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3286  RtlFreeUnicodeString( &path_us );
3287  return io.Status;
3288 }
3289 
3291  struct assembly_identity* ai)
3292 {
3293  static const WCHAR dotDllW[] = {'.','d','l','l',0};
3294  unsigned int i;
3295  WCHAR *buffer, *p, *directory;
3296  NTSTATUS status;
3298  HANDLE file;
3299  DWORD len;
3300 
3301  DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
3302  ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
3303 
3304  if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3305 
3306  /* FIXME: add support for language specific lookup */
3307 
3308  len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3309  strlenW(acl->actctx->appdir.info));
3310 
3311  nameW.Buffer = NULL;
3312  if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3313  (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3314  return STATUS_NO_MEMORY;
3315 
3316  if (!(directory = build_assembly_dir( ai )))
3317  {
3318  RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3319  return STATUS_NO_MEMORY;
3320  }
3321 
3322  /* Lookup in <dir>\name.dll
3323  * <dir>\name.manifest
3324  * <dir>\name\name.dll
3325  * <dir>\name\name.manifest
3326  *
3327  * First 'appdir' is used as <dir>, if that failed
3328  * it tries application manifest file path.
3329  */
3330  strcpyW( buffer, acl->actctx->appdir.info );
3331  p = buffer + strlenW(buffer);
3332  for (i = 0; i < 4; i++)
3333  {
3334  if (i == 2)
3335  {
3336  struct assembly *assembly = acl->actctx->assemblies;
3337  if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3338  }
3339  else *p++ = '\\';
3340 
3341  strcpyW( p, ai->name );
3342  p += strlenW(p);
3343 
3344  strcpyW( p, dotDllW );
3346  {
3347  status = open_nt_file( &file, &nameW );
3348  if (!status)
3349  {
3350  status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3351  (LPCWSTR)0, 0 );
3352  NtClose( file );
3353  break;
3354  }
3356  }
3357 
3358  strcpyW( p, dotManifestW );
3360  {
3361  status = open_nt_file( &file, &nameW );
3362  if (!status)
3363  {
3365  NtClose( file );
3366  break;
3367  }
3369  }
3371  }
3373  RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
3374  RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3375  return status;
3376 }
3377 
3379 {
3381  unsigned int i;
3382 
3383  for (i = 0; i < acl->num_dependencies; i++)
3384  {
3385  if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3386  {
3387  if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3388  {
3389  const struct assembly_version *ver = &acl->dependencies[i].version;
3390  DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3391  acl->dependencies[i].name,
3392  ver->major, ver->minor, ver->build, ver->revision );
3394  break;
3395  }
3396  }
3397  }
3398  /* FIXME should now iterate through all refs */
3399  return status;
3400 }
3401 
3402 /* find the appropriate activation context for RtlQueryInformationActivationContext */