4cf9bbaa4bd358d34dab164cb247a5aa50fcb9ac
[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 progids->allocated *= 2;
1508 progids->progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1509 }
1510
1511 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1512 progids->num++;
1513
1514 return TRUE;
1515 }
1516
1517 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1518 {
1519 xmlstr_t content;
1520 BOOL end = FALSE;
1521
1522 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1523 return FALSE;
1524
1525 if (!com_class_add_progid(&content, entity)) return FALSE;
1526 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1527 }
1528
1529 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1530 {
1531 xmlstr_t elem, attr_name, attr_value;
1532 BOOL ret = TRUE, end = FALSE, error;
1533 struct entity* entity;
1534 UNICODE_STRING attr_valueU, attr_nameU;
1535
1536 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1537 return FALSE;
1538
1539 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1540 {
1541 if (xmlstr_cmp(&attr_name, clsidW))
1542 {
1543 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1544 }
1545 else if (xmlstr_cmp(&attr_name, progidW))
1546 {
1547 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1548 }
1549 else if (xmlstr_cmp(&attr_name, tlbidW))
1550 {
1551 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1552 }
1553 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1554 {
1555 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1556 }
1557 else if (xmlstr_cmp(&attr_name, miscstatusW))
1558 {
1559 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1560 }
1561 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1562 {
1563 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1564 }
1565 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1566 {
1567 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1568 }
1569 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1570 {
1571 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1572 }
1573 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1574 {
1575 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1576 }
1577 else if (xmlstr_cmp(&attr_name, descriptionW))
1578 {
1579 /* not stored */
1580 }
1581 else
1582 {
1583 attr_nameU = xmlstr2unicode(&attr_name);
1584 attr_valueU = xmlstr2unicode(&attr_value);
1585 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1586 }
1587 }
1588
1589 if (error) return FALSE;
1590
1591 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1592 if (entity->u.comclass.progid)
1593 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1594
1595 if (end) return TRUE;
1596
1597 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1598 {
1599 if (xmlstr_cmp_end(&elem, comClassW))
1600 {
1601 ret = parse_end_element(xmlbuf);
1602 break;
1603 }
1604 else if (xmlstr_cmp(&elem, progidW))
1605 {
1606 ret = parse_com_class_progid(xmlbuf, entity);
1607 }
1608 else
1609 {
1610 attr_nameU = xmlstr2unicode(&elem);
1611 DPRINT1("unknown elem %wZ\n", &attr_nameU);
1612 ret = parse_unknown_elem(xmlbuf, &elem);
1613 }
1614 }
1615
1616 if (entity->u.comclass.progids.num)
1617 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1618
1619 return ret;
1620 }
1621
1622 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1623 {
1624 const WCHAR *curr;
1625 ULONG num = 0;
1626
1627 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1628 {
1629 if (*curr >= '0' && *curr <= '9')
1630 num = num * 10 + *curr - '0';
1631 else
1632 {
1633 UNICODE_STRING strU = xmlstr2unicode(str);
1634 DPRINT1("wrong numeric value %wZ\n", &strU);
1635 return FALSE;
1636 }
1637 }
1638 entity->u.ifaceps.nummethods = num;
1639
1640 return TRUE;
1641 }
1642
1643 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1644 {
1645 xmlstr_t attr_name, attr_value;
1646 BOOL end = FALSE, error;
1647 struct entity* entity;
1648 UNICODE_STRING attr_valueU, attr_nameU;
1649
1650 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1651 return FALSE;
1652
1653 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1654 {
1655 if (xmlstr_cmp(&attr_name, iidW))
1656 {
1657 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1658 }
1659 else if (xmlstr_cmp(&attr_name, g_nameW))
1660 {
1661 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1662 }
1663 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1664 {
1665 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1666 entity->u.ifaceps.mask |= BaseIface;
1667 }
1668 else if (xmlstr_cmp(&attr_name, nummethodsW))
1669 {
1670 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1671 entity->u.ifaceps.mask |= NumMethods;
1672 }
1673 else if (xmlstr_cmp(&attr_name, tlbidW))
1674 {
1675 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1676 }
1677 /* not used */
1678 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1679 {
1680 }
1681 else
1682 {
1683 attr_nameU = xmlstr2unicode(&attr_name);
1684 attr_valueU = xmlstr2unicode(&attr_value);
1685 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1686 }
1687 }
1688
1689 if (error) return FALSE;
1690 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1691 if (end) return TRUE;
1692
1693 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1694 }
1695
1696 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1697 {
1698 WORD *flags = &entity->u.typelib.flags;
1699 const WCHAR *str = value->ptr, *start;
1700 int i = 0;
1701
1702 *flags = 0;
1703
1704 /* it's comma separated list of flags */
1705 while (i < value->len)
1706 {
1707 start = str;
1708 while (*str != ',' && (i++ < value->len)) str++;
1709
1710 if (!strncmpiW(start, restrictedW, str-start))
1711 *flags |= LIBFLAG_FRESTRICTED;
1712 else if (!strncmpiW(start, controlW, str-start))
1713 *flags |= LIBFLAG_FCONTROL;
1714 else if (!strncmpiW(start, hiddenW, str-start))
1715 *flags |= LIBFLAG_FHIDDEN;
1716 else if (!strncmpiW(start, hasdiskimageW, str-start))
1717 *flags |= LIBFLAG_FHASDISKIMAGE;
1718 else
1719 {
1720 UNICODE_STRING valueU = xmlstr2unicode(value);
1721 DPRINT1("unknown flags value %wZ\n", &valueU);
1722 return FALSE;
1723 }
1724
1725 /* skip separator */
1726 str++;
1727 i++;
1728 }
1729
1730 return TRUE;
1731 }
1732
1733 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1734 {
1735 unsigned int ver[2];
1736 unsigned int pos;
1737 const WCHAR *curr;
1738 UNICODE_STRING strW;
1739
1740 /* major.minor */
1741 ver[0] = ver[1] = pos = 0;
1742 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1743 {
1744 if (*curr >= '0' && *curr <= '9')
1745 {
1746 ver[pos] = ver[pos] * 10 + *curr - '0';
1747 if (ver[pos] >= 0x10000) goto error;
1748 }
1749 else if (*curr == '.')
1750 {
1751 if (++pos >= 2) goto error;
1752 }
1753 else goto error;
1754 }
1755 entity->u.typelib.major = ver[0];
1756 entity->u.typelib.minor = ver[1];
1757 return TRUE;
1758
1759 error:
1760 strW = xmlstr2unicode(str);
1761 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
1762 return FALSE;
1763 }
1764
1765 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1766 {
1767 xmlstr_t attr_name, attr_value;
1768 BOOL end = FALSE, error;
1769 struct entity* entity;
1770 UNICODE_STRING attr_valueU, attr_nameU;
1771
1772 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1773 return FALSE;
1774
1775 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1776 {
1777 if (xmlstr_cmp(&attr_name, tlbidW))
1778 {
1779 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1780 }
1781 else if (xmlstr_cmp(&attr_name, versionW))
1782 {
1783 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1784 }
1785 else if (xmlstr_cmp(&attr_name, helpdirW))
1786 {
1787 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1788 }
1789 else if (xmlstr_cmp(&attr_name, flagsW))
1790 {
1791 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1792 }
1793 else
1794 {
1795 attr_nameU = xmlstr2unicode(&attr_name);
1796 attr_valueU = xmlstr2unicode(&attr_value);
1797 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1798 }
1799 }
1800
1801 if (error) return FALSE;
1802
1803 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1804
1805 if (end) return TRUE;
1806
1807 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1808 }
1809
1810 static inline int aligned_string_len(int len)
1811 {
1812 return (len + 3) & ~3;
1813 }
1814
1815 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1816 {
1817 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1818 struct assembly_version *ver = &assembly->id.version;
1819 WCHAR buff[25];
1820
1821 if (!ret) ret = buff;
1822 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1823 }
1824
1825 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1826 {
1827 xmlstr_t elem, content, attr_name, attr_value;
1828 BOOL end = FALSE, ret = TRUE, error;
1829 struct entity* entity;
1830 UNICODE_STRING elemU, attr_nameU, attr_valueU;
1831
1832 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1833 return FALSE;
1834
1835 entity->u.class.versioned = TRUE;
1836 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1837 {
1838 if (xmlstr_cmp(&attr_name, versionedW))
1839 {
1840 if (xmlstr_cmpi(&attr_value, noW))
1841 entity->u.class.versioned = FALSE;
1842 else if (!xmlstr_cmpi(&attr_value, yesW))
1843 return FALSE;
1844 }
1845 else
1846 {
1847 attr_nameU = xmlstr2unicode(&attr_name);
1848 attr_valueU = xmlstr2unicode(&attr_value);
1849 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1850 }
1851 }
1852
1853 if (error || end) return end;
1854
1855 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1856
1857 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1858
1859 acl->actctx->sections |= WINDOWCLASS_SECTION;
1860
1861 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1862 {
1863 if (xmlstr_cmp_end(&elem, windowClassW))
1864 {
1865 ret = parse_end_element(xmlbuf);
1866 break;
1867 }
1868 else
1869 {
1870 elemU = xmlstr2unicode(&elem);
1871 DPRINT1("unknown elem %wZ\n", &elemU);
1872 ret = parse_unknown_elem(xmlbuf, &elem);
1873 }
1874 }
1875
1876 return ret;
1877 }
1878
1879 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1880 {
1881 xmlstr_t attr_name, attr_value;
1882 UNICODE_STRING attr_valueU, attr_nameU;
1883 BOOL end = FALSE, error;
1884
1885 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1886 {
1887 attr_nameU = xmlstr2unicode(&attr_name);
1888 attr_valueU = xmlstr2unicode(&attr_value);
1889
1890 if (xmlstr_cmp(&attr_name, oldVersionW))
1891 {
1892 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
1893 }
1894 else if (xmlstr_cmp(&attr_name, newVersionW))
1895 {
1896 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
1897 }
1898 else
1899 {
1900 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1901 }
1902 }
1903
1904 if (error || end) return end;
1905 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1906 }
1907
1908 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1909 {
1910 xmlstr_t elem, content, attr_name, attr_value;
1911 BOOL end = FALSE, ret = TRUE, error = FALSE;
1912
1913 UNICODE_STRING elem1U, elem2U;
1914
1915 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1916 {
1917 elem1U = xmlstr2unicode(&attr_name);
1918 elem2U = xmlstr2unicode(&attr_value);
1919 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
1920 }
1921
1922 if (error) return FALSE;
1923 if (end) return TRUE;
1924
1925 if (!parse_text_content(xmlbuf, &content))
1926 return FALSE;
1927
1928 elem1U = xmlstr2unicode(&content);
1929 DPRINT("Got description %wZ\n", &elem1U);
1930
1931 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1932 {
1933 if (xmlstr_cmp_end(&elem, descriptionW))
1934 {
1935 ret = parse_end_element(xmlbuf);
1936 break;
1937 }
1938 else
1939 {
1940 elem1U = xmlstr2unicode(&elem);
1941 DPRINT1("unknown elem %wZ\n", &elem1U);
1942 ret = parse_unknown_elem(xmlbuf, &elem);
1943 }
1944 }
1945
1946 return ret;
1947 }
1948
1949 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1950 struct assembly* assembly,
1951 struct actctx_loader* acl)
1952 {
1953 xmlstr_t attr_name, attr_value;
1954 UNICODE_STRING attr_nameU, attr_valueU;
1955 BOOL end = FALSE, error;
1956 struct entity* entity;
1957
1958 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1959 if (!entity) return FALSE;
1960
1961 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1962 {
1963 if (xmlstr_cmp(&attr_name, iidW))
1964 {
1965 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1966 }
1967 else if (xmlstr_cmp(&attr_name, g_nameW))
1968 {
1969 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1970 }
1971 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1972 {
1973 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1974 entity->u.ifaceps.mask |= BaseIface;
1975 }
1976 else if (xmlstr_cmp(&attr_name, nummethodsW))
1977 {
1978 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1979 entity->u.ifaceps.mask |= NumMethods;
1980 }
1981 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1982 {
1983 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1984 }
1985 else if (xmlstr_cmp(&attr_name, tlbidW))
1986 {
1987 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1988 }
1989 else
1990 {
1991 attr_nameU = xmlstr2unicode(&attr_name);
1992 attr_valueU = xmlstr2unicode(&attr_value);
1993 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1994 }
1995 }
1996
1997 if (error) return FALSE;
1998 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1999 if (end) return TRUE;
2000
2001 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
2002 }
2003
2004 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2005 {
2006 xmlstr_t attr_name, attr_value, elem;
2007 BOOL end = FALSE, error, ret = TRUE;
2008 struct entity* entity;
2009
2010 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
2011 if (!entity) return FALSE;
2012
2013 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2014 {
2015 if (xmlstr_cmp(&attr_name, g_nameW))
2016 {
2017 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
2018 }
2019 else if (xmlstr_cmp(&attr_name, clsidW))
2020 {
2021 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
2022 }
2023 else if (xmlstr_cmp(&attr_name, progidW))
2024 {
2025 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
2026 }
2027 else if (xmlstr_cmp(&attr_name, tlbidW))
2028 {
2029 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
2030 }
2031 else if (xmlstr_cmp(&attr_name, threadingmodelW))
2032 {
2033 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
2034 }
2035 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2036 {
2037 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
2038 }
2039 else
2040 {
2041 UNICODE_STRING attr_nameU, attr_valueU;
2042 attr_nameU = xmlstr2unicode(&attr_name);
2043 attr_valueU = xmlstr2unicode(&attr_value);
2044 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2045 }
2046 }
2047
2048 if (error) return FALSE;
2049 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2050 if (entity->u.comclass.progid)
2051 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2052 if (end) return TRUE;
2053
2054 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2055 {
2056 if (xmlstr_cmp_end(&elem, clrClassW))
2057 {
2058 ret = parse_end_element(xmlbuf);
2059 break;
2060 }
2061 else if (xmlstr_cmp(&elem, progidW))
2062 {
2063 ret = parse_com_class_progid(xmlbuf, entity);
2064 }
2065 else
2066 {
2067 UNICODE_STRING elemU = xmlstr2unicode(&elem);
2068 DPRINT1("unknown elem %wZ\n", &elemU);
2069 ret = parse_unknown_elem(xmlbuf, &elem);
2070 }
2071 }
2072
2073 if (entity->u.comclass.progids.num)
2074 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2075
2076 return ret;
2077 }
2078
2079 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2080 {
2081 xmlstr_t attr_name, attr_value;
2082 UNICODE_STRING attr_nameU, attr_valueU;
2083 BOOL end = FALSE, error;
2084 struct entity* entity;
2085
2086 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2087 if (!entity) return FALSE;
2088
2089 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2090 {
2091 if (xmlstr_cmp(&attr_name, g_nameW))
2092 {
2093 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2094 }
2095 else if (xmlstr_cmp(&attr_name, clsidW))
2096 {
2097 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2098 }
2099 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2100 {
2101 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2102 }
2103 else
2104 {
2105 attr_nameU = xmlstr2unicode(&attr_name);
2106 attr_valueU = xmlstr2unicode(&attr_value);
2107 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2108 }
2109 }
2110
2111 if (error) return FALSE;
2112 acl->actctx->sections |= CLRSURROGATES_SECTION;
2113 if (end) return TRUE;
2114
2115 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2116 }
2117
2118 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2119 {
2120 struct assembly_identity ai;
2121 xmlstr_t elem, attr_name, attr_value;
2122 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2123
2124 UNICODE_STRING elem1U, elem2U;
2125
2126 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2127 {
2128 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2129 static const WCHAR trueW[] = {'t','r','u','e',0};
2130
2131 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2132 delayed = xmlstr_cmp(&attr_value, trueW);
2133 else
2134 {
2135 elem1U = xmlstr2unicode(&attr_name);
2136 elem2U = xmlstr2unicode(&attr_value);
2137 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
2138 }
2139 }
2140
2141 if (error || end) return end;
2142
2143 memset(&ai, 0, sizeof(ai));
2144 ai.optional = optional;
2145 ai.delayed = delayed;
2146
2147 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2148 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2149 return FALSE;
2150
2151 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2152
2153 /* store the newly found identity for later loading */
2154 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2155
2156 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2157 {
2158 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2159 {
2160 ret = parse_end_element(xmlbuf);
2161 break;
2162 }
2163 else if (xmlstr_cmp(&elem, bindingRedirectW))
2164 {
2165 ret = parse_binding_redirect_elem(xmlbuf);
2166 }
2167 else
2168 {
2169 DPRINT1("unknown elem %S\n", elem.ptr);
2170 ret = parse_unknown_elem(xmlbuf, &elem);
2171 }
2172 }
2173
2174 return ret;
2175 }
2176
2177 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2178 {
2179 xmlstr_t attr_name, attr_value, elem;
2180 UNICODE_STRING attr_nameU, attr_valueU;
2181 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2182
2183 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2184 {
2185 attr_nameU = xmlstr2unicode(&attr_name);
2186 attr_valueU = xmlstr2unicode(&attr_value);
2187
2188 if (xmlstr_cmp(&attr_name, optionalW))
2189 {
2190 optional = xmlstr_cmpi( &attr_value, yesW );
2191 DPRINT1("optional=%wZ\n", &attr_valueU);
2192 }
2193 else
2194 {
2195 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2196 }
2197 }
2198
2199 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2200 {
2201 if (xmlstr_cmp_end(&elem, dependencyW))
2202 {
2203 ret = parse_end_element(xmlbuf);
2204 break;
2205 }
2206 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2207 {
2208 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2209 }
2210 else
2211 {
2212 attr_nameU = xmlstr2unicode(&elem);
2213 DPRINT1("unknown element %wZ\n", &attr_nameU);
2214 ret = parse_unknown_elem(xmlbuf, &elem);
2215 }
2216 }
2217
2218 return ret;
2219 }
2220
2221 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2222 {
2223 BOOL end = FALSE;
2224
2225 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2226 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2227 }
2228
2229 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2230 {
2231 BOOL end = FALSE;
2232
2233 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2234 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2235 }
2236
2237 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2238 {
2239 xmlstr_t attr_name, attr_value, elem;
2240 UNICODE_STRING attr_nameU, attr_valueU;
2241 BOOL end = FALSE, error, ret = TRUE;
2242 struct dll_redirect* dll;
2243
2244 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2245
2246 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2247 {
2248 attr_nameU = xmlstr2unicode(&attr_name);
2249 attr_valueU = xmlstr2unicode(&attr_value);
2250
2251 if (xmlstr_cmp(&attr_name, g_nameW))
2252 {
2253 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2254 DPRINT("name=%wZ\n", &attr_valueU);
2255 }
2256 else if (xmlstr_cmp(&attr_name, hashW))
2257 {
2258 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2259 }
2260 else if (xmlstr_cmp(&attr_name, hashalgW))
2261 {
2262 static const WCHAR sha1W[] = {'S','H','A','1',0};
2263 if (!xmlstr_cmpi(&attr_value, sha1W))
2264 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
2265 }
2266 else
2267 {
2268 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2269 }
2270 }
2271
2272 if (error || !dll->name) return FALSE;
2273
2274 acl->actctx->sections |= DLLREDIRECT_SECTION;
2275
2276 if (end) return TRUE;
2277
2278 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2279 {
2280 if (xmlstr_cmp_end(&elem, fileW))
2281 {
2282 ret = parse_end_element(xmlbuf);
2283 break;
2284 }
2285 else if (xmlstr_cmp(&elem, comClassW))
2286 {
2287 ret = parse_com_class_elem(xmlbuf, dll, acl);
2288 }
2289 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2290 {
2291 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2292 }
2293 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2294 {
2295 DPRINT1("asmv2hash (undocumented) not supported\n");
2296 ret = parse_unknown_elem(xmlbuf, &elem);
2297 }
2298 else if (xmlstr_cmp(&elem, typelibW))
2299 {
2300 ret = parse_typelib_elem(xmlbuf, dll, acl);
2301 }
2302 else if (xmlstr_cmp(&elem, windowClassW))
2303 {
2304 ret = parse_window_class_elem(xmlbuf, dll, acl);
2305 }
2306 else
2307 {
2308 attr_nameU = xmlstr2unicode(&elem);
2309 DPRINT1("unknown elem %wZ\n", &attr_nameU);
2310 ret = parse_unknown_elem( xmlbuf, &elem );
2311 }
2312 }
2313
2314 return ret;
2315 }
2316
2317 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2318 struct assembly* assembly,
2319 struct assembly_identity* expected_ai)
2320 {
2321 xmlstr_t attr_name, attr_value, elem;
2322 UNICODE_STRING attr_nameU, attr_valueU;
2323 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2324
2325 DPRINT("(%p)\n", xmlbuf);
2326
2327 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2328 {
2329 attr_nameU = xmlstr2unicode(&attr_name);
2330 attr_valueU = xmlstr2unicode(&attr_value);
2331
2332 if (xmlstr_cmp(&attr_name, manifestVersionW))
2333 {
2334 static const WCHAR v10W[] = {'1','.','0',0};
2335 if (!xmlstr_cmp(&attr_value, v10W))
2336 {
2337 DPRINT1("wrong version %wZ\n", &attr_valueU);
2338 return FALSE;
2339 }
2340 version = TRUE;
2341 }
2342 else if (xmlstr_cmp(&attr_name, xmlnsW))
2343 {
2344 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2345 !xmlstr_cmp(&attr_value, manifestv2W) &&
2346 !xmlstr_cmp(&attr_value, manifestv3W))
2347 {
2348 DPRINT1("wrong namespace %wZ\n", &attr_valueU);
2349 return FALSE;
2350 }
2351 xmlns = TRUE;
2352 }
2353 else
2354 {
2355 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2356 }
2357 }
2358
2359 if (error || end || !xmlns || !version) return FALSE;
2360 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2361
2362 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2363 {
2364 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2365 return FALSE;
2366 assembly->no_inherit = TRUE;
2367 }
2368
2369 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2370 {
2371 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2372 return FALSE;
2373 }
2374 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2375 assembly->no_inherit)
2376 return FALSE;
2377
2378 while (ret)
2379 {
2380 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2381 {
2382 ret = parse_end_element(xmlbuf);
2383 break;
2384 }
2385 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2386 {
2387 ret = parse_description_elem(xmlbuf);
2388 }
2389 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2390 {
2391 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2392 }
2393 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2394 {
2395 ret = parse_dependency_elem(xmlbuf, acl);
2396 }
2397 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2398 {
2399 ret = parse_file_elem(xmlbuf, assembly, acl);
2400 }
2401 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2402 {
2403 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2404 }
2405 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2406 {
2407 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2408 }
2409 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2410 {
2411 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2412
2413 if (expected_ai)
2414 {
2415 /* FIXME: more tests */
2416 if (assembly->type == ASSEMBLY_MANIFEST &&
2417 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2418 {
2419 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2420 expected_ai->version.major, expected_ai->version.minor,
2421 expected_ai->version.build, expected_ai->version.revision,
2422 assembly->id.version.major, assembly->id.version.minor,
2423 assembly->id.version.build, assembly->id.version.revision);
2424 ret = FALSE;
2425 }
2426 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2427 (assembly->id.version.major != expected_ai->version.major ||
2428 assembly->id.version.minor != expected_ai->version.minor ||
2429 assembly->id.version.build < expected_ai->version.build ||
2430 (assembly->id.version.build == expected_ai->version.build &&
2431 assembly->id.version.revision < expected_ai->version.revision)))
2432 {
2433 DPRINT1("wrong version for shared assembly manifest\n");
2434 ret = FALSE;
2435 }
2436 }
2437 }
2438 #ifdef __REACTOS__
2439 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2440 {
2441 ret = parse_unknown_elem(xmlbuf, &elem);
2442 }
2443 #endif
2444 else
2445 {
2446 attr_nameU = xmlstr2unicode(&elem);
2447 DPRINT1("unknown element %wZ\n", &attr_nameU);
2448 ret = parse_unknown_elem(xmlbuf, &elem);
2449 }
2450 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2451 }
2452
2453 return ret;
2454 }
2455
2456 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2457 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2458 {
2459 xmlstr_t elem;
2460 UNICODE_STRING elemU;
2461
2462 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2463
2464 if (xmlstr_cmp(&elem, g_xmlW) &&
2465 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2466 return STATUS_SXS_CANT_GEN_ACTCTX;
2467
2468 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2469 {
2470 elemU = xmlstr2unicode(&elem);
2471 DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
2472 return STATUS_SXS_CANT_GEN_ACTCTX;
2473 }
2474
2475 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2476 {
2477 DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
2478 return STATUS_SXS_CANT_GEN_ACTCTX;
2479 }
2480
2481 if (next_xml_elem(xmlbuf, &elem))
2482 {
2483 elemU = xmlstr2unicode(&elem);
2484 DPRINT1("unexpected element %wZ\n", &elemU);
2485 return STATUS_SXS_CANT_GEN_ACTCTX;
2486 }
2487
2488 if (xmlbuf->ptr != xmlbuf->end)
2489 {
2490 DPRINT1("parse error\n");
2491 return STATUS_SXS_CANT_GEN_ACTCTX;
2492 }
2493 return STATUS_SUCCESS;
2494 }
2495
2496 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2497 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2498 const void *buffer, SIZE_T size )
2499 {
2500 xmlbuf_t xmlbuf;
2501 NTSTATUS status;
2502 struct assembly *assembly;
2503 int unicode_tests;
2504
2505 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2506
2507 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2508 return STATUS_SXS_CANT_GEN_ACTCTX;
2509
2510 if (directory && !(assembly->directory = strdupW(directory)))
2511 return STATUS_NO_MEMORY;
2512
2513 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2514 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2515 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2516
2517 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2518 if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2519 {
2520 xmlbuf.ptr = buffer;
2521 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2522 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2523 }
2524 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2525 {
2526 const WCHAR *buf = buffer;
2527 WCHAR *new_buff;
2528 unsigned int i;
2529
2530 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2531 return STATUS_NO_MEMORY;
2532 for (i = 0; i < size / sizeof(WCHAR); i++)
2533 new_buff[i] = RtlUshortByteSwap( buf[i] );
2534 xmlbuf.ptr = new_buff;
2535 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2536 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2537 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2538 }
2539 else
2540 {
2541 /* TODO: this doesn't handle arbitrary encodings */
2542 WCHAR *new_buff;
2543 ULONG sizeU;
2544
2545 status = RtlMultiByteToUnicodeSize(&sizeU, buffer, size);
2546 if (!NT_SUCCESS(status))
2547 {
2548 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2549 return STATUS_SXS_CANT_GEN_ACTCTX;
2550 }
2551
2552 new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2553 if (!new_buff)
2554 return STATUS_NO_MEMORY;
2555
2556 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2557 if (!NT_SUCCESS(status))
2558 {
2559 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2560 return STATUS_SXS_CANT_GEN_ACTCTX;
2561 }
2562
2563 xmlbuf.ptr = new_buff;
2564 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2565 status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2566 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2567 }
2568 return status;
2569 }
2570
2571 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2572 {
2573 OBJECT_ATTRIBUTES attr;
2574 IO_STATUS_BLOCK io;
2575
2576 attr.Length = sizeof(attr);
2577 attr.RootDirectory = 0;
2578 attr.Attributes = OBJ_CASE_INSENSITIVE;
2579 attr.ObjectName = name;
2580 attr.SecurityDescriptor = NULL;
2581 attr.SecurityQualityOfService = NULL;
2582 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2583 }
2584
2585 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
2586 {
2587 NTSTATUS status;
2588 ULONG_PTR magic;
2589 LDR_DATA_TABLE_ENTRY *pldr;
2590
2591 LdrLockLoaderLock(0, NULL, &magic);
2592 status = LdrFindEntryForAddress( module, &pldr );
2593 if (status == STATUS_SUCCESS)
2594 {
2595 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2596 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2597 {
2598 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2599 str->Length = pldr->FullDllName.Length;
2600 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2601 }
2602 else status = STATUS_NO_MEMORY;
2603 }
2604 LdrUnlockLoaderLock(0, magic);
2605 return status;
2606 }
2607
2608 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2609 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2610 HANDLE hModule, LPCWSTR resname, ULONG lang )
2611 {
2612 NTSTATUS status;
2613 UNICODE_STRING nameW;
2614 LDR_RESOURCE_INFO info;
2615 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2616 void *ptr;
2617
2618 //DPRINT( "looking for res %s in module %p %s\n", resname,
2619 // hModule, filename );
2620 DPRINT("get_manifest_in_module %p\n", hModule);
2621
2622 #if 0
2623 if (TRACE_ON(actctx))
2624 {
2625 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2626 {
2627 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2628 hModule, debugstr_w(nameW.Buffer) );
2629 RtlFreeUnicodeString( &nameW );
2630 }
2631 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2632 hModule, debugstr_w(filename) );
2633 }
2634 #endif
2635
2636 if (!resname) return STATUS_INVALID_PARAMETER;
2637
2638 info.Type = (ULONG_PTR)RT_MANIFEST;
2639 info.Language = lang;
2640 if (!((ULONG_PTR)resname >> 16))
2641 {
2642 info.Name = (ULONG_PTR)resname;
2643 status = LdrFindResource_U(hModule, &info, 3, &entry);
2644 }
2645 else if (resname[0] == '#')
2646 {
2647 ULONG value;
2648 RtlInitUnicodeString(&nameW, resname + 1);
2649 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2650 return STATUS_INVALID_PARAMETER;
2651 info.Name = value;
2652 status = LdrFindResource_U(hModule, &info, 3, &entry);
2653 }
2654 else
2655 {
2656 RtlCreateUnicodeString(&nameW, resname);
2657 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2658 info.Name = (ULONG_PTR)nameW.Buffer;
2659 status = LdrFindResource_U(hModule, &info, 3, &entry);
2660 RtlFreeUnicodeString(&nameW);
2661 }
2662 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2663
2664 if (status == STATUS_SUCCESS)
2665 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2666
2667 return status;
2668 }
2669
2670 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2671 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2672 HANDLE file, LPCWSTR resname, ULONG lang )
2673 {
2674 HANDLE mapping;
2675 OBJECT_ATTRIBUTES attr;
2676 LARGE_INTEGER size;
2677 LARGE_INTEGER offset;
2678 NTSTATUS status;
2679 SIZE_T count;
2680 void *base;
2681
2682 DPRINT( "looking for res %S in %S\n", resname, filename );
2683
2684 attr.Length = sizeof(attr);
2685 attr.RootDirectory = 0;
2686 attr.ObjectName = NULL;
2687 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2688 attr.SecurityDescriptor = NULL;
2689 attr.SecurityQualityOfService = NULL;
2690
2691 size.QuadPart = 0;
2692 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2693 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2694 if (status != STATUS_SUCCESS) return status;
2695
2696 offset.QuadPart = 0;
2697 count = 0;
2698 base = NULL;
2699 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2700 &count, ViewShare, 0, PAGE_READONLY );
2701 NtClose( mapping );
2702 if (status != STATUS_SUCCESS) return status;
2703
2704 if (RtlImageNtHeader(base)) /* we got a PE file */
2705 {
2706 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2707 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2708 }
2709 else status = STATUS_INVALID_IMAGE_FORMAT;
2710
2711 NtUnmapViewOfSection( NtCurrentProcess(), base );
2712 return status;
2713 }
2714
2715 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2716 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2717 {
2718 FILE_STANDARD_INFORMATION info;
2719 IO_STATUS_BLOCK io;
2720 HANDLE mapping;
2721 OBJECT_ATTRIBUTES attr;
2722 LARGE_INTEGER size;
2723 LARGE_INTEGER offset;
2724 NTSTATUS status;
2725 SIZE_T count;
2726 void *base;
2727
2728 DPRINT( "loading manifest file %S\n", filename );
2729
2730 attr.Length = sizeof(attr);
2731 attr.RootDirectory = 0;
2732 attr.ObjectName = NULL;
2733 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2734 attr.SecurityDescriptor = NULL;
2735 attr.SecurityQualityOfService = NULL;
2736
2737 size.QuadPart = 0;
2738 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2739 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2740
2741 if (status != STATUS_SUCCESS) return status;
2742
2743 offset.QuadPart = 0;
2744 count = 0;
2745 base = NULL;
2746 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2747 &count, ViewShare, 0, PAGE_READONLY );
2748 NtClose( mapping );
2749 if (status != STATUS_SUCCESS) return status;
2750
2751 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2752 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
2753
2754 if (status == STATUS_SUCCESS)
2755 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
2756
2757 NtUnmapViewOfSection( NtCurrentProcess(), base );
2758 return status;
2759 }
2760
2761 /* try to load the .manifest file associated to the file */
2762 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2763 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2764 {
2765 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2766 WCHAR *buffer;
2767 NTSTATUS status;
2768 UNICODE_STRING nameW;
2769 HANDLE file;
2770 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
2771
2772 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2773
2774 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
2775
2776 if (module) /* use the module filename */
2777 {
2778 UNICODE_STRING name;
2779
2780 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2781 {
2782 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2783 strcatW( name.Buffer, dotManifestW );
2784 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2785 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2786 RtlFreeUnicodeString( &name );
2787 }
2788 if (status) return status;
2789 }
2790 else
2791 {
2792 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2793 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2794 return STATUS_NO_MEMORY;
2795 strcpyW( buffer, filename );
2796 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2797 strcatW( buffer, dotManifestW );
2798 RtlInitUnicodeString( &nameW, buffer );
2799 }
2800
2801 if (!open_nt_file( &file, &nameW ))
2802 {
2803 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2804 NtClose( file );
2805 }
2806 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2807 RtlFreeUnicodeString( &nameW );
2808 return status;
2809 }
2810
2811 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2812 {
2813 static const WCHAR lookup_fmtW[] =
2814 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2815 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2816 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2817
2818 WCHAR *lookup, *ret = NULL;
2819 UNICODE_STRING lookup_us;
2820 IO_STATUS_BLOCK io;
2821 const WCHAR *lang = ai->language;
2822 unsigned int data_pos = 0, data_len;
2823 char buffer[8192];
2824
2825 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2826 (strlenW(ai->arch) + strlenW(ai->name)
2827 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2828 + sizeof(lookup_fmtW) )))
2829 return NULL;
2830
2831 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2832 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2833 ai->version.major, ai->version.minor, lang );
2834 RtlInitUnicodeString( &lookup_us, lookup );
2835
2836 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2837 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2838 {
2839 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2840 FILE_BOTH_DIR_INFORMATION *dir_info;
2841 WCHAR *tmp;
2842 ULONG build, revision;
2843
2844 data_len = (ULONG)io.Information;
2845
2846 for (;;)
2847 {
2848 if (data_pos >= data_len)
2849 {
2850 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2851 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2852 break;
2853 data_len = (ULONG)io.Information;
2854 data_pos = 0;
2855 }
2856 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2857
2858 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2859 else data_pos = data_len;
2860
2861 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
2862 build = atoiW(tmp);
2863 if (build < min_build) continue;
2864 tmp = strchrW(tmp, '.') + 1;
2865 revision = atoiW(tmp);
2866 if (build == min_build && revision < min_revision) continue;
2867 tmp = strchrW(tmp, '_') + 1;
2868 tmp = strchrW(tmp, '_') + 1;
2869 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2870 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2871 {
2872 /* prefer a non-Wine manifest if we already have one */
2873 /* we'll still load the builtin dll if specified through DllOverrides */
2874 if (ret) continue;
2875 }
2876 else
2877 {
2878 min_build = build;
2879 min_revision = revision;
2880 }
2881 ai->version.build = build;
2882 ai->version.revision = revision;
2883 RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
2884 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2885 {
2886 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2887 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2888 }
2889 }
2890 }
2891 else DPRINT1("no matching file for %S\n", lookup);
2892 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
2893 return ret;
2894 }
2895
2896 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2897 {
2898 struct assembly_identity sxs_ai;
2899 UNICODE_STRING path_us;
2900 OBJECT_ATTRIBUTES attr;
2901 IO_STATUS_BLOCK io;
2902 WCHAR *path, *file = NULL;
2903 HANDLE handle;
2904
2905 static const WCHAR manifest_dirW[] =
2906 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2907
2908 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2909
2910 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2911 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
2912 return STATUS_NO_MEMORY;
2913
2914 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
2915 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
2916
2917 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2918 {
2919 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2920 return STATUS_NO_SUCH_FILE;
2921 }
2922 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2923
2924 attr.Length = sizeof(attr);
2925 attr.RootDirectory = 0;
2926 attr.Attributes = OBJ_CASE_INSENSITIVE;
2927 attr.ObjectName = &path_us;
2928 attr.SecurityDescriptor = NULL;
2929 attr.SecurityQualityOfService = NULL;
2930
2931 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2932 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2933 {
2934 sxs_ai = *ai;
2935 file = lookup_manifest_file( handle, &sxs_ai );
2936 NtClose( handle );
2937 }
2938 if (!file)
2939 {
2940 RtlFreeUnicodeString( &path_us );
2941 return STATUS_NO_SUCH_FILE;
2942 }
2943
2944 /* append file name to directory path */
2945 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
2946 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2947 {
2948 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2949 RtlFreeUnicodeString( &path_us );
2950 return STATUS_NO_MEMORY;
2951 }
2952
2953 path[path_us.Length/sizeof(WCHAR)] = '\\';
2954 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2955 RtlInitUnicodeString( &path_us, path );
2956 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2957
2958 if (!open_nt_file( &handle, &path_us ))
2959 {
2960 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2961 NtClose( handle );
2962 }
2963 else io.Status = STATUS_NO_SUCH_FILE;
2964
2965 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2966 RtlFreeUnicodeString( &path_us );
2967 return io.Status;
2968 }
2969
2970 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2971 struct assembly_identity* ai)
2972 {
2973 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2974 unsigned int i;
2975 WCHAR *buffer, *p, *directory;
2976 NTSTATUS status;
2977 UNICODE_STRING nameW;
2978 HANDLE file;
2979 DWORD len;
2980
2981 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2982 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
2983
2984 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2985
2986 /* FIXME: add support for language specific lookup */
2987
2988 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2989 strlenW(acl->actctx->appdir.info));
2990
2991 nameW.Buffer = NULL;
2992 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2993 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2994 return STATUS_NO_MEMORY;
2995
2996 if (!(directory = build_assembly_dir( ai )))
2997 {
2998 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
2999 return STATUS_NO_MEMORY;
3000 }
3001
3002 /* Lookup in <dir>\name.dll
3003 * <dir>\name.manifest
3004 * <dir>\name\name.dll
3005 * <dir>\name\name.manifest
3006 *
3007 * First 'appdir' is used as <dir>, if that failed
3008 * it tries application manifest file path.
3009 */
3010 strcpyW( buffer, acl->actctx->appdir.info );
3011 p = buffer + strlenW(buffer);
3012 for (i = 0; i < 4; i++)
3013 {
3014 if (i == 2)
3015 {
3016 struct assembly *assembly = acl->actctx->assemblies;
3017 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3018 }
3019 else *p++ = '\\';
3020
3021 strcpyW( p, ai->name );
3022 p += strlenW(p);
3023
3024 strcpyW( p, dotDllW );
3025 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3026 {
3027 status = open_nt_file( &file, &nameW );
3028 if (!status)
3029 {
3030 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3031 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3032 NtClose( file );
3033 break;
3034 }
3035 RtlFreeUnicodeString( &nameW );
3036 }
3037
3038 strcpyW( p, dotManifestW );
3039 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3040 {
3041 status = open_nt_file( &file, &nameW );
3042 if (!status)
3043 {
3044 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3045 NtClose( file );
3046 break;
3047 }
3048 RtlFreeUnicodeString( &nameW );
3049 }
3050 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3051 }
3052 RtlFreeUnicodeString( &nameW );
3053 RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
3054 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3055 return status;
3056 }
3057
3058 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3059 {
3060 NTSTATUS status = STATUS_SUCCESS;
3061 unsigned int i;
3062
3063 for (i = 0; i < acl->num_dependencies; i++)
3064 {
3065 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3066 {
3067 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3068 {
3069 const struct assembly_version *ver = &acl->dependencies[i].version;
3070 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3071 acl->dependencies[i].name,
3072 ver->major, ver->minor, ver->build, ver->revision );
3073 status = STATUS_SXS_CANT_GEN_ACTCTX;
3074 break;
3075 }
3076 }
3077 }
3078 /* FIXME should now iterate through all refs */
3079 return status;
3080 }
3081
3082 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3083 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3084 {
3085 NTSTATUS status = STATUS_SUCCESS;
3086
3087 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT)
3088 {
3089 if (*handle) return STATUS_INVALID_PARAMETER;
3090
3091 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
3092 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
3093 }
3094 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE))
3095 {
3096 ULONG_PTR magic;
3097 LDR_DATA_TABLE_ENTRY *pldr;
3098
3099 if (!*handle) return STATUS_INVALID_PARAMETER;
3100
3101 LdrLockLoaderLock( 0, NULL, &magic );
3102 if (!LdrFindEntryForAddress( *handle, &pldr ))
3103 {
3104 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase)
3105 status = STATUS_DLL_NOT_FOUND;
3106 else
3107 *handle = pldr->EntryPointActivationContext;
3108 }
3109 else status = STATUS_DLL_NOT_FOUND;
3110 LdrUnlockLoaderLock( 0, magic );
3111 }
3112 else if (!*handle && (class != ActivationContextBasicInformation))
3113 *handle = process_actctx;
3114
3115 return status;
3116 }
3117
3118 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3119 {
3120 unsigned int i, j, total_len = 0, dll_count = 0;
3121 struct strsection_header *header;
3122 struct dllredirect_data *data;
3123 struct string_index *index;
3124 ULONG name_offset;
3125
3126 DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies);
3127
3128 /* compute section length */
3129 for (i = 0; i < actctx->num_assemblies; i++)
3130 {
3131 struct assembly *assembly = &actctx->assemblies[i];
3132 for (j = 0; j < assembly->num_dlls; j++)
3133 {
3134 struct dll_redirect *dll = &assembly->dlls[j];
3135
3136 /* each entry needs index, data and string data */
3137 total_len += sizeof(*index);
3138 total_len += sizeof(*data);
3139 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3140
3141 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name);
3142 }
3143
3144 dll_count += assembly->num_dlls;
3145 }
3146
3147 total_len += sizeof(*header);
3148
3149 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3150 if (!header) return STATUS_NO_MEMORY;
3151
3152 memset(header, 0, sizeof(*header));
3153 header->magic = STRSECTION_MAGIC;
3154 header->size = sizeof(*header);
3155 header->count = dll_count;
3156 header->index_offset = sizeof(*header);
3157 index = (struct string_index*)((BYTE*)header + header->index_offset);
3158 name_offset = header->index_offset + header->count*sizeof(*index);
3159
3160 for (i = 0; i < actctx->num_assemblies; i++)
3161 {
3162 struct assembly *assembly = &actctx->assemblies[i];
3163
3164 DPRINT("assembly->num_dlls %d\n", assembly->num_dlls);
3165
3166 for (j = 0; j < assembly->num_dlls; j++)
3167 {
3168 struct dll_redirect *dll = &assembly->dlls[j];
3169 UNICODE_STRING str;
3170 WCHAR *ptrW;
3171
3172 DPRINT("%d: dll name %S\n", j, dll->name);
3173 /* setup new index entry */
3174 str.Buffer = dll->name;
3175 str.Length = (USHORT)strlenW(dll->name)*sizeof(WCHAR);
3176 str.MaximumLength = str.Length + sizeof(WCHAR);
3177 /* hash original class name */
3178 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3179
3180 index->name_offset = name_offset;
3181 index->name_len = str.Length;
3182 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3183 index->data_len = sizeof(*data);
3184 index->rosterindex = i + 1;
3185
3186 /* setup data */
3187 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3188 data->size = sizeof(*data);
3189 data->unk = 2; /* FIXME: seems to be constant */
3190 memset(data->res, 0, sizeof(data->res));
3191
3192 /* dll name */
3193 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3194 memcpy(ptrW, dll->name, index->name_len);
3195 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3196
3197 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3198
3199 index++;
3200 }
3201 }
3202
3203 *section = header;
3204
3205 return STATUS_SUCCESS;
3206 }
3207
3208 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3209 {
3210 struct string_index *iter, *index = NULL;
3211 ULONG hash = 0, i;
3212
3213 DPRINT("section %p, name %wZ\n", section, name);
3214 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3215 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3216
3217 for (i = 0; i < section->count; i++)
3218 {
3219 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash);
3220 DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset));
3221 if (iter->hash == hash)
3222 {
3223 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3224
3225 if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) &&
3226 wcslen(nameW) == name->Length / sizeof(WCHAR))
3227 {
3228 index = iter;
3229 break;
3230 }
3231 else
3232 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3233 }
3234 iter++;
3235 }
3236
3237 return index;
3238 }
3239
3240 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3241 {
3242 struct guid_index *iter, *index = NULL;
3243 ULONG i;
3244
3245 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3246
3247 for (i = 0; i < section->count; i++)
3248 {
3249 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3250 {
3251 index = iter;
3252 break;
3253 }
3254 iter++;
3255 }
3256
3257 return index;
3258 }
3259
3260 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3261 {
3262 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3263 }
3264
3265 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3266 PACTCTX_SECTION_KEYED_DATA data)
3267 {
3268 struct dllredirect_data *dll;
3269 struct string_index *index;
3270
3271 DPRINT("sections: 0x%08X\n", actctx->sections);
3272 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3273
3274 DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section);
3275 if (!actctx->dllredirect_section)
3276 {
3277 struct strsection_header *section;
3278
3279 NTSTATUS status = build_dllredirect_section(actctx, &section);
3280 if (status) return status;
3281
3282 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3283 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3284 }
3285
3286 index = find_string_index(actctx->dllredirect_section, name);
3287 DPRINT("index: %d\n", index);
3288 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3289
3290 if (data)
3291 {
3292 dll = get_dllredirect_data(actctx, index);
3293
3294 data->ulDataFormatVersion = 1;
3295 data->lpData = dll;
3296 data->ulLength = dll->size;
3297 data->lpSectionGlobalData = NULL;
3298 data->ulSectionGlobalDataLength = 0;
3299 data->lpSectionBase = actctx->dllredirect_section;
3300 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
3301 data->hActCtx = NULL;
3302
3303 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3304 data->ulAssemblyRosterIndex = index->rosterindex;
3305 }
3306
3307 return STATUS_SUCCESS;
3308 }
3309
3310 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3311 {
3312 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3313 }
3314
3315 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3316 {
3317 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3318 }
3319
3320 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3321 {
3322 unsigned int i, j, k, total_len = 0, class_count = 0;
3323 struct wndclass_redirect_data *data;
3324 struct strsection_header *header;
3325 struct string_index *index;
3326 ULONG name_offset;
3327
3328 /* compute section length */
3329 for (i = 0; i < actctx->num_assemblies; i++)
3330 {
3331 struct assembly *assembly = &actctx->assemblies[i];
3332 for (j = 0; j < assembly->num_dlls; j++)
3333 {
3334 struct dll_redirect *dll = &assembly->dlls[j];
3335 for (k = 0; k < dll->entities.num; k++)
3336 {
3337 struct entity *entity = &dll->entities.base[k];
3338 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3339 {
3340 int class_len = strlenW(entity->u.class.name) + 1;
3341 int len;
3342
3343 /* each class entry needs index, data and string data */
3344 total_len += sizeof(*index);
3345 total_len += sizeof(*data);
3346 /* original name is stored separately */
3347 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3348 /* versioned name and module name are stored one after another */
3349 if (entity->u.class.versioned)
3350 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3351 else
3352 len = class_len;
3353 len += strlenW(dll->name) + 1;
3354 total_len += aligned_string_len(len*sizeof(WCHAR));
3355
3356 class_count++;
3357 }
3358 }
3359 }
3360 }
3361
3362 total_len += sizeof(*header);
3363
3364 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3365 if (!header) return STATUS_NO_MEMORY;
3366
3367 memset(header, 0, sizeof(*header));
3368 header->magic = STRSECTION_MAGIC;
3369 header->size = sizeof(*header);
3370 header->count = class_count;
3371 header->index_offset = sizeof(*header);
3372 index = (struct string_index*)((BYTE*)header + header->index_offset);
3373 name_offset = header->index_offset + header->count*sizeof(*index);
3374
3375 for (i = 0; i < actctx->num_assemblies; i++)
3376 {
3377 struct assembly *assembly = &actctx->assemblies[i];
3378 for (j = 0; j < assembly->num_dlls; j++)
3379 {
3380 struct dll_redirect *dll = &assembly->dlls[j];
3381 for (k = 0; k < dll->entities.num; k++)
3382 {
3383 struct entity *entity = &dll->entities.base[k];
3384 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3385 {
3386 static const WCHAR exclW[] = {'!',0};
3387 ULONG versioned_len, module_len;
3388 UNICODE_STRING str;
3389 WCHAR *ptrW;
3390
3391 /* setup new index entry */
3392 str.Buffer = entity->u.class.name;
3393 str.Length = (USHORT)strlenW(entity->u.class.name)*sizeof(WCHAR);
3394 str.MaximumLength = str.Length + sizeof(WCHAR);
3395 /* hash original class name */
3396 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3397
3398 /* include '!' separator too */
3399 if (entity->u.class.versioned)
3400 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3401 else
3402 versioned_len = str.Length;
3403 module_len = strlenW(dll->name)*sizeof(WCHAR);
3404
3405 index->name_offset = name_offset;
3406 index->name_len = str.Length;
3407 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3408 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3409 index->rosterindex = i + 1;
3410
3411 /* setup data */
3412 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3413 data->size = sizeof(*data);
3414 data->res = 0;
3415 data->name_len = versioned_len;
3416 data->name_offset = sizeof(*data);
3417 data->module_len = module_len;
3418 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3419
3420 /* original class name */
3421 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3422 memcpy(ptrW, entity->u.class.name, index->name_len);
3423 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3424
3425 /* module name */
3426 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3427 memcpy(ptrW, dll->name, data->module_len);
3428 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3429
3430 /* versioned name */
3431 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3432 if (entity->u.class.versioned)
3433 {
3434 get_assembly_version(assembly, ptrW);
3435 strcatW(ptrW, exclW);
3436 strcatW(ptrW, entity->u.class.name);
3437 }
3438 else
3439 {
3440 memcpy(ptrW, entity->u.class.name, index->name_len);
3441 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3442 }
3443
3444 name_offset += sizeof(*data);
3445 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3446
3447 index++;
3448 }
3449 }
3450 }
3451 }
3452
3453 *section = header;
3454
3455 return STATUS_SUCCESS;
3456 }
3457
3458 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3459 PACTCTX_SECTION_KEYED_DATA data)
3460 {
3461 struct string_index *iter, *index = NULL;
3462 struct wndclass_redirect_data *class;
3463 ULONG hash;
3464 int i;
3465
3466 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3467
3468 if (!actctx->wndclass_section)
3469 {
3470 struct strsection_header *section;
3471
3472 NTSTATUS status = build_wndclass_section(actctx, &section);
3473 if (status) return status;
3474
3475 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3476 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3477 }
3478
3479 hash = 0;
3480 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3481 iter = get_wndclass_first_index(actctx);
3482
3483 for (i = 0; i < actctx->wndclass_section->count; i++)
3484 {
3485 if (iter->hash == hash)
3486 {
3487 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3488
3489 if (!strcmpiW(nameW, name->Buffer))
3490 {
3491 index = iter;
3492 break;
3493 }
3494 else
3495 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3496 }
3497 iter++;
3498 }
3499
3500 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3501
3502 if (data)
3503 {
3504 class = get_wndclass_data(actctx, index);
3505
3506 data->ulDataFormatVersion = 1;
3507 data->lpData = class;
3508 /* full length includes string length with nulls */
3509 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3510 data->lpSectionGlobalData = NULL;
3511 data->ulSectionGlobalDataLength = 0;
3512 data->lpSectionBase = actctx->wndclass_section;
3513 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
3514 data->hActCtx = NULL;
3515
3516 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3517 data->ulAssemblyRosterIndex = index->rosterindex;
3518 }
3519
3520 return STATUS_SUCCESS;
3521 }
3522
3523 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3524 {
3525 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3526 struct guidsection_header *header;
3527 ULONG module_offset, data_offset;
3528 struct tlibredirect_data *data;
3529 struct guid_index *index;
3530
3531 /* compute section length */
3532 for (i = 0; i < actctx->num_assemblies; i++)
3533 {
3534 struct assembly *assembly = &actctx->assemblies[i];
3535 for (j = 0; j < assembly->num_dlls; j++)
3536 {
3537 struct dll_redirect *dll = &assembly->dlls[j];
3538 for (k = 0; k < dll->entities.num; k++)
3539 {
3540 struct entity *entity = &dll->entities.base[k];
3541 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3542 {
3543 /* each entry needs index, data and string data for module name and help string */
3544 total_len += sizeof(*index);
3545 total_len += sizeof(*data);
3546 /* help string is stored separately */
3547 if (*entity->u.typelib.helpdir)
3548 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3549
3550 /* module names are packed one after another */
3551 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3552
3553 tlib_count++;
3554 }
3555 }
3556 }
3557 }
3558
3559 total_len += aligned_string_len(names_len);
3560 total_len += sizeof(*header);
3561
3562 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3563 if (!header) return STATUS_NO_MEMORY;
3564
3565 memset(header, 0, sizeof(*header));
3566 header->magic = GUIDSECTION_MAGIC;
3567 header->size = sizeof(*header);
3568 header->count = tlib_count;
3569 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3570 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3571 module_offset = sizeof(*header);
3572 data_offset = header->index_offset + tlib_count*sizeof(*index);
3573
3574 for (i = 0; i < actctx->num_assemblies; i++)
3575 {
3576 struct assembly *assembly = &actctx->assemblies[i];
3577 for (j = 0; j < assembly->num_dlls; j++)
3578 {
3579 struct dll_redirect *dll = &assembly->dlls[j];
3580 for (k = 0; k < dll->entities.num; k++)
3581 {
3582 struct entity *entity = &dll->entities.base[k];
3583 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3584 {
3585 ULONG module_len, help_len;
3586 UNICODE_STRING str;
3587 WCHAR *ptrW;
3588
3589 if (*entity->u.typelib.helpdir)
3590 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3591 else
3592 help_len = 0;
3593
3594 module_len = strlenW(dll->name)*sizeof(WCHAR);
3595
3596 /* setup new index entry */
3597 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3598 RtlGUIDFromString(&str, &index->guid);
3599 index->data_offset = data_offset;
3600 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3601 index->rosterindex = i + 1;
3602
3603 /* setup data */
3604 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3605 data->size = sizeof(*data);
3606 data->res = 0;
3607 data->name_len = module_len;
3608 data->name_offset = module_offset;
3609 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3610 data->langid = 0;
3611 data->flags = entity->u.typelib.flags;
3612 data->help_len = help_len;
3613 data->help_offset = sizeof(*data);
3614 data->major_version = entity->u.typelib.major;
3615 data->minor_version = entity->u.typelib.minor;
3616
3617 /* module name */
3618 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3619 memcpy(ptrW, dll->name, data->name_len);
3620 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3621
3622 /* help string */
3623 if (data->help_len)
3624 {
3625 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3626 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3627 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3628 }
3629
3630 data_offset += sizeof(*data);
3631 if (help_len)
3632 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3633
3634 module_offset += module_len + sizeof(WCHAR);
3635
3636 index++;
3637 }
3638 }
3639 }
3640 }
3641
3642 *section = header;
3643
3644 return STATUS_SUCCESS;
3645 }
3646
3647 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3648 {
3649 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3650 }
3651
3652 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3653 {
3654 struct guid_index *index = NULL;
3655 struct tlibredirect_data *tlib;
3656
3657 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3658
3659 if (!actctx->tlib_section)
3660 {
3661 struct guidsection_header *section;
3662
3663 NTSTATUS status = build_tlib_section(actctx, &section);
3664 if (status) return status;
3665
3666 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3667 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3668 }
3669
3670 index = find_guid_index(actctx->tlib_section, guid);
3671 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3672
3673 tlib = get_tlib_data(actctx, index);
3674
3675 data->ulDataFormatVersion = 1;
3676 data->lpData = tlib;
3677 /* full length includes string length with nulls */
3678 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3679 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3680 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3681 data->lpSectionBase = actctx->tlib_section;
3682 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
3683 data->hActCtx = NULL;
3684
3685 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3686 data->ulAssemblyRosterIndex = index->rosterindex;
3687
3688 return STATUS_SUCCESS;
3689 }
3690
3691 static void generate_uuid(ULONG *seed, GUID *guid)
3692 {
3693 ULONG *ptr = (ULONG*)guid;
3694 int i;
3695
3696 /* GUID is 16 bytes long */
3697 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3698 *ptr = RtlUniform(seed);
3699
3700 guid->Data3 &= 0x0fff;
3701 guid->Data3 |= (4 << 12);
3702 guid->Data4[0] &= 0x3f;
3703 guid->Data4[0] |= 0x80;
3704 }
3705
3706 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3707 unsigned int *count, unsigned int *len, unsigned int *module_len)
3708 {
3709 unsigned int i;
3710
3711 for (i = 0; i < entities->num; i++)
3712 {
3713 struct entity *entity = &entities->base[i];
3714 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3715 {
3716 /* each entry needs two index entries, extra one goes for alias GUID */
3717 *len += 2*sizeof(struct guid_index);
3718 /* To save some memory we don't allocated two data structures,
3719 instead alias index and normal index point to the same data structure. */
3720 *len += sizeof(struct comclassredirect_data);
3721
3722 /* for clrClass store some more */
3723 if (entity->u.comclass.name)
3724 {
3725 unsigned int str_len;
3726
3727 /* all string data is stored together in aligned block */
3728 str_len = strlenW(entity->u.comclass.name)+1;
3729 if (entity->u.comclass.progid)
3730 str_len += strlenW(entity->u.comclass.progid)+1;
3731 if (entity->u.comclass.version)
3732 str_len += strlenW(entity->u.comclass.version)+1;
3733
3734 *len += sizeof(struct clrclass_data);
3735 *len += aligned_string_len(str_len*sizeof(WCHAR));
3736
3737 /* module name is forced to mscoree.dll, and stored two times with different case */
3738 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3739 }
3740 else
3741 {
3742 /* progid string is stored separately */
3743 if (entity->u.comclass.progid)
3744 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3745
3746 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3747 }
3748
3749 *count += 1;
3750 }
3751 }
3752 }
3753
3754 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3755 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3756 ULONG *seed, ULONG rosterindex)
3757 {
3758 unsigned int i;
3759
3760 for (i = 0; i < entities->num; i++)
3761 {
3762 struct entity *entity = &entities->base[i];
3763 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3764 {
3765 ULONG module_len, progid_len, str_len = 0;
3766 struct comclassredirect_data *data;
3767 struct guid_index *alias_index;
3768 struct clrclass_data *clrdata;
3769 UNICODE_STRING str;
3770 WCHAR *ptrW;
3771
3772 if (entity->u.comclass.progid)
3773 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3774 else
3775 progid_len = 0;
3776
3777 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3778
3779 /* setup new index entry */
3780 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3781 RtlGUIDFromString(&str, &(*index)->guid);
3782
3783 (*index)->data_offset = *data_offset;
3784 (*index)->data_len = sizeof(*data); /* additional length added later */
3785 (*index)->rosterindex = rosterindex;
3786
3787 /* Setup new index entry for alias guid. Alias index records are placed after
3788 normal records, so normal guids are hit first on search. Note that class count
3789 is doubled. */
3790 alias_index = (*index) + section->count/2;
3791 generate_uuid(seed, &alias_index->guid);
3792 alias_index->data_offset = (*index)->data_offset;
3793 alias_index->data_len = 0;
3794 alias_index->rosterindex = (*index)->rosterindex;
3795
3796 /* setup data */
3797 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3798 data->size = sizeof(*data);
3799 data->res = 0;
3800 data->res1[0] = 0;
3801 data->res1[1] = 0;
3802 data->model = entity->u.comclass.model;
3803 data->clsid = (*index)->guid;
3804 data->alias = alias_index->guid;
3805 data->clsid2 = data->clsid;
3806 if (entity->u.comclass.tlbid)
3807 {
3808 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3809 RtlGUIDFromString(&str, &data->tlbid);
3810 }
3811 else
3812 memset(&data->tlbid, 0, sizeof(data->tlbid));
3813 data->name_len = module_len;
3814 data->name_offset = *module_offset;
3815 data->progid_len = progid_len;
3816 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3817 data->clrdata_len = 0; /* will be set later */
3818 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3819 data->miscstatus = entity->u.comclass.miscstatus;
3820 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3821 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3822 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3823 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3824
3825 /* mask describes which misc* data is available */
3826 data->miscmask = 0;
3827 if (data->miscstatus)
3828 data->miscmask |= MiscStatus;
3829 if (data->miscstatuscontent)
3830 data->miscmask |= MiscStatusContent;
3831 if (data->miscstatusthumbnail)
3832 data->miscmask |= MiscStatusThumbnail;
3833 if (data->miscstatusicon)
3834 data->miscmask |= MiscStatusIcon;
3835 if (data->miscstatusdocprint)
3836 data->miscmask |= MiscStatusDocPrint;
3837
3838 if (data->clrdata_offset)
3839 {
3840 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3841
3842 clrdata->size = sizeof(*clrdata);
3843 clrdata->res[0] = 0;
3844 clrdata->res[1] = 2; /* FIXME: unknown field */
3845 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3846 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3847 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3848 clrdata->name_offset = clrdata->size;
3849 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3850 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3851 clrdata->res2[0] = 0;
3852 clrdata->res2[1] = 0;
3853
3854 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3855
3856 /* module name */
3857 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3858 memcpy(ptrW, mscoree2W, clrdata->module_len);
3859 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3860
3861 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3862 memcpy(ptrW, mscoreeW, data->name_len);
3863 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3864
3865 /* class name */
3866 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3867 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3868 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3869
3870 /* runtime version, optional */
3871 if (clrdata->version_len)
3872 {
3873 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3874
3875 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3876 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3877 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3878 }
3879
3880 if (data->progid_len)
3881 data->progid_offset += data->clrdata_len;
3882 (*index)->data_len += sizeof(*clrdata);
3883 }
3884 else
3885 {
3886 clrdata = NULL;
3887
3888 /* module name */
3889 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3890 memcpy(ptrW, dll->name, data->name_len);
3891 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3892 }
3893
3894 /* progid string */
3895 if (data->progid_len)
3896 {
3897 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3898 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3899 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3900 }
3901
3902 /* string block length */
3903 str_len = 0;
3904 if (clrdata)
3905 {
3906 str_len += clrdata->name_len + sizeof(WCHAR);
3907 if (clrdata->version_len)
3908 str_len += clrdata->version_len + sizeof(WCHAR);
3909 }
3910 if (progid_len)
3911 str_len += progid_len + sizeof(WCHAR);
3912
3913 (*index)->data_len += aligned_string_len(str_len);
3914 alias_index->data_len = (*index)->data_len;
3915
3916 /* move to next data record */
3917 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3918 (*module_offset) += module_len + sizeof(WCHAR);
3919
3920 if (clrdata)
3921 {
3922 (*data_offset) += sizeof(*clrdata);
3923 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3924 }
3925 (*index) += 1;
3926 }
3927 }
3928 }
3929
3930 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3931 {
3932 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3933 struct guidsection_header *header;
3934 ULONG module_offset, data_offset;
3935 struct guid_index *index;
3936 ULONG seed;
3937
3938 /* compute section length */
3939 for (i = 0; i < actctx->num_assemblies; i++)
3940 {
3941 struct assembly *assembly = &actctx->assemblies[i];
3942 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3943 for (j = 0; j < assembly->num_dlls; j++)
3944 {
3945 struct dll_redirect *dll = &assembly->dlls[j];
3946 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3947 }
3948 }
3949
3950 total_len += aligned_string_len(names_len);
3951 total_len += sizeof(*header);
3952
3953 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3954 if (!header) return STATUS_NO_MEMORY;
3955
3956 memset(header, 0, sizeof(*header));
3957 header->magic = GUIDSECTION_MAGIC;
3958 header->size = sizeof(*header);
3959 header->count = 2*class_count;
3960 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3961 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3962 module_offset = sizeof(*header);
3963 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3964
3965 seed = NtGetTickCount();
3966 for (i = 0; i < actctx->num_assemblies; i++)
3967 {
3968 struct assembly *assembly = &actctx->assemblies[i];
3969 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3970 for (j = 0; j < assembly->num_dlls; j++)
3971 {
3972 struct dll_redirect *dll = &assembly->dlls[j];
3973 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3974 }
3975 }
3976
3977 *section = header;
3978
3979 return STATUS_SUCCESS;
3980 }
3981
3982 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3983 {
3984 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3985 }
3986
3987 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3988 {
3989 struct comclassredirect_data *comclass;
3990 struct guid_index *index = NULL;
3991
3992 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3993
3994 if (!actctx->comserver_section)
3995 {
3996 struct guidsection_header *section;
3997
3998 NTSTATUS status = build_comserver_section(actctx, &section);
3999 if (status) return status;
4000
4001 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4002 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4003 }
4004
4005 index = find_guid_index(actctx->comserver_section, guid);
4006 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4007
4008 comclass = get_comclass_data(actctx, index);
4009
4010 data->ulDataFormatVersion = 1;
4011 data->lpData = comclass;
4012 /* full length includes string length with nulls */
4013 data->ulLength = comclass->size + comclass->clrdata_len;
4014 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4015 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4016 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4017 data->lpSectionBase = actctx->comserver_section;
4018 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
4019 data->hActCtx = NULL;
4020
4021 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4022 data->ulAssemblyRosterIndex = index->rosterindex;
4023
4024 return STATUS_SUCCESS;
4025 }
4026
4027 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4028 {
4029 unsigned int i;
4030
4031 for (i = 0; i < entities->num; i++)
4032 {
4033 struct entity *entity = &entities->base[i];
4034 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4035 {
4036 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4037 if (entity->u.ifaceps.name)
4038 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4039 *count += 1;
4040 }
4041 }
4042 }
4043
4044 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4045 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4046 {
4047 unsigned int i;
4048
4049 for (i = 0; i < entities->num; i++)
4050 {
4051 struct entity *entity = &entities->base[i];
4052 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4053 {
4054 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4055 UNICODE_STRING str;
4056 ULONG name_len;
4057
4058 if (entity->u.ifaceps.name)
4059 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4060 else
4061 name_len = 0;
4062
4063 /* setup index */
4064 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4065 RtlGUIDFromString(&str, &(*index)->guid);
4066 (*index)->data_offset = *data_offset;
4067 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4068 (*index)->rosterindex = rosterindex;
4069
4070 /* setup data record */
4071 data->size = sizeof(*data);
4072 data->mask = entity->u.ifaceps.mask;
4073
4074 /* proxyStubClsid32 value is only stored for external PS,
4075 if set it's used as iid, otherwise 'iid' attribute value is used */
4076 if (entity->u.ifaceps.ps32)
4077 {
4078 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4079 RtlGUIDFromString(&str, &data->iid);
4080 }
4081 else
4082 data->iid = (*index)->guid;
4083
4084 data->nummethods = entity->u.ifaceps.nummethods;
4085
4086 if (entity->u.ifaceps.tlib)
4087 {
4088 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4089 RtlGUIDFromString(&str, &data->tlbid);
4090 }
4091 else
4092 memset(&data->tlbid, 0, sizeof(data->tlbid));
4093
4094 if (entity->u.ifaceps.base)
4095 {
4096 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4097 RtlGUIDFromString(&str, &data->base);
4098 }
4099 else
4100 memset(&data->base, 0, sizeof(data->base));
4101
4102 data->name_len = name_len;
4103 data->name_offset = data->name_len ? sizeof(*data) : 0;
4104
4105 /* name string */
4106 if (data->name_len)
4107 {
4108 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4109 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4110 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4111 }
4112
4113 /* move to next record */
4114 (*index) += 1;
4115 *data_offset += sizeof(*data);
4116 if (data->name_len)
4117 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4118 }
4119 }
4120 }
4121
4122 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4123 {
4124 unsigned int i, j, total_len = 0, count = 0;
4125 struct guidsection_header *header;
4126 struct guid_index *index;
4127 ULONG data_offset;
4128
4129 /* compute section length */
4130 for (i = 0; i < actctx->num_assemblies; i++)
4131 {
4132 struct assembly *assembly = &actctx->assemblies[i];
4133
4134 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4135 for (j = 0; j < assembly->num_dlls; j++)
4136 {
4137 struct dll_redirect *dll = &assembly->dlls[j];
4138 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4139 }
4140 }
4141
4142 total_len += sizeof(*header);
4143
4144 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4145 if (!header) return STATUS_NO_MEMORY;
4146
4147 memset(header, 0, sizeof(*header));
4148 header->magic = GUIDSECTION_MAGIC;
4149 header->size = sizeof(*header);
4150 header->count = count;
4151 header->index_offset = sizeof(*header);
4152 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4153 data_offset = header->index_offset + count*sizeof(*index);
4154
4155 for (i = 0; i < actctx->num_assemblies; i++)
4156 {
4157 struct assembly *assembly = &actctx->assemblies[i];
4158
4159 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4160 for (j = 0; j < assembly->num_dlls; j++)
4161 {
4162 struct dll_redirect *dll = &assembly->dlls[j];
4163 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4164 }
4165 }
4166
4167 *section = header;
4168
4169 return STATUS_SUCCESS;
4170 }
4171
4172 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4173 {
4174 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4175 }
4176
4177 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4178 {
4179 struct ifacepsredirect_data *iface;
4180 struct guid_index *index = NULL;
4181
4182 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4183
4184 if (!actctx->ifaceps_section)
4185 {
4186 struct guidsection_header *section;
4187
4188 NTSTATUS status = build_ifaceps_section(actctx, &section);
4189 if (status) return status;
4190
4191 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4192 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4193 }
4194
4195 index = find_guid_index(actctx->ifaceps_section, guid);
4196 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4197
4198 iface = get_ifaceps_data(actctx, index);
4199
4200 data->ulDataFormatVersion = 1;
4201 data->lpData = iface;
4202 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4203 data->lpSectionGlobalData = NULL;
4204 data->ulSectionGlobalDataLength = 0;
4205 data->lpSectionBase = actctx->ifaceps_section;
4206 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
4207 data->hActCtx = NULL;
4208
4209 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4210 data->ulAssemblyRosterIndex = index->rosterindex;
4211
4212 return STATUS_SUCCESS;
4213 }
4214
4215 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4216 {
4217 unsigned int i, j, total_len = 0, count = 0;
4218 struct guidsection_header *header;
4219 struct clrsurrogate_data *data;
4220 struct guid_index *index;
4221 ULONG data_offset;
4222
4223 /* compute section length */
4224 for (i = 0; i < actctx->num_assemblies; i++)
4225 {
4226 struct assembly *assembly = &actctx->assemblies[i];
4227 for (j = 0; j < assembly->entities.num; j++)
4228 {
4229 struct entity *entity = &assembly->entities.base[j];
4230 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4231 {
4232 ULONG len;
4233
4234 total_len += sizeof(*index) + sizeof(*data);
4235 len = strlenW(entity->u.clrsurrogate.name) + 1;
4236 if (entity->u.clrsurrogate.version)
4237 len += strlenW(entity->u.clrsurrogate.version) + 1;
4238 total_len += aligned_string_len(len*sizeof(WCHAR));
4239
4240 count++;
4241 }
4242 }
4243 }
4244
4245 total_len += sizeof(*header);
4246
4247 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4248 if (!header) return STATUS_NO_MEMORY;
4249
4250 memset(header, 0, sizeof(*header));
4251 header->magic = GUIDSECTION_MAGIC;
4252 header->size = sizeof(*header);
4253 header->count = count;
4254 header->index_offset = sizeof(*header);
4255 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4256 data_offset = header->index_offset + count*sizeof(*index);
4257
4258 for (i = 0; i < actctx->num_assemblies; i++)
4259 {
4260 struct assembly *assembly = &actctx->assemblies[i];
4261 for (j = 0; j < assembly->entities.num; j++)
4262 {
4263 struct entity *entity = &assembly->entities.base[j];
4264 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4265 {
4266 ULONG version_len, name_len;
4267 UNICODE_STRING str;
4268 WCHAR *ptrW;
4269
4270 if (entity->u.clrsurrogate.version)
4271 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4272 else
4273 version_len = 0;
4274 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4275
4276 /* setup new index entry */
4277 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4278 RtlGUIDFromString(&str, &index->guid);
4279
4280 index->data_offset = data_offset;
4281 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4282 index->rosterindex = i + 1;
4283
4284 /* setup data */
4285 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4286 data->size = sizeof(*data);
4287 data->res = 0;
4288 data->clsid = index->guid;
4289 data->version_offset = version_len ? data->size : 0;
4290 data->version_len = version_len;
4291 data->name_offset = data->size + version_len;
4292 if (version_len)
4293 data->name_offset += sizeof(WCHAR);
4294 data->name_len = name_len;
4295
4296 /* surrogate name */
4297 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4298 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4299 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4300
4301 /* runtime version */
4302 if (data->version_len)
4303 {
4304 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4305 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4306 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4307 }
4308
4309 data_offset += index->data_offset;
4310 index++;
4311 }
4312 }
4313 }
4314
4315 *section = header;
4316
4317 return STATUS_SUCCESS;
4318 }
4319
4320 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4321 {
4322 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4323 }
4324
4325 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4326 {
4327 struct clrsurrogate_data *surrogate;
4328 struct guid_index *index = NULL;
4329
4330 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4331
4332 if (!actctx->clrsurrogate_section)
4333 {
4334 struct guidsection_header *section;
4335
4336 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4337 if (status) return status;
4338
4339 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4340 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4341 }
4342
4343 index = find_guid_index(actctx->clrsurrogate_section, guid);
4344 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4345
4346 surrogate = get_surrogate_data(actctx, index);
4347
4348 data->ulDataFormatVersion = 1;
4349 data->lpData = surrogate;
4350 /* full length includes string length with nulls */
4351 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4352 if (surrogate->version_len)
4353 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4354
4355 data->lpSectionGlobalData = NULL;
4356 data->ulSectionGlobalDataLength = 0;
4357 data->lpSectionBase = actctx->clrsurrogate_section;
4358 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
4359 data->hActCtx = NULL;
4360
4361 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4362 data->ulAssemblyRosterIndex = index->rosterindex;
4363
4364 return STATUS_SUCCESS;
4365 }
4366
4367 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4368 {
4369 unsigned int i, j, single_len;
4370
4371 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4372 for (i = 0; i < entities->num; i++)
4373 {
4374 struct entity *entity = &entities->base[i];
4375 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4376 {
4377 if (entity->u.comclass.progid)
4378 {
4379 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4380 *count += 1;
4381 }
4382
4383 for (j = 0; j < entity->u.comclass.progids.num; j++)
4384 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4385
4386 *total_len += single_len*entity->u.comclass.progids.num;
4387 *count += entity->u.comclass.progids.num;
4388 }
4389 }
4390 }
4391
4392 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4393 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4394 {
4395 struct progidredirect_data *data;
4396 UNICODE_STRING str;
4397 GUID *guid_ptr;
4398 WCHAR *ptrW;
4399
4400 /* setup new index entry */
4401
4402 /* hash progid name */
4403 RtlInitUnicodeString(&str, progid);
4404 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4405
4406 (*index)->name_offset = *data_offset;
4407 (*index)->name_len = str.Length;
4408 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4409 (*index)->data_len = sizeof(*data);
4410 (*index)->rosterindex = rosterindex;
4411
4412 *data_offset += aligned_string_len(str.MaximumLength);
4413
4414 /* setup data structure */
4415 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4416 data->size = sizeof(*data);
4417 data->reserved = 0;
4418 data->clsid_offset = *global_offset;
4419
4420 /* write progid string */
4421 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4422 memcpy(ptrW, progid, (*index)->name_len);
4423 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4424
4425 /* write guid to global area */
4426 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4427 *guid_ptr = *alias;
4428
4429 /* to next entry */
4430 *global_offset += sizeof(GUID);
4431 *data_offset += data->size;
4432 (*index) += 1;
4433 }
4434
4435 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4436 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4437 {
4438 unsigned int i, j;
4439
4440 for (i = 0; i < entities->num; i++)
4441 {
4442 struct entity *entity = &entities->base[i];
4443 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4444 {
4445 const struct progids *progids = &entity->u.comclass.progids;
4446 struct comclassredirect_data *comclass;
4447 struct guid_index *guid_index;
4448 UNICODE_STRING str;
4449 GUID clsid;
4450
4451 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4452 RtlGUIDFromString(&str, &clsid);
4453
4454 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4455 comclass = get_comclass_data(actctx, guid_index);
4456
4457 if (entity->u.comclass.progid)
4458 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4459 index, data_offset, global_offset, rosterindex);
4460
4461 for (j = 0; j < progids->num; j++)
4462 write_progid_record(section, progids->progids[j], &comclass->alias,
4463 index, data_offset, global_offset, rosterindex);
4464 }
4465 }
4466 }
4467
4468 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4469 {
4470 unsigned int i, j, total_len = 0, count = 0;
4471 struct strsection_header *header;
4472 ULONG data_offset, global_offset;
4473 struct string_index *index;
4474
4475 /* compute section length */
4476 for (i = 0; i < actctx->num_assemblies; i++)
4477 {
4478 struct assembly *assembly = &actctx->assemblies[i];
4479
4480 get_progid_datalen(&assembly->entities, &count, &total_len);
4481 for (j = 0; j < assembly->num_dlls; j++)
4482 {
4483 struct dll_redirect *dll = &assembly->dlls[j];
4484 get_progid_datalen(&dll->entities, &count, &total_len);
4485 }
4486 }
4487
4488 total_len += sizeof(*header);
4489
4490 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4491 if (!header) return STATUS_NO_MEMORY;
4492
4493 memset(header, 0, sizeof(*header));
4494 header->magic = STRSECTION_MAGIC;
4495 header->size = sizeof(*header);
4496 header->count = count;
4497 header->global_offset = header->size;
4498 header->global_len = count*sizeof(GUID);
4499 header->index_offset = header->size + header->global_len;
4500
4501 index = (struct string_index*)((BYTE*)header + header->index_offset);
4502 data_offset = header->index_offset + count*sizeof(*index);
4503 global_offset = header->global_offset;
4504
4505 for (i = 0; i < actctx->num_assemblies; i++)
4506 {
4507 struct assembly *assembly = &actctx->assemblies[i];
4508
4509 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4510 for (j = 0; j < assembly->num_dlls; j++)
4511 {
4512 struct dll_redirect *dll = &assembly->dlls[j];
4513 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4514 }
4515 }
4516
4517 *section = header;
4518
4519 return STATUS_SUCCESS;
4520 }
4521
4522 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4523 {
4524 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4525 }
4526
4527 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4528 PACTCTX_SECTION_KEYED_DATA data)
4529 {
4530 struct progidredirect_data *progid;
4531 struct string_index *index;
4532
4533 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4534
4535 if (!actctx->comserver_section)
4536 {
4537 struct guidsection_header *section;
4538
4539 NTSTATUS status = build_comserver_section(actctx, &section);
4540 if (status) return status;
4541
4542 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4543 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4544 }
4545
4546 if (!actctx->progid_section)
4547 {
4548 struct strsection_header *section;
4549
4550 NTSTATUS status = build_progid_section(actctx, &section);
4551 if (status) return status;
4552
4553 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4554 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4555 }
4556
4557 index = find_string_index(actctx->progid_section, name);
4558 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4559
4560 if (data)
4561 {
4562 progid = get_progid_data(actctx, index);
4563
4564 data->ulDataFormatVersion = 1;
4565 data->lpData = progid;
4566 data->ulLength = progid->size;
4567 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4568 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4569 data->lpSectionBase = actctx->progid_section;
4570 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
4571 data->hActCtx = NULL;
4572
4573 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4574 data->ulAssemblyRosterIndex = index->rosterindex;
4575 }
4576
4577 return STATUS_SUCCESS;
4578 }
4579
4580 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4581 const UNICODE_STRING *section_name,
4582 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4583 {
4584 NTSTATUS status;
4585
4586 switch (section_kind)
4587 {
4588 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION:
4589 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4590 return STATUS_SXS_KEY_NOT_FOUND;
4591 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4592 status = find_dll_redirection(actctx, section_name, data);
4593 break;
4594 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4595 status = find_window_class(actctx, section_name, data);
4596 break;
4597 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4598 status = find_progid_redirection(actctx, section_name, data);
4599 break;
4600 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4601 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4602 return STATUS_SXS_SECTION_NOT_FOUND;
4603 default:
4604 DPRINT1("Unknown section_kind %x\n", section_kind);
4605 return STATUS_SXS_SECTION_NOT_FOUND;
4606 }
4607
4608 if (status != STATUS_SUCCESS) return status;
4609
4610 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4611 {
4612 actctx_addref(actctx);
4613 data->hActCtx = actctx;
4614 }
4615 return STATUS_SUCCESS;
4616 }
4617
4618 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4619 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4620 {
4621 NTSTATUS status;
4622
4623 switch (section_kind)
4624 {
4625 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4626 status = find_tlib_redirection(actctx, guid, data);
4627 break;
4628 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4629 status = find_comserver_redirection(actctx, guid, data);
4630 break;
4631 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4632 status = find_cominterface_redirection(actctx, guid, data);
4633 break;
4634 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4635 status = find_clr_surrogate(actctx, guid, data);
4636 break;
4637 default:
4638 DPRINT("Unknown section_kind %x\n", section_kind);
4639 return STATUS_SXS_SECTION_NOT_FOUND;
4640 }
4641
4642 if (status != STATUS_SUCCESS) return status;
4643
4644 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4645 {
4646 actctx_addref(actctx);
4647 data->hActCtx = actctx;
4648 }
4649 return STATUS_SUCCESS;
4650 }
4651
4652 /* initialize the activation context for the current process */
4653 void actctx_init(void)
4654 {
4655 ACTCTXW ctx;
4656 HANDLE handle;
4657
4658 ctx.cbSize = sizeof(ctx);
4659 ctx.lpSource = NULL;
4660 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4661 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
4662 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4663
4664 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle)))
4665 {
4666 process_actctx = check_actctx(handle);
4667 }
4668 }
4669
4670 /* FUNCTIONS ***************************************************************/
4671
4672 /***********************************************************************
4673 * RtlCreateActivationContext (NTDLL.@)
4674 *
4675 * Create an activation context.
4676 */
4677 NTSTATUS
4678 NTAPI
4679 RtlCreateActivationContext(IN ULONG Flags,
4680 IN PACTIVATION_CONTEXT_DATA ActivationContextData,
4681 IN ULONG ExtraBytes,
4682 IN PVOID NotificationRoutine,
4683 IN PVOID NotificationContext,
4684 OUT PACTIVATION_CONTEXT *ActCtx)
4685 {
4686 const ACTCTXW *pActCtx = (PVOID)ActivationContextData;
4687 const WCHAR *directory = NULL;
4688 PACTIVATION_CONTEXT_WRAPPED ActualActCtx;
4689 ACTIVATION_CONTEXT *actctx;
4690 UNICODE_STRING nameW;
4691 ULONG lang = 0;
4692 NTSTATUS status = STATUS_NO_MEMORY;
4693 HANDLE file = 0;
4694 struct actctx_loader acl;
4695
4696 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule);
4697
4698 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4699 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4700 return STATUS_INVALID_PARAMETER;
4701
4702
4703 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx))))
4704 return STATUS_NO_MEMORY;
4705
4706 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER;
4707
4708 actctx = &ActualActCtx->ActivationContext;
4709 actctx->RefCount = 1;
4710 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4711 actctx->config.info = NULL;
4712 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4713 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4714 {
4715 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4716 }
4717 else
4718 {
4719 UNICODE_STRING dir;
4720 WCHAR *p;
4721 HMODULE module;
4722
4723 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4724 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
4725
4726 status = get_module_filename( module, &dir, 0 );
4727 if (!NT_SUCCESS(status)) goto error;
4728 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4729 actctx->appdir.info = dir.Buffer;
4730 }
4731
4732 nameW.Buffer = NULL;
4733
4734 /* open file only if it's going to be used */
4735 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4736 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4737 {
4738 WCHAR *source = NULL;
4739 BOOLEAN ret;
4740
4741 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4742 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative)
4743 {
4744 DWORD dir_len, source_len;
4745
4746 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4747 source_len = strlenW(pActCtx->lpSource);
4748 if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4749 {
4750 status = STATUS_NO_MEMORY;
4751 goto error;
4752 }
4753
4754 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4755 source[dir_len] = '\\';
4756 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4757 }
4758
4759 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4760 RtlFreeHeap( RtlGetProcessHeap(), 0, source );
4761 if (!ret)
4762 {
4763 status = STATUS_NO_SUCH_FILE;
4764 goto error;
4765 }
4766 status = open_nt_file( &file, &nameW );
4767 if (!NT_SUCCESS(status))
4768 {
4769 RtlFreeUnicodeString( &nameW );
4770 goto error;
4771 }
4772 }
4773
4774 acl.actctx = actctx;
4775 acl.dependencies = NULL;
4776 acl.num_dependencies = 0;
4777 acl.allocated_dependencies = 0;
4778
4779 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4780 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4781
4782 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4783 {
4784 /* if we have a resource it's a PE file */
4785 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4786 {
4787 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4788 pActCtx->lpResourceName, lang );
4789 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4790 /* FIXME: what to do if pActCtx->lpSource is set */
4791 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4792 pActCtx->hModule, pActCtx->lpResourceName );
4793 }
4794 else if (pActCtx->lpSource)
4795 {
4796 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4797 file, pActCtx->lpResourceName, lang );
4798 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4799 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4800 NULL, pActCtx->lpResourceName );
4801 }
4802 else status = STATUS_INVALID_PARAMETER;
4803 }
4804 else
4805 {
4806 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4807 }
4808
4809 if (file) NtClose( file );
4810 RtlFreeUnicodeString( &nameW );
4811
4812 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl);
4813 free_depend_manifests( &acl );
4814
4815 if (NT_SUCCESS(status))
4816 *ActCtx = actctx;
4817 else actctx_release( actctx );
4818 return status;
4819
4820 error:
4821 if (file) NtClose( file );
4822 actctx_release( actctx );
4823 return status;
4824 }
4825
4826 #if 0
4827 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4828
4829 VOID
4830 NTAPI
4831 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle)
4832 {
4833 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle;
4834 LONG OldRefCount, NewRefCount;
4835
4836 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
4837 {
4838 RtlpValidateActCtx(ActCtx);
4839
4840 while (TRUE)
4841 {
4842 OldRefCount = ActCtx->RefCount;
4843 ASSERT(OldRefCount > 0);
4844
4845 if (OldRefCount == LONG_MAX) break;
4846
4847 NewRefCount = OldRefCount + 1;
4848 if (InterlockedCompareExchange(&ActCtx->RefCount,
4849 NewRefCount,
4850 OldRefCount) == OldRefCount)
4851 {
4852 break;
4853 }
4854 }
4855
4856 NewRefCount = LONG_MAX;
4857 ASSERT(NewRefCount > 0);
4858 }
4859 }
4860
4861 VOID
4862 NTAPI
4863 RtlReleaseActivationContext( HANDLE handle )
4864 {
4865 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle;
4866
4867 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
4868 {
4869 RtlpValidateActCtx(ActCtx);
4870
4871 actctx_release(ActCtx);
4872 }
4873 }
4874 #else
4875
4876 /***********************************************************************
4877 * RtlAddRefActivationContext (NTDLL.@)
4878 */
4879 VOID NTAPI RtlAddRefActivationContext( HANDLE handle )
4880 {
4881 ACTIVATION_CONTEXT *actctx;
4882
4883 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4884 }
4885
4886
4887 /******************************************************************
4888 * RtlReleaseActivationContext (NTDLL.@)
4889 */
4890 VOID NTAPI RtlReleaseActivationContext( HANDLE handle )
4891 {
4892 ACTIVATION_CONTEXT *actctx;
4893
4894 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4895 }
4896
4897 #endif
4898
4899 /******************************************************************
4900 * RtlZombifyActivationContext (NTDLL.@)
4901 *
4902 */
4903 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context)
4904 {
4905 UNIMPLEMENTED;
4906
4907 if (Context == ACTCTX_FAKE_HANDLE)
4908 return STATUS_SUCCESS;
4909
4910 return STATUS_NOT_IMPLEMENTED;
4911 }
4912
4913 NTSTATUS
4914 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
4915 {
4916 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4917
4918 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
4919 return STATUS_NO_MEMORY;
4920
4921 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
4922 frame->ActivationContext = handle;
4923 frame->Flags = 0;
4924
4925 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4926 tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame,
4927 frame, handle);
4928
4929 tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
4930 RtlAddRefActivationContext( handle );
4931
4932 *cookie = (ULONG_PTR)frame;
4933 DPRINT( "%p cookie=%lx\n", handle, *cookie );
4934 return STATUS_SUCCESS;
4935 }
4936
4937 /******************************************************************
4938 * RtlActivateActivationContext (NTDLL.@)
4939 */
4940 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
4941 {
4942 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
4943 }
4944
4945 /***********************************************************************
4946 * RtlDeactivateActivationContext (NTDLL.@)
4947 */
4948 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4949 {
4950 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4951
4952 DPRINT( "%x cookie=%lx\n", flags, cookie );
4953
4954 /* find the right frame */
4955 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
4956 for (frame = top; frame; frame = frame->Previous)
4957 if ((ULONG_PTR)frame == cookie) break;
4958
4959 if (!frame)
4960 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4961
4962 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION))
4963 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4964
4965 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4966 NtCurrentTeb()->ActivationContextStackPointer,
4967 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame,
4968 frame->Previous);
4969
4970 /* pop everything up to and including frame */
4971 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
4972
4973 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
4974 {
4975 frame = top->Previous;
4976 RtlReleaseActivationContext( top->ActivationContext );
4977 RtlFreeHeap( RtlGetProcessHeap(), 0, top );
4978 top = frame;
4979 }
4980
4981 return STATUS_SUCCESS;
4982 }
4983
4984 VOID
4985 NTAPI
4986 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
4987 {
4988 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
4989
4990 /* Nothing to do if there is no stack */
4991 if (!Stack) return;
4992
4993 /* Get the current active frame */
4994 ActiveFrame = Stack->ActiveFrame;
4995
4996 /* Go through them in backwards order and release */
4997 while (ActiveFrame)
4998 {
4999 PrevFrame = ActiveFrame->Previous;
5000 RtlReleaseActivationContext(ActiveFrame->ActivationContext);
5001 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
5002 ActiveFrame = PrevFrame;
5003 }
5004
5005 /* Zero out the active frame */
5006 Stack->ActiveFrame = NULL;
5007
5008 /* TODO: Empty the Frame List Cache */
5009 ASSERT(IsListEmpty(&Stack->FrameListCache));
5010
5011 /* Free activation stack memory */
5012 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
5013 }
5014
5015 /******************************************************************
5016 * RtlFreeThreadActivationContextStack (NTDLL.@)
5017 */
5018 VOID NTAPI RtlFreeThreadActivationContextStack(VOID)
5019 {
5020 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
5021 NtCurrentTeb()->ActivationContextStackPointer = NULL;
5022 }
5023
5024
5025 /******************************************************************
5026 * RtlGetActiveActivationContext (NTDLL.@)
5027 */
5028 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle )
5029 {
5030 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5031 {
5032 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
5033 RtlAddRefActivationContext( *handle );
5034 }
5035 else
5036 *handle = 0;
5037
5038 return STATUS_SUCCESS;
5039 }
5040
5041
5042 /******************************************************************
5043 * RtlIsActivationContextActive (NTDLL.@)
5044 */
5045 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle )
5046 {
5047 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5048
5049 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
5050 if (frame->ActivationContext == handle) return TRUE;
5051 return FALSE;
5052 }
5053
5054
5055 /***********************************************************************
5056 * RtlQueryInformationActivationContext (NTDLL.@)
5057 *
5058 * Get information about an activation context.
5059 * FIXME: function signature/prototype may be wrong
5060 */
5061 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5062 ULONG class, PVOID buffer,
5063 SIZE_T bufsize, SIZE_T *retlen )
5064 {
5065 ACTIVATION_CONTEXT *actctx;
5066 NTSTATUS status;
5067
5068 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle,
5069 subinst, class, buffer, bufsize, retlen);
5070
5071 if (retlen) *retlen = 0;
5072 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5073
5074 switch (class)
5075 {
5076 case ActivationContextBasicInformation:
5077 {
5078 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5079
5080 if (retlen) *retlen = sizeof(*info);
5081 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5082
5083 info->hActCtx = handle;
5084 info->dwFlags = 0; /* FIXME */
5085 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle);
5086 }
5087 break;
5088
5089 case ActivationContextDetailedInformation:
5090 {
5091 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5092 struct assembly *assembly = NULL;
5093 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5094 LPWSTR ptr;
5095
5096 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5097
5098 if (actctx->num_assemblies) assembly = actctx->assemblies;
5099
5100 if (assembly && assembly->manifest.info)
5101 manifest_len = strlenW(assembly->manifest.info) + 1;
5102 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5103 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5104 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5105
5106 if (retlen) *retlen = len;
5107 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5108
5109 acdi->dwFlags = 0;
5110 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5111 acdi->ulAssemblyCount = actctx->num_assemblies;
5112 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5113 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
5114 acdi->ulRootConfigurationPathType = actctx->config.type;
5115 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
5116 acdi->ulAppDirPathType = actctx->appdir.type;
5117 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
5118 ptr = (LPWSTR)(acdi + 1);
5119 if (manifest_len)
5120 {
5121 acdi->lpRootManifestPath = ptr;
5122 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5123 ptr += manifest_len;
5124 }
5125 else acdi->lpRootManifestPath = NULL;
5126 if (config_len)
5127 {
5128 acdi->lpRootConfigurationPath = ptr;
5129 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5130 ptr += config_len;
5131 }
5132 else acdi->lpRootConfigurationPath = NULL;
5133 if (appdir_len)
5134 {
5135 acdi->lpAppDirPath = ptr;
5136 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5137 }
5138 else acdi->lpAppDirPath = NULL;
5139 }
5140 break;
5141
5142 case AssemblyDetailedInformationInActivationContext:
5143 {
5144 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5145 struct assembly *assembly;
5146 WCHAR *assembly_id;
5147 DWORD index;
5148 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5149 LPWSTR ptr;
5150
5151 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5152 if (!subinst) return STATUS_INVALID_PARAMETER;
5153
5154 index = *(DWORD*)subinst;
5155 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5156
5157 assembly = &actctx->assemblies[index - 1];
5158
5159 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5160 id_len = strlenW(assembly_id) + 1;
5161 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5162
5163 if (assembly->manifest.info &&
5164 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5165 path_len = strlenW(assembly->manifest.info) + 1;
5166
5167 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5168
5169 if (retlen) *retlen = len;
5170 if (!buffer || bufsize < len)
5171 {
5172 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5173 return STATUS_BUFFER_TOO_SMALL;
5174 }
5175
5176 afdi->ulFlags = 0; /* FIXME */
5177 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
5178 afdi->ulManifestPathType = assembly->manifest.type;
5179 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
5180 /* FIXME afdi->liManifestLastWriteTime = 0; */
5181 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5182 afdi->ulPolicyPathLength = 0;
5183 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5184 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5185 afdi->ulManifestVersionMajor = 1;
5186 afdi->ulManifestVersionMinor = 0;
5187 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5188 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5189 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
5190 ptr = (LPWSTR)(afdi + 1);
5191 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5192 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5193 ptr += id_len;
5194 if (path_len)
5195 {
5196 afdi->lpAssemblyManifestPath = ptr;
5197 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5198 ptr += path_len;
5199 } else afdi->lpAssemblyManifestPath = NULL;
5200 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5201 if (ad_len)
5202 {
5203 afdi->lpAssemblyDirectoryName = ptr;
5204 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5205 }
5206 else afdi->lpAssemblyDirectoryName = NULL;
5207 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5208 }
5209 break;
5210
5211 case FileInformationInAssemblyOfAssemblyInActivationContext:
5212 {
5213 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5214 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5215 struct assembly *assembly;
5216 struct dll_redirect *dll;
5217 SIZE_T len, dll_len = 0;
5218 LPWSTR ptr;
5219
5220 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5221 if (!acqi) return STATUS_INVALID_PARAMETER;
5222
5223 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5224 return STATUS_INVALID_PARAMETER;
5225 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5226
5227 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5228 return STATUS_INVALID_PARAMETER;
5229 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5230
5231 if (dll->name) dll_len = strlenW(dll->name) + 1;
5232 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5233
5234 if (!buffer || bufsize < len)
5235 {
5236 if (retlen) *retlen = len;
5237 return STATUS_BUFFER_TOO_SMALL;
5238 }
5239 if (retlen) *retlen = 0; /* yes that's what native does !! */
5240 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5241 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
5242 afdi->ulPathLength = 0; /* FIXME */
5243 ptr = (LPWSTR)(afdi + 1);
5244 if (dll_len)
5245 {
5246 afdi->lpFileName = ptr;
5247 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5248 } else afdi->lpFileName = NULL;
5249 afdi->lpFilePath = NULL; /* FIXME */
5250 }
5251 break;
5252
5253 default:
5254 DPRINT( "class %u not implemented\n", class );
5255 return STATUS_NOT_IMPLEMENTED;
5256 }
5257 return STATUS_SUCCESS;
5258 }
5259
5260 NTSTATUS
5261 NTAPI
5262 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
5263 PVOID pvBuffer,
5264 SIZE_T cbBuffer OPTIONAL,
5265 SIZE_T *pcbWrittenOrRequired OPTIONAL)
5266 {
5267 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT,
5268 NULL,
5269 NULL,
5270 ulInfoClass,
5271 pvBuffer,
5272 cbBuffer,
5273 pcbWrittenOrRequired);
5274 }
5275
5276 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5277 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5278 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5279
5280 NTSTATUS
5281 NTAPI
5282 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
5283 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
5284 {
5285 /* Check general parameter combinations */
5286 if (!section_name || !section_name->Buffer ||
5287 (flags & ~FIND_ACTCTX_VALID_MASK) ||
5288 ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
5289 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
5290 {
5291 DPRINT1("invalid parameter\n");
5292 return STATUS_INVALID_PARAMETER;
5293 }
5294
5295 /* TODO */
5296 if (flags & FIND_ACTCTX_RETURN_FLAGS ||
5297 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5298 {
5299 DPRINT1("unknown flags %08x\n", flags);
5300 return STATUS_INVALID_PARAMETER;
5301 }
5302
5303 return STATUS_SUCCESS;
5304 }
5305
5306 /***********************************************************************
5307 * RtlFindActivationContextSectionString (NTDLL.@)
5308 *
5309 * Find information about a string in an activation context.
5310 * FIXME: function signature/prototype may be wrong
5311 */
5312 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5313 const UNICODE_STRING *section_name, PVOID ptr )
5314 {
5315 PACTCTX_SECTION_KEYED_DATA data = ptr;
5316 NTSTATUS status;
5317
5318 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr);
5319 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
5320 if (!NT_SUCCESS(status))
5321 {
5322 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status);
5323 return status;
5324 }
5325
5326 status = STATUS_SXS_KEY_NOT_FOUND;
5327
5328 /* if there is no data, but params are valid,
5329 we return that sxs key is not found to be at least somehow compatible */
5330 if (!data)
5331 {
5332 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status);
5333 return status;
5334 }
5335
5336 ASSERT(NtCurrentTeb());
5337 ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
5338
5339 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame);
5340 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5341 {
5342 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5343 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5344 }
5345
5346 DPRINT("status %x\n", status);
5347 if (status != STATUS_SUCCESS)
5348 status = find_string( process_actctx, section_kind, section_name, flags, data );
5349
5350 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status);
5351 return status;
5352 }
5353
5354 /***********************************************************************
5355 * RtlFindActivationContextSectionGuid (NTDLL.@)
5356 *
5357 * Find information about a GUID in an activation context.
5358 * FIXME: function signature/prototype may be wrong
5359 */
5360 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5361 const GUID *guid, void *ptr )
5362 {
5363 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5364 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5365
5366 if (extguid)
5367 {
5368 DPRINT1("expected extguid == NULL\n");
5369 return STATUS_INVALID_PARAMETER;
5370 }
5371
5372 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5373 {
5374 DPRINT1("unknown flags %08x\n", flags);
5375 return STATUS_INVALID_PARAMETER;
5376 }
5377
5378 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5379 return STATUS_INVALID_PARAMETER;
5380
5381 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5382 {
5383 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5384 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5385 }
5386
5387 if (status != STATUS_SUCCESS)
5388 status = find_guid( process_actctx, section_kind, guid, flags, data );
5389
5390 return status;
5391 }
5392
5393 /* Stubs */
5394
5395 NTSTATUS
5396 NTAPI
5397 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
5398 {
5399 PACTIVATION_CONTEXT_STACK ContextStack;
5400
5401 /* Check if it's already allocated */
5402 if (*Stack) return STATUS_SUCCESS;
5403
5404 /* Allocate space for the context stack */
5405 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK));
5406 if (!ContextStack)
5407 {
5408 return STATUS_NO_MEMORY;
5409 }
5410
5411 /* Initialize the context stack */
5412 ContextStack->Flags = 0;
5413 ContextStack->ActiveFrame = NULL;
5414 InitializeListHead(&ContextStack->FrameListCache);
5415 ContextStack->NextCookieSequenceNumber = 1;
5416 ContextStack->StackId = 1; //TODO: Timer-based
5417
5418 *Stack = ContextStack;
5419
5420 return STATUS_SUCCESS;
5421 }
5422
5423 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5424 FASTCALL
5425 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
5426 IN PVOID Context)
5427 {
5428 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame;
5429 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
5430
5431 /* Get the current active frame */
5432 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5433
5434 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5435 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame,
5436 &Frame->Frame, Context);
5437
5438 /* Ensure it's in the right format and at least fits basic info */
5439 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5440 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5441
5442 /* Set debug info if size allows*/
5443 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5444 {
5445 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame);
5446 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context);
5447 //Frame->Extra3 = ...;
5448 }
5449
5450 if (ActiveFrame)
5451 {
5452 /*ASSERT((ActiveFrame->Flags &
5453 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5454 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5455 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5456
5457 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED))
5458 {
5459 // TODO: Perform some additional checks if it was not heap allocated
5460 }
5461 }
5462
5463 /* Save pointer to the new activation frame */
5464 NewFrame = &Frame->Frame;
5465
5466 /* Actually activate it */
5467 Frame->Frame.Previous = ActiveFrame;
5468 Frame->Frame.ActivationContext = Context;
5469 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED;
5470
5471 /* Check if we can activate this context */
5472 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
5473 Context)
5474 {
5475 /* Set new active frame */
5476 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame);
5477 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5478 return NewFrame;
5479 }
5480
5481 /* We can get here only one way: it was already activated */
5482 DPRINT("Trying to activate already activated activation context\n");
5483
5484 /* Activate only if we are allowing multiple activation */
5485 #if 0
5486 if (!RtlpNotAllowingMultipleActivation)
5487 {
5488 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED;
5489 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5490 }
5491 #else
5492 // Activate it anyway
5493 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5494 #endif
5495
5496 /* Return pointer to the activation frame */
5497 return NewFrame;
5498 }
5499
5500 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5501 FASTCALL
5502 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
5503 {
5504 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame;
5505
5506 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5507
5508 /* Ensure it's in the right format and at least fits basic info */
5509 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5510 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5511
5512 /* Make sure it is not deactivated and it is activated */
5513 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0);
5514 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
5515 ASSERT((Frame->Frame.Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
5516
5517 /* Check debug info if it is present */
5518 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5519 {
5520 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous));
5521 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext));
5522 //Frame->Extra3 = ...;
5523 }
5524
5525 if (ActiveFrame)
5526 {
5527 // TODO: Perform some additional checks here
5528 }
5529
5530 /* Special handling for not-really-activated */
5531 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)
5532 {
5533 DPRINT1("Deactivating not really activated activation context\n");
5534 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5535 return &Frame->Frame;
5536 }
5537
5538 /* find the right frame */
5539 NewFrame = &Frame->Frame;
5540 if (ActiveFrame != NewFrame)
5541 {
5542 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame);
5543 }
5544
5545 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5546 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous);
5547
5548 /* Pop everything up to and including frame */
5549 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous;
5550
5551 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5552 return NewFrame->Previous;
5553 }