4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/port.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
62 typedef enum tagLIBFLAGS
{
63 LIBFLAG_FRESTRICTED
= 0x1,
64 LIBFLAG_FCONTROL
= 0x2,
65 LIBFLAG_FHIDDEN
= 0x4,
66 LIBFLAG_FHASDISKIMAGE
= 0x8
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
73 OLEMISC_ONLYICONIC
= 0x2,
74 OLEMISC_INSERTNOTREPLACE
= 0x4,
76 OLEMISC_CANTLINKINSIDE
= 0x10,
77 OLEMISC_CANLINKBYOLE1
= 0x20,
78 OLEMISC_ISLINKOBJECT
= 0x40,
79 OLEMISC_INSIDEOUT
= 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
82 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
83 OLEMISC_ALWAYSRUN
= 0x800,
84 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
85 OLEMISC_ACTSLIKELABEL
= 0x2000,
86 OLEMISC_NOUIACTIVATE
= 0x4000,
87 OLEMISC_ALIGNABLE
= 0x8000,
88 OLEMISC_SIMPLEFRAME
= 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
90 OLEMISC_IMEMODE
= 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
92 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
96 #define MAX_NAMESPACES 64
121 struct xml_attr namespaces
[MAX_NAMESPACES
];
132 struct assembly_version
140 struct assembly_identity
147 struct assembly_version version
;
152 struct strsection_header
166 ULONG hash
; /* key string hash */
169 ULONG data_offset
; /* redirect data offset */
174 struct guidsection_header
194 struct wndclass_redirect_data
199 ULONG name_offset
; /* versioned name offset */
201 ULONG module_offset
;/* container name offset */
204 struct dllredirect_data
211 struct tlibredirect_data
225 enum comclass_threadingmodel
227 ThreadingModel_Apartment
= 1,
228 ThreadingModel_Free
= 2,
229 ThreadingModel_No
= 3,
230 ThreadingModel_Both
= 4,
231 ThreadingModel_Neutral
= 5
234 enum comclass_miscfields
238 MiscStatusContent
= 4,
239 MiscStatusThumbnail
= 8,
240 MiscStatusDocPrint
= 16
243 struct comclassredirect_data
259 ULONG clrdata_offset
;
261 DWORD miscstatuscontent
;
262 DWORD miscstatusthumbnail
;
263 DWORD miscstatusicon
;
264 DWORD miscstatusdocprint
;
273 struct ifacepsredirect_data
285 struct clrsurrogate_data
290 ULONG version_offset
;
305 ULONG version_offset
;
309 struct progidredirect_data
320 Sections are accessible by string or guid key, that defines two types of sections.
321 All sections of each type have same magic value and header structure, index
322 data could be of two possible types too. So every string based section uses
323 the same index format, same applies to guid sections - they share same guid index
326 - window class redirection section is a plain buffer with following format:
330 <data[]> --- <original name>
335 Header is fixed length structure - struct strsection_header,
336 contains redirected classes count;
338 Index is an array of fixed length index records, each record is
341 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
343 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
344 others are relative to section itself.
346 - dll redirect section format:
350 <data[]> --- <dll name>
353 This section doesn't seem to carry any payload data except dll names.
355 - typelib section format:
363 Header is fixed length, index is an array of fixed length 'struct guid_index'.
364 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
365 4-bytes aligned as a whole.
367 Module name offsets are relative to section, helpstring offset is relative to data
370 - comclass section format:
375 <data[]> --- <data> --- <data>
381 This section uses two index records per comclass, one entry contains original guid
382 as specified by context, another one has a generated guid. Index and strings handling
383 is similar to typelib sections.
385 For CLR classes additional data is stored after main COM class data, it contains
386 class name and runtime version string, see 'struct clrclass_data'.
388 Module name offsets are relative to section, progid offset is relative to data
391 - COM interface section format:
398 Interface section contains data for proxy/stubs and external proxy/stubs. External
399 ones are defined at assembly level, so this section has no module information.
400 All records are indexed with 'iid' value from manifest. There an exception for
401 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
402 redirect data, but index is still 'iid' from manifest.
404 Interface name offset is relative to data structure itself.
406 - CLR surrogates section format:
414 There's nothing special about this section, same way to store strings is used,
415 no modules part as it belongs to assembly level, not a file.
417 - ProgID section format:
422 <data[]> --- <progid>
425 This sections uses generated alias guids from COM server section. This way
426 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
427 is stored too, aligned.
434 unsigned int allocated
;
455 WCHAR
*name
; /* clrClass: class name */
456 WCHAR
*version
; /* clrClass: CLR runtime version */
459 DWORD miscstatuscontent
;
460 DWORD miscstatusthumbnail
;
461 DWORD miscstatusicon
;
462 DWORD miscstatusdocprint
;
463 struct progids progids
;
470 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
498 unsigned int allocated
;
505 struct entity_array entities
;
510 APPLICATION_MANIFEST
,
512 ASSEMBLY_SHARED_MANIFEST
,
517 enum assembly_type type
;
518 struct assembly_identity id
;
519 struct file_info manifest
;
522 struct dll_redirect
*dlls
;
523 unsigned int num_dlls
;
524 unsigned int allocated_dlls
;
525 struct entity_array entities
;
526 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
527 ULONG num_compat_contexts
;
528 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
532 enum context_sections
534 WINDOWCLASS_SECTION
= 1,
535 DLLREDIRECT_SECTION
= 2,
536 TLIBREDIRECT_SECTION
= 4,
537 SERVERREDIRECT_SECTION
= 8,
538 IFACEREDIRECT_SECTION
= 16,
539 CLRSURROGATES_SECTION
= 32,
540 PROGIDREDIRECT_SECTION
= 64
543 typedef struct _ACTIVATION_CONTEXT
547 struct file_info config
;
548 struct file_info appdir
;
549 struct assembly
*assemblies
;
550 unsigned int num_assemblies
;
551 unsigned int allocated_assemblies
;
554 struct strsection_header
*wndclass_section
;
555 struct strsection_header
*dllredirect_section
;
556 struct strsection_header
*progid_section
;
557 struct guidsection_header
*tlib_section
;
558 struct guidsection_header
*comserver_section
;
559 struct guidsection_header
*ifaceps_section
;
560 struct guidsection_header
*clrsurrogate_section
;
561 } ACTIVATION_CONTEXT
;
565 ACTIVATION_CONTEXT
*actctx
;
566 struct assembly_identity
*dependencies
;
567 unsigned int num_dependencies
;
568 unsigned int allocated_dependencies
;
571 static const xmlstr_t empty_xmlstr
;
574 static const WCHAR current_archW
[] = {'x','8','6',0};
575 #elif defined __x86_64__
576 static const WCHAR current_archW
[] = {'a','m','d','6','4',0};
577 #elif defined __arm__
578 static const WCHAR current_archW
[] = {'a','r','m',0};
579 #elif defined __aarch64__
580 static const WCHAR current_archW
[] = {'a','r','m','6','4',0};
582 static const WCHAR current_archW
[] = {'n','o','n','e',0};
585 static const WCHAR asmv1W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
586 static const WCHAR asmv2W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
587 static const WCHAR asmv3W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
588 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
589 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
590 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
591 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
592 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
593 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
594 static const WCHAR comInterfaceExternalProxyStubW
[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
595 static const WCHAR comInterfaceProxyStubW
[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
596 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
597 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
598 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
599 static const WCHAR fileW
[] = {'f','i','l','e',0};
600 static const WCHAR hashW
[] = {'h','a','s','h',0};
601 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
602 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
603 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
604 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
606 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
607 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
608 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
609 static const WCHAR iidW
[] = {'i','i','d',0};
610 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
611 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
612 static const WCHAR nameW
[] = {'n','a','m','e',0};
613 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
614 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
615 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
616 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
617 static const WCHAR processorArchitectureW
[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
618 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
619 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
620 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
621 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
622 static const WCHAR typeW
[] = {'t','y','p','e',0};
623 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
624 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
625 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
626 static const WCHAR yesW
[] = {'y','e','s',0};
627 static const WCHAR noW
[] = {'n','o',0};
628 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
629 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
630 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
631 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
632 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
633 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
634 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
635 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
636 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
637 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
638 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
639 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
640 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
641 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
642 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
643 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
645 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
646 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
647 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
648 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
649 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
650 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
651 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
652 static const WCHAR ignoreactivatewhenvisibleW
[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
653 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
654 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
655 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
656 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
657 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
658 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
659 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
660 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
661 static const WCHAR renderingisdeviceindependentW
[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
662 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
663 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
664 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
665 static const WCHAR supportsmultilevelundoW
[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
666 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
668 static const WCHAR compatibilityW
[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
669 static const WCHAR compatibilityNSW
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
670 static const WCHAR applicationW
[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
671 static const WCHAR supportedOSW
[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
672 static const WCHAR IdW
[] = {'I','d',0};
673 static const WCHAR requestedExecutionLevelW
[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
674 static const WCHAR requestedPrivilegesW
[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
675 static const WCHAR securityW
[] = {'s','e','c','u','r','i','t','y',0};
676 static const WCHAR trustInfoW
[] = {'t','r','u','s','t','I','n','f','o',0};
677 static const WCHAR windowsSettingsW
[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
678 static const WCHAR autoElevateW
[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
679 static const WCHAR disableThemingW
[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
680 static const WCHAR disableWindowFilteringW
[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0};
681 static const WCHAR windowsSettings2005NSW
[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
682 static const WCHAR windowsSettings2011NSW
[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
683 static const WCHAR windowsSettings2016NSW
[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
684 static const WCHAR windowsSettings2017NSW
[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
685 static const WCHAR dpiAwareW
[] = {'d','p','i','A','w','a','r','e',0};
686 static const WCHAR dpiAwarenessW
[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
687 static const WCHAR gdiScalingW
[] = {'g','d','i','S','c','a','l','i','n','g',0};
688 static const WCHAR highResolutionScrollingAwareW
[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
689 static const WCHAR longPathAwareW
[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
690 static const WCHAR magicFutureSettingW
[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
691 static const WCHAR printerDriverIsolationW
[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0};
692 static const WCHAR ultraHighResolutionScrollingAwareW
[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
700 static const struct olemisc_entry olemisc_values
[] =
702 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
703 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
704 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
705 { alignableW
, OLEMISC_ALIGNABLE
},
706 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
707 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
708 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
709 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
710 { imemodeW
, OLEMISC_IMEMODE
},
711 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
712 { insideoutW
, OLEMISC_INSIDEOUT
},
713 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
714 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
715 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
716 { onlyiconicW
, OLEMISC_ONLYICONIC
},
717 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
718 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
719 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
720 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
721 { staticW
, OLEMISC_STATIC
},
722 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
723 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
726 static const WCHAR xmlW
[] = {'?','x','m','l',0};
727 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
728 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
729 static const WCHAR wildcardW
[] = {'*',0};
731 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
732 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
734 static WCHAR
*strdupW(const WCHAR
* str
)
738 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
740 return strcpyW(ptr
, str
);
743 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
747 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
749 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
755 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
757 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
760 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
762 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
765 static BOOL
xml_attr_cmp( const struct xml_attr
*attr
, const WCHAR
*str
)
767 return xmlstr_cmp( &attr
->name
, str
);
770 static BOOL
xml_name_cmp( const struct xml_elem
*elem1
, const struct xml_elem
*elem2
)
772 return (elem1
->name
.len
== elem2
->name
.len
&&
773 elem1
->ns
.len
== elem2
->ns
.len
&&
774 !strncmpW( elem1
->name
.ptr
, elem2
->name
.ptr
, elem1
->name
.len
) &&
775 !strncmpW( elem1
->ns
.ptr
, elem2
->ns
.ptr
, elem1
->ns
.len
));
778 static inline BOOL
xml_elem_cmp(const struct xml_elem
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
780 if (!xmlstr_cmp( &elem
->name
, str
)) return FALSE
;
781 if (xmlstr_cmp( &elem
->ns
, namespace )) return TRUE
;
782 if (!strcmpW( namespace, asmv1W
))
784 if (xmlstr_cmp( &elem
->ns
, asmv2W
)) return TRUE
;
785 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
787 else if (!strcmpW( namespace, asmv2W
))
789 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
794 static inline BOOL
isxmlspace( WCHAR ch
)
796 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
799 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
801 return debugstr_wn(str
->ptr
, str
->len
);
804 static inline const char *debugstr_xml_elem( const struct xml_elem
*elem
)
806 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem
->name
.ptr
, elem
->name
.len
),
807 debugstr_wn( elem
->ns
.ptr
, elem
->ns
.len
));
810 static inline const char *debugstr_xml_attr( const struct xml_attr
*attr
)
812 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr
->name
.ptr
, attr
->name
.len
),
813 debugstr_wn( attr
->value
.ptr
, attr
->value
.len
));
816 static inline const char* debugstr_version(const struct assembly_version
*ver
)
818 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
821 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
823 struct assembly
*assembly
;
825 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
828 unsigned int new_count
;
829 if (actctx
->assemblies
)
831 new_count
= actctx
->allocated_assemblies
* 2;
832 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
833 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
838 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
840 if (!ptr
) return NULL
;
841 actctx
->assemblies
= ptr
;
842 actctx
->allocated_assemblies
= new_count
;
845 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
850 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
852 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
855 unsigned int new_count
;
858 new_count
= assembly
->allocated_dlls
* 2;
859 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
860 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
865 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
867 if (!ptr
) return NULL
;
868 assembly
->dlls
= ptr
;
869 assembly
->allocated_dlls
= new_count
;
871 return &assembly
->dlls
[assembly
->num_dlls
++];
874 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
877 if (assembly
->num_compat_contexts
)
879 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
880 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
881 assembly
->compat_contexts
,
882 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
886 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
888 if (!ptr
) return NULL
;
889 assembly
->compat_contexts
= ptr
;
890 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
893 static void free_assembly_identity(struct assembly_identity
*ai
)
895 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
896 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
897 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
898 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
899 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
902 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
904 struct entity
* entity
;
906 if (array
->num
== array
->allocated
)
909 unsigned int new_count
;
912 new_count
= array
->allocated
* 2;
913 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
914 array
->base
, new_count
* sizeof(*array
->base
) );
919 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
921 if (!ptr
) return NULL
;
923 array
->allocated
= new_count
;
925 entity
= &array
->base
[array
->num
++];
930 static void free_entity_array(struct entity_array
*array
)
933 for (i
= 0; i
< array
->num
; i
++)
935 struct entity
*entity
= &array
->base
[i
];
936 switch (entity
->kind
)
938 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
939 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
940 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
941 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
942 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
943 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
944 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
945 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
946 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
948 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
949 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
950 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
951 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
952 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
953 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
955 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
956 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
957 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
959 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
960 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
962 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
963 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
964 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
965 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
967 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
:
968 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.name
);
969 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.value
);
970 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.ns
);
973 FIXME("Unknown entity kind %d\n", entity
->kind
);
976 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
979 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
981 if (!str1
) return !str2
;
982 return str2
&& !strcmpiW( str1
, str2
);
985 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
986 const struct assembly_identity
*id2
)
988 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
989 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
990 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
992 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
994 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
997 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
998 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
999 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
1000 if (id1
->version
.build
== id2
->version
.build
&&
1001 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
1005 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
1006 struct assembly_identity
* ai
)
1010 /* check if we already have that assembly */
1012 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
1013 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
1015 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1016 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
1017 ai
->version
.build
, ai
->version
.revision
);
1021 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1022 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
1024 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1025 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
1026 ai
->version
.build
, ai
->version
.revision
);
1030 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
1033 unsigned int new_count
;
1034 if (acl
->dependencies
)
1036 new_count
= acl
->allocated_dependencies
* 2;
1037 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
1038 new_count
* sizeof(acl
->dependencies
[0]));
1043 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
1045 if (!ptr
) return FALSE
;
1046 acl
->dependencies
= ptr
;
1047 acl
->allocated_dependencies
= new_count
;
1049 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
1054 static void free_depend_manifests(struct actctx_loader
* acl
)
1057 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1058 free_assembly_identity(&acl
->dependencies
[i
]);
1059 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
1062 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
1064 static const WCHAR undW
[] = {'_',0};
1065 static const WCHAR noneW
[] = {'n','o','n','e',0};
1066 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
1068 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
1069 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1070 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1071 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1072 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
1073 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1076 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
1078 strcpyW( ret
, arch
);
1079 strcatW( ret
, undW
);
1080 strcatW( ret
, name
);
1081 strcatW( ret
, undW
);
1082 strcatW( ret
, key
);
1083 strcatW( ret
, undW
);
1084 sprintfW( ret
+ strlenW(ret
), version_formatW
,
1085 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1086 strcatW( ret
, undW
);
1087 strcatW( ret
, lang
);
1088 strcatW( ret
, undW
);
1089 strcatW( ret
, mskeyW
);
1093 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1098 strcatW( buffer
, prefix
);
1107 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1109 static const WCHAR archW
[] =
1110 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1111 static const WCHAR public_keyW
[] =
1112 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1113 static const WCHAR typeW
[] =
1114 {',','t','y','p','e','=',0};
1115 static const WCHAR versionW
[] =
1116 {',','v','e','r','s','i','o','n','=',0};
1118 WCHAR version
[64], *ret
;
1121 sprintfW( version
, version_formatW
,
1122 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1123 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1124 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1125 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1126 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
1127 size
+= strlenW(versionW
) + strlenW(version
) + 2;
1129 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1132 if (ai
->name
) strcpyW( ret
, ai
->name
);
1134 append_string( ret
, archW
, ai
->arch
);
1135 append_string( ret
, public_keyW
, ai
->public_key
);
1136 append_string( ret
, typeW
, ai
->type
);
1137 append_string( ret
, versionW
, version
);
1141 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1143 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1145 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1148 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1157 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1159 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1162 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1164 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1168 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1170 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1171 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1173 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1174 free_entity_array( &dll
->entities
);
1175 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1176 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1178 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1179 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1180 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1181 RtlFreeHeap( GetProcessHeap(), 0, assembly
->compat_contexts
);
1182 free_entity_array( &assembly
->entities
);
1183 free_assembly_identity(&assembly
->id
);
1185 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1186 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1187 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1188 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1189 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1190 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1191 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1192 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1193 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1194 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1196 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1200 static BOOL
set_error( xmlbuf_t
*xmlbuf
)
1202 xmlbuf
->error
= TRUE
;
1206 static BOOL
is_xmlns_attr( const struct xml_attr
*attr
)
1208 const int len
= strlenW( xmlnsW
);
1209 if (attr
->name
.len
< len
) return FALSE
;
1210 if (strncmpW( attr
->name
.ptr
, xmlnsW
, len
)) return FALSE
;
1211 return (attr
->name
.len
== len
|| attr
->name
.ptr
[len
] == ':');
1214 static void push_xmlns( xmlbuf_t
*xmlbuf
, const struct xml_attr
*attr
)
1216 const int len
= strlenW( xmlnsW
);
1217 struct xml_attr
*ns
;
1219 if (xmlbuf
->ns_pos
== MAX_NAMESPACES
- 1)
1221 FIXME( "too many namespaces in manifest\n" );
1222 set_error( xmlbuf
);
1225 ns
= &xmlbuf
->namespaces
[xmlbuf
->ns_pos
++];
1226 ns
->value
= attr
->value
;
1227 if (attr
->name
.len
> len
)
1229 ns
->name
.ptr
= attr
->name
.ptr
+ len
+ 1;
1230 ns
->name
.len
= attr
->name
.len
- len
- 1;
1232 else ns
->name
= empty_xmlstr
;
1235 static xmlstr_t
find_xmlns( xmlbuf_t
*xmlbuf
, const xmlstr_t
*name
)
1239 for (i
= xmlbuf
->ns_pos
- 1; i
>= 0; i
--)
1241 if (xmlbuf
->namespaces
[i
].name
.len
== name
->len
&&
1242 !strncmpW( xmlbuf
->namespaces
[i
].name
.ptr
, name
->ptr
, name
->len
))
1243 return xmlbuf
->namespaces
[i
].value
;
1245 if (xmlbuf
->ns_pos
) WARN( "namespace %s not found\n", debugstr_xmlstr( name
));
1246 return empty_xmlstr
;
1249 static BOOL
next_xml_attr(xmlbuf_t
*xmlbuf
, struct xml_attr
*attr
, BOOL
*end
)
1253 if (xmlbuf
->error
) return FALSE
;
1255 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1258 if (xmlbuf
->ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1260 if (*xmlbuf
->ptr
== '/')
1263 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1264 return set_error( xmlbuf
);
1271 if (*xmlbuf
->ptr
== '>')
1278 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1280 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1282 attr
->name
.ptr
= xmlbuf
->ptr
;
1283 attr
->name
.len
= ptr
-xmlbuf
->ptr
;
1286 /* skip spaces before '=' */
1287 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1288 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return set_error( xmlbuf
);
1290 /* skip '=' itself */
1292 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1294 /* skip spaces after '=' */
1295 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1297 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return set_error( xmlbuf
);
1299 attr
->value
.ptr
= ++ptr
;
1300 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1302 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1305 xmlbuf
->ptr
= xmlbuf
->end
;
1306 return set_error( xmlbuf
);
1309 attr
->value
.len
= ptr
- attr
->value
.ptr
;
1310 xmlbuf
->ptr
= ptr
+ 1;
1311 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1313 return set_error( xmlbuf
);
1316 static void read_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
)
1318 const WCHAR
* ptr
= xmlbuf
->ptr
;
1320 elem
->ns
= empty_xmlstr
;
1321 elem
->name
.ptr
= ptr
;
1322 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && *ptr
!= '/')
1326 elem
->ns
.ptr
= elem
->name
.ptr
;
1327 elem
->ns
.len
= ptr
- elem
->ns
.ptr
;
1328 elem
->name
.ptr
= ptr
+ 1;
1332 elem
->name
.len
= ptr
- elem
->name
.ptr
;
1336 static BOOL
next_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
, const struct xml_elem
*parent
)
1339 struct xml_attr attr
;
1343 xmlbuf
->ns_pos
= parent
->ns_pos
; /* restore namespace stack to parent state */
1345 if (xmlbuf
->error
) return FALSE
;
1349 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1352 xmlbuf
->ptr
= xmlbuf
->end
;
1353 return set_error( xmlbuf
);
1356 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1358 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1359 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1361 if (ptr
+ 3 > xmlbuf
->end
)
1363 xmlbuf
->ptr
= xmlbuf
->end
;
1364 return set_error( xmlbuf
);
1366 xmlbuf
->ptr
= ptr
+ 3;
1372 /* check for element terminating the parent element */
1373 if (ptr
< xmlbuf
->end
&& *ptr
== '/')
1376 read_xml_elem( xmlbuf
, elem
);
1377 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1378 if (!xml_name_cmp( elem
, parent
))
1380 ERR( "wrong closing element %s for %s\n",
1381 debugstr_xmlstr(&elem
->name
), debugstr_xmlstr(&parent
->name
));
1382 return set_error( xmlbuf
);
1384 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
)) xmlbuf
->ptr
++;
1385 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
++ != '>') return set_error( xmlbuf
);
1389 read_xml_elem( xmlbuf
, elem
);
1391 /* parse namespace attributes */
1393 while (next_xml_attr( &attr_buf
, &attr
, &end
))
1395 if (is_xmlns_attr( &attr
)) push_xmlns( xmlbuf
, &attr
);
1397 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1398 elem
->ns_pos
= xmlbuf
->ns_pos
;
1400 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1402 return set_error( xmlbuf
);
1405 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1407 /* FIXME: parse attributes */
1410 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1412 if (ptr
[0] == '?' && ptr
[1] == '>')
1414 xmlbuf
->ptr
= ptr
+ 2;
1421 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1425 if (xmlbuf
->error
) return FALSE
;
1427 if (!(ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
))) return set_error( xmlbuf
);
1429 content
->ptr
= xmlbuf
->ptr
;
1430 content
->len
= ptr
- xmlbuf
->ptr
;
1436 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1438 unsigned int ver
[4];
1442 /* major.minor.build.revision */
1443 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1444 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1446 if (*curr
>= '0' && *curr
<= '9')
1448 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1449 if (ver
[pos
] >= 0x10000) goto error
;
1451 else if (*curr
== '.')
1453 if (++pos
>= 4) goto error
;
1457 version
->major
= ver
[0];
1458 version
->minor
= ver
[1];
1459 version
->build
= ver
[2];
1460 version
->revision
= ver
[3];
1464 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1468 static void parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1470 struct xml_attr attr
;
1472 while (next_xml_attr(xmlbuf
, &attr
, end
))
1474 if (!is_xmlns_attr( &attr
)) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr
));
1478 static void parse_expect_end_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1480 struct xml_elem elem
;
1482 if (next_xml_elem(xmlbuf
, &elem
, parent
))
1484 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem
) );
1485 set_error( xmlbuf
);
1489 static void parse_unknown_elem(xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1491 struct xml_elem elem
;
1492 struct xml_attr attr
;
1495 while (next_xml_attr(xmlbuf
, &attr
, &end
));
1498 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1499 parse_unknown_elem(xmlbuf
, &elem
);
1502 static void parse_assembly_identity_elem(xmlbuf_t
*xmlbuf
, ACTIVATION_CONTEXT
*actctx
,
1503 struct assembly_identity
* ai
, const struct xml_elem
*parent
)
1505 struct xml_attr attr
;
1508 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1510 if (xml_attr_cmp(&attr
, nameW
))
1512 if (!(ai
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1514 else if (xml_attr_cmp(&attr
, typeW
))
1516 if (!(ai
->type
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1518 else if (xml_attr_cmp(&attr
, versionW
))
1520 if (!parse_version(&attr
.value
, &ai
->version
)) set_error( xmlbuf
);
1522 else if (xml_attr_cmp(&attr
, processorArchitectureW
))
1524 if (!(ai
->arch
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1526 else if (xml_attr_cmp(&attr
, publicKeyTokenW
))
1528 if (!(ai
->public_key
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1530 else if (xml_attr_cmp(&attr
, languageW
))
1532 if (!(ai
->language
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1534 else if (!is_xmlns_attr( &attr
))
1536 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1540 TRACE( "name=%s version=%s arch=%s\n",
1541 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1543 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1546 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1548 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1549 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1550 static const WCHAR freeW
[] = {'F','r','e','e',0};
1551 static const WCHAR bothW
[] = {'B','o','t','h',0};
1553 if (value
->len
== 0) return ThreadingModel_No
;
1554 if (xmlstr_cmp(value
, apartW
))
1555 return ThreadingModel_Apartment
;
1556 else if (xmlstr_cmp(value
, freeW
))
1557 return ThreadingModel_Free
;
1558 else if (xmlstr_cmp(value
, bothW
))
1559 return ThreadingModel_Both
;
1560 else if (xmlstr_cmp(value
, neutralW
))
1561 return ThreadingModel_Neutral
;
1563 return ThreadingModel_No
;
1566 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1571 max
= ARRAY_SIZE(olemisc_values
) - 1;
1579 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1580 if (!c
&& !olemisc_values
[n
].name
[len
])
1581 return olemisc_values
[n
].value
;
1589 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1593 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1595 const WCHAR
*str
= value
->ptr
, *start
;
1599 /* it's comma separated list of flags */
1600 while (i
< value
->len
)
1603 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1605 flags
|= get_olemisc_value(start
, str
-start
);
1607 /* skip separator */
1615 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1617 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1619 if (progids
->allocated
== 0)
1621 progids
->allocated
= 4;
1622 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1625 if (progids
->allocated
== progids
->num
)
1627 WCHAR
**new_progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
,
1628 2 * progids
->allocated
* sizeof(WCHAR
*));
1629 if (!new_progids
) return FALSE
;
1630 progids
->allocated
*= 2;
1631 progids
->progids
= new_progids
;
1634 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1640 static void parse_com_class_progid(xmlbuf_t
*xmlbuf
, struct entity
*entity
, const struct xml_elem
*parent
)
1645 parse_expect_no_attr(xmlbuf
, &end
);
1646 if (end
) set_error( xmlbuf
);
1647 if (!parse_text_content(xmlbuf
, &content
)) return;
1649 if (!com_class_add_progid(&content
, entity
)) set_error( xmlbuf
);
1650 parse_expect_end_elem(xmlbuf
, parent
);
1653 static void parse_com_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
, struct actctx_loader
*acl
,
1654 const struct xml_elem
*parent
)
1656 struct xml_elem elem
;
1657 struct xml_attr attr
;
1659 struct entity
* entity
;
1661 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1663 set_error( xmlbuf
);
1667 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1669 if (xml_attr_cmp(&attr
, clsidW
))
1671 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1673 else if (xml_attr_cmp(&attr
, progidW
))
1675 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1677 else if (xml_attr_cmp(&attr
, tlbidW
))
1679 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1681 else if (xml_attr_cmp(&attr
, threadingmodelW
))
1683 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
1685 else if (xml_attr_cmp(&attr
, miscstatusW
))
1687 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr
.value
);
1689 else if (xml_attr_cmp(&attr
, miscstatuscontentW
))
1691 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr
.value
);
1693 else if (xml_attr_cmp(&attr
, miscstatusthumbnailW
))
1695 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr
.value
);
1697 else if (xml_attr_cmp(&attr
, miscstatusiconW
))
1699 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr
.value
);
1701 else if (xml_attr_cmp(&attr
, miscstatusdocprintW
))
1703 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr
.value
);
1705 else if (xml_attr_cmp(&attr
, descriptionW
))
1709 else if (!is_xmlns_attr( &attr
))
1711 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1715 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1716 if (entity
->u
.comclass
.progid
)
1717 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1721 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1723 if (xml_elem_cmp(&elem
, progidW
, asmv1W
))
1725 parse_com_class_progid(xmlbuf
, entity
, &elem
);
1729 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1730 parse_unknown_elem(xmlbuf
, &elem
);
1734 if (entity
->u
.comclass
.progids
.num
)
1735 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1738 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1743 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1745 if (*curr
>= '0' && *curr
<= '9')
1746 num
= num
* 10 + *curr
- '0';
1749 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1753 entity
->u
.ifaceps
.nummethods
= num
;
1758 static void parse_cominterface_proxy_stub_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1759 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1761 struct xml_attr attr
;
1763 struct entity
* entity
;
1765 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1767 set_error( xmlbuf
);
1771 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1773 if (xml_attr_cmp(&attr
, iidW
))
1775 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1777 else if (xml_attr_cmp(&attr
, nameW
))
1779 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1781 else if (xml_attr_cmp(&attr
, baseInterfaceW
))
1783 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1784 entity
->u
.ifaceps
.mask
|= BaseIface
;
1786 else if (xml_attr_cmp(&attr
, nummethodsW
))
1788 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
1789 entity
->u
.ifaceps
.mask
|= NumMethods
;
1791 else if (xml_attr_cmp(&attr
, tlbidW
))
1793 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1796 else if (xml_attr_cmp(&attr
, proxyStubClsid32W
) || xml_attr_cmp(&attr
, threadingmodelW
))
1799 else if (!is_xmlns_attr( &attr
))
1801 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1805 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1806 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1809 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1811 WORD
*flags
= &entity
->u
.typelib
.flags
;
1812 const WCHAR
*str
= value
->ptr
, *start
;
1817 /* it's comma separated list of flags */
1818 while (i
< value
->len
)
1821 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1823 if (!strncmpiW(start
, restrictedW
, str
-start
))
1824 *flags
|= LIBFLAG_FRESTRICTED
;
1825 else if (!strncmpiW(start
, controlW
, str
-start
))
1826 *flags
|= LIBFLAG_FCONTROL
;
1827 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1828 *flags
|= LIBFLAG_FHIDDEN
;
1829 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1830 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1833 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1837 /* skip separator */
1845 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1847 unsigned int ver
[2];
1852 ver
[0] = ver
[1] = pos
= 0;
1853 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1855 if (*curr
>= '0' && *curr
<= '9')
1857 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1858 if (ver
[pos
] >= 0x10000) goto error
;
1860 else if (*curr
== '.')
1862 if (++pos
>= 2) goto error
;
1866 entity
->u
.typelib
.major
= ver
[0];
1867 entity
->u
.typelib
.minor
= ver
[1];
1871 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1875 static void parse_typelib_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1876 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1878 struct xml_attr attr
;
1880 struct entity
* entity
;
1882 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1884 set_error( xmlbuf
);
1888 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1890 if (xml_attr_cmp(&attr
, tlbidW
))
1892 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1894 else if (xml_attr_cmp(&attr
, versionW
))
1896 if (!parse_typelib_version(&attr
.value
, entity
)) set_error( xmlbuf
);
1898 else if (xml_attr_cmp(&attr
, helpdirW
))
1900 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1902 else if (xml_attr_cmp(&attr
, flagsW
))
1904 if (!parse_typelib_flags(&attr
.value
, entity
)) set_error( xmlbuf
);
1906 else if (!is_xmlns_attr( &attr
))
1908 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1912 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1913 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1916 static inline int aligned_string_len(int len
)
1918 return (len
+ 3) & ~3;
1921 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1923 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1924 struct assembly_version
*ver
= &assembly
->id
.version
;
1927 if (!ret
) ret
= buff
;
1928 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1931 static void parse_window_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1932 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1934 struct xml_elem elem
;
1935 struct xml_attr attr
;
1938 struct entity
* entity
;
1940 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1942 set_error( xmlbuf
);
1945 entity
->u
.class.versioned
= TRUE
;
1946 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1948 if (xml_attr_cmp(&attr
, versionedW
))
1950 if (xmlstr_cmpi(&attr
.value
, noW
))
1951 entity
->u
.class.versioned
= FALSE
;
1952 else if (!xmlstr_cmpi(&attr
.value
, yesW
))
1953 set_error( xmlbuf
);
1955 else if (!is_xmlns_attr( &attr
))
1957 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1963 if (!parse_text_content(xmlbuf
, &content
)) return;
1964 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) set_error( xmlbuf
);
1966 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1968 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1970 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1971 parse_unknown_elem(xmlbuf
, &elem
);
1975 static void parse_binding_redirect_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1977 struct xml_attr attr
;
1980 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1982 if (xml_attr_cmp(&attr
, oldVersionW
))
1984 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1986 else if (xml_attr_cmp(&attr
, newVersionW
))
1988 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1990 else if (!is_xmlns_attr( &attr
))
1992 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1996 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1999 static void parse_description_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2001 struct xml_elem elem
;
2002 struct xml_attr attr
;
2006 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2008 if (!is_xmlns_attr( &attr
)) WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2012 if (!parse_text_content(xmlbuf
, &content
)) return;
2014 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
2016 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2018 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2019 parse_unknown_elem(xmlbuf
, &elem
);
2023 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t
*xmlbuf
,
2024 struct assembly
* assembly
,
2025 struct actctx_loader
* acl
,
2026 const struct xml_elem
*parent
)
2028 struct xml_attr attr
;
2030 struct entity
* entity
;
2032 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
2034 set_error( xmlbuf
);
2038 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2040 if (xml_attr_cmp(&attr
, iidW
))
2042 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2044 else if (xml_attr_cmp(&attr
, nameW
))
2046 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2048 else if (xml_attr_cmp(&attr
, baseInterfaceW
))
2050 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2051 entity
->u
.ifaceps
.mask
|= BaseIface
;
2053 else if (xml_attr_cmp(&attr
, nummethodsW
))
2055 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
2056 entity
->u
.ifaceps
.mask
|= NumMethods
;
2058 else if (xml_attr_cmp(&attr
, proxyStubClsid32W
))
2060 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2062 else if (xml_attr_cmp(&attr
, tlbidW
))
2064 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2066 else if (!is_xmlns_attr( &attr
))
2068 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2072 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2073 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2076 static void parse_clr_class_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2077 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2080 struct xml_elem elem
;
2081 struct xml_attr attr
;
2083 struct entity
* entity
;
2085 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
2087 set_error( xmlbuf
);
2091 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2093 if (xml_attr_cmp(&attr
, nameW
))
2095 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2097 else if (xml_attr_cmp(&attr
, clsidW
))
2099 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2101 else if (xml_attr_cmp(&attr
, progidW
))
2103 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2105 else if (xml_attr_cmp(&attr
, tlbidW
))
2107 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2109 else if (xml_attr_cmp(&attr
, threadingmodelW
))
2111 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
2113 else if (xml_attr_cmp(&attr
, runtimeVersionW
))
2115 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2117 else if (!is_xmlns_attr( &attr
))
2119 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2123 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2124 if (entity
->u
.comclass
.progid
)
2125 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2128 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2130 if (xml_elem_cmp(&elem
, progidW
, asmv1W
))
2132 parse_com_class_progid(xmlbuf
, entity
, &elem
);
2136 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2137 parse_unknown_elem(xmlbuf
, &elem
);
2141 if (entity
->u
.comclass
.progids
.num
)
2142 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2145 static void parse_clr_surrogate_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2146 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2148 struct xml_attr attr
;
2150 struct entity
* entity
;
2152 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)))
2154 set_error( xmlbuf
);
2158 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2160 if (xml_attr_cmp(&attr
, nameW
))
2162 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2164 else if (xml_attr_cmp(&attr
, clsidW
))
2166 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2168 else if (xml_attr_cmp(&attr
, runtimeVersionW
))
2170 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2172 else if (!is_xmlns_attr( &attr
))
2174 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2178 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2179 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2182 static void parse_dependent_assembly_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2183 const struct xml_elem
*parent
, BOOL optional
)
2185 struct xml_elem elem
;
2186 struct xml_attr attr
;
2187 struct assembly_identity ai
;
2190 memset(&ai
, 0, sizeof(ai
));
2191 ai
.optional
= optional
;
2193 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2195 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2196 static const WCHAR trueW
[] = {'t','r','u','e',0};
2198 if (xml_attr_cmp(&attr
, allowDelayedBindingW
))
2199 ai
.delayed
= xmlstr_cmp(&attr
.value
, trueW
);
2200 else if (!is_xmlns_attr( &attr
))
2201 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2206 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2208 if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2210 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
, &elem
);
2211 /* store the newly found identity for later loading */
2212 if (ai
.arch
&& !strcmpW(ai
.arch
, wildcardW
)) ai
.arch
= strdupW( current_archW
);
2213 TRACE( "adding name=%s version=%s arch=%s\n",
2214 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2215 if (!add_dependent_assembly_id(acl
, &ai
)) set_error( xmlbuf
);
2217 else if (xml_elem_cmp(&elem
, bindingRedirectW
, asmv1W
))
2219 parse_binding_redirect_elem(xmlbuf
, &elem
);
2223 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2224 parse_unknown_elem(xmlbuf
, &elem
);
2229 static void parse_dependency_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2230 const struct xml_elem
*parent
)
2233 struct xml_elem elem
;
2234 struct xml_attr attr
;
2235 BOOL end
= FALSE
, optional
= FALSE
;
2237 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2239 if (xml_attr_cmp(&attr
, optionalW
))
2241 optional
= xmlstr_cmpi( &attr
.value
, yesW
);
2242 TRACE("optional=%s\n", debugstr_xmlstr(&attr
.value
));
2244 else if (!is_xmlns_attr( &attr
))
2246 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2250 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2252 if (xml_elem_cmp(&elem
, dependentAssemblyW
, asmv1W
))
2254 parse_dependent_assembly_elem(xmlbuf
, acl
, &elem
, optional
);
2258 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2259 parse_unknown_elem(xmlbuf
, &elem
);
2264 static void parse_noinherit_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2268 parse_expect_no_attr(xmlbuf
, &end
);
2269 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2272 static void parse_noinheritable_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2276 parse_expect_no_attr(xmlbuf
, &end
);
2277 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2280 static void parse_file_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2281 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2283 struct xml_elem elem
;
2284 struct xml_attr attr
;
2286 struct dll_redirect
* dll
;
2288 if (!(dll
= add_dll_redirect(assembly
)))
2290 set_error( xmlbuf
);
2294 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2296 if (xml_attr_cmp(&attr
, nameW
))
2298 if (!(dll
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2299 TRACE("name=%s\n", debugstr_xmlstr(&attr
.value
));
2301 else if (xml_attr_cmp(&attr
, hashW
))
2303 if (!(dll
->hash
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2305 else if (xml_attr_cmp(&attr
, hashalgW
))
2307 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2308 if (!xmlstr_cmpi(&attr
.value
, sha1W
))
2309 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr
.value
));
2311 else if (!is_xmlns_attr( &attr
))
2313 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2317 if (!dll
->name
) set_error( xmlbuf
);
2319 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2323 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2325 if (xml_elem_cmp(&elem
, comClassW
, asmv1W
))
2327 parse_com_class_elem(xmlbuf
, dll
, acl
, &elem
);
2329 else if (xml_elem_cmp(&elem
, comInterfaceProxyStubW
, asmv1W
))
2331 parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
, &elem
);
2333 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2335 WARN("asmv2:hash (undocumented) not supported\n");
2336 parse_unknown_elem(xmlbuf
, &elem
);
2338 else if (xml_elem_cmp(&elem
, typelibW
, asmv1W
))
2340 parse_typelib_elem(xmlbuf
, dll
, acl
, &elem
);
2342 else if (xml_elem_cmp(&elem
, windowClassW
, asmv1W
))
2344 parse_window_class_elem(xmlbuf
, dll
, acl
, &elem
);
2348 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2349 parse_unknown_elem( xmlbuf
, &elem
);
2354 static void parse_supportedos_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2355 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2357 struct xml_attr attr
;
2360 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2362 if (xml_attr_cmp(&attr
, IdW
))
2364 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2368 str
.Buffer
= (PWSTR
)attr
.value
.ptr
;
2369 str
.Length
= str
.MaximumLength
= (USHORT
)attr
.value
.len
* sizeof(WCHAR
);
2370 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2372 if (!(compat
= add_compat_context(assembly
)))
2374 set_error( xmlbuf
);
2377 compat
->Type
= ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2378 compat
->Id
= compat_id
;
2382 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr
.value
));
2385 else if (!is_xmlns_attr( &attr
))
2387 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2391 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2394 static void parse_compatibility_application_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2395 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2397 struct xml_elem elem
;
2399 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2401 if (xml_elem_cmp(&elem
, supportedOSW
, compatibilityNSW
))
2403 parse_supportedos_elem(xmlbuf
, assembly
, acl
, &elem
);
2407 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2408 parse_unknown_elem(xmlbuf
, &elem
);
2413 static void parse_compatibility_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2414 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2416 struct xml_elem elem
;
2418 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2420 if (xml_elem_cmp(&elem
, applicationW
, compatibilityNSW
))
2422 parse_compatibility_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2426 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2427 parse_unknown_elem(xmlbuf
, &elem
);
2432 static void parse_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
,
2433 struct xml_elem
*parent
)
2435 struct xml_elem elem
;
2436 struct xml_attr attr
;
2439 struct entity
*entity
;
2441 while (next_xml_attr( xmlbuf
, &attr
, &end
))
2443 if (!is_xmlns_attr( &attr
)) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr
) );
2448 if (!parse_text_content( xmlbuf
, &content
)) return;
2449 TRACE( "got %s %s\n", debugstr_xmlstr(&parent
->name
), debugstr_xmlstr(&content
) );
2451 entity
= add_entity( &assembly
->entities
, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
);
2454 set_error( xmlbuf
);
2457 entity
->u
.settings
.name
= xmlstrdupW( &parent
->name
);
2458 entity
->u
.settings
.value
= xmlstrdupW( &content
);
2459 entity
->u
.settings
.ns
= xmlstrdupW( &parent
->ns
);
2461 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2463 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2464 parse_unknown_elem( xmlbuf
, &elem
);
2468 static void parse_windows_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2469 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2471 struct xml_elem elem
;
2473 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2475 if (xml_elem_cmp( &elem
, autoElevateW
, windowsSettings2005NSW
) ||
2476 xml_elem_cmp( &elem
, disableThemingW
, windowsSettings2005NSW
) ||
2477 xml_elem_cmp( &elem
, disableWindowFilteringW
, windowsSettings2011NSW
) ||
2478 xml_elem_cmp( &elem
, dpiAwareW
, windowsSettings2005NSW
) ||
2479 xml_elem_cmp( &elem
, dpiAwarenessW
, windowsSettings2016NSW
) ||
2480 xml_elem_cmp( &elem
, gdiScalingW
, windowsSettings2017NSW
) ||
2481 xml_elem_cmp( &elem
, highResolutionScrollingAwareW
, windowsSettings2017NSW
) ||
2482 xml_elem_cmp( &elem
, longPathAwareW
, windowsSettings2016NSW
) ||
2483 xml_elem_cmp( &elem
, magicFutureSettingW
, windowsSettings2017NSW
) ||
2484 xml_elem_cmp( &elem
, printerDriverIsolationW
, windowsSettings2011NSW
) ||
2485 xml_elem_cmp( &elem
, ultraHighResolutionScrollingAwareW
, windowsSettings2017NSW
))
2487 parse_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2491 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2492 parse_unknown_elem( xmlbuf
, &elem
);
2497 static void parse_application_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2498 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2500 struct xml_elem elem
;
2502 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2504 if (xml_elem_cmp( &elem
, windowsSettingsW
, asmv3W
))
2506 parse_windows_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2510 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2511 parse_unknown_elem( xmlbuf
, &elem
);
2516 static void parse_requested_execution_level_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2517 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2519 static const WCHAR levelW
[] = {'l','e','v','e','l',0};
2520 static const WCHAR asInvokerW
[] = {'a','s','I','n','v','o','k','e','r',0};
2521 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};
2522 static const WCHAR highestAvailableW
[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2523 static const WCHAR uiAccessW
[] = {'u','i','A','c','c','e','s','s',0};
2524 static const WCHAR falseW
[] = {'f','a','l','s','e',0};
2525 static const WCHAR trueW
[] = {'t','r','u','e',0};
2527 struct xml_elem elem
;
2528 struct xml_attr attr
;
2531 /* Multiple requestedExecutionLevel elements are not supported. */
2532 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
) set_error( xmlbuf
);
2534 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2536 if (xml_attr_cmp(&attr
, levelW
))
2538 if (xmlstr_cmpi(&attr
.value
, asInvokerW
))
2539 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2540 else if (xmlstr_cmpi(&attr
.value
, highestAvailableW
))
2541 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2542 else if (xmlstr_cmpi(&attr
.value
, requireAdministratorW
))
2543 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2545 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr
.value
));
2547 else if (xml_attr_cmp(&attr
, uiAccessW
))
2549 if (xmlstr_cmpi(&attr
.value
, falseW
))
2550 assembly
->ui_access
= FALSE
;
2551 else if (xmlstr_cmpi(&attr
.value
, trueW
))
2552 assembly
->ui_access
= TRUE
;
2554 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr
.value
));
2556 else if (!is_xmlns_attr( &attr
))
2557 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2562 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2564 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2565 parse_unknown_elem(xmlbuf
, &elem
);
2569 static void parse_requested_privileges_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2570 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2572 struct xml_elem elem
;
2574 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2576 if (xml_elem_cmp(&elem
, requestedExecutionLevelW
, asmv1W
))
2578 parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
, &elem
);
2582 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2583 parse_unknown_elem(xmlbuf
, &elem
);
2588 static void parse_security_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2589 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2591 struct xml_elem elem
;
2593 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2595 if (xml_elem_cmp(&elem
, requestedPrivilegesW
, asmv1W
))
2597 parse_requested_privileges_elem(xmlbuf
, assembly
, acl
, &elem
);
2601 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2602 parse_unknown_elem(xmlbuf
, &elem
);
2607 static void parse_trust_info_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2608 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2610 struct xml_elem elem
;
2612 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2614 if (xml_elem_cmp(&elem
, securityW
, asmv1W
))
2616 parse_security_elem(xmlbuf
, assembly
, acl
, &elem
);
2620 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2621 parse_unknown_elem(xmlbuf
, &elem
);
2626 static void parse_assembly_elem( xmlbuf_t
*xmlbuf
, struct assembly
* assembly
,
2627 struct actctx_loader
* acl
, const struct xml_elem
*parent
,
2628 struct assembly_identity
* expected_ai
)
2630 struct xml_elem elem
;
2631 struct xml_attr attr
;
2632 BOOL end
= FALSE
, version
= FALSE
;
2634 TRACE("(%p)\n", xmlbuf
);
2636 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2638 if (xml_attr_cmp(&attr
, manifestVersionW
))
2640 static const WCHAR v10W
[] = {'1','.','0',0};
2641 if (!xmlstr_cmp(&attr
.value
, v10W
))
2643 FIXME("wrong version %s\n", debugstr_xmlstr(&attr
.value
));
2648 else if (!is_xmlns_attr( &attr
))
2650 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2654 if (end
|| !version
)
2656 set_error( xmlbuf
);
2660 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2662 if (assembly
->type
== APPLICATION_MANIFEST
&& xml_elem_cmp(&elem
, noInheritW
, asmv1W
))
2664 parse_noinherit_elem(xmlbuf
, &elem
);
2665 assembly
->no_inherit
= TRUE
;
2667 else if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2669 parse_noinheritable_elem(xmlbuf
, &elem
);
2671 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2673 parse_description_elem(xmlbuf
, &elem
);
2675 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2677 parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
, &elem
);
2679 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2681 parse_dependency_elem(xmlbuf
, acl
, &elem
);
2683 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2685 parse_file_elem(xmlbuf
, assembly
, acl
, &elem
);
2687 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2689 parse_clr_class_elem(xmlbuf
, assembly
, acl
, &elem
);
2691 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2693 parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
, &elem
);
2695 else if (xml_elem_cmp(&elem
, trustInfoW
, asmv1W
))
2697 parse_trust_info_elem(xmlbuf
, assembly
, acl
, &elem
);
2699 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2701 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
, &elem
);
2703 if (!xmlbuf
->error
&& expected_ai
)
2705 /* FIXME: more tests */
2706 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2707 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2709 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2710 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2711 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2712 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2713 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2714 set_error( xmlbuf
);
2716 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2717 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2718 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2719 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2720 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2721 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2723 FIXME("wrong version for shared assembly manifest\n");
2724 set_error( xmlbuf
);
2728 else if (xml_elem_cmp(&elem
, compatibilityW
, compatibilityNSW
))
2730 parse_compatibility_elem(xmlbuf
, assembly
, acl
, &elem
);
2732 else if (xml_elem_cmp(&elem
, applicationW
, asmv3W
))
2734 parse_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2738 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2739 parse_unknown_elem(xmlbuf
, &elem
);
2743 if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2744 assembly
->no_inherit
)
2746 set_error( xmlbuf
);
2750 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2751 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2753 struct xml_elem elem
;
2754 struct xml_elem parent
= {};
2756 xmlbuf
->error
= FALSE
;
2759 if (!next_xml_elem(xmlbuf
, &elem
, &parent
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2761 if (xmlstr_cmp(&elem
.name
, xmlW
) &&
2762 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
, &parent
)))
2763 return STATUS_SXS_CANT_GEN_ACTCTX
;
2765 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2767 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem
));
2768 return STATUS_SXS_CANT_GEN_ACTCTX
;
2771 parse_assembly_elem(xmlbuf
, assembly
, acl
, &elem
, ai
);
2774 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2775 return STATUS_SXS_CANT_GEN_ACTCTX
;
2778 if (next_xml_elem(xmlbuf
, &elem
, &parent
))
2780 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem
));
2781 return STATUS_SXS_CANT_GEN_ACTCTX
;
2784 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2786 FIXME("parse error\n");
2787 return STATUS_SXS_CANT_GEN_ACTCTX
;
2789 return STATUS_SUCCESS
;
2792 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2793 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2794 const void *buffer
, SIZE_T size
)
2798 struct assembly
*assembly
;
2801 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2803 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2804 return STATUS_SXS_CANT_GEN_ACTCTX
;
2806 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2807 return STATUS_NO_MEMORY
;
2809 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2810 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2811 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2813 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2814 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2816 xmlbuf
.ptr
= buffer
;
2817 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2818 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2820 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2822 const WCHAR
*buf
= buffer
;
2826 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2827 return STATUS_NO_MEMORY
;
2828 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2829 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2830 xmlbuf
.ptr
= new_buff
;
2831 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2832 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2833 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2837 /* let's assume utf-8 for now */
2838 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2843 FIXME( "utf-8 conversion failed\n" );
2844 return STATUS_SXS_CANT_GEN_ACTCTX
;
2846 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2847 return STATUS_NO_MEMORY
;
2848 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2849 xmlbuf
.ptr
= new_buff
;
2850 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2851 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2852 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2857 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2859 OBJECT_ATTRIBUTES attr
;
2862 attr
.Length
= sizeof(attr
);
2863 attr
.RootDirectory
= 0;
2864 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2865 attr
.ObjectName
= name
;
2866 attr
.SecurityDescriptor
= NULL
;
2867 attr
.SecurityQualityOfService
= NULL
;
2868 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2871 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2877 LdrLockLoaderLock(0, NULL
, &magic
);
2878 status
= LdrFindEntryForAddress( module
, &pldr
);
2879 if (status
== STATUS_SUCCESS
)
2881 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2882 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2884 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2885 str
->Length
= pldr
->FullDllName
.Length
;
2886 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2888 else status
= STATUS_NO_MEMORY
;
2890 LdrUnlockLoaderLock(0, magic
);
2894 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2895 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2896 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2899 UNICODE_STRING nameW
;
2900 LDR_RESOURCE_INFO info
;
2901 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2904 if (TRACE_ON(actctx
))
2906 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2908 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2909 hModule
, debugstr_w(nameW
.Buffer
) );
2910 RtlFreeUnicodeString( &nameW
);
2912 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2913 hModule
, debugstr_w(filename
) );
2916 if (!resname
) return STATUS_INVALID_PARAMETER
;
2918 info
.Type
= RT_MANIFEST
;
2919 info
.Language
= lang
;
2920 if (!((ULONG_PTR
)resname
>> 16))
2922 info
.Name
= (ULONG_PTR
)resname
;
2923 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2925 else if (resname
[0] == '#')
2928 RtlInitUnicodeString(&nameW
, resname
+ 1);
2929 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2930 return STATUS_INVALID_PARAMETER
;
2932 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2936 RtlCreateUnicodeString(&nameW
, resname
);
2937 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2938 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2939 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2940 RtlFreeUnicodeString(&nameW
);
2942 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2944 if (status
== STATUS_SUCCESS
)
2945 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2950 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2951 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2952 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2955 OBJECT_ATTRIBUTES attr
;
2957 LARGE_INTEGER offset
;
2962 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2964 attr
.Length
= sizeof(attr
);
2965 attr
.RootDirectory
= 0;
2966 attr
.ObjectName
= NULL
;
2967 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2968 attr
.SecurityDescriptor
= NULL
;
2969 attr
.SecurityQualityOfService
= NULL
;
2972 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2973 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2974 if (status
!= STATUS_SUCCESS
) return status
;
2976 offset
.QuadPart
= 0;
2979 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2980 &count
, ViewShare
, 0, PAGE_READONLY
);
2982 if (status
!= STATUS_SUCCESS
) return status
;
2984 if (RtlImageNtHeader(base
)) /* we got a PE file */
2986 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2987 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2989 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2991 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2995 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2996 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2998 FILE_END_OF_FILE_INFORMATION info
;
3001 OBJECT_ATTRIBUTES attr
;
3003 LARGE_INTEGER offset
;
3008 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
3010 attr
.Length
= sizeof(attr
);
3011 attr
.RootDirectory
= 0;
3012 attr
.ObjectName
= NULL
;
3013 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3014 attr
.SecurityDescriptor
= NULL
;
3015 attr
.SecurityQualityOfService
= NULL
;
3018 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3019 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3020 if (status
!= STATUS_SUCCESS
) return status
;
3022 offset
.QuadPart
= 0;
3025 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3026 &count
, ViewShare
, 0, PAGE_READONLY
);
3028 if (status
!= STATUS_SUCCESS
) return status
;
3030 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
3031 if (status
== STATUS_SUCCESS
)
3032 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
3034 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3038 /* try to load the .manifest file associated to the file */
3039 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3040 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3042 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
3045 UNICODE_STRING nameW
;
3047 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3049 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
3051 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
3053 if (module
) /* use the module filename */
3055 UNICODE_STRING name
;
3057 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
3059 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
3060 strcatW( name
.Buffer
, dotManifestW
);
3061 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3062 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3063 RtlFreeUnicodeString( &name
);
3065 if (status
) return status
;
3069 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3070 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3071 return STATUS_NO_MEMORY
;
3072 strcpyW( buffer
, filename
);
3073 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
3074 strcatW( buffer
, dotManifestW
);
3075 RtlInitUnicodeString( &nameW
, buffer
);
3078 if (!open_nt_file( &file
, &nameW
))
3080 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3083 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
3084 RtlFreeUnicodeString( &nameW
);
3088 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3090 static const WCHAR lookup_fmtW
[] =
3091 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3092 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3093 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3095 WCHAR
*lookup
, *ret
= NULL
;
3096 UNICODE_STRING lookup_us
;
3098 const WCHAR
*lang
= ai
->language
;
3099 unsigned int data_pos
= 0, data_len
;
3102 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
3104 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
3105 (strlenW(ai
->arch
) + strlenW(ai
->name
)
3106 + strlenW(ai
->public_key
) + strlenW(lang
) + 20) * sizeof(WCHAR
)
3107 + sizeof(lookup_fmtW
) )))
3109 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3110 ai
->version
.major
, ai
->version
.minor
, lang
);
3111 RtlInitUnicodeString( &lookup_us
, lookup
);
3113 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3114 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3116 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3117 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3119 ULONG build
, revision
;
3121 data_len
= io
.Information
;
3125 if (data_pos
>= data_len
)
3127 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3128 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3130 data_len
= io
.Information
;
3133 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3135 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3136 else data_pos
= data_len
;
3138 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
3140 if (build
< min_build
) continue;
3141 tmp
= strchrW(tmp
, '.') + 1;
3142 revision
= atoiW(tmp
);
3143 if (build
== min_build
&& revision
< min_revision
) continue;
3144 tmp
= strchrW(tmp
, '_') + 1;
3145 tmp
= strchrW(tmp
, '_') + 1;
3146 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3147 !strncmpiW( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3149 /* prefer a non-Wine manifest if we already have one */
3150 /* we'll still load the builtin dll if specified through DllOverrides */
3156 min_revision
= revision
;
3158 ai
->version
.build
= build
;
3159 ai
->version
.revision
= revision
;
3160 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3161 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3163 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3164 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3168 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3169 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3173 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3175 struct assembly_identity sxs_ai
;
3176 UNICODE_STRING path_us
;
3177 OBJECT_ATTRIBUTES attr
;
3179 WCHAR
*path
, *file
= NULL
;
3182 static const WCHAR manifest_dirW
[] =
3183 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3185 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3187 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
3188 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
3189 return STATUS_NO_MEMORY
;
3191 strcpyW( path
, user_shared_data
->NtSystemRoot
);
3192 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
3194 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3196 RtlFreeHeap( GetProcessHeap(), 0, path
);
3197 return STATUS_NO_SUCH_FILE
;
3199 RtlFreeHeap( GetProcessHeap(), 0, path
);
3201 attr
.Length
= sizeof(attr
);
3202 attr
.RootDirectory
= 0;
3203 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3204 attr
.ObjectName
= &path_us
;
3205 attr
.SecurityDescriptor
= NULL
;
3206 attr
.SecurityQualityOfService
= NULL
;
3208 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3209 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3212 file
= lookup_manifest_file( handle
, &sxs_ai
);
3217 RtlFreeUnicodeString( &path_us
);
3218 return STATUS_NO_SUCH_FILE
;
3221 /* append file name to directory path */
3222 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3223 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
3225 RtlFreeHeap( GetProcessHeap(), 0, file
);
3226 RtlFreeUnicodeString( &path_us
);
3227 return STATUS_NO_MEMORY
;
3230 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3231 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3232 RtlInitUnicodeString( &path_us
, path
);
3233 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
3235 if (!open_nt_file( &handle
, &path_us
))
3237 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3240 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3242 RtlFreeHeap( GetProcessHeap(), 0, file
);
3243 RtlFreeUnicodeString( &path_us
);
3247 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3248 struct assembly_identity
* ai
)
3250 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3252 WCHAR
*buffer
, *p
, *directory
;
3254 UNICODE_STRING nameW
;
3258 TRACE( "looking for name=%s version=%s arch=%s\n",
3259 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3261 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3263 /* FIXME: add support for language specific lookup */
3265 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3266 strlenW(acl
->actctx
->appdir
.info
));
3268 nameW
.Buffer
= NULL
;
3269 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3270 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3271 return STATUS_NO_MEMORY
;
3273 if (!(directory
= build_assembly_dir( ai
)))
3275 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3276 return STATUS_NO_MEMORY
;
3279 /* Lookup in <dir>\name.dll
3280 * <dir>\name.manifest
3281 * <dir>\name\name.dll
3282 * <dir>\name\name.manifest
3284 * First 'appdir' is used as <dir>, if that failed
3285 * it tries application manifest file path.
3287 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3288 p
= buffer
+ strlenW(buffer
);
3289 for (i
= 0; i
< 4; i
++)
3293 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3294 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3298 strcpyW( p
, ai
->name
);
3301 strcpyW( p
, dotDllW
);
3302 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3304 status
= open_nt_file( &file
, &nameW
);
3307 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3308 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3310 if (status
== STATUS_SUCCESS
)
3313 RtlFreeUnicodeString( &nameW
);
3316 strcpyW( p
, dotManifestW
);
3317 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3319 status
= open_nt_file( &file
, &nameW
);
3322 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3326 RtlFreeUnicodeString( &nameW
);
3328 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3330 RtlFreeUnicodeString( &nameW
);
3331 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3332 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3336 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3338 NTSTATUS status
= STATUS_SUCCESS
;
3341 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3343 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3345 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3347 FIXME( "Could not find dependent assembly %s (%s)\n",
3348 debugstr_w(acl
->dependencies
[i
].name
),
3349 debugstr_version(&acl
->dependencies
[i
].version
) );
3350 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3355 /* FIXME should now iterate through all refs */
3359 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3360 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3362 NTSTATUS status
= STATUS_SUCCESS
;
3364 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3366 if (*handle
) return STATUS_INVALID_PARAMETER
;
3368 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3369 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3371 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3376 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3378 LdrLockLoaderLock( 0, NULL
, &magic
);
3379 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3381 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
3382 status
= STATUS_DLL_NOT_FOUND
;
3384 *handle
= pldr
->ActivationContext
;
3386 else status
= STATUS_DLL_NOT_FOUND
;
3387 LdrUnlockLoaderLock( 0, magic
);
3389 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3390 *handle
= process_actctx
;
3395 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3397 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3398 struct strsection_header
*header
;
3399 struct dllredirect_data
*data
;
3400 struct string_index
*index
;
3403 /* compute section length */
3404 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3406 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3407 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3409 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3411 /* each entry needs index, data and string data */
3412 total_len
+= sizeof(*index
);
3413 total_len
+= sizeof(*data
);
3414 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3417 dll_count
+= assembly
->num_dlls
;
3420 total_len
+= sizeof(*header
);
3422 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3423 if (!header
) return STATUS_NO_MEMORY
;
3425 memset(header
, 0, sizeof(*header
));
3426 header
->magic
= STRSECTION_MAGIC
;
3427 header
->size
= sizeof(*header
);
3428 header
->count
= dll_count
;
3429 header
->index_offset
= sizeof(*header
);
3430 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3431 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3433 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3435 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3436 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3438 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3442 /* setup new index entry */
3443 str
.Buffer
= dll
->name
;
3444 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3445 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3446 /* hash original class name */
3447 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3449 index
->name_offset
= name_offset
;
3450 index
->name_len
= str
.Length
;
3451 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3452 index
->data_len
= sizeof(*data
);
3453 index
->rosterindex
= i
+ 1;
3456 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3457 data
->size
= sizeof(*data
);
3458 data
->unk
= 2; /* FIXME: seems to be constant */
3459 memset(data
->res
, 0, sizeof(data
->res
));
3462 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3463 memcpy(ptrW
, dll
->name
, index
->name_len
);
3464 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3466 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3474 return STATUS_SUCCESS
;
3477 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3479 struct string_index
*iter
, *index
= NULL
;
3482 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3483 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3485 for (i
= 0; i
< section
->count
; i
++)
3487 if (iter
->hash
== hash
)
3489 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3491 if (!strcmpiW(nameW
, name
->Buffer
))
3497 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3505 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3507 struct guid_index
*iter
, *index
= NULL
;
3510 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3512 for (i
= 0; i
< section
->count
; i
++)
3514 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3525 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3527 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3530 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3531 PACTCTX_SECTION_KEYED_DATA data
)
3533 struct dllredirect_data
*dll
;
3534 struct string_index
*index
;
3536 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3538 if (!actctx
->dllredirect_section
)
3540 struct strsection_header
*section
;
3542 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3543 if (status
) return status
;
3545 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3546 RtlFreeHeap(GetProcessHeap(), 0, section
);
3549 index
= find_string_index(actctx
->dllredirect_section
, name
);
3550 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3554 dll
= get_dllredirect_data(actctx
, index
);
3556 data
->ulDataFormatVersion
= 1;
3558 data
->ulLength
= dll
->size
;
3559 data
->lpSectionGlobalData
= NULL
;
3560 data
->ulSectionGlobalDataLength
= 0;
3561 data
->lpSectionBase
= actctx
->dllredirect_section
;
3562 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3563 data
->hActCtx
= NULL
;
3565 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3566 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3569 return STATUS_SUCCESS
;
3572 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3574 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3577 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3579 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3582 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3584 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3585 struct wndclass_redirect_data
*data
;
3586 struct strsection_header
*header
;
3587 struct string_index
*index
;
3590 /* compute section length */
3591 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3593 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3594 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3596 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3597 for (k
= 0; k
< dll
->entities
.num
; k
++)
3599 struct entity
*entity
= &dll
->entities
.base
[k
];
3600 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3602 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3605 /* each class entry needs index, data and string data */
3606 total_len
+= sizeof(*index
);
3607 total_len
+= sizeof(*data
);
3608 /* original name is stored separately */
3609 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3610 /* versioned name and module name are stored one after another */
3611 if (entity
->u
.class.versioned
)
3612 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3615 len
+= strlenW(dll
->name
) + 1;
3616 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3624 total_len
+= sizeof(*header
);
3626 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3627 if (!header
) return STATUS_NO_MEMORY
;
3629 memset(header
, 0, sizeof(*header
));
3630 header
->magic
= STRSECTION_MAGIC
;
3631 header
->size
= sizeof(*header
);
3632 header
->count
= class_count
;
3633 header
->index_offset
= sizeof(*header
);
3634 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3635 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3637 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3639 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3640 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3642 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3643 for (k
= 0; k
< dll
->entities
.num
; k
++)
3645 struct entity
*entity
= &dll
->entities
.base
[k
];
3646 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3648 static const WCHAR exclW
[] = {'!',0};
3649 ULONG versioned_len
, module_len
;
3653 /* setup new index entry */
3654 str
.Buffer
= entity
->u
.class.name
;
3655 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3656 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3657 /* hash original class name */
3658 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3660 /* include '!' separator too */
3661 if (entity
->u
.class.versioned
)
3662 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3664 versioned_len
= str
.Length
;
3665 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3667 index
->name_offset
= name_offset
;
3668 index
->name_len
= str
.Length
;
3669 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3670 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3671 index
->rosterindex
= i
+ 1;
3674 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3675 data
->size
= sizeof(*data
);
3677 data
->name_len
= versioned_len
;
3678 data
->name_offset
= sizeof(*data
);
3679 data
->module_len
= module_len
;
3680 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3682 /* original class name */
3683 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3684 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3685 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3688 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3689 memcpy(ptrW
, dll
->name
, data
->module_len
);
3690 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3692 /* versioned name */
3693 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3694 if (entity
->u
.class.versioned
)
3696 get_assembly_version(assembly
, ptrW
);
3697 strcatW(ptrW
, exclW
);
3698 strcatW(ptrW
, entity
->u
.class.name
);
3702 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3703 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3706 name_offset
+= sizeof(*data
);
3707 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3717 return STATUS_SUCCESS
;
3720 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3721 PACTCTX_SECTION_KEYED_DATA data
)
3723 struct string_index
*iter
, *index
= NULL
;
3724 struct wndclass_redirect_data
*class;
3728 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3730 if (!actctx
->wndclass_section
)
3732 struct strsection_header
*section
;
3734 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3735 if (status
) return status
;
3737 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3738 RtlFreeHeap(GetProcessHeap(), 0, section
);
3742 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3743 iter
= get_wndclass_first_index(actctx
);
3745 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3747 if (iter
->hash
== hash
)
3749 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3751 if (!strcmpiW(nameW
, name
->Buffer
))
3757 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3762 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3766 class = get_wndclass_data(actctx
, index
);
3768 data
->ulDataFormatVersion
= 1;
3769 data
->lpData
= class;
3770 /* full length includes string length with nulls */
3771 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3772 data
->lpSectionGlobalData
= NULL
;
3773 data
->ulSectionGlobalDataLength
= 0;
3774 data
->lpSectionBase
= actctx
->wndclass_section
;
3775 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3776 data
->hActCtx
= NULL
;
3778 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3779 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3782 return STATUS_SUCCESS
;
3785 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3787 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3788 struct guidsection_header
*header
;
3789 ULONG module_offset
, data_offset
;
3790 struct tlibredirect_data
*data
;
3791 struct guid_index
*index
;
3793 /* compute section length */
3794 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3796 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3797 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3799 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3800 for (k
= 0; k
< dll
->entities
.num
; k
++)
3802 struct entity
*entity
= &dll
->entities
.base
[k
];
3803 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3805 /* each entry needs index, data and string data for module name and help string */
3806 total_len
+= sizeof(*index
);
3807 total_len
+= sizeof(*data
);
3808 /* help string is stored separately */
3809 if (*entity
->u
.typelib
.helpdir
)
3810 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3812 /* module names are packed one after another */
3813 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3821 total_len
+= aligned_string_len(names_len
);
3822 total_len
+= sizeof(*header
);
3824 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3825 if (!header
) return STATUS_NO_MEMORY
;
3827 memset(header
, 0, sizeof(*header
));
3828 header
->magic
= GUIDSECTION_MAGIC
;
3829 header
->size
= sizeof(*header
);
3830 header
->count
= tlib_count
;
3831 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3832 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3833 module_offset
= sizeof(*header
);
3834 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3836 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3838 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3839 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3841 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3842 for (k
= 0; k
< dll
->entities
.num
; k
++)
3844 struct entity
*entity
= &dll
->entities
.base
[k
];
3845 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3847 ULONG module_len
, help_len
;
3851 if (*entity
->u
.typelib
.helpdir
)
3852 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3856 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3858 /* setup new index entry */
3859 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3860 RtlGUIDFromString(&str
, &index
->guid
);
3861 index
->data_offset
= data_offset
;
3862 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3863 index
->rosterindex
= i
+ 1;
3866 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3867 data
->size
= sizeof(*data
);
3869 data
->name_len
= module_len
;
3870 data
->name_offset
= module_offset
;
3871 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3873 data
->flags
= entity
->u
.typelib
.flags
;
3874 data
->help_len
= help_len
;
3875 data
->help_offset
= sizeof(*data
);
3876 data
->major_version
= entity
->u
.typelib
.major
;
3877 data
->minor_version
= entity
->u
.typelib
.minor
;
3880 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3881 memcpy(ptrW
, dll
->name
, data
->name_len
);
3882 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3887 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3888 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3889 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3892 data_offset
+= sizeof(*data
);
3894 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3896 module_offset
+= module_len
+ sizeof(WCHAR
);
3906 return STATUS_SUCCESS
;
3909 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3911 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3914 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3916 struct guid_index
*index
= NULL
;
3917 struct tlibredirect_data
*tlib
;
3919 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3921 if (!actctx
->tlib_section
)
3923 struct guidsection_header
*section
;
3925 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3926 if (status
) return status
;
3928 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3929 RtlFreeHeap(GetProcessHeap(), 0, section
);
3932 index
= find_guid_index(actctx
->tlib_section
, guid
);
3933 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3935 tlib
= get_tlib_data(actctx
, index
);
3937 data
->ulDataFormatVersion
= 1;
3938 data
->lpData
= tlib
;
3939 /* full length includes string length with nulls */
3940 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3941 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3942 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3943 data
->lpSectionBase
= actctx
->tlib_section
;
3944 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3945 data
->hActCtx
= NULL
;
3947 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3948 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3950 return STATUS_SUCCESS
;
3953 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3955 ULONG
*ptr
= (ULONG
*)guid
;
3958 /* GUID is 16 bytes long */
3959 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3960 *ptr
= RtlUniform(seed
);
3962 guid
->Data3
&= 0x0fff;
3963 guid
->Data3
|= (4 << 12);
3964 guid
->Data4
[0] &= 0x3f;
3965 guid
->Data4
[0] |= 0x80;
3968 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3969 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3973 for (i
= 0; i
< entities
->num
; i
++)
3975 struct entity
*entity
= &entities
->base
[i
];
3976 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3978 /* each entry needs two index entries, extra one goes for alias GUID */
3979 *len
+= 2*sizeof(struct guid_index
);
3980 /* To save some memory we don't allocated two data structures,
3981 instead alias index and normal index point to the same data structure. */
3982 *len
+= sizeof(struct comclassredirect_data
);
3984 /* for clrClass store some more */
3985 if (entity
->u
.comclass
.name
)
3987 unsigned int str_len
;
3989 /* all string data is stored together in aligned block */
3990 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3991 if (entity
->u
.comclass
.progid
)
3992 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3993 if (entity
->u
.comclass
.version
)
3994 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3996 *len
+= sizeof(struct clrclass_data
);
3997 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3999 /* module name is forced to mscoree.dll, and stored two times with different case */
4000 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
4004 /* progid string is stored separately */
4005 if (entity
->u
.comclass
.progid
)
4006 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4008 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
4016 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4017 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4018 ULONG
*seed
, ULONG rosterindex
)
4022 for (i
= 0; i
< entities
->num
; i
++)
4024 struct entity
*entity
= &entities
->base
[i
];
4025 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4027 ULONG module_len
, progid_len
, str_len
= 0;
4028 struct comclassredirect_data
*data
;
4029 struct guid_index
*alias_index
;
4030 struct clrclass_data
*clrdata
;
4034 if (entity
->u
.comclass
.progid
)
4035 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4039 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
4041 /* setup new index entry */
4042 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4043 RtlGUIDFromString(&str
, &(*index
)->guid
);
4045 (*index
)->data_offset
= *data_offset
;
4046 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4047 (*index
)->rosterindex
= rosterindex
;
4049 /* Setup new index entry for alias guid. Alias index records are placed after
4050 normal records, so normal guids are hit first on search. Note that class count
4052 alias_index
= (*index
) + section
->count
/2;
4053 generate_uuid(seed
, &alias_index
->guid
);
4054 alias_index
->data_offset
= (*index
)->data_offset
;
4055 alias_index
->data_len
= 0;
4056 alias_index
->rosterindex
= (*index
)->rosterindex
;
4059 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4060 data
->size
= sizeof(*data
);
4064 data
->model
= entity
->u
.comclass
.model
;
4065 data
->clsid
= (*index
)->guid
;
4066 data
->alias
= alias_index
->guid
;
4067 data
->clsid2
= data
->clsid
;
4068 if (entity
->u
.comclass
.tlbid
)
4070 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4071 RtlGUIDFromString(&str
, &data
->tlbid
);
4074 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4075 data
->name_len
= module_len
;
4076 data
->name_offset
= *module_offset
;
4077 data
->progid_len
= progid_len
;
4078 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4079 data
->clrdata_len
= 0; /* will be set later */
4080 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4081 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4082 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4083 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4084 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4085 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4087 /* mask describes which misc* data is available */
4089 if (data
->miscstatus
)
4090 data
->miscmask
|= MiscStatus
;
4091 if (data
->miscstatuscontent
)
4092 data
->miscmask
|= MiscStatusContent
;
4093 if (data
->miscstatusthumbnail
)
4094 data
->miscmask
|= MiscStatusThumbnail
;
4095 if (data
->miscstatusicon
)
4096 data
->miscmask
|= MiscStatusIcon
;
4097 if (data
->miscstatusdocprint
)
4098 data
->miscmask
|= MiscStatusDocPrint
;
4100 if (data
->clrdata_offset
)
4102 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4104 clrdata
->size
= sizeof(*clrdata
);
4105 clrdata
->res
[0] = 0;
4106 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4107 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
4108 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4109 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4110 clrdata
->name_offset
= clrdata
->size
;
4111 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4112 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4113 clrdata
->res2
[0] = 0;
4114 clrdata
->res2
[1] = 0;
4116 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4119 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4120 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
4121 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4123 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4124 memcpy(ptrW
, mscoreeW
, data
->name_len
);
4125 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4128 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4129 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4130 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4132 /* runtime version, optional */
4133 if (clrdata
->version_len
)
4135 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4137 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4138 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4139 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4142 if (data
->progid_len
)
4143 data
->progid_offset
+= data
->clrdata_len
;
4144 (*index
)->data_len
+= sizeof(*clrdata
);
4151 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4152 memcpy(ptrW
, dll
->name
, data
->name_len
);
4153 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4157 if (data
->progid_len
)
4159 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4160 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4161 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4164 /* string block length */
4168 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4169 if (clrdata
->version_len
)
4170 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4173 str_len
+= progid_len
+ sizeof(WCHAR
);
4175 (*index
)->data_len
+= aligned_string_len(str_len
);
4176 alias_index
->data_len
= (*index
)->data_len
;
4178 /* move to next data record */
4179 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4180 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4184 (*data_offset
) += sizeof(*clrdata
);
4185 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4192 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4194 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4195 struct guidsection_header
*header
;
4196 ULONG module_offset
, data_offset
;
4197 struct guid_index
*index
;
4200 /* compute section length */
4201 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4203 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4204 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4205 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4207 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4208 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4212 total_len
+= aligned_string_len(names_len
);
4213 total_len
+= sizeof(*header
);
4215 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4216 if (!header
) return STATUS_NO_MEMORY
;
4218 memset(header
, 0, sizeof(*header
));
4219 header
->magic
= GUIDSECTION_MAGIC
;
4220 header
->size
= sizeof(*header
);
4221 header
->count
= 2*class_count
;
4222 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4223 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4224 module_offset
= sizeof(*header
);
4225 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4227 seed
= NtGetTickCount();
4228 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4230 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4231 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4232 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4234 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4235 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4241 return STATUS_SUCCESS
;
4244 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4246 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4249 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4251 struct comclassredirect_data
*comclass
;
4252 struct guid_index
*index
= NULL
;
4254 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4256 if (!actctx
->comserver_section
)
4258 struct guidsection_header
*section
;
4260 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4261 if (status
) return status
;
4263 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4264 RtlFreeHeap(GetProcessHeap(), 0, section
);
4267 index
= find_guid_index(actctx
->comserver_section
, guid
);
4268 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4270 comclass
= get_comclass_data(actctx
, index
);
4272 data
->ulDataFormatVersion
= 1;
4273 data
->lpData
= comclass
;
4274 /* full length includes string length with nulls */
4275 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4276 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4277 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4278 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4279 data
->lpSectionBase
= actctx
->comserver_section
;
4280 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4281 data
->hActCtx
= NULL
;
4283 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4284 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4286 return STATUS_SUCCESS
;
4289 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4293 for (i
= 0; i
< entities
->num
; i
++)
4295 struct entity
*entity
= &entities
->base
[i
];
4296 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4298 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4299 if (entity
->u
.ifaceps
.name
)
4300 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4306 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4307 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4311 for (i
= 0; i
< entities
->num
; i
++)
4313 struct entity
*entity
= &entities
->base
[i
];
4314 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4316 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4320 if (entity
->u
.ifaceps
.name
)
4321 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4326 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4327 RtlGUIDFromString(&str
, &(*index
)->guid
);
4328 (*index
)->data_offset
= *data_offset
;
4329 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4330 (*index
)->rosterindex
= rosterindex
;
4332 /* setup data record */
4333 data
->size
= sizeof(*data
);
4334 data
->mask
= entity
->u
.ifaceps
.mask
;
4336 /* proxyStubClsid32 value is only stored for external PS,
4337 if set it's used as iid, otherwise 'iid' attribute value is used */
4338 if (entity
->u
.ifaceps
.ps32
)
4340 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4341 RtlGUIDFromString(&str
, &data
->iid
);
4344 data
->iid
= (*index
)->guid
;
4346 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4348 if (entity
->u
.ifaceps
.tlib
)
4350 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4351 RtlGUIDFromString(&str
, &data
->tlbid
);
4354 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4356 if (entity
->u
.ifaceps
.base
)
4358 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4359 RtlGUIDFromString(&str
, &data
->base
);
4362 memset(&data
->base
, 0, sizeof(data
->base
));
4364 data
->name_len
= name_len
;
4365 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4370 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4371 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4372 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4375 /* move to next record */
4377 *data_offset
+= sizeof(*data
);
4379 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4384 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4386 unsigned int i
, j
, total_len
= 0, count
= 0;
4387 struct guidsection_header
*header
;
4388 struct guid_index
*index
;
4391 /* compute section length */
4392 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4394 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4396 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4397 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4399 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4400 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4404 total_len
+= sizeof(*header
);
4406 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4407 if (!header
) return STATUS_NO_MEMORY
;
4409 memset(header
, 0, sizeof(*header
));
4410 header
->magic
= GUIDSECTION_MAGIC
;
4411 header
->size
= sizeof(*header
);
4412 header
->count
= count
;
4413 header
->index_offset
= sizeof(*header
);
4414 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4415 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4417 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4419 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4421 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4422 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4424 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4425 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4431 return STATUS_SUCCESS
;
4434 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4436 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4439 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4441 struct ifacepsredirect_data
*iface
;
4442 struct guid_index
*index
= NULL
;
4444 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4446 if (!actctx
->ifaceps_section
)
4448 struct guidsection_header
*section
;
4450 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4451 if (status
) return status
;
4453 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4454 RtlFreeHeap(GetProcessHeap(), 0, section
);
4457 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4458 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4460 iface
= get_ifaceps_data(actctx
, index
);
4462 data
->ulDataFormatVersion
= 1;
4463 data
->lpData
= iface
;
4464 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4465 data
->lpSectionGlobalData
= NULL
;
4466 data
->ulSectionGlobalDataLength
= 0;
4467 data
->lpSectionBase
= actctx
->ifaceps_section
;
4468 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4469 data
->hActCtx
= NULL
;
4471 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4472 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4474 return STATUS_SUCCESS
;
4477 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4479 unsigned int i
, j
, total_len
= 0, count
= 0;
4480 struct guidsection_header
*header
;
4481 struct clrsurrogate_data
*data
;
4482 struct guid_index
*index
;
4485 /* compute section length */
4486 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4488 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4489 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4491 struct entity
*entity
= &assembly
->entities
.base
[j
];
4492 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4496 total_len
+= sizeof(*index
) + sizeof(*data
);
4497 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4498 if (entity
->u
.clrsurrogate
.version
)
4499 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4500 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4507 total_len
+= sizeof(*header
);
4509 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4510 if (!header
) return STATUS_NO_MEMORY
;
4512 memset(header
, 0, sizeof(*header
));
4513 header
->magic
= GUIDSECTION_MAGIC
;
4514 header
->size
= sizeof(*header
);
4515 header
->count
= count
;
4516 header
->index_offset
= sizeof(*header
);
4517 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4518 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4520 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4522 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4523 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4525 struct entity
*entity
= &assembly
->entities
.base
[j
];
4526 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4528 ULONG version_len
, name_len
;
4532 if (entity
->u
.clrsurrogate
.version
)
4533 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4536 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4538 /* setup new index entry */
4539 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4540 RtlGUIDFromString(&str
, &index
->guid
);
4542 index
->data_offset
= data_offset
;
4543 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4544 index
->rosterindex
= i
+ 1;
4547 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4548 data
->size
= sizeof(*data
);
4550 data
->clsid
= index
->guid
;
4551 data
->version_offset
= version_len
? data
->size
: 0;
4552 data
->version_len
= version_len
;
4553 data
->name_offset
= data
->size
+ version_len
;
4555 data
->name_offset
+= sizeof(WCHAR
);
4556 data
->name_len
= name_len
;
4558 /* surrogate name */
4559 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4560 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4561 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4563 /* runtime version */
4564 if (data
->version_len
)
4566 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4567 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4568 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4571 data_offset
+= index
->data_offset
;
4579 return STATUS_SUCCESS
;
4582 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4584 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4587 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4589 struct clrsurrogate_data
*surrogate
;
4590 struct guid_index
*index
= NULL
;
4592 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4594 if (!actctx
->clrsurrogate_section
)
4596 struct guidsection_header
*section
;
4598 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4599 if (status
) return status
;
4601 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4602 RtlFreeHeap(GetProcessHeap(), 0, section
);
4605 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4606 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4608 surrogate
= get_surrogate_data(actctx
, index
);
4610 data
->ulDataFormatVersion
= 1;
4611 data
->lpData
= surrogate
;
4612 /* full length includes string length with nulls */
4613 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4614 if (surrogate
->version_len
)
4615 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4617 data
->lpSectionGlobalData
= NULL
;
4618 data
->ulSectionGlobalDataLength
= 0;
4619 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4620 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4621 data
->hActCtx
= NULL
;
4623 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4624 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4626 return STATUS_SUCCESS
;
4629 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4631 unsigned int i
, j
, single_len
;
4633 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4634 for (i
= 0; i
< entities
->num
; i
++)
4636 struct entity
*entity
= &entities
->base
[i
];
4637 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4639 if (entity
->u
.comclass
.progid
)
4641 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4645 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4646 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4648 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4649 *count
+= entity
->u
.comclass
.progids
.num
;
4654 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4655 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4657 struct progidredirect_data
*data
;
4662 /* setup new index entry */
4664 /* hash progid name */
4665 RtlInitUnicodeString(&str
, progid
);
4666 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4668 (*index
)->name_offset
= *data_offset
;
4669 (*index
)->name_len
= str
.Length
;
4670 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4671 (*index
)->data_len
= sizeof(*data
);
4672 (*index
)->rosterindex
= rosterindex
;
4674 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4676 /* setup data structure */
4677 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4678 data
->size
= sizeof(*data
);
4680 data
->clsid_offset
= *global_offset
;
4682 /* write progid string */
4683 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4684 memcpy(ptrW
, progid
, (*index
)->name_len
);
4685 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4687 /* write guid to global area */
4688 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4692 *global_offset
+= sizeof(GUID
);
4693 *data_offset
+= data
->size
;
4697 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4698 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4702 for (i
= 0; i
< entities
->num
; i
++)
4704 struct entity
*entity
= &entities
->base
[i
];
4705 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4707 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4708 struct comclassredirect_data
*comclass
;
4709 struct guid_index
*guid_index
;
4713 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4714 RtlGUIDFromString(&str
, &clsid
);
4716 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4717 comclass
= get_comclass_data(actctx
, guid_index
);
4719 if (entity
->u
.comclass
.progid
)
4720 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4721 index
, data_offset
, global_offset
, rosterindex
);
4723 for (j
= 0; j
< progids
->num
; j
++)
4724 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4725 index
, data_offset
, global_offset
, rosterindex
);
4730 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4732 unsigned int i
, j
, total_len
= 0, count
= 0;
4733 struct strsection_header
*header
;
4734 ULONG data_offset
, global_offset
;
4735 struct string_index
*index
;
4737 /* compute section length */
4738 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4740 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4742 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4743 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4745 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4746 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4750 total_len
+= sizeof(*header
);
4752 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4753 if (!header
) return STATUS_NO_MEMORY
;
4755 memset(header
, 0, sizeof(*header
));
4756 header
->magic
= STRSECTION_MAGIC
;
4757 header
->size
= sizeof(*header
);
4758 header
->count
= count
;
4759 header
->global_offset
= header
->size
;
4760 header
->global_len
= count
*sizeof(GUID
);
4761 header
->index_offset
= header
->size
+ header
->global_len
;
4763 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4764 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4765 global_offset
= header
->global_offset
;
4767 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4769 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4771 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4772 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4774 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4775 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4781 return STATUS_SUCCESS
;
4784 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4786 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4789 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4790 PACTCTX_SECTION_KEYED_DATA data
)
4792 struct progidredirect_data
*progid
;
4793 struct string_index
*index
;
4795 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4797 if (!actctx
->comserver_section
)
4799 struct guidsection_header
*section
;
4801 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4802 if (status
) return status
;
4804 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4805 RtlFreeHeap(GetProcessHeap(), 0, section
);
4808 if (!actctx
->progid_section
)
4810 struct strsection_header
*section
;
4812 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4813 if (status
) return status
;
4815 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4816 RtlFreeHeap(GetProcessHeap(), 0, section
);
4819 index
= find_string_index(actctx
->progid_section
, name
);
4820 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4824 progid
= get_progid_data(actctx
, index
);
4826 data
->ulDataFormatVersion
= 1;
4827 data
->lpData
= progid
;
4828 data
->ulLength
= progid
->size
;
4829 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4830 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4831 data
->lpSectionBase
= actctx
->progid_section
;
4832 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4833 data
->hActCtx
= NULL
;
4835 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4836 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4839 return STATUS_SUCCESS
;
4842 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4843 const UNICODE_STRING
*section_name
,
4844 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4848 switch (section_kind
)
4850 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4851 status
= find_dll_redirection(actctx
, section_name
, data
);
4853 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4854 status
= find_window_class(actctx
, section_name
, data
);
4856 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4857 status
= find_progid_redirection(actctx
, section_name
, data
);
4859 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4860 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4861 return STATUS_SXS_SECTION_NOT_FOUND
;
4863 WARN("Unknown section_kind %x\n", section_kind
);
4864 return STATUS_SXS_SECTION_NOT_FOUND
;
4867 if (status
!= STATUS_SUCCESS
) return status
;
4869 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4871 actctx_addref(actctx
);
4872 data
->hActCtx
= actctx
;
4874 return STATUS_SUCCESS
;
4877 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4878 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4882 switch (section_kind
)
4884 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4885 status
= find_tlib_redirection(actctx
, guid
, data
);
4887 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4888 status
= find_comserver_redirection(actctx
, guid
, data
);
4890 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4891 status
= find_cominterface_redirection(actctx
, guid
, data
);
4893 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4894 status
= find_clr_surrogate(actctx
, guid
, data
);
4897 WARN("Unknown section_kind %x\n", section_kind
);
4898 return STATUS_SXS_SECTION_NOT_FOUND
;
4901 if (status
!= STATUS_SUCCESS
) return status
;
4903 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4905 actctx_addref(actctx
);
4906 data
->hActCtx
= actctx
;
4908 return STATUS_SUCCESS
;
4911 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
4915 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4917 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4918 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4920 struct entity
*entity
= &assembly
->entities
.base
[j
];
4921 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
4922 !strcmpW( entity
->u
.settings
.name
, settings
) &&
4923 !strcmpW( entity
->u
.settings
.ns
, ns
))
4924 return entity
->u
.settings
.value
;
4930 /* initialize the activation context for the current process */
4931 void actctx_init(void)
4936 ctx
.cbSize
= sizeof(ctx
);
4937 ctx
.lpSource
= NULL
;
4938 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4939 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4940 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4942 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4946 /***********************************************************************
4947 * RtlCreateActivationContext (NTDLL.@)
4949 * Create an activation context.
4951 * FIXME: function signature/prototype is wrong
4953 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4955 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4956 const WCHAR
*directory
= NULL
;
4957 ACTIVATION_CONTEXT
*actctx
;
4958 UNICODE_STRING nameW
;
4960 NTSTATUS status
= STATUS_NO_MEMORY
;
4962 struct actctx_loader acl
;
4964 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4966 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4967 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4968 return STATUS_INVALID_PARAMETER
;
4970 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4971 return STATUS_NO_MEMORY
;
4973 actctx
->magic
= ACTCTX_MAGIC
;
4974 actctx
->ref_count
= 1;
4975 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4976 actctx
->config
.info
= NULL
;
4977 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4978 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4980 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4988 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4989 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4991 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4992 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4993 actctx
->appdir
.info
= dir
.Buffer
;
4996 nameW
.Buffer
= NULL
;
4998 /* open file only if it's going to be used */
4999 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
5000 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
5002 WCHAR
*source
= NULL
;
5005 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5006 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
5008 DWORD dir_len
, source_len
;
5010 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
5011 source_len
= strlenW(pActCtx
->lpSource
);
5012 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5014 status
= STATUS_NO_MEMORY
;
5018 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5019 source
[dir_len
] = '\\';
5020 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5023 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5024 RtlFreeHeap( GetProcessHeap(), 0, source
);
5027 status
= STATUS_NO_SUCH_FILE
;
5030 status
= open_nt_file( &file
, &nameW
);
5033 RtlFreeUnicodeString( &nameW
);
5038 acl
.actctx
= actctx
;
5039 acl
.dependencies
= NULL
;
5040 acl
.num_dependencies
= 0;
5041 acl
.allocated_dependencies
= 0;
5043 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5044 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5046 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5048 /* if we have a resource it's a PE file */
5049 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5051 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5052 pActCtx
->lpResourceName
, lang
);
5053 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5054 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5055 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5057 else if (pActCtx
->lpSource
)
5059 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5060 file
, pActCtx
->lpResourceName
, lang
);
5061 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5062 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5063 NULL
, pActCtx
->lpResourceName
);
5065 else status
= STATUS_INVALID_PARAMETER
;
5069 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5072 if (file
) NtClose( file
);
5073 RtlFreeUnicodeString( &nameW
);
5075 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
5076 free_depend_manifests( &acl
);
5078 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
5079 else actctx_release( actctx
);
5083 if (file
) NtClose( file
);
5084 actctx_release( actctx
);
5089 /***********************************************************************
5090 * RtlAddRefActivationContext (NTDLL.@)
5092 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
5094 ACTIVATION_CONTEXT
*actctx
;
5096 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5100 /******************************************************************
5101 * RtlReleaseActivationContext (NTDLL.@)
5103 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5105 ACTIVATION_CONTEXT
*actctx
;
5107 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5110 /******************************************************************
5111 * RtlZombifyActivationContext (NTDLL.@)
5113 * FIXME: function prototype might be wrong
5115 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5117 FIXME("%p: stub\n", handle
);
5118 return STATUS_NOT_IMPLEMENTED
;
5121 /******************************************************************
5122 * RtlActivateActivationContext (NTDLL.@)
5124 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5126 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5128 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5129 return STATUS_NO_MEMORY
;
5131 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5132 frame
->ActivationContext
= handle
;
5134 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
5135 RtlAddRefActivationContext( handle
);
5137 *cookie
= (ULONG_PTR
)frame
;
5138 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
5139 return STATUS_SUCCESS
;
5143 /***********************************************************************
5144 * RtlDeactivateActivationContext (NTDLL.@)
5146 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5148 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5150 TRACE( "%x cookie=%lx\n", flags
, cookie
);
5152 /* find the right frame */
5153 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5154 for (frame
= top
; frame
; frame
= frame
->Previous
)
5155 if ((ULONG_PTR
)frame
== cookie
) break;
5158 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5160 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5161 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5163 /* pop everything up to and including frame */
5164 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5166 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5168 frame
= top
->Previous
;
5169 RtlReleaseActivationContext( top
->ActivationContext
);
5170 RtlFreeHeap( GetProcessHeap(), 0, top
);
5176 /******************************************************************
5177 * RtlFreeThreadActivationContextStack (NTDLL.@)
5179 void WINAPI
RtlFreeThreadActivationContextStack(void)
5181 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5183 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5186 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5187 RtlReleaseActivationContext( frame
->ActivationContext
);
5188 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5191 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5195 /******************************************************************
5196 * RtlGetActiveActivationContext (NTDLL.@)
5198 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5200 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5202 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5203 RtlAddRefActivationContext( *handle
);
5208 return STATUS_SUCCESS
;
5212 /******************************************************************
5213 * RtlIsActivationContextActive (NTDLL.@)
5215 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5217 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5219 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5220 if (frame
->ActivationContext
== handle
) return TRUE
;
5225 /***********************************************************************
5226 * RtlQueryInformationActivationContext (NTDLL.@)
5228 * Get information about an activation context.
5229 * FIXME: function signature/prototype may be wrong
5231 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5232 ULONG
class, PVOID buffer
,
5233 SIZE_T bufsize
, SIZE_T
*retlen
)
5235 ACTIVATION_CONTEXT
*actctx
;
5238 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5239 subinst
, class, buffer
, bufsize
, retlen
);
5241 if (retlen
) *retlen
= 0;
5242 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5246 case ActivationContextBasicInformation
:
5248 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5250 if (retlen
) *retlen
= sizeof(*info
);
5251 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5253 info
->hActCtx
= handle
;
5254 info
->dwFlags
= 0; /* FIXME */
5255 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5259 case ActivationContextDetailedInformation
:
5261 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5262 struct assembly
*assembly
= NULL
;
5263 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5266 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5268 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5270 if (assembly
&& assembly
->manifest
.info
)
5271 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5272 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5273 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5274 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5276 if (retlen
) *retlen
= len
;
5277 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5280 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5281 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5282 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5283 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5284 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5285 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5286 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5287 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5288 ptr
= (LPWSTR
)(acdi
+ 1);
5291 acdi
->lpRootManifestPath
= ptr
;
5292 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5293 ptr
+= manifest_len
;
5295 else acdi
->lpRootManifestPath
= NULL
;
5298 acdi
->lpRootConfigurationPath
= ptr
;
5299 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5302 else acdi
->lpRootConfigurationPath
= NULL
;
5305 acdi
->lpAppDirPath
= ptr
;
5306 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5308 else acdi
->lpAppDirPath
= NULL
;
5312 case AssemblyDetailedInformationInActivationContext
:
5314 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5315 struct assembly
*assembly
;
5318 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5321 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5322 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5324 index
= *(DWORD
*)subinst
;
5325 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5327 assembly
= &actctx
->assemblies
[index
- 1];
5329 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5330 id_len
= strlenW(assembly_id
) + 1;
5331 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5333 if (assembly
->manifest
.info
&&
5334 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5335 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5337 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5339 if (retlen
) *retlen
= len
;
5340 if (!buffer
|| bufsize
< len
)
5342 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5343 return STATUS_BUFFER_TOO_SMALL
;
5346 afdi
->ulFlags
= 0; /* FIXME */
5347 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5348 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5349 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5350 /* FIXME afdi->liManifestLastWriteTime = 0; */
5351 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5352 afdi
->ulPolicyPathLength
= 0;
5353 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5354 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5355 afdi
->ulManifestVersionMajor
= 1;
5356 afdi
->ulManifestVersionMinor
= 0;
5357 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5358 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5359 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5360 ptr
= (LPWSTR
)(afdi
+ 1);
5361 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5362 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5366 afdi
->lpAssemblyManifestPath
= ptr
;
5367 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5369 } else afdi
->lpAssemblyManifestPath
= NULL
;
5370 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5373 afdi
->lpAssemblyDirectoryName
= ptr
;
5374 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5376 else afdi
->lpAssemblyDirectoryName
= NULL
;
5377 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5381 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5383 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5384 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5385 struct assembly
*assembly
;
5386 struct dll_redirect
*dll
;
5387 SIZE_T len
, dll_len
= 0;
5390 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5391 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5393 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5394 return STATUS_INVALID_PARAMETER
;
5395 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5397 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5398 return STATUS_INVALID_PARAMETER
;
5399 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5401 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5402 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5404 if (!buffer
|| bufsize
< len
)
5406 if (retlen
) *retlen
= len
;
5407 return STATUS_BUFFER_TOO_SMALL
;
5409 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5410 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5411 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5412 afdi
->ulPathLength
= 0; /* FIXME */
5413 ptr
= (LPWSTR
)(afdi
+ 1);
5416 afdi
->lpFileName
= ptr
;
5417 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5418 } else afdi
->lpFileName
= NULL
;
5419 afdi
->lpFilePath
= NULL
; /* FIXME */
5423 case CompatibilityInformationInActivationContext
:
5425 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5426 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5427 struct assembly
*assembly
= NULL
;
5428 ULONG num_compat_contexts
= 0, n
;
5431 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5433 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5436 num_compat_contexts
= assembly
->num_compat_contexts
;
5437 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5439 if (retlen
) *retlen
= len
;
5440 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5442 *acci
= num_compat_contexts
;
5443 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5444 for (n
= 0; n
< num_compat_contexts
; ++n
)
5446 elements
[n
] = assembly
->compat_contexts
[n
];
5451 case RunlevelInformationInActivationContext
:
5453 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5454 struct assembly
*assembly
;
5457 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5459 len
= sizeof(*acrli
);
5460 if (retlen
) *retlen
= len
;
5461 if (!buffer
|| bufsize
< len
)
5462 return STATUS_BUFFER_TOO_SMALL
;
5464 assembly
= actctx
->assemblies
;
5467 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5468 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5473 FIXME( "class %u not implemented\n", class );
5474 return STATUS_NOT_IMPLEMENTED
;
5476 return STATUS_SUCCESS
;
5479 /***********************************************************************
5480 * RtlFindActivationContextSectionString (NTDLL.@)
5482 * Find information about a string in an activation context.
5483 * FIXME: function signature/prototype may be wrong
5485 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5486 const UNICODE_STRING
*section_name
, PVOID ptr
)
5488 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5489 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5491 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5492 debugstr_us(section_name
), data
);
5496 FIXME("expected guid == NULL\n");
5497 return STATUS_INVALID_PARAMETER
;
5499 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5501 FIXME("unknown flags %08x\n", flags
);
5502 return STATUS_INVALID_PARAMETER
;
5504 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5505 !section_name
|| !section_name
->Buffer
)
5507 WARN("invalid parameter\n");
5508 return STATUS_INVALID_PARAMETER
;
5511 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5513 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5514 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5517 if (status
!= STATUS_SUCCESS
)
5518 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5523 /***********************************************************************
5524 * RtlFindActivationContextSectionGuid (NTDLL.@)
5526 * Find information about a GUID in an activation context.
5527 * FIXME: function signature/prototype may be wrong
5529 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5530 const GUID
*guid
, void *ptr
)
5532 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5533 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5535 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5539 FIXME("expected extguid == NULL\n");
5540 return STATUS_INVALID_PARAMETER
;
5543 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5545 FIXME("unknown flags %08x\n", flags
);
5546 return STATUS_INVALID_PARAMETER
;
5549 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5550 return STATUS_INVALID_PARAMETER
;
5552 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5554 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5555 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5558 if (status
!= STATUS_SUCCESS
)
5559 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5565 /***********************************************************************
5566 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5568 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5569 const WCHAR
*settings
, WCHAR
*buffer
,
5570 SIZE_T size
, SIZE_T
*written
)
5572 ACTIVATION_CONTEXT
*actctx
= check_actctx( handle
);
5577 WARN( "unknown flags %08x\n", flags
);
5578 return STATUS_INVALID_PARAMETER
;
5583 if (strcmpW( ns
, windowsSettings2005NSW
) &&
5584 strcmpW( ns
, windowsSettings2011NSW
) &&
5585 strcmpW( ns
, windowsSettings2016NSW
) &&
5586 strcmpW( ns
, windowsSettings2017NSW
))
5587 return STATUS_INVALID_PARAMETER
;
5589 else ns
= windowsSettings2005NSW
;
5591 if (!handle
) handle
= process_actctx
;
5592 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5594 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5596 if (written
) *written
= strlenW(res
) + 1;
5597 if (size
< strlenW(res
)) return STATUS_BUFFER_TOO_SMALL
;
5598 strcpyW( buffer
, res
);
5599 return STATUS_SUCCESS
;