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