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