ReactOS 0.4.15-dev-6657-ged9973f
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
17#include <rtl.h>
18#include <ntstrsafe.h>
19#include <compat_undoc.h>
20
21#define NDEBUG
22#include <debug.h>
23
24#include <wine/unicode.h>
25
27
28#define ACTCTX_FLAGS_ALL (\
29 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
30 ACTCTX_FLAG_LANGID_VALID |\
31 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
32 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
33 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
34 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
35 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
36 ACTCTX_FLAG_HMODULE_VALID )
37
38#define STRSECTION_MAGIC 0x64487353 /* dHsS */
39#define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
40
41#define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
42
43#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
44#define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
45
46#define MAX_NAMESPACES 64
47
48typedef struct
49{
50 const WCHAR *ptr;
51 unsigned int len;
52} xmlstr_t;
53
55{
58 int ns_pos;
59};
60
62{
65};
66
67typedef struct
68{
69 const WCHAR *ptr;
70 const WCHAR *end;
71 struct xml_attr namespaces[MAX_NAMESPACES];
72 int ns_pos;
74} xmlbuf_t;
75
77{
80};
81
83{
88};
89
91{
100};
101
103{
104 DWORD magic;
105 ULONG size;
106 DWORD unk1[3];
107 ULONG count;
109 DWORD unk2[2];
112};
113
114struct string_index
115{
116 ULONG hash; /* key string hash */
119 ULONG data_offset; /* redirect data offset */
122};
123
125{
126 DWORD magic;
127 ULONG size;
128 DWORD unk[3];
129 ULONG count;
131 DWORD unk2;
134};
135
136struct guid_index
137{
138 GUID guid;
142};
143
145{
146 ULONG size;
147 DWORD res;
149 ULONG name_offset; /* versioned name offset */
151 ULONG module_offset;/* container name offset */
152};
153
154struct dllredirect_data
155{
156 ULONG size;
157 ULONG unk;
158 DWORD res[3];
159};
160
162{
163 ULONG size;
164 DWORD res;
168 WORD flags;
173};
174
176{
183
185{
192
194{
195 ULONG size;
196 BYTE res;
198 BYTE res1[2];
199 DWORD model;
200 GUID clsid;
201 GUID alias;
202 GUID clsid2;
203 GUID tlbid;
215};
216
218{
220 BaseIface = 2
222
224{
225 ULONG size;
226 DWORD mask;
227 GUID iid;
229 GUID tlbid;
230 GUID base;
233};
234
236{
237 ULONG size;
238 DWORD res;
239 GUID clsid;
244};
245
246struct clrclass_data
247{
248 ULONG size;
249 DWORD res[2];
256 DWORD res2[2];
257};
258
260{
261 ULONG size;
264};
265
266/*
267
268 Sections structure.
269
270 Sections are accessible by string or guid key, that defines two types of sections.
271 All sections of each type have same magic value and header structure, index
272 data could be of two possible types too. So every string based section uses
273 the same index format, same applies to guid sections - they share same guid index
274 format.
275
276 - window class redirection section is a plain buffer with following format:
277
278 <section header>
279 <index[]>
280 <data[]> --- <original name>
281 <redirect data>
282 <versioned name>
283 <module name>
284
285 Header is fixed length structure - struct strsection_header,
286 contains redirected classes count;
287
288 Index is an array of fixed length index records, each record is
289 struct string_index.
290
291 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
292
293 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
294 others are relative to section itself.
295
296 - dll redirect section format:
297
298 <section header>
299 <index[]>
300 <data[]> --- <dll name>
301 <data>
302
303 This section doesn't seem to carry any payload data except dll names.
304
305 - typelib section format:
306
307 <section header>
308 <module names[]>
309 <index[]>
310 <data[]> --- <data>
311 <helpstring>
312
313 Header is fixed length, index is an array of fixed length 'struct guid_index'.
314 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
315 4-bytes aligned as a whole.
316
317 Module name offsets are relative to section, helpstring offset is relative to data
318 structure itself.
319
320 - comclass section format:
321
322 <section header>
323 <module names[]>
324 <index[]>
325 <data[]> --- <data> --- <data>
326 <progid> <clrdata>
327 <name>
328 <version>
329 <progid>
330
331 This section uses two index records per comclass, one entry contains original guid
332 as specified by context, another one has a generated guid. Index and strings handling
333 is similar to typelib sections.
334
335 For CLR classes additional data is stored after main COM class data, it contains
336 class name and runtime version string, see 'struct clrclass_data'.
337
338 Module name offsets are relative to section, progid offset is relative to data
339 structure itself.
340
341 - COM interface section format:
342
343 <section header>
344 <index[]>
345 <data[]> --- <data>
346 <name>
347
348 Interface section contains data for proxy/stubs and external proxy/stubs. External
349 ones are defined at assembly level, so this section has no module information.
350 All records are indexed with 'iid' value from manifest. There an exception for
351 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
352 redirect data, but index is still 'iid' from manifest.
353
354 Interface name offset is relative to data structure itself.
355
356 - CLR surrogates section format:
357
358 <section header>
359 <index[]>
360 <data[]> --- <data>
361 <name>
362 <version>
363
364 There's nothing special about this section, same way to store strings is used,
365 no modules part as it belongs to assembly level, not a file.
366
367 - ProgID section format:
368
369 <section header>
370 <guids[]>
371 <index[]>
372 <data[]> --- <progid>
373 <data>
374
375 This sections uses generated alias guids from COM server section. This way
376 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
377 is stored too, aligned.
378*/
379
381{
383 unsigned int num;
384 unsigned int allocated;
385};
386
387struct entity
388{
390 union
391 {
392 struct
393 {
400 struct
401 {
403 WCHAR *tlbid;
405 WCHAR *name; /* clrClass: class name */
406 WCHAR *version; /* clrClass: CLR runtime version */
415 struct {
419 WCHAR *name;
420 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
424 struct
425 {
426 WCHAR *name;
428 } class;
429 struct
430 {
431 WCHAR *name;
432 WCHAR *clsid;
433 WCHAR *version;
435 struct
436 {
437 WCHAR *name;
441 } u;
442};
443
445{
446 struct entity *base;
447 unsigned int num;
448 unsigned int allocated;
449};
450
452{
456};
457
459{
463};
464
465struct assembly
466{
473 unsigned int num_dlls;
474 unsigned int allocated_dlls;
476 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
478 ACTCTX_REQUESTED_RUN_LEVEL run_level;
480};
481
483{
492
494{
499
501{
506
508{
512 PACTIVATION_CONTEXT_DATA ActivationContextData;
524 unsigned int num_assemblies;
526 /* section data */
536
538{
541 unsigned int num_dependencies;
543};
544
546
547#ifdef __i386__
548static const WCHAR current_archW[] = {'x','8','6',0};
549#elif defined __x86_64__
550static const WCHAR current_archW[] = {'a','m','d','6','4',0};
551#elif defined __arm__
552static const WCHAR current_archW[] = {'a','r','m',0};
553#elif defined __aarch64__
554static const WCHAR current_archW[] = {'a','r','m','6','4',0};
555#else
556static const WCHAR current_archW[] = {'n','o','n','e',0};
557#endif
558
559static 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};
560static 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};
561static 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};
562
564{
568
569VOID
570NTAPI
572 IN ULONG FailureCode)
573{
574 EXCEPTION_RECORD ExceptionRecord;
575
576 /* Fatal SxS exception header */
577 ExceptionRecord.ExceptionRecord = NULL;
578 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
580
581 /* With SxS-specific information plus the context itself */
582 ExceptionRecord.ExceptionInformation[0] = 1;
583 ExceptionRecord.ExceptionInformation[1] = FailureCode;
584 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
585 ExceptionRecord.NumberParameters = 3;
586
587 /* Raise it */
588 RtlRaiseException(&ExceptionRecord);
589}
590
592VOID
594{
596
597 /* Get the caller-opaque header */
598 pActual = CONTAINING_RECORD(ActCtx,
600 ActivationContext);
601
602 /* Check if the header matches as expected */
603 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
604 {
605 /* Nope, print out a warning, assert, and then throw an exception */
606 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
607 " This means someone stepped on the allocation, or someone is using a\n"
608 " deallocated activation context\n",
610 pActual->MagicMarker,
611 ActCtx);
614 }
615}
616
617static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
618static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
619static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
620static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
621static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
622static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
623static 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};
624static 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};
625static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
626static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
627static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
628static const WCHAR fileW[] = {'f','i','l','e',0};
629static const WCHAR hashW[] = {'h','a','s','h',0};
630static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
631static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
632static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
633static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
634
635static const WCHAR clsidW[] = {'c','l','s','i','d',0};
636static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
637static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
638static const WCHAR iidW[] = {'i','i','d',0};
639static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
640static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
641static const WCHAR g_nameW[] = {'n','a','m','e',0};
642static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
643static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
644static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
645static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
646static 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};
647static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
648static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
649static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
650static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
651static const WCHAR typeW[] = {'t','y','p','e',0};
652static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
653static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
654static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
655static const WCHAR yesW[] = {'y','e','s',0};
656static const WCHAR noW[] = {'n','o',0};
657static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
658static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
659static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
660static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
661static const WCHAR flagsW[] = {'f','l','a','g','s',0};
662static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
663static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
664static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
665static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
666static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
667static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
668static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
669static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
670static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
671static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
672static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
673
674static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
675static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
676static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
677static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
678static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
679static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
680static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
681static 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};
682static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
683static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
684static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
685static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
686static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
687static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
688static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
689static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
690static 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};
691static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
692static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
693static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
694static 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};
695static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
696
697static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
698static 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};
699static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
700static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
701static const WCHAR IdW[] = {'I','d',0};
702static 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};
703static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
704static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
705static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
706static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
707static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
708static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
709static 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};
710static 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};
711static 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};
712static 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};
713static 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};
714static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
715static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
716static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
717static 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};
718static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
719static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
720static 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};
721static 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};
722
724{
725 const WCHAR *name;
726 OLEMISC value;
727};
728
729static const struct olemisc_entry olemisc_values[] =
730{
731 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
732 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
733 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
734 { alignableW, OLEMISC_ALIGNABLE },
735 { alwaysrunW, OLEMISC_ALWAYSRUN },
736 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
737 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
738 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
739 { imemodeW, OLEMISC_IMEMODE },
740 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
741 { insideoutW, OLEMISC_INSIDEOUT },
742 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
743 { islinkobjectW, OLEMISC_ISLINKOBJECT },
744 { nouiactivateW, OLEMISC_NOUIACTIVATE },
745 { onlyiconicW, OLEMISC_ONLYICONIC },
746 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
747 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
748 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
749 { simpleframeW, OLEMISC_SIMPLEFRAME },
750 { staticW, OLEMISC_STATIC },
751 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
752 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
753};
754
755static const WCHAR g_xmlW[] = {'?','x','m','l',0};
756static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
757static const WCHAR manifestv2W[] = {'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};
758static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
759
760static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
761static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
762static const WCHAR wildcardW[] = {'*',0};
763
767
768static WCHAR *strdupW(const WCHAR* str)
769{
770 WCHAR* ptr;
771
772 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
773 return NULL;
774 return strcpyW(ptr, str);
775}
776
778{
779 WCHAR *strW;
780
781 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
782 {
783 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
784 strW[str->len] = 0;
785 }
786 return strW;
787}
788
789static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
790{
791 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
792}
793
794static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
795{
796 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
797}
798
799static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
800{
801 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
802 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
803}
804
805static inline BOOL xml_attr_cmp(const struct xml_attr* attr, const WCHAR *str)
806{
807 return xmlstr_cmp(&attr->name, str);
808}
809
810static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
811{
812 return (elem1->name.len == elem2->name.len &&
813 elem1->ns.len == elem2->ns.len &&
814 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
815 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
816}
817
818static inline BOOL xml_elem_cmp(const struct xml_elem* elem, const WCHAR *str, const WCHAR *namespace)
819{
820 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
821 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
822 if (!wcscmp( namespace, asmv1W ))
823 {
824 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
825 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
826 }
827 else if (!wcscmp( namespace, asmv2W ))
828 {
829 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
830 }
831 return FALSE;
832}
833
834static inline BOOL isxmlspace( WCHAR ch )
835{
836 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
837}
838
840{
841 struct assembly *assembly;
842
843 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx);
844
845 if (actctx->num_assemblies == actctx->allocated_assemblies)
846 {
847 void *ptr;
848 unsigned int new_count;
849 if (actctx->assemblies)
850 {
851 new_count = actctx->allocated_assemblies * 2;
852 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
853 actctx->assemblies, new_count * sizeof(*assembly) );
854 }
855 else
856 {
857 new_count = 4;
858 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
859 }
860 if (!ptr) return NULL;
861 actctx->assemblies = ptr;
862 actctx->allocated_assemblies = new_count;
863 }
864
865 assembly = &actctx->assemblies[actctx->num_assemblies++];
866 assembly->type = at;
867 return assembly;
868}
869
871{
872 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls);
873
875 {
876 void *ptr;
877 unsigned int new_count;
878 if (assembly->dlls)
879 {
880 new_count = assembly->allocated_dlls * 2;
881 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
882 assembly->dlls, new_count * sizeof(*assembly->dlls) );
883 }
884 else
885 {
886 new_count = 4;
887 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
888 }
889 if (!ptr) return NULL;
890 assembly->dlls = ptr;
891 assembly->allocated_dlls = new_count;
892 }
893 return &assembly->dlls[assembly->num_dlls++];
894}
895
896static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
897{
898 void *ptr;
900 {
901 unsigned int new_count = assembly->num_compat_contexts + 1;
902 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
904 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
905 }
906 else
907 {
908 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
909 }
910 if (!ptr) return NULL;
913}
914
916{
917 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
918 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
919 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
920 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
921 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
922}
923
925{
926 struct entity* entity;
927
928 if (array->num == array->allocated)
929 {
930 void *ptr;
931 unsigned int new_count;
932 if (array->base)
933 {
934 new_count = array->allocated * 2;
935 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
936 array->base, new_count * sizeof(*array->base) );
937 }
938 else
939 {
940 new_count = 4;
941 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
942 }
943 if (!ptr) return NULL;
944 array->base = ptr;
945 array->allocated = new_count;
946 }
947 entity = &array->base[array->num++];
948 entity->kind = kind;
949 return entity;
950}
951
953{
954 unsigned int i, j;
955 for (i = 0; i < array->num; i++)
956 {
957 struct entity *entity = &array->base[i];
958 switch (entity->kind)
959 {
960 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
961 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
962 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
963 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
964 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
965 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
966 for (j = 0; j < entity->u.comclass.progids.num; j++)
967 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
968 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
969 break;
970 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
971 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
972 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
973 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
974 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
975 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib);
976 break;
977 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
978 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
979 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
980 break;
981 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
982 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
983 break;
984 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
985 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
986 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
987 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
988 break;
989 default:
990 DPRINT1("Unknown entity kind %u\n", entity->kind);
991 }
992 }
993 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
994}
995
996static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
997{
998 if (!str1) return !str2;
999 return str2 && !strcmpiW( str1, str2 );
1000}
1001
1003 const struct assembly_identity *id2 )
1004{
1005 if (!is_matching_string( id1->name, id2->name )) return FALSE;
1006 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1007 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1008
1009 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
1010 {
1011 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
1012 return FALSE;
1013 }
1014 if (id1->version.major != id2->version.major) return FALSE;
1015 if (id1->version.minor != id2->version.minor) return FALSE;
1016 if (id1->version.build > id2->version.build) return FALSE;
1017 if (id1->version.build == id2->version.build &&
1018 id1->version.revision > id2->version.revision) return FALSE;
1019 return TRUE;
1020}
1021
1023 struct assembly_identity* ai)
1024{
1025 unsigned int i;
1026
1027 /* check if we already have that assembly */
1028
1029 for (i = 0; i < acl->actctx->num_assemblies; i++)
1030 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1031 {
1032 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
1033 ai->name, ai->arch, ai->version.major, ai->version.minor,
1034 ai->version.build, ai->version.revision );
1035 return TRUE;
1036 }
1037
1038 for (i = 0; i < acl->num_dependencies; i++)
1039 if (is_matching_identity( ai, &acl->dependencies[i] ))
1040 {
1041 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
1042 ai->name, ai->arch, ai->version.major, ai->version.minor,
1043 ai->version.build, ai->version.revision );
1044 return TRUE;
1045 }
1046
1048 {
1049 void *ptr;
1050 unsigned int new_count;
1051 if (acl->dependencies)
1052 {
1053 new_count = acl->allocated_dependencies * 2;
1054 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
1055 new_count * sizeof(acl->dependencies[0]));
1056 }
1057 else
1058 {
1059 new_count = 4;
1060 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1061 }
1062 if (!ptr) return FALSE;
1063 acl->dependencies = ptr;
1064 acl->allocated_dependencies = new_count;
1065 }
1066 acl->dependencies[acl->num_dependencies++] = *ai;
1067
1068 return TRUE;
1069}
1070
1071static void free_depend_manifests(struct actctx_loader* acl)
1072{
1073 unsigned int i;
1074 for (i = 0; i < acl->num_dependencies; i++)
1076 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
1077}
1078
1080{
1081 static const WCHAR undW[] = {'_',0};
1082 static const WCHAR noneW[] = {'n','o','n','e',0};
1083 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1084
1085 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1086 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1087 const WCHAR *lang = ai->language ? ai->language : noneW;
1088 const WCHAR *name = ai->name ? ai->name : noneW;
1089 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1090 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1091 WCHAR *ret;
1092
1093 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
1094
1095 strcpyW( ret, arch );
1096 strcatW( ret, undW );
1097 strcatW( ret, name );
1098 strcatW( ret, undW );
1099 strcatW( ret, key );
1100 strcatW( ret, undW );
1102 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1103 strcatW( ret, undW );
1104 strcatW( ret, lang );
1105 strcatW( ret, undW );
1106 strcatW( ret, mskeyW );
1107 return ret;
1108}
1109
1110static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1111{
1112 WCHAR *p = buffer;
1113
1114 if (!str) return;
1115 strcatW( buffer, prefix );
1116 p += strlenW(p);
1117 *p++ = '"';
1118 strcpyW( p, str );
1119 p += strlenW(p);
1120 *p++ = '"';
1121 *p = 0;
1122}
1123
1124static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1125{
1126 static const WCHAR archW[] =
1127 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1128 static const WCHAR public_keyW[] =
1129 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1130 static const WCHAR typeW2[] =
1131 {',','t','y','p','e','=',0};
1132 static const WCHAR versionW2[] =
1133 {',','v','e','r','s','i','o','n','=',0};
1134
1135 WCHAR version[64], *ret;
1136 SIZE_T size = 0;
1137
1139 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1140 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1141 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1142 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1143 if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2;
1144 size += strlenW(versionW2) + strlenW(version) + 2;
1145
1146 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1147 return NULL;
1148
1149 if (ai->name) strcpyW( ret, ai->name );
1150 else *ret = 0;
1151 append_string( ret, archW, ai->arch );
1152 append_string( ret, public_keyW, ai->public_key );
1153 append_string( ret, typeW2, ai->type );
1154 append_string( ret, versionW2, version );
1155 return ret;
1156}
1157
1159{
1162
1163 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1164 _SEH2_TRY
1165 {
1166 if (actctx)
1167 {
1168 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1169 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
1170 }
1171 }
1173 {
1174 DPRINT1("Invalid activation context handle!\n");
1175 }
1176 _SEH2_END;
1177 return ret;
1178}
1179
1181{
1182 InterlockedExchangeAdd( &actctx->RefCount, 1 );
1183}
1184
1186{
1188
1189 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
1190 {
1191 unsigned int i, j;
1192
1193 for (i = 0; i < actctx->num_assemblies; i++)
1194 {
1195 struct assembly *assembly = &actctx->assemblies[i];
1196 for (j = 0; j < assembly->num_dlls; j++)
1197 {
1198 struct dll_redirect *dll = &assembly->dlls[j];
1199 free_entity_array( &dll->entities );
1200 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
1201 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
1202 }
1203 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
1204 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
1205 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
1206 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts );
1209 }
1210 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
1211 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
1212 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
1213 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
1214 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
1215 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
1216 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
1217 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
1218 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
1219 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
1220
1221 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
1222 pActual->MagicMarker = 0;
1223 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
1224 }
1225}
1226
1227static BOOL set_error(xmlbuf_t* xmlbuf)
1228{
1229 xmlbuf->error = TRUE;
1230 return FALSE;
1231}
1232
1233static BOOL is_xmlns_attr(const struct xml_attr *attr)
1234{
1235 const int len = wcslen( xmlnsW );
1236 if (attr->name.len < len) return FALSE;
1237 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1238 return (attr->name.len == len || attr->name.ptr[len] == ':');
1239}
1240
1241static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1242{
1243 const int len = wcslen( xmlnsW );
1244 struct xml_attr *ns;
1245
1246 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1247 {
1248 // FIXME( "too many namespaces in manifest\n" );
1249 set_error( xmlbuf );
1250 return;
1251 }
1252 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1253 ns->value = attr->value;
1254 if (attr->name.len > len)
1255 {
1256 ns->name.ptr = attr->name.ptr + len + 1;
1257 ns->name.len = attr->name.len - len - 1;
1258 }
1259 else ns->name = empty_xmlstr;
1260}
1261
1262static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1263{
1264 int i;
1265
1266 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1267 {
1268 if (xmlbuf->namespaces[i].name.len == name->len &&
1269 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1270 return xmlbuf->namespaces[i].value;
1271 }
1272
1273 return empty_xmlstr;
1274}
1275
1276static BOOL next_xml_attr(xmlbuf_t* xmlbuf, struct xml_attr* attr, BOOL* end)
1277{
1278 const WCHAR* ptr;
1279 WCHAR quote;
1280
1281 if (xmlbuf->error) return FALSE;
1282
1283 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1284 xmlbuf->ptr++;
1285
1286 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1287
1288 if (*xmlbuf->ptr == '/')
1289 {
1290 xmlbuf->ptr++;
1291 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1292 return set_error( xmlbuf );
1293
1294 xmlbuf->ptr++;
1295 *end = TRUE;
1296 return FALSE;
1297 }
1298
1299 if (*xmlbuf->ptr == '>')
1300 {
1301 xmlbuf->ptr++;
1302 return FALSE;
1303 }
1304
1305 ptr = xmlbuf->ptr;
1306 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1307
1308 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1309
1310 attr->name.ptr = xmlbuf->ptr;
1311 attr->name.len = ptr-xmlbuf->ptr;
1312 xmlbuf->ptr = ptr;
1313
1314 /* skip spaces before '=' */
1315 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1316 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1317
1318 /* skip '=' itself */
1319 ptr++;
1320 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1321
1322 /* skip spaces after '=' */
1323 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1324
1325 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1326
1327 quote = *ptr++;
1328 attr->value.ptr = ptr;
1329 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1330
1331 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1332 if (ptr == xmlbuf->end)
1333 {
1334 xmlbuf->ptr = xmlbuf->end;
1335 return set_error( xmlbuf );
1336 }
1337
1338 attr->value.len = ptr - attr->value.ptr;
1339 xmlbuf->ptr = ptr + 1;
1340 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1341
1342 return set_error( xmlbuf );
1343}
1344
1345static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1346{
1347 const WCHAR* ptr = xmlbuf->ptr;
1348
1349 elem->ns = empty_xmlstr;
1350 elem->name.ptr = ptr;
1351 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1352 {
1353 if (*ptr == ':')
1354 {
1355 elem->ns.ptr = elem->name.ptr;
1356 elem->ns.len = ptr - elem->ns.ptr;
1357 elem->name.ptr = ptr + 1;
1358 }
1359 ptr++;
1360 }
1361 elem->name.len = ptr - elem->name.ptr;
1362 xmlbuf->ptr = ptr;
1363}
1364
1365static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1366{
1367 const WCHAR* ptr;
1368 struct xml_attr attr;
1369 xmlbuf_t attr_buf;
1370 BOOL end = FALSE;
1371
1372 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1373
1374 if (xmlbuf->error) return FALSE;
1375
1376 for (;;)
1377 {
1378 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1379 if (ptr == xmlbuf->end)
1380 {
1381 xmlbuf->ptr = xmlbuf->end;
1382 return set_error( xmlbuf );
1383 }
1384 ptr++;
1385 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1386 {
1387 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1388 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1389
1390 if (ptr + 3 > xmlbuf->end)
1391 {
1392 xmlbuf->ptr = xmlbuf->end;
1393 return set_error( xmlbuf );
1394 }
1395 xmlbuf->ptr = ptr + 3;
1396 }
1397 else break;
1398 }
1399
1400 xmlbuf->ptr = ptr;
1401 /* check for element terminating the parent element */
1402 if (ptr < xmlbuf->end && *ptr == '/')
1403 {
1404 xmlbuf->ptr++;
1405 read_xml_elem( xmlbuf, elem );
1406 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1407 if (!xml_name_cmp( elem, parent ))
1408 {
1409 /*ERR( "wrong closing element %s for %s\n",
1410 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));*/
1411 return set_error( xmlbuf );
1412 }
1413 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1414 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1415 return FALSE;
1416 }
1417
1418 read_xml_elem( xmlbuf, elem );
1419
1420 /* parse namespace attributes */
1421 attr_buf = *xmlbuf;
1422 while (next_xml_attr( &attr_buf, &attr, &end ))
1423 {
1424 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1425 }
1426 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1427 elem->ns_pos = xmlbuf->ns_pos;
1428
1429 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1430
1431 return set_error( xmlbuf );
1432}
1433
1435{
1436 /* FIXME: parse attributes */
1437 const WCHAR *ptr;
1438
1439 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1440 {
1441 if (ptr[0] == '?' && ptr[1] == '>')
1442 {
1443 xmlbuf->ptr = ptr + 2;
1444 return TRUE;
1445 }
1446 }
1447 return FALSE;
1448}
1449
1451{
1452 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1453
1454 if (!ptr) return FALSE;
1455
1456 content->ptr = xmlbuf->ptr;
1457 content->len = ptr - xmlbuf->ptr;
1458 xmlbuf->ptr = ptr;
1459
1460 return TRUE;
1461}
1462
1464{
1465 unsigned int ver[4];
1466 unsigned int pos;
1467 const WCHAR *curr;
1468
1469 /* major.minor.build.revision */
1470 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1471 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1472 {
1473 if (*curr >= '0' && *curr <= '9')
1474 {
1475 ver[pos] = ver[pos] * 10 + *curr - '0';
1476 if (ver[pos] >= 0x10000) goto error;
1477 }
1478 else if (*curr == '.')
1479 {
1480 if (++pos >= 4) goto error;
1481 }
1482 else goto error;
1483 }
1484 version->major = ver[0];
1485 version->minor = ver[1];
1486 version->build = ver[2];
1487 version->revision = ver[3];
1488 return TRUE;
1489
1490error:
1491 return FALSE;
1492}
1493
1495{
1496 struct xml_attr attr;
1497
1498 while (next_xml_attr(xmlbuf, &attr, end))
1499 {
1500 // TODO: report error
1501 // if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1502 }
1503}
1504
1505static void parse_expect_end_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1506{
1507 struct xml_elem elem;
1508
1509 if (next_xml_elem(xmlbuf, &elem, parent))
1510 {
1511 // FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1512 set_error( xmlbuf );
1513 }
1514}
1515
1516static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1517{
1518 struct xml_elem elem;
1519 struct xml_attr attr;
1520 BOOL end = FALSE;
1521
1522 while (next_xml_attr(xmlbuf, &attr, &end));
1523 if (end) return;
1524
1525 while (next_xml_elem(xmlbuf, &elem, parent))
1526 parse_unknown_elem(xmlbuf, &elem);
1527}
1528
1530 struct assembly_identity* ai, const struct xml_elem *parent)
1531{
1532 struct xml_attr attr;
1533 BOOL end = FALSE;
1534
1535 while (next_xml_attr(xmlbuf, &attr, &end))
1536 {
1537 if (xml_attr_cmp(&attr, g_nameW))
1538 {
1539 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1540 }
1541 else if (xml_attr_cmp(&attr, typeW))
1542 {
1543 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1544 }
1545 else if (xml_attr_cmp(&attr, versionW))
1546 {
1547 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1548 }
1550 {
1551 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1552 }
1553 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1554 {
1555 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1556 }
1557 else if (xml_attr_cmp(&attr, languageW))
1558 {
1559 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1560 }
1561 }
1562
1563 if (!end) parse_expect_end_elem(xmlbuf, parent);
1564}
1565
1567{
1568 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1569 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1570 static const WCHAR freeW[] = {'F','r','e','e',0};
1571 static const WCHAR bothW[] = {'B','o','t','h',0};
1572
1573 if (value->len == 0) return ThreadingModel_No;
1574 if (xmlstr_cmp(value, apartW))
1576 else if (xmlstr_cmp(value, freeW))
1577 return ThreadingModel_Free;
1578 else if (xmlstr_cmp(value, bothW))
1579 return ThreadingModel_Both;
1580 else if (xmlstr_cmp(value, neutralW))
1582 else
1583 return ThreadingModel_No;
1584};
1585
1586static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1587{
1588 int min, max;
1589
1590 min = 0;
1591 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1592
1593 while (min <= max)
1594 {
1595 int n, c;
1596
1597 n = (min+max)/2;
1598
1600 if (!c && !olemisc_values[n].name[len])
1601 return olemisc_values[n].value;
1602
1603 if (c >= 0)
1604 max = n-1;
1605 else
1606 min = n+1;
1607 }
1608
1609 DPRINT1("unknown flag %S\n", str);
1610 return 0;
1611}
1612
1614{
1615 const WCHAR *str = value->ptr, *start;
1616 DWORD flags = 0;
1617 int i = 0;
1618
1619 /* it's comma separated list of flags */
1620 while (i < value->len)
1621 {
1622 start = str;
1623 while (*str != ',' && (i++ < value->len)) str++;
1624
1626
1627 /* skip separator */
1628 str++;
1629 i++;
1630 }
1631
1632 return flags;
1633}
1634
1636{
1637 struct progids *progids = &entity->u.comclass.progids;
1638
1639 if (progids->allocated == 0)
1640 {
1641 progids->allocated = 4;
1642 if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1643 }
1644
1645 if (progids->allocated == progids->num)
1646 {
1647 WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids,
1648 2 * progids->allocated * sizeof(WCHAR*));
1649 if (!new_progids) return FALSE;
1650 progids->allocated *= 2;
1651 progids->progids = new_progids;
1652 }
1653
1654 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1655 progids->num++;
1656
1657 return TRUE;
1658}
1659
1660static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1661{
1663 BOOL end = FALSE;
1664
1665 parse_expect_no_attr(xmlbuf, &end);
1666 if (end) set_error( xmlbuf );
1667 if (!parse_text_content(xmlbuf, &content)) return;
1668
1669 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1671}
1672
1673static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1674 const struct xml_elem *parent )
1675{
1676 struct xml_elem elem;
1677 struct xml_attr attr;
1678 BOOL end = FALSE;
1679 struct entity* entity;
1680
1681 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1682 {
1683 set_error( xmlbuf );
1684 return;
1685 }
1686
1687 while (next_xml_attr(xmlbuf, &attr, &end))
1688 {
1689 if (xml_attr_cmp(&attr, clsidW))
1690 {
1691 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1692 }
1693 else if (xml_attr_cmp(&attr, progidW))
1694 {
1695 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1696 }
1697 else if (xml_attr_cmp(&attr, tlbidW))
1698 {
1699 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1700 }
1701 else if (xml_attr_cmp(&attr, threadingmodelW))
1702 {
1704 }
1705 else if (xml_attr_cmp(&attr, miscstatusW))
1706 {
1708 }
1710 {
1711 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1712 }
1714 {
1715 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1716 }
1717 else if (xml_attr_cmp(&attr, miscstatusiconW))
1718 {
1719 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1720 }
1722 {
1723 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1724 }
1725 else if (xml_attr_cmp(&attr, descriptionW))
1726 {
1727 /* not stored */
1728 }
1729 }
1730
1732 if (entity->u.comclass.progid)
1734
1735 if (end) return;
1736
1737 while (next_xml_elem(xmlbuf, &elem, parent))
1738 {
1740 {
1742 }
1743 else
1744 {
1745 parse_unknown_elem(xmlbuf, &elem);
1746 }
1747 }
1748
1749 if (entity->u.comclass.progids.num)
1751}
1752
1754{
1755 const WCHAR *curr;
1756 ULONG num = 0;
1757
1758 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1759 {
1760 if (*curr >= '0' && *curr <= '9')
1761 num = num * 10 + *curr - '0';
1762 else
1763 {
1764 // DPRINT1("wrong numeric value %wZ\n", &strU);
1765 return FALSE;
1766 }
1767 }
1768 entity->u.ifaceps.nummethods = num;
1769
1770 return TRUE;
1771}
1772
1773static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1774 struct actctx_loader *acl, WCHAR *clsid )
1775{
1776 struct entity *entity;
1777 WCHAR *str;
1778
1779 if (!clsid) return;
1780
1781 if (!(str = strdupW(clsid)))
1782 {
1783 set_error( xmlbuf );
1784 return;
1785 }
1786
1787 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1788 {
1789 RtlFreeHeap(RtlGetProcessHeap(), 0, str);
1790 set_error( xmlbuf );
1791 return;
1792 }
1793
1794 entity->u.comclass.clsid = str;
1796
1798}
1799
1801 struct actctx_loader *acl, const struct xml_elem *parent )
1802{
1803 WCHAR *psclsid = NULL;
1804 struct entity *entity;
1805 struct xml_attr attr;
1806 BOOL end = FALSE;
1807
1808 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1809 {
1810 set_error( xmlbuf );
1811 return;
1812 }
1813
1814 while (next_xml_attr(xmlbuf, &attr, &end))
1815 {
1816 if (xml_attr_cmp(&attr, iidW))
1817 {
1818 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1819 }
1820 else if (xml_attr_cmp(&attr, g_nameW))
1821 {
1822 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1823 }
1824 else if (xml_attr_cmp(&attr, baseInterfaceW))
1825 {
1826 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1827 entity->u.ifaceps.mask |= BaseIface;
1828 }
1829 else if (xml_attr_cmp(&attr, nummethodsW))
1830 {
1831 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1832 entity->u.ifaceps.mask |= NumMethods;
1833 }
1834 else if (xml_attr_cmp(&attr, tlbidW))
1835 {
1836 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1837 }
1839 {
1840 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1841 }
1842 /* not used */
1843 else if (xml_attr_cmp(&attr, threadingmodelW))
1844 {
1845 }
1846 }
1847
1849 if (!end) parse_expect_end_elem(xmlbuf, parent);
1850
1851 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1852
1853 RtlFreeHeap(RtlGetProcessHeap(), 0, psclsid);
1854}
1855
1857{
1858 WORD *flags = &entity->u.typelib.flags;
1859 const WCHAR *str = value->ptr, *start;
1860 int i = 0;
1861
1862 *flags = 0;
1863
1864 /* it's comma separated list of flags */
1865 while (i < value->len)
1866 {
1867 start = str;
1868 while (*str != ',' && (i++ < value->len)) str++;
1869
1871 *flags |= LIBFLAG_FRESTRICTED;
1872 else if (!strncmpiW(start, controlW, str-start))
1873 *flags |= LIBFLAG_FCONTROL;
1874 else if (!strncmpiW(start, hiddenW, str-start))
1875 *flags |= LIBFLAG_FHIDDEN;
1876 else if (!strncmpiW(start, hasdiskimageW, str-start))
1877 *flags |= LIBFLAG_FHASDISKIMAGE;
1878 else
1879 {
1880 // DPRINT1("unknown flags value %wZ\n", &valueU);
1881 return FALSE;
1882 }
1883
1884 /* skip separator */
1885 str++;
1886 i++;
1887 }
1888
1889 return TRUE;
1890}
1891
1893{
1894 unsigned int ver[2];
1895 unsigned int pos;
1896 const WCHAR *curr;
1897
1898 /* major.minor */
1899 ver[0] = ver[1] = pos = 0;
1900 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1901 {
1902 if (*curr >= '0' && *curr <= '9')
1903 {
1904 ver[pos] = ver[pos] * 10 + *curr - '0';
1905 if (ver[pos] >= 0x10000) goto error;
1906 }
1907 else if (*curr == '.')
1908 {
1909 if (++pos >= 2) goto error;
1910 }
1911 else goto error;
1912 }
1913 entity->u.typelib.major = ver[0];
1914 entity->u.typelib.minor = ver[1];
1915 return TRUE;
1916
1917error:
1918 return FALSE;
1919}
1920
1921static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1922 struct actctx_loader *acl, const struct xml_elem *parent )
1923{
1924 struct xml_attr attr;
1925 BOOL end = FALSE;
1926 struct entity* entity;
1927
1928 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1929 {
1930 set_error( xmlbuf );
1931 return;
1932 }
1933
1934 while (next_xml_attr(xmlbuf, &attr, &end))
1935 {
1936 if (xml_attr_cmp(&attr, tlbidW))
1937 {
1938 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1939 }
1940 else if (xml_attr_cmp(&attr, versionW))
1941 {
1942 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1943 }
1944 else if (xml_attr_cmp(&attr, helpdirW))
1945 {
1946 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1947 }
1948 else if (xml_attr_cmp(&attr, flagsW))
1949 {
1950 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1951 }
1952 }
1953
1955 if (!end) parse_expect_end_elem(xmlbuf, parent);
1956}
1957
1958static inline int aligned_string_len(int len)
1959{
1960 return (len + 3) & ~3;
1961}
1962
1964{
1965 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1966 struct assembly_version *ver = &assembly->id.version;
1967 WCHAR buff[25];
1968
1969 if (!ret) ret = buff;
1970 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1971}
1972
1973static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1974 struct actctx_loader *acl, const struct xml_elem *parent )
1975{
1976 struct xml_elem elem;
1977 struct xml_attr attr;
1979 BOOL end = FALSE;
1980 struct entity* entity;
1981
1982 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1983 {
1984 set_error( xmlbuf );
1985 return;
1986 }
1987 entity->u.class.versioned = TRUE;
1988 while (next_xml_attr(xmlbuf, &attr, &end))
1989 {
1991 {
1992 if (xmlstr_cmpi(&attr.value, noW))
1993 entity->u.class.versioned = FALSE;
1994 else if (!xmlstr_cmpi(&attr.value, yesW))
1995 set_error( xmlbuf );
1996 }
1997 }
1998
1999 if (end) return;
2000
2001 if (!parse_text_content(xmlbuf, &content)) return;
2002 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
2003
2005
2006 while (next_xml_elem(xmlbuf, &elem, parent))
2007 {
2008 parse_unknown_elem(xmlbuf, &elem);
2009 }
2010}
2011
2012static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2013{
2014 struct xml_attr attr;
2015 BOOL end = FALSE;
2016
2017 while (next_xml_attr(xmlbuf, &attr, &end))
2018 {
2020 {
2021 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2022 }
2023 else if (xml_attr_cmp(&attr, newVersionW))
2024 {
2025 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2026 }
2027 }
2028
2029 if (!end) parse_expect_end_elem(xmlbuf, parent);
2030}
2031
2032static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2033{
2034 struct xml_elem elem;
2035 struct xml_attr attr;
2037 BOOL end = FALSE;
2038
2039 while (next_xml_attr(xmlbuf, &attr, &end));
2040
2041 if (end) return;
2042 if (!parse_text_content(xmlbuf, &content)) return;
2043
2044 while (next_xml_elem(xmlbuf, &elem, parent))
2045 {
2046 parse_unknown_elem(xmlbuf, &elem);
2047 }
2048}
2049
2051 struct assembly* assembly,
2052 struct actctx_loader* acl,
2053 const struct xml_elem *parent)
2054{
2055 struct xml_attr attr;
2056 BOOL end = FALSE;
2057 struct entity* entity;
2058
2059 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2060 {
2061 set_error( xmlbuf );
2062 return;
2063 }
2064
2065 while (next_xml_attr(xmlbuf, &attr, &end))
2066 {
2067 if (xml_attr_cmp(&attr, iidW))
2068 {
2069 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2070 }
2071 else if (xml_attr_cmp(&attr, g_nameW))
2072 {
2073 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2074 }
2075 else if (xml_attr_cmp(&attr, baseInterfaceW))
2076 {
2077 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2078 entity->u.ifaceps.mask |= BaseIface;
2079 }
2080 else if (xml_attr_cmp(&attr, nummethodsW))
2081 {
2082 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2083 entity->u.ifaceps.mask |= NumMethods;
2084 }
2086 {
2087 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2088 }
2089 else if (xml_attr_cmp(&attr, tlbidW))
2090 {
2091 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2092 }
2093 }
2094
2096 if (!end) parse_expect_end_elem(xmlbuf, parent);
2097}
2098
2099static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2100 struct actctx_loader *acl, const struct xml_elem *parent )
2101
2102{
2103 struct xml_elem elem;
2104 struct xml_attr attr;
2105 BOOL end = FALSE;
2106 struct entity* entity;
2107
2108 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2109 {
2110 set_error( xmlbuf );
2111 return;
2112 }
2113
2114 while (next_xml_attr(xmlbuf, &attr, &end))
2115 {
2116 if (xml_attr_cmp(&attr, g_nameW))
2117 {
2118 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2119 }
2120 else if (xml_attr_cmp(&attr, clsidW))
2121 {
2122 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2123 }
2124 else if (xml_attr_cmp(&attr, progidW))
2125 {
2126 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2127 }
2128 else if (xml_attr_cmp(&attr, tlbidW))
2129 {
2130 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2131 }
2132 else if (xml_attr_cmp(&attr, threadingmodelW))
2133 {
2135 }
2136 else if (xml_attr_cmp(&attr, runtimeVersionW))
2137 {
2138 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2139 }
2140 }
2141
2143 if (entity->u.comclass.progid)
2145 if (end) return;
2146
2147 while (next_xml_elem(xmlbuf, &elem, parent))
2148 {
2150 {
2152 }
2153 else
2154 {
2155 parse_unknown_elem(xmlbuf, &elem);
2156 }
2157 }
2158
2159 if (entity->u.comclass.progids.num)
2161}
2162
2164 struct actctx_loader *acl, const struct xml_elem *parent )
2165{
2166 struct xml_attr attr;
2167 BOOL end = FALSE;
2168 struct entity* entity;
2169
2170 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2171 {
2172 set_error( xmlbuf );
2173 return;
2174 }
2175
2176 while (next_xml_attr(xmlbuf, &attr, &end))
2177 {
2178 if (xml_attr_cmp(&attr, g_nameW))
2179 {
2180 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2181 }
2182 else if (xml_attr_cmp(&attr, clsidW))
2183 {
2184 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2185 }
2186 else if (xml_attr_cmp(&attr, runtimeVersionW))
2187 {
2188 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2189 }
2190 }
2191
2193 if (!end) parse_expect_end_elem(xmlbuf, parent);
2194}
2195
2196static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2197 const struct xml_elem *parent, BOOL optional )
2198{
2199 struct xml_elem elem;
2200 struct xml_attr attr;
2201 struct assembly_identity ai;
2202 BOOL end = FALSE;
2203
2204 memset(&ai, 0, sizeof(ai));
2205 ai.optional = optional;
2206
2207 while (next_xml_attr(xmlbuf, &attr, &end))
2208 {
2209 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2210 static const WCHAR trueW[] = {'t','r','u','e',0};
2211
2212 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2214 }
2215
2216 if (end) return;
2217
2218 while (next_xml_elem(xmlbuf, &elem, parent))
2219 {
2221 {
2222 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2223 /* store the newly found identity for later loading */
2224 if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2225 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2226 }
2228 {
2230 }
2231 else
2232 {
2233 parse_unknown_elem(xmlbuf, &elem);
2234 }
2235 }
2236}
2237
2238static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2239 const struct xml_elem *parent )
2240
2241{
2242 struct xml_elem elem;
2243 struct xml_attr attr;
2245
2246 while (next_xml_attr(xmlbuf, &attr, &end))
2247 {
2249 {
2251 }
2252 }
2253
2254 while (next_xml_elem(xmlbuf, &elem, parent))
2255 {
2257 {
2259 }
2260 else
2261 {
2262 parse_unknown_elem(xmlbuf, &elem);
2263 }
2264 }
2265}
2266
2267static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2268{
2269 BOOL end = FALSE;
2270
2271 parse_expect_no_attr(xmlbuf, &end);
2272 if (!end) parse_expect_end_elem(xmlbuf, parent);
2273}
2274
2275static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2276{
2277 BOOL end = FALSE;
2278
2279 parse_expect_no_attr(xmlbuf, &end);
2280 if (!end) parse_expect_end_elem(xmlbuf, parent);
2281}
2282
2283static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2284 struct actctx_loader* acl, const struct xml_elem *parent )
2285{
2286 struct xml_elem elem;
2287 struct xml_attr attr;
2288 BOOL end = FALSE;
2289 struct dll_redirect* dll;
2290
2291 if (!(dll = add_dll_redirect(assembly)))
2292 {
2293 set_error( xmlbuf );
2294 return;
2295 }
2296
2297 while (next_xml_attr(xmlbuf, &attr, &end))
2298 {
2299 if (xml_attr_cmp(&attr, g_nameW))
2300 {
2301 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2302 }
2303 else if (xml_attr_cmp(&attr, hashW))
2304 {
2305 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2306 }
2307 else if (xml_attr_cmp(&attr, hashalgW))
2308 {
2309 static const WCHAR sha1W[] = {'S','H','A','1',0};
2310 if (!xmlstr_cmpi(&attr.value, sha1W)) {
2311 //FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2312 }
2313 }
2314 }
2315
2316 if (!dll->name) set_error( xmlbuf );
2317
2319
2320 if (end) return;
2321
2322 while (next_xml_elem(xmlbuf, &elem, parent))
2323 {
2325 {
2326 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2327 }
2329 {
2331 }
2332 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2333 {
2334 parse_unknown_elem(xmlbuf, &elem);
2335 }
2336 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2337 {
2338 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2339 }
2340 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2341 {
2342 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2343 }
2344 else
2345 {
2346 parse_unknown_elem( xmlbuf, &elem );
2347 }
2348 }
2349}
2350
2351static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2352 struct actctx_loader *acl, const struct xml_elem *parent )
2353{
2354 struct xml_attr attr;
2355 BOOL end = FALSE;
2356
2357 while (next_xml_attr(xmlbuf, &attr, &end))
2358 {
2359 if (xml_attr_cmp(&attr, IdW))
2360 {
2361 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2363 GUID compat_id;
2364
2365 str.Buffer = (PWSTR)attr.value.ptr;
2366 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2367 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2368 {
2369 if (!(compat = add_compat_context(assembly)))
2370 {
2371 set_error( xmlbuf );
2372 return;
2373 }
2374 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2375 compat->Id = compat_id;
2376 }
2377 }
2378 }
2379
2380 if (!end) parse_expect_end_elem(xmlbuf, parent);
2381}
2382
2384 struct actctx_loader* acl, const struct xml_elem *parent)
2385{
2386 struct xml_elem elem;
2387
2388 while (next_xml_elem(xmlbuf, &elem, parent))
2389 {
2391 {
2392 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2393 }
2394 else
2395 {
2396 parse_unknown_elem(xmlbuf, &elem);
2397 }
2398 }
2399}
2400
2402 struct actctx_loader* acl, const struct xml_elem *parent)
2403{
2404 struct xml_elem elem;
2405
2406 while (next_xml_elem(xmlbuf, &elem, parent))
2407 {
2409 {
2411 }
2412 else
2413 {
2414 parse_unknown_elem(xmlbuf, &elem);
2415 }
2416 }
2417}
2418
2419static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2420 struct xml_elem *parent )
2421{
2422 struct xml_elem elem;
2423 struct xml_attr attr;
2425 BOOL end = FALSE;
2426 struct entity *entity;
2427
2428 while (next_xml_attr( xmlbuf, &attr, &end ))
2429 {
2430 }
2431
2432 if (end) return;
2433
2434 if (!parse_text_content( xmlbuf, &content )) return;
2435
2436 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2437 if (!entity)
2438 {
2439 set_error( xmlbuf );
2440 return;
2441 }
2442 entity->u.settings.name = xmlstrdupW( &parent->name );
2443 entity->u.settings.value = xmlstrdupW( &content );
2444 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2445
2446 while (next_xml_elem(xmlbuf, &elem, parent))
2447 {
2448 parse_unknown_elem( xmlbuf, &elem );
2449 }
2450}
2451
2453 struct actctx_loader *acl, const struct xml_elem *parent )
2454{
2455 struct xml_elem elem;
2456
2457 while (next_xml_elem( xmlbuf, &elem, parent ))
2458 {
2470 {
2471 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2472 }
2473 else
2474 {
2475 parse_unknown_elem( xmlbuf, &elem );
2476 }
2477 }
2478}
2479
2480static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2481 struct actctx_loader *acl, const struct xml_elem *parent )
2482{
2483 struct xml_elem elem;
2484
2485 while (next_xml_elem( xmlbuf, &elem, parent ))
2486 {
2488 {
2489 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2490 }
2491 else
2492 {
2493 parse_unknown_elem( xmlbuf, &elem );
2494 }
2495 }
2496}
2497
2499 struct actctx_loader *acl, const struct xml_elem *parent )
2500{
2501 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2502 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2503 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};
2504 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2505 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2506 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2507 static const WCHAR trueW[] = {'t','r','u','e',0};
2508
2509 struct xml_elem elem;
2510 struct xml_attr attr;
2511 BOOL end = FALSE;
2512
2513 /* Multiple requestedExecutionLevel elements are not supported. */
2514 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2515
2516 while (next_xml_attr(xmlbuf, &attr, &end))
2517 {
2518 if (xml_attr_cmp(&attr, levelW))
2519 {
2520 if (xmlstr_cmpi(&attr.value, asInvokerW))
2521 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2522 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2523 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2524 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2525 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2526 }
2527 else if (xml_attr_cmp(&attr, uiAccessW))
2528 {
2531 else if (xmlstr_cmpi(&attr.value, trueW))
2533 }
2534 }
2535
2536 if (end) return;
2537
2538 while (next_xml_elem(xmlbuf, &elem, parent))
2539 {
2540 parse_unknown_elem(xmlbuf, &elem);
2541 }
2542}
2543
2545 struct actctx_loader *acl, const struct xml_elem *parent )
2546{
2547 struct xml_elem elem;
2548
2549 while (next_xml_elem(xmlbuf, &elem, parent))
2550 {
2552 {
2554 }
2555 else
2556 {
2557 parse_unknown_elem(xmlbuf, &elem);
2558 }
2559 }
2560}
2561
2562static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
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 {
2570 {
2572 }
2573 else
2574 {
2575 parse_unknown_elem(xmlbuf, &elem);
2576 }
2577 }
2578}
2579
2580static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2581 struct actctx_loader *acl, const struct xml_elem *parent )
2582{
2583 struct xml_elem elem;
2584
2585 while (next_xml_elem(xmlbuf, &elem, parent))
2586 {
2588 {
2589 parse_security_elem(xmlbuf, assembly, acl, &elem);
2590 }
2591 else
2592 {
2593 parse_unknown_elem(xmlbuf, &elem);
2594 }
2595 }
2596}
2597
2598static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2599 struct actctx_loader* acl, const struct xml_elem *parent,
2600 struct assembly_identity* expected_ai)
2601{
2602 struct xml_elem elem;
2603 struct xml_attr attr;
2604 BOOL end = FALSE, version = FALSE;
2605
2606 while (next_xml_attr(xmlbuf, &attr, &end))
2607 {
2609 {
2610 static const WCHAR v10W[] = {'1','.','0',0};
2611 if (!xmlstr_cmp(&attr.value, v10W))
2612 {
2613 break;
2614 }
2615 version = TRUE;
2616 }
2617 }
2618
2619 if (end || !version)
2620 {
2621 set_error( xmlbuf );
2622 return;
2623 }
2624
2625 while (next_xml_elem(xmlbuf, &elem, parent))
2626 {
2628 {
2629 parse_noinherit_elem(xmlbuf, &elem);
2631 }
2633 {
2635 }
2636 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2637 {
2638 parse_description_elem(xmlbuf, &elem);
2639 }
2641 {
2643 }
2644 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2645 {
2646 parse_dependency_elem(xmlbuf, acl, &elem);
2647 }
2648 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2649 {
2650 parse_file_elem(xmlbuf, assembly, acl, &elem);
2651 }
2652 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2653 {
2654 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2655 }
2657 {
2658 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2659 }
2660 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2661 {
2662 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2663 }
2665 {
2667
2668 if (!xmlbuf->error && expected_ai)
2669 {
2670 /* FIXME: more tests */
2672 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2673 {
2674 set_error( xmlbuf );
2675 }
2676 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2677 (assembly->id.version.major != expected_ai->version.major ||
2678 assembly->id.version.minor != expected_ai->version.minor ||
2679 assembly->id.version.build < expected_ai->version.build ||
2680 (assembly->id.version.build == expected_ai->version.build &&
2681 assembly->id.version.revision < expected_ai->version.revision)))
2682 {
2683 set_error( xmlbuf );
2684 }
2685 }
2686 }
2688 {
2689 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2690 }
2691 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2692 {
2693 parse_application_elem(xmlbuf, assembly, acl, &elem);
2694 }
2695 else
2696 {
2697 parse_unknown_elem(xmlbuf, &elem);
2698 }
2699 }
2700
2703 {
2704 set_error( xmlbuf );
2705 }
2706}
2707
2709 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2710{
2711 struct xml_elem elem;
2712 struct xml_elem parent = {0};
2713
2714 xmlbuf->error = FALSE;
2715 xmlbuf->ns_pos = 0;
2716
2717 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2718
2719 if (xmlstr_cmp(&elem.name, g_xmlW) &&
2720 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2722
2724 {
2726 }
2727
2728 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2729 if (xmlbuf->error)
2730 {
2732 }
2733
2734 if (next_xml_elem(xmlbuf, &elem, &parent))
2735 {
2737 }
2738
2739 if (xmlbuf->ptr != xmlbuf->end)
2740 {
2742 }
2743 return STATUS_SUCCESS;
2744}
2745
2748 const void *buffer, SIZE_T size )
2749{
2750 xmlbuf_t xmlbuf;
2752 struct assembly *assembly;
2753 int unicode_tests;
2754
2755 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
2756
2759
2761 return STATUS_NO_MEMORY;
2762
2763 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2764 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2765 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2766
2768 if (RtlIsTextUnicode(buffer, size, &unicode_tests ))
2769 {
2770 xmlbuf.ptr = buffer;
2771 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2772 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2773 }
2774 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2775 {
2776 const WCHAR *buf = buffer;
2777 WCHAR *new_buff;
2778 unsigned int i;
2779
2780 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
2781 return STATUS_NO_MEMORY;
2782 for (i = 0; i < size / sizeof(WCHAR); i++)
2783 new_buff[i] = RtlUshortByteSwap( buf[i] );
2784 xmlbuf.ptr = new_buff;
2785 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2786 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2787 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
2788 }
2789 else
2790 {
2791 /* TODO: this doesn't handle arbitrary encodings */
2792 WCHAR *new_buff;
2793 ULONG sizeU;
2794
2796 if (!NT_SUCCESS(status))
2797 {
2798 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status);
2800 }
2801
2802 new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU);
2803 if (!new_buff)
2804 return STATUS_NO_MEMORY;
2805
2806 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size);
2807 if (!NT_SUCCESS(status))
2808 {
2809 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status);
2811 }
2812
2813 xmlbuf.ptr = new_buff;
2814 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR);
2815 status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf);
2816 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff);
2817 }
2818 return status;
2819}
2820
2822{
2825
2826 attr.Length = sizeof(attr);
2827 attr.RootDirectory = 0;
2828 attr.Attributes = OBJ_CASE_INSENSITIVE;
2829 attr.ObjectName = name;
2830 attr.SecurityDescriptor = NULL;
2831 attr.SecurityQualityOfService = NULL;
2833}
2834
2836{
2840
2843 if (status == STATUS_SUCCESS)
2844 {
2845 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2846 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2847 {
2848 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2849 str->Length = pldr->FullDllName.Length;
2850 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2851 }
2852 else status = STATUS_NO_MEMORY;
2853 }
2855 return status;
2856}
2857
2860 HANDLE hModule, LPCWSTR resname, ULONG lang )
2861{
2866 void *ptr;
2867
2868 //DPRINT( "looking for res %s in module %p %s\n", resname,
2869 // hModule, filename );
2870 DPRINT("get_manifest_in_module %p\n", hModule);
2871
2872#if 0
2873 if (TRACE_ON(actctx))
2874 {
2875 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2876 {
2877 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2878 hModule, debugstr_w(nameW.Buffer) );
2880 }
2881 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
2883 }
2884#endif
2885
2886 if (!resname) return STATUS_INVALID_PARAMETER;
2887
2888 info.Type = (ULONG_PTR)RT_MANIFEST;
2889 info.Language = lang;
2890 if (!((ULONG_PTR)resname >> 16))
2891 {
2892 info.Name = (ULONG_PTR)resname;
2894 }
2895 else if (resname[0] == '#')
2896 {
2897 ULONG value;
2898 RtlInitUnicodeString(&nameW, resname + 1);
2901 info.Name = value;
2903 }
2904 else
2905 {
2906 RtlCreateUnicodeString(&nameW, resname);
2908 info.Name = (ULONG_PTR)nameW.Buffer;
2911 }
2913
2914 if (status == STATUS_SUCCESS)
2915 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2916
2917 return status;
2918}
2919
2921 LPCWSTR name, void *root,
2922 int want_dir );
2923
2925 void *root, int want_dir );
2926
2927
2929 void *root, int want_dir )
2930{
2932 int pos;
2933
2934 for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
2935 {
2936 if (!entry[pos].DataIsDirectory == !want_dir)
2937 return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
2938 }
2939 return NULL;
2940}
2941
2942
2946{
2947 ULONG size;
2948 PVOID root, ptr;
2949 IMAGE_RESOURCE_DIRECTORY *resdirptr;
2952
2955 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND;
2956 resdirptr = root;
2957
2958 if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1)))
2960
2961 resdirptr = ptr;
2962 if (!(ptr = find_first_id_entry(resdirptr, root, 1)))
2964
2965 resdirptr = ptr;
2966 if (!(ptr = find_first_entry(resdirptr, root, 0)))
2968
2969 entry = ptr;
2971
2972 if (status == STATUS_SUCCESS)
2973 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2974
2975 return status;
2976}
2977
2978
2981 HANDLE file, LPCWSTR resname, ULONG lang )
2982{
2988 SIZE_T count;
2989 void *base;
2990 WCHAR resnameBuf[20];
2991 LPCWSTR resptr = resname;
2992
2993 if ((!((ULONG_PTR)resname >> 16)))
2994 {
2995 sprintfW(resnameBuf, L"#%u", PtrToUlong(resname));
2996 resptr = resnameBuf;
2997 }
2998
2999 DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>");
3000
3001 attr.Length = sizeof(attr);
3002 attr.RootDirectory = 0;
3003 attr.ObjectName = NULL;
3004 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3005 attr.SecurityDescriptor = NULL;
3006 attr.SecurityQualityOfService = NULL;
3007
3008 size.QuadPart = 0;
3011 if (status != STATUS_SUCCESS) return status;
3012
3013 offset.QuadPart = 0;
3014 count = 0;
3015 base = NULL;
3018 NtClose( mapping );
3019 if (status != STATUS_SUCCESS) return status;
3020
3021 if (RtlImageNtHeader(base)) /* we got a PE file */
3022 {
3023 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3024 if (resname)
3025 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3026 else
3028 }
3030
3032 return status;
3033}
3034
3037{
3045 SIZE_T count;
3046 void *base;
3047
3048 DPRINT( "loading manifest file %S\n", filename );
3049
3050 attr.Length = sizeof(attr);
3051 attr.RootDirectory = 0;
3052 attr.ObjectName = NULL;
3053 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3054 attr.SecurityDescriptor = NULL;
3055 attr.SecurityQualityOfService = NULL;
3056
3057 size.QuadPart = 0;
3060
3061 if (status != STATUS_SUCCESS) return status;
3062
3063 offset.QuadPart = 0;
3064 count = 0;
3065 base = NULL;
3068 NtClose( mapping );
3069 if (status != STATUS_SUCCESS) return status;
3070
3071 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
3073
3074 if (status == STATUS_SUCCESS)
3075 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
3076
3078 return status;
3079}
3080
3081/* try to load the .manifest file associated to the file */
3084{
3085 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3086 WCHAR *buffer;
3089 HANDLE file;
3091
3092 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3093
3094 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
3095
3096 if (module) /* use the module filename */
3097 {
3099
3100 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3101 {
3102 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3103 strcatW( name.Buffer, dotManifestW );
3104 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3107 }
3108 if (status) return status;
3109 }
3110 else
3111 {
3112 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
3113 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3114 return STATUS_NO_MEMORY;
3116 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3119 }
3120
3121 if (!open_nt_file( &file, &nameW ))
3122 {
3124 NtClose( file );
3125 }
3128 return status;
3129}
3130
3132{
3133 static const WCHAR lookup_fmtW[] =
3134 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3135 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3136 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3137
3138 WCHAR *lookup, *ret = NULL;
3139 UNICODE_STRING lookup_us;
3141 const WCHAR *lang = ai->language;
3142 unsigned int data_pos = 0, data_len;
3143 char buffer[8192];
3144
3145 if (!(lookup =