ReactOS  0.4.14-dev-115-g4576127
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 
47 
48 typedef struct
49 {
50  const WCHAR *ptr;
51  unsigned int len;
52 } xmlstr_t;
53 
54 typedef struct
55 {
56  const WCHAR *ptr;
57  const WCHAR *end;
58 } xmlbuf_t;
59 
60 struct file_info
61 {
64 };
65 
67 {
72 };
73 
75 {
84 };
85 
86 struct strsection_header
87 {
88  DWORD magic;
89  ULONG size;
90  DWORD unk1[3];
91  ULONG count;
93  DWORD unk2[2];
96 };
97 
98 struct string_index
99 {
100  ULONG hash; /* key string hash */
102  ULONG name_len;
103  ULONG data_offset; /* redirect data offset */
104  ULONG data_len;
106 };
107 
108 struct guidsection_header
109 {
110  DWORD magic;
111  ULONG size;
112  DWORD unk[3];
113  ULONG count;
115  DWORD unk2;
118 };
119 
120 struct guid_index
121 {
122  GUID guid;
124  ULONG data_len;
126 };
127 
129 {
130  ULONG size;
131  DWORD res;
132  ULONG name_len;
133  ULONG name_offset; /* versioned name offset */
135  ULONG module_offset;/* container name offset */
136 };
137 
138 struct dllredirect_data
139 {
140  ULONG size;
141  ULONG unk;
142  DWORD res[3];
143 };
144 
145 struct tlibredirect_data
146 {
147  ULONG size;
148  DWORD res;
149  ULONG name_len;
151  LANGID langid;
152  WORD flags;
153  ULONG help_len;
157 };
158 
160 {
166 };
167 
169 {
175 };
176 
178 {
179  ULONG size;
180  BYTE res;
181  BYTE miscmask;
182  BYTE res1[2];
183  DWORD model;
184  GUID clsid;
185  GUID alias;
186  GUID clsid2;
187  GUID tlbid;
188  ULONG name_len;
199 };
200 
202 {
205 };
206 
208 {
209  ULONG size;
210  DWORD mask;
211  GUID iid;
213  GUID tlbid;
214  GUID base;
215  ULONG name_len;
217 };
218 
219 struct clrsurrogate_data
220 {
221  ULONG size;
222  DWORD res;
223  GUID clsid;
227  ULONG name_len;
228 };
229 
230 struct clrclass_data
231 {
232  ULONG size;
233  DWORD res[2];
236  ULONG name_len;
240  DWORD res2[2];
241 };
242 
243 struct progidredirect_data
244 {
245  ULONG size;
246  DWORD reserved;
248 };
249 
250 /*
251 
252  Sections structure.
253 
254  Sections are accessible by string or guid key, that defines two types of sections.
255  All sections of each type have same magic value and header structure, index
256  data could be of two possible types too. So every string based section uses
257  the same index format, same applies to guid sections - they share same guid index
258  format.
259 
260  - window class redirection section is a plain buffer with following format:
261 
262  <section header>
263  <index[]>
264  <data[]> --- <original name>
265  <redirect data>
266  <versioned name>
267  <module name>
268 
269  Header is fixed length structure - struct strsection_header,
270  contains redirected classes count;
271 
272  Index is an array of fixed length index records, each record is
273  struct string_index.
274 
275  All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
276 
277  Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
278  others are relative to section itself.
279 
280  - dll redirect section format:
281 
282  <section header>
283  <index[]>
284  <data[]> --- <dll name>
285  <data>
286 
287  This section doesn't seem to carry any payload data except dll names.
288 
289  - typelib section format:
290 
291  <section header>
292  <module names[]>
293  <index[]>
294  <data[]> --- <data>
295  <helpstring>
296 
297  Header is fixed length, index is an array of fixed length 'struct guid_index'.
298  All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
299  4-bytes aligned as a whole.
300 
301  Module name offsets are relative to section, helpstring offset is relative to data
302  structure itself.
303 
304  - comclass section format:
305 
306  <section header>
307  <module names[]>
308  <index[]>
309  <data[]> --- <data> --- <data>
310  <progid> <clrdata>
311  <name>
312  <version>
313  <progid>
314 
315  This section uses two index records per comclass, one entry contains original guid
316  as specified by context, another one has a generated guid. Index and strings handling
317  is similar to typelib sections.
318 
319  For CLR classes additional data is stored after main COM class data, it contains
320  class name and runtime version string, see 'struct clrclass_data'.
321 
322  Module name offsets are relative to section, progid offset is relative to data
323  structure itself.
324 
325  - COM interface section format:
326 
327  <section header>
328  <index[]>
329  <data[]> --- <data>
330  <name>
331 
332  Interface section contains data for proxy/stubs and external proxy/stubs. External
333  ones are defined at assembly level, so this section has no module information.
334  All records are indexed with 'iid' value from manifest. There an exception for
335  external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
336  redirect data, but index is still 'iid' from manifest.
337 
338  Interface name offset is relative to data structure itself.
339 
340  - CLR surrogates section format:
341 
342  <section header>
343  <index[]>
344  <data[]> --- <data>
345  <name>
346  <version>
347 
348  There's nothing special about this section, same way to store strings is used,
349  no modules part as it belongs to assembly level, not a file.
350 
351  - ProgID section format:
352 
353  <section header>
354  <guids[]>
355  <index[]>
356  <data[]> --- <progid>
357  <data>
358 
359  This sections uses generated alias guids from COM server section. This way
360  ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
361  is stored too, aligned.
362 */
363 
364 struct progids
365 {
367  unsigned int num;
368  unsigned int allocated;
369 };
370 
371 struct entity
372 {
374  union
375  {
376  struct
377  {
383  } typelib;
384  struct
385  {
387  WCHAR *tlbid;
389  WCHAR *name; /* clrClass: class name */
390  WCHAR *version; /* clrClass: CLR runtime version */
397  struct progids progids;
398  } comclass;
399  struct {
403  WCHAR *name;
404  WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
407  } ifaceps;
408  struct
409  {
410  WCHAR *name;
412  } class;
413  struct
414  {
415  WCHAR *name;
416  WCHAR *clsid;
417  WCHAR *version;
418  } clrsurrogate;
419  } u;
420 };
421 
423 {
424  struct entity *base;
425  unsigned int num;
426  unsigned int allocated;
427 };
428 
430 {
434 };
435 
437 {
441 };
442 
443 struct assembly
444 {
451  unsigned int num_dlls;
452  unsigned int allocated_dlls;
454  COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
456  ACTCTX_REQUESTED_RUN_LEVEL run_level;
458 };
459 
461 {
469 };
470 
472 {
477 
478 typedef struct _ASSEMBLY_STORAGE_MAP
479 {
484 
485 typedef struct _ACTIVATION_CONTEXT
486 {
490  PACTIVATION_CONTEXT_DATA ActivationContextData;
502  unsigned int num_assemblies;
503  unsigned int allocated_assemblies;
504  /* section data */
514 
516 {
519  unsigned int num_dependencies;
521 };
522 
523 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
524 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
525 
527 {
531 
532 VOID
533 NTAPI
535  IN ULONG FailureCode)
536 {
537  EXCEPTION_RECORD ExceptionRecord;
538 
539  /* Fatal SxS exception header */
540  ExceptionRecord.ExceptionRecord = NULL;
541  ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
542  ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
543 
544  /* With SxS-specific information plus the context itself */
545  ExceptionRecord.ExceptionInformation[0] = 1;
546  ExceptionRecord.ExceptionInformation[1] = FailureCode;
547  ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
548  ExceptionRecord.NumberParameters = 3;
549 
550  /* Raise it */
551  RtlRaiseException(&ExceptionRecord);
552 }
553 
555 VOID
557 {
559 
560  /* Get the caller-opaque header */
561  pActual = CONTAINING_RECORD(ActCtx,
563  ActivationContext);
564 
565  /* Check if the header matches as expected */
566  if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
567  {
568  /* Nope, print out a warning, assert, and then throw an exception */
569  DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
570  " This means someone stepped on the allocation, or someone is using a\n"
571  " deallocated activation context\n",
572  __FUNCTION__,
573  pActual->MagicMarker,
574  ActCtx);
577  }
578 }
579 
580 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
581 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
582 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
583 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
584 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
585 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
586 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};
587 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};
588 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
589 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
590 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
591 static const WCHAR fileW[] = {'f','i','l','e',0};
592 static const WCHAR hashW[] = {'h','a','s','h',0};
593 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
594 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
595 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
596 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
597 
598 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
599 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
600 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
601 static const WCHAR iidW[] = {'i','i','d',0};
602 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
603 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
604 static const WCHAR g_nameW[] = {'n','a','m','e',0};
605 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
606 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
607 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
608 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
609 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};
610 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
611 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
612 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
613 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
614 static const WCHAR typeW[] = {'t','y','p','e',0};
615 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
616 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
617 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
618 static const WCHAR yesW[] = {'y','e','s',0};
619 static const WCHAR noW[] = {'n','o',0};
620 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
621 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
622 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
623 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
624 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
625 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
626 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
627 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
628 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
629 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
630 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
631 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
632 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
633 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
634 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
635 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
636 
637 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
638 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
639 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
640 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
641 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
642 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
643 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
644 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};
645 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
646 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
647 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
648 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
649 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
650 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
651 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
652 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
653 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};
654 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
655 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
656 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
657 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};
658 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
659 
660 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
661 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};
662 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
663 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
664 static const WCHAR IdW[] = {'I','d',0};
665 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};
666 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
667 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
668 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
669 
671 {
672  const WCHAR *name;
673  OLEMISC value;
674 };
675 
676 static const struct olemisc_entry olemisc_values[] =
677 {
678  { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
679  { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
680  { actslikelabelW, OLEMISC_ACTSLIKELABEL },
681  { alignableW, OLEMISC_ALIGNABLE },
682  { alwaysrunW, OLEMISC_ALWAYSRUN },
683  { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
684  { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
685  { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
686  { imemodeW, OLEMISC_IMEMODE },
687  { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
688  { insideoutW, OLEMISC_INSIDEOUT },
689  { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
690  { islinkobjectW, OLEMISC_ISLINKOBJECT },
691  { nouiactivateW, OLEMISC_NOUIACTIVATE },
692  { onlyiconicW, OLEMISC_ONLYICONIC },
693  { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
694  { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
695  { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
696  { simpleframeW, OLEMISC_SIMPLEFRAME },
697  { staticW, OLEMISC_STATIC },
698  { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
699  { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
700 };
701 
702 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
703 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};
704 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};
705 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};
706 
707 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
708 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
709 static const WCHAR wildcardW[] = {'*',0};
710 
714 
715 static WCHAR *strdupW(const WCHAR* str)
716 {
717  WCHAR* ptr;
718 
719  if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
720  return NULL;
721  return strcpyW(ptr, str);
722 }
723 
724 static WCHAR *xmlstrdupW(const xmlstr_t* str)
725 {
726  WCHAR *strW;
727 
728  if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
729  {
730  memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
731  strW[str->len] = 0;
732  }
733  return strW;
734 }
735 
736 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
737 {
738  return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
739 }
740 
741 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
742 {
743  return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
744 }
745 
746 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
747 {
748  return (xmlstr->len && xmlstr->ptr[0] == '/' &&
749  !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
750 }
751 
752 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
753 {
754  UINT len = strlenW( namespace );
755 
756  if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
757  return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
758  !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
759 }
760 
761 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
762 {
763  if (elem->len && elem->ptr[0] == '/')
764  {
765  xmlstr_t elem_end;
766  elem_end.ptr = elem->ptr + 1;
767  elem_end.len = elem->len - 1;
768  return xml_elem_cmp( &elem_end, str, namespace );
769  }
770  return FALSE;
771 }
772 
773 static inline BOOL isxmlspace( WCHAR ch )
774 {
775  return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
776 }
777 
779 {
781 
782  res.Buffer = (PWSTR)xmlstr->ptr;
783  res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR);
784 
785  return res;
786 }
787 
789 {
790  struct assembly *assembly;
791 
792  DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
793 
794  if (actctx->num_assemblies == actctx->allocated_assemblies)
795  {
796  void *ptr;
797  unsigned int new_count;
798  if (actctx->assemblies)
799  {
800  new_count = actctx->allocated_assemblies * 2;
801  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
802  actctx->assemblies, new_count * sizeof(*assembly) );
803  }
804  else
805  {
806  new_count = 4;
807  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
808  }
809  if (!ptr) return NULL;
810  actctx->assemblies = ptr;
811  actctx->allocated_assemblies = new_count;
812  }
813 
814  assembly = &actctx->assemblies[actctx->num_assemblies++];
815  assembly->type = at;
816  return assembly;
817 }
818 
820 {
821  DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
822 
824  {
825  void *ptr;
826  unsigned int new_count;
827  if (assembly->dlls)
828  {
829  new_count = assembly->allocated_dlls * 2;
830  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
831  assembly->dlls, new_count * sizeof(*assembly->dlls) );
832  }
833  else
834  {
835  new_count = 4;
836  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
837  }
838  if (!ptr) return NULL;
839  assembly->dlls = ptr;
840  assembly->allocated_dlls = new_count;
841  }
842  return &assembly->dlls[assembly->num_dlls++];
843 }
844 
845 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
846 {
847  void *ptr;
849  {
850  unsigned int new_count = assembly->num_compat_contexts + 1;
851  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
853  new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
854  }
855  else
856  {
857  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
858  }
859  if (!ptr) return NULL;
862 }
863 
865 {
866  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
867  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
868  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
869  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
870  RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
871 }
872 
873 static struct entity* add_entity(struct entity_array *array, DWORD kind)
874 {
875  struct entity* entity;
876 
877  if (array->num == array->allocated)
878  {
879  void *ptr;
880  unsigned int new_count;
881  if (array->base)
882  {
883  new_count = array->allocated * 2;
884  ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
885  array->base, new_count * sizeof(*array->base) );
886  }
887  else
888  {
889  new_count = 4;
890  ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
891  }
892  if (!ptr) return NULL;
893  array->base = ptr;
894  array->allocated = new_count;
895  }
896  entity = &array->base[array->num++];
897  entity->kind = kind;
898  return entity;
899 }
900 
902 {
903  unsigned int i, j;
904  for (i = 0; i < array->num; i++)
905  {
906  struct entity *entity = &array->base[i];
907  switch (entity->kind)
908  {
909  case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
910  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
911  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
912  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
913  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
914  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
915  for (j = 0; j < entity->u.comclass.progids.num; j++)
916  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
917  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
918  break;
919  case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
920  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
921  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
922  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
923  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
924  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
925  break;
926  case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
927  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
928  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
929  break;
930  case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
931  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
932  break;
933  case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
934  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
935  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
936  RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
937  break;
938  default:
939  DPRINT1("Unknown entity kind %u\n", entity->kind);
940  }
941  }
942  RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
943 }
944 
945 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
946 {
947  if (!str1) return !str2;
948  return str2 && !strcmpiW( str1, str2 );
949 }
950 
951 static BOOL is_matching_identity( const struct assembly_identity *id1,
952  const struct assembly_identity *id2 )
953 {
954  if (!is_matching_string( id1->name, id2->name )) return FALSE;
955  if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
956  if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
957 
958  if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
959  {
960  if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
961  return FALSE;
962  }
963  if (id1->version.major != id2->version.major) return FALSE;
964  if (id1->version.minor != id2->version.minor) return FALSE;
965  if (id1->version.build > id2->version.build) return FALSE;
966  if (id1->version.build == id2->version.build &&
967  id1->version.revision > id2->version.revision) return FALSE;
968  return TRUE;
969 }
970 
972  struct assembly_identity* ai)
973 {
974  unsigned int i;
975 
976  /* check if we already have that assembly */
977 
978  for (i = 0; i < acl->actctx->num_assemblies; i++)
979  if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
980  {
981  DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
982  ai->name, ai->arch, ai->version.major, ai->version.minor,
983  ai->version.build, ai->version.revision );
984  return TRUE;
985  }
986 
987  for (i = 0; i < acl->num_dependencies; i++)
988  if (is_matching_identity( ai, &acl->dependencies[i] ))
989  {
990  DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
991  ai->name, ai->arch, ai->version.major, ai->version.minor,
992  ai->version.build, ai->version.revision );
993  return TRUE;
994  }
995 
996  if (acl->num_dependencies == acl->allocated_dependencies)
997  {
998  void *ptr;
999  unsigned int new_count;
1000  if (acl->dependencies)
1001  {
1002  new_count = acl->allocated_dependencies * 2;
1003  ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
1004  new_count * sizeof(acl->dependencies[0]));
1005  }
1006  else
1007  {
1008  new_count = 4;
1009  ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1010  }
1011  if (!ptr) return FALSE;
1012  acl->dependencies = ptr;
1013  acl->allocated_dependencies = new_count;
1014  }
1015  acl->dependencies[acl->num_dependencies++] = *ai;
1016 
1017  return TRUE;
1018 }
1019 
1020 static void free_depend_manifests(struct actctx_loader* acl)
1021 {
1022  unsigned int i;
1023  for (i = 0; i < acl->num_dependencies; i++)
1025  RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
1026 }
1027 
1029 {
1030  static const WCHAR undW[] = {'_',0};
1031  static const WCHAR noneW[] = {'n','o','n','e',0};
1032  static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1033 
1034  const WCHAR *arch = ai->arch ? ai->arch : noneW;
1035  const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1036  const WCHAR *lang = ai->language ? ai->language : noneW;
1037  const WCHAR *name = ai->name ? ai->name : noneW;
1038  SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1039  strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1040  WCHAR *ret;
1041 
1042  if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1043 
1044  strcpyW( ret, arch );
1045  strcatW( ret, undW );
1046  strcatW( ret, name );
1047  strcatW( ret, undW );
1048  strcatW( ret, key );
1049  strcatW( ret, undW );
1051  ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1052  strcatW( ret, undW );
1053  strcatW( ret, lang );
1054  strcatW( ret, undW );
1055  strcatW( ret, mskeyW );
1056  return ret;
1057 }
1058 
1059 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1060 {
1061  WCHAR *p = buffer;
1062 
1063  if (!str) return;
1064  strcatW( buffer, prefix );
1065  p += strlenW(p);
1066  *p++ = '"';
1067  strcpyW( p, str );
1068  p += strlenW(p);
1069  *p++ = '"';
1070  *p = 0;
1071 }
1072 
1073 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1074 {
1075  static const WCHAR archW[] =
1076  {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1077  static const WCHAR public_keyW[] =
1078  {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1079  static const WCHAR typeW2[] =
1080  {',','t','y','p','e','=',0};
1081  static const WCHAR versionW2[] =
1082  {',','v','e','r','s','i','o','n','=',0};
1083 
1084  WCHAR version[64], *ret;
1085  SIZE_T size = 0;
1086 
1088  ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1089  if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1090  if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1091  if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1092  if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1093  size += strlenW(versionW2) + strlenW(version) + 2;
1094 
1095  if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1096  return NULL;
1097 
1098  if (ai->name) strcpyW( ret, ai->name );
1099  else *ret = 0;
1100  append_string( ret, archW, ai->arch );
1101  append_string( ret, public_keyW, ai->public_key );
1102  append_string( ret, typeW2, ai->type );
1103  append_string( ret, versionW2, version );
1104  return ret;
1105 }
1106 
1108 {
1111 
1112  if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1113  _SEH2_TRY
1114  {
1115  if (actctx)
1116  {
1117  pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1118  if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1119  }
1120  }
1122  {
1123  DPRINT1("Invalid activation context handle!\n");
1124  }
1125  _SEH2_END;
1126  return ret;
1127 }
1128 
1130 {
1131  InterlockedExchangeAdd( &actctx->RefCount, 1 );
1132 }
1133 
1135 {
1137 
1138  if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1139  {
1140  unsigned int i, j;
1141 
1142  for (i = 0; i < actctx->num_assemblies; i++)
1143  {
1144  struct assembly *assembly = &actctx->assemblies[i];
1145  for (j = 0; j < assembly->num_dlls; j++)
1146  {
1147  struct dll_redirect *dll = &assembly->dlls[j];
1148  free_entity_array( &dll->entities );
1149  RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1150  RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1151  }
1152  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1153  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1154  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1155  RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts );
1158  }
1159  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1160  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1161  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1162  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1163  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1164  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1165  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1166  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1167  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1168  RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1169 
1170  pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1171  pActual->MagicMarker = 0;
1172  RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1173  }
1174 }
1175 
1177  BOOL* error, BOOL* end)
1178 {
1179  const WCHAR* ptr;
1180 
1181  *error = TRUE;
1182 
1183  while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1184  xmlbuf->ptr++;
1185 
1186  if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1187 
1188  if (*xmlbuf->ptr == '/')
1189  {
1190  xmlbuf->ptr++;
1191  if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1192  return FALSE;
1193 
1194  xmlbuf->ptr++;
1195  *end = TRUE;
1196  *error = FALSE;
1197  return FALSE;
1198  }
1199 
1200  if (*xmlbuf->ptr == '>')
1201  {
1202  xmlbuf->ptr++;
1203  *error = FALSE;
1204  return FALSE;
1205  }
1206 
1207  ptr = xmlbuf->ptr;
1208  while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1209 
1210  if (ptr == xmlbuf->end) return FALSE;
1211 
1212  name->ptr = xmlbuf->ptr;
1213  name->len = ptr-xmlbuf->ptr;
1214  xmlbuf->ptr = ptr;
1215 
1216  /* skip spaces before '=' */
1217  while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1218  if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1219 
1220  /* skip '=' itself */
1221  ptr++;
1222  if (ptr == xmlbuf->end) return FALSE;
1223 
1224  /* skip spaces after '=' */
1225  while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1226 
1227  if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1228 
1229  value->ptr = ++ptr;
1230  if (ptr == xmlbuf->end) return FALSE;
1231 
1232  ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1233  if (!ptr)
1234  {
1235  xmlbuf->ptr = xmlbuf->end;
1236  return FALSE;
1237  }
1238 
1239  value->len = ptr - value->ptr;
1240  xmlbuf->ptr = ptr + 1;
1241 
1242  if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1243 
1244  *error = FALSE;
1245  return TRUE;
1246 }
1247 
1249 {
1250  const WCHAR* ptr;
1251 
1252  for (;;)
1253  {
1254  ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1255  if (!ptr)
1256  {
1257  xmlbuf->ptr = xmlbuf->end;
1258  return FALSE;
1259  }
1260  ptr++;
1261  if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1262  {
1263  for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1264  if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1265 
1266  if (ptr + 3 > xmlbuf->end)
1267  {
1268  xmlbuf->ptr = xmlbuf->end;
1269  return FALSE;
1270  }
1271  xmlbuf->ptr = ptr + 3;
1272  }
1273  else break;
1274  }
1275 
1276  xmlbuf->ptr = ptr;
1277  while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1278  ptr++;
1279 
1280  elem->ptr = xmlbuf->ptr;
1281  elem->len = ptr - xmlbuf->ptr;
1282  xmlbuf->ptr = ptr;
1283  return xmlbuf->ptr != xmlbuf->end;
1284 }
1285 
1287 {
1288  /* FIXME: parse attributes */
1289  const WCHAR *ptr;
1290 
1291  for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1292  {
1293  if (ptr[0] == '?' && ptr[1] == '>')
1294  {
1295  xmlbuf->ptr = ptr + 2;
1296  return TRUE;
1297  }
1298  }
1299  return FALSE;
1300 }
1301 
1303 {
1304  const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1305 
1306  if (!ptr) return FALSE;
1307 
1308  content->ptr = xmlbuf->ptr;
1309  content->len = ptr - xmlbuf->ptr;
1310  xmlbuf->ptr = ptr;
1311 
1312  return TRUE;
1313 }
1314 
1316 {
1317  unsigned int ver[4];
1318  unsigned int pos;
1319  const WCHAR *curr;
1320  UNICODE_STRING strU;
1321 
1322  /* major.minor.build.revision */
1323  ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1324  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1325  {
1326  if (*curr >= '0' && *curr <= '9')
1327  {
1328  ver[pos] = ver[pos] * 10 + *curr - '0';
1329  if (ver[pos] >= 0x10000) goto error;
1330  }
1331  else if (*curr == '.')
1332  {
1333  if (++pos >= 4) goto error;
1334  }
1335  else goto error;
1336  }
1337  version->major = ver[0];
1338  version->minor = ver[1];
1339  version->build = ver[2];
1340  version->revision = ver[3];
1341  return TRUE;
1342 
1343 error:
1344  strU = xmlstr2unicode(str);
1345  DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU );
1346  return FALSE;
1347 }
1348 
1349 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1350 {
1351  xmlstr_t elem;
1352  UNICODE_STRING elemU;
1353  if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1354  if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1355  elemU = xmlstr2unicode(&elem);
1356  DPRINT1( "unexpected element %wZ\n", &elemU );
1357  return FALSE;
1358 }
1359 
1361 {
1362  xmlstr_t attr_name, attr_value;
1363  UNICODE_STRING attr_nameU, attr_valueU;
1364  BOOL error;
1365 
1366  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1367  {
1368  attr_nameU = xmlstr2unicode(&attr_name);
1369  attr_valueU = xmlstr2unicode(&attr_value);
1370  DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU,
1371  &attr_valueU);
1372  }
1373  return !error;
1374 }
1375 
1377 {
1378  BOOL end = FALSE;
1379  return parse_expect_no_attr(xmlbuf, &end) && !end;
1380 }
1381 
1382 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1383 {
1384  xmlstr_t elem;
1385  UNICODE_STRING elemU;
1386  if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1387  if (!xml_elem_cmp_end(&elem, name, namespace))
1388  {
1389  elemU = xmlstr2unicode(&elem);
1390  DPRINT1( "unexpected element %wZ\n", &elemU );
1391  return FALSE;
1392  }
1393  return parse_end_element(xmlbuf);
1394 }
1395 
1396 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1397 {
1398  xmlstr_t attr_name, attr_value, elem;
1399  BOOL end = FALSE, error, ret = TRUE;
1400 
1401  while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1402  if(error || end) return end;
1403 
1404  while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1405  {
1406  if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1407  !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1408  break;
1409  else
1410  ret = parse_unknown_elem(xmlbuf, &elem);
1411  }
1412 
1413  return ret && parse_end_element(xmlbuf);
1414 }
1415 
1417  struct assembly_identity* ai)
1418 {
1419  xmlstr_t attr_name, attr_value;
1420  BOOL end = FALSE, error;
1421  UNICODE_STRING attr_valueU, attr_nameU;
1422 
1423  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1424  {
1425  if (xmlstr_cmp(&attr_name, g_nameW))
1426  {
1427  if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1428  }
1429  else if (xmlstr_cmp(&attr_name, typeW))
1430  {
1431  if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1432  }
1433  else if (xmlstr_cmp(&attr_name, versionW))
1434  {
1435  if (!parse_version(&attr_value, &ai->version)) return FALSE;
1436  }
1437  else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1438  {
1439  if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1440  }
1441  else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1442  {
1443  if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1444  }
1445  else if (xmlstr_cmp(&attr_name, languageW))
1446  {
1447  DPRINT("Unsupported yet language attribute (%.*S)\n",
1448  attr_value.len, attr_value.ptr);
1449  if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1450  }
1451  else
1452  {
1453  attr_nameU = xmlstr2unicode(&attr_name);
1454  attr_valueU = xmlstr2unicode(&attr_value);
1455  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1456  }
1457  }
1458 
1459  if (error || end) return end;
1461 }
1462 
1464 {
1465  static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1466  static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1467  static const WCHAR freeW[] = {'F','r','e','e',0};
1468  static const WCHAR bothW[] = {'B','o','t','h',0};
1469 
1470  if (value->len == 0) return ThreadingModel_No;
1471  if (xmlstr_cmp(value, apartW))
1472  return ThreadingModel_Apartment;
1473  else if (xmlstr_cmp(value, freeW))
1474  return ThreadingModel_Free;
1475  else if (xmlstr_cmp(value, bothW))
1476  return ThreadingModel_Both;
1477  else if (xmlstr_cmp(value, neutralW))
1478  return ThreadingModel_Neutral;
1479  else
1480  return ThreadingModel_No;
1481 };
1482 
1483 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1484 {
1485  int min, max;
1486 
1487  min = 0;
1488  max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1489 
1490  while (min <= max)
1491  {
1492  int n, c;
1493 
1494  n = (min+max)/2;
1495 
1497  if (!c && !olemisc_values[n].name[len])
1498  return olemisc_values[n].value;
1499 
1500  if (c >= 0)
1501  max = n-1;
1502  else
1503  min = n+1;
1504  }
1505 
1506  DPRINT1("unknown flag %S\n", str);
1507  return 0;
1508 }
1509 
1511 {
1512  const WCHAR *str = value->ptr, *start;
1513  DWORD flags = 0;
1514  int i = 0;
1515 
1516  /* it's comma separated list of flags */
1517  while (i < value->len)
1518  {
1519  start = str;
1520  while (*str != ',' && (i++ < value->len)) str++;
1521 
1523 
1524  /* skip separator */
1525  str++;
1526  i++;
1527  }
1528 
1529  return flags;
1530 }
1531 
1533 {
1534  struct progids *progids = &entity->u.comclass.progids;
1535 
1536  if (progids->allocated == 0)
1537  {
1538  progids->allocated = 4;
1539  if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1540  }
1541 
1542  if (progids->allocated == progids->num)
1543  {
1544  WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1545  2 * progids->allocated * sizeof(WCHAR*));
1546  if (!new_progids) return FALSE;
1547  progids->allocated *= 2;
1548  progids->progids = new_progids;
1549  }
1550 
1551  if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1552  progids->num++;
1553 
1554  return TRUE;
1555 }
1556 
1558 {
1559  xmlstr_t content;
1560  BOOL end = FALSE;
1561 
1562  if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1563  return FALSE;
1564 
1565  if (!com_class_add_progid(&content, entity)) return FALSE;
1566  return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1567 }
1568 
1569 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1570 {
1571  xmlstr_t elem, attr_name, attr_value;
1572  BOOL ret = TRUE, end = FALSE, error;
1573  struct entity* entity;
1574  UNICODE_STRING attr_valueU, attr_nameU;
1575 
1576  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1577  return FALSE;
1578 
1579  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1580  {
1581  if (xmlstr_cmp(&attr_name, clsidW))
1582  {
1583  if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1584  }
1585  else if (xmlstr_cmp(&attr_name, progidW))
1586  {
1587  if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1588  }
1589  else if (xmlstr_cmp(&attr_name, tlbidW))
1590  {
1591  if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1592  }
1593  else if (xmlstr_cmp(&attr_name, threadingmodelW))
1594  {
1595  entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1596  }
1597  else if (xmlstr_cmp(&attr_name, miscstatusW))
1598  {
1599  entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1600  }
1601  else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1602  {
1603  entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1604  }
1605  else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1606  {
1607  entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1608  }
1609  else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1610  {
1611  entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1612  }
1613  else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1614  {
1615  entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1616  }
1617  else if (xmlstr_cmp(&attr_name, descriptionW))
1618  {
1619  /* not stored */
1620  }
1621  else
1622  {
1623  attr_nameU = xmlstr2unicode(&attr_name);
1624  attr_valueU = xmlstr2unicode(&attr_value);
1625  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1626  }
1627  }
1628 
1629  if (error) return FALSE;
1630 
1632  if (entity->u.comclass.progid)
1634 
1635  if (end) return TRUE;
1636 
1637  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1638  {
1639  if (xmlstr_cmp_end(&elem, comClassW))
1640  {
1641  ret = parse_end_element(xmlbuf);
1642  break;
1643  }
1644  else if (xmlstr_cmp(&elem, progidW))
1645  {
1646  ret = parse_com_class_progid(xmlbuf, entity);
1647  }
1648  else
1649  {
1650  attr_nameU = xmlstr2unicode(&elem);
1651  DPRINT1("unknown elem %wZ\n", &attr_nameU);
1652  ret = parse_unknown_elem(xmlbuf, &elem);
1653  }
1654  }
1655 
1656  if (entity->u.comclass.progids.num)
1658 
1659  return ret;
1660 }
1661 
1663 {
1664  const WCHAR *curr;
1665  ULONG num = 0;
1666 
1667  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1668  {
1669  if (*curr >= '0' && *curr <= '9')
1670  num = num * 10 + *curr - '0';
1671  else
1672  {
1674  DPRINT1("wrong numeric value %wZ\n", &strU);
1675  return FALSE;
1676  }
1677  }
1678  entity->u.ifaceps.nummethods = num;
1679 
1680  return TRUE;
1681 }
1682 
1684 {
1685  xmlstr_t attr_name, attr_value;
1686  BOOL end = FALSE, error;
1687  struct entity* entity;
1688  UNICODE_STRING attr_valueU, attr_nameU;
1689 
1690  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1691  return FALSE;
1692 
1693  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1694  {
1695  if (xmlstr_cmp(&attr_name, iidW))
1696  {
1697  if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1698  }
1699  else if (xmlstr_cmp(&attr_name, g_nameW))
1700  {
1701  if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1702  }
1703  else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1704  {
1705  if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1706  entity->u.ifaceps.mask |= BaseIface;
1707  }
1708  else if (xmlstr_cmp(&attr_name, nummethodsW))
1709  {
1710  if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1711  entity->u.ifaceps.mask |= NumMethods;
1712  }
1713  else if (xmlstr_cmp(&attr_name, tlbidW))
1714  {
1715  if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1716  }
1717  /* not used */
1718  else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1719  {
1720  }
1721  else
1722  {
1723  attr_nameU = xmlstr2unicode(&attr_name);
1724  attr_valueU = xmlstr2unicode(&attr_value);
1725  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1726  }
1727  }
1728 
1729  if (error) return FALSE;
1731  if (end) return TRUE;
1732 
1734 }
1735 
1737 {
1738  WORD *flags = &entity->u.typelib.flags;
1739  const WCHAR *str = value->ptr, *start;
1740  int i = 0;
1741 
1742  *flags = 0;
1743 
1744  /* it's comma separated list of flags */
1745  while (i < value->len)
1746  {
1747  start = str;
1748  while (*str != ',' && (i++ < value->len)) str++;
1749 
1751  *flags |= LIBFLAG_FRESTRICTED;
1752  else if (!strncmpiW(start, controlW, str-start))
1753  *flags |= LIBFLAG_FCONTROL;
1754  else if (!strncmpiW(start, hiddenW, str-start))
1755  *flags |= LIBFLAG_FHIDDEN;
1756  else if (!strncmpiW(start, hasdiskimageW, str-start))
1757  *flags |= LIBFLAG_FHASDISKIMAGE;
1758  else
1759  {
1761  DPRINT1("unknown flags value %wZ\n", &valueU);
1762  return FALSE;
1763  }
1764 
1765  /* skip separator */
1766  str++;
1767  i++;
1768  }
1769 
1770  return TRUE;
1771 }
1772 
1774 {
1775  unsigned int ver[2];
1776  unsigned int pos;
1777  const WCHAR *curr;
1779 
1780  /* major.minor */
1781  ver[0] = ver[1] = pos = 0;
1782  for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1783  {
1784  if (*curr >= '0' && *curr <= '9')
1785  {
1786  ver[pos] = ver[pos] * 10 + *curr - '0';
1787  if (ver[pos] >= 0x10000) goto error;
1788  }
1789  else if (*curr == '.')
1790  {
1791  if (++pos >= 2) goto error;
1792  }
1793  else goto error;
1794  }
1795  entity->u.typelib.major = ver[0];
1796  entity->u.typelib.minor = ver[1];
1797  return TRUE;
1798 
1799 error:
1800  strW = xmlstr2unicode(str);
1801  DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
1802  return FALSE;
1803 }
1804 
1805 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1806 {
1807  xmlstr_t attr_name, attr_value;
1808  BOOL end = FALSE, error;
1809  struct entity* entity;
1810  UNICODE_STRING attr_valueU, attr_nameU;
1811 
1812  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1813  return FALSE;
1814 
1815  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1816  {
1817  if (xmlstr_cmp(&attr_name, tlbidW))
1818  {
1819  if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1820  }
1821  else if (xmlstr_cmp(&attr_name, versionW))
1822  {
1823  if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1824  }
1825  else if (xmlstr_cmp(&attr_name, helpdirW))
1826  {
1827  if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1828  }
1829  else if (xmlstr_cmp(&attr_name, flagsW))
1830  {
1831  if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1832  }
1833  else
1834  {
1835  attr_nameU = xmlstr2unicode(&attr_name);
1836  attr_valueU = xmlstr2unicode(&attr_value);
1837  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1838  }
1839  }
1840 
1841  if (error) return FALSE;
1842 
1844 
1845  if (end) return TRUE;
1846 
1847  return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1848 }
1849 
1850 static inline int aligned_string_len(int len)
1851 {
1852  return (len + 3) & ~3;
1853 }
1854 
1856 {
1857  static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1858  struct assembly_version *ver = &assembly->id.version;
1859  WCHAR buff[25];
1860 
1861  if (!ret) ret = buff;
1862  return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1863 }
1864 
1866 {
1867  xmlstr_t elem, content, attr_name, attr_value;
1868  BOOL end = FALSE, ret = TRUE, error;
1869  struct entity* entity;
1870  UNICODE_STRING elemU, attr_nameU, attr_valueU;
1871 
1872  if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1873  return FALSE;
1874 
1875  entity->u.class.versioned = TRUE;
1876  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1877  {
1878  if (xmlstr_cmp(&attr_name, versionedW))
1879  {
1880  if (xmlstr_cmpi(&attr_value, noW))
1881  entity->u.class.versioned = FALSE;
1882  else if (!xmlstr_cmpi(&attr_value, yesW))
1883  return FALSE;
1884  }
1885  else
1886  {
1887  attr_nameU = xmlstr2unicode(&attr_name);
1888  attr_valueU = xmlstr2unicode(&attr_value);
1889  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1890  }
1891  }
1892 
1893  if (error || end) return end;
1894 
1895  if (!parse_text_content(xmlbuf, &content)) return FALSE;
1896 
1897  if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1898 
1900 
1901  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1902  {
1904  {
1905  ret = parse_end_element(xmlbuf);
1906  break;
1907  }
1908  else
1909  {
1910  elemU = xmlstr2unicode(&elem);
1911  DPRINT1("unknown elem %wZ\n", &elemU);
1912  ret = parse_unknown_elem(xmlbuf, &elem);
1913  }
1914  }
1915 
1916  return ret;
1917 }
1918 
1920 {
1921  xmlstr_t attr_name, attr_value;
1922  UNICODE_STRING attr_valueU, attr_nameU;
1923  BOOL end = FALSE, error;
1924 
1925  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1926  {
1927  attr_nameU = xmlstr2unicode(&attr_name);
1928  attr_valueU = xmlstr2unicode(&attr_value);
1929 
1930  if (xmlstr_cmp(&attr_name, oldVersionW))
1931  {
1932  DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
1933  }
1934  else if (xmlstr_cmp(&attr_name, newVersionW))
1935  {
1936  DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
1937  }
1938  else
1939  {
1940  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1941  }
1942  }
1943 
1944  if (error || end) return end;
1946 }
1947 
1949 {
1950  xmlstr_t elem, content, attr_name, attr_value;
1951  BOOL end = FALSE, ret = TRUE, error = FALSE;
1952 
1953  UNICODE_STRING elem1U, elem2U;
1954 
1955  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1956  {
1957  elem1U = xmlstr2unicode(&attr_name);
1958  elem2U = xmlstr2unicode(&attr_value);
1959  DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
1960  }
1961 
1962  if (error) return FALSE;
1963  if (end) return TRUE;
1964 
1965  if (!parse_text_content(xmlbuf, &content))
1966  return FALSE;
1967 
1968  elem1U = xmlstr2unicode(&content);
1969  DPRINT("Got description %wZ\n", &elem1U);
1970 
1971  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1972  {
1974  {
1975  ret = parse_end_element(xmlbuf);
1976  break;
1977  }
1978  else
1979  {
1980  elem1U = xmlstr2unicode(&elem);
1981  DPRINT1("unknown elem %wZ\n", &elem1U);
1982  ret = parse_unknown_elem(xmlbuf, &elem);
1983  }
1984  }
1985 
1986  return ret;
1987 }
1988 
1990  struct assembly* assembly,
1991  struct actctx_loader* acl)
1992 {
1993  xmlstr_t attr_name, attr_value;
1994  UNICODE_STRING attr_nameU, attr_valueU;
1995  BOOL end = FALSE, error;
1996  struct entity* entity;
1997 
1998  entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1999  if (!entity) return FALSE;
2000 
2001  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2002  {
2003  if (xmlstr_cmp(&attr_name, iidW))
2004  {
2005  if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
2006  }
2007  else if (xmlstr_cmp(&attr_name, g_nameW))
2008  {
2009  if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
2010  }
2011  else if (xmlstr_cmp(&attr_name, baseInterfaceW))
2012  {
2013  if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
2014  entity->u.ifaceps.mask |= BaseIface;
2015  }
2016  else if (xmlstr_cmp(&attr_name, nummethodsW))
2017  {
2018  if (!(parse_nummethods(&attr_value, entity))) return FALSE;
2019  entity->u.ifaceps.mask |= NumMethods;
2020  }
2021  else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
2022  {
2023  if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
2024  }
2025  else if (xmlstr_cmp(&attr_name, tlbidW))
2026  {
2027  if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
2028  }
2029  else
2030  {
2031  attr_nameU = xmlstr2unicode(&attr_name);
2032  attr_valueU = xmlstr2unicode(&attr_value);
2033  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2034  }
2035  }
2036 
2037  if (error) return FALSE;
2039  if (end) return TRUE;
2040 
2042 }
2043 
2044 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2045 {
2046  xmlstr_t attr_name, attr_value, elem;
2047  BOOL end = FALSE, error, ret = TRUE;
2048  struct entity* entity;
2049 
2050  entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
2051  if (!entity) return FALSE;
2052 
2053  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2054  {
2055  if (xmlstr_cmp(&attr_name, g_nameW))
2056  {
2057  if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
2058  }
2059  else if (xmlstr_cmp(&attr_name, clsidW))
2060  {
2061  if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
2062  }
2063  else if (xmlstr_cmp(&attr_name, progidW))
2064  {
2065  if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
2066  }
2067  else if (xmlstr_cmp(&attr_name, tlbidW))
2068  {
2069  if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
2070  }
2071  else if (xmlstr_cmp(&attr_name, threadingmodelW))
2072  {
2073  entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
2074  }
2075  else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2076  {
2077  if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
2078  }
2079  else
2080  {
2081  UNICODE_STRING attr_nameU, attr_valueU;
2082  attr_nameU = xmlstr2unicode(&attr_name);
2083  attr_valueU = xmlstr2unicode(&attr_value);
2084  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2085  }
2086  }
2087 
2088  if (error) return FALSE;
2090  if (entity->u.comclass.progid)
2092  if (end) return TRUE;
2093 
2094  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2095  {
2096  if (xmlstr_cmp_end(&elem, clrClassW))
2097  {
2098  ret = parse_end_element(xmlbuf);
2099  break;
2100  }
2101  else if (xmlstr_cmp(&elem, progidW))
2102  {
2103  ret = parse_com_class_progid(xmlbuf, entity);
2104  }
2105  else
2106  {
2108  DPRINT1("unknown elem %wZ\n", &elemU);
2109  ret = parse_unknown_elem(xmlbuf, &elem);
2110  }
2111  }
2112 
2113  if (entity->u.comclass.progids.num)
2115 
2116  return ret;
2117 }
2118 
2120 {
2121  xmlstr_t attr_name, attr_value;
2122  UNICODE_STRING attr_nameU, attr_valueU;
2123  BOOL end = FALSE, error;
2124  struct entity* entity;
2125 
2126  entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2127  if (!entity) return FALSE;
2128 
2129  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2130  {
2131  if (xmlstr_cmp(&attr_name, g_nameW))
2132  {
2133  if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2134  }
2135  else if (xmlstr_cmp(&attr_name, clsidW))
2136  {
2137  if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2138  }
2139  else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2140  {
2141  if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2142  }
2143  else
2144  {
2145  attr_nameU = xmlstr2unicode(&attr_name);
2146  attr_valueU = xmlstr2unicode(&attr_value);
2147  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2148  }
2149  }
2150 
2151  if (error) return FALSE;
2153  if (end) return TRUE;
2154 
2155  return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2156 }
2157 
2159 {
2160  struct assembly_identity ai;
2161  xmlstr_t elem, attr_name, attr_value;
2162  BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2163 
2164  UNICODE_STRING elem1U, elem2U;
2165 
2166  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2167  {
2168  static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2169  static const WCHAR trueW[] = {'t','r','u','e',0};
2170 
2171  if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2172  delayed = xmlstr_cmp(&attr_value, trueW);
2173  else
2174  {
2175  elem1U = xmlstr2unicode(&attr_name);
2176  elem2U = xmlstr2unicode(&attr_value);
2177  DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
2178  }
2179  }
2180 
2181  if (error || end) return end;
2182 
2183  memset(&ai, 0, sizeof(ai));
2184  ai.optional = optional;
2185  ai.delayed = delayed;
2186 
2187  if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2188  !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2189  return FALSE;
2190 
2191  //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2192 
2193  /* store the newly found identity for later loading */
2194  if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2195 
2196  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2197  {
2199  {
2200  ret = parse_end_element(xmlbuf);
2201  break;
2202  }
2203  else if (xmlstr_cmp(&elem, bindingRedirectW))
2204  {
2205  ret = parse_binding_redirect_elem(xmlbuf);
2206  }
2207  else
2208  {
2209  DPRINT1("unknown elem %S\n", elem.ptr);
2210  ret = parse_unknown_elem(xmlbuf, &elem);
2211  }
2212  }
2213 
2214  return ret;
2215 }
2216 
2217 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2218 {
2219  xmlstr_t attr_name, attr_value, elem;
2220  UNICODE_STRING attr_nameU, attr_valueU;
2221  BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2222 
2223  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2224  {
2225  attr_nameU = xmlstr2unicode(&attr_name);
2226  attr_valueU = xmlstr2unicode(&attr_value);
2227 
2228  if (xmlstr_cmp(&attr_name, optionalW))
2229  {
2230  optional = xmlstr_cmpi( &attr_value, yesW );
2231  DPRINT1("optional=%wZ\n", &attr_valueU);
2232  }
2233  else
2234  {
2235  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2236  }
2237  }
2238 
2239  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2240  {
2242  {
2243  ret = parse_end_element(xmlbuf);
2244  break;
2245  }
2246  else if (xmlstr_cmp(&elem, dependentAssemblyW))
2247  {
2248  ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2249  }
2250  else
2251  {
2252  attr_nameU = xmlstr2unicode(&elem);
2253  DPRINT1("unknown element %wZ\n", &attr_nameU);
2254  ret = parse_unknown_elem(xmlbuf, &elem);
2255  }
2256  }
2257 
2258  return ret;
2259 }
2260 
2262 {
2263  BOOL end = FALSE;
2264 
2265  if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2266  return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2267 }
2268 
2270 {
2271  BOOL end = FALSE;
2272 
2273  if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2274  return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2275 }
2276 
2277 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2278 {
2279  xmlstr_t attr_name, attr_value, elem;
2280  UNICODE_STRING attr_nameU, attr_valueU;
2281  BOOL end = FALSE, error, ret = TRUE;
2282  struct dll_redirect* dll;
2283 
2284  if (!(dll = add_dll_redirect(assembly))) return FALSE;
2285 
2286  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2287  {
2288  attr_nameU = xmlstr2unicode(&attr_name);
2289  attr_valueU = xmlstr2unicode(&attr_value);
2290 
2291  if (xmlstr_cmp(&attr_name, g_nameW))
2292  {
2293  if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2294  DPRINT("name=%wZ\n", &attr_valueU);
2295  }
2296  else if (xmlstr_cmp(&attr_name, hashW))
2297  {
2298  if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2299  }
2300  else if (xmlstr_cmp(&attr_name, hashalgW))
2301  {
2302  static const WCHAR sha1W[] = {'S','H','A','1',0};
2303  if (!xmlstr_cmpi(&attr_value, sha1W))
2304  DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
2305  }
2306  else
2307  {
2308  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2309  }
2310  }
2311 
2312  if (error || !dll->name) return FALSE;
2313 
2315 
2316  if (end) return TRUE;
2317 
2318  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2319  {
2320  if (xmlstr_cmp_end(&elem, fileW))
2321  {
2322  ret = parse_end_element(xmlbuf);
2323  break;
2324  }
2325  else if (xmlstr_cmp(&elem, comClassW))
2326  {
2327  ret = parse_com_class_elem(xmlbuf, dll, acl);
2328  }
2330  {
2331  ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2332  }
2333  else if (xml_elem_cmp(&elem, hashW, asmv2W))
2334  {
2335  DPRINT1("asmv2hash (undocumented) not supported\n");
2336  ret = parse_unknown_elem(xmlbuf, &elem);
2337  }
2338  else if (xmlstr_cmp(&elem, typelibW))
2339  {
2340  ret = parse_typelib_elem(xmlbuf, dll, acl);
2341  }
2342  else if (xmlstr_cmp(&elem, windowClassW))
2343  {
2344  ret = parse_window_class_elem(xmlbuf, dll, acl);
2345  }
2346  else
2347  {
2348  attr_nameU = xmlstr2unicode(&elem);
2349  DPRINT1("unknown elem %wZ\n", &attr_nameU);
2350  ret = parse_unknown_elem( xmlbuf, &elem );
2351  }
2352  }
2353 
2354  return ret;
2355 }
2356 
2358 {
2359  xmlstr_t attr_name, attr_value;
2360  BOOL end = FALSE, error;
2361 
2362  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2363  {
2364  if (xmlstr_cmp(&attr_name, IdW))
2365  {
2366  COMPATIBILITY_CONTEXT_ELEMENT *compat;
2368  GUID compat_id;
2369 
2370  str.Buffer = (PWSTR)attr_value.ptr;
2371  str.Length = str.MaximumLength = (USHORT)attr_value.len * sizeof(WCHAR);
2372  if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2373  {
2374  if (!(compat = add_compat_context(assembly))) return FALSE;
2375  compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2376  compat->Id = compat_id;
2377  }
2378  else
2379  {
2380  UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value);
2381  DPRINT1("Invalid guid %wZ\n", &attr_valueU);
2382  }
2383  }
2384  else
2385  {
2386  UNICODE_STRING attr_nameU = xmlstr2unicode(&attr_name);
2387  UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value);
2388  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2389  }
2390  }
2391 
2392  if (error) return FALSE;
2393  if (end) return TRUE;
2394 
2395  return parse_expect_end_elem(xmlbuf, supportedOSW, asmv1W);
2396 }
2397 
2399  struct actctx_loader* acl)
2400 {
2401  BOOL ret = TRUE;
2402  xmlstr_t elem;
2403 
2404  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2405  {
2407  {
2408  ret = parse_end_element(xmlbuf);
2409  break;
2410  }
2411  else if (xmlstr_cmp(&elem, supportedOSW))
2412  {
2413  ret = parse_supportedos_elem(xmlbuf, assembly, acl);
2414  }
2415  else
2416  {
2418  DPRINT1("unknown elem %wZ\n", &elemU);
2419  ret = parse_unknown_elem(xmlbuf, &elem);
2420  }
2421  }
2422 
2423  return ret;
2424 }
2425 
2427  struct actctx_loader* acl)
2428 {
2429  xmlstr_t elem;
2430  BOOL ret = TRUE;
2431 
2432  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2433  {
2435  {
2436  ret = parse_end_element(xmlbuf);
2437  break;
2438  }
2439  else if (xmlstr_cmp(&elem, applicationW))
2440  {
2442  }
2443  else
2444  {
2446  DPRINT1("unknown elem %wZ\n", &elemU);
2447  ret = parse_unknown_elem(xmlbuf, &elem);
2448  }
2449  }
2450  return ret;
2451 }
2452 
2454 {
2455  static const WCHAR levelW[] = {'l','e','v','e','l',0};
2456  static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2457  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};
2458  static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2459  static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2460  static const WCHAR falseW[] = {'f','a','l','s','e',0};
2461  static const WCHAR trueW[] = {'t','r','u','e',0};
2462 
2463  xmlstr_t attr_name, attr_value, elem;
2464  BOOL end = FALSE, ret = TRUE, error;
2465 
2466  /* Multiple requestedExecutionLevel elements are not supported. */
2467  if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED)
2468  return FALSE;
2469 
2470  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2471  {
2472  UNICODE_STRING attr_nameU = xmlstr2unicode(&attr_name);
2473  UNICODE_STRING attr_valueU = xmlstr2unicode(&attr_value);
2474  if (xmlstr_cmp(&attr_name, levelW))
2475  {
2476  if (xmlstr_cmpi(&attr_value, asInvokerW))
2477  assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2478  else if (xmlstr_cmpi(&attr_value, highestAvailableW))
2479  assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2480  else if (xmlstr_cmpi(&attr_value, requireAdministratorW))
2481  assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2482  else
2483  DPRINT1("unknown execution level: %wZ\n", &attr_valueU);
2484  }
2485  else if (xmlstr_cmp(&attr_name, uiAccessW))
2486  {
2487  if (xmlstr_cmpi(&attr_value, falseW))
2489  else if (xmlstr_cmpi(&attr_value, trueW))
2490  assembly->ui_access = TRUE;
2491  else
2492  DPRINT1("unknown uiAccess value: %wZ\n", &attr_valueU);
2493  }
2494  else
2495  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2496  }
2497 
2498  if (error) return FALSE;
2499  if (end) return TRUE;
2500 
2501  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2502  {
2504  {
2505  ret = parse_end_element(xmlbuf);
2506  break;
2507  }
2508  else
2509  {
2511  DPRINT1("unknown element %wZ\n", &elemU);
2512  ret = parse_unknown_elem(xmlbuf, &elem);
2513  }
2514  }
2515 
2516  return ret;
2517 }
2518 
2520 {
2521  xmlstr_t elem;
2522  BOOL ret = TRUE;
2523 
2524  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2525  {
2527  {
2528  ret = parse_end_element(xmlbuf);
2529  break;
2530  }
2533  else
2534  {
2536  DPRINT1("unknown elem %wZ\n", &elemU);
2537  ret = parse_unknown_elem(xmlbuf, &elem);
2538  }
2539  }
2540 
2541  return ret;
2542 }
2543 
2544 static BOOL parse_security_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2545 {
2546  xmlstr_t elem;
2547  BOOL ret = TRUE;
2548 
2549  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2550  {
2552  {
2553  ret = parse_end_element(xmlbuf);
2554  break;
2555  }
2558  else
2559  {
2561  DPRINT1("unknown elem %wZ\n", &elemU);
2562  ret = parse_unknown_elem(xmlbuf, &elem);
2563  }
2564  }
2565 
2566  return ret;
2567 }
2568 
2569 static BOOL parse_trust_info_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2570 {
2571  xmlstr_t elem;
2572  BOOL ret = TRUE;
2573 
2574  while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2575  {
2577  {
2578  ret = parse_end_element(xmlbuf);
2579  break;
2580  }
2581  else if (xml_elem_cmp(&elem, securityW, asmv2W))
2582  ret = parse_security_elem(xmlbuf, assembly, acl);
2583  else
2584  {
2586  DPRINT1("unknown elem %wZ\n", &elemU);
2587  ret = parse_unknown_elem(xmlbuf, &elem);
2588  }
2589  }
2590 
2591  return ret;
2592 }
2593 
2594 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2595  struct assembly* assembly,
2596  struct assembly_identity* expected_ai)
2597 {
2598  xmlstr_t attr_name, attr_value, elem;
2599  UNICODE_STRING attr_nameU, attr_valueU;
2600  BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2601 
2602  DPRINT("(%p)\n", xmlbuf);
2603 
2604  while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2605  {
2606  attr_nameU = xmlstr2unicode(&attr_name);
2607  attr_valueU = xmlstr2unicode(&attr_value);
2608 
2609  if (xmlstr_cmp(&attr_name, manifestVersionW))
2610  {
2611  static const WCHAR v10W[] = {'1','.','0',0};
2612  if (!xmlstr_cmp(&attr_value, v10W))
2613  {
2614  DPRINT1("wrong version %wZ\n", &attr_valueU);
2615  return FALSE;
2616  }
2617  version = TRUE;
2618  }
2619  else if (xmlstr_cmp(&attr_name, xmlnsW))
2620  {
2621  if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2622  !xmlstr_cmp(&attr_value, manifestv2W) &&
2623  !xmlstr_cmp(&attr_value, manifestv3W))
2624  {
2625  DPRINT1("wrong namespace %wZ\n", &attr_valueU);
2626  return FALSE;
2627  }
2628  xmlns = TRUE;
2629  }
2630  else
2631  {
2632  DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2633  }
2634  }
2635 
2636  if (error || end || !xmlns || !version) return FALSE;
2637  if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2638 
2640  {
2641  if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2642  return FALSE;
2644  }
2645 
2647  {
2648  if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2649  return FALSE;
2650  }
2653  return FALSE;
2654 
2655  while (ret)
2656  {
2658  {
2659  ret = parse_end_element(xmlbuf);
2660  break;
2661  }
2662  else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2663  {
2664  ret = parse_description_elem(xmlbuf);
2665  }
2667  {
2669  }
2670  else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2671  {
2672  ret = parse_dependency_elem(xmlbuf, acl);
2673  }
2674  else if (xml_elem_cmp(&elem, fileW, asmv1W))
2675  {
2676  ret = parse_file_elem(xmlbuf, assembly, acl);
2677  }
2678  else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2679  {
2680  ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2681  }
2682  else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2683  {
2684  ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2685  }
2686  else if (xml_elem_cmp(&elem, trustInfoW, asmv2W) ||
2688  {
2689  ret = parse_trust_info_elem(xmlbuf, assembly, acl);
2690  }
2692  {
2693  if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2694 
2695  if (expected_ai)
2696  {
2697  /* FIXME: more tests */
2698  if (assembly->type == ASSEMBLY_MANIFEST &&
2699  memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2700  {
2701  DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2702  expected_ai->version.major, expected_ai->version.minor,
2703  expected_ai->version.build, expected_ai->version.revision,
2704  assembly->id.version.major, assembly->id.version.minor,
2705  assembly->id.version.build, assembly->id.version.revision);
2706  ret = FALSE;
2707  }
2708  else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2709  (assembly->id.version.major != expected_ai->version.major ||
2710  assembly->id.version.minor != expected_ai->version.minor ||
2711  assembly->id.version.build < expected_ai->version.build ||
2712  (assembly->id.version.build == expected_ai->version.build &&
2713  assembly->id.version.revision < expected_ai->version.revision)))
2714  {
2715  DPRINT1("wrong version for shared assembly manifest\n");
2716  ret = FALSE;
2717  }
2718  }
2719  }
2721  {
2722  ret = parse_compatibility_elem(xmlbuf, assembly, acl);
2723  }
2724  else
2725  {
2726  attr_nameU = xmlstr2unicode(&elem);
2727  DPRINT1("unknown element %wZ\n", &attr_nameU);
2728  ret = parse_unknown_elem(xmlbuf, &elem);
2729  }
2730  if (ret) ret = next_xml_elem(xmlbuf, &elem);
2731  }
2732 
2733  return ret;
2734 }
2735 
2737  struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2738 {
2739  xmlstr_t elem;
2740  UNICODE_STRING elemU;
2741 
2742  if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2743 
2744  if (xmlstr_cmp(&elem, g_xmlW) &&
2745  (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2747 
2748  if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2749  {
2750  elemU = xmlstr2unicode(&elem);
2751  DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
2753  }
2754 
2755  if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2756  {
2757  DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
2759  }
2760 
2761  if (next_xml_elem(xmlbuf, &elem))
2762  {
2763  elemU = xmlstr2unicode(&elem);
2764  DPRINT1("unexpected element %wZ\n", &elemU);
2766  }
2767 
2768  if (xmlbuf->ptr != xmlbuf->end)
2769  {
2770  DPRINT1("parse error\n");
2772  }
2773  return STATUS_SUCCESS;
2774 }
2775 
2776 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2778  const void *buffer, SIZE_T size )
2779 {
2780  xmlbuf_t xmlbuf;
2781  NTSTATUS status;
2782  struct assembly *assembly;
2783  int unicode_tests;
2784 
2785  DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2786 
2789 
2791  return STATUS_NO_MEMORY;
2792 
2793  if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2794  assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2795  : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2796 
2798  if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2799  {
2800  xmlbuf.ptr = buffer;
2801  xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2802  status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2803  }
2804  else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2805  {
2806  const WCHAR *buf = buffer;
2807  WCHAR *new_buff;
2808  unsigned int i;
2809 
2810  if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2811  return STATUS_NO_MEMORY;
2812  for (i = 0; i < size / sizeof(WCHAR); i++)
2813  new_buff[i] = RtlUshortByteSwap( buf[i] );
2814  xmlbuf.ptr = new_buff;
2815  xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2816  status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2817  RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2818  }
2819  else
2820  {
2821  /* TODO: this doesn't handle arbitrary encodings */
2822  WCHAR *new_buff;
2823  ULONG sizeU;
2824 
2826  if (!NT_SUCCESS(status))
2827  {
2828  DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2830  }
2831 
2832  new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2833  if (!new_buff)
2834  return STATUS_NO_MEMORY;
2835 
2836  status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2837  if (!NT_SUCCESS(status))
2838  {
2839  DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2841  }
2842 
2843  xmlbuf.ptr = new_buff;
2844  xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2845  status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2846  RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2847  }
2848  return status;
2849 }
2850 
2852 {
2855 
2856  attr.Length = sizeof(attr);
2857  attr.RootDirectory = 0;
2858  attr.Attributes = OBJ_CASE_INSENSITIVE;
2859  attr.ObjectName = name;
2860  attr.SecurityDescriptor = NULL;
2861  attr.SecurityQualityOfService = NULL;
2863 }
2864 
2866 {
2867  NTSTATUS status;
2868  ULONG_PTR magic;
2869  LDR_DATA_TABLE_ENTRY *pldr;
2870 
2872  status = LdrFindEntryForAddress( module, &pldr );
2873  if (status == STATUS_SUCCESS)
2874  {
2875  if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2876  pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2877  {
2878  memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2879  str->Length = pldr->FullDllName.Length;
2880  str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2881  }
2882  else status = STATUS_NO_MEMORY;
2883  }
2885  return status;
2886 }
2887 
2890  HANDLE hModule, LPCWSTR resname, ULONG lang )
2891 {
2892  NTSTATUS status;
2896  void *ptr;
2897 
2898  //DPRINT( "looking for res %s in module %p %s\n", resname,
2899  // hModule, filename );
2900  DPRINT("get_manifest_in_module %p\n", hModule);
2901 
2902 #if 0
2903  if (TRACE_ON(actctx))
2904  {
2905  if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2906  {
2907  DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2908  hModule, debugstr_w(nameW.Buffer) );
2910  }
2911  else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2913  }
2914 #endif
2915 
2916  if (!resname) return STATUS_INVALID_PARAMETER;
2917 
2918  info.Type = (ULONG_PTR)RT_MANIFEST;
2919  info.Language = lang;
2920  if (!((ULONG_PTR)resname >> 16))
2921  {
2922  info.Name = (ULONG_PTR)resname;
2924  }
2925  else if (resname[0] == '#')
2926  {
2927  ULONG value;
2928  RtlInitUnicodeString(&nameW, resname + 1);
2930  return STATUS_INVALID_PARAMETER;
2931  info.Name = value;
2933  }
2934  else
2935  {
2936  RtlCreateUnicodeString(&nameW, resname);
2938  info.Name = (ULONG_PTR)nameW.Buffer;
2941  }
2943 
2944  if (status == STATUS_SUCCESS)
2945  status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2946 
2947  return status;
2948 }
2949 
2951  LPCWSTR name, void *root,
2952  int want_dir );
2953 
2955  void *root, int want_dir );
2956 
2957 
2959  void *root, int want_dir )
2960 {
2962  int pos;
2963 
2964  for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
2965  {
2966  if (!entry[pos].DataIsDirectory == !want_dir)
2967  return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
2968  }
2969  return NULL;
2970 }
2971 
2972 
2976 {
2977  ULONG size;
2978  PVOID root, ptr;
2979  IMAGE_RESOURCE_DIRECTORY *resdirptr;
2981  NTSTATUS status;
2982 
2984  if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
2985  if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
2986  resdirptr = root;
2987 
2988  if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1)))
2990 
2991  resdirptr = ptr;
2992  if (!(ptr = find_first_id_entry(resdirptr, root, 1)))
2994 
2995  resdirptr = ptr;
2996  if (!(ptr = find_first_entry(resdirptr, root, 0)))
2998 
2999  entry = ptr;
3001 
3002  if (status == STATUS_SUCCESS)
3003  status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
3004 
3005  return status;
3006 }
3007 
3008 
3011  HANDLE file, LPCWSTR resname, ULONG lang )
3012 {
3013  HANDLE mapping;
3017  NTSTATUS status;
3018  SIZE_T count;
3019  void *base;
3020  WCHAR resnameBuf[20];
3021  LPCWSTR resptr = resname;
3022 
3023  if ((!((ULONG_PTR)resname >> 16)))
3024  {
3025  sprintfW(resnameBuf, L"#%u", PtrToUlong(resname));
3026  resptr = resnameBuf;
3027  }
3028 
3029  DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>");
3030 
3031  attr.Length = sizeof(attr);
3032  attr.RootDirectory = 0;
3033  attr.ObjectName = NULL;
3034  attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3035  attr.SecurityDescriptor = NULL;
3036  attr.SecurityQualityOfService = NULL;
3037 
3038  size.QuadPart = 0;
3041  if (status != STATUS_SUCCESS) return status;
3042 
3043  offset.QuadPart = 0;
3044  count = 0;
3045  base = NULL;
3047  &count, ViewShare, 0, PAGE_READONLY );
3048  NtClose( mapping );
3049  if (status != STATUS_SUCCESS) return status;
3050 
3051  if (RtlImageNtHeader(base)) /* we got a PE file */
3052  {
3053  HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3054  if (resname)
3055  status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3056  else
3058  }
3060 
3062  return status;
3063 }
3064 
3067 {
3070  HANDLE mapping;
3074  NTSTATUS status;
3075  SIZE_T count;
3076  void *base;
3077 
3078  DPRINT( "loading manifest file %S\n", filename );
3079 
3080  attr.Length = sizeof(attr);
3081  attr.RootDirectory = 0;
3082  attr.ObjectName = NULL;
3083  attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3084  attr.SecurityDescriptor = NULL;
3085  attr.SecurityQualityOfService = NULL;
3086 
3087  size.QuadPart = 0;
3090 
3091  if (status != STATUS_SUCCESS) return status;
3092 
3093  offset.QuadPart = 0;
3094  count = 0;
3095  base = NULL;
3097  &count, ViewShare, 0, PAGE_READONLY );
3098  NtClose( mapping );
3099  if (status != STATUS_SUCCESS) return status;
3100 
3101  /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
3103 
3104  if (status == STATUS_SUCCESS)
3105  status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
3106 
3108  return status;
3109 }
3110 
3111 /* try to load the .manifest file associated to the file */
3114 {
3115  static const WCHAR fmtW[] = { '.','%','l','u',0 };
3116  WCHAR *buffer;
3117  NTSTATUS status;
3119  HANDLE file;
3121 
3122  if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3123 
3124  DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
3125 
3126  if (module) /* use the module filename */
3127  {
3129 
3130  if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3131  {
3132  if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3133  strcatW( name.Buffer, dotManifestW );
3134  if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3137  }
3138  if (status) return status;
3139  }
3140  else
3141  {
3142  if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3143  (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3144  return STATUS_NO_MEMORY;
3145  strcpyW( buffer, filename );
3146  if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3149  }
3150 
3151  if (!open_nt_file( &file, &nameW ))
3152  {
3154  NtClose( file );
3155  }
3158  return status;
3159 }
3160 
3162 {
3163  static const WCHAR lookup_fmtW[] =
3164  {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3165  '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3166  static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3167 
3168  WCHAR *lookup, *ret = NULL;
3169  UNICODE_STRING lookup_us;
3171  const WCHAR *lang = ai->language;
3172  unsigned int data_pos = 0, data_len;
3173  char buffer[8192];
3174 
3175  if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3176  (strlenW(ai->arch) + strlenW(ai->name)
3177  + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
3178  + sizeof(lookup_fmtW) )))
3179  return NULL;
3180 
3181  if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3182  sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3183  ai->version.major, ai->version.minor, lang );
3184  RtlInitUnicodeString( &lookup_us, lookup );
3185 
3186  if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3187  FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3188  {
3189  ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3190  FILE_BOTH_DIR_INFORMATION *dir_info;
3191  WCHAR *tmp;
3192  ULONG build, revision;
3193 
3194  data_len = (ULONG)io.Information;
3195 
3196  for (;;)
3197  {
3198  if (data_pos >= data_len)
3199  {
3200  if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3201  FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3202  break;
3203  data_len = (ULONG)io.Information;
3204  data_pos = 0;
3205  }
3206  dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3207 
3208  if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3209  else data_pos = data_len;
3210 
3211  tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
3212  build = atoiW(tmp);
3213  if (build < min_build) continue;
3214  tmp = strchrW(tmp, '.') + 1;
3215  revision = atoiW(tmp);
3216  if (build == min_build && revision < min_revision) continue;
3217  tmp = strchrW(tmp, '_') + 1;
3218  tmp = strchrW(tmp, '_') + 1;
3219  if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3220  !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3221  {
3222  /* prefer a non-Wine manifest if we already have one */
3223  /* we'll still load the builtin dll if specified through DllOverrides */
3224  if (ret) continue;
3225  }
3226  else
3227  {
3228  min_build = build;
3229  min_revision = revision;
3230  }
3231  ai->version.build = build;
3232  ai->version.revision = revision;
3233  RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
3234  if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3235  {
3236  memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3237  ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3238  }
3239  }
3240  }
3241  else DPRINT1("no matching file for %S\n", lookup);
3242  RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
3243  return ret;
3244 }
3245 
3247 {
3248  struct assembly_identity sxs_ai;
3249  UNICODE_STRING path_us;
3252  WCHAR *path, *file = NULL;
3253  HANDLE handle;
3254 
3255  static const WCHAR manifest_dirW[] =
3256  {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3257 
3258  if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3259 
3260  if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3261  ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
3262  return STATUS_NO_MEMORY;
3263 
3264  memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
3265  memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
3266 
3267  if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3268  {
3269  RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3270  return STATUS_NO_SUCH_FILE;
3271  }
3272  RtlFreeHeap( RtlGetProcessHeap(), 0, path );
3273 
3274  attr.Length = sizeof(attr);
3275  attr.RootDirectory = 0;
3276  attr.Attributes = OBJ_CASE_INSENSITIVE;
3277  attr.ObjectName = &path_us;
3278  attr.SecurityDescriptor = NULL;
3279  attr.SecurityQualityOfService = NULL;
3280 
3283  {
3284  sxs_ai = *ai;
3285  file = lookup_manifest_file( handle, &sxs_ai );
3286  NtClose( handle );
3287  }
3288  if (!file)
3289  {
3290  RtlFreeUnicodeString( &path_us );
3291  return STATUS_NO_SUCH_FILE;
3292  }
3293 
3294  /* append file name to directory path */
3295  if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
3296  path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3297  {
3298  RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3299  RtlFreeUnicodeString( &path_us );
3300  return STATUS_NO_MEMORY;
3301  }
3302 
3303  path[path_us.Length/sizeof(WCHAR)] = '\\';
3304  strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3305  RtlInitUnicodeString( &path_us, path );
3306  *strrchrW(file, '.') = 0; /* remove .manifest extension */
3307 
3308  if (!open_nt_file( &handle, &path_us ))
3309  {
3310  io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3311  NtClose( handle );
3312  }
3313  else io.Status = STATUS_NO_SUCH_FILE;
3314 
3315  RtlFreeHeap( RtlGetProcessHeap(), 0, file );
3316  RtlFreeUnicodeString( &path_us );
3317  return io.Status;
3318 }
3319 
3321  struct assembly_identity* ai)
3322 {
3323  static const WCHAR dotDllW[] = {'.','d','l','l',0};
3324  unsigned int i;
3325  WCHAR *buffer, *p, *directory;
3326  NTSTATUS status;
3328  HANDLE file;
3329  DWORD len;
3330 
3331  DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
3332  ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
3333 
3334  if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3335 
3336  /* FIXME: add support for language specific lookup */
3337 
3338  len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3339  strlenW(acl->actctx->appdir.info));
3340 
3341  nameW.Buffer = NULL;
3342  if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3343  (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3344  return STATUS_NO_MEMORY;
3345 
3346  if (!(directory = build_assembly_dir( ai )))
3347  {
3348  RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3349  return STATUS_NO_MEMORY;
3350  }
3351 
3352  /* Lookup in <dir>\name.dll
3353  * <dir>\name.manifest
3354  * <dir>\name\name.dll
3355  * <dir>\name\name.manifest
3356  *
3357  * First 'appdir' is used as <dir>, if that failed
3358  * it tries application manifest file path.
3359  */
3360  strcpyW( buffer, acl->actctx->appdir.info );
3361  p = buffer + strlenW(buffer);
3362  for (i = 0; i < 4; i++)
3363  {
3364  if (i == 2)
3365  {
3366  struct assembly *assembly = acl->actctx->assemblies;
3367  if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3368  }
3369  else *p++ = '\\';
3370 
3371  strcpyW( p, ai->name );
3372  p += strlenW(p);
3373 
3374  strcpyW( p, dotDllW );
3376  {
3377  status = open_nt_file( &file, &nameW );
3378  if (!status)
3379  {
3380  status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3381  (LPCWSTR)0, 0 );
3382  NtClose( file );
3383  break;
3384  }
3386  }
3387 
3388  strcpyW( p, dotManifestW );
3390  {
3391  status = open_nt_file( &file, &nameW );
3392  if (!status)
3393  {
3395  NtClose( file );
3396  break;
3397  }
3399  }
3401  }
3403  RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
3404  RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3405  return status;
3406 }
3407 
3409 {
3411  unsigned int i;
3412 
3413  for (i = 0; i < acl->num_dependencies; i++)
3414  {
3415  if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3416  {
3417  if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3418  {
3419  const struct assembly_version *ver = &acl->dependencies[i].version;
3420  DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3421  acl->dependencies[i].name,
3422  ver->major, ver->minor, ver->build, ver->revision );
3424  break;
3425  }
3426  }
3427  }
3428  /* FIXME should now iterate through all refs */
3429  return status;
3430 }
3431 
3432 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3434 {
3436 
3438  {
3439  if (*handle) return STATUS_INVALID_PARAMETER;
3440 
3441  if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
3442  *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
3443  }
3445  {
3446  ULONG_PTR magic;
3447  LDR_DATA_TABLE_ENTRY *pldr;
3448 
3449  if (!*handle) return STATUS_INVALID_PARAMETER;
3450 
3451  LdrLockLoaderLock( 0, NULL, &magic );
3452  if (!LdrFindEntryForAddress( *handle, &pldr ))
3453  {
3456  else
3458  }
3460  LdrUnlockLoaderLock( 0, magic );
3461  }
3462  else if (!*handle && (class != ActivationContextBasicInformation))
3464 
3465  return status;
3466 }
3467 
3469 {
3470  unsigned int i, j, total_len = 0, dll_count = 0;
3471  struct strsection_header *header;
3472  struct dllredirect_data *data;
3473  struct string_index *index;
3475 
3476  DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies);
3477 
3478  /* compute section length */
3479  for (i = 0; i < actctx->num_assemblies; i++)
3480  {
3481  struct assembly *assembly = &actctx->assemblies[i];
3482  for (j = 0; j < assembly->num_dlls; j++)
3483  {
3484  struct dll_redirect *dll = &assembly->dlls[j];
3485 
3486  /* each entry needs index, data and string data */
3487  total_len += sizeof(*index);
3488  total_len += sizeof(*data);
3489  total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3490 
3491  DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name);
3492  }
3493 
3495  }
3496 
3497  total_len += sizeof(*header);
3498 
3499  header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3500  if (!header) return STATUS_NO_MEMORY;
3501 
3502  memset(header, 0, sizeof(*header));
3503  header->magic = STRSECTION_MAGIC;
3504  header->size = sizeof(*header);
3505  header->count = dll_count;
3506  header->index_offset = sizeof(*header);
3507  index = (struct string_index*)((BYTE*)header + header->index_offset);
3508  name_offset = header->index_offset + header->count*sizeof(*index);
3509 
3510  for (i = 0; i < actctx->num_assemblies; i++)
3511  {
3512  struct assembly *assembly = &actctx->assemblies[i];
3513 
3514  DPRINT("assembly->num_dlls %d\n", assembly->num_dlls);
3515 
3516  for (j = 0; j < assembly->num_dlls; j++)
3517  {
3518  struct dll_redirect *dll = &assembly->dlls[j];
3520  WCHAR *ptrW;
3521 
3522  DPRINT("%d: dll name %S\n", j, dll->name);
3523  /* setup new index entry */
3524