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