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