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
);
2840 /* let's assume utf-8 for now */
2841 RtlUTF8ToUnicodeN( NULL
, 0, &len
, buffer
, size
);
2842 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
2843 RtlUTF8ToUnicodeN( new_buff
, len
, &len
, buffer
, size
);
2844 xmlbuf
.ptr
= new_buff
;
2845 xmlbuf
.end
= xmlbuf
.ptr
+ len
/ sizeof(WCHAR
);
2846 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2847 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2852 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2854 OBJECT_ATTRIBUTES attr
;
2857 attr
.Length
= sizeof(attr
);
2858 attr
.RootDirectory
= 0;
2859 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2860 attr
.ObjectName
= name
;
2861 attr
.SecurityDescriptor
= NULL
;
2862 attr
.SecurityQualityOfService
= NULL
;
2863 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2866 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2872 LdrLockLoaderLock(0, NULL
, &magic
);
2873 status
= LdrFindEntryForAddress( module
, &pldr
);
2874 if (status
== STATUS_SUCCESS
)
2876 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2877 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2879 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2880 str
->Length
= pldr
->FullDllName
.Length
;
2881 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2883 else status
= STATUS_NO_MEMORY
;
2885 LdrUnlockLoaderLock(0, magic
);
2889 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2890 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2891 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2894 UNICODE_STRING nameW
;
2895 LDR_RESOURCE_INFO info
;
2896 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2899 if (TRACE_ON(actctx
))
2901 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2903 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2904 hModule
, debugstr_w(nameW
.Buffer
) );
2905 RtlFreeUnicodeString( &nameW
);
2907 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2908 hModule
, debugstr_w(filename
) );
2911 if (!resname
) return STATUS_INVALID_PARAMETER
;
2913 info
.Type
= RT_MANIFEST
;
2914 info
.Language
= lang
;
2915 if (!((ULONG_PTR
)resname
>> 16))
2917 info
.Name
= (ULONG_PTR
)resname
;
2918 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2920 else if (resname
[0] == '#')
2923 RtlInitUnicodeString(&nameW
, resname
+ 1);
2924 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2925 return STATUS_INVALID_PARAMETER
;
2927 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2931 RtlCreateUnicodeString(&nameW
, resname
);
2932 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2933 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2934 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2935 RtlFreeUnicodeString(&nameW
);
2937 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2939 if (status
== STATUS_SUCCESS
)
2940 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2945 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2946 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2947 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2950 OBJECT_ATTRIBUTES attr
;
2952 LARGE_INTEGER offset
;
2957 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2959 attr
.Length
= sizeof(attr
);
2960 attr
.RootDirectory
= 0;
2961 attr
.ObjectName
= NULL
;
2962 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2963 attr
.SecurityDescriptor
= NULL
;
2964 attr
.SecurityQualityOfService
= NULL
;
2967 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2968 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2969 if (status
!= STATUS_SUCCESS
) return status
;
2971 offset
.QuadPart
= 0;
2974 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2975 &count
, ViewShare
, 0, PAGE_READONLY
);
2977 if (status
!= STATUS_SUCCESS
) return status
;
2979 if (RtlImageNtHeader(base
)) /* we got a PE file */
2981 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2982 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2984 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2986 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2990 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2991 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2993 FILE_END_OF_FILE_INFORMATION info
;
2996 OBJECT_ATTRIBUTES attr
;
2998 LARGE_INTEGER offset
;
3003 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
3005 attr
.Length
= sizeof(attr
);
3006 attr
.RootDirectory
= 0;
3007 attr
.ObjectName
= NULL
;
3008 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3009 attr
.SecurityDescriptor
= NULL
;
3010 attr
.SecurityQualityOfService
= NULL
;
3013 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3014 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3015 if (status
!= STATUS_SUCCESS
) return status
;
3017 offset
.QuadPart
= 0;
3020 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3021 &count
, ViewShare
, 0, PAGE_READONLY
);
3023 if (status
!= STATUS_SUCCESS
) return status
;
3025 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
3026 if (status
== STATUS_SUCCESS
)
3027 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
3029 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3033 /* try to load the .manifest file associated to the file */
3034 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3035 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3037 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
3040 UNICODE_STRING nameW
;
3042 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3044 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
3046 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
3048 if (module
) /* use the module filename */
3050 UNICODE_STRING name
;
3052 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
3054 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
3055 strcatW( name
.Buffer
, dotManifestW
);
3056 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3057 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3058 RtlFreeUnicodeString( &name
);
3060 if (status
) return status
;
3064 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3065 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3066 return STATUS_NO_MEMORY
;
3067 strcpyW( buffer
, filename
);
3068 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
3069 strcatW( buffer
, dotManifestW
);
3070 RtlInitUnicodeString( &nameW
, buffer
);
3073 if (!open_nt_file( &file
, &nameW
))
3075 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3078 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
3079 RtlFreeUnicodeString( &nameW
);
3083 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3085 static const WCHAR lookup_fmtW
[] =
3086 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3087 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3088 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3090 WCHAR
*lookup
, *ret
= NULL
;
3091 UNICODE_STRING lookup_us
;
3093 const WCHAR
*lang
= ai
->language
;
3094 unsigned int data_pos
= 0, data_len
;
3097 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
3099 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
3100 (strlenW(ai
->arch
) + strlenW(ai
->name
)
3101 + strlenW(ai
->public_key
) + strlenW(lang
) + 20) * sizeof(WCHAR
)
3102 + sizeof(lookup_fmtW
) )))
3104 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3105 ai
->version
.major
, ai
->version
.minor
, lang
);
3106 RtlInitUnicodeString( &lookup_us
, lookup
);
3108 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3109 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3111 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3112 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3114 ULONG build
, revision
;
3116 data_len
= io
.Information
;
3120 if (data_pos
>= data_len
)
3122 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3123 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3125 data_len
= io
.Information
;
3128 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3130 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3131 else data_pos
= data_len
;
3133 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
3135 if (build
< min_build
) continue;
3136 tmp
= strchrW(tmp
, '.') + 1;
3137 revision
= atoiW(tmp
);
3138 if (build
== min_build
&& revision
< min_revision
) continue;
3139 tmp
= strchrW(tmp
, '_') + 1;
3140 tmp
= strchrW(tmp
, '_') + 1;
3141 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3142 !strncmpiW( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3144 /* prefer a non-Wine manifest if we already have one */
3145 /* we'll still load the builtin dll if specified through DllOverrides */
3151 min_revision
= revision
;
3153 ai
->version
.build
= build
;
3154 ai
->version
.revision
= revision
;
3155 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3156 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3158 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3159 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3163 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3164 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3168 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3170 struct assembly_identity sxs_ai
;
3171 UNICODE_STRING path_us
;
3172 OBJECT_ATTRIBUTES attr
;
3174 WCHAR
*path
, *file
= NULL
;
3177 static const WCHAR manifest_dirW
[] =
3178 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3180 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3182 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
3183 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
3184 return STATUS_NO_MEMORY
;
3186 strcpyW( path
, user_shared_data
->NtSystemRoot
);
3187 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
3189 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3191 RtlFreeHeap( GetProcessHeap(), 0, path
);
3192 return STATUS_NO_SUCH_FILE
;
3194 RtlFreeHeap( GetProcessHeap(), 0, path
);
3196 attr
.Length
= sizeof(attr
);
3197 attr
.RootDirectory
= 0;
3198 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3199 attr
.ObjectName
= &path_us
;
3200 attr
.SecurityDescriptor
= NULL
;
3201 attr
.SecurityQualityOfService
= NULL
;
3203 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3204 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3207 file
= lookup_manifest_file( handle
, &sxs_ai
);
3212 RtlFreeUnicodeString( &path_us
);
3213 return STATUS_NO_SUCH_FILE
;
3216 /* append file name to directory path */
3217 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3218 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
3220 RtlFreeHeap( GetProcessHeap(), 0, file
);
3221 RtlFreeUnicodeString( &path_us
);
3222 return STATUS_NO_MEMORY
;
3225 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3226 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3227 RtlInitUnicodeString( &path_us
, path
);
3228 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
3230 if (!open_nt_file( &handle
, &path_us
))
3232 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3235 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3237 RtlFreeHeap( GetProcessHeap(), 0, file
);
3238 RtlFreeUnicodeString( &path_us
);
3242 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3243 struct assembly_identity
* ai
)
3245 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3247 WCHAR
*buffer
, *p
, *directory
;
3249 UNICODE_STRING nameW
;
3253 TRACE( "looking for name=%s version=%s arch=%s\n",
3254 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3256 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3258 /* FIXME: add support for language specific lookup */
3260 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3261 strlenW(acl
->actctx
->appdir
.info
));
3263 nameW
.Buffer
= NULL
;
3264 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3265 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3266 return STATUS_NO_MEMORY
;
3268 if (!(directory
= build_assembly_dir( ai
)))
3270 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3271 return STATUS_NO_MEMORY
;
3274 /* Lookup in <dir>\name.dll
3275 * <dir>\name.manifest
3276 * <dir>\name\name.dll
3277 * <dir>\name\name.manifest
3279 * First 'appdir' is used as <dir>, if that failed
3280 * it tries application manifest file path.
3282 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3283 p
= buffer
+ strlenW(buffer
);
3284 for (i
= 0; i
< 4; i
++)
3288 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3289 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3293 strcpyW( p
, ai
->name
);
3296 strcpyW( p
, dotDllW
);
3297 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3299 status
= open_nt_file( &file
, &nameW
);
3302 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3303 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3305 if (status
== STATUS_SUCCESS
)
3308 RtlFreeUnicodeString( &nameW
);
3311 strcpyW( p
, dotManifestW
);
3312 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3314 status
= open_nt_file( &file
, &nameW
);
3317 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3321 RtlFreeUnicodeString( &nameW
);
3323 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3325 RtlFreeUnicodeString( &nameW
);
3326 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3327 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3331 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3333 NTSTATUS status
= STATUS_SUCCESS
;
3336 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3338 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3340 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3342 FIXME( "Could not find dependent assembly %s (%s)\n",
3343 debugstr_w(acl
->dependencies
[i
].name
),
3344 debugstr_version(&acl
->dependencies
[i
].version
) );
3345 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3350 /* FIXME should now iterate through all refs */
3354 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3355 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3357 NTSTATUS status
= STATUS_SUCCESS
;
3359 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3361 if (*handle
) return STATUS_INVALID_PARAMETER
;
3363 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3364 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3366 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3371 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3373 LdrLockLoaderLock( 0, NULL
, &magic
);
3374 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3376 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
3377 status
= STATUS_DLL_NOT_FOUND
;
3379 *handle
= pldr
->ActivationContext
;
3381 else status
= STATUS_DLL_NOT_FOUND
;
3382 LdrUnlockLoaderLock( 0, magic
);
3384 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3385 *handle
= process_actctx
;
3390 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3392 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3393 struct strsection_header
*header
;
3394 struct dllredirect_data
*data
;
3395 struct string_index
*index
;
3398 /* compute section length */
3399 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3401 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3402 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3404 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3406 /* each entry needs index, data and string data */
3407 total_len
+= sizeof(*index
);
3408 total_len
+= sizeof(*data
);
3409 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3412 dll_count
+= assembly
->num_dlls
;
3415 total_len
+= sizeof(*header
);
3417 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3418 if (!header
) return STATUS_NO_MEMORY
;
3420 memset(header
, 0, sizeof(*header
));
3421 header
->magic
= STRSECTION_MAGIC
;
3422 header
->size
= sizeof(*header
);
3423 header
->count
= dll_count
;
3424 header
->index_offset
= sizeof(*header
);
3425 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3426 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3428 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3430 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3431 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3433 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3437 /* setup new index entry */
3438 str
.Buffer
= dll
->name
;
3439 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3440 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3441 /* hash original class name */
3442 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3444 index
->name_offset
= name_offset
;
3445 index
->name_len
= str
.Length
;
3446 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3447 index
->data_len
= sizeof(*data
);
3448 index
->rosterindex
= i
+ 1;
3451 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3452 data
->size
= sizeof(*data
);
3453 data
->unk
= 2; /* FIXME: seems to be constant */
3454 memset(data
->res
, 0, sizeof(data
->res
));
3457 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3458 memcpy(ptrW
, dll
->name
, index
->name_len
);
3459 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3461 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3469 return STATUS_SUCCESS
;
3472 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3474 struct string_index
*iter
, *index
= NULL
;
3477 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3478 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3480 for (i
= 0; i
< section
->count
; i
++)
3482 if (iter
->hash
== hash
)
3484 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3486 if (!strcmpiW(nameW
, name
->Buffer
))
3492 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3500 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3502 struct guid_index
*iter
, *index
= NULL
;
3505 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3507 for (i
= 0; i
< section
->count
; i
++)
3509 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3520 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3522 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3525 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3526 PACTCTX_SECTION_KEYED_DATA data
)
3528 struct dllredirect_data
*dll
;
3529 struct string_index
*index
;
3531 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3533 if (!actctx
->dllredirect_section
)
3535 struct strsection_header
*section
;
3537 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3538 if (status
) return status
;
3540 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3541 RtlFreeHeap(GetProcessHeap(), 0, section
);
3544 index
= find_string_index(actctx
->dllredirect_section
, name
);
3545 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3549 dll
= get_dllredirect_data(actctx
, index
);
3551 data
->ulDataFormatVersion
= 1;
3553 data
->ulLength
= dll
->size
;
3554 data
->lpSectionGlobalData
= NULL
;
3555 data
->ulSectionGlobalDataLength
= 0;
3556 data
->lpSectionBase
= actctx
->dllredirect_section
;
3557 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3558 data
->hActCtx
= NULL
;
3560 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3561 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3564 return STATUS_SUCCESS
;
3567 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3569 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3572 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3574 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3577 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3579 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3580 struct wndclass_redirect_data
*data
;
3581 struct strsection_header
*header
;
3582 struct string_index
*index
;
3585 /* compute section length */
3586 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3588 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3589 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3591 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3592 for (k
= 0; k
< dll
->entities
.num
; k
++)
3594 struct entity
*entity
= &dll
->entities
.base
[k
];
3595 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3597 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3600 /* each class entry needs index, data and string data */
3601 total_len
+= sizeof(*index
);
3602 total_len
+= sizeof(*data
);
3603 /* original name is stored separately */
3604 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3605 /* versioned name and module name are stored one after another */
3606 if (entity
->u
.class.versioned
)
3607 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3610 len
+= strlenW(dll
->name
) + 1;
3611 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3619 total_len
+= sizeof(*header
);
3621 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3622 if (!header
) return STATUS_NO_MEMORY
;
3624 memset(header
, 0, sizeof(*header
));
3625 header
->magic
= STRSECTION_MAGIC
;
3626 header
->size
= sizeof(*header
);
3627 header
->count
= class_count
;
3628 header
->index_offset
= sizeof(*header
);
3629 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3630 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3632 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3634 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3635 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3637 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3638 for (k
= 0; k
< dll
->entities
.num
; k
++)
3640 struct entity
*entity
= &dll
->entities
.base
[k
];
3641 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3643 static const WCHAR exclW
[] = {'!',0};
3644 ULONG versioned_len
, module_len
;
3648 /* setup new index entry */
3649 str
.Buffer
= entity
->u
.class.name
;
3650 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3651 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3652 /* hash original class name */
3653 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3655 /* include '!' separator too */
3656 if (entity
->u
.class.versioned
)
3657 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3659 versioned_len
= str
.Length
;
3660 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3662 index
->name_offset
= name_offset
;
3663 index
->name_len
= str
.Length
;
3664 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3665 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3666 index
->rosterindex
= i
+ 1;
3669 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3670 data
->size
= sizeof(*data
);
3672 data
->name_len
= versioned_len
;
3673 data
->name_offset
= sizeof(*data
);
3674 data
->module_len
= module_len
;
3675 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3677 /* original class name */
3678 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3679 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3680 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3683 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3684 memcpy(ptrW
, dll
->name
, data
->module_len
);
3685 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3687 /* versioned name */
3688 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3689 if (entity
->u
.class.versioned
)
3691 get_assembly_version(assembly
, ptrW
);
3692 strcatW(ptrW
, exclW
);
3693 strcatW(ptrW
, entity
->u
.class.name
);
3697 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3698 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3701 name_offset
+= sizeof(*data
);
3702 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3712 return STATUS_SUCCESS
;
3715 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3716 PACTCTX_SECTION_KEYED_DATA data
)
3718 struct string_index
*iter
, *index
= NULL
;
3719 struct wndclass_redirect_data
*class;
3723 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3725 if (!actctx
->wndclass_section
)
3727 struct strsection_header
*section
;
3729 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3730 if (status
) return status
;
3732 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3733 RtlFreeHeap(GetProcessHeap(), 0, section
);
3737 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3738 iter
= get_wndclass_first_index(actctx
);
3740 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3742 if (iter
->hash
== hash
)
3744 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3746 if (!strcmpiW(nameW
, name
->Buffer
))
3752 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3757 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3761 class = get_wndclass_data(actctx
, index
);
3763 data
->ulDataFormatVersion
= 1;
3764 data
->lpData
= class;
3765 /* full length includes string length with nulls */
3766 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3767 data
->lpSectionGlobalData
= NULL
;
3768 data
->ulSectionGlobalDataLength
= 0;
3769 data
->lpSectionBase
= actctx
->wndclass_section
;
3770 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3771 data
->hActCtx
= NULL
;
3773 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3774 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3777 return STATUS_SUCCESS
;
3780 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3782 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3783 struct guidsection_header
*header
;
3784 ULONG module_offset
, data_offset
;
3785 struct tlibredirect_data
*data
;
3786 struct guid_index
*index
;
3788 /* compute section length */
3789 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3791 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3792 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3794 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3795 for (k
= 0; k
< dll
->entities
.num
; k
++)
3797 struct entity
*entity
= &dll
->entities
.base
[k
];
3798 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3800 /* each entry needs index, data and string data for module name and help string */
3801 total_len
+= sizeof(*index
);
3802 total_len
+= sizeof(*data
);
3803 /* help string is stored separately */
3804 if (*entity
->u
.typelib
.helpdir
)
3805 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3807 /* module names are packed one after another */
3808 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3816 total_len
+= aligned_string_len(names_len
);
3817 total_len
+= sizeof(*header
);
3819 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3820 if (!header
) return STATUS_NO_MEMORY
;
3822 memset(header
, 0, sizeof(*header
));
3823 header
->magic
= GUIDSECTION_MAGIC
;
3824 header
->size
= sizeof(*header
);
3825 header
->count
= tlib_count
;
3826 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3827 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3828 module_offset
= sizeof(*header
);
3829 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3831 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3833 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3834 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3836 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3837 for (k
= 0; k
< dll
->entities
.num
; k
++)
3839 struct entity
*entity
= &dll
->entities
.base
[k
];
3840 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3842 ULONG module_len
, help_len
;
3846 if (*entity
->u
.typelib
.helpdir
)
3847 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3851 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3853 /* setup new index entry */
3854 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3855 RtlGUIDFromString(&str
, &index
->guid
);
3856 index
->data_offset
= data_offset
;
3857 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3858 index
->rosterindex
= i
+ 1;
3861 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3862 data
->size
= sizeof(*data
);
3864 data
->name_len
= module_len
;
3865 data
->name_offset
= module_offset
;
3866 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3868 data
->flags
= entity
->u
.typelib
.flags
;
3869 data
->help_len
= help_len
;
3870 data
->help_offset
= sizeof(*data
);
3871 data
->major_version
= entity
->u
.typelib
.major
;
3872 data
->minor_version
= entity
->u
.typelib
.minor
;
3875 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3876 memcpy(ptrW
, dll
->name
, data
->name_len
);
3877 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3882 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3883 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3884 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3887 data_offset
+= sizeof(*data
);
3889 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3891 module_offset
+= module_len
+ sizeof(WCHAR
);
3901 return STATUS_SUCCESS
;
3904 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3906 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3909 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3911 struct guid_index
*index
= NULL
;
3912 struct tlibredirect_data
*tlib
;
3914 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3916 if (!actctx
->tlib_section
)
3918 struct guidsection_header
*section
;
3920 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3921 if (status
) return status
;
3923 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3924 RtlFreeHeap(GetProcessHeap(), 0, section
);
3927 index
= find_guid_index(actctx
->tlib_section
, guid
);
3928 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3930 tlib
= get_tlib_data(actctx
, index
);
3932 data
->ulDataFormatVersion
= 1;
3933 data
->lpData
= tlib
;
3934 /* full length includes string length with nulls */
3935 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3936 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3937 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3938 data
->lpSectionBase
= actctx
->tlib_section
;
3939 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3940 data
->hActCtx
= NULL
;
3942 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3943 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3945 return STATUS_SUCCESS
;
3948 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3950 ULONG
*ptr
= (ULONG
*)guid
;
3953 /* GUID is 16 bytes long */
3954 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3955 *ptr
= RtlUniform(seed
);
3957 guid
->Data3
&= 0x0fff;
3958 guid
->Data3
|= (4 << 12);
3959 guid
->Data4
[0] &= 0x3f;
3960 guid
->Data4
[0] |= 0x80;
3963 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3964 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3968 for (i
= 0; i
< entities
->num
; i
++)
3970 struct entity
*entity
= &entities
->base
[i
];
3971 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3973 /* each entry needs two index entries, extra one goes for alias GUID */
3974 *len
+= 2*sizeof(struct guid_index
);
3975 /* To save some memory we don't allocated two data structures,
3976 instead alias index and normal index point to the same data structure. */
3977 *len
+= sizeof(struct comclassredirect_data
);
3979 /* for clrClass store some more */
3980 if (entity
->u
.comclass
.name
)
3982 unsigned int str_len
;
3984 /* all string data is stored together in aligned block */
3985 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3986 if (entity
->u
.comclass
.progid
)
3987 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3988 if (entity
->u
.comclass
.version
)
3989 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3991 *len
+= sizeof(struct clrclass_data
);
3992 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3994 /* module name is forced to mscoree.dll, and stored two times with different case */
3995 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3999 /* progid string is stored separately */
4000 if (entity
->u
.comclass
.progid
)
4001 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4003 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
4011 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4012 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4013 ULONG
*seed
, ULONG rosterindex
)
4017 for (i
= 0; i
< entities
->num
; i
++)
4019 struct entity
*entity
= &entities
->base
[i
];
4020 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4022 ULONG module_len
, progid_len
, str_len
= 0;
4023 struct comclassredirect_data
*data
;
4024 struct guid_index
*alias_index
;
4025 struct clrclass_data
*clrdata
;
4029 if (entity
->u
.comclass
.progid
)
4030 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4034 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
4036 /* setup new index entry */
4037 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4038 RtlGUIDFromString(&str
, &(*index
)->guid
);
4040 (*index
)->data_offset
= *data_offset
;
4041 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4042 (*index
)->rosterindex
= rosterindex
;
4044 /* Setup new index entry for alias guid. Alias index records are placed after
4045 normal records, so normal guids are hit first on search. Note that class count
4047 alias_index
= (*index
) + section
->count
/2;
4048 generate_uuid(seed
, &alias_index
->guid
);
4049 alias_index
->data_offset
= (*index
)->data_offset
;
4050 alias_index
->data_len
= 0;
4051 alias_index
->rosterindex
= (*index
)->rosterindex
;
4054 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4055 data
->size
= sizeof(*data
);
4059 data
->model
= entity
->u
.comclass
.model
;
4060 data
->clsid
= (*index
)->guid
;
4061 data
->alias
= alias_index
->guid
;
4062 data
->clsid2
= data
->clsid
;
4063 if (entity
->u
.comclass
.tlbid
)
4065 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4066 RtlGUIDFromString(&str
, &data
->tlbid
);
4069 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4070 data
->name_len
= module_len
;
4071 data
->name_offset
= *module_offset
;
4072 data
->progid_len
= progid_len
;
4073 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4074 data
->clrdata_len
= 0; /* will be set later */
4075 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4076 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4077 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4078 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4079 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4080 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4082 /* mask describes which misc* data is available */
4084 if (data
->miscstatus
)
4085 data
->miscmask
|= MiscStatus
;
4086 if (data
->miscstatuscontent
)
4087 data
->miscmask
|= MiscStatusContent
;
4088 if (data
->miscstatusthumbnail
)
4089 data
->miscmask
|= MiscStatusThumbnail
;
4090 if (data
->miscstatusicon
)
4091 data
->miscmask
|= MiscStatusIcon
;
4092 if (data
->miscstatusdocprint
)
4093 data
->miscmask
|= MiscStatusDocPrint
;
4095 if (data
->clrdata_offset
)
4097 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4099 clrdata
->size
= sizeof(*clrdata
);
4100 clrdata
->res
[0] = 0;
4101 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4102 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
4103 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4104 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4105 clrdata
->name_offset
= clrdata
->size
;
4106 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4107 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4108 clrdata
->res2
[0] = 0;
4109 clrdata
->res2
[1] = 0;
4111 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4114 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4115 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
4116 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4118 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4119 memcpy(ptrW
, mscoreeW
, data
->name_len
);
4120 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4123 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4124 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4125 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4127 /* runtime version, optional */
4128 if (clrdata
->version_len
)
4130 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4132 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4133 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4134 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4137 if (data
->progid_len
)
4138 data
->progid_offset
+= data
->clrdata_len
;
4139 (*index
)->data_len
+= sizeof(*clrdata
);
4146 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4147 memcpy(ptrW
, dll
->name
, data
->name_len
);
4148 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4152 if (data
->progid_len
)
4154 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4155 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4156 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4159 /* string block length */
4163 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4164 if (clrdata
->version_len
)
4165 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4168 str_len
+= progid_len
+ sizeof(WCHAR
);
4170 (*index
)->data_len
+= aligned_string_len(str_len
);
4171 alias_index
->data_len
= (*index
)->data_len
;
4173 /* move to next data record */
4174 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4175 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4179 (*data_offset
) += sizeof(*clrdata
);
4180 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4187 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4189 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4190 struct guidsection_header
*header
;
4191 ULONG module_offset
, data_offset
;
4192 struct guid_index
*index
;
4195 /* compute section length */
4196 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4198 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4199 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4200 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4202 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4203 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4207 total_len
+= aligned_string_len(names_len
);
4208 total_len
+= sizeof(*header
);
4210 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4211 if (!header
) return STATUS_NO_MEMORY
;
4213 memset(header
, 0, sizeof(*header
));
4214 header
->magic
= GUIDSECTION_MAGIC
;
4215 header
->size
= sizeof(*header
);
4216 header
->count
= 2*class_count
;
4217 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4218 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4219 module_offset
= sizeof(*header
);
4220 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4222 seed
= NtGetTickCount();
4223 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4225 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4226 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4227 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4229 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4230 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4236 return STATUS_SUCCESS
;
4239 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4241 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4244 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4246 struct comclassredirect_data
*comclass
;
4247 struct guid_index
*index
= NULL
;
4249 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4251 if (!actctx
->comserver_section
)
4253 struct guidsection_header
*section
;
4255 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4256 if (status
) return status
;
4258 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4259 RtlFreeHeap(GetProcessHeap(), 0, section
);
4262 index
= find_guid_index(actctx
->comserver_section
, guid
);
4263 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4265 comclass
= get_comclass_data(actctx
, index
);
4267 data
->ulDataFormatVersion
= 1;
4268 data
->lpData
= comclass
;
4269 /* full length includes string length with nulls */
4270 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4271 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4272 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4273 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4274 data
->lpSectionBase
= actctx
->comserver_section
;
4275 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4276 data
->hActCtx
= NULL
;
4278 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4279 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4281 return STATUS_SUCCESS
;
4284 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4288 for (i
= 0; i
< entities
->num
; i
++)
4290 struct entity
*entity
= &entities
->base
[i
];
4291 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4293 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4294 if (entity
->u
.ifaceps
.name
)
4295 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4301 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4302 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4306 for (i
= 0; i
< entities
->num
; i
++)
4308 struct entity
*entity
= &entities
->base
[i
];
4309 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4311 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4315 if (entity
->u
.ifaceps
.name
)
4316 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4321 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4322 RtlGUIDFromString(&str
, &(*index
)->guid
);
4323 (*index
)->data_offset
= *data_offset
;
4324 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4325 (*index
)->rosterindex
= rosterindex
;
4327 /* setup data record */
4328 data
->size
= sizeof(*data
);
4329 data
->mask
= entity
->u
.ifaceps
.mask
;
4331 /* proxyStubClsid32 value is only stored for external PS,
4332 if set it's used as iid, otherwise 'iid' attribute value is used */
4333 if (entity
->u
.ifaceps
.ps32
)
4335 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4336 RtlGUIDFromString(&str
, &data
->iid
);
4339 data
->iid
= (*index
)->guid
;
4341 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4343 if (entity
->u
.ifaceps
.tlib
)
4345 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4346 RtlGUIDFromString(&str
, &data
->tlbid
);
4349 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4351 if (entity
->u
.ifaceps
.base
)
4353 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4354 RtlGUIDFromString(&str
, &data
->base
);
4357 memset(&data
->base
, 0, sizeof(data
->base
));
4359 data
->name_len
= name_len
;
4360 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4365 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4366 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4367 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4370 /* move to next record */
4372 *data_offset
+= sizeof(*data
);
4374 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4379 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4381 unsigned int i
, j
, total_len
= 0, count
= 0;
4382 struct guidsection_header
*header
;
4383 struct guid_index
*index
;
4386 /* compute section length */
4387 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4389 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4391 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4392 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4394 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4395 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4399 total_len
+= sizeof(*header
);
4401 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4402 if (!header
) return STATUS_NO_MEMORY
;
4404 memset(header
, 0, sizeof(*header
));
4405 header
->magic
= GUIDSECTION_MAGIC
;
4406 header
->size
= sizeof(*header
);
4407 header
->count
= count
;
4408 header
->index_offset
= sizeof(*header
);
4409 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4410 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4412 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4414 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4416 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4417 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4419 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4420 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4426 return STATUS_SUCCESS
;
4429 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4431 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4434 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4436 struct ifacepsredirect_data
*iface
;
4437 struct guid_index
*index
= NULL
;
4439 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4441 if (!actctx
->ifaceps_section
)
4443 struct guidsection_header
*section
;
4445 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4446 if (status
) return status
;
4448 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4449 RtlFreeHeap(GetProcessHeap(), 0, section
);
4452 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4453 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4455 iface
= get_ifaceps_data(actctx
, index
);
4457 data
->ulDataFormatVersion
= 1;
4458 data
->lpData
= iface
;
4459 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4460 data
->lpSectionGlobalData
= NULL
;
4461 data
->ulSectionGlobalDataLength
= 0;
4462 data
->lpSectionBase
= actctx
->ifaceps_section
;
4463 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4464 data
->hActCtx
= NULL
;
4466 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4467 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4469 return STATUS_SUCCESS
;
4472 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4474 unsigned int i
, j
, total_len
= 0, count
= 0;
4475 struct guidsection_header
*header
;
4476 struct clrsurrogate_data
*data
;
4477 struct guid_index
*index
;
4480 /* compute section length */
4481 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4483 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4484 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4486 struct entity
*entity
= &assembly
->entities
.base
[j
];
4487 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4491 total_len
+= sizeof(*index
) + sizeof(*data
);
4492 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4493 if (entity
->u
.clrsurrogate
.version
)
4494 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4495 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4502 total_len
+= sizeof(*header
);
4504 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4505 if (!header
) return STATUS_NO_MEMORY
;
4507 memset(header
, 0, sizeof(*header
));
4508 header
->magic
= GUIDSECTION_MAGIC
;
4509 header
->size
= sizeof(*header
);
4510 header
->count
= count
;
4511 header
->index_offset
= sizeof(*header
);
4512 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4513 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4515 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4517 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4518 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4520 struct entity
*entity
= &assembly
->entities
.base
[j
];
4521 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4523 ULONG version_len
, name_len
;
4527 if (entity
->u
.clrsurrogate
.version
)
4528 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4531 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4533 /* setup new index entry */
4534 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4535 RtlGUIDFromString(&str
, &index
->guid
);
4537 index
->data_offset
= data_offset
;
4538 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4539 index
->rosterindex
= i
+ 1;
4542 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4543 data
->size
= sizeof(*data
);
4545 data
->clsid
= index
->guid
;
4546 data
->version_offset
= version_len
? data
->size
: 0;
4547 data
->version_len
= version_len
;
4548 data
->name_offset
= data
->size
+ version_len
;
4550 data
->name_offset
+= sizeof(WCHAR
);
4551 data
->name_len
= name_len
;
4553 /* surrogate name */
4554 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4555 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4556 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4558 /* runtime version */
4559 if (data
->version_len
)
4561 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4562 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4563 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4566 data_offset
+= index
->data_offset
;
4574 return STATUS_SUCCESS
;
4577 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4579 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4582 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4584 struct clrsurrogate_data
*surrogate
;
4585 struct guid_index
*index
= NULL
;
4587 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4589 if (!actctx
->clrsurrogate_section
)
4591 struct guidsection_header
*section
;
4593 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4594 if (status
) return status
;
4596 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4597 RtlFreeHeap(GetProcessHeap(), 0, section
);
4600 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4601 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4603 surrogate
= get_surrogate_data(actctx
, index
);
4605 data
->ulDataFormatVersion
= 1;
4606 data
->lpData
= surrogate
;
4607 /* full length includes string length with nulls */
4608 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4609 if (surrogate
->version_len
)
4610 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4612 data
->lpSectionGlobalData
= NULL
;
4613 data
->ulSectionGlobalDataLength
= 0;
4614 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4615 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4616 data
->hActCtx
= NULL
;
4618 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4619 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4621 return STATUS_SUCCESS
;
4624 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4626 unsigned int i
, j
, single_len
;
4628 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4629 for (i
= 0; i
< entities
->num
; i
++)
4631 struct entity
*entity
= &entities
->base
[i
];
4632 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4634 if (entity
->u
.comclass
.progid
)
4636 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4640 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4641 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4643 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4644 *count
+= entity
->u
.comclass
.progids
.num
;
4649 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4650 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4652 struct progidredirect_data
*data
;
4657 /* setup new index entry */
4659 /* hash progid name */
4660 RtlInitUnicodeString(&str
, progid
);
4661 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4663 (*index
)->name_offset
= *data_offset
;
4664 (*index
)->name_len
= str
.Length
;
4665 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4666 (*index
)->data_len
= sizeof(*data
);
4667 (*index
)->rosterindex
= rosterindex
;
4669 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4671 /* setup data structure */
4672 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4673 data
->size
= sizeof(*data
);
4675 data
->clsid_offset
= *global_offset
;
4677 /* write progid string */
4678 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4679 memcpy(ptrW
, progid
, (*index
)->name_len
);
4680 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4682 /* write guid to global area */
4683 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4687 *global_offset
+= sizeof(GUID
);
4688 *data_offset
+= data
->size
;
4692 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4693 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4697 for (i
= 0; i
< entities
->num
; i
++)
4699 struct entity
*entity
= &entities
->base
[i
];
4700 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4702 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4703 struct comclassredirect_data
*comclass
;
4704 struct guid_index
*guid_index
;
4708 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4709 RtlGUIDFromString(&str
, &clsid
);
4711 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4712 comclass
= get_comclass_data(actctx
, guid_index
);
4714 if (entity
->u
.comclass
.progid
)
4715 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4716 index
, data_offset
, global_offset
, rosterindex
);
4718 for (j
= 0; j
< progids
->num
; j
++)
4719 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4720 index
, data_offset
, global_offset
, rosterindex
);
4725 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4727 unsigned int i
, j
, total_len
= 0, count
= 0;
4728 struct strsection_header
*header
;
4729 ULONG data_offset
, global_offset
;
4730 struct string_index
*index
;
4732 /* compute section length */
4733 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4735 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4737 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4738 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4740 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4741 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4745 total_len
+= sizeof(*header
);
4747 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4748 if (!header
) return STATUS_NO_MEMORY
;
4750 memset(header
, 0, sizeof(*header
));
4751 header
->magic
= STRSECTION_MAGIC
;
4752 header
->size
= sizeof(*header
);
4753 header
->count
= count
;
4754 header
->global_offset
= header
->size
;
4755 header
->global_len
= count
*sizeof(GUID
);
4756 header
->index_offset
= header
->size
+ header
->global_len
;
4758 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4759 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4760 global_offset
= header
->global_offset
;
4762 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4764 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4766 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4767 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4769 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4770 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4776 return STATUS_SUCCESS
;
4779 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4781 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4784 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4785 PACTCTX_SECTION_KEYED_DATA data
)
4787 struct progidredirect_data
*progid
;
4788 struct string_index
*index
;
4790 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4792 if (!actctx
->comserver_section
)
4794 struct guidsection_header
*section
;
4796 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4797 if (status
) return status
;
4799 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4800 RtlFreeHeap(GetProcessHeap(), 0, section
);
4803 if (!actctx
->progid_section
)
4805 struct strsection_header
*section
;
4807 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4808 if (status
) return status
;
4810 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4811 RtlFreeHeap(GetProcessHeap(), 0, section
);
4814 index
= find_string_index(actctx
->progid_section
, name
);
4815 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4819 progid
= get_progid_data(actctx
, index
);
4821 data
->ulDataFormatVersion
= 1;
4822 data
->lpData
= progid
;
4823 data
->ulLength
= progid
->size
;
4824 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4825 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4826 data
->lpSectionBase
= actctx
->progid_section
;
4827 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4828 data
->hActCtx
= NULL
;
4830 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4831 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4834 return STATUS_SUCCESS
;
4837 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4838 const UNICODE_STRING
*section_name
,
4839 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4843 switch (section_kind
)
4845 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4846 status
= find_dll_redirection(actctx
, section_name
, data
);
4848 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4849 status
= find_window_class(actctx
, section_name
, data
);
4851 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4852 status
= find_progid_redirection(actctx
, section_name
, data
);
4854 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4855 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4856 return STATUS_SXS_SECTION_NOT_FOUND
;
4858 WARN("Unknown section_kind %x\n", section_kind
);
4859 return STATUS_SXS_SECTION_NOT_FOUND
;
4862 if (status
!= STATUS_SUCCESS
) return status
;
4864 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4866 actctx_addref(actctx
);
4867 data
->hActCtx
= actctx
;
4869 return STATUS_SUCCESS
;
4872 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4873 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4877 switch (section_kind
)
4879 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4880 status
= find_tlib_redirection(actctx
, guid
, data
);
4882 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4883 status
= find_comserver_redirection(actctx
, guid
, data
);
4885 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4886 status
= find_cominterface_redirection(actctx
, guid
, data
);
4888 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4889 status
= find_clr_surrogate(actctx
, guid
, data
);
4892 WARN("Unknown section_kind %x\n", section_kind
);
4893 return STATUS_SXS_SECTION_NOT_FOUND
;
4896 if (status
!= STATUS_SUCCESS
) return status
;
4898 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4900 actctx_addref(actctx
);
4901 data
->hActCtx
= actctx
;
4903 return STATUS_SUCCESS
;
4906 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
4910 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4912 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4913 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4915 struct entity
*entity
= &assembly
->entities
.base
[j
];
4916 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
4917 !strcmpW( entity
->u
.settings
.name
, settings
) &&
4918 !strcmpW( entity
->u
.settings
.ns
, ns
))
4919 return entity
->u
.settings
.value
;
4925 /* initialize the activation context for the current process */
4926 void actctx_init(void)
4931 ctx
.cbSize
= sizeof(ctx
);
4932 ctx
.lpSource
= NULL
;
4933 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4934 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4935 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4937 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4941 /***********************************************************************
4942 * RtlCreateActivationContext (NTDLL.@)
4944 * Create an activation context.
4946 * FIXME: function signature/prototype is wrong
4948 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4950 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4951 const WCHAR
*directory
= NULL
;
4952 ACTIVATION_CONTEXT
*actctx
;
4953 UNICODE_STRING nameW
;
4955 NTSTATUS status
= STATUS_NO_MEMORY
;
4957 struct actctx_loader acl
;
4959 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4961 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4962 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4963 return STATUS_INVALID_PARAMETER
;
4965 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4966 return STATUS_NO_MEMORY
;
4968 actctx
->magic
= ACTCTX_MAGIC
;
4969 actctx
->ref_count
= 1;
4970 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4971 actctx
->config
.info
= NULL
;
4972 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4973 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4975 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4983 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4984 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4986 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4987 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4988 actctx
->appdir
.info
= dir
.Buffer
;
4991 nameW
.Buffer
= NULL
;
4993 /* open file only if it's going to be used */
4994 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4995 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4997 WCHAR
*source
= NULL
;
5000 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5001 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
5003 DWORD dir_len
, source_len
;
5005 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
5006 source_len
= strlenW(pActCtx
->lpSource
);
5007 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5009 status
= STATUS_NO_MEMORY
;
5013 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5014 source
[dir_len
] = '\\';
5015 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5018 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5019 RtlFreeHeap( GetProcessHeap(), 0, source
);
5022 status
= STATUS_NO_SUCH_FILE
;
5025 status
= open_nt_file( &file
, &nameW
);
5028 RtlFreeUnicodeString( &nameW
);
5033 acl
.actctx
= actctx
;
5034 acl
.dependencies
= NULL
;
5035 acl
.num_dependencies
= 0;
5036 acl
.allocated_dependencies
= 0;
5038 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5039 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5041 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5043 /* if we have a resource it's a PE file */
5044 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5046 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5047 pActCtx
->lpResourceName
, lang
);
5048 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5049 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5050 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5052 else if (pActCtx
->lpSource
)
5054 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5055 file
, pActCtx
->lpResourceName
, lang
);
5056 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5057 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5058 NULL
, pActCtx
->lpResourceName
);
5060 else status
= STATUS_INVALID_PARAMETER
;
5064 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5067 if (file
) NtClose( file
);
5068 RtlFreeUnicodeString( &nameW
);
5070 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
5071 free_depend_manifests( &acl
);
5073 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
5074 else actctx_release( actctx
);
5078 if (file
) NtClose( file
);
5079 actctx_release( actctx
);
5084 /***********************************************************************
5085 * RtlAddRefActivationContext (NTDLL.@)
5087 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
5089 ACTIVATION_CONTEXT
*actctx
;
5091 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5095 /******************************************************************
5096 * RtlReleaseActivationContext (NTDLL.@)
5098 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5100 ACTIVATION_CONTEXT
*actctx
;
5102 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5105 /******************************************************************
5106 * RtlZombifyActivationContext (NTDLL.@)
5108 * FIXME: function prototype might be wrong
5110 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5112 FIXME("%p: stub\n", handle
);
5113 return STATUS_NOT_IMPLEMENTED
;
5116 /******************************************************************
5117 * RtlActivateActivationContext (NTDLL.@)
5119 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5121 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5123 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5124 return STATUS_NO_MEMORY
;
5126 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5127 frame
->ActivationContext
= handle
;
5129 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
5130 RtlAddRefActivationContext( handle
);
5132 *cookie
= (ULONG_PTR
)frame
;
5133 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
5134 return STATUS_SUCCESS
;
5138 /***********************************************************************
5139 * RtlDeactivateActivationContext (NTDLL.@)
5141 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5143 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5145 TRACE( "%x cookie=%lx\n", flags
, cookie
);
5147 /* find the right frame */
5148 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5149 for (frame
= top
; frame
; frame
= frame
->Previous
)
5150 if ((ULONG_PTR
)frame
== cookie
) break;
5153 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5155 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5156 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5158 /* pop everything up to and including frame */
5159 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5161 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5163 frame
= top
->Previous
;
5164 RtlReleaseActivationContext( top
->ActivationContext
);
5165 RtlFreeHeap( GetProcessHeap(), 0, top
);
5171 /******************************************************************
5172 * RtlFreeThreadActivationContextStack (NTDLL.@)
5174 void WINAPI
RtlFreeThreadActivationContextStack(void)
5176 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5178 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5181 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5182 RtlReleaseActivationContext( frame
->ActivationContext
);
5183 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5186 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5190 /******************************************************************
5191 * RtlGetActiveActivationContext (NTDLL.@)
5193 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5195 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5197 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5198 RtlAddRefActivationContext( *handle
);
5203 return STATUS_SUCCESS
;
5207 /******************************************************************
5208 * RtlIsActivationContextActive (NTDLL.@)
5210 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5212 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5214 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5215 if (frame
->ActivationContext
== handle
) return TRUE
;
5220 /***********************************************************************
5221 * RtlQueryInformationActivationContext (NTDLL.@)
5223 * Get information about an activation context.
5224 * FIXME: function signature/prototype may be wrong
5226 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5227 ULONG
class, PVOID buffer
,
5228 SIZE_T bufsize
, SIZE_T
*retlen
)
5230 ACTIVATION_CONTEXT
*actctx
;
5233 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5234 subinst
, class, buffer
, bufsize
, retlen
);
5236 if (retlen
) *retlen
= 0;
5237 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5241 case ActivationContextBasicInformation
:
5243 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5245 if (retlen
) *retlen
= sizeof(*info
);
5246 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5248 info
->hActCtx
= handle
;
5249 info
->dwFlags
= 0; /* FIXME */
5250 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5254 case ActivationContextDetailedInformation
:
5256 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5257 struct assembly
*assembly
= NULL
;
5258 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5261 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5263 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5265 if (assembly
&& assembly
->manifest
.info
)
5266 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5267 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5268 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5269 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5271 if (retlen
) *retlen
= len
;
5272 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5275 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5276 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5277 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5278 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5279 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5280 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5281 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5282 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5283 ptr
= (LPWSTR
)(acdi
+ 1);
5286 acdi
->lpRootManifestPath
= ptr
;
5287 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5288 ptr
+= manifest_len
;
5290 else acdi
->lpRootManifestPath
= NULL
;
5293 acdi
->lpRootConfigurationPath
= ptr
;
5294 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5297 else acdi
->lpRootConfigurationPath
= NULL
;
5300 acdi
->lpAppDirPath
= ptr
;
5301 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5303 else acdi
->lpAppDirPath
= NULL
;
5307 case AssemblyDetailedInformationInActivationContext
:
5309 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5310 struct assembly
*assembly
;
5313 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5316 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5317 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5319 index
= *(DWORD
*)subinst
;
5320 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5322 assembly
= &actctx
->assemblies
[index
- 1];
5324 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5325 id_len
= strlenW(assembly_id
) + 1;
5326 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5328 if (assembly
->manifest
.info
&&
5329 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5330 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5332 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5334 if (retlen
) *retlen
= len
;
5335 if (!buffer
|| bufsize
< len
)
5337 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5338 return STATUS_BUFFER_TOO_SMALL
;
5341 afdi
->ulFlags
= 0; /* FIXME */
5342 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5343 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5344 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5345 /* FIXME afdi->liManifestLastWriteTime = 0; */
5346 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5347 afdi
->ulPolicyPathLength
= 0;
5348 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5349 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5350 afdi
->ulManifestVersionMajor
= 1;
5351 afdi
->ulManifestVersionMinor
= 0;
5352 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5353 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5354 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5355 ptr
= (LPWSTR
)(afdi
+ 1);
5356 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5357 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5361 afdi
->lpAssemblyManifestPath
= ptr
;
5362 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5364 } else afdi
->lpAssemblyManifestPath
= NULL
;
5365 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5368 afdi
->lpAssemblyDirectoryName
= ptr
;
5369 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5371 else afdi
->lpAssemblyDirectoryName
= NULL
;
5372 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5376 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5378 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5379 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5380 struct assembly
*assembly
;
5381 struct dll_redirect
*dll
;
5382 SIZE_T len
, dll_len
= 0;
5385 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5386 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5388 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5389 return STATUS_INVALID_PARAMETER
;
5390 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5392 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5393 return STATUS_INVALID_PARAMETER
;
5394 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5396 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5397 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5399 if (!buffer
|| bufsize
< len
)
5401 if (retlen
) *retlen
= len
;
5402 return STATUS_BUFFER_TOO_SMALL
;
5404 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5405 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5406 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5407 afdi
->ulPathLength
= 0; /* FIXME */
5408 ptr
= (LPWSTR
)(afdi
+ 1);
5411 afdi
->lpFileName
= ptr
;
5412 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5413 } else afdi
->lpFileName
= NULL
;
5414 afdi
->lpFilePath
= NULL
; /* FIXME */
5418 case CompatibilityInformationInActivationContext
:
5420 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5421 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5422 struct assembly
*assembly
= NULL
;
5423 ULONG num_compat_contexts
= 0, n
;
5426 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5428 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5431 num_compat_contexts
= assembly
->num_compat_contexts
;
5432 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5434 if (retlen
) *retlen
= len
;
5435 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5437 *acci
= num_compat_contexts
;
5438 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5439 for (n
= 0; n
< num_compat_contexts
; ++n
)
5441 elements
[n
] = assembly
->compat_contexts
[n
];
5446 case RunlevelInformationInActivationContext
:
5448 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5449 struct assembly
*assembly
;
5452 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5454 len
= sizeof(*acrli
);
5455 if (retlen
) *retlen
= len
;
5456 if (!buffer
|| bufsize
< len
)
5457 return STATUS_BUFFER_TOO_SMALL
;
5459 assembly
= actctx
->assemblies
;
5462 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5463 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5468 FIXME( "class %u not implemented\n", class );
5469 return STATUS_NOT_IMPLEMENTED
;
5471 return STATUS_SUCCESS
;
5474 /***********************************************************************
5475 * RtlFindActivationContextSectionString (NTDLL.@)
5477 * Find information about a string in an activation context.
5478 * FIXME: function signature/prototype may be wrong
5480 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5481 const UNICODE_STRING
*section_name
, PVOID ptr
)
5483 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5484 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5486 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5487 debugstr_us(section_name
), data
);
5491 FIXME("expected guid == NULL\n");
5492 return STATUS_INVALID_PARAMETER
;
5494 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5496 FIXME("unknown flags %08x\n", flags
);
5497 return STATUS_INVALID_PARAMETER
;
5499 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5500 !section_name
|| !section_name
->Buffer
)
5502 WARN("invalid parameter\n");
5503 return STATUS_INVALID_PARAMETER
;
5506 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5508 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5509 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5512 if (status
!= STATUS_SUCCESS
)
5513 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5518 /***********************************************************************
5519 * RtlFindActivationContextSectionGuid (NTDLL.@)
5521 * Find information about a GUID in an activation context.
5522 * FIXME: function signature/prototype may be wrong
5524 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5525 const GUID
*guid
, void *ptr
)
5527 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5528 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5530 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5534 FIXME("expected extguid == NULL\n");
5535 return STATUS_INVALID_PARAMETER
;
5538 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5540 FIXME("unknown flags %08x\n", flags
);
5541 return STATUS_INVALID_PARAMETER
;
5544 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5545 return STATUS_INVALID_PARAMETER
;
5547 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5549 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5550 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5553 if (status
!= STATUS_SUCCESS
)
5554 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5560 /***********************************************************************
5561 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5563 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5564 const WCHAR
*settings
, WCHAR
*buffer
,
5565 SIZE_T size
, SIZE_T
*written
)
5567 ACTIVATION_CONTEXT
*actctx
;
5572 WARN( "unknown flags %08x\n", flags
);
5573 return STATUS_INVALID_PARAMETER
;
5578 if (strcmpW( ns
, windowsSettings2005NSW
) &&
5579 strcmpW( ns
, windowsSettings2011NSW
) &&
5580 strcmpW( ns
, windowsSettings2016NSW
) &&
5581 strcmpW( ns
, windowsSettings2017NSW
))
5582 return STATUS_INVALID_PARAMETER
;
5584 else ns
= windowsSettings2005NSW
;
5586 if (!handle
) handle
= process_actctx
;
5587 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5589 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5591 if (written
) *written
= strlenW(res
) + 1;
5592 if (size
< strlenW(res
)) return STATUS_BUFFER_TOO_SMALL
;
5593 strcpyW( buffer
, res
);
5594 return STATUS_SUCCESS
;