[RTL] Handle RtlReAllocateHeap failure in com_class_add_progid. CID 1223161
[reactos.git] / sdk / lib / rtl / actctx.c
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 Staging 1.7.37 */
16
17 #include <rtl.h>
18
19 #define NDEBUG
20 #include <debug.h>
21
22 #include <wine/unicode.h>
23
24 BOOLEAN RtlpNotAllowingMultipleActivation;
25
26 #define ACTCTX_FLAGS_ALL (\
27 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
28 ACTCTX_FLAG_LANGID_VALID |\
29 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
30 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
31 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
32 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
33 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
34 ACTCTX_FLAG_HMODULE_VALID )
35
36 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
37 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
38
39 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
40
41 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
42 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
43
44
45
46 typedef struct
47 {
48 const WCHAR *ptr;
49 unsigned int len;
50 } xmlstr_t;
51
52 typedef struct
53 {
54 const WCHAR *ptr;
55 const WCHAR *end;
56 } xmlbuf_t;
57
58 struct file_info
59 {
60 ULONG type;
61 WCHAR *info;
62 };
63
64 struct assembly_version
65 {
66 USHORT major;
67 USHORT minor;
68 USHORT build;
69 USHORT revision;
70 };
71
72 struct assembly_identity
73 {
74 WCHAR *name;
75 WCHAR *arch;
76 WCHAR *public_key;
77 WCHAR *language;
78 WCHAR *type;
79 struct assembly_version version;
80 BOOL optional;
81 BOOL delayed;
82 };
83
84 struct strsection_header
85 {
86 DWORD magic;
87 ULONG size;
88 DWORD unk1[3];
89 ULONG count;
90 ULONG index_offset;
91 DWORD unk2[2];
92 ULONG global_offset;
93 ULONG global_len;
94 };
95
96 struct string_index
97 {
98 ULONG hash; /* key string hash */
99 ULONG name_offset;
100 ULONG name_len;
101 ULONG data_offset; /* redirect data offset */
102 ULONG data_len;
103 ULONG rosterindex;
104 };
105
106 struct guidsection_header
107 {
108 DWORD magic;
109 ULONG size;
110 DWORD unk[3];
111 ULONG count;
112 ULONG index_offset;
113 DWORD unk2;
114 ULONG names_offset;
115 ULONG names_len;
116 };
117
118 struct guid_index
119 {
120 GUID guid;
121 ULONG data_offset;
122 ULONG data_len;
123 ULONG rosterindex;
124 };
125
126 struct wndclass_redirect_data
127 {
128 ULONG size;
129 DWORD res;
130 ULONG name_len;
131 ULONG name_offset; /* versioned name offset */
132 ULONG module_len;
133 ULONG module_offset;/* container name offset */
134 };
135
136 struct dllredirect_data
137 {
138 ULONG size;
139 ULONG unk;
140 DWORD res[3];
141 };
142
143 struct tlibredirect_data
144 {
145 ULONG size;
146 DWORD res;
147 ULONG name_len;
148 ULONG name_offset;
149 LANGID langid;
150 WORD flags;
151 ULONG help_len;
152 ULONG help_offset;
153 WORD major_version;
154 WORD minor_version;
155 };
156
157 enum comclass_threadingmodel
158 {
159 ThreadingModel_Apartment = 1,
160 ThreadingModel_Free = 2,
161 ThreadingModel_No = 3,
162 ThreadingModel_Both = 4,
163 ThreadingModel_Neutral = 5
164 };
165
166 enum comclass_miscfields
167 {
168 MiscStatus = 1,
169 MiscStatusIcon = 2,
170 MiscStatusContent = 4,
171 MiscStatusThumbnail = 8,
172 MiscStatusDocPrint = 16
173 };
174
175 struct comclassredirect_data
176 {
177 ULONG size;
178 BYTE res;
179 BYTE miscmask;
180 BYTE res1[2];
181 DWORD model;
182 GUID clsid;
183 GUID alias;
184 GUID clsid2;
185 GUID tlbid;
186 ULONG name_len;
187 ULONG name_offset;
188 ULONG progid_len;
189 ULONG progid_offset;
190 ULONG clrdata_len;
191 ULONG clrdata_offset;
192 DWORD miscstatus;
193 DWORD miscstatuscontent;
194 DWORD miscstatusthumbnail;
195 DWORD miscstatusicon;
196 DWORD miscstatusdocprint;
197 };
198
199 enum ifaceps_mask
200 {
201 NumMethods = 1,
202 BaseIface = 2
203 };
204
205 struct ifacepsredirect_data
206 {
207 ULONG size;
208 DWORD mask;
209 GUID iid;
210 ULONG nummethods;
211 GUID tlbid;
212 GUID base;
213 ULONG name_len;
214 ULONG name_offset;
215 };
216
217 struct clrsurrogate_data
218 {
219 ULONG size;
220 DWORD res;
221 GUID clsid;
222 ULONG version_offset;
223 ULONG version_len;
224 ULONG name_offset;
225 ULONG name_len;
226 };
227
228 struct clrclass_data
229 {
230 ULONG size;
231 DWORD res[2];
232 ULONG module_len;
233 ULONG module_offset;
234 ULONG name_len;
235 ULONG name_offset;
236 ULONG version_len;
237 ULONG version_offset;
238 DWORD res2[2];
239 };
240
241 struct progidredirect_data
242 {
243 ULONG size;
244 DWORD reserved;
245 ULONG clsid_offset;
246 };
247
248 /*
249
250 Sections structure.
251
252 Sections are accessible by string or guid key, that defines two types of sections.
253 All sections of each type have same magic value and header structure, index
254 data could be of two possible types too. So every string based section uses
255 the same index format, same applies to guid sections - they share same guid index
256 format.
257
258 - window class redirection section is a plain buffer with following format:
259
260 <section header>
261 <index[]>
262 <data[]> --- <original name>
263 <redirect data>
264 <versioned name>
265 <module name>
266
267 Header is fixed length structure - struct strsection_header,
268 contains redirected classes count;
269
270 Index is an array of fixed length index records, each record is
271 struct string_index.
272
273 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
274
275 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
276 others are relative to section itself.
277
278 - dll redirect section format:
279
280 <section header>
281 <index[]>
282 <data[]> --- <dll name>
283 <data>
284
285 This section doesn't seem to carry any payload data except dll names.
286
287 - typelib section format:
288
289 <section header>
290 <module names[]>
291 <index[]>
292 <data[]> --- <data>
293 <helpstring>
294
295 Header is fixed length, index is an array of fixed length 'struct guid_index'.
296 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
297 4-bytes aligned as a whole.
298
299 Module name offsets are relative to section, helpstring offset is relative to data
300 structure itself.
301
302 - comclass section format:
303
304 <section header>
305 <module names[]>
306 <index[]>
307 <data[]> --- <data> --- <data>
308 <progid> <clrdata>
309 <name>
310 <version>
311 <progid>
312
313 This section uses two index records per comclass, one entry contains original guid
314 as specified by context, another one has a generated guid. Index and strings handling
315 is similar to typelib sections.
316
317 For CLR classes additional data is stored after main COM class data, it contains
318 class name and runtime version string, see 'struct clrclass_data'.
319
320 Module name offsets are relative to section, progid offset is relative to data
321 structure itself.
322
323 - COM interface section format:
324
325 <section header>
326 <index[]>
327 <data[]> --- <data>
328 <name>
329
330 Interface section contains data for proxy/stubs and external proxy/stubs. External
331 ones are defined at assembly level, so this section has no module information.
332 All records are indexed with 'iid' value from manifest. There an exception for
333 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
334 redirect data, but index is still 'iid' from manifest.
335
336 Interface name offset is relative to data structure itself.
337
338 - CLR surrogates section format:
339
340 <section header>
341 <index[]>
342 <data[]> --- <data>
343 <name>
344 <version>
345
346 There's nothing special about this section, same way to store strings is used,
347 no modules part as it belongs to assembly level, not a file.
348
349 - ProgID section format:
350
351 <section header>
352 <guids[]>
353 <index[]>
354 <data[]> --- <progid>
355 <data>
356
357 This sections uses generated alias guids from COM server section. This way
358 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
359 is stored too, aligned.
360 */
361
362 struct progids
363 {
364 WCHAR **progids;
365 unsigned int num;
366 unsigned int allocated;
367 };
368
369 struct entity
370 {
371 DWORD kind;
372 union
373 {
374 struct
375 {
376 WCHAR *tlbid;
377 WCHAR *helpdir;
378 WORD flags;
379 WORD major;
380 WORD minor;
381 } typelib;
382 struct
383 {
384 WCHAR *clsid;
385 WCHAR *tlbid;
386 WCHAR *progid;
387 WCHAR *name; /* clrClass: class name */
388 WCHAR *version; /* clrClass: CLR runtime version */
389 DWORD model;
390 DWORD miscstatus;
391 DWORD miscstatuscontent;
392 DWORD miscstatusthumbnail;
393 DWORD miscstatusicon;
394 DWORD miscstatusdocprint;
395 struct progids progids;
396 } comclass;
397 struct {
398 WCHAR *iid;
399 WCHAR *base;
400 WCHAR *tlib;
401 WCHAR *name;
402 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
403 DWORD mask;
404 ULONG nummethods;
405 } ifaceps;
406 struct
407 {
408 WCHAR *name;
409 BOOL versioned;
410 } class;
411 struct
412 {
413 WCHAR *name;
414 WCHAR *clsid;
415 WCHAR *version;
416 } clrsurrogate;
417 } u;
418 };
419
420 struct entity_array
421 {
422 struct entity *base;
423 unsigned int num;
424 unsigned int allocated;
425 };
426
427 struct dll_redirect
428 {
429 WCHAR *name;
430 WCHAR *hash;
431 struct entity_array entities;
432 };
433
434 enum assembly_type
435 {
436 APPLICATION_MANIFEST,
437 ASSEMBLY_MANIFEST,
438 ASSEMBLY_SHARED_MANIFEST,
439 };
440
441 struct assembly
442 {
443 enum assembly_type type;
444 struct assembly_identity id;
445 struct file_info manifest;
446 WCHAR *directory;
447 BOOL no_inherit;
448 struct dll_redirect *dlls;
449 unsigned int num_dlls;
450 unsigned int allocated_dlls;
451 struct entity_array entities;
452 };
453
454 enum context_sections
455 {
456 WINDOWCLASS_SECTION = 1,
457 DLLREDIRECT_SECTION = 2,
458 TLIBREDIRECT_SECTION = 4,
459 SERVERREDIRECT_SECTION = 8,
460 IFACEREDIRECT_SECTION = 16,
461 CLRSURROGATES_SECTION = 32,
462 PROGIDREDIRECT_SECTION = 64
463 };
464
465 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
466 {
467 ULONG Flags;
468 UNICODE_STRING DosPath;
469 HANDLE Handle;
470 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;
471
472 typedef struct _ASSEMBLY_STORAGE_MAP
473 {
474 ULONG Flags;
475 ULONG AssemblyCount;
476 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray;
477 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
478
479 typedef struct _ACTIVATION_CONTEXT
480 {
481 LONG RefCount;
482 ULONG Flags;
483 LIST_ENTRY Links;
484 PACTIVATION_CONTEXT_DATA ActivationContextData;
485 PVOID NotificationRoutine;
486 PVOID NotificationContext;
487 ULONG SentNotifications[8];
488 ULONG DisabledNotifications[8];
489 ASSEMBLY_STORAGE_MAP StorageMap;
490 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries;
491 ULONG StackTraceIndex;
492 PVOID StackTraces[4][4];
493 struct file_info config;
494 struct file_info appdir;
495 struct assembly *assemblies;
496 unsigned int num_assemblies;
497 unsigned int allocated_assemblies;
498 /* section data */
499 DWORD sections;
500 struct strsection_header *wndclass_section;
501 struct strsection_header *dllredirect_section;
502 struct strsection_header *progid_section;
503 struct guidsection_header *tlib_section;
504 struct guidsection_header *comserver_section;
505 struct guidsection_header *ifaceps_section;
506 struct guidsection_header *clrsurrogate_section;
507 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
508
509 struct actctx_loader
510 {
511 ACTIVATION_CONTEXT *actctx;
512 struct assembly_identity *dependencies;
513 unsigned int num_dependencies;
514 unsigned int allocated_dependencies;
515 };
516
517 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
518 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
519
520 typedef struct _ACTIVATION_CONTEXT_WRAPPED
521 {
522 PVOID MagicMarker;
523 ACTIVATION_CONTEXT ActivationContext;
524 } ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED;
525
526 VOID
527 NTAPI
528 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx,
529 IN ULONG FailureCode)
530 {
531 EXCEPTION_RECORD ExceptionRecord;
532
533 /* Fatal SxS exception header */
534 ExceptionRecord.ExceptionRecord = NULL;
535 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
536 ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
537
538 /* With SxS-specific information plus the context itself */
539 ExceptionRecord.ExceptionInformation[0] = 1;
540 ExceptionRecord.ExceptionInformation[1] = FailureCode;
541 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
542 ExceptionRecord.NumberParameters = 3;
543
544 /* Raise it */
545 RtlRaiseException(&ExceptionRecord);
546 }
547
548 FORCEINLINE
549 VOID
550 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx)
551 {
552 PACTIVATION_CONTEXT_WRAPPED pActual;
553
554 /* Get the caller-opaque header */
555 pActual = CONTAINING_RECORD(ActCtx,
556 ACTIVATION_CONTEXT_WRAPPED,
557 ActivationContext);
558
559 /* Check if the header matches as expected */
560 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
561 {
562 /* Nope, print out a warning, assert, and then throw an exception */
563 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
564 " This means someone stepped on the allocation, or someone is using a\n"
565 " deallocated activation context\n",
566 __FUNCTION__,
567 pActual->MagicMarker,
568 ActCtx);
569 ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER);
570 RtlpSxsBreakOnInvalidMarker(ActCtx, 1);
571 }
572 }
573
574 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
575 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
576 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
577 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
578 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
579 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
580 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};
581 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};
582 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
583 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
584 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
585 static const WCHAR fileW[] = {'f','i','l','e',0};
586 static const WCHAR hashW[] = {'h','a','s','h',0};
587 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
588 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
589 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
590 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
591
592 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
593 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
594 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
595 static const WCHAR iidW[] = {'i','i','d',0};
596 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
597 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
598 static const WCHAR g_nameW[] = {'n','a','m','e',0};
599 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
600 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
601 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
602 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
603 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};
604 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
605 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
606 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
607 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
608 static const WCHAR typeW[] = {'t','y','p','e',0};
609 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
610 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
611 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
612 static const WCHAR yesW[] = {'y','e','s',0};
613 static const WCHAR noW[] = {'n','o',0};
614 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
615 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
616 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
617 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
618 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
619 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
620 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
621 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
622 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
623 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
624 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
625 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
626 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
627 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
628 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
629 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
630
631 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
632 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
633 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
634 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
635 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
636 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
637 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
638 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};
639 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
640 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
641 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
642 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
643 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
644 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
645 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
646 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
647 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};
648 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
649 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
650 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
651 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};
652 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
653
654 struct olemisc_entry
655 {
656 const WCHAR *name;
657 OLEMISC value;
658 };
659
660 static const struct olemisc_entry olemisc_values[] =
661 {
662 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
663 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
664 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
665 { alignableW, OLEMISC_ALIGNABLE },
666 { alwaysrunW, OLEMISC_ALWAYSRUN },
667 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
668 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
669 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
670 { imemodeW, OLEMISC_IMEMODE },
671 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
672 { insideoutW, OLEMISC_INSIDEOUT },
673 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
674 { islinkobjectW, OLEMISC_ISLINKOBJECT },
675 { nouiactivateW, OLEMISC_NOUIACTIVATE },
676 { onlyiconicW, OLEMISC_ONLYICONIC },
677 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
678 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
679 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
680 { simpleframeW, OLEMISC_SIMPLEFRAME },
681 { staticW, OLEMISC_STATIC },
682 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
683 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
684 };
685
686 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
687 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};
688 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};
689 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};
690
691 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
692 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
693 static const WCHAR wildcardW[] = {'*',0};
694
695 static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } };
696 static ACTIVATION_CONTEXT *process_actctx = &system_actctx.ActivationContext;
697
698 static WCHAR *strdupW(const WCHAR* str)
699 {
700 WCHAR* ptr;
701
702 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
703 return NULL;
704 return strcpyW(ptr, str);
705 }
706
707 static WCHAR *xmlstrdupW(const xmlstr_t* str)
708 {
709 WCHAR *strW;
710
711 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
712 {
713 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
714 strW[str->len] = 0;
715 }
716 return strW;
717 }
718
719 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
720 {
721 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
722 }
723
724 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
725 {
726 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
727 }
728
729 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
730 {
731 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
732 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
733 }
734
735 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
736 {
737 UINT len = strlenW( namespace );
738
739 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
740 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
741 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
742 }
743
744 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
745 {
746 if (elem->len && elem->ptr[0] == '/')
747 {
748 xmlstr_t elem_end;
749 elem_end.ptr = elem->ptr + 1;
750 elem_end.len = elem->len - 1;
751 return xml_elem_cmp( &elem_end, str, namespace );
752 }
753 return FALSE;
754 }
755
756 static inline BOOL isxmlspace( WCHAR ch )
757 {
758 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
759 }
760
761 static UNICODE_STRING xmlstr2unicode(const xmlstr_t *xmlstr)
762 {
763 UNICODE_STRING res;
764
765 res.Buffer = (PWSTR)xmlstr->ptr;
766 res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR);
767
768 return res;
769 }
770
771 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
772 {
773 struct assembly *assembly;
774
775 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
776
777 if (actctx->num_assemblies == actctx->allocated_assemblies)
778 {
779 void *ptr;
780 unsigned int new_count;
781 if (actctx->assemblies)
782 {
783 new_count = actctx->allocated_assemblies * 2;
784 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
785 actctx->assemblies, new_count * sizeof(*assembly) );
786 }
787 else
788 {
789 new_count = 4;
790 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
791 }
792 if (!ptr) return NULL;
793 actctx->assemblies = ptr;
794 actctx->allocated_assemblies = new_count;
795 }
796
797 assembly = &actctx->assemblies[actctx->num_assemblies++];
798 assembly->type = at;
799 return assembly;
800 }
801
802 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
803 {
804 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
805
806 if (assembly->num_dlls == assembly->allocated_dlls)
807 {
808 void *ptr;
809 unsigned int new_count;
810 if (assembly->dlls)
811 {
812 new_count = assembly->allocated_dlls * 2;
813 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
814 assembly->dlls, new_count * sizeof(*assembly->dlls) );
815 }
816 else
817 {
818 new_count = 4;
819 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
820 }
821 if (!ptr) return NULL;
822 assembly->dlls = ptr;
823 assembly->allocated_dlls = new_count;
824 }
825 return &assembly->dlls[assembly->num_dlls++];
826 }
827
828 static void free_assembly_identity(struct assembly_identity *ai)
829 {
830 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
831 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
832 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
833 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
834 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
835 }
836
837 static struct entity* add_entity(struct entity_array *array, DWORD kind)
838 {
839 struct entity* entity;
840
841 if (array->num == array->allocated)
842 {
843 void *ptr;
844 unsigned int new_count;
845 if (array->base)
846 {
847 new_count = array->allocated * 2;
848 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
849 array->base, new_count * sizeof(*array->base) );
850 }
851 else
852 {
853 new_count = 4;
854 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
855 }
856 if (!ptr) return NULL;
857 array->base = ptr;
858 array->allocated = new_count;
859 }
860 entity = &array->base[array->num++];
861 entity->kind = kind;
862 return entity;
863 }
864
865 static void free_entity_array(struct entity_array *array)
866 {
867 unsigned int i, j;
868 for (i = 0; i < array->num; i++)
869 {
870 struct entity *entity = &array->base[i];
871 switch (entity->kind)
872 {
873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
874 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
875 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
876 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
877 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
879 for (j = 0; j < entity->u.comclass.progids.num; j++)
880 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
881 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
882 break;
883 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
884 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
885 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
886 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
887 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
888 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
889 break;
890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
891 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
892 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
893 break;
894 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
895 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
896 break;
897 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
898 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
899 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
900 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
901 break;
902 default:
903 DPRINT1("Unknown entity kind %u\n", entity->kind);
904 }
905 }
906 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
907 }
908
909 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
910 {
911 if (!str1) return !str2;
912 return str2 && !strcmpiW( str1, str2 );
913 }
914
915 static BOOL is_matching_identity( const struct assembly_identity *id1,
916 const struct assembly_identity *id2 )
917 {
918 if (!is_matching_string( id1->name, id2->name )) return FALSE;
919 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
920 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
921
922 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
923 {
924 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
925 return FALSE;
926 }
927 if (id1->version.major != id2->version.major) return FALSE;
928 if (id1->version.minor != id2->version.minor) return FALSE;
929 if (id1->version.build > id2->version.build) return FALSE;
930 if (id1->version.build == id2->version.build &&
931 id1->version.revision > id2->version.revision) return FALSE;
932 return TRUE;
933 }
934
935 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
936 struct assembly_identity* ai)
937 {
938 unsigned int i;
939
940 /* check if we already have that assembly */
941
942 for (i = 0; i < acl->actctx->num_assemblies; i++)
943 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
944 {
945 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
946 ai->name, ai->arch, ai->version.major, ai->version.minor,
947 ai->version.build, ai->version.revision );
948 return TRUE;
949 }
950
951 for (i = 0; i < acl->num_dependencies; i++)
952 if (is_matching_identity( ai, &acl->dependencies[i] ))
953 {
954 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
955 ai->name, ai->arch, ai->version.major, ai->version.minor,
956 ai->version.build, ai->version.revision );
957 return TRUE;
958 }
959
960 if (acl->num_dependencies == acl->allocated_dependencies)
961 {
962 void *ptr;
963 unsigned int new_count;
964 if (acl->dependencies)
965 {
966 new_count = acl->allocated_dependencies * 2;
967 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
968 new_count * sizeof(acl->dependencies[0]));
969 }
970 else
971 {
972 new_count = 4;
973 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
974 }
975 if (!ptr) return FALSE;
976 acl->dependencies = ptr;
977 acl->allocated_dependencies = new_count;
978 }
979 acl->dependencies[acl->num_dependencies++] = *ai;
980
981 return TRUE;
982 }
983
984 static void free_depend_manifests(struct actctx_loader* acl)
985 {
986 unsigned int i;
987 for (i = 0; i < acl->num_dependencies; i++)
988 free_assembly_identity(&acl->dependencies[i]);
989 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
990 }
991
992 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
993 {
994 static const WCHAR undW[] = {'_',0};
995 static const WCHAR noneW[] = {'n','o','n','e',0};
996 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
997
998 const WCHAR *arch = ai->arch ? ai->arch : noneW;
999 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1000 const WCHAR *lang = ai->language ? ai->language : noneW;
1001 const WCHAR *name = ai->name ? ai->name : noneW;
1002 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1003 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1004 WCHAR *ret;
1005
1006 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1007
1008 strcpyW( ret, arch );
1009 strcatW( ret, undW );
1010 strcatW( ret, name );
1011 strcatW( ret, undW );
1012 strcatW( ret, key );
1013 strcatW( ret, undW );
1014 sprintfW( ret + strlenW(ret), version_formatW,
1015 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1016 strcatW( ret, undW );
1017 strcatW( ret, lang );
1018 strcatW( ret, undW );
1019 strcatW( ret, mskeyW );
1020 return ret;
1021 }
1022
1023 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1024 {
1025 WCHAR *p = buffer;
1026
1027 if (!str) return;
1028 strcatW( buffer, prefix );
1029 p += strlenW(p);
1030 *p++ = '"';
1031 strcpyW( p, str );
1032 p += strlenW(p);
1033 *p++ = '"';
1034 *p = 0;
1035 }
1036
1037 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1038 {
1039 static const WCHAR archW[] =
1040 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1041 static const WCHAR public_keyW[] =
1042 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1043 static const WCHAR typeW2[] =
1044 {',','t','y','p','e','=',0};
1045 static const WCHAR versionW2[] =
1046 {',','v','e','r','s','i','o','n','=',0};
1047
1048 WCHAR version[64], *ret;
1049 SIZE_T size = 0;
1050
1051 sprintfW( version, version_formatW,
1052 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1053 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1054 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1055 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1056 if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1057 size += strlenW(versionW2) + strlenW(version) + 2;
1058
1059 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1060 return NULL;
1061
1062 if (ai->name) strcpyW( ret, ai->name );
1063 else *ret = 0;
1064 append_string( ret, archW, ai->arch );
1065 append_string( ret, public_keyW, ai->public_key );
1066 append_string( ret, typeW2, ai->type );
1067 append_string( ret, versionW2, version );
1068 return ret;
1069 }
1070
1071 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1072 {
1073 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1074 PACTIVATION_CONTEXT_WRAPPED pActual;
1075
1076 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1077 _SEH2_TRY
1078 {
1079 if (actctx)
1080 {
1081 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1082 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1083 }
1084 }
1085 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1086 {
1087 DPRINT1("Invalid activation context handle!\n");
1088 }
1089 _SEH2_END;
1090 return ret;
1091 }
1092
1093 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1094 {
1095 InterlockedExchangeAdd( &actctx->RefCount, 1 );
1096 }
1097
1098 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1099 {
1100 PACTIVATION_CONTEXT_WRAPPED pActual;
1101
1102 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1103 {
1104 unsigned int i, j;
1105
1106 for (i = 0; i < actctx->num_assemblies; i++)
1107 {
1108 struct assembly *assembly = &actctx->assemblies[i];
1109 for (j = 0; j < assembly->num_dlls; j++)
1110 {
1111 struct dll_redirect *dll = &assembly->dlls[j];
1112 free_entity_array( &dll->entities );
1113 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1114 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1115 }
1116 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1117 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1118 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1119 free_entity_array( &assembly->entities );
1120 free_assembly_identity(&assembly->id);
1121 }
1122 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1123 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1124 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1125 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1126 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1127 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1128 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1129 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1130 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1131 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1132
1133 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1134 pActual->MagicMarker = 0;
1135 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1136 }
1137 }
1138
1139 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1140 BOOL* error, BOOL* end)
1141 {
1142 const WCHAR* ptr;
1143
1144 *error = TRUE;
1145
1146 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1147 xmlbuf->ptr++;
1148
1149 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1150
1151 if (*xmlbuf->ptr == '/')
1152 {
1153 xmlbuf->ptr++;
1154 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1155 return FALSE;
1156
1157 xmlbuf->ptr++;
1158 *end = TRUE;
1159 *error = FALSE;
1160 return FALSE;
1161 }
1162
1163 if (*xmlbuf->ptr == '>')
1164 {
1165 xmlbuf->ptr++;
1166 *error = FALSE;
1167 return FALSE;
1168 }
1169
1170 ptr = xmlbuf->ptr;
1171 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1172
1173 if (ptr == xmlbuf->end) return FALSE;
1174
1175 name->ptr = xmlbuf->ptr;
1176 name->len = ptr-xmlbuf->ptr;
1177 xmlbuf->ptr = ptr;
1178
1179 /* skip spaces before '=' */
1180 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1181 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1182
1183 /* skip '=' itself */
1184 ptr++;
1185 if (ptr == xmlbuf->end) return FALSE;
1186
1187 /* skip spaces after '=' */
1188 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1189
1190 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1191
1192 value->ptr = ++ptr;
1193 if (ptr == xmlbuf->end) return FALSE;
1194
1195 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1196 if (!ptr)
1197 {
1198 xmlbuf->ptr = xmlbuf->end;
1199 return FALSE;
1200 }
1201
1202 value->len = ptr - value->ptr;
1203 xmlbuf->ptr = ptr + 1;
1204
1205 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1206
1207 *error = FALSE;
1208 return TRUE;
1209 }
1210
1211 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1212 {
1213 const WCHAR* ptr;
1214
1215 for (;;)
1216 {
1217 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1218 if (!ptr)
1219 {
1220 xmlbuf->ptr = xmlbuf->end;
1221 return FALSE;
1222 }
1223 ptr++;
1224 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1225 {
1226 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1227 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1228
1229 if (ptr + 3 > xmlbuf->end)
1230 {
1231 xmlbuf->ptr = xmlbuf->end;
1232 return FALSE;
1233 }
1234 xmlbuf->ptr = ptr + 3;
1235 }
1236 else break;
1237 }
1238
1239 xmlbuf->ptr = ptr;
1240 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1241 ptr++;
1242
1243 elem->ptr = xmlbuf->ptr;
1244 elem->len = ptr - xmlbuf->ptr;
1245 xmlbuf->ptr = ptr;
1246 return xmlbuf->ptr != xmlbuf->end;
1247 }
1248
1249 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1250 {
1251 /* FIXME: parse attributes */
1252 const WCHAR *ptr;
1253
1254 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1255 {
1256 if (ptr[0] == '?' && ptr[1] == '>')
1257 {
1258 xmlbuf->ptr = ptr + 2;
1259 return TRUE;
1260 }
1261 }
1262 return FALSE;
1263 }
1264
1265 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1266 {
1267 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1268
1269 if (!ptr) return FALSE;
1270
1271 content->ptr = xmlbuf->ptr;
1272 content->len = ptr - xmlbuf->ptr;
1273 xmlbuf->ptr = ptr;
1274
1275 return TRUE;
1276 }
1277
1278 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1279 {
1280 unsigned int ver[4];
1281 unsigned int pos;
1282 const WCHAR *curr;
1283 UNICODE_STRING strU;
1284
1285 /* major.minor.build.revision */
1286 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1287 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1288 {
1289 if (*curr >= '0' && *curr <= '9')
1290 {
1291 ver[pos] = ver[pos] * 10 + *curr - '0';
1292 if (ver[pos] >= 0x10000) goto error;
1293 }
1294 else if (*curr == '.')
1295 {
1296 if (++pos >= 4) goto error;
1297 }
1298 else goto error;
1299 }
1300 version->major = ver[0];
1301 version->minor = ver[1];
1302 version->build = ver[2];
1303 version->revision = ver[3];
1304 return TRUE;
1305
1306 error:
1307 strU = xmlstr2unicode(str);
1308 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU );
1309 return FALSE;
1310 }
1311
1312 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1313 {
1314 xmlstr_t elem;
1315 UNICODE_STRING elemU;
1316 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1317 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1318 elemU = xmlstr2unicode(&elem);
1319 DPRINT1( "unexpected element %wZ\n", &elemU );
1320 return FALSE;
1321 }
1322
1323 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1324 {
1325 xmlstr_t attr_name, attr_value;
1326 UNICODE_STRING attr_nameU, attr_valueU;
1327 BOOL error;
1328
1329 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1330 {
1331 attr_nameU = xmlstr2unicode(&attr_name);
1332 attr_valueU = xmlstr2unicode(&attr_value);
1333 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU,
1334 &attr_valueU);
1335 }
1336 return !error;
1337 }
1338
1339 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1340 {
1341 BOOL end = FALSE;
1342 return parse_expect_no_attr(xmlbuf, &end) && !end;
1343 }
1344
1345 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1346 {
1347 xmlstr_t elem;
1348 UNICODE_STRING elemU;
1349 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1350 if (!xml_elem_cmp_end(&elem, name, namespace))
1351 {
1352 elemU = xmlstr2unicode(&elem);
1353 DPRINT1( "unexpected element %wZ\n", &elemU );
1354 return FALSE;
1355 }
1356 return parse_end_element(xmlbuf);
1357 }
1358
1359 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1360 {
1361 xmlstr_t attr_name, attr_value, elem;
1362 BOOL end = FALSE, error, ret = TRUE;
1363
1364 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1365 if(error || end) return end;
1366
1367 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1368 {
1369 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1370 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1371 break;
1372 else
1373 ret = parse_unknown_elem(xmlbuf, &elem);
1374 }
1375
1376 return ret && parse_end_element(xmlbuf);
1377 }
1378
1379 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1380 struct assembly_identity* ai)
1381 {
1382 xmlstr_t attr_name, attr_value;
1383 BOOL end = FALSE, error;
1384 UNICODE_STRING attr_valueU, attr_nameU;
1385
1386 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1387 {
1388 if (xmlstr_cmp(&attr_name, g_nameW))
1389 {
1390 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1391 }
1392 else if (xmlstr_cmp(&attr_name, typeW))
1393 {
1394 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1395 }
1396 else if (xmlstr_cmp(&attr_name, versionW))
1397 {
1398 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1399 }
1400 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1401 {
1402 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1403 }
1404 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1405 {
1406 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1407 }
1408 else if (xmlstr_cmp(&attr_name, languageW))
1409 {
1410 DPRINT("Unsupported yet language attribute (%.*S)\n",
1411 attr_value.len, attr_value.ptr);
1412 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1413 }
1414 else
1415 {
1416 attr_nameU = xmlstr2unicode(&attr_name);
1417 attr_valueU = xmlstr2unicode(&attr_value);
1418 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1419 }
1420 }
1421
1422 if (error || end) return end;
1423 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1424 }
1425
1426 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1427 {
1428 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1429 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1430 static const WCHAR freeW[] = {'F','r','e','e',0};
1431 static const WCHAR bothW[] = {'B','o','t','h',0};
1432
1433 if (value->len == 0) return ThreadingModel_No;
1434 if (xmlstr_cmp(value, apartW))
1435 return ThreadingModel_Apartment;
1436 else if (xmlstr_cmp(value, freeW))
1437 return ThreadingModel_Free;
1438 else if (xmlstr_cmp(value, bothW))
1439 return ThreadingModel_Both;
1440 else if (xmlstr_cmp(value, neutralW))
1441 return ThreadingModel_Neutral;
1442 else
1443 return ThreadingModel_No;
1444 };
1445
1446 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1447 {
1448 int min, max;
1449
1450 min = 0;
1451 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1452
1453 while (min <= max)
1454 {
1455 int n, c;
1456
1457 n = (min+max)/2;
1458
1459 c = strncmpW(olemisc_values[n].name, str, len);
1460 if (!c && !olemisc_values[n].name[len])
1461 return olemisc_values[n].value;
1462
1463 if (c >= 0)
1464 max = n-1;
1465 else
1466 min = n+1;
1467 }
1468
1469 DPRINT1("unknown flag %S\n", str);
1470 return 0;
1471 }
1472
1473 static DWORD parse_com_class_misc(const xmlstr_t *value)
1474 {
1475 const WCHAR *str = value->ptr, *start;
1476 DWORD flags = 0;
1477 int i = 0;
1478
1479 /* it's comma separated list of flags */
1480 while (i < value->len)
1481 {
1482 start = str;
1483 while (*str != ',' && (i++ < value->len)) str++;
1484
1485 flags |= get_olemisc_value(start, str-start);
1486
1487 /* skip separator */
1488 str++;
1489 i++;
1490 }
1491
1492 return flags;
1493 }
1494
1495 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1496 {
1497 struct progids *progids = &entity->u.comclass.progids;
1498
1499 if (progids->allocated == 0)
1500 {
1501 progids->allocated = 4;
1502 if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1503 }
1504
1505 if (progids->allocated == progids->num)
1506 {
1507 WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1508 2 * progids->allocated * sizeof(WCHAR*));
1509 if (!new_progids) return FALSE;
1510 progids->allocated *= 2;
1511 progids->progids = new_progids;
1512 }
1513
1514 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1515 progids->num++;
1516
1517 return TRUE;
1518 }
1519
1520 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1521 {
1522 xmlstr_t content;
1523 BOOL end = FALSE;
1524
1525 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1526 return FALSE;
1527
1528 if (!com_class_add_progid(&content, entity)) return FALSE;
1529 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1530 }
1531
1532 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1533 {
1534 xmlstr_t elem, attr_name, attr_value;
1535 BOOL ret = TRUE, end = FALSE, error;
1536 struct entity* entity;
1537 UNICODE_STRING attr_valueU, attr_nameU;
1538
1539 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1540 return FALSE;
1541
1542 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1543 {
1544 if (xmlstr_cmp(&attr_name, clsidW))
1545 {
1546 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1547 }
1548 else if (xmlstr_cmp(&attr_name, progidW))
1549 {
1550 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1551 }
1552 else if (xmlstr_cmp(&attr_name, tlbidW))
1553 {
1554 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1555 }
1556 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1557 {
1558 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1559 }
1560 else if (xmlstr_cmp(&attr_name, miscstatusW))
1561 {
1562 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1563 }
1564 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1565 {
1566 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1567 }
1568 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1569 {
1570 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1571 }
1572 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1573 {
1574 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1575 }
1576 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1577 {
1578 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1579 }
1580 else if (xmlstr_cmp(&attr_name, descriptionW))
1581 {
1582 /* not stored */
1583 }
1584 else
1585 {
1586 attr_nameU = xmlstr2unicode(&attr_name);
1587 attr_valueU = xmlstr2unicode(&attr_value);
1588 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1589 }
1590 }
1591
1592 if (error) return FALSE;
1593
1594 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1595 if (entity->u.comclass.progid)
1596 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1597
1598 if (end) return TRUE;
1599
1600 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1601 {
1602 if (xmlstr_cmp_end(&elem, comClassW))
1603 {
1604 ret = parse_end_element(xmlbuf);
1605 break;
1606 }
1607 else if (xmlstr_cmp(&elem, progidW))
1608 {
1609 ret = parse_com_class_progid(xmlbuf, entity);
1610 }
1611 else
1612 {
1613 attr_nameU = xmlstr2unicode(&elem);
1614 DPRINT1("unknown elem %wZ\n", &attr_nameU);
1615 ret = parse_unknown_elem(xmlbuf, &elem);
1616 }
1617 }
1618
1619 if (entity->u.comclass.progids.num)
1620 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1621
1622 return ret;
1623 }
1624
1625 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1626 {
1627 const WCHAR *curr;
1628 ULONG num = 0;
1629
1630 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1631 {
1632 if (*curr >= '0' && *curr <= '9')
1633 num = num * 10 + *curr - '0';
1634 else
1635 {
1636 UNICODE_STRING strU = xmlstr2unicode(str);
1637 DPRINT1("wrong numeric value %wZ\n", &strU);
1638 return FALSE;
1639 }
1640 }
1641 entity->u.ifaceps.nummethods = num;
1642
1643 return TRUE;
1644 }
1645
1646 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1647 {
1648 xmlstr_t attr_name, attr_value;
1649 BOOL end = FALSE, error;
1650 struct entity* entity;
1651 UNICODE_STRING attr_valueU, attr_nameU;
1652
1653 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1654 return FALSE;
1655
1656 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1657 {
1658 if (xmlstr_cmp(&attr_name, iidW))
1659 {
1660 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1661 }
1662 else if (xmlstr_cmp(&attr_name, g_nameW))
1663 {
1664 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1665 }
1666 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1667 {
1668 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1669 entity->u.ifaceps.mask |= BaseIface;
1670 }
1671 else if (xmlstr_cmp(&attr_name, nummethodsW))
1672 {
1673 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1674 entity->u.ifaceps.mask |= NumMethods;
1675 }
1676 else if (xmlstr_cmp(&attr_name, tlbidW))
1677 {
1678 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1679 }
1680 /* not used */
1681 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1682 {
1683 }
1684 else
1685 {
1686 attr_nameU = xmlstr2unicode(&attr_name);
1687 attr_valueU = xmlstr2unicode(&attr_value);
1688 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1689 }
1690 }
1691
1692 if (error) return FALSE;
1693 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1694 if (end) return TRUE;
1695
1696 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1697 }
1698
1699 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1700 {
1701 WORD *flags = &entity->u.typelib.flags;
1702 const WCHAR *str = value->ptr, *start;
1703 int i = 0;
1704
1705 *flags = 0;
1706
1707 /* it's comma separated list of flags */
1708 while (i < value->len)
1709 {
1710 start = str;
1711 while (*str != ',' && (i++ < value->len)) str++;
1712
1713 if (!strncmpiW(start, restrictedW, str-start))
1714 *flags |= LIBFLAG_FRESTRICTED;
1715 else if (!strncmpiW(start, controlW, str-start))
1716 *flags |= LIBFLAG_FCONTROL;
1717 else if (!strncmpiW(start, hiddenW, str-start))
1718 *flags |= LIBFLAG_FHIDDEN;
1719 else if (!strncmpiW(start, hasdiskimageW, str-start))
1720 *flags |= LIBFLAG_FHASDISKIMAGE;
1721 else
1722 {
1723 UNICODE_STRING valueU = xmlstr2unicode(value);
1724 DPRINT1("unknown flags value %wZ\n", &valueU);
1725 return FALSE;
1726 }
1727
1728 /* skip separator */
1729 str++;
1730 i++;
1731 }
1732
1733 return TRUE;
1734 }
1735
1736 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1737 {
1738 unsigned int ver[2];
1739 unsigned int pos;
1740 const WCHAR *curr;
1741 UNICODE_STRING strW;
1742
1743 /* major.minor */
1744 ver[0] = ver[1] = pos = 0;
1745 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1746 {
1747 if (*curr >= '0' && *curr <= '9')
1748 {
1749 ver[pos] = ver[pos] * 10 + *curr - '0';
1750 if (ver[pos] >= 0x10000) goto error;
1751 }
1752 else if (*curr == '.')
1753 {
1754 if (++pos >= 2) goto error;
1755 }
1756 else goto error;
1757 }
1758 entity->u.typelib.major = ver[0];
1759 entity->u.typelib.minor = ver[1];
1760 return TRUE;
1761
1762 error:
1763 strW = xmlstr2unicode(str);
1764 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
1765 return FALSE;
1766 }
1767
1768 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1769 {
1770 xmlstr_t attr_name, attr_value;
1771 BOOL end = FALSE, error;
1772 struct entity* entity;
1773 UNICODE_STRING attr_valueU, attr_nameU;
1774
1775 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1776 return FALSE;
1777
1778 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1779 {
1780 if (xmlstr_cmp(&attr_name, tlbidW))
1781 {
1782 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1783 }
1784 else if (xmlstr_cmp(&attr_name, versionW))
1785 {
1786 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1787 }
1788 else if (xmlstr_cmp(&attr_name, helpdirW))
1789 {
1790 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1791 }
1792 else if (xmlstr_cmp(&attr_name, flagsW))
1793 {
1794 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1795 }
1796 else
1797 {
1798 attr_nameU = xmlstr2unicode(&attr_name);
1799 attr_valueU = xmlstr2unicode(&attr_value);
1800 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1801 }
1802 }
1803
1804 if (error) return FALSE;
1805
1806 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1807
1808 if (end) return TRUE;
1809
1810 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1811 }
1812
1813 static inline int aligned_string_len(int len)
1814 {
1815 return (len + 3) & ~3;
1816 }
1817
1818 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1819 {
1820 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1821 struct assembly_version *ver = &assembly->id.version;
1822 WCHAR buff[25];
1823
1824 if (!ret) ret = buff;
1825 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1826 }
1827
1828 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1829 {
1830 xmlstr_t elem, content, attr_name, attr_value;
1831 BOOL end = FALSE, ret = TRUE, error;
1832 struct entity* entity;
1833 UNICODE_STRING elemU, attr_nameU, attr_valueU;
1834
1835 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1836 return FALSE;
1837
1838 entity->u.class.versioned = TRUE;
1839 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1840 {
1841 if (xmlstr_cmp(&attr_name, versionedW))
1842 {
1843 if (xmlstr_cmpi(&attr_value, noW))
1844 entity->u.class.versioned = FALSE;
1845 else if (!xmlstr_cmpi(&attr_value, yesW))
1846 return FALSE;
1847 }
1848 else
1849 {
1850 attr_nameU = xmlstr2unicode(&attr_name);
1851 attr_valueU = xmlstr2unicode(&attr_value);
1852 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1853 }
1854 }
1855
1856 if (error || end) return end;
1857
1858 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1859
1860 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1861
1862 acl->actctx->sections |= WINDOWCLASS_SECTION;
1863
1864 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1865 {
1866 if (xmlstr_cmp_end(&elem, windowClassW))
1867 {
1868 ret = parse_end_element(xmlbuf);
1869 break;
1870 }
1871 else
1872 {
1873 elemU = xmlstr2unicode(&elem);
1874 DPRINT1("unknown elem %wZ\n", &elemU);
1875 ret = parse_unknown_elem(xmlbuf, &elem);
1876 }
1877 }
1878
1879 return ret;
1880 }
1881
1882 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1883 {
1884 xmlstr_t attr_name, attr_value;
1885 UNICODE_STRING attr_valueU, attr_nameU;
1886 BOOL end = FALSE, error;
1887
1888 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1889 {
1890 attr_nameU = xmlstr2unicode(&attr_name);
1891 attr_valueU = xmlstr2unicode(&attr_value);
1892
1893 if (xmlstr_cmp(&attr_name, oldVersionW))
1894 {
1895 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
1896 }
1897 else if (xmlstr_cmp(&attr_name, newVersionW))
1898 {
1899 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
1900 }
1901 else
1902 {
1903 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1904 }
1905 }
1906
1907 if (error || end) return end;
1908 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1909 }
1910
1911 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1912 {
1913 xmlstr_t elem, content, attr_name, attr_value;
1914 BOOL end = FALSE, ret = TRUE, error = FALSE;
1915
1916 UNICODE_STRING elem1U, elem2U;
1917
1918 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1919 {
1920 elem1U = xmlstr2unicode(&attr_name);
1921 elem2U = xmlstr2unicode(&attr_value);
1922 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
1923 }
1924
1925 if (error) return FALSE;
1926 if (end) return TRUE;
1927
1928 if (!parse_text_content(xmlbuf, &content))
1929 return FALSE;
1930
1931 elem1U = xmlstr2unicode(&content);
1932 DPRINT("Got description %wZ\n", &elem1U);
1933
1934 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1935 {
1936 if (xmlstr_cmp_end(&elem, descriptionW))
1937 {
1938 ret = parse_end_element(xmlbuf);
1939 break;
1940 }
1941 else
1942 {
1943 elem1U = xmlstr2unicode(&elem);
1944 DPRINT1("unknown elem %wZ\n", &elem1U);
1945 ret = parse_unknown_elem(xmlbuf, &elem);
1946 }
1947 }
1948
1949 return ret;
1950 }
1951
1952 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1953 struct assembly* assembly,
1954 struct actctx_loader* acl)
1955 {
1956 xmlstr_t attr_name, attr_value;
1957 UNICODE_STRING attr_nameU, attr_valueU;
1958 BOOL end = FALSE, error;
1959 struct entity* entity;
1960
1961 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1962 if (!entity) return FALSE;
1963
1964 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1965 {
1966 if (xmlstr_cmp(&attr_name, iidW))
1967 {
1968 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1969 }
1970 else if (xmlstr_cmp(&attr_name, g_nameW))
1971 {
1972 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1973 }
1974 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1975 {
1976 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1977 entity->u.ifaceps.mask |= BaseIface;
1978 }
1979 else if (xmlstr_cmp(&attr_name, nummethodsW))
1980 {
1981 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1982 entity->u.ifaceps.mask |= NumMethods;
1983 }
1984 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1985 {
1986 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1987 }
1988 else if (xmlstr_cmp(&attr_name, tlbidW))
1989 {
1990 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1991 }
1992 else
1993 {
1994 attr_nameU = xmlstr2unicode(&attr_name);
1995 attr_valueU = xmlstr2unicode(&attr_value);
1996 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1997 }
1998 }
1999
2000 if (error) return FALSE;
2001 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2002 if (end) return TRUE;
2003
2004 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
2005 }
2006
2007 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2008 {
2009 xmlstr_t attr_name, attr_value, elem;
2010 BOOL end = FALSE, error, ret = TRUE;
2011 struct entity* entity;
2012
2013 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
2014 if (!entity) return FALSE;
2015
2016 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2017 {
2018 if (xmlstr_cmp(&attr_name, g_nameW))
2019 {
2020 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
2021 }
2022 else if (xmlstr_cmp(&attr_name, clsidW))
2023 {
2024 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
2025 }
2026 else if (xmlstr_cmp(&attr_name, progidW))
2027 {
2028 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
2029 }
2030 else if (xmlstr_cmp(&attr_name, tlbidW))
2031 {
2032 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
2033 }
2034 else if (xmlstr_cmp(&attr_name, threadingmodelW))
2035 {
2036 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
2037 }
2038 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2039 {
2040 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
2041 }
2042 else
2043 {
2044 UNICODE_STRING attr_nameU, attr_valueU;
2045 attr_nameU = xmlstr2unicode(&attr_name);
2046 attr_valueU = xmlstr2unicode(&attr_value);
2047 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2048 }
2049 }
2050
2051 if (error) return FALSE;
2052 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2053 if (entity->u.comclass.progid)
2054 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2055 if (end) return TRUE;
2056
2057 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2058 {
2059 if (xmlstr_cmp_end(&elem, clrClassW))
2060 {
2061 ret = parse_end_element(xmlbuf);
2062 break;
2063 }
2064 else if (xmlstr_cmp(&elem, progidW))
2065 {
2066 ret = parse_com_class_progid(xmlbuf, entity);
2067 }
2068 else
2069 {
2070 UNICODE_STRING elemU = xmlstr2unicode(&elem);
2071 DPRINT1("unknown elem %wZ\n", &elemU);
2072 ret = parse_unknown_elem(xmlbuf, &elem);
2073 }
2074 }
2075
2076 if (entity->u.comclass.progids.num)
2077 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2078
2079 return ret;
2080 }
2081
2082 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2083 {
2084 xmlstr_t attr_name, attr_value;
2085 UNICODE_STRING attr_nameU, attr_valueU;
2086 BOOL end = FALSE, error;
2087 struct entity* entity;
2088
2089 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2090 if (!entity) return FALSE;
2091
2092 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2093 {
2094 if (xmlstr_cmp(&attr_name, g_nameW))
2095 {
2096 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2097 }
2098 else if (xmlstr_cmp(&attr_name, clsidW))
2099 {
2100 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2101 }
2102 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2103 {
2104 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2105 }
2106 else
2107 {
2108 attr_nameU = xmlstr2unicode(&attr_name);
2109 attr_valueU = xmlstr2unicode(&attr_value);
2110 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2111 }
2112 }
2113
2114 if (error) return FALSE;
2115 acl->actctx->sections |= CLRSURROGATES_SECTION;
2116 if (end) return TRUE;
2117
2118 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2119 }
2120
2121 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2122 {
2123 struct assembly_identity ai;
2124 xmlstr_t elem, attr_name, attr_value;
2125 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2126
2127 UNICODE_STRING elem1U, elem2U;
2128
2129 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2130 {
2131 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2132 static const WCHAR trueW[] = {'t','r','u','e',0};
2133
2134 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2135 delayed = xmlstr_cmp(&attr_value, trueW);
2136 else
2137 {
2138 elem1U = xmlstr2unicode(&attr_name);
2139 elem2U = xmlstr2unicode(&attr_value);
2140 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
2141 }
2142 }
2143
2144 if (error || end) return end;
2145
2146 memset(&ai, 0, sizeof(ai));
2147 ai.optional = optional;
2148 ai.delayed = delayed;
2149
2150 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2151 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2152 return FALSE;
2153
2154 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2155
2156 /* store the newly found identity for later loading */
2157 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2158
2159 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2160 {
2161 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2162 {
2163 ret = parse_end_element(xmlbuf);
2164 break;
2165 }
2166 else if (xmlstr_cmp(&elem, bindingRedirectW))
2167 {
2168 ret = parse_binding_redirect_elem(xmlbuf);
2169 }
2170 else
2171 {
2172 DPRINT1("unknown elem %S\n", elem.ptr);
2173 ret = parse_unknown_elem(xmlbuf, &elem);
2174 }
2175 }
2176
2177 return ret;
2178 }
2179
2180 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2181 {
2182 xmlstr_t attr_name, attr_value, elem;
2183 UNICODE_STRING attr_nameU, attr_valueU;
2184 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2185
2186 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2187 {
2188 attr_nameU = xmlstr2unicode(&attr_name);
2189 attr_valueU = xmlstr2unicode(&attr_value);
2190
2191 if (xmlstr_cmp(&attr_name, optionalW))
2192 {
2193 optional = xmlstr_cmpi( &attr_value, yesW );
2194 DPRINT1("optional=%wZ\n", &attr_valueU);
2195 }
2196 else
2197 {
2198 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2199 }
2200 }
2201
2202 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2203 {
2204 if (xmlstr_cmp_end(&elem, dependencyW))
2205 {
2206 ret = parse_end_element(xmlbuf);
2207 break;
2208 }
2209 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2210 {
2211 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2212 }
2213 else
2214 {
2215 attr_nameU = xmlstr2unicode(&elem);
2216 DPRINT1("unknown element %wZ\n", &attr_nameU);
2217 ret = parse_unknown_elem(xmlbuf, &elem);
2218 }
2219 }
2220
2221 return ret;
2222 }
2223
2224 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2225 {
2226 BOOL end = FALSE;
2227
2228 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2229 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2230 }
2231
2232 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2233 {
2234 BOOL end = FALSE;
2235
2236 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2237 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2238 }
2239
2240 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2241 {
2242 xmlstr_t attr_name, attr_value, elem;
2243 UNICODE_STRING attr_nameU, attr_valueU;
2244 BOOL end = FALSE, error, ret = TRUE;
2245 struct dll_redirect* dll;
2246
2247 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2248
2249 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2250 {
2251 attr_nameU = xmlstr2unicode(&attr_name);
2252 attr_valueU = xmlstr2unicode(&attr_value);
2253
2254 if (xmlstr_cmp(&attr_name, g_nameW))
2255 {
2256 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2257 DPRINT("name=%wZ\n", &attr_valueU);
2258 }
2259 else if (xmlstr_cmp(&attr_name, hashW))
2260 {
2261 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2262 }
2263 else if (xmlstr_cmp(&attr_name, hashalgW))
2264 {
2265 static const WCHAR sha1W[] = {'S','H','A','1',0};
2266 if (!xmlstr_cmpi(&attr_value, sha1W))
2267 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
2268 }
2269 else
2270 {
2271 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2272 }
2273 }
2274
2275 if (error || !dll->name) return FALSE;
2276
2277 acl->actctx->sections |= DLLREDIRECT_SECTION;
2278
2279 if (end) return TRUE;
2280
2281 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2282 {
2283 if (xmlstr_cmp_end(&elem, fileW))
2284 {
2285 ret = parse_end_element(xmlbuf);
2286 break;
2287 }
2288 else if (xmlstr_cmp(&elem, comClassW))
2289 {
2290 ret = parse_com_class_elem(xmlbuf, dll, acl);
2291 }
2292 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2293 {
2294 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2295 }
2296 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2297 {
2298 DPRINT1("asmv2hash (undocumented) not supported\n");
2299 ret = parse_unknown_elem(xmlbuf, &elem);
2300 }
2301 else if (xmlstr_cmp(&elem, typelibW))
2302 {
2303 ret = parse_typelib_elem(xmlbuf, dll, acl);
2304 }
2305 else if (xmlstr_cmp(&elem, windowClassW))
2306 {
2307 ret = parse_window_class_elem(xmlbuf, dll, acl);
2308 }
2309 else
2310 {
2311 attr_nameU = xmlstr2unicode(&elem);
2312 DPRINT1("unknown elem %wZ\n", &attr_nameU);
2313 ret = parse_unknown_elem( xmlbuf, &elem );
2314 }
2315 }
2316
2317 return ret;
2318 }
2319
2320 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2321 struct assembly* assembly,
2322 struct assembly_identity* expected_ai)
2323 {
2324 xmlstr_t attr_name, attr_value, elem;
2325 UNICODE_STRING attr_nameU, attr_valueU;
2326 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2327
2328 DPRINT("(%p)\n", xmlbuf);
2329
2330 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2331 {
2332 attr_nameU = xmlstr2unicode(&attr_name);
2333 attr_valueU = xmlstr2unicode(&attr_value);
2334
2335 if (xmlstr_cmp(&attr_name, manifestVersionW))
2336 {
2337 static const WCHAR v10W[] = {'1','.','0',0};
2338 if (!xmlstr_cmp(&attr_value, v10W))
2339 {
2340 DPRINT1("wrong version %wZ\n", &attr_valueU);
2341 return FALSE;
2342 }
2343 version = TRUE;
2344 }
2345 else if (xmlstr_cmp(&attr_name, xmlnsW))
2346 {
2347 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2348 !xmlstr_cmp(&attr_value, manifestv2W) &&
2349 !xmlstr_cmp(&attr_value, manifestv3W))
2350 {
2351 DPRINT1("wrong namespace %wZ\n", &attr_valueU);
2352 return FALSE;
2353 }
2354 xmlns = TRUE;
2355 }
2356 else
2357 {
2358 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2359 }
2360 }
2361
2362 if (error || end || !xmlns || !version) return FALSE;
2363 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2364
2365 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2366 {
2367 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2368 return FALSE;
2369 assembly->no_inherit = TRUE;
2370 }
2371
2372 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2373 {
2374 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2375 return FALSE;
2376 }
2377 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2378 assembly->no_inherit)
2379 return FALSE;
2380
2381 while (ret)
2382 {
2383 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2384 {
2385 ret = parse_end_element(xmlbuf);
2386 break;
2387 }
2388 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2389 {
2390 ret = parse_description_elem(xmlbuf);
2391 }
2392 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2393 {
2394 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2395 }
2396 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2397 {
2398 ret = parse_dependency_elem(xmlbuf, acl);
2399 }
2400 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2401 {
2402 ret = parse_file_elem(xmlbuf, assembly, acl);
2403 }
2404 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2405 {
2406 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2407 }
2408 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2409 {
2410 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2411 }
2412 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2413 {
2414 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2415
2416 if (expected_ai)
2417 {
2418 /* FIXME: more tests */
2419 if (assembly->type == ASSEMBLY_MANIFEST &&
2420 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2421 {
2422 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2423 expected_ai->version.major, expected_ai->version.minor,
2424 expected_ai->version.build, expected_ai->version.revision,
2425 assembly->id.version.major, assembly->id.version.minor,
2426 assembly->id.version.build, assembly->id.version.revision);
2427 ret = FALSE;
2428 }
2429 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2430 (assembly->id.version.major != expected_ai->version.major ||
2431 assembly->id.version.minor != expected_ai->version.minor ||
2432 assembly->id.version.build < expected_ai->version.build ||
2433 (assembly->id.version.build == expected_ai->version.build &&
2434 assembly->id.version.revision < expected_ai->version.revision)))
2435 {
2436 DPRINT1("wrong version for shared assembly manifest\n");
2437 ret = FALSE;
2438 }
2439 }
2440 }
2441 #ifdef __REACTOS__
2442 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2443 {
2444 ret = parse_unknown_elem(xmlbuf, &elem);
2445 }
2446 #endif
2447 else
2448 {
2449 attr_nameU = xmlstr2unicode(&elem);
2450 DPRINT1("unknown element %wZ\n", &attr_nameU);
2451 ret = parse_unknown_elem(xmlbuf, &elem);
2452 }
2453 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2454 }
2455
2456 return ret;
2457 }
2458
2459 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2460 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2461 {
2462 xmlstr_t elem;
2463 UNICODE_STRING elemU;
2464
2465 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2466
2467 if (xmlstr_cmp(&elem, g_xmlW) &&
2468 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2469 return STATUS_SXS_CANT_GEN_ACTCTX;
2470
2471 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2472 {
2473 elemU = xmlstr2unicode(&elem);
2474 DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
2475 return STATUS_SXS_CANT_GEN_ACTCTX;
2476 }
2477
2478 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2479 {
2480 DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
2481 return STATUS_SXS_CANT_GEN_ACTCTX;
2482 }
2483
2484 if (next_xml_elem(xmlbuf, &elem))
2485 {
2486 elemU = xmlstr2unicode(&elem);
2487 DPRINT1("unexpected element %wZ\n", &elemU);
2488 return STATUS_SXS_CANT_GEN_ACTCTX;
2489 }
2490
2491 if (xmlbuf->ptr != xmlbuf->end)
2492 {
2493 DPRINT1("parse error\n");
2494 return STATUS_SXS_CANT_GEN_ACTCTX;
2495 }
2496 return STATUS_SUCCESS;
2497 }
2498
2499 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2500 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2501 const void *buffer, SIZE_T size )
2502 {
2503 xmlbuf_t xmlbuf;
2504 NTSTATUS status;
2505 struct assembly *assembly;
2506 int unicode_tests;
2507
2508 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2509
2510 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2511 return STATUS_SXS_CANT_GEN_ACTCTX;
2512
2513 if (directory && !(assembly->directory = strdupW(directory)))
2514 return STATUS_NO_MEMORY;
2515
2516 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2517 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2518 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2519
2520 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2521 if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2522 {
2523 xmlbuf.ptr = buffer;
2524 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2525 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2526 }
2527 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2528 {
2529 const WCHAR *buf = buffer;
2530 WCHAR *new_buff;
2531 unsigned int i;
2532
2533 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2534 return STATUS_NO_MEMORY;
2535 for (i = 0; i < size / sizeof(WCHAR); i++)
2536 new_buff[i] = RtlUshortByteSwap( buf[i] );
2537 xmlbuf.ptr = new_buff;
2538 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2539 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2540 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2541 }
2542 else
2543 {
2544 /* TODO: this doesn't handle arbitrary encodings */
2545 WCHAR *new_buff;
2546 ULONG sizeU;
2547
2548 status = RtlMultiByteToUnicodeSize(&sizeU, buffer, size);
2549 if (!NT_SUCCESS(status))
2550 {
2551 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2552 return STATUS_SXS_CANT_GEN_ACTCTX;
2553 }
2554
2555 new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2556 if (!new_buff)
2557 return STATUS_NO_MEMORY;
2558
2559 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2560 if (!NT_SUCCESS(status))
2561 {
2562 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2563 return STATUS_SXS_CANT_GEN_ACTCTX;
2564 }
2565
2566 xmlbuf.ptr = new_buff;
2567 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2568 status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2569 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2570 }
2571 return status;
2572 }
2573
2574 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2575 {
2576 OBJECT_ATTRIBUTES attr;
2577 IO_STATUS_BLOCK io;
2578
2579 attr.Length = sizeof(attr);
2580 attr.RootDirectory = 0;
2581 attr.Attributes = OBJ_CASE_INSENSITIVE;
2582 attr.ObjectName = name;
2583 attr.SecurityDescriptor = NULL;
2584 attr.SecurityQualityOfService = NULL;
2585 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2586 }
2587
2588 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
2589 {
2590 NTSTATUS status;
2591 ULONG_PTR magic;
2592 LDR_DATA_TABLE_ENTRY *pldr;
2593
2594 LdrLockLoaderLock(0, NULL, &magic);
2595 status = LdrFindEntryForAddress( module, &pldr );
2596 if (status == STATUS_SUCCESS)
2597 {
2598 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2599 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2600 {
2601 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2602 str->Length = pldr->FullDllName.Length;
2603 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2604 }
2605 else status = STATUS_NO_MEMORY;
2606 }
2607 LdrUnlockLoaderLock(0, magic);
2608 return status;
2609 }
2610
2611 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2612 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2613 HANDLE hModule, LPCWSTR resname, ULONG lang )
2614 {
2615 NTSTATUS status;
2616 UNICODE_STRING nameW;
2617 LDR_RESOURCE_INFO info;
2618 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2619 void *ptr;
2620
2621 //DPRINT( "looking for res %s in module %p %s\n", resname,
2622 // hModule, filename );
2623 DPRINT("get_manifest_in_module %p\n", hModule);
2624
2625 #if 0
2626 if (TRACE_ON(actctx))
2627 {
2628 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2629 {
2630 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2631 hModule, debugstr_w(nameW.Buffer) );
2632 RtlFreeUnicodeString( &nameW );
2633 }
2634 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2635 hModule, debugstr_w(filename) );
2636 }
2637 #endif
2638
2639 if (!resname) return STATUS_INVALID_PARAMETER;
2640
2641 info.Type = (ULONG_PTR)RT_MANIFEST;
2642 info.Language = lang;
2643 if (!((ULONG_PTR)resname >> 16))
2644 {
2645 info.Name = (ULONG_PTR)resname;
2646 status = LdrFindResource_U(hModule, &info, 3, &entry);
2647 }
2648 else if (resname[0] == '#')
2649 {
2650 ULONG value;
2651 RtlInitUnicodeString(&nameW, resname + 1);
2652 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2653 return STATUS_INVALID_PARAMETER;
2654 info.Name = value;
2655 status = LdrFindResource_U(hModule, &info, 3, &entry);
2656 }
2657 else
2658 {
2659 RtlCreateUnicodeString(&nameW, resname);
2660 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2661 info.Name = (ULONG_PTR)nameW.Buffer;
2662 status = LdrFindResource_U(hModule, &info, 3, &entry);
2663 RtlFreeUnicodeString(&nameW);
2664 }
2665 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2666
2667 if (status == STATUS_SUCCESS)
2668 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2669
2670 return status;
2671 }
2672
2673 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2674 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2675 HANDLE file, LPCWSTR resname, ULONG lang )
2676 {
2677 HANDLE mapping;
2678 OBJECT_ATTRIBUTES attr;
2679 LARGE_INTEGER size;
2680 LARGE_INTEGER offset;
2681 NTSTATUS status;
2682 SIZE_T count;
2683 void *base;
2684
2685 DPRINT( "looking for res %S in %S\n", resname, filename );
2686
2687 attr.Length = sizeof(attr);
2688 attr.RootDirectory = 0;
2689 attr.ObjectName = NULL;
2690 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2691 attr.SecurityDescriptor = NULL;
2692 attr.SecurityQualityOfService = NULL;
2693
2694 size.QuadPart = 0;
2695 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2696 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2697 if (status != STATUS_SUCCESS) return status;
2698
2699 offset.QuadPart = 0;
2700 count = 0;
2701 base = NULL;
2702 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2703 &count, ViewShare, 0, PAGE_READONLY );
2704 NtClose( mapping );
2705 if (status != STATUS_SUCCESS) return status;
2706
2707 if (RtlImageNtHeader(base)) /* we got a PE file */
2708 {
2709 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2710 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2711 }
2712 else status = STATUS_INVALID_IMAGE_FORMAT;
2713
2714 NtUnmapViewOfSection( NtCurrentProcess(), base );
2715 return status;
2716 }
2717
2718 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2719 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2720 {
2721 FILE_STANDARD_INFORMATION info;
2722 IO_STATUS_BLOCK io;
2723 HANDLE mapping;
2724 OBJECT_ATTRIBUTES attr;
2725 LARGE_INTEGER size;
2726 LARGE_INTEGER offset;
2727 NTSTATUS status;
2728 SIZE_T count;
2729 void *base;
2730
2731 DPRINT( "loading manifest file %S\n", filename );
2732
2733 attr.Length = sizeof(attr);
2734 attr.RootDirectory = 0;
2735 attr.ObjectName = NULL;
2736 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2737 attr.SecurityDescriptor = NULL;
2738 attr.SecurityQualityOfService = NULL;
2739
2740 size.QuadPart = 0;
2741 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2742 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2743
2744 if (status != STATUS_SUCCESS) return status;
2745
2746 offset.QuadPart = 0;
2747 count = 0;
2748 base = NULL;
2749 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2750 &count, ViewShare, 0, PAGE_READONLY );
2751 NtClose( mapping );
2752 if (status != STATUS_SUCCESS) return status;
2753
2754 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2755 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
2756
2757 if (status == STATUS_SUCCESS)
2758 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
2759
2760 NtUnmapViewOfSection( NtCurrentProcess(), base );
2761 return status;
2762 }
2763
2764 /* try to load the .manifest file associated to the file */
2765 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2766 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2767 {
2768 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2769 WCHAR *buffer;
2770 NTSTATUS status;
2771 UNICODE_STRING nameW;
2772 HANDLE file;
2773 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
2774
2775 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2776
2777 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
2778
2779 if (module) /* use the module filename */
2780 {
2781 UNICODE_STRING name;
2782
2783 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2784 {
2785 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2786 strcatW( name.Buffer, dotManifestW );
2787 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2788 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2789 RtlFreeUnicodeString( &name );
2790 }
2791 if (status) return status;
2792 }
2793 else
2794 {
2795 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2796 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2797 return STATUS_NO_MEMORY;
2798 strcpyW( buffer, filename );
2799 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2800 strcatW( buffer, dotManifestW );
2801 RtlInitUnicodeString( &nameW, buffer );
2802 }
2803
2804 if (!open_nt_file( &file, &nameW ))
2805 {
2806 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2807 NtClose( file );
2808 }
2809 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2810 RtlFreeUnicodeString( &nameW );
2811 return status;
2812 }
2813
2814 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2815 {
2816 static const WCHAR lookup_fmtW[] =
2817 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2818 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2819 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2820
2821 WCHAR *lookup, *ret = NULL;
2822 UNICODE_STRING lookup_us;
2823 IO_STATUS_BLOCK io;
2824 const WCHAR *lang = ai->language;
2825 unsigned int data_pos = 0, data_len;
2826 char buffer[8192];
2827
2828 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2829 (strlenW(ai->arch) + strlenW(ai->name)
2830 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2831 + sizeof(lookup_fmtW) )))
2832 return NULL;
2833
2834 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2835 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2836 ai->version.major, ai->version.minor, lang );
2837 RtlInitUnicodeString( &lookup_us, lookup );
2838
2839 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2840 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2841 {
2842 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2843 FILE_BOTH_DIR_INFORMATION *dir_info;
2844 WCHAR *tmp;
2845 ULONG build, revision;
2846
2847 data_len = (ULONG)io.Information;
2848
2849 for (;;)
2850 {
2851 if (data_pos >= data_len)
2852 {
2853 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2854 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2855 break;
2856 data_len = (ULONG)io.Information;
2857 data_pos = 0;
2858 }
2859 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2860
2861 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2862 else data_pos = data_len;
2863
2864 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
2865 build = atoiW(tmp);
2866 if (build < min_build) continue;
2867 tmp = strchrW(tmp, '.') + 1;
2868 revision = atoiW(tmp);
2869 if (build == min_build && revision < min_revision) continue;
2870 tmp = strchrW(tmp, '_') + 1;
2871 tmp = strchrW(tmp, '_') + 1;
2872 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2873 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2874 {
2875 /* prefer a non-Wine manifest if we already have one */
2876 /* we'll still load the builtin dll if specified through DllOverrides */
2877 if (ret) continue;
2878 }
2879 else
2880 {
2881 min_build = build;
2882 min_revision = revision;
2883 }
2884 ai->version.build = build;
2885 ai->version.revision = revision;
2886 RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
2887 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2888 {
2889 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2890 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2891 }
2892 }
2893 }
2894 else DPRINT1("no matching file for %S\n", lookup);
2895 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
2896 return ret;
2897 }
2898
2899 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2900 {
2901 struct assembly_identity sxs_ai;
2902 UNICODE_STRING path_us;
2903 OBJECT_ATTRIBUTES attr;
2904 IO_STATUS_BLOCK io;
2905 WCHAR *path, *file = NULL;
2906 HANDLE handle;
2907
2908 static const WCHAR manifest_dirW[] =
2909 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2910
2911 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2912
2913 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2914 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
2915 return STATUS_NO_MEMORY;
2916
2917 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
2918 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );</