396b442fcddbc982aa0bace278fcadb18424c836
[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 #include <ntstrsafe.h>
19
20 #define NDEBUG
21 #include <debug.h>
22
23 #include <wine/unicode.h>
24
25 BOOLEAN RtlpNotAllowingMultipleActivation;
26
27 #define ACTCTX_FLAGS_ALL (\
28 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
29 ACTCTX_FLAG_LANGID_VALID |\
30 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
31 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
32 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
33 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
34 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
35 ACTCTX_FLAG_HMODULE_VALID )
36
37 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
38 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
39
40 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
41
42 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
43 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
44
45
46
47 typedef struct
48 {
49 const WCHAR *ptr;
50 unsigned int len;
51 } xmlstr_t;
52
53 typedef struct
54 {
55 const WCHAR *ptr;
56 const WCHAR *end;
57 } xmlbuf_t;
58
59 struct file_info
60 {
61 ULONG type;
62 WCHAR *info;
63 };
64
65 struct assembly_version
66 {
67 USHORT major;
68 USHORT minor;
69 USHORT build;
70 USHORT revision;
71 };
72
73 struct assembly_identity
74 {
75 WCHAR *name;
76 WCHAR *arch;
77 WCHAR *public_key;
78 WCHAR *language;
79 WCHAR *type;
80 struct assembly_version version;
81 BOOL optional;
82 BOOL delayed;
83 };
84
85 struct strsection_header
86 {
87 DWORD magic;
88 ULONG size;
89 DWORD unk1[3];
90 ULONG count;
91 ULONG index_offset;
92 DWORD unk2[2];
93 ULONG global_offset;
94 ULONG global_len;
95 };
96
97 struct string_index
98 {
99 ULONG hash; /* key string hash */
100 ULONG name_offset;
101 ULONG name_len;
102 ULONG data_offset; /* redirect data offset */
103 ULONG data_len;
104 ULONG rosterindex;
105 };
106
107 struct guidsection_header
108 {
109 DWORD magic;
110 ULONG size;
111 DWORD unk[3];
112 ULONG count;
113 ULONG index_offset;
114 DWORD unk2;
115 ULONG names_offset;
116 ULONG names_len;
117 };
118
119 struct guid_index
120 {
121 GUID guid;
122 ULONG data_offset;
123 ULONG data_len;
124 ULONG rosterindex;
125 };
126
127 struct wndclass_redirect_data
128 {
129 ULONG size;
130 DWORD res;
131 ULONG name_len;
132 ULONG name_offset; /* versioned name offset */
133 ULONG module_len;
134 ULONG module_offset;/* container name offset */
135 };
136
137 struct dllredirect_data
138 {
139 ULONG size;
140 ULONG unk;
141 DWORD res[3];
142 };
143
144 struct tlibredirect_data
145 {
146 ULONG size;
147 DWORD res;
148 ULONG name_len;
149 ULONG name_offset;
150 LANGID langid;
151 WORD flags;
152 ULONG help_len;
153 ULONG help_offset;
154 WORD major_version;
155 WORD minor_version;
156 };
157
158 enum comclass_threadingmodel
159 {
160 ThreadingModel_Apartment = 1,
161 ThreadingModel_Free = 2,
162 ThreadingModel_No = 3,
163 ThreadingModel_Both = 4,
164 ThreadingModel_Neutral = 5
165 };
166
167 enum comclass_miscfields
168 {
169 MiscStatus = 1,
170 MiscStatusIcon = 2,
171 MiscStatusContent = 4,
172 MiscStatusThumbnail = 8,
173 MiscStatusDocPrint = 16
174 };
175
176 struct comclassredirect_data
177 {
178 ULONG size;
179 BYTE res;
180 BYTE miscmask;
181 BYTE res1[2];
182 DWORD model;
183 GUID clsid;
184 GUID alias;
185 GUID clsid2;
186 GUID tlbid;
187 ULONG name_len;
188 ULONG name_offset;
189 ULONG progid_len;
190 ULONG progid_offset;
191 ULONG clrdata_len;
192 ULONG clrdata_offset;
193 DWORD miscstatus;
194 DWORD miscstatuscontent;
195 DWORD miscstatusthumbnail;
196 DWORD miscstatusicon;
197 DWORD miscstatusdocprint;
198 };
199
200 enum ifaceps_mask
201 {
202 NumMethods = 1,
203 BaseIface = 2
204 };
205
206 struct ifacepsredirect_data
207 {
208 ULONG size;
209 DWORD mask;
210 GUID iid;
211 ULONG nummethods;
212 GUID tlbid;
213 GUID base;
214 ULONG name_len;
215 ULONG name_offset;
216 };
217
218 struct clrsurrogate_data
219 {
220 ULONG size;
221 DWORD res;
222 GUID clsid;
223 ULONG version_offset;
224 ULONG version_len;
225 ULONG name_offset;
226 ULONG name_len;
227 };
228
229 struct clrclass_data
230 {
231 ULONG size;
232 DWORD res[2];
233 ULONG module_len;
234 ULONG module_offset;
235 ULONG name_len;
236 ULONG name_offset;
237 ULONG version_len;
238 ULONG version_offset;
239 DWORD res2[2];
240 };
241
242 struct progidredirect_data
243 {
244 ULONG size;
245 DWORD reserved;
246 ULONG clsid_offset;
247 };
248
249 /*
250
251 Sections structure.
252
253 Sections are accessible by string or guid key, that defines two types of sections.
254 All sections of each type have same magic value and header structure, index
255 data could be of two possible types too. So every string based section uses
256 the same index format, same applies to guid sections - they share same guid index
257 format.
258
259 - window class redirection section is a plain buffer with following format:
260
261 <section header>
262 <index[]>
263 <data[]> --- <original name>
264 <redirect data>
265 <versioned name>
266 <module name>
267
268 Header is fixed length structure - struct strsection_header,
269 contains redirected classes count;
270
271 Index is an array of fixed length index records, each record is
272 struct string_index.
273
274 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
275
276 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
277 others are relative to section itself.
278
279 - dll redirect section format:
280
281 <section header>
282 <index[]>
283 <data[]> --- <dll name>
284 <data>
285
286 This section doesn't seem to carry any payload data except dll names.
287
288 - typelib section format:
289
290 <section header>
291 <module names[]>
292 <index[]>
293 <data[]> --- <data>
294 <helpstring>
295
296 Header is fixed length, index is an array of fixed length 'struct guid_index'.
297 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
298 4-bytes aligned as a whole.
299
300 Module name offsets are relative to section, helpstring offset is relative to data
301 structure itself.
302
303 - comclass section format:
304
305 <section header>
306 <module names[]>
307 <index[]>
308 <data[]> --- <data> --- <data>
309 <progid> <clrdata>
310 <name>
311 <version>
312 <progid>
313
314 This section uses two index records per comclass, one entry contains original guid
315 as specified by context, another one has a generated guid. Index and strings handling
316 is similar to typelib sections.
317
318 For CLR classes additional data is stored after main COM class data, it contains
319 class name and runtime version string, see 'struct clrclass_data'.
320
321 Module name offsets are relative to section, progid offset is relative to data
322 structure itself.
323
324 - COM interface section format:
325
326 <section header>
327 <index[]>
328 <data[]> --- <data>
329 <name>
330
331 Interface section contains data for proxy/stubs and external proxy/stubs. External
332 ones are defined at assembly level, so this section has no module information.
333 All records are indexed with 'iid' value from manifest. There an exception for
334 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
335 redirect data, but index is still 'iid' from manifest.
336
337 Interface name offset is relative to data structure itself.
338
339 - CLR surrogates section format:
340
341 <section header>
342 <index[]>
343 <data[]> --- <data>
344 <name>
345 <version>
346
347 There's nothing special about this section, same way to store strings is used,
348 no modules part as it belongs to assembly level, not a file.
349
350 - ProgID section format:
351
352 <section header>
353 <guids[]>
354 <index[]>
355 <data[]> --- <progid>
356 <data>
357
358 This sections uses generated alias guids from COM server section. This way
359 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
360 is stored too, aligned.
361 */
362
363 struct progids
364 {
365 WCHAR **progids;
366 unsigned int num;
367 unsigned int allocated;
368 };
369
370 struct entity
371 {
372 DWORD kind;
373 union
374 {
375 struct
376 {
377 WCHAR *tlbid;
378 WCHAR *helpdir;
379 WORD flags;
380 WORD major;
381 WORD minor;
382 } typelib;
383 struct
384 {
385 WCHAR *clsid;
386 WCHAR *tlbid;
387 WCHAR *progid;
388 WCHAR *name; /* clrClass: class name */
389 WCHAR *version; /* clrClass: CLR runtime version */
390 DWORD model;
391 DWORD miscstatus;
392 DWORD miscstatuscontent;
393 DWORD miscstatusthumbnail;
394 DWORD miscstatusicon;
395 DWORD miscstatusdocprint;
396 struct progids progids;
397 } comclass;
398 struct {
399 WCHAR *iid;
400 WCHAR *base;
401 WCHAR *tlib;
402 WCHAR *name;
403 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
404 DWORD mask;
405 ULONG nummethods;
406 } ifaceps;
407 struct
408 {
409 WCHAR *name;
410 BOOL versioned;
411 } class;
412 struct
413 {
414 WCHAR *name;
415 WCHAR *clsid;
416 WCHAR *version;
417 } clrsurrogate;
418 } u;
419 };
420
421 struct entity_array
422 {
423 struct entity *base;
424 unsigned int num;
425 unsigned int allocated;
426 };
427
428 struct dll_redirect
429 {
430 WCHAR *name;
431 WCHAR *hash;
432 struct entity_array entities;
433 };
434
435 enum assembly_type
436 {
437 APPLICATION_MANIFEST,
438 ASSEMBLY_MANIFEST,
439 ASSEMBLY_SHARED_MANIFEST,
440 };
441
442 struct assembly
443 {
444 enum assembly_type type;
445 struct assembly_identity id;
446 struct file_info manifest;
447 WCHAR *directory;
448 BOOL no_inherit;
449 struct dll_redirect *dlls;
450 unsigned int num_dlls;
451 unsigned int allocated_dlls;
452 struct entity_array entities;
453 };
454
455 enum context_sections
456 {
457 WINDOWCLASS_SECTION = 1,
458 DLLREDIRECT_SECTION = 2,
459 TLIBREDIRECT_SECTION = 4,
460 SERVERREDIRECT_SECTION = 8,
461 IFACEREDIRECT_SECTION = 16,
462 CLRSURROGATES_SECTION = 32,
463 PROGIDREDIRECT_SECTION = 64
464 };
465
466 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
467 {
468 ULONG Flags;
469 UNICODE_STRING DosPath;
470 HANDLE Handle;
471 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;
472
473 typedef struct _ASSEMBLY_STORAGE_MAP
474 {
475 ULONG Flags;
476 ULONG AssemblyCount;
477 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray;
478 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
479
480 typedef struct _ACTIVATION_CONTEXT
481 {
482 LONG RefCount;
483 ULONG Flags;
484 LIST_ENTRY Links;
485 PACTIVATION_CONTEXT_DATA ActivationContextData;
486 PVOID NotificationRoutine;
487 PVOID NotificationContext;
488 ULONG SentNotifications[8];
489 ULONG DisabledNotifications[8];
490 ASSEMBLY_STORAGE_MAP StorageMap;
491 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries;
492 ULONG StackTraceIndex;
493 PVOID StackTraces[4][4];
494 struct file_info config;
495 struct file_info appdir;
496 struct assembly *assemblies;
497 unsigned int num_assemblies;
498 unsigned int allocated_assemblies;
499 /* section data */
500 DWORD sections;
501 struct strsection_header *wndclass_section;
502 struct strsection_header *dllredirect_section;
503 struct strsection_header *progid_section;
504 struct guidsection_header *tlib_section;
505 struct guidsection_header *comserver_section;
506 struct guidsection_header *ifaceps_section;
507 struct guidsection_header *clrsurrogate_section;
508 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
509
510 struct actctx_loader
511 {
512 ACTIVATION_CONTEXT *actctx;
513 struct assembly_identity *dependencies;
514 unsigned int num_dependencies;
515 unsigned int allocated_dependencies;
516 };
517
518 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
519 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
520
521 typedef struct _ACTIVATION_CONTEXT_WRAPPED
522 {
523 PVOID MagicMarker;
524 ACTIVATION_CONTEXT ActivationContext;
525 } ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED;
526
527 VOID
528 NTAPI
529 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx,
530 IN ULONG FailureCode)
531 {
532 EXCEPTION_RECORD ExceptionRecord;
533
534 /* Fatal SxS exception header */
535 ExceptionRecord.ExceptionRecord = NULL;
536 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
537 ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
538
539 /* With SxS-specific information plus the context itself */
540 ExceptionRecord.ExceptionInformation[0] = 1;
541 ExceptionRecord.ExceptionInformation[1] = FailureCode;
542 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
543 ExceptionRecord.NumberParameters = 3;
544
545 /* Raise it */
546 RtlRaiseException(&ExceptionRecord);
547 }
548
549 FORCEINLINE
550 VOID
551 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx)
552 {
553 PACTIVATION_CONTEXT_WRAPPED pActual;
554
555 /* Get the caller-opaque header */
556 pActual = CONTAINING_RECORD(ActCtx,
557 ACTIVATION_CONTEXT_WRAPPED,
558 ActivationContext);
559
560 /* Check if the header matches as expected */
561 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
562 {
563 /* Nope, print out a warning, assert, and then throw an exception */
564 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
565 " This means someone stepped on the allocation, or someone is using a\n"
566 " deallocated activation context\n",
567 __FUNCTION__,
568 pActual->MagicMarker,
569 ActCtx);
570 ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER);
571 RtlpSxsBreakOnInvalidMarker(ActCtx, 1);
572 }
573 }
574
575 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
576 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
577 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
578 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
579 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
580 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
581 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};
582 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};
583 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
584 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
585 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
586 static const WCHAR fileW[] = {'f','i','l','e',0};
587 static const WCHAR hashW[] = {'h','a','s','h',0};
588 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
589 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
590 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
591 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
592
593 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
594 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
595 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
596 static const WCHAR iidW[] = {'i','i','d',0};
597 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
598 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
599 static const WCHAR g_nameW[] = {'n','a','m','e',0};
600 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
601 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
602 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
603 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
604 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};
605 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
606 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
607 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
608 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
609 static const WCHAR typeW[] = {'t','y','p','e',0};
610 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
611 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
612 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
613 static const WCHAR yesW[] = {'y','e','s',0};
614 static const WCHAR noW[] = {'n','o',0};
615 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
616 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
617 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
618 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
619 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
620 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
621 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
622 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
623 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
624 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
625 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
626 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
627 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
628 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
629 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
630 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
631
632 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
633 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
634 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
635 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
636 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
637 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
638 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
639 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};
640 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
641 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
642 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
643 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
644 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
645 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
646 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
647 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
648 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};
649 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
650 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
651 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
652 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};
653 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
654
655 struct olemisc_entry
656 {
657 const WCHAR *name;
658 OLEMISC value;
659 };
660
661 static const struct olemisc_entry olemisc_values[] =
662 {
663 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
664 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
665 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
666 { alignableW, OLEMISC_ALIGNABLE },
667 { alwaysrunW, OLEMISC_ALWAYSRUN },
668 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
669 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
670 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
671 { imemodeW, OLEMISC_IMEMODE },
672 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
673 { insideoutW, OLEMISC_INSIDEOUT },
674 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
675 { islinkobjectW, OLEMISC_ISLINKOBJECT },
676 { nouiactivateW, OLEMISC_NOUIACTIVATE },
677 { onlyiconicW, OLEMISC_ONLYICONIC },
678 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
679 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
680 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
681 { simpleframeW, OLEMISC_SIMPLEFRAME },
682 { staticW, OLEMISC_STATIC },
683 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
684 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
685 };
686
687 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
688 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};
689 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};
690 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};
691
692 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
693 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
694 static const WCHAR wildcardW[] = {'*',0};
695
696 static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } };
697 static ACTIVATION_CONTEXT *process_actctx = &system_actctx.ActivationContext;
698 static ACTIVATION_CONTEXT *implicit_actctx = &system_actctx.ActivationContext;
699
700 static WCHAR *strdupW(const WCHAR* str)
701 {
702 WCHAR* ptr;
703
704 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
705 return NULL;
706 return strcpyW(ptr, str);
707 }
708
709 static WCHAR *xmlstrdupW(const xmlstr_t* str)
710 {
711 WCHAR *strW;
712
713 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
714 {
715 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
716 strW[str->len] = 0;
717 }
718 return strW;
719 }
720
721 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
722 {
723 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
724 }
725
726 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
727 {
728 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
729 }
730
731 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
732 {
733 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
734 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
735 }
736
737 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
738 {
739 UINT len = strlenW( namespace );
740
741 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
742 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
743 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
744 }
745
746 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
747 {
748 if (elem->len && elem->ptr[0] == '/')
749 {
750 xmlstr_t elem_end;
751 elem_end.ptr = elem->ptr + 1;
752 elem_end.len = elem->len - 1;
753 return xml_elem_cmp( &elem_end, str, namespace );
754 }
755 return FALSE;
756 }
757
758 static inline BOOL isxmlspace( WCHAR ch )
759 {
760 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
761 }
762
763 static UNICODE_STRING xmlstr2unicode(const xmlstr_t *xmlstr)
764 {
765 UNICODE_STRING res;
766
767 res.Buffer = (PWSTR)xmlstr->ptr;
768 res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR);
769
770 return res;
771 }
772
773 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
774 {
775 struct assembly *assembly;
776
777 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
778
779 if (actctx->num_assemblies == actctx->allocated_assemblies)
780 {
781 void *ptr;
782 unsigned int new_count;
783 if (actctx->assemblies)
784 {
785 new_count = actctx->allocated_assemblies * 2;
786 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
787 actctx->assemblies, new_count * sizeof(*assembly) );
788 }
789 else
790 {
791 new_count = 4;
792 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
793 }
794 if (!ptr) return NULL;
795 actctx->assemblies = ptr;
796 actctx->allocated_assemblies = new_count;
797 }
798
799 assembly = &actctx->assemblies[actctx->num_assemblies++];
800 assembly->type = at;
801 return assembly;
802 }
803
804 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
805 {
806 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
807
808 if (assembly->num_dlls == assembly->allocated_dlls)
809 {
810 void *ptr;
811 unsigned int new_count;
812 if (assembly->dlls)
813 {
814 new_count = assembly->allocated_dlls * 2;
815 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
816 assembly->dlls, new_count * sizeof(*assembly->dlls) );
817 }
818 else
819 {
820 new_count = 4;
821 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
822 }
823 if (!ptr) return NULL;
824 assembly->dlls = ptr;
825 assembly->allocated_dlls = new_count;
826 }
827 return &assembly->dlls[assembly->num_dlls++];
828 }
829
830 static void free_assembly_identity(struct assembly_identity *ai)
831 {
832 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
833 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
834 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
835 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
836 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
837 }
838
839 static struct entity* add_entity(struct entity_array *array, DWORD kind)
840 {
841 struct entity* entity;
842
843 if (array->num == array->allocated)
844 {
845 void *ptr;
846 unsigned int new_count;
847 if (array->base)
848 {
849 new_count = array->allocated * 2;
850 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
851 array->base, new_count * sizeof(*array->base) );
852 }
853 else
854 {
855 new_count = 4;
856 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
857 }
858 if (!ptr) return NULL;
859 array->base = ptr;
860 array->allocated = new_count;
861 }
862 entity = &array->base[array->num++];
863 entity->kind = kind;
864 return entity;
865 }
866
867 static void free_entity_array(struct entity_array *array)
868 {
869 unsigned int i, j;
870 for (i = 0; i < array->num; i++)
871 {
872 struct entity *entity = &array->base[i];
873 switch (entity->kind)
874 {
875 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
876 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
877 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
879 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
880 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
881 for (j = 0; j < entity->u.comclass.progids.num; j++)
882 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
883 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
884 break;
885 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
886 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
887 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
888 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
889 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
890 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
891 break;
892 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
893 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
894 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
895 break;
896 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
897 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
898 break;
899 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
900 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
901 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
902 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
903 break;
904 default:
905 DPRINT1("Unknown entity kind %u\n", entity->kind);
906 }
907 }
908 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
909 }
910
911 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
912 {
913 if (!str1) return !str2;
914 return str2 && !strcmpiW( str1, str2 );
915 }
916
917 static BOOL is_matching_identity( const struct assembly_identity *id1,
918 const struct assembly_identity *id2 )
919 {
920 if (!is_matching_string( id1->name, id2->name )) return FALSE;
921 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
922 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
923
924 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
925 {
926 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
927 return FALSE;
928 }
929 if (id1->version.major != id2->version.major) return FALSE;
930 if (id1->version.minor != id2->version.minor) return FALSE;
931 if (id1->version.build > id2->version.build) return FALSE;
932 if (id1->version.build == id2->version.build &&
933 id1->version.revision > id2->version.revision) return FALSE;
934 return TRUE;
935 }
936
937 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
938 struct assembly_identity* ai)
939 {
940 unsigned int i;
941
942 /* check if we already have that assembly */
943
944 for (i = 0; i < acl->actctx->num_assemblies; i++)
945 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
946 {
947 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
948 ai->name, ai->arch, ai->version.major, ai->version.minor,
949 ai->version.build, ai->version.revision );
950 return TRUE;
951 }
952
953 for (i = 0; i < acl->num_dependencies; i++)
954 if (is_matching_identity( ai, &acl->dependencies[i] ))
955 {
956 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
957 ai->name, ai->arch, ai->version.major, ai->version.minor,
958 ai->version.build, ai->version.revision );
959 return TRUE;
960 }
961
962 if (acl->num_dependencies == acl->allocated_dependencies)
963 {
964 void *ptr;
965 unsigned int new_count;
966 if (acl->dependencies)
967 {
968 new_count = acl->allocated_dependencies * 2;
969 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
970 new_count * sizeof(acl->dependencies[0]));
971 }
972 else
973 {
974 new_count = 4;
975 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
976 }
977 if (!ptr) return FALSE;
978 acl->dependencies = ptr;
979 acl->allocated_dependencies = new_count;
980 }
981 acl->dependencies[acl->num_dependencies++] = *ai;
982
983 return TRUE;
984 }
985
986 static void free_depend_manifests(struct actctx_loader* acl)
987 {
988 unsigned int i;
989 for (i = 0; i < acl->num_dependencies; i++)
990 free_assembly_identity(&acl->dependencies[i]);
991 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
992 }
993
994 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
995 {
996 static const WCHAR undW[] = {'_',0};
997 static const WCHAR noneW[] = {'n','o','n','e',0};
998 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
999
1000 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1001 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1002 const WCHAR *lang = ai->language ? ai->language : noneW;
1003 const WCHAR *name = ai->name ? ai->name : noneW;
1004 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1005 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1006 WCHAR *ret;
1007
1008 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1009
1010 strcpyW( ret, arch );
1011 strcatW( ret, undW );
1012 strcatW( ret, name );
1013 strcatW( ret, undW );
1014 strcatW( ret, key );
1015 strcatW( ret, undW );
1016 sprintfW( ret + strlenW(ret), version_formatW,
1017 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1018 strcatW( ret, undW );
1019 strcatW( ret, lang );
1020 strcatW( ret, undW );
1021 strcatW( ret, mskeyW );
1022 return ret;
1023 }
1024
1025 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1026 {
1027 WCHAR *p = buffer;
1028
1029 if (!str) return;
1030 strcatW( buffer, prefix );
1031 p += strlenW(p);
1032 *p++ = '"';
1033 strcpyW( p, str );
1034 p += strlenW(p);
1035 *p++ = '"';
1036 *p = 0;
1037 }
1038
1039 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1040 {
1041 static const WCHAR archW[] =
1042 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1043 static const WCHAR public_keyW[] =
1044 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1045 static const WCHAR typeW2[] =
1046 {',','t','y','p','e','=',0};
1047 static const WCHAR versionW2[] =
1048 {',','v','e','r','s','i','o','n','=',0};
1049
1050 WCHAR version[64], *ret;
1051 SIZE_T size = 0;
1052
1053 sprintfW( version, version_formatW,
1054 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1055 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1056 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1057 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1058 if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1059 size += strlenW(versionW2) + strlenW(version) + 2;
1060
1061 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1062 return NULL;
1063
1064 if (ai->name) strcpyW( ret, ai->name );
1065 else *ret = 0;
1066 append_string( ret, archW, ai->arch );
1067 append_string( ret, public_keyW, ai->public_key );
1068 append_string( ret, typeW2, ai->type );
1069 append_string( ret, versionW2, version );
1070 return ret;
1071 }
1072
1073 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1074 {
1075 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1076 PACTIVATION_CONTEXT_WRAPPED pActual;
1077
1078 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1079 _SEH2_TRY
1080 {
1081 if (actctx)
1082 {
1083 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1084 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1085 }
1086 }
1087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1088 {
1089 DPRINT1("Invalid activation context handle!\n");
1090 }
1091 _SEH2_END;
1092 return ret;
1093 }
1094
1095 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1096 {
1097 InterlockedExchangeAdd( &actctx->RefCount, 1 );
1098 }
1099
1100 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1101 {
1102 PACTIVATION_CONTEXT_WRAPPED pActual;
1103
1104 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1105 {
1106 unsigned int i, j;
1107
1108 for (i = 0; i < actctx->num_assemblies; i++)
1109 {
1110 struct assembly *assembly = &actctx->assemblies[i];
1111 for (j = 0; j < assembly->num_dlls; j++)
1112 {
1113 struct dll_redirect *dll = &assembly->dlls[j];
1114 free_entity_array( &dll->entities );
1115 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1116 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1117 }
1118 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1119 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1120 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1121 free_entity_array( &assembly->entities );
1122 free_assembly_identity(&assembly->id);
1123 }
1124 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1125 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1126 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1127 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1128 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1129 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1130 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1131 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1132 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1133 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1134
1135 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1136 pActual->MagicMarker = 0;
1137 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1138 }
1139 }
1140
1141 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1142 BOOL* error, BOOL* end)
1143 {
1144 const WCHAR* ptr;
1145
1146 *error = TRUE;
1147
1148 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1149 xmlbuf->ptr++;
1150
1151 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1152
1153 if (*xmlbuf->ptr == '/')
1154 {
1155 xmlbuf->ptr++;
1156 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1157 return FALSE;
1158
1159 xmlbuf->ptr++;
1160 *end = TRUE;
1161 *error = FALSE;
1162 return FALSE;
1163 }
1164
1165 if (*xmlbuf->ptr == '>')
1166 {
1167 xmlbuf->ptr++;
1168 *error = FALSE;
1169 return FALSE;
1170 }
1171
1172 ptr = xmlbuf->ptr;
1173 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1174
1175 if (ptr == xmlbuf->end) return FALSE;
1176
1177 name->ptr = xmlbuf->ptr;
1178 name->len = ptr-xmlbuf->ptr;
1179 xmlbuf->ptr = ptr;
1180
1181 /* skip spaces before '=' */
1182 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1183 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1184
1185 /* skip '=' itself */
1186 ptr++;
1187 if (ptr == xmlbuf->end) return FALSE;
1188
1189 /* skip spaces after '=' */
1190 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1191
1192 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1193
1194 value->ptr = ++ptr;
1195 if (ptr == xmlbuf->end) return FALSE;
1196
1197 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1198 if (!ptr)
1199 {
1200 xmlbuf->ptr = xmlbuf->end;
1201 return FALSE;
1202 }
1203
1204 value->len = ptr - value->ptr;
1205 xmlbuf->ptr = ptr + 1;
1206
1207 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1208
1209 *error = FALSE;
1210 return TRUE;
1211 }
1212
1213 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1214 {
1215 const WCHAR* ptr;
1216
1217 for (;;)
1218 {
1219 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1220 if (!ptr)
1221 {
1222 xmlbuf->ptr = xmlbuf->end;
1223 return FALSE;
1224 }
1225 ptr++;
1226 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1227 {
1228 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1229 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1230
1231 if (ptr + 3 > xmlbuf->end)
1232 {
1233 xmlbuf->ptr = xmlbuf->end;
1234 return FALSE;
1235 }
1236 xmlbuf->ptr = ptr + 3;
1237 }
1238 else break;
1239 }
1240
1241 xmlbuf->ptr = ptr;
1242 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1243 ptr++;
1244
1245 elem->ptr = xmlbuf->ptr;
1246 elem->len = ptr - xmlbuf->ptr;
1247 xmlbuf->ptr = ptr;
1248 return xmlbuf->ptr != xmlbuf->end;
1249 }
1250
1251 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1252 {
1253 /* FIXME: parse attributes */
1254 const WCHAR *ptr;
1255
1256 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1257 {
1258 if (ptr[0] == '?' && ptr[1] == '>')
1259 {
1260 xmlbuf->ptr = ptr + 2;
1261 return TRUE;
1262 }
1263 }
1264 return FALSE;
1265 }
1266
1267 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1268 {
1269 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1270
1271 if (!ptr) return FALSE;
1272
1273 content->ptr = xmlbuf->ptr;
1274 content->len = ptr - xmlbuf->ptr;
1275 xmlbuf->ptr = ptr;
1276
1277 return TRUE;
1278 }
1279
1280 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1281 {
1282 unsigned int ver[4];
1283 unsigned int pos;
1284 const WCHAR *curr;
1285 UNICODE_STRING strU;
1286
1287 /* major.minor.build.revision */
1288 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1289 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1290 {
1291 if (*curr >= '0' && *curr <= '9')
1292 {
1293 ver[pos] = ver[pos] * 10 + *curr - '0';
1294 if (ver[pos] >= 0x10000) goto error;
1295 }
1296 else if (*curr == '.')
1297 {
1298 if (++pos >= 4) goto error;
1299 }
1300 else goto error;
1301 }
1302 version->major = ver[0];
1303 version->minor = ver[1];
1304 version->build = ver[2];
1305 version->revision = ver[3];
1306 return TRUE;
1307
1308 error:
1309 strU = xmlstr2unicode(str);
1310 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU );
1311 return FALSE;
1312 }
1313
1314 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1315 {
1316 xmlstr_t elem;
1317 UNICODE_STRING elemU;
1318 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1319 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1320 elemU = xmlstr2unicode(&elem);
1321 DPRINT1( "unexpected element %wZ\n", &elemU );
1322 return FALSE;
1323 }
1324
1325 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1326 {
1327 xmlstr_t attr_name, attr_value;
1328 UNICODE_STRING attr_nameU, attr_valueU;
1329 BOOL error;
1330
1331 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1332 {
1333 attr_nameU = xmlstr2unicode(&attr_name);
1334 attr_valueU = xmlstr2unicode(&attr_value);
1335 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU,
1336 &attr_valueU);
1337 }
1338 return !error;
1339 }
1340
1341 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1342 {
1343 BOOL end = FALSE;
1344 return parse_expect_no_attr(xmlbuf, &end) && !end;
1345 }
1346
1347 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1348 {
1349 xmlstr_t elem;
1350 UNICODE_STRING elemU;
1351 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1352 if (!xml_elem_cmp_end(&elem, name, namespace))
1353 {
1354 elemU = xmlstr2unicode(&elem);
1355 DPRINT1( "unexpected element %wZ\n", &elemU );
1356 return FALSE;
1357 }
1358 return parse_end_element(xmlbuf);
1359 }
1360
1361 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1362 {
1363 xmlstr_t attr_name, attr_value, elem;
1364 BOOL end = FALSE, error, ret = TRUE;
1365
1366 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1367 if(error || end) return end;
1368
1369 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1370 {
1371 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1372 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1373 break;
1374 else
1375 ret = parse_unknown_elem(xmlbuf, &elem);
1376 }
1377
1378 return ret && parse_end_element(xmlbuf);
1379 }
1380
1381 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1382 struct assembly_identity* ai)
1383 {
1384 xmlstr_t attr_name, attr_value;
1385 BOOL end = FALSE, error;
1386 UNICODE_STRING attr_valueU, attr_nameU;
1387
1388 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1389 {
1390 if (xmlstr_cmp(&attr_name, g_nameW))
1391 {
1392 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1393 }
1394 else if (xmlstr_cmp(&attr_name, typeW))
1395 {
1396 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1397 }
1398 else if (xmlstr_cmp(&attr_name, versionW))
1399 {
1400 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1401 }
1402 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1403 {
1404 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1405 }
1406 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1407 {
1408 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1409 }
1410 else if (xmlstr_cmp(&attr_name, languageW))
1411 {
1412 DPRINT("Unsupported yet language attribute (%.*S)\n",
1413 attr_value.len, attr_value.ptr);
1414 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1415 }
1416 else
1417 {
1418 attr_nameU = xmlstr2unicode(&attr_name);
1419 attr_valueU = xmlstr2unicode(&attr_value);
1420 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1421 }
1422 }
1423
1424 if (error || end) return end;
1425 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1426 }
1427
1428 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1429 {
1430 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1431 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1432 static const WCHAR freeW[] = {'F','r','e','e',0};
1433 static const WCHAR bothW[] = {'B','o','t','h',0};
1434
1435 if (value->len == 0) return ThreadingModel_No;
1436 if (xmlstr_cmp(value, apartW))
1437 return ThreadingModel_Apartment;
1438 else if (xmlstr_cmp(value, freeW))
1439 return ThreadingModel_Free;
1440 else if (xmlstr_cmp(value, bothW))
1441 return ThreadingModel_Both;
1442 else if (xmlstr_cmp(value, neutralW))
1443 return ThreadingModel_Neutral;
1444 else
1445 return ThreadingModel_No;
1446 };
1447
1448 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1449 {
1450 int min, max;
1451
1452 min = 0;
1453 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1454
1455 while (min <= max)
1456 {
1457 int n, c;
1458
1459 n = (min+max)/2;
1460
1461 c = strncmpW(olemisc_values[n].name, str, len);
1462 if (!c && !olemisc_values[n].name[len])
1463 return olemisc_values[n].value;
1464
1465 if (c >= 0)
1466 max = n-1;
1467 else
1468 min = n+1;
1469 }
1470
1471 DPRINT1("unknown flag %S\n", str);
1472 return 0;
1473 }
1474
1475 static DWORD parse_com_class_misc(const xmlstr_t *value)
1476 {
1477 const WCHAR *str = value->ptr, *start;
1478 DWORD flags = 0;
1479 int i = 0;
1480
1481 /* it's comma separated list of flags */
1482 while (i < value->len)
1483 {
1484 start = str;
1485 while (*str != ',' && (i++ < value->len)) str++;
1486
1487 flags |= get_olemisc_value(start, str-start);
1488
1489 /* skip separator */
1490 str++;
1491 i++;
1492 }
1493
1494 return flags;
1495 }
1496
1497 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1498 {
1499 struct progids *progids = &entity->u.comclass.progids;
1500
1501 if (progids->allocated == 0)
1502 {
1503 progids->allocated = 4;
1504 if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1505 }
1506
1507 if (progids->allocated == progids->num)
1508 {
1509 WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1510 2 * progids->allocated * sizeof(WCHAR*));
1511 if (!new_progids) return FALSE;
1512 progids->allocated *= 2;
1513 progids->progids = new_progids;
1514 }
1515
1516 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1517 progids->num++;
1518
1519 return TRUE;
1520 }
1521
1522 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1523 {
1524 xmlstr_t content;
1525 BOOL end = FALSE;
1526
1527 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1528 return FALSE;
1529
1530 if (!com_class_add_progid(&content, entity)) return FALSE;
1531 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1532 }
1533
1534 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1535 {
1536 xmlstr_t elem, attr_name, attr_value;
1537 BOOL ret = TRUE, end = FALSE, error;
1538 struct entity* entity;
1539 UNICODE_STRING attr_valueU, attr_nameU;
1540
1541 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1542 return FALSE;
1543
1544 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1545 {
1546 if (xmlstr_cmp(&attr_name, clsidW))
1547 {
1548 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1549 }
1550 else if (xmlstr_cmp(&attr_name, progidW))
1551 {
1552 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1553 }
1554 else if (xmlstr_cmp(&attr_name, tlbidW))
1555 {
1556 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1557 }
1558 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1559 {
1560 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1561 }
1562 else if (xmlstr_cmp(&attr_name, miscstatusW))
1563 {
1564 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1565 }
1566 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1567 {
1568 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1569 }
1570 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1571 {
1572 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1573 }
1574 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1575 {
1576 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1577 }
1578 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1579 {
1580 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1581 }
1582 else if (xmlstr_cmp(&attr_name, descriptionW))
1583 {
1584 /* not stored */
1585 }
1586 else
1587 {
1588 attr_nameU = xmlstr2unicode(&attr_name);
1589 attr_valueU = xmlstr2unicode(&attr_value);
1590 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1591 }
1592 }
1593
1594 if (error) return FALSE;
1595
1596 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1597 if (entity->u.comclass.progid)
1598 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1599
1600 if (end) return TRUE;
1601
1602 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1603 {
1604 if (xmlstr_cmp_end(&elem, comClassW))
1605 {
1606 ret = parse_end_element(xmlbuf);
1607 break;
1608 }
1609 else if (xmlstr_cmp(&elem, progidW))
1610 {
1611 ret = parse_com_class_progid(xmlbuf, entity);
1612 }
1613 else
1614 {
1615 attr_nameU = xmlstr2unicode(&elem);
1616 DPRINT1("unknown elem %wZ\n", &attr_nameU);
1617 ret = parse_unknown_elem(xmlbuf, &elem);
1618 }
1619 }
1620
1621 if (entity->u.comclass.progids.num)
1622 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1623
1624 return ret;
1625 }
1626
1627 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1628 {
1629 const WCHAR *curr;
1630 ULONG num = 0;
1631
1632 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1633 {
1634 if (*curr >= '0' && *curr <= '9')
1635 num = num * 10 + *curr - '0';
1636 else
1637 {
1638 UNICODE_STRING strU = xmlstr2unicode(str);
1639 DPRINT1("wrong numeric value %wZ\n", &strU);
1640 return FALSE;
1641 }
1642 }
1643 entity->u.ifaceps.nummethods = num;
1644
1645 return TRUE;
1646 }
1647
1648 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1649 {
1650 xmlstr_t attr_name, attr_value;
1651 BOOL end = FALSE, error;
1652 struct entity* entity;
1653 UNICODE_STRING attr_valueU, attr_nameU;
1654
1655 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1656 return FALSE;
1657
1658 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1659 {
1660 if (xmlstr_cmp(&attr_name, iidW))
1661 {
1662 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1663 }
1664 else if (xmlstr_cmp(&attr_name, g_nameW))
1665 {
1666 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1667 }
1668 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1669 {
1670 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1671 entity->u.ifaceps.mask |= BaseIface;
1672 }
1673 else if (xmlstr_cmp(&attr_name, nummethodsW))
1674 {
1675 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1676 entity->u.ifaceps.mask |= NumMethods;
1677 }
1678 else if (xmlstr_cmp(&attr_name, tlbidW))
1679 {
1680 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1681 }
1682 /* not used */
1683 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1684 {
1685 }
1686 else
1687 {
1688 attr_nameU = xmlstr2unicode(&attr_name);
1689 attr_valueU = xmlstr2unicode(&attr_value);
1690 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1691 }
1692 }
1693
1694 if (error) return FALSE;
1695 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1696 if (end) return TRUE;
1697
1698 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1699 }
1700
1701 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1702 {
1703 WORD *flags = &entity->u.typelib.flags;
1704 const WCHAR *str = value->ptr, *start;
1705 int i = 0;
1706
1707 *flags = 0;
1708
1709 /* it's comma separated list of flags */
1710 while (i < value->len)
1711 {
1712 start = str;
1713 while (*str != ',' && (i++ < value->len)) str++;
1714
1715 if (!strncmpiW(start, restrictedW, str-start))
1716 *flags |= LIBFLAG_FRESTRICTED;
1717 else if (!strncmpiW(start, controlW, str-start))
1718 *flags |= LIBFLAG_FCONTROL;
1719 else if (!strncmpiW(start, hiddenW, str-start))
1720 *flags |= LIBFLAG_FHIDDEN;
1721 else if (!strncmpiW(start, hasdiskimageW, str-start))
1722 *flags |= LIBFLAG_FHASDISKIMAGE;
1723 else
1724 {
1725 UNICODE_STRING valueU = xmlstr2unicode(value);
1726 DPRINT1("unknown flags value %wZ\n", &valueU);
1727 return FALSE;
1728 }
1729
1730 /* skip separator */
1731 str++;
1732 i++;
1733 }
1734
1735 return TRUE;
1736 }
1737
1738 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1739 {
1740 unsigned int ver[2];
1741 unsigned int pos;
1742 const WCHAR *curr;
1743 UNICODE_STRING strW;
1744
1745 /* major.minor */
1746 ver[0] = ver[1] = pos = 0;
1747 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1748 {
1749 if (*curr >= '0' && *curr <= '9')
1750 {
1751 ver[pos] = ver[pos] * 10 + *curr - '0';
1752 if (ver[pos] >= 0x10000) goto error;
1753 }
1754 else if (*curr == '.')
1755 {
1756 if (++pos >= 2) goto error;
1757 }
1758 else goto error;
1759 }
1760 entity->u.typelib.major = ver[0];
1761 entity->u.typelib.minor = ver[1];
1762 return TRUE;
1763
1764 error:
1765 strW = xmlstr2unicode(str);
1766 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
1767 return FALSE;
1768 }
1769
1770 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1771 {
1772 xmlstr_t attr_name, attr_value;
1773 BOOL end = FALSE, error;
1774 struct entity* entity;
1775 UNICODE_STRING attr_valueU, attr_nameU;
1776
1777 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1778 return FALSE;
1779
1780 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1781 {
1782 if (xmlstr_cmp(&attr_name, tlbidW))
1783 {
1784 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1785 }
1786 else if (xmlstr_cmp(&attr_name, versionW))
1787 {
1788 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1789 }
1790 else if (xmlstr_cmp(&attr_name, helpdirW))
1791 {
1792 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1793 }
1794 else if (xmlstr_cmp(&attr_name, flagsW))
1795 {
1796 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1797 }
1798 else
1799 {
1800 attr_nameU = xmlstr2unicode(&attr_name);
1801 attr_valueU = xmlstr2unicode(&attr_value);
1802 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1803 }
1804 }
1805
1806 if (error) return FALSE;
1807
1808 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1809
1810 if (end) return TRUE;
1811
1812 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1813 }
1814
1815 static inline int aligned_string_len(int len)
1816 {
1817 return (len + 3) & ~3;
1818 }
1819
1820 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1821 {
1822 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1823 struct assembly_version *ver = &assembly->id.version;
1824 WCHAR buff[25];
1825
1826 if (!ret) ret = buff;
1827 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1828 }
1829
1830 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1831 {
1832 xmlstr_t elem, content, attr_name, attr_value;
1833 BOOL end = FALSE, ret = TRUE, error;
1834 struct entity* entity;
1835 UNICODE_STRING elemU, attr_nameU, attr_valueU;
1836
1837 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1838 return FALSE;
1839
1840 entity->u.class.versioned = TRUE;
1841 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1842 {
1843 if (xmlstr_cmp(&attr_name, versionedW))
1844 {
1845 if (xmlstr_cmpi(&attr_value, noW))
1846 entity->u.class.versioned = FALSE;
1847 else if (!xmlstr_cmpi(&attr_value, yesW))
1848 return FALSE;
1849 }
1850 else
1851 {
1852 attr_nameU = xmlstr2unicode(&attr_name);
1853 attr_valueU = xmlstr2unicode(&attr_value);
1854 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1855 }
1856 }
1857
1858 if (error || end) return end;
1859
1860 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1861
1862 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1863
1864 acl->actctx->sections |= WINDOWCLASS_SECTION;
1865
1866 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1867 {
1868 if (xmlstr_cmp_end(&elem, windowClassW))
1869 {
1870 ret = parse_end_element(xmlbuf);
1871 break;
1872 }
1873 else
1874 {
1875 elemU = xmlstr2unicode(&elem);
1876 DPRINT1("unknown elem %wZ\n", &elemU);
1877 ret = parse_unknown_elem(xmlbuf, &elem);
1878 }
1879 }
1880
1881 return ret;
1882 }
1883
1884 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1885 {
1886 xmlstr_t attr_name, attr_value;
1887 UNICODE_STRING attr_valueU, attr_nameU;
1888 BOOL end = FALSE, error;
1889
1890 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1891 {
1892 attr_nameU = xmlstr2unicode(&attr_name);
1893 attr_valueU = xmlstr2unicode(&attr_value);
1894
1895 if (xmlstr_cmp(&attr_name, oldVersionW))
1896 {
1897 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
1898 }
1899 else if (xmlstr_cmp(&attr_name, newVersionW))
1900 {
1901 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
1902 }
1903 else
1904 {
1905 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1906 }
1907 }
1908
1909 if (error || end) return end;
1910 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1911 }
1912
1913 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1914 {
1915 xmlstr_t elem, content, attr_name, attr_value;
1916 BOOL end = FALSE, ret = TRUE, error = FALSE;
1917
1918 UNICODE_STRING elem1U, elem2U;
1919
1920 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1921 {
1922 elem1U = xmlstr2unicode(&attr_name);
1923 elem2U = xmlstr2unicode(&attr_value);
1924 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
1925 }
1926
1927 if (error) return FALSE;
1928 if (end) return TRUE;
1929
1930 if (!parse_text_content(xmlbuf, &content))
1931 return FALSE;
1932
1933 elem1U = xmlstr2unicode(&content);
1934 DPRINT("Got description %wZ\n", &elem1U);
1935
1936 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1937 {
1938 if (xmlstr_cmp_end(&elem, descriptionW))
1939 {
1940 ret = parse_end_element(xmlbuf);
1941 break;
1942 }
1943 else
1944 {
1945 elem1U = xmlstr2unicode(&elem);
1946 DPRINT1("unknown elem %wZ\n", &elem1U);
1947 ret = parse_unknown_elem(xmlbuf, &elem);
1948 }
1949 }
1950
1951 return ret;
1952 }
1953
1954 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1955 struct assembly* assembly,
1956 struct actctx_loader* acl)
1957 {
1958 xmlstr_t attr_name, attr_value;
1959 UNICODE_STRING attr_nameU, attr_valueU;
1960 BOOL end = FALSE, error;
1961 struct entity* entity;
1962
1963 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1964 if (!entity) return FALSE;
1965
1966 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1967 {
1968 if (xmlstr_cmp(&attr_name, iidW))
1969 {
1970 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1971 }
1972 else if (xmlstr_cmp(&attr_name, g_nameW))
1973 {
1974 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1975 }
1976 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1977 {
1978 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1979 entity->u.ifaceps.mask |= BaseIface;
1980 }
1981 else if (xmlstr_cmp(&attr_name, nummethodsW))
1982 {
1983 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1984 entity->u.ifaceps.mask |= NumMethods;
1985 }
1986 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1987 {
1988 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1989 }
1990 else if (xmlstr_cmp(&attr_name, tlbidW))
1991 {
1992 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1993 }
1994 else
1995 {
1996 attr_nameU = xmlstr2unicode(&attr_name);
1997 attr_valueU = xmlstr2unicode(&attr_value);
1998 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1999 }
2000 }
2001
2002 if (error) return FALSE;
2003 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2004 if (end) return TRUE;
2005
2006 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
2007 }
2008
2009 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2010 {
2011 xmlstr_t attr_name, attr_value, elem;
2012 BOOL end = FALSE, error, ret = TRUE;
2013 struct entity* entity;
2014
2015 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
2016 if (!entity) return FALSE;
2017
2018 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2019 {
2020 if (xmlstr_cmp(&attr_name, g_nameW))
2021 {
2022 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
2023 }
2024 else if (xmlstr_cmp(&attr_name, clsidW))
2025 {
2026 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
2027 }
2028 else if (xmlstr_cmp(&attr_name, progidW))
2029 {
2030 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
2031 }
2032 else if (xmlstr_cmp(&attr_name, tlbidW))
2033 {
2034 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
2035 }
2036 else if (xmlstr_cmp(&attr_name, threadingmodelW))
2037 {
2038 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
2039 }
2040 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2041 {
2042 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
2043 }
2044 else
2045 {
2046 UNICODE_STRING attr_nameU, attr_valueU;
2047 attr_nameU = xmlstr2unicode(&attr_name);
2048 attr_valueU = xmlstr2unicode(&attr_value);
2049 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2050 }
2051 }
2052
2053 if (error) return FALSE;
2054 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2055 if (entity->u.comclass.progid)
2056 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2057 if (end) return TRUE;
2058
2059 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2060 {
2061 if (xmlstr_cmp_end(&elem, clrClassW))
2062 {
2063 ret = parse_end_element(xmlbuf);
2064 break;
2065 }
2066 else if (xmlstr_cmp(&elem, progidW))
2067 {
2068 ret = parse_com_class_progid(xmlbuf, entity);
2069 }
2070 else
2071 {
2072 UNICODE_STRING elemU = xmlstr2unicode(&elem);
2073 DPRINT1("unknown elem %wZ\n", &elemU);
2074 ret = parse_unknown_elem(xmlbuf, &elem);
2075 }
2076 }
2077
2078 if (entity->u.comclass.progids.num)
2079 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2080
2081 return ret;
2082 }
2083
2084 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2085 {
2086 xmlstr_t attr_name, attr_value;
2087 UNICODE_STRING attr_nameU, attr_valueU;
2088 BOOL end = FALSE, error;
2089 struct entity* entity;
2090
2091 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2092 if (!entity) return FALSE;
2093
2094 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2095 {
2096 if (xmlstr_cmp(&attr_name, g_nameW))
2097 {
2098 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2099 }
2100 else if (xmlstr_cmp(&attr_name, clsidW))
2101 {
2102 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2103 }
2104 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2105 {
2106 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2107 }
2108 else
2109 {
2110 attr_nameU = xmlstr2unicode(&attr_name);
2111 attr_valueU = xmlstr2unicode(&attr_value);
2112 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2113 }
2114 }
2115
2116 if (error) return FALSE;
2117 acl->actctx->sections |= CLRSURROGATES_SECTION;
2118 if (end) return TRUE;
2119
2120 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2121 }
2122
2123 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2124 {
2125 struct assembly_identity ai;
2126 xmlstr_t elem, attr_name, attr_value;
2127 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2128
2129 UNICODE_STRING elem1U, elem2U;
2130
2131 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2132 {
2133 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2134 static const WCHAR trueW[] = {'t','r','u','e',0};
2135
2136 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2137 delayed = xmlstr_cmp(&attr_value, trueW);
2138 else
2139 {
2140 elem1U = xmlstr2unicode(&attr_name);
2141 elem2U = xmlstr2unicode(&attr_value);
2142 DPRINT1("unknown attr %s=%s\n", &elem1U, &elem2U);
2143 }
2144 }
2145
2146 if (error || end) return end;
2147
2148 memset(&ai, 0, sizeof(ai));
2149 ai.optional = optional;
2150 ai.delayed = delayed;
2151
2152 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2153 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2154 return FALSE;
2155
2156 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2157
2158 /* store the newly found identity for later loading */
2159 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2160
2161 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2162 {
2163 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2164 {
2165 ret = parse_end_element(xmlbuf);
2166 break;
2167 }
2168 else if (xmlstr_cmp(&elem, bindingRedirectW))
2169 {
2170 ret = parse_binding_redirect_elem(xmlbuf);
2171 }
2172 else
2173 {
2174 DPRINT1("unknown elem %S\n", elem.ptr);
2175 ret = parse_unknown_elem(xmlbuf, &elem);
2176 }
2177 }
2178
2179 return ret;
2180 }
2181
2182 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2183 {
2184 xmlstr_t attr_name, attr_value, elem;
2185 UNICODE_STRING attr_nameU, attr_valueU;
2186 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2187
2188 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2189 {
2190 attr_nameU = xmlstr2unicode(&attr_name);
2191 attr_valueU = xmlstr2unicode(&attr_value);
2192
2193 if (xmlstr_cmp(&attr_name, optionalW))
2194 {
2195 optional = xmlstr_cmpi( &attr_value, yesW );
2196 DPRINT1("optional=%wZ\n", &attr_valueU);
2197 }
2198 else
2199 {
2200 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2201 }
2202 }
2203
2204 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2205 {
2206 if (xmlstr_cmp_end(&elem, dependencyW))
2207 {
2208 ret = parse_end_element(xmlbuf);
2209 break;
2210 }
2211 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2212 {
2213 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2214 }
2215 else
2216 {
2217 attr_nameU = xmlstr2unicode(&elem);
2218 DPRINT1("unknown element %wZ\n", &attr_nameU);
2219 ret = parse_unknown_elem(xmlbuf, &elem);
2220 }
2221 }
2222
2223 return ret;
2224 }
2225
2226 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2227 {
2228 BOOL end = FALSE;
2229
2230 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2231 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2232 }
2233
2234 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2235 {
2236 BOOL end = FALSE;
2237
2238 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2239 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2240 }
2241
2242 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2243 {
2244 xmlstr_t attr_name, attr_value, elem;
2245 UNICODE_STRING attr_nameU, attr_valueU;
2246 BOOL end = FALSE, error, ret = TRUE;
2247 struct dll_redirect* dll;
2248
2249 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2250
2251 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2252 {
2253 attr_nameU = xmlstr2unicode(&attr_name);
2254 attr_valueU = xmlstr2unicode(&attr_value);
2255
2256 if (xmlstr_cmp(&attr_name, g_nameW))
2257 {
2258 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2259 DPRINT("name=%wZ\n", &attr_valueU);
2260 }
2261 else if (xmlstr_cmp(&attr_name, hashW))
2262 {
2263 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2264 }
2265 else if (xmlstr_cmp(&attr_name, hashalgW))
2266 {
2267 static const WCHAR sha1W[] = {'S','H','A','1',0};
2268 if (!xmlstr_cmpi(&attr_value, sha1W))
2269 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
2270 }
2271 else
2272 {
2273 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2274 }
2275 }
2276
2277 if (error || !dll->name) return FALSE;
2278
2279 acl->actctx->sections |= DLLREDIRECT_SECTION;
2280
2281 if (end) return TRUE;
2282
2283 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2284 {
2285 if (xmlstr_cmp_end(&elem, fileW))
2286 {
2287 ret = parse_end_element(xmlbuf);
2288 break;
2289 }
2290 else if (xmlstr_cmp(&elem, comClassW))
2291 {
2292 ret = parse_com_class_elem(xmlbuf, dll, acl);
2293 }
2294 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2295 {
2296 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2297 }
2298 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2299 {
2300 DPRINT1("asmv2hash (undocumented) not supported\n");
2301 ret = parse_unknown_elem(xmlbuf, &elem);
2302 }
2303 else if (xmlstr_cmp(&elem, typelibW))
2304 {
2305 ret = parse_typelib_elem(xmlbuf, dll, acl);
2306 }
2307 else if (xmlstr_cmp(&elem, windowClassW))
2308 {
2309 ret = parse_window_class_elem(xmlbuf, dll, acl);
2310 }
2311 else
2312 {
2313 attr_nameU = xmlstr2unicode(&elem);
2314 DPRINT1("unknown elem %wZ\n", &attr_nameU);
2315 ret = parse_unknown_elem( xmlbuf, &elem );
2316 }
2317 }
2318
2319 return ret;
2320 }
2321
2322 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2323 struct assembly* assembly,
2324 struct assembly_identity* expected_ai)
2325 {
2326 xmlstr_t attr_name, attr_value, elem;
2327 UNICODE_STRING attr_nameU, attr_valueU;
2328 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2329
2330 DPRINT("(%p)\n", xmlbuf);
2331
2332 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2333 {
2334 attr_nameU = xmlstr2unicode(&attr_name);
2335 attr_valueU = xmlstr2unicode(&attr_value);
2336
2337 if (xmlstr_cmp(&attr_name, manifestVersionW))
2338 {
2339 static const WCHAR v10W[] = {'1','.','0',0};
2340 if (!xmlstr_cmp(&attr_value, v10W))
2341 {
2342 DPRINT1("wrong version %wZ\n", &attr_valueU);
2343 return FALSE;
2344 }
2345 version = TRUE;
2346 }
2347 else if (xmlstr_cmp(&attr_name, xmlnsW))
2348 {
2349 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2350 !xmlstr_cmp(&attr_value, manifestv2W) &&
2351 !xmlstr_cmp(&attr_value, manifestv3W))
2352 {
2353 DPRINT1("wrong namespace %wZ\n", &attr_valueU);
2354 return FALSE;
2355 }
2356 xmlns = TRUE;
2357 }
2358 else
2359 {
2360 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
2361 }
2362 }
2363
2364 if (error || end || !xmlns || !version) return FALSE;
2365 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2366
2367 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2368 {
2369 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2370 return FALSE;
2371 assembly->no_inherit = TRUE;
2372 }
2373
2374 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2375 {
2376 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2377 return FALSE;
2378 }
2379 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2380 assembly->no_inherit)
2381 return FALSE;
2382
2383 while (ret)
2384 {
2385 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2386 {
2387 ret = parse_end_element(xmlbuf);
2388 break;
2389 }
2390 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2391 {
2392 ret = parse_description_elem(xmlbuf);
2393 }
2394 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2395 {
2396 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2397 }
2398 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2399 {
2400 ret = parse_dependency_elem(xmlbuf, acl);
2401 }
2402 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2403 {
2404 ret = parse_file_elem(xmlbuf, assembly, acl);
2405 }
2406 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2407 {
2408 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2409 }
2410 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2411 {
2412 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2413 }
2414 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2415 {
2416 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2417
2418 if (expected_ai)
2419 {
2420 /* FIXME: more tests */
2421 if (assembly->type == ASSEMBLY_MANIFEST &&
2422 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2423 {
2424 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2425 expected_ai->version.major, expected_ai->version.minor,
2426 expected_ai->version.build, expected_ai->version.revision,
2427 assembly->id.version.major, assembly->id.version.minor,
2428 assembly->id.version.build, assembly->id.version.revision);
2429 ret = FALSE;
2430 }
2431 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2432 (assembly->id.version.major != expected_ai->version.major ||
2433 assembly->id.version.minor != expected_ai->version.minor ||
2434 assembly->id.version.build < expected_ai->version.build ||
2435 (assembly->id.version.build == expected_ai->version.build &&
2436 assembly->id.version.revision < expected_ai->version.revision)))
2437 {
2438 DPRINT1("wrong version for shared assembly manifest\n");
2439 ret = FALSE;
2440 }
2441 }
2442 }
2443 #ifdef __REACTOS__
2444 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2445 {
2446 ret = parse_unknown_elem(xmlbuf, &elem);
2447 }
2448 #endif
2449 else
2450 {
2451 attr_nameU = xmlstr2unicode(&elem);
2452 DPRINT1("unknown element %wZ\n", &attr_nameU);
2453 ret = parse_unknown_elem(xmlbuf, &elem);
2454 }
2455 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2456 }
2457
2458 return ret;
2459 }
2460
2461 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2462 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2463 {
2464 xmlstr_t elem;
2465 UNICODE_STRING elemU;
2466
2467 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2468
2469 if (xmlstr_cmp(&elem, g_xmlW) &&
2470 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2471 return STATUS_SXS_CANT_GEN_ACTCTX;
2472
2473 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2474 {
2475 elemU = xmlstr2unicode(&elem);
2476 DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
2477 return STATUS_SXS_CANT_GEN_ACTCTX;
2478 }
2479
2480 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2481 {
2482 DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
2483 return STATUS_SXS_CANT_GEN_ACTCTX;
2484 }
2485
2486 if (next_xml_elem(xmlbuf, &elem))
2487 {
2488 elemU = xmlstr2unicode(&elem);
2489 DPRINT1("unexpected element %wZ\n", &elemU);
2490 return STATUS_SXS_CANT_GEN_ACTCTX;
2491 }
2492
2493 if (xmlbuf->ptr != xmlbuf->end)
2494 {
2495 DPRINT1("parse error\n");
2496 return STATUS_SXS_CANT_GEN_ACTCTX;
2497 }
2498 return STATUS_SUCCESS;
2499 }
2500
2501 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2502 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2503 const void *buffer, SIZE_T size )
2504 {
2505 xmlbuf_t xmlbuf;
2506 NTSTATUS status;
2507 struct assembly *assembly;
2508 int unicode_tests;
2509
2510 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2511
2512 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2513 return STATUS_SXS_CANT_GEN_ACTCTX;
2514
2515 if (directory && !(assembly->directory = strdupW(directory)))
2516 return STATUS_NO_MEMORY;
2517
2518 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2519 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2520 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2521
2522 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2523 if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2524 {
2525 xmlbuf.ptr = buffer;
2526 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2527 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2528 }
2529 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2530 {
2531 const WCHAR *buf = buffer;
2532 WCHAR *new_buff;
2533 unsigned int i;
2534
2535 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2536 return STATUS_NO_MEMORY;
2537 for (i = 0; i < size / sizeof(WCHAR); i++)
2538 new_buff[i] = RtlUshortByteSwap( buf[i] );
2539 xmlbuf.ptr = new_buff;
2540 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2541 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2542 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2543 }
2544 else
2545 {
2546 /* TODO: this doesn't handle arbitrary encodings */
2547 WCHAR *new_buff;
2548 ULONG sizeU;
2549
2550 status = RtlMultiByteToUnicodeSize(&sizeU, buffer, size);
2551 if (!NT_SUCCESS(status))
2552 {
2553 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2554 return STATUS_SXS_CANT_GEN_ACTCTX;
2555 }
2556
2557 new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2558 if (!new_buff)
2559 return STATUS_NO_MEMORY;
2560
2561 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2562 if (!NT_SUCCESS(status))
2563 {
2564 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2565 return STATUS_SXS_CANT_GEN_ACTCTX;
2566 }
2567
2568 xmlbuf.ptr = new_buff;
2569 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2570 status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2571 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2572 }
2573 return status;
2574 }
2575
2576 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2577 {
2578 OBJECT_ATTRIBUTES attr;
2579 IO_STATUS_BLOCK io;
2580
2581 attr.Length = sizeof(attr);
2582 attr.RootDirectory = 0;
2583 attr.Attributes = OBJ_CASE_INSENSITIVE;
2584 attr.ObjectName = name;
2585 attr.SecurityDescriptor = NULL;
2586 attr.SecurityQualityOfService = NULL;
2587 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2588 }
2589
2590 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
2591 {
2592 NTSTATUS status;
2593 ULONG_PTR magic;
2594 LDR_DATA_TABLE_ENTRY *pldr;
2595
2596 LdrLockLoaderLock(0, NULL, &magic);
2597 status = LdrFindEntryForAddress( module, &pldr );
2598 if (status == STATUS_SUCCESS)
2599 {
2600 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2601 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2602 {
2603 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2604 str->Length = pldr->FullDllName.Length;
2605 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2606 }
2607 else status = STATUS_NO_MEMORY;
2608 }
2609 LdrUnlockLoaderLock(0, magic);
2610 return status;
2611 }
2612
2613 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2614 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2615 HANDLE hModule, LPCWSTR resname, ULONG lang )
2616 {
2617 NTSTATUS status;
2618 UNICODE_STRING nameW;
2619 LDR_RESOURCE_INFO info;
2620 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2621 void *ptr;
2622
2623 //DPRINT( "looking for res %s in module %p %s\n", resname,
2624 // hModule, filename );
2625 DPRINT("get_manifest_in_module %p\n", hModule);
2626
2627 #if 0
2628 if (TRACE_ON(actctx))
2629 {
2630 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2631 {
2632 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2633 hModule, debugstr_w(nameW.Buffer) );
2634 RtlFreeUnicodeString( &nameW );
2635 }
2636 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2637 hModule, debugstr_w(filename) );
2638 }
2639 #endif
2640
2641 if (!resname) return STATUS_INVALID_PARAMETER;
2642
2643 info.Type = (ULONG_PTR)RT_MANIFEST;
2644 info.Language = lang;
2645 if (!((ULONG_PTR)resname >> 16))
2646 {
2647 info.Name = (ULONG_PTR)resname;
2648 status = LdrFindResource_U(hModule, &info, 3, &entry);
2649 }
2650 else if (resname[0] == '#')
2651 {
2652 ULONG value;
2653 RtlInitUnicodeString(&nameW, resname + 1);
2654 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2655 return STATUS_INVALID_PARAMETER;
2656 info.Name = value;
2657 status = LdrFindResource_U(hModule, &info, 3, &entry);
2658 }
2659 else
2660 {
2661 RtlCreateUnicodeString(&nameW, resname);
2662 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2663 info.Name = (ULONG_PTR)nameW.Buffer;
2664 status = LdrFindResource_U(hModule, &info, 3, &entry);
2665 RtlFreeUnicodeString(&nameW);
2666 }
2667 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2668
2669 if (status == STATUS_SUCCESS)
2670 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2671
2672 return status;
2673 }
2674
2675 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2676 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2677 HANDLE file, LPCWSTR resname, ULONG lang )
2678 {
2679 HANDLE mapping;
2680 OBJECT_ATTRIBUTES attr;
2681 LARGE_INTEGER size;
2682 LARGE_INTEGER offset;
2683 NTSTATUS status;
2684 SIZE_T count;
2685 void *base;
2686
2687 DPRINT( "looking for res %S in %S\n", resname, filename );
2688
2689 attr.Length = sizeof(attr);
2690 attr.RootDirectory = 0;
2691 attr.ObjectName = NULL;
2692 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2693 attr.SecurityDescriptor = NULL;
2694 attr.SecurityQualityOfService = NULL;
2695
2696 size.QuadPart = 0;
2697 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2698 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2699 if (status != STATUS_SUCCESS) return status;
2700
2701 offset.QuadPart = 0;
2702 count = 0;
2703 base = NULL;
2704 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2705 &count, ViewShare, 0, PAGE_READONLY );
2706 NtClose( mapping );
2707 if (status != STATUS_SUCCESS) return status;
2708
2709 if (RtlImageNtHeader(base)) /* we got a PE file */
2710 {
2711 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2712 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2713 }
2714 else status = STATUS_INVALID_IMAGE_FORMAT;
2715
2716 NtUnmapViewOfSection( NtCurrentProcess(), base );
2717 return status;
2718 }
2719
2720 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2721 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2722 {
2723 FILE_STANDARD_INFORMATION info;
2724 IO_STATUS_BLOCK io;
2725 HANDLE mapping;
2726 OBJECT_ATTRIBUTES attr;
2727 LARGE_INTEGER size;
2728 LARGE_INTEGER offset;
2729 NTSTATUS status;
2730 SIZE_T count;
2731 void *base;
2732
2733 DPRINT( "loading manifest file %S\n", filename );
2734
2735 attr.Length = sizeof(attr);
2736 attr.RootDirectory = 0;
2737 attr.ObjectName = NULL;
2738 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2739 attr.SecurityDescriptor = NULL;
2740 attr.SecurityQualityOfService = NULL;
2741
2742 size.QuadPart = 0;
2743 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2744 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2745
2746 if (status != STATUS_SUCCESS) return status;
2747
2748 offset.QuadPart = 0;
2749 count = 0;
2750 base = NULL;
2751 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
2752 &count, ViewShare, 0, PAGE_READONLY );
2753 NtClose( mapping );
2754 if (status != STATUS_SUCCESS) return status;
2755
2756 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2757 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
2758
2759 if (status == STATUS_SUCCESS)
2760 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
2761
2762 NtUnmapViewOfSection( NtCurrentProcess(), base );
2763 return status;
2764 }
2765
2766 /* try to load the .manifest file associated to the file */
2767 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2768 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2769 {
2770 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2771 WCHAR *buffer;
2772 NTSTATUS status;
2773 UNICODE_STRING nameW;
2774 HANDLE file;
2775 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
2776
2777 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2778
2779 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
2780
2781 if (module) /* use the module filename */
2782 {
2783 UNICODE_STRING name;
2784
2785 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2786 {
2787 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2788 strcatW( name.Buffer, dotManifestW );
2789 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2790 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2791 RtlFreeUnicodeString( &name );
2792 }
2793 if (status) return status;
2794 }
2795 else
2796 {
2797 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2798 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2799 return STATUS_NO_MEMORY;
2800 strcpyW( buffer, filename );
2801 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2802 strcatW( buffer, dotManifestW );
2803 RtlInitUnicodeString( &nameW, buffer );
2804 }
2805
2806 if (!open_nt_file( &file, &nameW ))
2807 {
2808 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2809 NtClose( file );
2810 }
2811 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2812 RtlFreeUnicodeString( &nameW );
2813 return status;
2814 }
2815
2816 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2817 {
2818 static const WCHAR lookup_fmtW[] =
2819 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2820 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2821 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2822
2823 WCHAR *lookup, *ret = NULL;
2824 UNICODE_STRING lookup_us;
2825 IO_STATUS_BLOCK io;
2826 const WCHAR *lang = ai->language;
2827 unsigned int data_pos = 0, data_len;
2828 char buffer[8192];
2829
2830 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2831 (strlenW(ai->arch) + strlenW(ai->name)
2832 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2833 + sizeof(lookup_fmtW) )))
2834 return NULL;
2835
2836 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2837 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2838 ai->version.major, ai->version.minor, lang );
2839 RtlInitUnicodeString( &lookup_us, lookup );
2840
2841 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2842 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2843 {
2844 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2845 FILE_BOTH_DIR_INFORMATION *dir_info;
2846 WCHAR *tmp;
2847 ULONG build, revision;
2848
2849 data_len = (ULONG)io.Information;
2850
2851 for (;;)
2852 {
2853 if (data_pos >= data_len)
2854 {
2855 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2856 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2857 break;
2858 data_len = (ULONG)io.Information;
2859 data_pos = 0;
2860 }
2861 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2862
2863 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2864 else data_pos = data_len;
2865
2866 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
2867 build = atoiW(tmp);
2868 if (build < min_build) continue;
2869 tmp = strchrW(tmp, '.') + 1;
2870 revision = atoiW(tmp);
2871 if (build == min_build && revision < min_revision) continue;
2872 tmp = strchrW(tmp, '_') + 1;
2873 tmp = strchrW(tmp, '_') + 1;
2874 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2875 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2876 {
2877 /* prefer a non-Wine manifest if we already have one */
2878 /* we'll still load the builtin dll if specified through DllOverrides */
2879 if (ret) continue;
2880 }
2881 else
2882 {
2883 min_build = build;
2884 min_revision = revision;
2885 }
2886 ai->version.build = build;
2887 ai->version.revision = revision;
2888 RtlFreeHeap( RtlGetProcessHeap(), 0, ret );
2889 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2890 {
2891 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2892 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2893 }
2894 }
2895 }
2896 else DPRINT1("no matching file for %S\n", lookup);
2897 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
2898 return ret;
2899 }
2900
2901 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2902 {
2903 struct assembly_identity sxs_ai;
2904 UNICODE_STRING path_us;
2905 OBJECT_ATTRIBUTES attr;
2906 IO_STATUS_BLOCK io;
2907 WCHAR *path, *file = NULL;
2908 HANDLE handle;
2909
2910 static const WCHAR manifest_dirW[] =
2911 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2912
2913 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2914
2915 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2916 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
2917 return STATUS_NO_MEMORY;
2918
2919 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
2920 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
2921
2922 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2923 {
2924 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2925 return STATUS_NO_SUCH_FILE;
2926 }
2927 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2928
2929 attr.Length = sizeof(attr);
2930 attr.RootDirectory = 0;
2931 attr.Attributes = OBJ_CASE_INSENSITIVE;
2932 attr.ObjectName = &path_us;
2933 attr.SecurityDescriptor = NULL;
2934 attr.SecurityQualityOfService = NULL;
2935
2936 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2937 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2938 {
2939 sxs_ai = *ai;
2940 file = lookup_manifest_file( handle, &sxs_ai );
2941 NtClose( handle );
2942 }
2943 if (!file)
2944 {
2945 RtlFreeUnicodeString( &path_us );
2946 return STATUS_NO_SUCH_FILE;
2947 }
2948
2949 /* append file name to directory path */
2950 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
2951 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2952 {
2953 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2954 RtlFreeUnicodeString( &path_us );
2955 return STATUS_NO_MEMORY;
2956 }
2957
2958 path[path_us.Length/sizeof(WCHAR)] = '\\';
2959 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2960 RtlInitUnicodeString( &path_us, path );
2961 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2962
2963 if (!open_nt_file( &handle, &path_us ))
2964 {
2965 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2966 NtClose( handle );
2967 }
2968 else io.Status = STATUS_NO_SUCH_FILE;
2969
2970 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2971 RtlFreeUnicodeString( &path_us );
2972 return io.Status;
2973 }
2974
2975 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2976 struct assembly_identity* ai)
2977 {
2978 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2979 unsigned int i;
2980 WCHAR *buffer, *p, *directory;
2981 NTSTATUS status;
2982 UNICODE_STRING nameW;
2983 HANDLE file;
2984 DWORD len;
2985
2986 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2987 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
2988
2989 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2990
2991 /* FIXME: add support for language specific lookup */
2992
2993 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2994 strlenW(acl->actctx->appdir.info));
2995
2996 nameW.Buffer = NULL;
2997 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2998 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2999 return STATUS_NO_MEMORY;
3000
3001 if (!(directory = build_assembly_dir( ai )))
3002 {
3003 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3004 return STATUS_NO_MEMORY;
3005 }
3006
3007 /* Lookup in <dir>\name.dll
3008 * <dir>\name.manifest
3009 * <dir>\name\name.dll
3010 * <dir>\name\name.manifest
3011 *
3012 * First 'appdir' is used as <dir>, if that failed
3013 * it tries application manifest file path.
3014 */
3015 strcpyW( buffer, acl->actctx->appdir.info );
3016 p = buffer + strlenW(buffer);
3017 for (i = 0; i < 4; i++)
3018 {
3019 if (i == 2)
3020 {
3021 struct assembly *assembly = acl->actctx->assemblies;
3022 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3023 }
3024 else *p++ = '\\';
3025
3026 strcpyW( p, ai->name );
3027 p += strlenW(p);
3028
3029 strcpyW( p, dotDllW );
3030 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3031 {
3032 status = open_nt_file( &file, &nameW );
3033 if (!status)
3034 {
3035 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3036 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3037 NtClose( file );
3038 break;
3039 }
3040 RtlFreeUnicodeString( &nameW );
3041 }
3042
3043 strcpyW( p, dotManifestW );
3044 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3045 {
3046 status = open_nt_file( &file, &nameW );
3047 if (!status)
3048 {
3049 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3050 NtClose( file );
3051 break;
3052 }
3053 RtlFreeUnicodeString( &nameW );
3054 }
3055 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3056 }
3057 RtlFreeUnicodeString( &nameW );
3058 RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
3059 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
3060 return status;
3061 }
3062
3063 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3064 {
3065 NTSTATUS status = STATUS_SUCCESS;
3066 unsigned int i;
3067
3068 for (i = 0; i < acl->num_dependencies; i++)
3069 {
3070 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3071 {
3072 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3073 {
3074 const struct assembly_version *ver = &acl->dependencies[i].version;
3075 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3076 acl->dependencies[i].name,
3077 ver->major, ver->minor, ver->build, ver->revision );
3078 status = STATUS_SXS_CANT_GEN_ACTCTX;
3079 break;
3080 }
3081 }
3082 }
3083 /* FIXME should now iterate through all refs */
3084 return status;
3085 }
3086
3087 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3088 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3089 {
3090 NTSTATUS status = STATUS_SUCCESS;
3091
3092 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT)
3093 {
3094 if (*handle) return STATUS_INVALID_PARAMETER;
3095
3096 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
3097 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
3098 }
3099 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE))
3100 {
3101 ULONG_PTR magic;
3102 LDR_DATA_TABLE_ENTRY *pldr;
3103
3104 if (!*handle) return STATUS_INVALID_PARAMETER;
3105
3106 LdrLockLoaderLock( 0, NULL, &magic );
3107 if (!LdrFindEntryForAddress( *handle, &pldr ))
3108 {
3109 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase)
3110 status = STATUS_DLL_NOT_FOUND;
3111 else
3112 *handle = pldr->EntryPointActivationContext;
3113 }
3114 else status = STATUS_DLL_NOT_FOUND;
3115 LdrUnlockLoaderLock( 0, magic );
3116 }
3117 else if (!*handle && (class != ActivationContextBasicInformation))
3118 *handle = process_actctx;
3119
3120 return status;
3121 }
3122
3123 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3124 {
3125 unsigned int i, j, total_len = 0, dll_count = 0;
3126 struct strsection_header *header;
3127 struct dllredirect_data *data;
3128 struct string_index *index;
3129 ULONG name_offset;
3130
3131 DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies);
3132
3133 /* compute section length */
3134 for (i = 0; i < actctx->num_assemblies; i++)
3135 {
3136 struct assembly *assembly = &actctx->assemblies[i];
3137 for (j = 0; j < assembly->num_dlls; j++)
3138 {
3139 struct dll_redirect *dll = &assembly->dlls[j];
3140
3141 /* each entry needs index, data and string data */
3142 total_len += sizeof(*index);
3143 total_len += sizeof(*data);
3144 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3145
3146 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name);
3147 }
3148
3149 dll_count += assembly->num_dlls;
3150 }
3151
3152 total_len += sizeof(*header);
3153
3154 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3155 if (!header) return STATUS_NO_MEMORY;
3156
3157 memset(header, 0, sizeof(*header));
3158 header->magic = STRSECTION_MAGIC;
3159 header->size = sizeof(*header);
3160 header->count = dll_count;
3161 header->index_offset = sizeof(*header);
3162 index = (struct string_index*)((BYTE*)header + header->index_offset);
3163 name_offset = header->index_offset + header->count*sizeof(*index);
3164
3165 for (i = 0; i < actctx->num_assemblies; i++)
3166 {
3167 struct assembly *assembly = &actctx->assemblies[i];
3168
3169 DPRINT("assembly->num_dlls %d\n", assembly->num_dlls);
3170
3171 for (j = 0; j < assembly->num_dlls; j++)
3172 {
3173 struct dll_redirect *dll = &assembly->dlls[j];
3174 UNICODE_STRING str;
3175 WCHAR *ptrW;
3176
3177 DPRINT("%d: dll name %S\n", j, dll->name);
3178 /* setup new index entry */
3179 str.Buffer = dll->name;
3180 str.Length = (USHORT)strlenW(dll->name)*sizeof(WCHAR);
3181 str.MaximumLength = str.Length + sizeof(WCHAR);
3182 /* hash original class name */
3183 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3184
3185 index->name_offset = name_offset;
3186 index->name_len = str.Length;
3187 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3188 index->data_len = sizeof(*data);
3189 index->rosterindex = i + 1;
3190
3191 /* setup data */
3192 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3193 data->size = sizeof(*data);
3194 data->unk = 2; /* FIXME: seems to be constant */
3195 memset(data->res, 0, sizeof(data->res));
3196
3197 /* dll name */
3198 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3199 memcpy(ptrW, dll->name, index->name_len);
3200 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3201
3202 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3203
3204 index++;
3205 }
3206 }
3207
3208 *section = header;
3209
3210 return STATUS_SUCCESS;
3211 }
3212
3213 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3214 {
3215 struct string_index *iter, *index = NULL;
3216 ULONG hash = 0, i;
3217
3218 DPRINT("section %p, name %wZ\n", section, name);
3219 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3220 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3221
3222 for (i = 0; i < section->count; i++)
3223 {
3224 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash);
3225 DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset));
3226 if (iter->hash == hash)
3227 {
3228 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3229
3230 if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) &&
3231 wcslen(nameW) == name->Length / sizeof(WCHAR))
3232 {
3233 index = iter;
3234 break;
3235 }
3236 else
3237 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3238 }
3239 iter++;
3240 }
3241
3242 return index;
3243 }
3244
3245 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3246 {
3247 struct guid_index *iter, *index = NULL;
3248 ULONG i;
3249
3250 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3251
3252 for (i = 0; i < section->count; i++)
3253 {
3254 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3255 {
3256 index = iter;
3257 break;
3258 }
3259 iter++;
3260 }
3261
3262 return index;
3263 }
3264
3265 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3266 {
3267 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3268 }
3269
3270 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3271 PACTCTX_SECTION_KEYED_DATA data)
3272 {
3273 struct dllredirect_data *dll;
3274 struct string_index *index;
3275
3276 DPRINT("sections: 0x%08X\n", actctx->sections);
3277 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3278
3279 DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section);
3280 if (!actctx->dllredirect_section)
3281 {
3282 struct strsection_header *section;
3283
3284 NTSTATUS status = build_dllredirect_section(actctx, &section);
3285 if (status) return status;
3286
3287 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3288 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3289 }
3290
3291 index = find_string_index(actctx->dllredirect_section, name);
3292 DPRINT("index: %d\n", index);
3293 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3294
3295 if (data)
3296 {
3297 dll = get_dllredirect_data(actctx, index);
3298
3299 data->ulDataFormatVersion = 1;
3300 data->lpData = dll;
3301 data->ulLength = dll->size;
3302 data->lpSectionGlobalData = NULL;
3303 data->ulSectionGlobalDataLength = 0;
3304 data->lpSectionBase = actctx->dllredirect_section;
3305 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
3306 data->hActCtx = NULL;
3307
3308 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3309 data->ulAssemblyRosterIndex = index->rosterindex;
3310 }
3311
3312 return STATUS_SUCCESS;
3313 }
3314
3315 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3316 {
3317 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3318 }
3319
3320 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3321 {
3322 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3323 }
3324
3325 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3326 {
3327 unsigned int i, j, k, total_len = 0, class_count = 0;
3328 struct wndclass_redirect_data *data;
3329 struct strsection_header *header;
3330 struct string_index *index;
3331 ULONG name_offset;
3332
3333 /* compute section length */
3334 for (i = 0; i < actctx->num_assemblies; i++)
3335 {
3336 struct assembly *assembly = &actctx->assemblies[i];
3337 for (j = 0; j < assembly->num_dlls; j++)
3338 {
3339 struct dll_redirect *dll = &assembly->dlls[j];
3340 for (k = 0; k < dll->entities.num; k++)
3341 {
3342 struct entity *entity = &dll->entities.base[k];
3343 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3344 {
3345 int class_len = strlenW(entity->u.class.name) + 1;
3346 int len;
3347
3348 /* each class entry needs index, data and string data */
3349 total_len += sizeof(*index);
3350 total_len += sizeof(*data);
3351 /* original name is stored separately */
3352 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3353 /* versioned name and module name are stored one after another */
3354 if (entity->u.class.versioned)
3355 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3356 else
3357 len = class_len;
3358 len += strlenW(dll->name) + 1;
3359 total_len += aligned_string_len(len*sizeof(WCHAR));
3360
3361 class_count++;
3362 }
3363 }
3364 }
3365 }
3366
3367 total_len += sizeof(*header);
3368
3369 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3370 if (!header) return STATUS_NO_MEMORY;
3371
3372 memset(header, 0, sizeof(*header));
3373 header->magic = STRSECTION_MAGIC;
3374 header->size = sizeof(*header);
3375 header->count = class_count;
3376 header->index_offset = sizeof(*header);
3377 index = (struct string_index*)((BYTE*)header + header->index_offset);
3378 name_offset = header->index_offset + header->count*sizeof(*index);
3379
3380 for (i = 0; i < actctx->num_assemblies; i++)
3381 {
3382 struct assembly *assembly = &actctx->assemblies[i];
3383 for (j = 0; j < assembly->num_dlls; j++)
3384 {
3385 struct dll_redirect *dll = &assembly->dlls[j];
3386 for (k = 0; k < dll->entities.num; k++)
3387 {
3388 struct entity *entity = &dll->entities.base[k];
3389 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3390 {
3391 static const WCHAR exclW[] = {'!',0};
3392 ULONG versioned_len, module_len;
3393 UNICODE_STRING str;
3394 WCHAR *ptrW;
3395
3396 /* setup new index entry */
3397 str.Buffer = entity->u.class.name;
3398 str.Length = (USHORT)strlenW(entity->u.class.name)*sizeof(WCHAR);
3399 str.MaximumLength = str.Length + sizeof(WCHAR);
3400 /* hash original class name */
3401 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3402
3403 /* include '!' separator too */
3404 if (entity->u.class.versioned)
3405 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3406 else
3407 versioned_len = str.Length;
3408 module_len = strlenW(dll->name)*sizeof(WCHAR);
3409
3410 index->name_offset = name_offset;
3411 index->name_len = str.Length;
3412 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3413 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3414 index->rosterindex = i + 1;
3415
3416 /* setup data */
3417 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3418 data->size = sizeof(*data);
3419 data->res = 0;
3420 data->name_len = versioned_len;
3421 data->name_offset = sizeof(*data);
3422 data->module_len = module_len;
3423 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3424
3425 /* original class name */
3426 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3427 memcpy(ptrW, entity->u.class.name, index->name_len);
3428 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3429
3430 /* module name */
3431 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3432 memcpy(ptrW, dll->name, data->module_len);
3433 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3434
3435 /* versioned name */
3436 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3437 if (entity->u.class.versioned)
3438 {
3439 get_assembly_version(assembly, ptrW);
3440 strcatW(ptrW, exclW);
3441 strcatW(ptrW, entity->u.class.name);
3442 }
3443 else
3444 {
3445 memcpy(ptrW, entity->u.class.name, index->name_len);
3446 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3447 }
3448
3449 name_offset += sizeof(*data);
3450 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3451
3452 index++;
3453 }
3454 }
3455 }
3456 }
3457
3458 *section = header;
3459
3460 return STATUS_SUCCESS;
3461 }
3462
3463 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3464 PACTCTX_SECTION_KEYED_DATA data)
3465 {
3466 struct string_index *iter, *index = NULL;
3467 struct wndclass_redirect_data *class;
3468 ULONG hash;
3469 int i;
3470
3471 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3472
3473 if (!actctx->wndclass_section)
3474 {
3475 struct strsection_header *section;
3476
3477 NTSTATUS status = build_wndclass_section(actctx, &section);
3478 if (status) return status;
3479
3480 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3481 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3482 }
3483
3484 hash = 0;
3485 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3486 iter = get_wndclass_first_index(actctx);
3487
3488 for (i = 0; i < actctx->wndclass_section->count; i++)
3489 {
3490 if (iter->hash == hash)
3491 {
3492 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3493
3494 if (!strcmpiW(nameW, name->Buffer))
3495 {
3496 index = iter;
3497 break;
3498 }
3499 else
3500 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
3501 }
3502 iter++;
3503 }
3504
3505 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3506
3507 if (data)
3508 {
3509 class = get_wndclass_data(actctx, index);
3510
3511 data->ulDataFormatVersion = 1;
3512 data->lpData = class;
3513 /* full length includes string length with nulls */
3514 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3515 data->lpSectionGlobalData = NULL;
3516 data->ulSectionGlobalDataLength = 0;
3517 data->lpSectionBase = actctx->wndclass_section;
3518 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
3519 data->hActCtx = NULL;
3520
3521 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3522 data->ulAssemblyRosterIndex = index->rosterindex;
3523 }
3524
3525 return STATUS_SUCCESS;
3526 }
3527
3528 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3529 {
3530 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3531 struct guidsection_header *header;
3532 ULONG module_offset, data_offset;
3533 struct tlibredirect_data *data;
3534 struct guid_index *index;
3535
3536 /* compute section length */
3537 for (i = 0; i < actctx->num_assemblies; i++)
3538 {
3539 struct assembly *assembly = &actctx->assemblies[i];
3540 for (j = 0; j < assembly->num_dlls; j++)
3541 {
3542 struct dll_redirect *dll = &assembly->dlls[j];
3543 for (k = 0; k < dll->entities.num; k++)
3544 {
3545 struct entity *entity = &dll->entities.base[k];
3546 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3547 {
3548 /* each entry needs index, data and string data for module name and help string */
3549 total_len += sizeof(*index);
3550 total_len += sizeof(*data);
3551 /* help string is stored separately */
3552 if (*entity->u.typelib.helpdir)
3553 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3554
3555 /* module names are packed one after another */
3556 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3557
3558 tlib_count++;
3559 }
3560 }
3561 }
3562 }
3563
3564 total_len += aligned_string_len(names_len);
3565 total_len += sizeof(*header);
3566
3567 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3568 if (!header) return STATUS_NO_MEMORY;
3569
3570 memset(header, 0, sizeof(*header));
3571 header->magic = GUIDSECTION_MAGIC;
3572 header->size = sizeof(*header);
3573 header->count = tlib_count;
3574 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3575 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3576 module_offset = sizeof(*header);
3577 data_offset = header->index_offset + tlib_count*sizeof(*index);
3578
3579 for (i = 0; i < actctx->num_assemblies; i++)
3580 {
3581 struct assembly *assembly = &actctx->assemblies[i];
3582 for (j = 0; j < assembly->num_dlls; j++)
3583 {
3584 struct dll_redirect *dll = &assembly->dlls[j];
3585 for (k = 0; k < dll->entities.num; k++)
3586 {
3587 struct entity *entity = &dll->entities.base[k];
3588 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3589 {
3590 ULONG module_len, help_len;
3591 UNICODE_STRING str;
3592 WCHAR *ptrW;
3593
3594 if (*entity->u.typelib.helpdir)
3595 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3596 else
3597 help_len = 0;
3598
3599 module_len = strlenW(dll->name)*sizeof(WCHAR);
3600
3601 /* setup new index entry */
3602 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3603 RtlGUIDFromString(&str, &index->guid);
3604 index->data_offset = data_offset;
3605 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3606 index->rosterindex = i + 1;
3607
3608 /* setup data */
3609 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3610 data->size = sizeof(*data);
3611 data->res = 0;
3612 data->name_len = module_len;
3613 data->name_offset = module_offset;
3614 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3615 data->langid = 0;
3616 data->flags = entity->u.typelib.flags;
3617 data->help_len = help_len;
3618 data->help_offset = sizeof(*data);
3619 data->major_version = entity->u.typelib.major;
3620 data->minor_version = entity->u.typelib.minor;
3621
3622 /* module name */
3623 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3624 memcpy(ptrW, dll->name, data->name_len);
3625 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3626
3627 /* help string */
3628 if (data->help_len)
3629 {
3630 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3631 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3632 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3633 }
3634
3635 data_offset += sizeof(*data);
3636 if (help_len)
3637 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3638
3639 module_offset += module_len + sizeof(WCHAR);
3640
3641 index++;
3642 }
3643 }
3644 }
3645 }
3646
3647 *section = header;
3648
3649 return STATUS_SUCCESS;
3650 }
3651
3652 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3653 {
3654 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3655 }
3656
3657 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3658 {
3659 struct guid_index *index = NULL;
3660 struct tlibredirect_data *tlib;
3661
3662 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3663
3664 if (!actctx->tlib_section)
3665 {
3666 struct guidsection_header *section;
3667
3668 NTSTATUS status = build_tlib_section(actctx, &section);
3669 if (status) return status;
3670
3671 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3672 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
3673 }
3674
3675 index = find_guid_index(actctx->tlib_section, guid);
3676 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3677
3678 tlib = get_tlib_data(actctx, index);
3679
3680 data->ulDataFormatVersion = 1;
3681 data->lpData = tlib;
3682 /* full length includes string length with nulls */
3683 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3684 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3685 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3686 data->lpSectionBase = actctx->tlib_section;
3687 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
3688 data->hActCtx = NULL;
3689
3690 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3691 data->ulAssemblyRosterIndex = index->rosterindex;
3692
3693 return STATUS_SUCCESS;
3694 }
3695
3696 static void generate_uuid(ULONG *seed, GUID *guid)
3697 {
3698 ULONG *ptr = (ULONG*)guid;
3699 int i;
3700
3701 /* GUID is 16 bytes long */
3702 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3703 *ptr = RtlUniform(seed);
3704
3705 guid->Data3 &= 0x0fff;
3706 guid->Data3 |= (4 << 12);
3707 guid->Data4[0] &= 0x3f;
3708 guid->Data4[0] |= 0x80;
3709 }
3710
3711 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3712 unsigned int *count, unsigned int *len, unsigned int *module_len)
3713 {
3714 unsigned int i;
3715
3716 for (i = 0; i < entities->num; i++)
3717 {
3718 struct entity *entity = &entities->base[i];
3719 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3720 {
3721 /* each entry needs two index entries, extra one goes for alias GUID */
3722 *len += 2*sizeof(struct guid_index);
3723 /* To save some memory we don't allocated two data structures,
3724 instead alias index and normal index point to the same data structure. */
3725 *len += sizeof(struct comclassredirect_data);
3726
3727 /* for clrClass store some more */
3728 if (entity->u.comclass.name)
3729 {
3730 unsigned int str_len;
3731
3732 /* all string data is stored together in aligned block */
3733 str_len = strlenW(entity->u.comclass.name)+1;
3734 if (entity->u.comclass.progid)
3735 str_len += strlenW(entity->u.comclass.progid)+1;
3736 if (entity->u.comclass.version)
3737 str_len += strlenW(entity->u.comclass.version)+1;
3738
3739 *len += sizeof(struct clrclass_data);
3740 *len += aligned_string_len(str_len*sizeof(WCHAR));
3741
3742 /* module name is forced to mscoree.dll, and stored two times with different case */
3743 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3744 }
3745 else
3746 {
3747 /* progid string is stored separately */
3748 if (entity->u.comclass.progid)
3749 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3750
3751 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3752 }
3753
3754 *count += 1;
3755 }
3756 }
3757 }
3758
3759 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3760 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3761 ULONG *seed, ULONG rosterindex)
3762 {
3763 unsigned int i;
3764
3765 for (i = 0; i < entities->num; i++)
3766 {
3767 struct entity *entity = &entities->base[i];
3768 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3769 {
3770 ULONG module_len, progid_len, str_len = 0;
3771 struct comclassredirect_data *data;
3772 struct guid_index *alias_index;
3773 struct clrclass_data *clrdata;
3774 UNICODE_STRING str;
3775 WCHAR *ptrW;
3776
3777 if (entity->u.comclass.progid)
3778 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3779 else
3780 progid_len = 0;
3781
3782 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3783
3784 /* setup new index entry */
3785 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3786 RtlGUIDFromString(&str, &(*index)->guid);
3787
3788 (*index)->data_offset = *data_offset;
3789 (*index)->data_len = sizeof(*data); /* additional length added later */
3790 (*index)->rosterindex = rosterindex;
3791
3792 /* Setup new index entry for alias guid. Alias index records are placed after
3793 normal records, so normal guids are hit first on search. Note that class count
3794 is doubled. */
3795 alias_index = (*index) + section->count/2;
3796 generate_uuid(seed, &alias_index->guid);
3797 alias_index->data_offset = (*index)->data_offset;
3798 alias_index->data_len = 0;
3799 alias_index->rosterindex = (*index)->rosterindex;
3800
3801 /* setup data */
3802 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3803 data->size = sizeof(*data);
3804 data->res = 0;
3805 data->res1[0] = 0;
3806 data->res1[1] = 0;
3807 data->model = entity->u.comclass.model;
3808 data->clsid = (*index)->guid;
3809 data->alias = alias_index->guid;
3810 data->clsid2 = data->clsid;
3811 if (entity->u.comclass.tlbid)
3812 {
3813 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3814 RtlGUIDFromString(&str, &data->tlbid);
3815 }
3816 else
3817 memset(&data->tlbid, 0, sizeof(data->tlbid));
3818 data->name_len = module_len;
3819 data->name_offset = *module_offset;
3820 data->progid_len = progid_len;
3821 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3822 data->clrdata_len = 0; /* will be set later */
3823 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3824 data->miscstatus = entity->u.comclass.miscstatus;
3825 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3826 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3827 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3828 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3829
3830 /* mask describes which misc* data is available */
3831 data->miscmask = 0;
3832 if (data->miscstatus)
3833 data->miscmask |= MiscStatus;
3834 if (data->miscstatuscontent)
3835 data->miscmask |= MiscStatusContent;
3836 if (data->miscstatusthumbnail)
3837 data->miscmask |= MiscStatusThumbnail;
3838 if (data->miscstatusicon)
3839 data->miscmask |= MiscStatusIcon;
3840 if (data->miscstatusdocprint)
3841 data->miscmask |= MiscStatusDocPrint;
3842
3843 if (data->clrdata_offset)
3844 {
3845 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3846
3847 clrdata->size = sizeof(*clrdata);
3848 clrdata->res[0] = 0;
3849 clrdata->res[1] = 2; /* FIXME: unknown field */
3850 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3851 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3852 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3853 clrdata->name_offset = clrdata->size;
3854 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3855 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3856 clrdata->res2[0] = 0;
3857 clrdata->res2[1] = 0;
3858
3859 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3860
3861 /* module name */
3862 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3863 memcpy(ptrW, mscoree2W, clrdata->module_len);
3864 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3865
3866 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3867 memcpy(ptrW, mscoreeW, data->name_len);
3868 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3869
3870 /* class name */
3871 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3872 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3873 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3874
3875 /* runtime version, optional */
3876 if (clrdata->version_len)
3877 {
3878 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3879
3880 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3881 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3882 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3883 }
3884
3885 if (data->progid_len)
3886 data->progid_offset += data->clrdata_len;
3887 (*index)->data_len += sizeof(*clrdata);
3888 }
3889 else
3890 {
3891 clrdata = NULL;
3892
3893 /* module name */
3894 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3895 memcpy(ptrW, dll->name, data->name_len);
3896 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3897 }
3898
3899 /* progid string */
3900 if (data->progid_len)
3901 {
3902 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3903 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3904 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3905 }
3906
3907 /* string block length */
3908 str_len = 0;
3909 if (clrdata)
3910 {
3911 str_len += clrdata->name_len + sizeof(WCHAR);
3912 if (clrdata->version_len)
3913 str_len += clrdata->version_len + sizeof(WCHAR);
3914 }
3915 if (progid_len)
3916 str_len += progid_len + sizeof(WCHAR);
3917
3918 (*index)->data_len += aligned_string_len(str_len);
3919 alias_index->data_len = (*index)->data_len;
3920
3921 /* move to next data record */
3922 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3923 (*module_offset) += module_len + sizeof(WCHAR);
3924
3925 if (clrdata)
3926 {
3927 (*data_offset) += sizeof(*clrdata);
3928 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3929 }
3930 (*index) += 1;
3931 }
3932 }
3933 }
3934
3935 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3936 {
3937 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3938 struct guidsection_header *header;
3939 ULONG module_offset, data_offset;
3940 struct guid_index *index;
3941 ULONG seed;
3942
3943 /* compute section length */
3944 for (i = 0; i < actctx->num_assemblies; i++)
3945 {
3946 struct assembly *assembly = &actctx->assemblies[i];
3947 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3948 for (j = 0; j < assembly->num_dlls; j++)
3949 {
3950 struct dll_redirect *dll = &assembly->dlls[j];
3951 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3952 }
3953 }
3954
3955 total_len += aligned_string_len(names_len);
3956 total_len += sizeof(*header);
3957
3958 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
3959 if (!header) return STATUS_NO_MEMORY;
3960
3961 memset(header, 0, sizeof(*header));
3962 header->magic = GUIDSECTION_MAGIC;
3963 header->size = sizeof(*header);
3964 header->count = 2*class_count;
3965 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3966 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3967 module_offset = sizeof(*header);
3968 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3969
3970 seed = NtGetTickCount();
3971 for (i = 0; i < actctx->num_assemblies; i++)
3972 {
3973 struct assembly *assembly = &actctx->assemblies[i];
3974 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3975 for (j = 0; j < assembly->num_dlls; j++)
3976 {
3977 struct dll_redirect *dll = &assembly->dlls[j];
3978 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3979 }
3980 }
3981
3982 *section = header;
3983
3984 return STATUS_SUCCESS;
3985 }
3986
3987 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3988 {
3989 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3990 }
3991
3992 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3993 {
3994 struct comclassredirect_data *comclass;
3995 struct guid_index *index = NULL;
3996
3997 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3998
3999 if (!actctx->comserver_section)
4000 {
4001 struct guidsection_header *section;
4002
4003 NTSTATUS status = build_comserver_section(actctx, &section);
4004 if (status) return status;
4005
4006 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4007 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4008 }
4009
4010 index = find_guid_index(actctx->comserver_section, guid);
4011 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4012
4013 comclass = get_comclass_data(actctx, index);
4014
4015 data->ulDataFormatVersion = 1;
4016 data->lpData = comclass;
4017 /* full length includes string length with nulls */
4018 data->ulLength = comclass->size + comclass->clrdata_len;
4019 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4020 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4021 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4022 data->lpSectionBase = actctx->comserver_section;
4023 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
4024 data->hActCtx = NULL;
4025
4026 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4027 data->ulAssemblyRosterIndex = index->rosterindex;
4028
4029 return STATUS_SUCCESS;
4030 }
4031
4032 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4033 {
4034 unsigned int i;
4035
4036 for (i = 0; i < entities->num; i++)
4037 {
4038 struct entity *entity = &entities->base[i];
4039 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4040 {
4041 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4042 if (entity->u.ifaceps.name)
4043 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4044 *count += 1;
4045 }
4046 }
4047 }
4048
4049 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4050 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4051 {
4052 unsigned int i;
4053
4054 for (i = 0; i < entities->num; i++)
4055 {
4056 struct entity *entity = &entities->base[i];
4057 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4058 {
4059 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4060 UNICODE_STRING str;
4061 ULONG name_len;
4062
4063 if (entity->u.ifaceps.name)
4064 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4065 else
4066 name_len = 0;
4067
4068 /* setup index */
4069 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4070 RtlGUIDFromString(&str, &(*index)->guid);
4071 (*index)->data_offset = *data_offset;
4072 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4073 (*index)->rosterindex = rosterindex;
4074
4075 /* setup data record */
4076 data->size = sizeof(*data);
4077 data->mask = entity->u.ifaceps.mask;
4078
4079 /* proxyStubClsid32 value is only stored for external PS,
4080 if set it's used as iid, otherwise 'iid' attribute value is used */
4081 if (entity->u.ifaceps.ps32)
4082 {
4083 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4084 RtlGUIDFromString(&str, &data->iid);
4085 }
4086 else
4087 data->iid = (*index)->guid;
4088
4089 data->nummethods = entity->u.ifaceps.nummethods;
4090
4091 if (entity->u.ifaceps.tlib)
4092 {
4093 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4094 RtlGUIDFromString(&str, &data->tlbid);
4095 }
4096 else
4097 memset(&data->tlbid, 0, sizeof(data->tlbid));
4098
4099 if (entity->u.ifaceps.base)
4100 {
4101 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4102 RtlGUIDFromString(&str, &data->base);
4103 }
4104 else
4105 memset(&data->base, 0, sizeof(data->base));
4106
4107 data->name_len = name_len;
4108 data->name_offset = data->name_len ? sizeof(*data) : 0;
4109
4110 /* name string */
4111 if (data->name_len)
4112 {
4113 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4114 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4115 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4116 }
4117
4118 /* move to next record */
4119 (*index) += 1;
4120 *data_offset += sizeof(*data);
4121 if (data->name_len)
4122 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4123 }
4124 }
4125 }
4126
4127 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4128 {
4129 unsigned int i, j, total_len = 0, count = 0;
4130 struct guidsection_header *header;
4131 struct guid_index *index;
4132 ULONG data_offset;
4133
4134 /* compute section length */
4135 for (i = 0; i < actctx->num_assemblies; i++)
4136 {
4137 struct assembly *assembly = &actctx->assemblies[i];
4138
4139 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4140 for (j = 0; j < assembly->num_dlls; j++)
4141 {
4142 struct dll_redirect *dll = &assembly->dlls[j];
4143 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4144 }
4145 }
4146
4147 total_len += sizeof(*header);
4148
4149 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4150 if (!header) return STATUS_NO_MEMORY;
4151
4152 memset(header, 0, sizeof(*header));
4153 header->magic = GUIDSECTION_MAGIC;
4154 header->size = sizeof(*header);
4155 header->count = count;
4156 header->index_offset = sizeof(*header);
4157 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4158 data_offset = header->index_offset + count*sizeof(*index);
4159
4160 for (i = 0; i < actctx->num_assemblies; i++)
4161 {
4162 struct assembly *assembly = &actctx->assemblies[i];
4163
4164 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4165 for (j = 0; j < assembly->num_dlls; j++)
4166 {
4167 struct dll_redirect *dll = &assembly->dlls[j];
4168 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4169 }
4170 }
4171
4172 *section = header;
4173
4174 return STATUS_SUCCESS;
4175 }
4176
4177 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4178 {
4179 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4180 }
4181
4182 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4183 {
4184 struct ifacepsredirect_data *iface;
4185 struct guid_index *index = NULL;
4186
4187 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4188
4189 if (!actctx->ifaceps_section)
4190 {
4191 struct guidsection_header *section;
4192
4193 NTSTATUS status = build_ifaceps_section(actctx, &section);
4194 if (status) return status;
4195
4196 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4197 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4198 }
4199
4200 index = find_guid_index(actctx->ifaceps_section, guid);
4201 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4202
4203 iface = get_ifaceps_data(actctx, index);
4204
4205 data->ulDataFormatVersion = 1;
4206 data->lpData = iface;
4207 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4208 data->lpSectionGlobalData = NULL;
4209 data->ulSectionGlobalDataLength = 0;
4210 data->lpSectionBase = actctx->ifaceps_section;
4211 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
4212 data->hActCtx = NULL;
4213
4214 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4215 data->ulAssemblyRosterIndex = index->rosterindex;
4216
4217 return STATUS_SUCCESS;
4218 }
4219
4220 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4221 {
4222 unsigned int i, j, total_len = 0, count = 0;
4223 struct guidsection_header *header;
4224 struct clrsurrogate_data *data;
4225 struct guid_index *index;
4226 ULONG data_offset;
4227
4228 /* compute section length */
4229 for (i = 0; i < actctx->num_assemblies; i++)
4230 {
4231 struct assembly *assembly = &actctx->assemblies[i];
4232 for (j = 0; j < assembly->entities.num; j++)
4233 {
4234 struct entity *entity = &assembly->entities.base[j];
4235 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4236 {
4237 ULONG len;
4238
4239 total_len += sizeof(*index) + sizeof(*data);
4240 len = strlenW(entity->u.clrsurrogate.name) + 1;
4241 if (entity->u.clrsurrogate.version)
4242 len += strlenW(entity->u.clrsurrogate.version) + 1;
4243 total_len += aligned_string_len(len*sizeof(WCHAR));
4244
4245 count++;
4246 }
4247 }
4248 }
4249
4250 total_len += sizeof(*header);
4251
4252 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4253 if (!header) return STATUS_NO_MEMORY;
4254
4255 memset(header, 0, sizeof(*header));
4256 header->magic = GUIDSECTION_MAGIC;
4257 header->size = sizeof(*header);
4258 header->count = count;
4259 header->index_offset = sizeof(*header);
4260 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4261 data_offset = header->index_offset + count*sizeof(*index);
4262
4263 for (i = 0; i < actctx->num_assemblies; i++)
4264 {
4265 struct assembly *assembly = &actctx->assemblies[i];
4266 for (j = 0; j < assembly->entities.num; j++)
4267 {
4268 struct entity *entity = &assembly->entities.base[j];
4269 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4270 {
4271 ULONG version_len, name_len;
4272 UNICODE_STRING str;
4273 WCHAR *ptrW;
4274
4275 if (entity->u.clrsurrogate.version)
4276 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4277 else
4278 version_len = 0;
4279 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4280
4281 /* setup new index entry */
4282 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4283 RtlGUIDFromString(&str, &index->guid);
4284
4285 index->data_offset = data_offset;
4286 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4287 index->rosterindex = i + 1;
4288
4289 /* setup data */
4290 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4291 data->size = sizeof(*data);
4292 data->res = 0;
4293 data->clsid = index->guid;
4294 data->version_offset = version_len ? data->size : 0;
4295 data->version_len = version_len;
4296 data->name_offset = data->size + version_len;
4297 if (version_len)
4298 data->name_offset += sizeof(WCHAR);
4299 data->name_len = name_len;
4300
4301 /* surrogate name */
4302 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4303 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4304 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4305
4306 /* runtime version */
4307 if (data->version_len)
4308 {
4309 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4310 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4311 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4312 }
4313
4314 data_offset += index->data_offset;
4315 index++;
4316 }
4317 }
4318 }
4319
4320 *section = header;
4321
4322 return STATUS_SUCCESS;
4323 }
4324
4325 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4326 {
4327 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4328 }
4329
4330 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4331 {
4332 struct clrsurrogate_data *surrogate;
4333 struct guid_index *index = NULL;
4334
4335 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4336
4337 if (!actctx->clrsurrogate_section)
4338 {
4339 struct guidsection_header *section;
4340
4341 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4342 if (status) return status;
4343
4344 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4345 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4346 }
4347
4348 index = find_guid_index(actctx->clrsurrogate_section, guid);
4349 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4350
4351 surrogate = get_surrogate_data(actctx, index);
4352
4353 data->ulDataFormatVersion = 1;
4354 data->lpData = surrogate;
4355 /* full length includes string length with nulls */
4356 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4357 if (surrogate->version_len)
4358 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4359
4360 data->lpSectionGlobalData = NULL;
4361 data->ulSectionGlobalDataLength = 0;
4362 data->lpSectionBase = actctx->clrsurrogate_section;
4363 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
4364 data->hActCtx = NULL;
4365
4366 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4367 data->ulAssemblyRosterIndex = index->rosterindex;
4368
4369 return STATUS_SUCCESS;
4370 }
4371
4372 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4373 {
4374 unsigned int i, j, single_len;
4375
4376 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4377 for (i = 0; i < entities->num; i++)
4378 {
4379 struct entity *entity = &entities->base[i];
4380 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4381 {
4382 if (entity->u.comclass.progid)
4383 {
4384 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4385 *count += 1;
4386 }
4387
4388 for (j = 0; j < entity->u.comclass.progids.num; j++)
4389 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4390
4391 *total_len += single_len*entity->u.comclass.progids.num;
4392 *count += entity->u.comclass.progids.num;
4393 }
4394 }
4395 }
4396
4397 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4398 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4399 {
4400 struct progidredirect_data *data;
4401 UNICODE_STRING str;
4402 GUID *guid_ptr;
4403 WCHAR *ptrW;
4404
4405 /* setup new index entry */
4406
4407 /* hash progid name */
4408 RtlInitUnicodeString(&str, progid);
4409 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4410
4411 (*index)->name_offset = *data_offset;
4412 (*index)->name_len = str.Length;
4413 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4414 (*index)->data_len = sizeof(*data);
4415 (*index)->rosterindex = rosterindex;
4416
4417 *data_offset += aligned_string_len(str.MaximumLength);
4418
4419 /* setup data structure */
4420 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4421 data->size = sizeof(*data);
4422 data->reserved = 0;
4423 data->clsid_offset = *global_offset;
4424
4425 /* write progid string */
4426 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4427 memcpy(ptrW, progid, (*index)->name_len);
4428 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4429
4430 /* write guid to global area */
4431 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4432 *guid_ptr = *alias;
4433
4434 /* to next entry */
4435 *global_offset += sizeof(GUID);
4436 *data_offset += data->size;
4437 (*index) += 1;
4438 }
4439
4440 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4441 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4442 {
4443 unsigned int i, j;
4444
4445 for (i = 0; i < entities->num; i++)
4446 {
4447 struct entity *entity = &entities->base[i];
4448 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4449 {
4450 const struct progids *progids = &entity->u.comclass.progids;
4451 struct comclassredirect_data *comclass;
4452 struct guid_index *guid_index;
4453 UNICODE_STRING str;
4454 GUID clsid;
4455
4456 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4457 RtlGUIDFromString(&str, &clsid);
4458
4459 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4460 comclass = get_comclass_data(actctx, guid_index);
4461
4462 if (entity->u.comclass.progid)
4463 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4464 index, data_offset, global_offset, rosterindex);
4465
4466 for (j = 0; j < progids->num; j++)
4467 write_progid_record(section, progids->progids[j], &comclass->alias,
4468 index, data_offset, global_offset, rosterindex);
4469 }
4470 }
4471 }
4472
4473 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4474 {
4475 unsigned int i, j, total_len = 0, count = 0;
4476 struct strsection_header *header;
4477 ULONG data_offset, global_offset;
4478 struct string_index *index;
4479
4480 /* compute section length */
4481 for (i = 0; i < actctx->num_assemblies; i++)
4482 {
4483 struct assembly *assembly = &actctx->assemblies[i];
4484
4485 get_progid_datalen(&assembly->entities, &count, &total_len);
4486 for (j = 0; j < assembly->num_dlls; j++)
4487 {
4488 struct dll_redirect *dll = &assembly->dlls[j];
4489 get_progid_datalen(&dll->entities, &count, &total_len);
4490 }
4491 }
4492
4493 total_len += sizeof(*header);
4494
4495 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
4496 if (!header) return STATUS_NO_MEMORY;
4497
4498 memset(header, 0, sizeof(*header));
4499 header->magic = STRSECTION_MAGIC;
4500 header->size = sizeof(*header);
4501 header->count = count;
4502 header->global_offset = header->size;
4503 header->global_len = count*sizeof(GUID);
4504 header->index_offset = header->size + header->global_len;
4505
4506 index = (struct string_index*)((BYTE*)header + header->index_offset);
4507 data_offset = header->index_offset + count*sizeof(*index);
4508 global_offset = header->global_offset;
4509
4510 for (i = 0; i < actctx->num_assemblies; i++)
4511 {
4512 struct assembly *assembly = &actctx->assemblies[i];
4513
4514 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4515 for (j = 0; j < assembly->num_dlls; j++)
4516 {
4517 struct dll_redirect *dll = &assembly->dlls[j];
4518 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4519 }
4520 }
4521
4522 *section = header;
4523
4524 return STATUS_SUCCESS;
4525 }
4526
4527 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4528 {
4529 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4530 }
4531
4532 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4533 PACTCTX_SECTION_KEYED_DATA data)
4534 {
4535 struct progidredirect_data *progid;
4536 struct string_index *index;
4537
4538 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4539
4540 if (!actctx->comserver_section)
4541 {
4542 struct guidsection_header *section;
4543
4544 NTSTATUS status = build_comserver_section(actctx, &section);
4545 if (status) return status;
4546
4547 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4548 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4549 }
4550
4551 if (!actctx->progid_section)
4552 {
4553 struct strsection_header *section;
4554
4555 NTSTATUS status = build_progid_section(actctx, &section);
4556 if (status) return status;
4557
4558 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4559 RtlFreeHeap(RtlGetProcessHeap(), 0, section);
4560 }
4561
4562 index = find_string_index(actctx->progid_section, name);
4563 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4564
4565 if (data)
4566 {
4567 progid = get_progid_data(actctx, index);
4568
4569 data->ulDataFormatVersion = 1;
4570 data->lpData = progid;
4571 data->ulLength = progid->size;
4572 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4573 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4574 data->lpSectionBase = actctx->progid_section;
4575 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
4576 data->hActCtx = NULL;
4577
4578 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4579 data->ulAssemblyRosterIndex = index->rosterindex;
4580 }
4581
4582 return STATUS_SUCCESS;
4583 }
4584
4585 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4586 const UNICODE_STRING *section_name,
4587 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4588 {
4589 NTSTATUS status;
4590
4591 switch (section_kind)
4592 {
4593 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION:
4594 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4595 return STATUS_SXS_KEY_NOT_FOUND;
4596 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4597 status = find_dll_redirection(actctx, section_name, data);
4598 break;
4599 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4600 status = find_window_class(actctx, section_name, data);
4601 break;
4602 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4603 status = find_progid_redirection(actctx, section_name, data);
4604 break;
4605 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4606 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
4607 return STATUS_SXS_SECTION_NOT_FOUND;
4608 default:
4609 DPRINT1("Unknown section_kind %x\n", section_kind);
4610 return STATUS_SXS_SECTION_NOT_FOUND;
4611 }
4612
4613 if (status != STATUS_SUCCESS) return status;
4614
4615 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4616 {
4617 actctx_addref(actctx);
4618 data->hActCtx = actctx;
4619 }
4620 return STATUS_SUCCESS;
4621 }
4622
4623 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4624 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4625 {
4626 NTSTATUS status;
4627
4628 switch (section_kind)
4629 {
4630 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4631 status = find_tlib_redirection(actctx, guid, data);
4632 break;
4633 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4634 status = find_comserver_redirection(actctx, guid, data);
4635 break;
4636 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4637 status = find_cominterface_redirection(actctx, guid, data);
4638 break;
4639 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4640 status = find_clr_surrogate(actctx, guid, data);
4641 break;
4642 default:
4643 DPRINT("Unknown section_kind %x\n", section_kind);
4644 return STATUS_SXS_SECTION_NOT_FOUND;
4645 }
4646
4647 if (status != STATUS_SUCCESS) return status;
4648
4649 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4650 {
4651 actctx_addref(actctx);
4652 data->hActCtx = actctx;
4653 }
4654 return STATUS_SUCCESS;
4655 }
4656
4657 /* initialize the activation context for the current process */
4658 void actctx_init(void)
4659 {
4660 ACTCTXW ctx;
4661 HANDLE handle;
4662 WCHAR buffer[1024];
4663 NTSTATUS Status;
4664
4665 ctx.cbSize = sizeof(ctx);
4666 ctx.lpSource = NULL;
4667 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4668 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
4669 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4670
4671 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle)))
4672 {
4673 process_actctx = check_actctx(handle);
4674 }
4675
4676 ctx.dwFlags = 0;
4677 ctx.hModule = NULL;
4678 ctx.lpResourceName = NULL;
4679 ctx.lpSource = buffer;
4680 RtlStringCchCopyW(buffer, 1024, SharedUserData->NtSystemRoot);
4681 RtlStringCchCatW(buffer, 1024, L"\\winsxs\\manifests\\systemcompatible.manifest");
4682 Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle);
4683 if (NT_SUCCESS(Status))
4684 {
4685 implicit_actctx = check_actctx(handle);
4686 }
4687 else
4688 {
4689 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status);
4690 }
4691 }
4692
4693 /* FUNCTIONS ***************************************************************/
4694
4695 /***********************************************************************
4696 * RtlCreateActivationContext (NTDLL.@)
4697 *
4698 * Create an activation context.
4699 */
4700 NTSTATUS
4701 NTAPI
4702 RtlCreateActivationContext(IN ULONG Flags,
4703 IN PACTIVATION_CONTEXT_DATA ActivationContextData,
4704 IN ULONG ExtraBytes,
4705 IN PVOID NotificationRoutine,
4706 IN PVOID NotificationContext,
4707 OUT PACTIVATION_CONTEXT *ActCtx)
4708 {
4709 const ACTCTXW *pActCtx = (PVOID)ActivationContextData;
4710 const WCHAR *directory = NULL;
4711 PACTIVATION_CONTEXT_WRAPPED ActualActCtx;
4712 ACTIVATION_CONTEXT *actctx;
4713 UNICODE_STRING nameW;
4714 ULONG lang = 0;
4715 NTSTATUS status = STATUS_NO_MEMORY;
4716 HANDLE file = 0;
4717 struct actctx_loader acl;
4718
4719 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule);
4720
4721 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4722 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4723 return STATUS_INVALID_PARAMETER;
4724
4725
4726 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx))))
4727 return STATUS_NO_MEMORY;
4728
4729 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER;
4730
4731 actctx = &ActualActCtx->ActivationContext;
4732 actctx->RefCount = 1;
4733 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4734 actctx->config.info = NULL;
4735 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4736 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4737 {
4738 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4739 }
4740 else
4741 {
4742 UNICODE_STRING dir;
4743 WCHAR *p;
4744 HMODULE module;
4745
4746 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4747 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
4748
4749 status = get_module_filename( module, &dir, 0 );
4750 if (!NT_SUCCESS(status)) goto error;
4751 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4752 actctx->appdir.info = dir.Buffer;
4753 }
4754
4755 nameW.Buffer = NULL;
4756
4757 /* open file only if it's going to be used */
4758 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4759 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4760 {
4761 WCHAR *source = NULL;
4762 BOOLEAN ret;
4763
4764 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4765 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative)
4766 {
4767 DWORD dir_len, source_len;
4768
4769 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4770 source_len = strlenW(pActCtx->lpSource);
4771 if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4772 {
4773 status = STATUS_NO_MEMORY;
4774 goto error;
4775 }
4776
4777 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4778 source[dir_len] = '\\';
4779 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4780 }
4781
4782 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4783 RtlFreeHeap( RtlGetProcessHeap(), 0, source );
4784 if (!ret)
4785 {
4786 status = STATUS_NO_SUCH_FILE;
4787 goto error;
4788 }
4789 status = open_nt_file( &file, &nameW );
4790 if (!NT_SUCCESS(status))
4791 {
4792 RtlFreeUnicodeString( &nameW );
4793 goto error;
4794 }
4795 }
4796
4797 acl.actctx = actctx;
4798 acl.dependencies = NULL;
4799 acl.num_dependencies = 0;
4800 acl.allocated_dependencies = 0;
4801
4802 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4803 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4804
4805 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4806 {
4807 /* if we have a resource it's a PE file */
4808 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4809 {
4810 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4811 pActCtx->lpResourceName, lang );
4812 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4813 /* FIXME: what to do if pActCtx->lpSource is set */
4814 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4815 pActCtx->hModule, pActCtx->lpResourceName );
4816 }
4817 else if (pActCtx->lpSource)
4818 {
4819 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4820 file, pActCtx->lpResourceName, lang );
4821 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4822 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4823 NULL, pActCtx->lpResourceName );
4824 }
4825 else status = STATUS_INVALID_PARAMETER;
4826 }
4827 else
4828 {
4829 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4830 }
4831
4832 if (file) NtClose( file );
4833 RtlFreeUnicodeString( &nameW );
4834
4835 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl);
4836 free_depend_manifests( &acl );
4837
4838 if (NT_SUCCESS(status))
4839 *ActCtx = actctx;
4840 else actctx_release( actctx );
4841 return status;
4842
4843 error:
4844 if (file) NtClose( file );
4845 actctx_release( actctx );
4846 return status;
4847 }
4848
4849 #if 0
4850 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4851
4852 VOID
4853 NTAPI
4854 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle)
4855 {
4856 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle;
4857 LONG OldRefCount, NewRefCount;
4858
4859 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
4860 {
4861 RtlpValidateActCtx(ActCtx);
4862
4863 while (TRUE)
4864 {
4865 OldRefCount = ActCtx->RefCount;
4866 ASSERT(OldRefCount > 0);
4867
4868 if (OldRefCount == LONG_MAX) break;
4869
4870 NewRefCount = OldRefCount + 1;
4871 if (InterlockedCompareExchange(&ActCtx->RefCount,
4872 NewRefCount,
4873 OldRefCount) == OldRefCount)
4874 {
4875 break;
4876 }
4877 }
4878
4879 NewRefCount = LONG_MAX;
4880 ASSERT(NewRefCount > 0);
4881 }
4882 }
4883
4884 VOID
4885 NTAPI
4886 RtlReleaseActivationContext( HANDLE handle )
4887 {
4888 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle;
4889
4890 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
4891 {
4892 RtlpValidateActCtx(ActCtx);
4893
4894 actctx_release(ActCtx);
4895 }
4896 }
4897 #else
4898
4899 /***********************************************************************
4900 * RtlAddRefActivationContext (NTDLL.@)
4901 */
4902 VOID NTAPI RtlAddRefActivationContext( HANDLE handle )
4903 {
4904 ACTIVATION_CONTEXT *actctx;
4905
4906 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4907 }
4908
4909
4910 /******************************************************************
4911 * RtlReleaseActivationContext (NTDLL.@)
4912 */
4913 VOID NTAPI RtlReleaseActivationContext( HANDLE handle )
4914 {
4915 ACTIVATION_CONTEXT *actctx;
4916
4917 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4918 }
4919
4920 #endif
4921
4922 /******************************************************************
4923 * RtlZombifyActivationContext (NTDLL.@)
4924 *
4925 */
4926 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context)
4927 {
4928 UNIMPLEMENTED;
4929
4930 if (Context == ACTCTX_FAKE_HANDLE)
4931 return STATUS_SUCCESS;
4932
4933 return STATUS_NOT_IMPLEMENTED;
4934 }
4935
4936 NTSTATUS
4937 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
4938 {
4939 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4940
4941 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
4942 return STATUS_NO_MEMORY;
4943
4944 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
4945 frame->ActivationContext = handle;
4946 frame->Flags = 0;
4947
4948 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4949 tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame,
4950 frame, handle);
4951
4952 tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
4953 RtlAddRefActivationContext( handle );
4954
4955 *cookie = (ULONG_PTR)frame;
4956 DPRINT( "%p cookie=%lx\n", handle, *cookie );
4957 return STATUS_SUCCESS;
4958 }
4959
4960 /******************************************************************
4961 * RtlActivateActivationContext (NTDLL.@)
4962 */
4963 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
4964 {
4965 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
4966 }
4967
4968 /***********************************************************************
4969 * RtlDeactivateActivationContext (NTDLL.@)
4970 */
4971 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4972 {
4973 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4974
4975 DPRINT( "%x cookie=%lx\n", flags, cookie );
4976
4977 /* find the right frame */
4978 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
4979 for (frame = top; frame; frame = frame->Previous)
4980 if ((ULONG_PTR)frame == cookie) break;
4981
4982 if (!frame)
4983 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4984
4985 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION))
4986 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4987
4988 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4989 NtCurrentTeb()->ActivationContextStackPointer,
4990 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame,
4991 frame->Previous);
4992
4993 /* pop everything up to and including frame */
4994 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
4995
4996 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
4997 {
4998 frame = top->Previous;
4999 RtlReleaseActivationContext( top->ActivationContext );
5000 RtlFreeHeap( RtlGetProcessHeap(), 0, top );
5001 top = frame;
5002 }
5003
5004 return STATUS_SUCCESS;
5005 }
5006
5007 VOID
5008 NTAPI
5009 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
5010 {
5011 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
5012
5013 /* Nothing to do if there is no stack */
5014 if (!Stack) return;
5015
5016 /* Get the current active frame */
5017 ActiveFrame = Stack->ActiveFrame;
5018
5019 /* Go through them in backwards order and release */
5020 while (ActiveFrame)
5021 {
5022 PrevFrame = ActiveFrame->Previous;
5023 RtlReleaseActivationContext(ActiveFrame->ActivationContext);
5024 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
5025 ActiveFrame = PrevFrame;
5026 }
5027
5028 /* Zero out the active frame */
5029 Stack->ActiveFrame = NULL;
5030
5031 /* TODO: Empty the Frame List Cache */
5032 ASSERT(IsListEmpty(&Stack->FrameListCache));
5033
5034 /* Free activation stack memory */
5035 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
5036 }
5037
5038 /******************************************************************
5039 * RtlFreeThreadActivationContextStack (NTDLL.@)
5040 */
5041 VOID NTAPI RtlFreeThreadActivationContextStack(VOID)
5042 {
5043 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
5044 NtCurrentTeb()->ActivationContextStackPointer = NULL;
5045 }
5046
5047
5048 /******************************************************************
5049 * RtlGetActiveActivationContext (NTDLL.@)
5050 */
5051 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle )
5052 {
5053 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5054 {
5055 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
5056 RtlAddRefActivationContext( *handle );
5057 }
5058 else
5059 *handle = 0;
5060
5061 return STATUS_SUCCESS;
5062 }
5063
5064
5065 /******************************************************************
5066 * RtlIsActivationContextActive (NTDLL.@)
5067 */
5068 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle )
5069 {
5070 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5071
5072 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
5073 if (frame->ActivationContext == handle) return TRUE;
5074 return FALSE;
5075 }
5076
5077
5078 /***********************************************************************
5079 * RtlQueryInformationActivationContext (NTDLL.@)
5080 *
5081 * Get information about an activation context.
5082 * FIXME: function signature/prototype may be wrong
5083 */
5084 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5085 ULONG class, PVOID buffer,
5086 SIZE_T bufsize, SIZE_T *retlen )
5087 {
5088 ACTIVATION_CONTEXT *actctx;
5089 NTSTATUS status;
5090
5091 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle,
5092 subinst, class, buffer, bufsize, retlen);
5093
5094 if (retlen) *retlen = 0;
5095 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5096
5097 switch (class)
5098 {
5099 case ActivationContextBasicInformation:
5100 {
5101 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5102
5103 if (retlen) *retlen = sizeof(*info);
5104 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5105
5106 info->hActCtx = handle;
5107 info->dwFlags = 0; /* FIXME */
5108 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle);
5109 }
5110 break;
5111
5112 case ActivationContextDetailedInformation:
5113 {
5114 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5115 struct assembly *assembly = NULL;
5116 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5117 LPWSTR ptr;
5118
5119 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5120
5121 if (actctx->num_assemblies) assembly = actctx->assemblies;
5122
5123 if (assembly && assembly->manifest.info)
5124 manifest_len = strlenW(assembly->manifest.info) + 1;
5125 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5126 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5127 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5128
5129 if (retlen) *retlen = len;
5130 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5131
5132 acdi->dwFlags = 0;
5133 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5134 acdi->ulAssemblyCount = actctx->num_assemblies;
5135 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5136 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
5137 acdi->ulRootConfigurationPathType = actctx->config.type;
5138 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
5139 acdi->ulAppDirPathType = actctx->appdir.type;
5140 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
5141 ptr = (LPWSTR)(acdi + 1);
5142 if (manifest_len)
5143 {
5144 acdi->lpRootManifestPath = ptr;
5145 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5146 ptr += manifest_len;
5147 }
5148 else acdi->lpRootManifestPath = NULL;
5149 if (config_len)
5150 {
5151 acdi->lpRootConfigurationPath = ptr;
5152 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5153 ptr += config_len;
5154 }
5155 else acdi->lpRootConfigurationPath = NULL;
5156 if (appdir_len)
5157 {
5158 acdi->lpAppDirPath = ptr;
5159 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5160 }
5161 else acdi->lpAppDirPath = NULL;
5162 }
5163 break;
5164
5165 case AssemblyDetailedInformationInActivationContext:
5166 {
5167 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5168 struct assembly *assembly;
5169 WCHAR *assembly_id;
5170 DWORD index;
5171 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5172 LPWSTR ptr;
5173
5174 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5175 if (!subinst) return STATUS_INVALID_PARAMETER;
5176
5177 index = *(DWORD*)subinst;
5178 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5179
5180 assembly = &actctx->assemblies[index - 1];
5181
5182 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5183 id_len = strlenW(assembly_id) + 1;
5184 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5185
5186 if (assembly->manifest.info &&
5187 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5188 path_len = strlenW(assembly->manifest.info) + 1;
5189
5190 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5191
5192 if (retlen) *retlen = len;
5193 if (!buffer || bufsize < len)
5194 {
5195 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5196 return STATUS_BUFFER_TOO_SMALL;
5197 }
5198
5199 afdi->ulFlags = 0; /* FIXME */
5200 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
5201 afdi->ulManifestPathType = assembly->manifest.type;
5202 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
5203 /* FIXME afdi->liManifestLastWriteTime = 0; */
5204 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5205 afdi->ulPolicyPathLength = 0;
5206 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5207 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5208 afdi->ulManifestVersionMajor = 1;
5209 afdi->ulManifestVersionMinor = 0;
5210 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5211 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5212 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
5213 ptr = (LPWSTR)(afdi + 1);
5214 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5215 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5216 ptr += id_len;
5217 if (path_len)
5218 {
5219 afdi->lpAssemblyManifestPath = ptr;
5220 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5221 ptr += path_len;
5222 } else afdi->lpAssemblyManifestPath = NULL;
5223 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5224 if (ad_len)
5225 {
5226 afdi->lpAssemblyDirectoryName = ptr;
5227 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5228 }
5229 else afdi->lpAssemblyDirectoryName = NULL;
5230 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
5231 }
5232 break;
5233
5234 case FileInformationInAssemblyOfAssemblyInActivationContext:
5235 {
5236 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5237 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5238 struct assembly *assembly;
5239 struct dll_redirect *dll;
5240 SIZE_T len, dll_len = 0;
5241 LPWSTR ptr;
5242
5243 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5244 if (!acqi) return STATUS_INVALID_PARAMETER;
5245
5246 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5247 return STATUS_INVALID_PARAMETER;
5248 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5249
5250 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5251 return STATUS_INVALID_PARAMETER;
5252 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5253
5254 if (dll->name) dll_len = strlenW(dll->name) + 1;
5255 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5256
5257 if (!buffer || bufsize < len)
5258 {
5259 if (retlen) *retlen = len;
5260 return STATUS_BUFFER_TOO_SMALL;
5261 }
5262 if (retlen) *retlen = 0; /* yes that's what native does !! */
5263 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5264 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
5265 afdi->ulPathLength = 0; /* FIXME */
5266 ptr = (LPWSTR)(afdi + 1);
5267 if (dll_len)
5268 {
5269 afdi->lpFileName = ptr;
5270 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5271 } else afdi->lpFileName = NULL;
5272 afdi->lpFilePath = NULL; /* FIXME */
5273 }
5274 break;
5275
5276 default:
5277 DPRINT( "class %u not implemented\n", class );
5278 return STATUS_NOT_IMPLEMENTED;
5279 }
5280 return STATUS_SUCCESS;
5281 }
5282
5283 NTSTATUS
5284 NTAPI
5285 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
5286 PVOID pvBuffer,
5287 SIZE_T cbBuffer OPTIONAL,
5288 SIZE_T *pcbWrittenOrRequired OPTIONAL)
5289 {
5290 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT,
5291 NULL,
5292 NULL,
5293 ulInfoClass,
5294 pvBuffer,
5295 cbBuffer,
5296 pcbWrittenOrRequired);
5297 }
5298
5299 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5300 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5301 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5302
5303 NTSTATUS
5304 NTAPI
5305 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
5306 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
5307 {
5308 /* Check general parameter combinations */
5309 if (!section_name || !section_name->Buffer ||
5310 (flags & ~FIND_ACTCTX_VALID_MASK) ||
5311 ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
5312 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
5313 {
5314 DPRINT1("invalid parameter\n");
5315 return STATUS_INVALID_PARAMETER;
5316 }
5317
5318 /* TODO */
5319 if (flags & FIND_ACTCTX_RETURN_FLAGS ||
5320 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5321 {
5322 DPRINT1("unknown flags %08x\n", flags);
5323 return STATUS_INVALID_PARAMETER;
5324 }
5325
5326 return STATUS_SUCCESS;
5327 }
5328
5329 /***********************************************************************
5330 * RtlFindActivationContextSectionString (NTDLL.@)
5331 *
5332 * Find information about a string in an activation context.
5333 * FIXME: function signature/prototype may be wrong
5334 */
5335 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5336 const UNICODE_STRING *section_name, PVOID ptr )
5337 {
5338 PACTCTX_SECTION_KEYED_DATA data = ptr;
5339 NTSTATUS status;
5340
5341 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr);
5342 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
5343 if (!NT_SUCCESS(status))
5344 {
5345 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status);
5346 return status;
5347 }
5348
5349 status = STATUS_SXS_KEY_NOT_FOUND;
5350
5351 /* if there is no data, but params are valid,
5352 we return that sxs key is not found to be at least somehow compatible */
5353 if (!data)
5354 {
5355 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status);
5356 return status;
5357 }
5358
5359 ASSERT(NtCurrentTeb());
5360 ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
5361
5362 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame);
5363 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5364 {
5365 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5366 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5367 }
5368
5369 DPRINT("status %x\n", status);
5370 if (status != STATUS_SUCCESS)
5371 status = find_string( process_actctx, section_kind, section_name, flags, data );
5372
5373 if (status != STATUS_SUCCESS)
5374 status = find_string( implicit_actctx, section_kind, section_name, flags, data );
5375
5376 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status);
5377 return status;
5378 }
5379
5380 /***********************************************************************
5381 * RtlFindActivationContextSectionGuid (NTDLL.@)
5382 *
5383 * Find information about a GUID in an activation context.
5384 * FIXME: function signature/prototype may be wrong
5385 */
5386 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5387 const GUID *guid, void *ptr )
5388 {
5389 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5390 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5391
5392 if (extguid)
5393 {
5394 DPRINT1("expected extguid == NULL\n");
5395 return STATUS_INVALID_PARAMETER;
5396 }
5397
5398 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5399 {
5400 DPRINT1("unknown flags %08x\n", flags);
5401 return STATUS_INVALID_PARAMETER;
5402 }
5403
5404 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5405 return STATUS_INVALID_PARAMETER;
5406
5407 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
5408 {
5409 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
5410 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5411 }
5412
5413 if (status != STATUS_SUCCESS)
5414 status = find_guid( process_actctx, section_kind, guid, flags, data );
5415
5416 if (status != STATUS_SUCCESS)
5417 status = find_guid( implicit_actctx, section_kind, guid, flags, data );
5418
5419 return status;
5420 }
5421
5422 /* Stubs */
5423
5424 NTSTATUS
5425 NTAPI
5426 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
5427 {
5428 PACTIVATION_CONTEXT_STACK ContextStack;
5429
5430 /* Check if it's already allocated */
5431 if (*Stack) return STATUS_SUCCESS;
5432
5433 /* Allocate space for the context stack */
5434 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK));
5435 if (!ContextStack)
5436 {
5437 return STATUS_NO_MEMORY;
5438 }
5439
5440 /* Initialize the context stack */
5441 ContextStack->Flags = 0;
5442 ContextStack->ActiveFrame = NULL;
5443 InitializeListHead(&ContextStack->FrameListCache);
5444 ContextStack->NextCookieSequenceNumber = 1;
5445 ContextStack->StackId = 1; //TODO: Timer-based
5446
5447 *Stack = ContextStack;
5448
5449 return STATUS_SUCCESS;
5450 }
5451
5452 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5453 FASTCALL
5454 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
5455 IN PVOID Context)
5456 {
5457 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame;
5458 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
5459
5460 /* Get the current active frame */
5461 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5462
5463 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5464 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame,
5465 &Frame->Frame, Context);
5466
5467 /* Ensure it's in the right format and at least fits basic info */
5468 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5469 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5470
5471 /* Set debug info if size allows*/
5472 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5473 {
5474 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame);
5475 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context);
5476 //Frame->Extra3 = ...;
5477 }
5478
5479 if (ActiveFrame)
5480 {
5481 /*ASSERT((ActiveFrame->Flags &
5482 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5483 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5484 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5485
5486 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED))
5487 {
5488 // TODO: Perform some additional checks if it was not heap allocated
5489 }
5490 }
5491
5492 /* Save pointer to the new activation frame */
5493 NewFrame = &Frame->Frame;
5494
5495 /* Actually activate it */
5496 Frame->Frame.Previous = ActiveFrame;
5497 Frame->Frame.ActivationContext = Context;
5498 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED;
5499
5500 /* Check if we can activate this context */
5501 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
5502 Context)
5503 {
5504 /* Set new active frame */
5505 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame);
5506 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5507 return NewFrame;
5508 }
5509
5510 /* We can get here only one way: it was already activated */
5511 DPRINT("Trying to activate already activated activation context\n");
5512
5513 /* Activate only if we are allowing multiple activation */
5514 #if 0
5515 if (!RtlpNotAllowingMultipleActivation)
5516 {
5517 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED;
5518 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5519 }
5520 #else
5521 // Activate it anyway
5522 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame;
5523 #endif
5524
5525 /* Return pointer to the activation frame */
5526 return NewFrame;
5527 }
5528
5529 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5530 FASTCALL
5531 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
5532 {
5533 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame;
5534
5535 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
5536
5537 /* Ensure it's in the right format and at least fits basic info */
5538 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER);
5539 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC));
5540
5541 /* Make sure it is not deactivated and it is activated */
5542 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0);
5543 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);
5544 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);
5545
5546 /* Check debug info if it is present */
5547 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED))
5548 {
5549 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous));
5550 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext));
5551 //Frame->Extra3 = ...;
5552 }
5553
5554 if (ActiveFrame)
5555 {
5556 // TODO: Perform some additional checks here
5557 }
5558
5559 /* Special handling for not-really-activated */
5560 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)
5561 {
5562 DPRINT1("Deactivating not really activated activation context\n");
5563 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5564 return &Frame->Frame;
5565 }
5566
5567 /* find the right frame */
5568 NewFrame = &Frame->Frame;
5569 if (ActiveFrame != NewFrame)
5570 {
5571 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame);
5572 }
5573
5574 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5575 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous);
5576
5577 /* Pop everything up to and including frame */
5578 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous;
5579
5580 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED;
5581 return NewFrame->Previous;
5582 }