ReactOS 0.4.15-dev-8102-g108db8f
actctx.c
Go to the documentation of this file.
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#define NDEBUG
23#include <debug.h>
24
25#include <wine/unicode.h>
26#include "wine/exception.h"
27
28#define GetProcessHeap() RtlGetProcessHeap()
29#define GetCurrentProcess() NtCurrentProcess()
30#define FIXME DPRINT1
31#define WARN DPRINT1
32#define TRACE DPRINT
33#define FILE_END_OF_FILE_INFORMATION FILE_STANDARD_INFORMATION
34#define FileEndOfFileInformation FileStandardInformation
35#define RELATIVE_PATH RtlPathTypeRelative
36#define user_shared_data SharedUserData
37
38#undef RT_MANIFEST
39#undef CREATEPROCESS_MANIFEST_RESOURCE_ID
40
41BOOLEAN RtlpNotAllowingMultipleActivation;
42
43#endif // __REACTOS__
44
45#define ACTCTX_FLAGS_ALL (\
46 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
47 ACTCTX_FLAG_LANGID_VALID |\
48 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
49 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
50 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
51 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
52 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
53 ACTCTX_FLAG_HMODULE_VALID )
54
55#define ACTCTX_MAGIC 0xC07E3E11
56#define STRSECTION_MAGIC 0x64487353 /* dHsS */
57#define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
58
59#define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
60
61#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
62#define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
63
64/* we don't want to include winuser.h */
65#define RT_MANIFEST ((ULONG_PTR)24)
66#define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
67
68#ifndef __REACTOS__ // defined in oaidl.h
69/* from oaidl.h */
70typedef enum tagLIBFLAGS {
76
77/* from oleidl.idl */
78typedef enum tagOLEMISC
79{
98 OLEMISC_IMEMODE = 0x40000,
103#endif // !__REACTOS__
104
105#define MAX_NAMESPACES 64
106
107typedef struct
108{
109 const WCHAR *ptr;
110 unsigned int len;
111} xmlstr_t;
112
114{
118};
119
121{
124};
125
126typedef struct
127{
128 const WCHAR *ptr;
129 const WCHAR *end;
130 struct xml_attr namespaces[MAX_NAMESPACES];
133} xmlbuf_t;
134
136{
139};
140
142{
147};
148
150{
159};
160
162{
163 DWORD magic;
164 ULONG size;
165 DWORD unk1[3];
166 ULONG count;
168 DWORD unk2[2];
171};
172
173struct string_index
174{
175 ULONG hash; /* key string hash */
178 ULONG data_offset; /* redirect data offset */
181};
182
184{
185 DWORD magic;
186 ULONG size;
187 DWORD unk[3];
188 ULONG count;
190 DWORD unk2;
193};
194
195struct guid_index
196{
197 GUID guid;
201};
202
204{
205 ULONG size;
206 DWORD res;
208 ULONG name_offset; /* versioned name offset */
210 ULONG module_offset;/* container name offset */
211};
212
213struct dllredirect_data
214{
215 ULONG size;
216 ULONG unk;
217 DWORD res[3];
218};
219
221{
222 ULONG size;
223 DWORD res;
227 WORD flags;
232};
233
235{
242
244{
251
253{
254 ULONG size;
255 BYTE res;
257 BYTE res1[2];
258 DWORD model;
259 GUID clsid;
260 GUID alias;
261 GUID clsid2;
262 GUID tlbid;
274};
275
277{
279 BaseIface = 2
281
283{
284 ULONG size;
285 DWORD mask;
286 GUID iid;
288 GUID tlbid;
289 GUID base;
292};
293
295{
296 ULONG size;
297 DWORD res;
298 GUID clsid;
303};
304
305struct clrclass_data
306{
307 ULONG size;
308 DWORD res[2];
315 DWORD res2[2];
316};
317
319{
320 ULONG size;
323};
324
325/*
326
327 Sections structure.
328
329 Sections are accessible by string or guid key, that defines two types of sections.
330 All sections of each type have same magic value and header structure, index
331 data could be of two possible types too. So every string based section uses
332 the same index format, same applies to guid sections - they share same guid index
333 format.
334
335 - window class redirection section is a plain buffer with following format:
336
337 <section header>
338 <index[]>
339 <data[]> --- <original name>
340 <redirect data>
341 <versioned name>
342 <module name>
343
344 Header is fixed length structure - struct strsection_header,
345 contains redirected classes count;
346
347 Index is an array of fixed length index records, each record is
348 struct string_index.
349
350 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
351
352 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
353 others are relative to section itself.
354
355 - dll redirect section format:
356
357 <section header>
358 <index[]>
359 <data[]> --- <dll name>
360 <data>
361
362 This section doesn't seem to carry any payload data except dll names.
363
364 - typelib section format:
365
366 <section header>
367 <module names[]>
368 <index[]>
369 <data[]> --- <data>
370 <helpstring>
371
372 Header is fixed length, index is an array of fixed length 'struct guid_index'.
373 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
374 4-bytes aligned as a whole.
375
376 Module name offsets are relative to section, helpstring offset is relative to data
377 structure itself.
378
379 - comclass section format:
380
381 <section header>
382 <module names[]>
383 <index[]>
384 <data[]> --- <data> --- <data>
385 <progid> <clrdata>
386 <name>
387 <version>
388 <progid>
389
390 This section uses two index records per comclass, one entry contains original guid
391 as specified by context, another one has a generated guid. Index and strings handling
392 is similar to typelib sections.
393
394 For CLR classes additional data is stored after main COM class data, it contains
395 class name and runtime version string, see 'struct clrclass_data'.
396
397 Module name offsets are relative to section, progid offset is relative to data
398 structure itself.
399
400 - COM interface section format:
401
402 <section header>
403 <index[]>
404 <data[]> --- <data>
405 <name>
406
407 Interface section contains data for proxy/stubs and external proxy/stubs. External
408 ones are defined at assembly level, so this section has no module information.
409 All records are indexed with 'iid' value from manifest. There an exception for
410 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
411 redirect data, but index is still 'iid' from manifest.
412
413 Interface name offset is relative to data structure itself.
414
415 - CLR surrogates section format:
416
417 <section header>
418 <index[]>
419 <data[]> --- <data>
420 <name>
421 <version>
422
423 There's nothing special about this section, same way to store strings is used,
424 no modules part as it belongs to assembly level, not a file.
425
426 - ProgID section format:
427
428 <section header>
429 <guids[]>
430 <index[]>
431 <data[]> --- <progid>
432 <data>
433
434 This sections uses generated alias guids from COM server section. This way
435 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
436 is stored too, aligned.
437*/
438
440{
442 unsigned int num;
443 unsigned int allocated;
444};
445
446struct entity
447{
449 union
450 {
451 struct
452 {
459 struct
460 {
462 WCHAR *tlbid;
464 WCHAR *name; /* clrClass: class name */
465 WCHAR *version; /* clrClass: CLR runtime version */
474 struct {
478 WCHAR *name;
479 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
483 struct
484 {
485 WCHAR *name;
487 } class;
488 struct
489 {
490 WCHAR *name;
491 WCHAR *clsid;
492 WCHAR *version;
494 struct
495 {
496 WCHAR *name;
500 } u;
501};
502
504{
505 struct entity *base;
506 unsigned int num;
507 unsigned int allocated;
508};
509
511{
515};
516
518{
522};
523
524struct assembly
525{
532 unsigned int num_dlls;
533 unsigned int allocated_dlls;
535 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
537 ACTCTX_REQUESTED_RUN_LEVEL run_level;
539};
540
542{
551
552#ifdef __REACTOS__
553typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
554{
555 ULONG Flags;
556 UNICODE_STRING DosPath;
558} ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;
559
560typedef struct _ASSEMBLY_STORAGE_MAP
561{
562 ULONG Flags;
563 ULONG AssemblyCount;
564 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray;
565} ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
566#endif // __REACTOS__
567
569{
570#ifdef __REACTOS__
571 LONG RefCount;
572 ULONG Flags;
573 LIST_ENTRY Links;
574 PACTIVATION_CONTEXT_DATA ActivationContextData;
575 PVOID NotificationRoutine;
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#else
586#endif // __REACTOS__
590 unsigned int num_assemblies;
592 /* section data */
602
604{
607 unsigned int num_dependencies;
609};
610
612
613#ifdef __i386__
614static const WCHAR current_archW[] = {'x','8','6',0};
615#elif defined __x86_64__
616static const WCHAR current_archW[] = {'a','m','d','6','4',0};
617#elif defined __arm__
618static const WCHAR current_archW[] = {'a','r','m',0};
619#elif defined __aarch64__
620static const WCHAR current_archW[] = {'a','r','m','6','4',0};
621#else
622static const WCHAR current_archW[] = {'n','o','n','e',0};
623#endif
624
625static 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};
626static 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};
627static 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};
628
629#ifdef __REACTOS__
630typedef struct _ACTIVATION_CONTEXT_WRAPPED
631{
632 PVOID MagicMarker;
633 ACTIVATION_CONTEXT ActivationContext;
634} ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED;
635
636VOID
637NTAPI
638RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx,
639 IN ULONG FailureCode)
640{
641 EXCEPTION_RECORD ExceptionRecord;
642
643 /* Fatal SxS exception header */
644 ExceptionRecord.ExceptionRecord = NULL;
645 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
647
648 /* With SxS-specific information plus the context itself */
649 ExceptionRecord.ExceptionInformation[0] = 1;
650 ExceptionRecord.ExceptionInformation[1] = FailureCode;
651 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
652 ExceptionRecord.NumberParameters = 3;
653
654 /* Raise it */
655 RtlRaiseException(&ExceptionRecord);
656}
657
659VOID
660RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx)
661{
662 PACTIVATION_CONTEXT_WRAPPED pActual;
663
664 /* Get the caller-opaque header */
665 pActual = CONTAINING_RECORD(ActCtx,
666 ACTIVATION_CONTEXT_WRAPPED,
667 ActivationContext);
668
669 /* Check if the header matches as expected */
670 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
671 {
672 /* Nope, print out a warning, assert, and then throw an exception */
673 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
674 " This means someone stepped on the allocation, or someone is using a\n"
675 " deallocated activation context\n",
677 pActual->MagicMarker,
678 ActCtx);
679 ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER);
680 RtlpSxsBreakOnInvalidMarker(ActCtx, 1);
681 }
682}
683#endif // __REACTOS__
684
685static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
686static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
687static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
688static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
689static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
690static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
691static 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};
692static 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};
693static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
694static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
695static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
696static const WCHAR fileW[] = {'f','i','l','e',0};
697static const WCHAR hashW[] = {'h','a','s','h',0};
698static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
699static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
700static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
701static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
702
703static const WCHAR clsidW[] = {'c','l','s','i','d',0};
704static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
705static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
706static const WCHAR iidW[] = {'i','i','d',0};
707static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
708static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
709static const WCHAR g_nameW[] = {'n','a','m','e',0};
710static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
711static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
712static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
713static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
714static 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};
715static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
716static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
717static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
718static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
719static const WCHAR typeW[] = {'t','y','p','e',0};
720static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
721static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
722static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
723static const WCHAR yesW[] = {'y','e','s',0};
724static const WCHAR noW[] = {'n','o',0};
725static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
726static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
727static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
728static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
729static const WCHAR flagsW[] = {'f','l','a','g','s',0};
730static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
731static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
732static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
733static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
734static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
735static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
736static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
737static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
738static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
739static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
740static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
741
742static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
743static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
744static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
745static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
746static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
747static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
748static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
749static 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};
750static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
751static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
752static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
753static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
754static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
755static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
756static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
757static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
758static 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};
759static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
760static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
761static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
762static 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};
763static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
764
765static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
766static 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};
767static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
768static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
769static const WCHAR IdW[] = {'I','d',0};
770static 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};
771static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
772static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
773static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
774static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
775static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
776static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
777static 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};
778static 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};
779static 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};
780static 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};
781static 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};
782static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
783static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
784static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
785static 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};
786static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
787static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
788static 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};
789static 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};
790
792{
793 const WCHAR *name;
795};
796
797static const struct olemisc_entry olemisc_values[] =
798{
821};
822
823static const WCHAR g_xmlW[] = {'?','x','m','l',0};
824
825static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
826static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
827static const WCHAR wildcardW[] = {'*',0};
828
829static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } };
832
833static WCHAR *strdupW(const WCHAR* str)
834{
835 WCHAR* ptr;
836
837 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
838 return NULL;
839 return strcpyW(ptr, str);
840}
841
843{
844 WCHAR *strW;
845
846 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
847 {
848 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
849 strW[str->len] = 0;
850 }
851 return strW;
852}
853
854static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
855{
856 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
857}
858
859static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
860{
861 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
862}
863
864static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
865{
866 return xmlstr_cmp( &attr->name, str );
867}
868
869static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
870{
871 return (elem1->name.len == elem2->name.len &&
872 elem1->ns.len == elem2->ns.len &&
873 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
874 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
875}
876
877static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
878{
879 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
880 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
881 if (!wcscmp( namespace, asmv1W ))
882 {
883 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
884 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
885 }
886 else if (!wcscmp( namespace, asmv2W ))
887 {
888 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
889 }
890 return FALSE;
891}
892
893static inline BOOL isxmlspace( WCHAR ch )
894{
895 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
896}
897
898#ifndef __REACTOS__
899static inline const char* debugstr_xmlstr(const xmlstr_t* str)
900{
901 return debugstr_wn(str->ptr, str->len);
902}
903
904static inline const char* debugstr_version(const struct assembly_version *ver)
905{
906 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
907}
908#endif // !__REACTOS__
909
911{
912 struct assembly *assembly;
913
914 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
915
916 if (actctx->num_assemblies == actctx->allocated_assemblies)
917 {
918 void *ptr;
919 unsigned int new_count;
920 if (actctx->assemblies)
921 {
922 new_count = actctx->allocated_assemblies * 2;
924 actctx->assemblies, new_count * sizeof(*assembly) );
925 }
926 else
927 {
928 new_count = 4;
929 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
930 }
931 if (!ptr) return NULL;
932 actctx->assemblies = ptr;
933 actctx->allocated_assemblies = new_count;
934 }
935
936 assembly = &actctx->assemblies[actctx->num_assemblies++];
937 assembly->type = at;
938 return assembly;
939}
940
942{
943 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
944
946 {
947 void *ptr;
948 unsigned int new_count;
949 if (assembly->dlls)
950 {
951 new_count = assembly->allocated_dlls * 2;
953 assembly->dlls, new_count * sizeof(*assembly->dlls) );
954 }
955 else
956 {
957 new_count = 4;
958 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
959 }
960 if (!ptr) return NULL;
961 assembly->dlls = ptr;
962 assembly->allocated_dlls = new_count;
963 }
964 return &assembly->dlls[assembly->num_dlls++];
965}
966
967static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
968{
969 void *ptr;
971 {
972 unsigned int new_count = assembly->num_compat_contexts + 1;
975 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
976 }
977 else
978 {
979 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
980 }
981 if (!ptr) return NULL;
984}
985
987{
988 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
989 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
992 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
993}
994
996{
997 struct entity* entity;
998
999 if (array->num == array->allocated)
1000 {
1001 void *ptr;
1002 unsigned int new_count;
1003 if (array->base)
1004 {
1005 new_count = array->allocated * 2;
1007 array->base, new_count * sizeof(*array->base) );
1008 }
1009 else
1010 {
1011 new_count = 4;
1012 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
1013 }
1014 if (!ptr) return NULL;
1015 array->base = ptr;
1016 array->allocated = new_count;
1017 }
1018 entity = &array->base[array->num++];
1019 entity->kind = kind;
1020 return entity;
1021}
1022
1024{
1025 unsigned int i, j;
1026 for (i = 0; i < array->num; i++)
1027 {
1028 struct entity *entity = &array->base[i];
1029 switch (entity->kind)
1030 {
1031 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
1036 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
1037 for (j = 0; j < entity->u.comclass.progids.num; j++)
1038 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
1039 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
1040 break;
1041 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
1047 break;
1048 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
1050 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
1051 break;
1052 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
1054 break;
1055 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
1059 break;
1060 default:
1061 FIXME("Unknown entity kind %d\n", entity->kind);
1062 }
1063 }
1064 RtlFreeHeap( GetProcessHeap(), 0, array->base );
1065}
1066
1067static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
1068{
1069 if (!str1) return !str2;
1070 return str2 && !strcmpiW( str1, str2 );
1071}
1072
1074 const struct assembly_identity *id2 )
1075{
1076 if (!is_matching_string( id1->name, id2->name )) return FALSE;
1077 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1078 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1079
1080 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
1081 {
1082 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
1083 return FALSE;
1084 }
1085 if (id1->version.major != id2->version.major) return FALSE;
1086 if (id1->version.minor != id2->version.minor) return FALSE;
1087 if (id1->version.build > id2->version.build) return FALSE;
1088 if (id1->version.build == id2->version.build &&
1089 id1->version.revision > id2->version.revision) return FALSE;
1090 return TRUE;
1091}
1092
1094 struct assembly_identity* ai)
1095{
1096 unsigned int i;
1097
1098 /* check if we already have that assembly */
1099
1100 for (i = 0; i < acl->actctx->num_assemblies; i++)
1101 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1102 {
1103 TRACE( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
1104 ai->name, ai->arch, ai->version.major, ai->version.minor,
1105 ai->version.build, ai->version.revision );
1106 return TRUE;
1107 }
1108
1109 for (i = 0; i < acl->num_dependencies; i++)
1110 if (is_matching_identity( ai, &acl->dependencies[i] ))
1111 {
1112 TRACE( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
1113 ai->name, ai->arch, ai->version.major, ai->version.minor,
1114 ai->version.build, ai->version.revision );
1115 return TRUE;
1116 }
1117
1119 {
1120 void *ptr;
1121 unsigned int new_count;
1122 if (acl->dependencies)
1123 {
1124 new_count = acl->allocated_dependencies * 2;
1126 new_count * sizeof(acl->dependencies[0]));
1127 }
1128 else
1129 {
1130 new_count = 4;
1131 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1132 }
1133 if (!ptr) return FALSE;
1134 acl->dependencies = ptr;
1135 acl->allocated_dependencies = new_count;
1136 }
1137 acl->dependencies[acl->num_dependencies++] = *ai;
1138
1139 return TRUE;
1140}
1141
1142static void free_depend_manifests(struct actctx_loader* acl)
1143{
1144 unsigned int i;
1145 for (i = 0; i < acl->num_dependencies; i++)
1148}
1149
1151{
1152 static const WCHAR undW[] = {'_',0};
1153 static const WCHAR noneW[] = {'n','o','n','e',0};
1154 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1155
1156 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1157 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1158 const WCHAR *lang = ai->language ? ai->language : noneW;
1159 const WCHAR *name = ai->name ? ai->name : noneW;
1160 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1161 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1162 WCHAR *ret;
1163
1164 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1165
1166 strcpyW( ret, arch );
1167 strcatW( ret, undW );
1168 strcatW( ret, name );
1169 strcatW( ret, undW );
1170 strcatW( ret, key );
1171 strcatW( ret, undW );
1173 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1174 strcatW( ret, undW );
1175 strcatW( ret, lang );
1176 strcatW( ret, undW );
1177 strcatW( ret, mskeyW );
1178 return ret;
1179}
1180
1181static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1182{
1183 WCHAR *p = buffer;
1184
1185 if (!str) return;
1186 strcatW( buffer, prefix );
1187 p += strlenW(p);
1188 *p++ = '"';
1189 strcpyW( p, str );
1190 p += strlenW(p);
1191 *p++ = '"';
1192 *p = 0;
1193}
1194
1195static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1196{
1197 static const WCHAR archW[] =
1198 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1199 static const WCHAR public_keyW[] =
1200 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1201 static const WCHAR typeW2[] =
1202 {',','t','y','p','e','=',0};
1203 static const WCHAR versionW2[] =
1204 {',','v','e','r','s','i','o','n','=',0};
1205
1206 WCHAR version[64], *ret;
1207 SIZE_T size = 0;
1208
1210 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1211 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1212 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1213 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1214 if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1215 size += strlenW(versionW2) + strlenW(version) + 2;
1216
1217 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1218 return NULL;
1219
1220 if (ai->name) strcpyW( ret, ai->name );
1221 else *ret = 0;
1222 append_string( ret, archW, ai->arch );
1223 append_string( ret, public_keyW, ai->public_key );
1224 append_string( ret, typeW2, ai->type );
1225 append_string( ret, versionW2, version );
1226 return ret;
1227}
1228
1230{
1232 PACTIVATION_CONTEXT_WRAPPED pActual;
1233
1234 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1235 __TRY
1236 {
1237 if (actctx)
1238 {
1239 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1240 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1241 }
1242 }
1244 {
1245 DPRINT1("Invalid activation context handle!\n");
1246 }
1247 __ENDTRY
1248 return ret;
1249}
1250
1252{
1253 InterlockedExchangeAdd( &actctx->RefCount, 1 );
1254}
1255
1257{
1258 PACTIVATION_CONTEXT_WRAPPED pActual;
1259
1260 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1261 {
1262 unsigned int i, j;
1263
1264 for (i = 0; i < actctx->num_assemblies; i++)
1265 {
1266 struct assembly *assembly = &actctx->assemblies[i];
1267 for (j = 0; j < assembly->num_dlls; j++)
1268 {
1269 struct dll_redirect *dll = &assembly->dlls[j];
1270 free_entity_array( &dll->entities );
1271 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1272 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1273 }
1280 }
1281 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1282 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1283 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1284 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1285 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1286 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1287 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1288 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1289 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1290 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1291
1292 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1293 pActual->MagicMarker = 0;
1294 RtlFreeHeap(GetProcessHeap(), 0, pActual);
1295 }
1296}
1297
1298static BOOL set_error( xmlbuf_t *xmlbuf )
1299{
1300 xmlbuf->error = TRUE;
1301 return FALSE;
1302}
1303
1304static BOOL is_xmlns_attr( const struct xml_attr *attr )
1305{
1306 const int len = wcslen( xmlnsW );
1307 if (attr->name.len < len) return FALSE;
1308 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1309 return (attr->name.len == len || attr->name.ptr[len] == ':');
1310}
1311
1312static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1313{
1314 const int len = wcslen( xmlnsW );
1315 struct xml_attr *ns;
1316
1317 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1318 {
1319 // FIXME( "too many namespaces in manifest\n" );
1320 set_error( xmlbuf );
1321 return;
1322 }
1323 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1324 ns->value = attr->value;
1325 if (attr->name.len > len)
1326 {
1327 ns->name.ptr = attr->name.ptr + len + 1;
1328 ns->name.len = attr->name.len - len - 1;
1329 }
1330 else ns->name = empty_xmlstr;
1331}
1332
1333static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1334{
1335 int i;
1336
1337 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1338 {
1339 if (xmlbuf->namespaces[i].name.len == name->len &&
1340 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1341 return xmlbuf->namespaces[i].value;
1342 }
1343
1344 return empty_xmlstr;
1345}
1346
1347static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1348{
1349 const WCHAR* ptr;
1350 WCHAR quote;
1351
1352 if (xmlbuf->error) return FALSE;
1353
1354 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1355 xmlbuf->ptr++;
1356
1357 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1358
1359 if (*xmlbuf->ptr == '/')
1360 {
1361 xmlbuf->ptr++;
1362 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1363 return set_error( xmlbuf );
1364
1365 xmlbuf->ptr++;
1366 *end = TRUE;
1367 return FALSE;
1368 }
1369
1370 if (*xmlbuf->ptr == '>')
1371 {
1372 xmlbuf->ptr++;
1373 return FALSE;
1374 }
1375
1376 ptr = xmlbuf->ptr;
1377 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1378
1379 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1380
1381 attr->name.ptr = xmlbuf->ptr;
1382 attr->name.len = ptr-xmlbuf->ptr;
1383 xmlbuf->ptr = ptr;
1384
1385 /* skip spaces before '=' */
1386 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1387 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1388
1389 /* skip '=' itself */
1390 ptr++;
1391 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1392
1393 /* skip spaces after '=' */
1394 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1395
1396 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1397
1398 quote = *ptr++;
1399 attr->value.ptr = ptr;
1400 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1401
1402 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1403 if (ptr == xmlbuf->end)
1404 {
1405 xmlbuf->ptr = xmlbuf->end;
1406 return set_error( xmlbuf );
1407 }
1408
1409 attr->value.len = ptr - attr->value.ptr;
1410 xmlbuf->ptr = ptr + 1;
1411 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1412
1413 return set_error( xmlbuf );
1414}
1415
1416static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1417{
1418 const WCHAR* ptr = xmlbuf->ptr;
1419
1420 elem->ns = empty_xmlstr;
1421 elem->name.ptr = ptr;
1422 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1423 {
1424 if (*ptr == ':')
1425 {
1426 elem->ns.ptr = elem->name.ptr;
1427 elem->ns.len = ptr - elem->ns.ptr;
1428 elem->name.ptr = ptr + 1;
1429 }
1430 ptr++;
1431 }
1432 elem->name.len = ptr - elem->name.ptr;
1433 xmlbuf->ptr = ptr;
1434}
1435
1436static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1437{
1438 const WCHAR* ptr;
1439 struct xml_attr attr;
1440 xmlbuf_t attr_buf;
1441 BOOL end = FALSE;
1442
1443 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1444
1445 if (xmlbuf->error) return FALSE;
1446
1447 for (;;)
1448 {
1449 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1450 if (ptr == xmlbuf->end)
1451 {
1452 xmlbuf->ptr = xmlbuf->end;
1453 return set_error( xmlbuf );
1454 }
1455 ptr++;
1456 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1457 {
1458 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1459 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1460
1461 if (ptr + 3 > xmlbuf->end)
1462 {
1463 xmlbuf->ptr = xmlbuf->end;
1464 return set_error( xmlbuf );
1465 }
1466 xmlbuf->ptr = ptr + 3;
1467 }
1468 else break;
1469 }
1470
1471 xmlbuf->ptr = ptr;
1472 /* check for element terminating the parent element */
1473 if (ptr < xmlbuf->end && *ptr == '/')
1474 {
1475 xmlbuf->ptr++;
1476 read_xml_elem( xmlbuf, elem );
1477 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1478 if (!xml_name_cmp( elem, parent ))
1479 {
1480 /*ERR( "wrong closing element %s for %s\n",
1481 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));*/
1482 return set_error( xmlbuf );
1483 }
1484 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1485 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1486 return FALSE;
1487 }
1488
1489 read_xml_elem( xmlbuf, elem );
1490
1491 /* parse namespace attributes */
1492 attr_buf = *xmlbuf;
1493 while (next_xml_attr( &attr_buf, &attr, &end ))
1494 {
1495 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1496 }
1497 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1498 elem->ns_pos = xmlbuf->ns_pos;
1499
1500 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1501
1502 return set_error( xmlbuf );
1503}
1504
1506{
1507 /* FIXME: parse attributes */
1508 const WCHAR *ptr;
1509
1510 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1511 {
1512 if (ptr[0] == '?' && ptr[1] == '>')
1513 {
1514 xmlbuf->ptr = ptr + 2;
1515 return TRUE;
1516 }
1517 }
1518 return FALSE;
1519}
1520
1522{
1523 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1524
1525 if (!ptr) return FALSE;
1526
1527 content->ptr = xmlbuf->ptr;
1528 content->len = ptr - xmlbuf->ptr;
1529 xmlbuf->ptr = ptr;
1530
1531 return TRUE;
1532}
1533
1535{
1536 unsigned int ver[4];
1537 unsigned int pos;
1538 const WCHAR *curr;
1539
1540 /* major.minor.build.revision */
1541 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1542 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1543 {
1544 if (*curr >= '0' && *curr <= '9')
1545 {
1546 ver[pos] = ver[pos] * 10 + *curr - '0';
1547 if (ver[pos] >= 0x10000) goto error;
1548 }
1549 else if (*curr == '.')
1550 {
1551 if (++pos >= 4) goto error;
1552 }
1553 else goto error;
1554 }
1555 version->major = ver[0];
1556 version->minor = ver[1];
1557 version->build = ver[2];
1558 version->revision = ver[3];
1559 return TRUE;
1560
1561error:
1562 return FALSE;
1563}
1564
1566{
1567 struct xml_attr attr;
1568
1569 while (next_xml_attr(xmlbuf, &attr, end))
1570 {
1571 // TODO: report error
1572 // if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1573 }
1574}
1575
1576static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1577{
1578 struct xml_elem elem;
1579
1580 if (next_xml_elem(xmlbuf, &elem, parent))
1581 {
1582 // FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1583 set_error( xmlbuf );
1584 }
1585}
1586
1587static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1588{
1589 struct xml_elem elem;
1590 struct xml_attr attr;
1591 BOOL end = FALSE;
1592
1593 while (next_xml_attr(xmlbuf, &attr, &end));
1594 if (end) return;
1595
1596 while (next_xml_elem(xmlbuf, &elem, parent))
1597 parse_unknown_elem(xmlbuf, &elem);
1598}
1599
1601 struct assembly_identity* ai, const struct xml_elem *parent)
1602{
1603 struct xml_attr attr;
1604 BOOL end = FALSE;
1605
1606 while (next_xml_attr(xmlbuf, &attr, &end))
1607 {
1608 if (xml_attr_cmp(&attr, g_nameW))
1609 {
1610 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1611 }
1612 else if (xml_attr_cmp(&attr, typeW))
1613 {
1614 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1615 }
1616 else if (xml_attr_cmp(&attr, versionW))
1617 {
1618 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1619 }
1621 {
1622 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1623 }
1624 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1625 {
1626 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1627 }
1628 else if (xml_attr_cmp(&attr, languageW))
1629 {
1630 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1631 }
1632 }
1633
1634 if (!end) parse_expect_end_elem(xmlbuf, parent);
1635}
1636
1638{
1639 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1640 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1641 static const WCHAR freeW[] = {'F','r','e','e',0};
1642 static const WCHAR bothW[] = {'B','o','t','h',0};
1643
1644 if (value->len == 0) return ThreadingModel_No;
1645 if (xmlstr_cmp(value, apartW))
1647 else if (xmlstr_cmp(value, freeW))
1648 return ThreadingModel_Free;
1649 else if (xmlstr_cmp(value, bothW))
1650 return ThreadingModel_Both;
1651 else if (xmlstr_cmp(value, neutralW))
1653 else
1654 return ThreadingModel_No;
1655};
1656
1658{
1659 int min, max;
1660
1661 min = 0;
1662 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1663
1664 while (min <= max)
1665 {
1666 int n, c;
1667
1668 n = (min+max)/2;
1669
1671 if (!c && !olemisc_values[n].name[len])
1672 return olemisc_values[n].value;
1673
1674 if (c >= 0)
1675 max = n-1;
1676 else
1677 min = n+1;
1678 }
1679
1680 WARN("unknown flag %S\n", str);
1681 return 0;
1682}
1683
1685{
1686 const WCHAR *str = value->ptr, *start;
1687 DWORD flags = 0;
1688 int i = 0;
1689
1690 /* it's comma separated list of flags */
1691 while (i < value->len)
1692 {
1693 start = str;
1694 while (*str != ',' && (i++ < value->len)) str++;
1695
1697
1698 /* skip separator */
1699 str++;
1700 i++;
1701 }
1702
1703 return flags;
1704}
1705
1707{
1708 struct progids *progids = &entity->u.comclass.progids;
1709
1710 if (progids->allocated == 0)
1711 {
1712 progids->allocated = 4;
1713 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1714 }
1715
1716 if (progids->allocated == progids->num)
1717 {
1718 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1719 2 * progids->allocated * sizeof(WCHAR*));
1720 if (!new_progids) return FALSE;
1721 progids->allocated *= 2;
1722 progids->progids = new_progids;
1723 }
1724
1725 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1726 progids->num++;
1727
1728 return TRUE;
1729}
1730
1731static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1732{
1734 BOOL end = FALSE;
1735
1736 parse_expect_no_attr(xmlbuf, &end);
1737 if (end) set_error( xmlbuf );
1738 if (!parse_text_content(xmlbuf, &content)) return;
1739
1740 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1742}
1743
1744static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1745 const struct xml_elem *parent )
1746{
1747 struct xml_elem elem;
1748 struct xml_attr attr;
1749 BOOL end = FALSE;
1750 struct entity* entity;
1751
1752 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1753 {
1754 set_error( xmlbuf );
1755 return;
1756 }
1757
1758 while (next_xml_attr(xmlbuf, &attr, &end))
1759 {
1760 if (xml_attr_cmp(&attr, clsidW))
1761 {
1762 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1763 }
1764 else if (xml_attr_cmp(&attr, progidW))
1765 {
1766 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1767 }
1768 else if (xml_attr_cmp(&attr, tlbidW))
1769 {
1770 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1771 }
1772 else if (xml_attr_cmp(&attr, threadingmodelW))
1773 {
1775 }
1776 else if (xml_attr_cmp(&attr, miscstatusW))
1777 {
1779 }
1781 {
1782 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1783 }
1785 {
1786 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1787 }
1788 else if (xml_attr_cmp(&attr, miscstatusiconW))
1789 {
1790 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1791 }
1793 {
1794 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1795 }
1796 else if (xml_attr_cmp(&attr, descriptionW))
1797 {
1798 /* not stored */
1799 }
1800 }
1801
1803 if (entity->u.comclass.progid)
1805
1806 if (end) return;
1807
1808 while (next_xml_elem(xmlbuf, &elem, parent))
1809 {
1811 {
1813 }
1814 else
1815 {
1816 parse_unknown_elem(xmlbuf, &elem);
1817 }
1818 }
1819
1820 if (entity->u.comclass.progids.num)
1822}
1823
1825{
1826 const WCHAR *curr;
1827 ULONG num = 0;
1828
1829 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1830 {
1831 if (*curr >= '0' && *curr <= '9')
1832 num = num * 10 + *curr - '0';
1833 else
1834 {
1835 // ERR("wrong numeric value %wZ\n", &strU);
1836 return FALSE;
1837 }
1838 }
1839 entity->u.ifaceps.nummethods = num;
1840
1841 return TRUE;
1842}
1843
1844static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1845 struct actctx_loader *acl, WCHAR *clsid )
1846{
1847 struct entity *entity;
1848 WCHAR *str;
1849
1850 if (!clsid) return;
1851
1852 if (!(str = strdupW(clsid)))
1853 {
1854 set_error( xmlbuf );
1855 return;
1856 }
1857
1858 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1859 {
1861 set_error( xmlbuf );
1862 return;
1863 }
1864
1865 entity->u.comclass.clsid = str;
1867
1869}
1870
1872 struct actctx_loader *acl, const struct xml_elem *parent )
1873{
1874 WCHAR *psclsid = NULL;
1875 struct entity *entity;
1876 struct xml_attr attr;
1877 BOOL end = FALSE;
1878
1879 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1880 {
1881 set_error( xmlbuf );
1882 return;
1883 }
1884
1885 while (next_xml_attr(xmlbuf, &attr, &end))
1886 {
1887 if (xml_attr_cmp(&attr, iidW))
1888 {
1889 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1890 }
1891 else if (xml_attr_cmp(&attr, g_nameW))
1892 {
1893 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1894 }
1895 else if (xml_attr_cmp(&attr, baseInterfaceW))
1896 {
1897 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1898 entity->u.ifaceps.mask |= BaseIface;
1899 }
1900 else if (xml_attr_cmp(&attr, nummethodsW))
1901 {
1902 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1903 entity->u.ifaceps.mask |= NumMethods;
1904 }
1905 else if (xml_attr_cmp(&attr, tlbidW))
1906 {
1907 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1908 }
1910 {
1911 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1912 }
1913 /* not used */
1914 else if (xml_attr_cmp(&attr, threadingmodelW))
1915 {
1916 }
1917 }
1918
1920 if (!end) parse_expect_end_elem(xmlbuf, parent);
1921
1922 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1923
1924 RtlFreeHeap(GetProcessHeap(), 0, psclsid);
1925}
1926
1928{
1929 WORD *flags = &entity->u.typelib.flags;
1930 const WCHAR *str = value->ptr, *start;
1931 int i = 0;
1932
1933 *flags = 0;
1934
1935 /* it's comma separated list of flags */
1936 while (i < value->len)
1937 {
1938 start = str;
1939 while (*str != ',' && (i++ < value->len)) str++;
1940
1943 else if (!strncmpiW(start, controlW, str-start))
1945 else if (!strncmpiW(start, hiddenW, str-start))
1947 else if (!strncmpiW(start, hasdiskimageW, str-start))
1949 else
1950 {
1951 // WARN("unknown flags value %wZ\n", &valueU);
1952 return FALSE;
1953 }
1954
1955 /* skip separator */
1956 str++;
1957 i++;
1958 }
1959
1960 return TRUE;
1961}
1962
1964{
1965 unsigned int ver[2];
1966 unsigned int pos;
1967 const WCHAR *curr;
1968
1969 /* major.minor */
1970 ver[0] = ver[1] = pos = 0;
1971 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1972 {
1973 if (*curr >= '0' && *curr <= '9')
1974 {
1975 ver[pos] = ver[pos] * 10 + *curr - '0';
1976 if (ver[pos] >= 0x10000) goto error;
1977 }
1978 else if (*curr == '.')
1979 {
1980 if (++pos >= 2) goto error;
1981 }
1982 else goto error;
1983 }
1984 entity->u.typelib.major = ver[0];
1985 entity->u.typelib.minor = ver[1];
1986 return TRUE;
1987
1988error:
1989 return FALSE;
1990}
1991
1992static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1993 struct actctx_loader *acl, const struct xml_elem *parent )
1994{
1995 struct xml_attr attr;
1996 BOOL end = FALSE;
1997 struct entity* entity;
1998
1999 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
2000 {
2001 set_error( xmlbuf );
2002 return;
2003 }
2004
2005 while (next_xml_attr(xmlbuf, &attr, &end))
2006 {
2007 if (xml_attr_cmp(&attr, tlbidW))
2008 {
2009 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2010 }
2011 else if (xml_attr_cmp(&attr, versionW))
2012 {
2013 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
2014 }
2015 else if (xml_attr_cmp(&attr, helpdirW))
2016 {
2017 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2018 }
2019 else if (xml_attr_cmp(&attr, flagsW))
2020 {
2021 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
2022 }
2023 }
2024
2026 if (!end) parse_expect_end_elem(xmlbuf, parent);
2027}
2028
2029static inline int aligned_string_len(int len)
2030{
2031 return (len + 3) & ~3;
2032}
2033
2035{
2036 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
2037 struct assembly_version *ver = &assembly->id.version;
2038 WCHAR buff[25];
2039
2040 if (!ret) ret = buff;
2041 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
2042}
2043
2044static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
2045 struct actctx_loader *acl, const struct xml_elem *parent )
2046{
2047 struct xml_elem elem;
2048 struct xml_attr attr;
2050 BOOL end = FALSE;
2051 struct entity* entity;
2052
2053 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
2054 {
2055 set_error( xmlbuf );
2056 return;
2057 }
2058 entity->u.class.versioned = TRUE;
2059 while (next_xml_attr(xmlbuf, &attr, &end))
2060 {
2062 {
2063 if (xmlstr_cmpi(&attr.value, noW))
2064 entity->u.class.versioned = FALSE;
2065 else if (!xmlstr_cmpi(&attr.value, yesW))
2066 set_error( xmlbuf );
2067 }
2068 }
2069
2070 if (end) return;
2071
2072 if (!parse_text_content(xmlbuf, &content)) return;
2073 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
2074
2076
2077 while (next_xml_elem(xmlbuf, &elem, parent))
2078 {
2079 parse_unknown_elem(xmlbuf, &elem);
2080 }
2081}
2082
2083static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2084{
2085 struct xml_attr attr;
2086 BOOL end = FALSE;
2087
2088 while (next_xml_attr(xmlbuf, &attr, &end))
2089 {
2091 {
2092 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2093 }
2094 else if (xml_attr_cmp(&attr, newVersionW))
2095 {
2096 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2097 }
2098 }
2099
2100 if (!end) parse_expect_end_elem(xmlbuf, parent);
2101}
2102
2103static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2104{
2105 struct xml_elem elem;
2106 struct xml_attr attr;
2108 BOOL end = FALSE;
2109
2110 while (next_xml_attr(xmlbuf, &attr, &end));
2111
2112 if (end) return;
2113 if (!parse_text_content(xmlbuf, &content)) return;
2114
2115 while (next_xml_elem(xmlbuf, &elem, parent))
2116 {
2117 parse_unknown_elem(xmlbuf, &elem);
2118 }
2119}
2120
2122 struct assembly* assembly,
2123 struct actctx_loader* acl,
2124 const struct xml_elem *parent)
2125{
2126 struct xml_attr attr;
2127 BOOL end = FALSE;
2128 struct entity* entity;
2129
2130 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2131 {
2132 set_error( xmlbuf );
2133 return;
2134 }
2135
2136 while (next_xml_attr(xmlbuf, &attr, &end))
2137 {
2138 if (xml_attr_cmp(&attr, iidW))
2139 {
2140 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2141 }
2142 else if (xml_attr_cmp(&attr, g_nameW))
2143 {
2144 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2145 }
2146 else if (xml_attr_cmp(&attr, baseInterfaceW))
2147 {
2148 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2149 entity->u.ifaceps.mask |= BaseIface;
2150 }
2151 else if (xml_attr_cmp(&attr, nummethodsW))
2152 {
2153 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2154 entity->u.ifaceps.mask |= NumMethods;
2155 }
2157 {
2158 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2159 }
2160 else if (xml_attr_cmp(&attr, tlbidW))
2161 {
2162 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2163 }
2164 }
2165
2167 if (!end) parse_expect_end_elem(xmlbuf, parent);
2168}
2169
2170static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2171 struct actctx_loader *acl, const struct xml_elem *parent )
2172
2173{
2174 struct xml_elem elem;
2175 struct xml_attr attr;
2176 BOOL end = FALSE;
2177 struct entity* entity;
2178
2179 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2180 {
2181 set_error( xmlbuf );
2182 return;
2183 }
2184
2185 while (next_xml_attr(xmlbuf, &attr, &end))
2186 {
2187 if (xml_attr_cmp(&attr, g_nameW))
2188 {
2189 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2190 }
2191 else if (xml_attr_cmp(&attr, clsidW))
2192 {
2193 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2194 }
2195 else if (xml_attr_cmp(&attr, progidW))
2196 {
2197 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2198 }
2199 else if (xml_attr_cmp(&attr, tlbidW))
2200 {
2201 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2202 }
2203 else if (xml_attr_cmp(&attr, threadingmodelW))
2204 {
2206 }
2207 else if (xml_attr_cmp(&attr, runtimeVersionW))
2208 {
2209 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2210 }
2211 }
2212
2214 if (entity->u.comclass.progid)
2216 if (end) return;
2217
2218 while (next_xml_elem(xmlbuf, &elem, parent))
2219 {
2221 {
2223 }
2224 else
2225 {
2226 parse_unknown_elem(xmlbuf, &elem);
2227 }
2228 }
2229
2230 if (entity->u.comclass.progids.num)
2232}
2233
2235 struct actctx_loader *acl, const struct xml_elem *parent )
2236{
2237 struct xml_attr attr;
2238 BOOL end = FALSE;
2239 struct entity* entity;
2240
2241 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2242 {
2243 set_error( xmlbuf );
2244 return;
2245 }
2246
2247 while (next_xml_attr(xmlbuf, &attr, &end))
2248 {
2249 if (xml_attr_cmp(&attr, g_nameW))
2250 {
2251 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2252 }
2253 else if (xml_attr_cmp(&attr, clsidW))
2254 {
2255 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2256 }
2257 else if (xml_attr_cmp(&attr, runtimeVersionW))
2258 {
2259 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2260 }
2261 }
2262
2264 if (!end) parse_expect_end_elem(xmlbuf, parent);
2265}
2266
2267static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2268 const struct xml_elem *parent, BOOL optional )
2269{
2270 struct xml_elem elem;
2271 struct xml_attr attr;
2272 struct assembly_identity ai;
2273 BOOL end = FALSE;
2274
2275 memset(&ai, 0, sizeof(ai));
2276 ai.optional = optional;
2277
2278 while (next_xml_attr(xmlbuf, &attr, &end))
2279 {
2280 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2281 static const WCHAR trueW[] = {'t','r','u','e',0};
2282
2283 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2285 }
2286
2287 if (end) return;
2288
2289 while (next_xml_elem(xmlbuf, &elem, parent))
2290 {
2292 {
2293 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2294 /* store the newly found identity for later loading */
2295 if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2296 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2297 }
2299 {
2301 }
2302 else
2303 {
2304 parse_unknown_elem(xmlbuf, &elem);
2305 }
2306 }
2307}
2308
2309static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2310 const struct xml_elem *parent )
2311
2312{
2313 struct xml_elem elem;
2314 struct xml_attr attr;
2316
2317 while (next_xml_attr(xmlbuf, &attr, &end))
2318 {
2320 {
2322 }
2323 }
2324
2325 while (next_xml_elem(xmlbuf, &elem, parent))
2326 {
2328 {
2330 }
2331 else
2332 {
2333 parse_unknown_elem(xmlbuf, &elem);
2334 }
2335 }
2336}
2337
2338static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2339{
2340 BOOL end = FALSE;
2341
2342 parse_expect_no_attr(xmlbuf, &end);
2343 if (!end) parse_expect_end_elem(xmlbuf, parent);
2344}
2345
2346static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2347{
2348 BOOL end = FALSE;
2349
2350 parse_expect_no_attr(xmlbuf, &end);
2351 if (!end) parse_expect_end_elem(xmlbuf, parent);
2352}
2353
2354static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2355 struct actctx_loader* acl, const struct xml_elem *parent )
2356{
2357 struct xml_elem elem;
2358 struct xml_attr attr;
2359 BOOL end = FALSE;
2360 struct dll_redirect* dll;
2361
2362 if (!(dll = add_dll_redirect(assembly)))
2363 {
2364 set_error( xmlbuf );
2365 return;
2366 }
2367
2368 while (next_xml_attr(xmlbuf, &attr, &end))
2369 {
2370 if (xml_attr_cmp(&attr, g_nameW))
2371 {
2372 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2373 }
2374 else if (xml_attr_cmp(&attr, hashW))
2375 {
2376 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2377 }
2378 else if (xml_attr_cmp(&attr, hashalgW))
2379 {
2380 static const WCHAR sha1W[] = {'S','H','A','1',0};
2381 if (!xmlstr_cmpi(&attr.value, sha1W)) {
2382 //FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2383 }
2384 }
2385 }
2386
2387 if (!dll->name) set_error( xmlbuf );
2388
2390
2391 if (end) return;
2392
2393 while (next_xml_elem(xmlbuf, &elem, parent))
2394 {
2396 {
2397 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2398 }
2400 {
2402 }
2403 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2404 {
2405 parse_unknown_elem(xmlbuf, &elem);
2406 }
2407 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2408 {
2409 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2410 }
2411 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2412 {
2413 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2414 }
2415 else
2416 {
2417 parse_unknown_elem( xmlbuf, &elem );
2418 }
2419 }
2420}
2421
2422static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2423 struct actctx_loader *acl, const struct xml_elem *parent )
2424{
2425 struct xml_attr attr;
2426 BOOL end = FALSE;
2427
2428 while (next_xml_attr(xmlbuf, &attr, &end))
2429 {
2430 if (xml_attr_cmp(&attr, IdW))
2431 {
2432 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2434 GUID compat_id;
2435
2436 str.Buffer = (PWSTR)attr.value.ptr;
2437 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2438 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2439 {
2440 if (!(compat = add_compat_context(assembly)))
2441 {
2442 set_error( xmlbuf );
2443 return;
2444 }
2445 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2446 compat->Id = compat_id;
2447 }
2448 }
2449 }
2450
2451 if (!end) parse_expect_end_elem(xmlbuf, parent);
2452}
2453
2455 struct actctx_loader* acl, const struct xml_elem *parent)
2456{
2457 struct xml_elem elem;
2458
2459 while (next_xml_elem(xmlbuf, &elem, parent))
2460 {
2462 {
2463 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2464 }
2465 else
2466 {
2467 parse_unknown_elem(xmlbuf, &elem);
2468 }
2469 }
2470}
2471
2473 struct actctx_loader* acl, const struct xml_elem *parent)
2474{
2475 struct xml_elem elem;
2476
2477 while (next_xml_elem(xmlbuf, &elem, parent))
2478 {
2480 {
2482 }
2483 else
2484 {
2485 parse_unknown_elem(xmlbuf, &elem);
2486 }
2487 }
2488}
2489
2490static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2491 struct xml_elem *parent )
2492{
2493 struct xml_elem elem;
2494 struct xml_attr attr;
2496 BOOL end = FALSE;
2497 struct entity *entity;
2498
2499 while (next_xml_attr( xmlbuf, &attr, &end ))
2500 {
2501 }
2502
2503 if (end) return;
2504
2505 if (!parse_text_content( xmlbuf, &content )) return;
2506
2507 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2508 if (!entity)
2509 {
2510 set_error( xmlbuf );
2511 return;
2512 }
2513 entity->u.settings.name = xmlstrdupW( &parent->name );
2514 entity->u.settings.value = xmlstrdupW( &content );
2515 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2516
2517 while (next_xml_elem(xmlbuf, &elem, parent))
2518 {
2519 parse_unknown_elem( xmlbuf, &elem );
2520 }
2521}
2522
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 {
2541 {
2542 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2543 }
2544 else
2545 {
2546 parse_unknown_elem( xmlbuf, &elem );
2547 }
2548 }
2549}
2550
2551static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2552 struct actctx_loader *acl, const struct xml_elem *parent )
2553{
2554 struct xml_elem elem;
2555
2556 while (next_xml_elem( xmlbuf, &elem, parent ))
2557 {
2559 {
2560 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2561 }
2562 else
2563 {
2564 parse_unknown_elem( xmlbuf, &elem );
2565 }
2566 }
2567}
2568
2570 struct actctx_loader *acl, const struct xml_elem *parent )
2571{
2572 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2573 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2574 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};
2575 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2576 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2577 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2578 static const WCHAR trueW[] = {'t','r','u','e',0};
2579
2580 struct xml_elem elem;
2581 struct xml_attr attr;
2582 BOOL end = FALSE;
2583
2584 /* Multiple requestedExecutionLevel elements are not supported. */
2585 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2586
2587 while (next_xml_attr(xmlbuf, &attr, &end))
2588 {
2589 if (xml_attr_cmp(&attr, levelW))
2590 {
2591 if (xmlstr_cmpi(&attr.value, asInvokerW))
2592 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2593 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2594 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2595 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2596 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2597 }
2598 else if (xml_attr_cmp(&attr, uiAccessW))
2599 {
2602 else if (xmlstr_cmpi(&attr.value, trueW))
2604 }
2605 }
2606
2607 if (end) return;
2608
2609 while (next_xml_elem(xmlbuf, &elem, parent))
2610 {
2611 parse_unknown_elem(xmlbuf, &elem);
2612 }
2613}
2614
2616 struct actctx_loader *acl, const struct xml_elem *parent )
2617{
2618 struct xml_elem elem;
2619
2620 while (next_xml_elem(xmlbuf, &elem, parent))
2621 {
2623 {
2625 }
2626 else
2627 {
2628 parse_unknown_elem(xmlbuf, &elem);
2629 }
2630 }
2631}
2632
2633static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2634 struct actctx_loader *acl, const struct xml_elem *parent )
2635{
2636 struct xml_elem elem;
2637
2638 while (next_xml_elem(xmlbuf, &elem, parent))
2639 {
2641 {
2643 }
2644 else
2645 {
2646 parse_unknown_elem(xmlbuf, &elem);
2647 }
2648 }
2649}
2650
2651static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2652 struct actctx_loader *acl, const struct xml_elem *parent )
2653{
2654 struct xml_elem elem;
2655
2656 while (next_xml_elem(xmlbuf, &elem, parent))
2657 {
2659 {
2660 parse_security_elem(xmlbuf, assembly, acl, &elem);
2661 }
2662 else
2663 {
2664 parse_unknown_elem(xmlbuf, &elem);
2665 }
2666 }
2667}
2668
2669static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2670 struct actctx_loader* acl, const struct xml_elem *parent,
2671 struct assembly_identity* expected_ai)
2672{
2673 struct xml_elem elem;
2674 struct xml_attr attr;
2675 BOOL end = FALSE, version = FALSE;
2676
2677 while (next_xml_attr(xmlbuf, &attr, &end))
2678 {
2680 {
2681 static const WCHAR v10W[] = {'1','.','0',0};
2682 if (!xmlstr_cmp(&attr.value, v10W))
2683 {
2684 break;
2685 }
2686 version = TRUE;
2687 }
2688 }
2689
2690 if (end || !version)
2691 {
2692 set_error( xmlbuf );
2693 return;
2694 }
2695
2696 while (next_xml_elem(xmlbuf, &elem, parent))
2697 {
2699 {
2700 parse_noinherit_elem(xmlbuf, &elem);
2702 }
2704 {
2706 }
2707 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2708 {
2709 parse_description_elem(xmlbuf, &elem);
2710 }
2712 {
2714 }
2715 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2716 {
2717 parse_dependency_elem(xmlbuf, acl, &elem);
2718 }
2719 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2720 {
2721 parse_file_elem(xmlbuf, assembly, acl, &elem);
2722 }
2723 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2724 {
2725 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2726 }
2728 {
2729 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2730 }
2731 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2732 {
2733 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2734 }
2736 {
2738
2739 if (!xmlbuf->error && expected_ai)
2740 {
2741 /* FIXME: more tests */
2743 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2744 {
2745 set_error( xmlbuf );
2746 }
2747 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2748 (assembly->id.version.major != expected_ai->version.major ||
2749 assembly->id.version.minor != expected_ai->version.minor ||
2750 assembly->id.version.build < expected_ai->version.build ||
2751 (assembly->id.version.build == expected_ai->version.build &&
2752 assembly->id.version.revision < expected_ai->version.revision)))
2753 {
2754 set_error( xmlbuf );
2755 }
2756 }
2757 }
2759 {
2760 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2761 }
2762 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2763 {
2764 parse_application_elem(xmlbuf, assembly, acl, &elem);
2765 }
2766 else
2767 {
2768 parse_unknown_elem(xmlbuf, &elem);
2769 }
2770 }
2771
2774 {
2775 set_error( xmlbuf );
2776 }
2777}
2778
2780 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2781{
2782 struct xml_elem elem;
2783 struct xml_elem parent = {0};
2784
2785 xmlbuf->error = FALSE;
2786 xmlbuf->ns_pos = 0;
2787
2788 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2789
2790 if (xmlstr_cmp(&elem.name, g_xmlW) &&
2791 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2793
2795 {
2797 }
2798
2799 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2800 if (xmlbuf->error)
2801 {
2803 }
2804
2805 if (next_xml_elem(xmlbuf, &elem, &parent))
2806 {
2808 }
2809
2810 if (xmlbuf->ptr != xmlbuf->end)
2811 {
2813 }
2814 return STATUS_SUCCESS;
2815}
2816
2819 const void *buffer, SIZE_T size )
2820{
2821 xmlbuf_t xmlbuf;
2823 struct assembly *assembly;
2824 int unicode_tests;
2825
2826 TRACE( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2827
2830
2832 return STATUS_NO_MEMORY;
2833
2834 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2835 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2836 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2837
2839 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2840 {
2841 xmlbuf.ptr = buffer;
2842 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2843 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2844 }
2845 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2846 {
2847 const WCHAR *buf = buffer;
2848 WCHAR *new_buff;
2849 unsigned int i;
2850
2851 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2852 return STATUS_NO_MEMORY;
2853 for (i = 0; i < size / sizeof(WCHAR); i++)
2854 new_buff[i] = RtlUshortByteSwap( buf[i] );
2855 xmlbuf.ptr = new_buff;
2856 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2857 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2858 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2859 }
2860 else
2861 {
2862 /* TODO: this doesn't handle arbitrary encodings */
2863 WCHAR *new_buff;
2864 ULONG sizeU;
2865
2867 if (!NT_SUCCESS(status))
2868 {
2869 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2871 }
2872
2873 new_buff = RtlAllocateHeap(GetProcessHeap(), 0, sizeU);
2874 if (!new_buff)
2875 return STATUS_NO_MEMORY;
2876
2877 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2878 if (!NT_SUCCESS(status))
2879 {
2880 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2882 }
2883
2884 xmlbuf.ptr = new_buff;
2885 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2886 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2887 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2888 }
2889 return status;
2890}
2891
2893{
2896
2897 attr.Length = sizeof(attr);
2898 attr.RootDirectory = 0;
2899 attr.Attributes = OBJ_CASE_INSENSITIVE;
2900 attr.ObjectName = name;
2901 attr.SecurityDescriptor = NULL;
2902 attr.SecurityQualityOfService = NULL;
2904}
2905
2907{
2911
2914 if (status == STATUS_SUCCESS)
2915 {
2916 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2917 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2918 {
2919 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2920 str->Length = pldr->FullDllName.Length;
2921 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2922 }
2923 else status = STATUS_NO_MEMORY;
2924 }
2926 return status;
2927}
2928
2931 HANDLE hModule, LPCWSTR resname, ULONG lang )
2932{
2937 void *ptr;
2938
2939 //DPRINT( "looking for res %s in module %p %s\n", resname,
2940 // hModule, filename );
2941 DPRINT("get_manifest_in_module %p\n", hModule);
2942
2943#if 0
2944 if (TRACE_ON(actctx))
2945 {
2946 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2947 {
2948 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2949 hModule, debugstr_w(nameW.Buffer) );
2951 }
2952 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2954 }
2955#endif
2956
2957 if (!resname) return STATUS_INVALID_PARAMETER;
2958
2959 info.Type = RT_MANIFEST;
2960 info.Language = lang;
2961 if (!((ULONG_PTR)resname >> 16))
2962 {
2963 info.Name = (ULONG_PTR)resname;
2965 }
2966 else if (resname[0] == '#')
2967 {
2968 ULONG value;
2969 RtlInitUnicodeString(&nameW, resname + 1);
2972 info.Name = value;
2974 }
2975 else
2976 {
2977 RtlCreateUnicodeString(&nameW, resname);
2979 info.Name = (ULONG_PTR)nameW.Buffer;
2982 }
2984
2985 if (status == STATUS_SUCCESS)
2986 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2987
2988 return status;
2989}
2990
2991#ifdef __REACTOS__
2993 LPCWSTR name, void *root,
2994 int want_dir );
2995
2997 void *root, int want_dir );
2998
2999
3000static IMAGE_RESOURCE_DIRECTORY *find_first_id_entry( IMAGE_RESOURCE_DIRECTORY *dir,
3001 void *root, int want_dir )
3002{
3004 int pos;
3005
3006 for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
3007 {
3008 if (!entry[pos].DataIsDirectory == !want_dir)
3009 return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
3010 }
3011 return NULL;
3012}
3013
3014
3015static NTSTATUS search_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
3018{
3019 ULONG size;
3020 PVOID root, ptr;
3021 IMAGE_RESOURCE_DIRECTORY *resdirptr;
3024
3027 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
3028 resdirptr = root;
3029
3030 if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1)))
3032
3033 resdirptr = ptr;
3034 if (!(ptr = find_first_id_entry(resdirptr, root, 1)))
3036
3037 resdirptr = ptr;
3038 if (!(ptr = find_first_entry(resdirptr, root, 0)))
3040
3041 entry = ptr;
3043
3044 if (status == STATUS_SUCCESS)
3045 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
3046
3047 return status;
3048}
3049#endif // __REACTOS__
3050
3053 HANDLE file, LPCWSTR resname, ULONG lang )
3054{
3060 SIZE_T count;
3061 void *base;
3062 WCHAR resnameBuf[20];
3063 LPCWSTR resptr = resname;
3064
3065 if ((!((ULONG_PTR)resname >> 16)))
3066 {
3067 sprintfW(resnameBuf, L"#%u", PtrToUlong(resname));
3068 resptr = resnameBuf;
3069 }
3070
3071 TRACE( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>");
3072
3073 attr.Length = sizeof(attr);
3074 attr.RootDirectory = 0;
3075 attr.ObjectName = NULL;
3076 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3077 attr.SecurityDescriptor = NULL;
3078 attr.SecurityQualityOfService = NULL;
3079
3080 size.QuadPart = 0;
3083 if (status != STATUS_SUCCESS) return status;
3084
3085 offset.QuadPart = 0;
3086 count = 0;
3087 base = NULL;
3090 NtClose( mapping );
3091 if (status != STATUS_SUCCESS) return status;
3092
3093 if (RtlImageNtHeader(base)) /* we got a PE file */
3094 {
3095 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3096 if (resname)
3097 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3098 else
3099 status = search_manifest_in_module(acl, ai, filename, directory, shared, module, lang);
3100 }
3102
3104 return status;
3105}
3106
3109{
3117 SIZE_T count;
3118 void *base;
3119
3120 TRACE( "loading manifest file %S\n", filename );
3121
3122 attr.Length = sizeof(attr);
3123 attr.RootDirectory = 0;
3124 attr.ObjectName = NULL;
3125 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3126 attr.SecurityDescriptor = NULL;
3127 attr.SecurityQualityOfService = NULL;
3128
3129 size.QuadPart = 0;
3132 if (status != STATUS_SUCCESS) return status;
3133
3134 offset.QuadPart = 0;
3135 count = 0;
3136 base = NULL;
3139 NtClose( mapping );
3140 if (status != STATUS_SUCCESS) return status;
3141
3143 if (status == STATUS_SUCCESS)
3144 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
3145
3147 return status;
3148}
3149
3150/* try to load the .manifest file associated to the file */
3153{
3154 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3155 WCHAR *buffer;
3158 HANDLE file;
3160
3161 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3162
3163 TRACE( "looking for manifest associated with %S id %lu\n", filename, resid );
3164
3165 if (module) /* use the module filename */
3166 {
3168
3169 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3170 {