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