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