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"
40 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
42 #define ACTCTX_FLAGS_ALL (\
43 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
44 ACTCTX_FLAG_LANGID_VALID |\
45 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
46 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
47 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
48 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
49 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
50 ACTCTX_FLAG_HMODULE_VALID )
52 #define ACTCTX_MAGIC 0xC07E3E11
53 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
54 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
56 /* we don't want to include winuser.h */
57 #define RT_MANIFEST ((ULONG_PTR)24)
58 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 typedef enum tagLIBFLAGS
{
62 LIBFLAG_FRESTRICTED
= 0x1,
63 LIBFLAG_FCONTROL
= 0x2,
64 LIBFLAG_FHIDDEN
= 0x4,
65 LIBFLAG_FHASDISKIMAGE
= 0x8
69 typedef enum tagOLEMISC
71 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
72 OLEMISC_ONLYICONIC
= 0x2,
73 OLEMISC_INSERTNOTREPLACE
= 0x4,
75 OLEMISC_CANTLINKINSIDE
= 0x10,
76 OLEMISC_CANLINKBYOLE1
= 0x20,
77 OLEMISC_ISLINKOBJECT
= 0x40,
78 OLEMISC_INSIDEOUT
= 0x80,
79 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
80 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
81 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
82 OLEMISC_ALWAYSRUN
= 0x800,
83 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
84 OLEMISC_ACTSLIKELABEL
= 0x2000,
85 OLEMISC_NOUIACTIVATE
= 0x4000,
86 OLEMISC_ALIGNABLE
= 0x8000,
87 OLEMISC_SIMPLEFRAME
= 0x10000,
88 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
89 OLEMISC_IMEMODE
= 0x40000,
90 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
91 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
92 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
95 #define MAX_NAMESPACES 64
120 struct xml_attr namespaces
[MAX_NAMESPACES
];
131 struct assembly_version
139 struct assembly_identity
146 struct assembly_version version
;
151 struct strsection_header
165 ULONG hash
; /* key string hash */
168 ULONG data_offset
; /* redirect data offset */
173 struct guidsection_header
193 struct wndclass_redirect_data
198 ULONG name_offset
; /* versioned name offset */
200 ULONG module_offset
;/* container name offset */
203 struct dllredirect_data
210 struct tlibredirect_data
224 enum comclass_threadingmodel
226 ThreadingModel_Apartment
= 1,
227 ThreadingModel_Free
= 2,
228 ThreadingModel_No
= 3,
229 ThreadingModel_Both
= 4,
230 ThreadingModel_Neutral
= 5
233 enum comclass_miscfields
237 MiscStatusContent
= 4,
238 MiscStatusThumbnail
= 8,
239 MiscStatusDocPrint
= 16
242 struct comclassredirect_data
258 ULONG clrdata_offset
;
260 DWORD miscstatuscontent
;
261 DWORD miscstatusthumbnail
;
262 DWORD miscstatusicon
;
263 DWORD miscstatusdocprint
;
272 struct ifacepsredirect_data
284 struct clrsurrogate_data
289 ULONG version_offset
;
304 ULONG version_offset
;
308 struct progidredirect_data
319 Sections are accessible by string or guid key, that defines two types of sections.
320 All sections of each type have same magic value and header structure, index
321 data could be of two possible types too. So every string based section uses
322 the same index format, same applies to guid sections - they share same guid index
325 - window class redirection section is a plain buffer with following format:
329 <data[]> --- <original name>
334 Header is fixed length structure - struct strsection_header,
335 contains redirected classes count;
337 Index is an array of fixed length index records, each record is
340 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
342 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
343 others are relative to section itself.
345 - dll redirect section format:
349 <data[]> --- <dll name>
352 This section doesn't seem to carry any payload data except dll names.
354 - typelib section format:
362 Header is fixed length, index is an array of fixed length 'struct guid_index'.
363 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
364 4-bytes aligned as a whole.
366 Module name offsets are relative to section, helpstring offset is relative to data
369 - comclass section format:
374 <data[]> --- <data> --- <data>
380 This section uses two index records per comclass, one entry contains original guid
381 as specified by context, another one has a generated guid. Index and strings handling
382 is similar to typelib sections.
384 For CLR classes additional data is stored after main COM class data, it contains
385 class name and runtime version string, see 'struct clrclass_data'.
387 Module name offsets are relative to section, progid offset is relative to data
390 - COM interface section format:
397 Interface section contains data for proxy/stubs and external proxy/stubs. External
398 ones are defined at assembly level, so this section has no module information.
399 All records are indexed with 'iid' value from manifest. There an exception for
400 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
401 redirect data, but index is still 'iid' from manifest.
403 Interface name offset is relative to data structure itself.
405 - CLR surrogates section format:
413 There's nothing special about this section, same way to store strings is used,
414 no modules part as it belongs to assembly level, not a file.
416 - ProgID section format:
421 <data[]> --- <progid>
424 This sections uses generated alias guids from COM server section. This way
425 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
426 is stored too, aligned.
433 unsigned int allocated
;
454 WCHAR
*name
; /* clrClass: class name */
455 WCHAR
*version
; /* clrClass: CLR runtime version */
458 DWORD miscstatuscontent
;
459 DWORD miscstatusthumbnail
;
460 DWORD miscstatusicon
;
461 DWORD miscstatusdocprint
;
462 struct progids progids
;
469 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
497 unsigned int allocated
;
504 struct entity_array entities
;
509 APPLICATION_MANIFEST
,
511 ASSEMBLY_SHARED_MANIFEST
,
516 enum assembly_type type
;
517 struct assembly_identity id
;
518 struct file_info manifest
;
521 struct dll_redirect
*dlls
;
522 unsigned int num_dlls
;
523 unsigned int allocated_dlls
;
524 struct entity_array entities
;
525 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
526 ULONG num_compat_contexts
;
527 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
531 enum context_sections
533 WINDOWCLASS_SECTION
= 1,
534 DLLREDIRECT_SECTION
= 2,
535 TLIBREDIRECT_SECTION
= 4,
536 SERVERREDIRECT_SECTION
= 8,
537 IFACEREDIRECT_SECTION
= 16,
538 CLRSURROGATES_SECTION
= 32,
539 PROGIDREDIRECT_SECTION
= 64
542 typedef struct _ACTIVATION_CONTEXT
546 struct file_info config
;
547 struct file_info appdir
;
548 struct assembly
*assemblies
;
549 unsigned int num_assemblies
;
550 unsigned int allocated_assemblies
;
553 struct strsection_header
*wndclass_section
;
554 struct strsection_header
*dllredirect_section
;
555 struct strsection_header
*progid_section
;
556 struct guidsection_header
*tlib_section
;
557 struct guidsection_header
*comserver_section
;
558 struct guidsection_header
*ifaceps_section
;
559 struct guidsection_header
*clrsurrogate_section
;
560 } ACTIVATION_CONTEXT
;
564 ACTIVATION_CONTEXT
*actctx
;
565 struct assembly_identity
*dependencies
;
566 unsigned int num_dependencies
;
567 unsigned int allocated_dependencies
;
570 static const xmlstr_t empty_xmlstr
;
573 static const WCHAR current_archW
[] = {'x','8','6',0};
574 #elif defined __x86_64__
575 static const WCHAR current_archW
[] = {'a','m','d','6','4',0};
576 #elif defined __arm__
577 static const WCHAR current_archW
[] = {'a','r','m',0};
578 #elif defined __aarch64__
579 static const WCHAR current_archW
[] = {'a','r','m','6','4',0};
581 static const WCHAR current_archW
[] = {'n','o','n','e',0};
584 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};
585 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};
586 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};
587 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
588 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
589 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
590 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
591 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
592 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
593 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};
594 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};
595 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
596 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
597 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
598 static const WCHAR fileW
[] = {'f','i','l','e',0};
599 static const WCHAR hashW
[] = {'h','a','s','h',0};
600 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
601 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
602 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
603 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
605 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
606 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
607 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
608 static const WCHAR iidW
[] = {'i','i','d',0};
609 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
610 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
611 static const WCHAR nameW
[] = {'n','a','m','e',0};
612 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
613 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
614 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
615 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
616 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};
617 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
618 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
619 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
620 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
621 static const WCHAR typeW
[] = {'t','y','p','e',0};
622 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
623 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
624 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
625 static const WCHAR yesW
[] = {'y','e','s',0};
626 static const WCHAR noW
[] = {'n','o',0};
627 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
628 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
629 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
630 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
631 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
632 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
633 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
634 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
635 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
636 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
637 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
638 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
639 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
640 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
641 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
642 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
644 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
645 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
646 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
647 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
648 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
649 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
650 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
651 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};
652 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
653 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
654 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
655 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
656 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
657 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
658 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
659 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
660 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};
661 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
662 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
663 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
664 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};
665 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
667 static const WCHAR compatibilityW
[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
668 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};
669 static const WCHAR applicationW
[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
670 static const WCHAR supportedOSW
[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
671 static const WCHAR IdW
[] = {'I','d',0};
672 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};
673 static const WCHAR requestedPrivilegesW
[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
674 static const WCHAR securityW
[] = {'s','e','c','u','r','i','t','y',0};
675 static const WCHAR trustInfoW
[] = {'t','r','u','s','t','I','n','f','o',0};
676 static const WCHAR windowsSettingsW
[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
677 static const WCHAR autoElevateW
[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
678 static const WCHAR disableThemingW
[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
679 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};
680 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};
681 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};
682 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};
683 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};
684 static const WCHAR dpiAwareW
[] = {'d','p','i','A','w','a','r','e',0};
685 static const WCHAR dpiAwarenessW
[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
686 static const WCHAR gdiScalingW
[] = {'g','d','i','S','c','a','l','i','n','g',0};
687 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};
688 static const WCHAR longPathAwareW
[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
689 static const WCHAR magicFutureSettingW
[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
690 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};
691 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};
699 static const struct olemisc_entry olemisc_values
[] =
701 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
702 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
703 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
704 { alignableW
, OLEMISC_ALIGNABLE
},
705 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
706 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
707 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
708 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
709 { imemodeW
, OLEMISC_IMEMODE
},
710 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
711 { insideoutW
, OLEMISC_INSIDEOUT
},
712 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
713 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
714 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
715 { onlyiconicW
, OLEMISC_ONLYICONIC
},
716 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
717 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
718 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
719 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
720 { staticW
, OLEMISC_STATIC
},
721 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
722 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
725 static const WCHAR xmlW
[] = {'?','x','m','l',0};
726 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
727 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
728 static const WCHAR wildcardW
[] = {'*',0};
730 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
731 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
733 static WCHAR
*strdupW(const WCHAR
* str
)
737 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str
) + 1) * sizeof(WCHAR
))))
739 return wcscpy(ptr
, str
);
742 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
746 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
748 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
754 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
756 return !wcsncmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
759 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
761 return !wcsnicmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
764 static BOOL
xml_attr_cmp( const struct xml_attr
*attr
, const WCHAR
*str
)
766 return xmlstr_cmp( &attr
->name
, str
);
769 static BOOL
xml_name_cmp( const struct xml_elem
*elem1
, const struct xml_elem
*elem2
)
771 return (elem1
->name
.len
== elem2
->name
.len
&&
772 elem1
->ns
.len
== elem2
->ns
.len
&&
773 !wcsncmp( elem1
->name
.ptr
, elem2
->name
.ptr
, elem1
->name
.len
) &&
774 !wcsncmp( elem1
->ns
.ptr
, elem2
->ns
.ptr
, elem1
->ns
.len
));
777 static inline BOOL
xml_elem_cmp(const struct xml_elem
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
779 if (!xmlstr_cmp( &elem
->name
, str
)) return FALSE
;
780 if (xmlstr_cmp( &elem
->ns
, namespace )) return TRUE
;
781 if (!wcscmp( namespace, asmv1W
))
783 if (xmlstr_cmp( &elem
->ns
, asmv2W
)) return TRUE
;
784 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
786 else if (!wcscmp( namespace, asmv2W
))
788 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
793 static inline BOOL
isxmlspace( WCHAR ch
)
795 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
798 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
800 return debugstr_wn(str
->ptr
, str
->len
);
803 static inline const char *debugstr_xml_elem( const struct xml_elem
*elem
)
805 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem
->name
.ptr
, elem
->name
.len
),
806 debugstr_wn( elem
->ns
.ptr
, elem
->ns
.len
));
809 static inline const char *debugstr_xml_attr( const struct xml_attr
*attr
)
811 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr
->name
.ptr
, attr
->name
.len
),
812 debugstr_wn( attr
->value
.ptr
, attr
->value
.len
));
815 static inline const char* debugstr_version(const struct assembly_version
*ver
)
817 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
820 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
826 LdrLockLoaderLock(0, NULL
, &magic
);
827 status
= LdrFindEntryForAddress( module
, &pldr
);
828 if (status
== STATUS_SUCCESS
)
830 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
831 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
833 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
834 str
->Length
= pldr
->FullDllName
.Length
;
835 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
837 else status
= STATUS_NO_MEMORY
;
839 LdrUnlockLoaderLock(0, magic
);
843 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
845 struct assembly
*assembly
;
847 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
850 unsigned int new_count
;
851 if (actctx
->assemblies
)
853 new_count
= actctx
->allocated_assemblies
* 2;
854 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
855 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
860 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
862 if (!ptr
) return NULL
;
863 actctx
->assemblies
= ptr
;
864 actctx
->allocated_assemblies
= new_count
;
867 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
872 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
874 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
877 unsigned int new_count
;
880 new_count
= assembly
->allocated_dlls
* 2;
881 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
882 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
887 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
889 if (!ptr
) return NULL
;
890 assembly
->dlls
= ptr
;
891 assembly
->allocated_dlls
= new_count
;
893 return &assembly
->dlls
[assembly
->num_dlls
++];
896 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
899 if (assembly
->num_compat_contexts
)
901 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
902 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
903 assembly
->compat_contexts
,
904 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
908 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
910 if (!ptr
) return NULL
;
911 assembly
->compat_contexts
= ptr
;
912 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
915 static void free_assembly_identity(struct assembly_identity
*ai
)
917 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
918 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
919 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
920 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
921 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
924 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
926 struct entity
* entity
;
928 if (array
->num
== array
->allocated
)
931 unsigned int new_count
;
934 new_count
= array
->allocated
* 2;
935 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
936 array
->base
, new_count
* sizeof(*array
->base
) );
941 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
943 if (!ptr
) return NULL
;
945 array
->allocated
= new_count
;
947 entity
= &array
->base
[array
->num
++];
952 static void free_entity_array(struct entity_array
*array
)
955 for (i
= 0; i
< array
->num
; i
++)
957 struct entity
*entity
= &array
->base
[i
];
958 switch (entity
->kind
)
960 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
961 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
962 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
963 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
964 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
965 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
966 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
967 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
968 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
970 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
971 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
972 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
973 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
974 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
975 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
977 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
978 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
979 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
981 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
982 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
984 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
985 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
986 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
987 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
989 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
:
990 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.name
);
991 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.value
);
992 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.ns
);
995 FIXME("Unknown entity kind %d\n", entity
->kind
);
998 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
1001 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
1003 if (!str1
) return !str2
;
1004 return str2
&& !RtlCompareUnicodeStrings( str1
, wcslen(str1
), str2
, wcslen(str2
), TRUE
);
1007 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
1008 const struct assembly_identity
*id2
)
1010 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
1011 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
1012 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
1014 if (id1
->language
&& id2
->language
&& !is_matching_string( id1
->language
, id2
->language
))
1016 if (wcscmp( wildcardW
, id1
->language
) && wcscmp( wildcardW
, id2
->language
))
1019 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
1020 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
1021 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
1022 if (id1
->version
.build
== id2
->version
.build
&&
1023 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
1027 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
1028 struct assembly_identity
* ai
)
1032 /* check if we already have that assembly */
1034 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
1035 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
1037 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1038 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
1039 ai
->version
.build
, ai
->version
.revision
);
1043 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1044 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
1046 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1047 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
1048 ai
->version
.build
, ai
->version
.revision
);
1052 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
1055 unsigned int new_count
;
1056 if (acl
->dependencies
)
1058 new_count
= acl
->allocated_dependencies
* 2;
1059 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
1060 new_count
* sizeof(acl
->dependencies
[0]));
1065 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
1067 if (!ptr
) return FALSE
;
1068 acl
->dependencies
= ptr
;
1069 acl
->allocated_dependencies
= new_count
;
1071 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
1076 static void free_depend_manifests(struct actctx_loader
* acl
)
1079 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1080 free_assembly_identity(&acl
->dependencies
[i
]);
1081 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
1084 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
1086 static const WCHAR undW
[] = {'_',0};
1087 static const WCHAR noneW
[] = {'n','o','n','e',0};
1088 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
1090 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
1091 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1092 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1093 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1094 SIZE_T size
= (wcslen(arch
) + 1 + wcslen(name
) + 1 + wcslen(key
) + 24 + 1 +
1095 wcslen(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1098 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
1100 wcscpy( ret
, arch
);
1101 wcscat( ret
, undW
);
1102 wcscat( ret
, name
);
1103 wcscat( ret
, undW
);
1105 wcscat( ret
, undW
);
1106 NTDLL_swprintf( ret
+ wcslen(ret
), version_formatW
,
1107 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1108 wcscat( ret
, undW
);
1109 wcscat( ret
, lang
);
1110 wcscat( ret
, undW
);
1111 wcscat( ret
, mskeyW
);
1115 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1120 wcscat( buffer
, prefix
);
1129 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1131 static const WCHAR archW
[] =
1132 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1133 static const WCHAR public_keyW
[] =
1134 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1135 static const WCHAR typeW
[] =
1136 {',','t','y','p','e','=',0};
1137 static const WCHAR versionW
[] =
1138 {',','v','e','r','s','i','o','n','=',0};
1140 WCHAR version
[64], *ret
;
1143 NTDLL_swprintf( version
, version_formatW
,
1144 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1145 if (ai
->name
) size
+= wcslen(ai
->name
) * sizeof(WCHAR
);
1146 if (ai
->arch
) size
+= wcslen(archW
) + wcslen(ai
->arch
) + 2;
1147 if (ai
->public_key
) size
+= wcslen(public_keyW
) + wcslen(ai
->public_key
) + 2;
1148 if (ai
->type
) size
+= wcslen(typeW
) + wcslen(ai
->type
) + 2;
1149 size
+= wcslen(versionW
) + wcslen(version
) + 2;
1151 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1154 if (ai
->name
) wcscpy( ret
, ai
->name
);
1156 append_string( ret
, archW
, ai
->arch
);
1157 append_string( ret
, public_keyW
, ai
->public_key
);
1158 append_string( ret
, typeW
, ai
->type
);
1159 append_string( ret
, versionW
, version
);
1163 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1165 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1167 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1170 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1179 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1181 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1184 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1186 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1190 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1192 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1193 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1195 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1196 free_entity_array( &dll
->entities
);
1197 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1198 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1200 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1201 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1202 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1203 RtlFreeHeap( GetProcessHeap(), 0, assembly
->compat_contexts
);
1204 free_entity_array( &assembly
->entities
);
1205 free_assembly_identity(&assembly
->id
);
1207 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1208 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1209 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1210 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1211 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1212 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1213 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1214 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1215 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1216 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1218 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1222 static BOOL
set_error( xmlbuf_t
*xmlbuf
)
1224 xmlbuf
->error
= TRUE
;
1228 static BOOL
is_xmlns_attr( const struct xml_attr
*attr
)
1230 const int len
= wcslen( xmlnsW
);
1231 if (attr
->name
.len
< len
) return FALSE
;
1232 if (wcsncmp( attr
->name
.ptr
, xmlnsW
, len
)) return FALSE
;
1233 return (attr
->name
.len
== len
|| attr
->name
.ptr
[len
] == ':');
1236 static void push_xmlns( xmlbuf_t
*xmlbuf
, const struct xml_attr
*attr
)
1238 const int len
= wcslen( xmlnsW
);
1239 struct xml_attr
*ns
;
1241 if (xmlbuf
->ns_pos
== MAX_NAMESPACES
- 1)
1243 FIXME( "too many namespaces in manifest\n" );
1244 set_error( xmlbuf
);
1247 ns
= &xmlbuf
->namespaces
[xmlbuf
->ns_pos
++];
1248 ns
->value
= attr
->value
;
1249 if (attr
->name
.len
> len
)
1251 ns
->name
.ptr
= attr
->name
.ptr
+ len
+ 1;
1252 ns
->name
.len
= attr
->name
.len
- len
- 1;
1254 else ns
->name
= empty_xmlstr
;
1257 static xmlstr_t
find_xmlns( xmlbuf_t
*xmlbuf
, const xmlstr_t
*name
)
1261 for (i
= xmlbuf
->ns_pos
- 1; i
>= 0; i
--)
1263 if (xmlbuf
->namespaces
[i
].name
.len
== name
->len
&&
1264 !wcsncmp( xmlbuf
->namespaces
[i
].name
.ptr
, name
->ptr
, name
->len
))
1265 return xmlbuf
->namespaces
[i
].value
;
1267 if (xmlbuf
->ns_pos
) WARN( "namespace %s not found\n", debugstr_xmlstr( name
));
1268 return empty_xmlstr
;
1271 static BOOL
next_xml_attr(xmlbuf_t
*xmlbuf
, struct xml_attr
*attr
, BOOL
*end
)
1276 if (xmlbuf
->error
) return FALSE
;
1278 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1281 if (xmlbuf
->ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1283 if (*xmlbuf
->ptr
== '/')
1286 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1287 return set_error( xmlbuf
);
1294 if (*xmlbuf
->ptr
== '>')
1301 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1303 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1305 attr
->name
.ptr
= xmlbuf
->ptr
;
1306 attr
->name
.len
= ptr
-xmlbuf
->ptr
;
1309 /* skip spaces before '=' */
1310 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1311 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return set_error( xmlbuf
);
1313 /* skip '=' itself */
1315 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1317 /* skip spaces after '=' */
1318 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1320 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return set_error( xmlbuf
);
1323 attr
->value
.ptr
= ptr
;
1324 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1326 while (ptr
< xmlbuf
->end
&& *ptr
!= quote
) ptr
++;
1327 if (ptr
== xmlbuf
->end
)
1329 xmlbuf
->ptr
= xmlbuf
->end
;
1330 return set_error( xmlbuf
);
1333 attr
->value
.len
= ptr
- attr
->value
.ptr
;
1334 xmlbuf
->ptr
= ptr
+ 1;
1335 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1337 return set_error( xmlbuf
);
1340 static void read_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
)
1342 const WCHAR
* ptr
= xmlbuf
->ptr
;
1344 elem
->ns
= empty_xmlstr
;
1345 elem
->name
.ptr
= ptr
;
1346 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && *ptr
!= '/')
1350 elem
->ns
.ptr
= elem
->name
.ptr
;
1351 elem
->ns
.len
= ptr
- elem
->ns
.ptr
;
1352 elem
->name
.ptr
= ptr
+ 1;
1356 elem
->name
.len
= ptr
- elem
->name
.ptr
;
1360 static BOOL
next_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
, const struct xml_elem
*parent
)
1363 struct xml_attr attr
;
1367 xmlbuf
->ns_pos
= parent
->ns_pos
; /* restore namespace stack to parent state */
1369 if (xmlbuf
->error
) return FALSE
;
1373 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1374 if (ptr
== xmlbuf
->end
)
1376 xmlbuf
->ptr
= xmlbuf
->end
;
1377 return set_error( xmlbuf
);
1380 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1382 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1383 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1385 if (ptr
+ 3 > xmlbuf
->end
)
1387 xmlbuf
->ptr
= xmlbuf
->end
;
1388 return set_error( xmlbuf
);
1390 xmlbuf
->ptr
= ptr
+ 3;
1396 /* check for element terminating the parent element */
1397 if (ptr
< xmlbuf
->end
&& *ptr
== '/')
1400 read_xml_elem( xmlbuf
, elem
);
1401 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1402 if (!xml_name_cmp( elem
, parent
))
1404 ERR( "wrong closing element %s for %s\n",
1405 debugstr_xmlstr(&elem
->name
), debugstr_xmlstr(&parent
->name
));
1406 return set_error( xmlbuf
);
1408 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
)) xmlbuf
->ptr
++;
1409 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
++ != '>') return set_error( xmlbuf
);
1413 read_xml_elem( xmlbuf
, elem
);
1415 /* parse namespace attributes */
1417 while (next_xml_attr( &attr_buf
, &attr
, &end
))
1419 if (is_xmlns_attr( &attr
)) push_xmlns( xmlbuf
, &attr
);
1421 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1422 elem
->ns_pos
= xmlbuf
->ns_pos
;
1424 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1426 return set_error( xmlbuf
);
1429 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1431 /* FIXME: parse attributes */
1434 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1436 if (ptr
[0] == '?' && ptr
[1] == '>')
1438 xmlbuf
->ptr
= ptr
+ 2;
1445 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1449 if (xmlbuf
->error
) return FALSE
;
1451 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1452 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1454 content
->ptr
= xmlbuf
->ptr
;
1455 content
->len
= ptr
- xmlbuf
->ptr
;
1461 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1463 unsigned int ver
[4];
1467 /* major.minor.build.revision */
1468 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1469 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1471 if (*curr
>= '0' && *curr
<= '9')
1473 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1474 if (ver
[pos
] >= 0x10000) goto error
;
1476 else if (*curr
== '.')
1478 if (++pos
>= 4) goto error
;
1482 version
->major
= ver
[0];
1483 version
->minor
= ver
[1];
1484 version
->build
= ver
[2];
1485 version
->revision
= ver
[3];
1489 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1493 static void parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1495 struct xml_attr attr
;
1497 while (next_xml_attr(xmlbuf
, &attr
, end
))
1499 if (!is_xmlns_attr( &attr
)) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr
));
1503 static void parse_expect_end_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1505 struct xml_elem elem
;
1507 if (next_xml_elem(xmlbuf
, &elem
, parent
))
1509 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem
) );
1510 set_error( xmlbuf
);
1514 static void parse_unknown_elem(xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1516 struct xml_elem elem
;
1517 struct xml_attr attr
;
1520 while (next_xml_attr(xmlbuf
, &attr
, &end
));
1523 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1524 parse_unknown_elem(xmlbuf
, &elem
);
1527 static void parse_assembly_identity_elem(xmlbuf_t
*xmlbuf
, ACTIVATION_CONTEXT
*actctx
,
1528 struct assembly_identity
* ai
, const struct xml_elem
*parent
)
1530 struct xml_attr attr
;
1533 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1535 if (xml_attr_cmp(&attr
, nameW
))
1537 if (!(ai
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1539 else if (xml_attr_cmp(&attr
, typeW
))
1541 if (!(ai
->type
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1543 else if (xml_attr_cmp(&attr
, versionW
))
1545 if (!parse_version(&attr
.value
, &ai
->version
)) set_error( xmlbuf
);
1547 else if (xml_attr_cmp(&attr
, processorArchitectureW
))
1549 if (!(ai
->arch
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1551 else if (xml_attr_cmp(&attr
, publicKeyTokenW
))
1553 if (!(ai
->public_key
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1555 else if (xml_attr_cmp(&attr
, languageW
))
1557 if (!(ai
->language
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1559 else if (!is_xmlns_attr( &attr
))
1561 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1565 TRACE( "name=%s version=%s arch=%s\n",
1566 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1568 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1571 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1573 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1574 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1575 static const WCHAR freeW
[] = {'F','r','e','e',0};
1576 static const WCHAR bothW
[] = {'B','o','t','h',0};
1578 if (value
->len
== 0) return ThreadingModel_No
;
1579 if (xmlstr_cmp(value
, apartW
))
1580 return ThreadingModel_Apartment
;
1581 else if (xmlstr_cmp(value
, freeW
))
1582 return ThreadingModel_Free
;
1583 else if (xmlstr_cmp(value
, bothW
))
1584 return ThreadingModel_Both
;
1585 else if (xmlstr_cmp(value
, neutralW
))
1586 return ThreadingModel_Neutral
;
1588 return ThreadingModel_No
;
1591 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1596 max
= ARRAY_SIZE(olemisc_values
) - 1;
1604 c
= wcsncmp(olemisc_values
[n
].name
, str
, len
);
1605 if (!c
&& !olemisc_values
[n
].name
[len
])
1606 return olemisc_values
[n
].value
;
1614 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1618 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1620 const WCHAR
*str
= value
->ptr
, *start
;
1624 /* it's comma separated list of flags */
1625 while (i
< value
->len
)
1628 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1630 flags
|= get_olemisc_value(start
, str
-start
);
1632 /* skip separator */
1640 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1642 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1644 if (progids
->allocated
== 0)
1646 progids
->allocated
= 4;
1647 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1650 if (progids
->allocated
== progids
->num
)
1652 WCHAR
**new_progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
,
1653 2 * progids
->allocated
* sizeof(WCHAR
*));
1654 if (!new_progids
) return FALSE
;
1655 progids
->allocated
*= 2;
1656 progids
->progids
= new_progids
;
1659 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1665 static void parse_com_class_progid(xmlbuf_t
*xmlbuf
, struct entity
*entity
, const struct xml_elem
*parent
)
1670 parse_expect_no_attr(xmlbuf
, &end
);
1671 if (end
) set_error( xmlbuf
);
1672 if (!parse_text_content(xmlbuf
, &content
)) return;
1674 if (!com_class_add_progid(&content
, entity
)) set_error( xmlbuf
);
1675 parse_expect_end_elem(xmlbuf
, parent
);
1678 static void parse_com_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
, struct actctx_loader
*acl
,
1679 const struct xml_elem
*parent
)
1681 struct xml_elem elem
;
1682 struct xml_attr attr
;
1684 struct entity
* entity
;
1686 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1688 set_error( xmlbuf
);
1692 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1694 if (xml_attr_cmp(&attr
, clsidW
))
1696 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1698 else if (xml_attr_cmp(&attr
, progidW
))
1700 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1702 else if (xml_attr_cmp(&attr
, tlbidW
))
1704 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1706 else if (xml_attr_cmp(&attr
, threadingmodelW
))
1708 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
1710 else if (xml_attr_cmp(&attr
, miscstatusW
))
1712 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr
.value
);
1714 else if (xml_attr_cmp(&attr
, miscstatuscontentW
))
1716 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr
.value
);
1718 else if (xml_attr_cmp(&attr
, miscstatusthumbnailW
))
1720 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr
.value
);
1722 else if (xml_attr_cmp(&attr
, miscstatusiconW
))
1724 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr
.value
);
1726 else if (xml_attr_cmp(&attr
, miscstatusdocprintW
))
1728 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr
.value
);
1730 else if (xml_attr_cmp(&attr
, descriptionW
))
1734 else if (!is_xmlns_attr( &attr
))
1736 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1740 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1741 if (entity
->u
.comclass
.progid
)
1742 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1746 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1748 if (xml_elem_cmp(&elem
, progidW
, asmv1W
))
1750 parse_com_class_progid(xmlbuf
, entity
, &elem
);
1754 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1755 parse_unknown_elem(xmlbuf
, &elem
);
1759 if (entity
->u
.comclass
.progids
.num
)
1760 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1763 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1768 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1770 if (*curr
>= '0' && *curr
<= '9')
1771 num
= num
* 10 + *curr
- '0';
1774 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1778 entity
->u
.ifaceps
.nummethods
= num
;
1783 static void parse_cominterface_proxy_stub_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1784 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1786 struct xml_attr attr
;
1788 struct entity
* entity
;
1790 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1792 set_error( xmlbuf
);
1796 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1798 if (xml_attr_cmp(&attr
, iidW
))
1800 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1802 else if (xml_attr_cmp(&attr
, nameW
))
1804 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1806 else if (xml_attr_cmp(&attr
, baseInterfaceW
))
1808 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1809 entity
->u
.ifaceps
.mask
|= BaseIface
;
1811 else if (xml_attr_cmp(&attr
, nummethodsW
))
1813 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
1814 entity
->u
.ifaceps
.mask
|= NumMethods
;
1816 else if (xml_attr_cmp(&attr
, tlbidW
))
1818 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1821 else if (xml_attr_cmp(&attr
, proxyStubClsid32W
) || xml_attr_cmp(&attr
, threadingmodelW
))
1824 else if (!is_xmlns_attr( &attr
))
1826 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1830 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1831 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1834 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1836 WORD
*flags
= &entity
->u
.typelib
.flags
;
1837 const WCHAR
*str
= value
->ptr
, *start
;
1842 /* it's comma separated list of flags */
1843 while (i
< value
->len
)
1846 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1848 if (!wcsnicmp(start
, restrictedW
, str
-start
))
1849 *flags
|= LIBFLAG_FRESTRICTED
;
1850 else if (!wcsnicmp(start
, controlW
, str
-start
))
1851 *flags
|= LIBFLAG_FCONTROL
;
1852 else if (!wcsnicmp(start
, hiddenW
, str
-start
))
1853 *flags
|= LIBFLAG_FHIDDEN
;
1854 else if (!wcsnicmp(start
, hasdiskimageW
, str
-start
))
1855 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1858 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1862 /* skip separator */
1870 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1872 unsigned int ver
[2];
1877 ver
[0] = ver
[1] = pos
= 0;
1878 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1880 if (*curr
>= '0' && *curr
<= '9')
1882 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1883 if (ver
[pos
] >= 0x10000) goto error
;
1885 else if (*curr
== '.')
1887 if (++pos
>= 2) goto error
;
1891 entity
->u
.typelib
.major
= ver
[0];
1892 entity
->u
.typelib
.minor
= ver
[1];
1896 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1900 static void parse_typelib_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1901 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1903 struct xml_attr attr
;
1905 struct entity
* entity
;
1907 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1909 set_error( xmlbuf
);
1913 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1915 if (xml_attr_cmp(&attr
, tlbidW
))
1917 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1919 else if (xml_attr_cmp(&attr
, versionW
))
1921 if (!parse_typelib_version(&attr
.value
, entity
)) set_error( xmlbuf
);
1923 else if (xml_attr_cmp(&attr
, helpdirW
))
1925 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1927 else if (xml_attr_cmp(&attr
, flagsW
))
1929 if (!parse_typelib_flags(&attr
.value
, entity
)) set_error( xmlbuf
);
1931 else if (!is_xmlns_attr( &attr
))
1933 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1937 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1938 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1941 static inline int aligned_string_len(int len
)
1943 return (len
+ 3) & ~3;
1946 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1948 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1949 struct assembly_version
*ver
= &assembly
->id
.version
;
1952 if (!ret
) ret
= buff
;
1953 return NTDLL_swprintf(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1956 static void parse_window_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1957 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1959 struct xml_elem elem
;
1960 struct xml_attr attr
;
1963 struct entity
* entity
;
1965 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1967 set_error( xmlbuf
);
1970 entity
->u
.class.versioned
= TRUE
;
1971 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1973 if (xml_attr_cmp(&attr
, versionedW
))
1975 if (xmlstr_cmpi(&attr
.value
, noW
))
1976 entity
->u
.class.versioned
= FALSE
;
1977 else if (!xmlstr_cmpi(&attr
.value
, yesW
))
1978 set_error( xmlbuf
);
1980 else if (!is_xmlns_attr( &attr
))
1982 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1988 if (!parse_text_content(xmlbuf
, &content
)) return;
1989 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) set_error( xmlbuf
);
1991 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1993 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1995 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1996 parse_unknown_elem(xmlbuf
, &elem
);
2000 static void parse_binding_redirect_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2002 struct xml_attr attr
;
2005 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2007 if (xml_attr_cmp(&attr
, oldVersionW
))
2009 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
2011 else if (xml_attr_cmp(&attr
, newVersionW
))
2013 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
2015 else if (!is_xmlns_attr( &attr
))
2017 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2021 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2024 static void parse_description_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2026 struct xml_elem elem
;
2027 struct xml_attr attr
;
2031 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2033 if (!is_xmlns_attr( &attr
)) WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2037 if (!parse_text_content(xmlbuf
, &content
)) return;
2039 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
2041 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2043 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2044 parse_unknown_elem(xmlbuf
, &elem
);
2048 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t
*xmlbuf
,
2049 struct assembly
* assembly
,
2050 struct actctx_loader
* acl
,
2051 const struct xml_elem
*parent
)
2053 struct xml_attr attr
;
2055 struct entity
* entity
;
2057 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
2059 set_error( xmlbuf
);
2063 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2065 if (xml_attr_cmp(&attr
, iidW
))
2067 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2069 else if (xml_attr_cmp(&attr
, nameW
))
2071 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2073 else if (xml_attr_cmp(&attr
, baseInterfaceW
))
2075 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2076 entity
->u
.ifaceps
.mask
|= BaseIface
;
2078 else if (xml_attr_cmp(&attr
, nummethodsW
))
2080 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
2081 entity
->u
.ifaceps
.mask
|= NumMethods
;
2083 else if (xml_attr_cmp(&attr
, proxyStubClsid32W
))
2085 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2087 else if (xml_attr_cmp(&attr
, tlbidW
))
2089 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2091 else if (!is_xmlns_attr( &attr
))
2093 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2097 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2098 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2101 static void parse_clr_class_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2102 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2105 struct xml_elem elem
;
2106 struct xml_attr attr
;
2108 struct entity
* entity
;
2110 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
2112 set_error( xmlbuf
);
2116 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2118 if (xml_attr_cmp(&attr
, nameW
))
2120 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2122 else if (xml_attr_cmp(&attr
, clsidW
))
2124 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2126 else if (xml_attr_cmp(&attr
, progidW
))
2128 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2130 else if (xml_attr_cmp(&attr
, tlbidW
))
2132 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2134 else if (xml_attr_cmp(&attr
, threadingmodelW
))
2136 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
2138 else if (xml_attr_cmp(&attr
, runtimeVersionW
))
2140 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2142 else if (!is_xmlns_attr( &attr
))
2144 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2148 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2149 if (entity
->u
.comclass
.progid
)
2150 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2153 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2155 if (xml_elem_cmp(&elem
, progidW
, asmv1W
))
2157 parse_com_class_progid(xmlbuf
, entity
, &elem
);
2161 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2162 parse_unknown_elem(xmlbuf
, &elem
);
2166 if (entity
->u
.comclass
.progids
.num
)
2167 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2170 static void parse_clr_surrogate_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2171 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2173 struct xml_attr attr
;
2175 struct entity
* entity
;
2177 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)))
2179 set_error( xmlbuf
);
2183 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2185 if (xml_attr_cmp(&attr
, nameW
))
2187 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2189 else if (xml_attr_cmp(&attr
, clsidW
))
2191 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2193 else if (xml_attr_cmp(&attr
, runtimeVersionW
))
2195 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2197 else if (!is_xmlns_attr( &attr
))
2199 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2203 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2204 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2207 static void parse_dependent_assembly_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2208 const struct xml_elem
*parent
, BOOL optional
)
2210 struct xml_elem elem
;
2211 struct xml_attr attr
;
2212 struct assembly_identity ai
;
2215 memset(&ai
, 0, sizeof(ai
));
2216 ai
.optional
= optional
;
2218 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2220 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2221 static const WCHAR trueW
[] = {'t','r','u','e',0};
2223 if (xml_attr_cmp(&attr
, allowDelayedBindingW
))
2224 ai
.delayed
= xmlstr_cmp(&attr
.value
, trueW
);
2225 else if (!is_xmlns_attr( &attr
))
2226 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2231 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2233 if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2235 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
, &elem
);
2236 /* store the newly found identity for later loading */
2237 if (ai
.arch
&& !wcscmp(ai
.arch
, wildcardW
)) ai
.arch
= strdupW( current_archW
);
2238 TRACE( "adding name=%s version=%s arch=%s\n",
2239 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2240 if (!add_dependent_assembly_id(acl
, &ai
)) set_error( xmlbuf
);
2242 else if (xml_elem_cmp(&elem
, bindingRedirectW
, asmv1W
))
2244 parse_binding_redirect_elem(xmlbuf
, &elem
);
2248 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2249 parse_unknown_elem(xmlbuf
, &elem
);
2254 static void parse_dependency_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2255 const struct xml_elem
*parent
)
2258 struct xml_elem elem
;
2259 struct xml_attr attr
;
2260 BOOL end
= FALSE
, optional
= FALSE
;
2262 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2264 if (xml_attr_cmp(&attr
, optionalW
))
2266 optional
= xmlstr_cmpi( &attr
.value
, yesW
);
2267 TRACE("optional=%s\n", debugstr_xmlstr(&attr
.value
));
2269 else if (!is_xmlns_attr( &attr
))
2271 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2275 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2277 if (xml_elem_cmp(&elem
, dependentAssemblyW
, asmv1W
))
2279 parse_dependent_assembly_elem(xmlbuf
, acl
, &elem
, optional
);
2283 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2284 parse_unknown_elem(xmlbuf
, &elem
);
2289 static void parse_noinherit_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2293 parse_expect_no_attr(xmlbuf
, &end
);
2294 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2297 static void parse_noinheritable_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2301 parse_expect_no_attr(xmlbuf
, &end
);
2302 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2305 static void parse_file_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2306 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2308 struct xml_elem elem
;
2309 struct xml_attr attr
;
2311 struct dll_redirect
* dll
;
2313 if (!(dll
= add_dll_redirect(assembly
)))
2315 set_error( xmlbuf
);
2319 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2321 if (xml_attr_cmp(&attr
, nameW
))
2323 if (!(dll
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2324 TRACE("name=%s\n", debugstr_xmlstr(&attr
.value
));
2326 else if (xml_attr_cmp(&attr
, hashW
))
2328 if (!(dll
->hash
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2330 else if (xml_attr_cmp(&attr
, hashalgW
))
2332 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2333 if (!xmlstr_cmpi(&attr
.value
, sha1W
))
2334 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr
.value
));
2336 else if (!is_xmlns_attr( &attr
))
2338 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2342 if (!dll
->name
) set_error( xmlbuf
);
2344 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2348 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2350 if (xml_elem_cmp(&elem
, comClassW
, asmv1W
))
2352 parse_com_class_elem(xmlbuf
, dll
, acl
, &elem
);
2354 else if (xml_elem_cmp(&elem
, comInterfaceProxyStubW
, asmv1W
))
2356 parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
, &elem
);
2358 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2360 WARN("asmv2:hash (undocumented) not supported\n");
2361 parse_unknown_elem(xmlbuf
, &elem
);
2363 else if (xml_elem_cmp(&elem
, typelibW
, asmv1W
))
2365 parse_typelib_elem(xmlbuf
, dll
, acl
, &elem
);
2367 else if (xml_elem_cmp(&elem
, windowClassW
, asmv1W
))
2369 parse_window_class_elem(xmlbuf
, dll
, acl
, &elem
);
2373 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2374 parse_unknown_elem( xmlbuf
, &elem
);
2379 static void parse_supportedos_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2380 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2382 struct xml_attr attr
;
2385 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2387 if (xml_attr_cmp(&attr
, IdW
))
2389 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2393 str
.Buffer
= (PWSTR
)attr
.value
.ptr
;
2394 str
.Length
= str
.MaximumLength
= (USHORT
)attr
.value
.len
* sizeof(WCHAR
);
2395 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2397 if (!(compat
= add_compat_context(assembly
)))
2399 set_error( xmlbuf
);
2402 compat
->Type
= ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2403 compat
->Id
= compat_id
;
2407 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr
.value
));
2410 else if (!is_xmlns_attr( &attr
))
2412 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2416 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2419 static void parse_compatibility_application_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2420 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2422 struct xml_elem elem
;
2424 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2426 if (xml_elem_cmp(&elem
, supportedOSW
, compatibilityNSW
))
2428 parse_supportedos_elem(xmlbuf
, assembly
, acl
, &elem
);
2432 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2433 parse_unknown_elem(xmlbuf
, &elem
);
2438 static void parse_compatibility_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2439 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2441 struct xml_elem elem
;
2443 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2445 if (xml_elem_cmp(&elem
, applicationW
, compatibilityNSW
))
2447 parse_compatibility_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2451 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2452 parse_unknown_elem(xmlbuf
, &elem
);
2457 static void parse_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
,
2458 struct xml_elem
*parent
)
2460 struct xml_elem elem
;
2461 struct xml_attr attr
;
2464 struct entity
*entity
;
2466 while (next_xml_attr( xmlbuf
, &attr
, &end
))
2468 if (!is_xmlns_attr( &attr
)) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr
) );
2473 if (!parse_text_content( xmlbuf
, &content
)) return;
2474 TRACE( "got %s %s\n", debugstr_xmlstr(&parent
->name
), debugstr_xmlstr(&content
) );
2476 entity
= add_entity( &assembly
->entities
, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
);
2479 set_error( xmlbuf
);
2482 entity
->u
.settings
.name
= xmlstrdupW( &parent
->name
);
2483 entity
->u
.settings
.value
= xmlstrdupW( &content
);
2484 entity
->u
.settings
.ns
= xmlstrdupW( &parent
->ns
);
2486 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2488 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2489 parse_unknown_elem( xmlbuf
, &elem
);
2493 static void parse_windows_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2494 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2496 struct xml_elem elem
;
2498 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2500 if (xml_elem_cmp( &elem
, autoElevateW
, windowsSettings2005NSW
) ||
2501 xml_elem_cmp( &elem
, disableThemingW
, windowsSettings2005NSW
) ||
2502 xml_elem_cmp( &elem
, disableWindowFilteringW
, windowsSettings2011NSW
) ||
2503 xml_elem_cmp( &elem
, dpiAwareW
, windowsSettings2005NSW
) ||
2504 xml_elem_cmp( &elem
, dpiAwarenessW
, windowsSettings2016NSW
) ||
2505 xml_elem_cmp( &elem
, gdiScalingW
, windowsSettings2017NSW
) ||
2506 xml_elem_cmp( &elem
, highResolutionScrollingAwareW
, windowsSettings2017NSW
) ||
2507 xml_elem_cmp( &elem
, longPathAwareW
, windowsSettings2016NSW
) ||
2508 xml_elem_cmp( &elem
, magicFutureSettingW
, windowsSettings2017NSW
) ||
2509 xml_elem_cmp( &elem
, printerDriverIsolationW
, windowsSettings2011NSW
) ||
2510 xml_elem_cmp( &elem
, ultraHighResolutionScrollingAwareW
, windowsSettings2017NSW
))
2512 parse_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2516 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2517 parse_unknown_elem( xmlbuf
, &elem
);
2522 static void parse_application_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2523 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2525 struct xml_elem elem
;
2527 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2529 if (xml_elem_cmp( &elem
, windowsSettingsW
, asmv3W
))
2531 parse_windows_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2535 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2536 parse_unknown_elem( xmlbuf
, &elem
);
2541 static void parse_requested_execution_level_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2542 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2544 static const WCHAR levelW
[] = {'l','e','v','e','l',0};
2545 static const WCHAR asInvokerW
[] = {'a','s','I','n','v','o','k','e','r',0};
2546 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};
2547 static const WCHAR highestAvailableW
[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2548 static const WCHAR uiAccessW
[] = {'u','i','A','c','c','e','s','s',0};
2549 static const WCHAR falseW
[] = {'f','a','l','s','e',0};
2550 static const WCHAR trueW
[] = {'t','r','u','e',0};
2552 struct xml_elem elem
;
2553 struct xml_attr attr
;
2556 /* Multiple requestedExecutionLevel elements are not supported. */
2557 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
) set_error( xmlbuf
);
2559 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2561 if (xml_attr_cmp(&attr
, levelW
))
2563 if (xmlstr_cmpi(&attr
.value
, asInvokerW
))
2564 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2565 else if (xmlstr_cmpi(&attr
.value
, highestAvailableW
))
2566 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2567 else if (xmlstr_cmpi(&attr
.value
, requireAdministratorW
))
2568 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2570 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr
.value
));
2572 else if (xml_attr_cmp(&attr
, uiAccessW
))
2574 if (xmlstr_cmpi(&attr
.value
, falseW
))
2575 assembly
->ui_access
= FALSE
;
2576 else if (xmlstr_cmpi(&attr
.value
, trueW
))
2577 assembly
->ui_access
= TRUE
;
2579 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr
.value
));
2581 else if (!is_xmlns_attr( &attr
))
2582 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2587 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2589 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2590 parse_unknown_elem(xmlbuf
, &elem
);
2594 static void parse_requested_privileges_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2595 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2597 struct xml_elem elem
;
2599 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2601 if (xml_elem_cmp(&elem
, requestedExecutionLevelW
, asmv1W
))
2603 parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
, &elem
);
2607 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2608 parse_unknown_elem(xmlbuf
, &elem
);
2613 static void parse_security_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2614 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2616 struct xml_elem elem
;
2618 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2620 if (xml_elem_cmp(&elem
, requestedPrivilegesW
, asmv1W
))
2622 parse_requested_privileges_elem(xmlbuf
, assembly
, acl
, &elem
);
2626 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2627 parse_unknown_elem(xmlbuf
, &elem
);
2632 static void parse_trust_info_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2633 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2635 struct xml_elem elem
;
2637 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2639 if (xml_elem_cmp(&elem
, securityW
, asmv1W
))
2641 parse_security_elem(xmlbuf
, assembly
, acl
, &elem
);
2645 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2646 parse_unknown_elem(xmlbuf
, &elem
);
2651 static void parse_assembly_elem( xmlbuf_t
*xmlbuf
, struct assembly
* assembly
,
2652 struct actctx_loader
* acl
, const struct xml_elem
*parent
,
2653 struct assembly_identity
* expected_ai
)
2655 struct xml_elem elem
;
2656 struct xml_attr attr
;
2657 BOOL end
= FALSE
, version
= FALSE
;
2659 TRACE("(%p)\n", xmlbuf
);
2661 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2663 if (xml_attr_cmp(&attr
, manifestVersionW
))
2665 static const WCHAR v10W
[] = {'1','.','0',0};
2666 if (!xmlstr_cmp(&attr
.value
, v10W
))
2668 FIXME("wrong version %s\n", debugstr_xmlstr(&attr
.value
));
2673 else if (!is_xmlns_attr( &attr
))
2675 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2679 if (end
|| !version
)
2681 set_error( xmlbuf
);
2685 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2687 if (assembly
->type
== APPLICATION_MANIFEST
&& xml_elem_cmp(&elem
, noInheritW
, asmv1W
))
2689 parse_noinherit_elem(xmlbuf
, &elem
);
2690 assembly
->no_inherit
= TRUE
;
2692 else if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2694 parse_noinheritable_elem(xmlbuf
, &elem
);
2696 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2698 parse_description_elem(xmlbuf
, &elem
);
2700 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2702 parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
, &elem
);
2704 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2706 parse_dependency_elem(xmlbuf
, acl
, &elem
);
2708 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2710 parse_file_elem(xmlbuf
, assembly
, acl
, &elem
);
2712 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2714 parse_clr_class_elem(xmlbuf
, assembly
, acl
, &elem
);
2716 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2718 parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
, &elem
);
2720 else if (xml_elem_cmp(&elem
, trustInfoW
, asmv1W
))
2722 parse_trust_info_elem(xmlbuf
, assembly
, acl
, &elem
);
2724 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2726 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
, &elem
);
2728 if (!xmlbuf
->error
&& expected_ai
)
2730 /* FIXME: more tests */
2731 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2732 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2734 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2735 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2736 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2737 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2738 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2739 set_error( xmlbuf
);
2741 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2742 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2743 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2744 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2745 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2746 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2748 FIXME("wrong version for shared assembly manifest\n");
2749 set_error( xmlbuf
);
2753 else if (xml_elem_cmp(&elem
, compatibilityW
, compatibilityNSW
))
2755 parse_compatibility_elem(xmlbuf
, assembly
, acl
, &elem
);
2757 else if (xml_elem_cmp(&elem
, applicationW
, asmv3W
))
2759 parse_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2763 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2764 parse_unknown_elem(xmlbuf
, &elem
);
2768 if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2769 assembly
->no_inherit
)
2771 set_error( xmlbuf
);
2775 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2776 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2778 struct xml_elem elem
;
2779 struct xml_elem parent
= {};
2781 xmlbuf
->error
= FALSE
;
2784 if (!next_xml_elem(xmlbuf
, &elem
, &parent
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2786 if (xmlstr_cmp(&elem
.name
, xmlW
) &&
2787 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
, &parent
)))
2788 return STATUS_SXS_CANT_GEN_ACTCTX
;
2790 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2792 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem
));
2793 return STATUS_SXS_CANT_GEN_ACTCTX
;
2796 parse_assembly_elem(xmlbuf
, assembly
, acl
, &elem
, ai
);
2799 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2800 return STATUS_SXS_CANT_GEN_ACTCTX
;
2803 if (next_xml_elem(xmlbuf
, &elem
, &parent
))
2805 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem
));
2806 return STATUS_SXS_CANT_GEN_ACTCTX
;
2809 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2811 FIXME("parse error\n");
2812 return STATUS_SXS_CANT_GEN_ACTCTX
;
2814 return STATUS_SUCCESS
;
2817 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2818 LPCWSTR filename
, HANDLE module
, LPCWSTR directory
, BOOL shared
,
2819 const void *buffer
, SIZE_T size
)
2823 struct assembly
*assembly
;
2826 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2828 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2829 return STATUS_SXS_CANT_GEN_ACTCTX
;
2831 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2832 return STATUS_NO_MEMORY
;
2836 UNICODE_STRING module_path
;
2837 if ((status
= get_module_filename( module
, &module_path
, 0 ))) return status
;
2838 assembly
->manifest
.info
= module_path
.Buffer
;
2840 else if(!(assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY
;
2842 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2843 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2845 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2846 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2848 xmlbuf
.ptr
= buffer
;
2849 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2850 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2852 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2854 const WCHAR
*buf
= buffer
;
2858 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2859 return STATUS_NO_MEMORY
;
2860 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2861 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2862 xmlbuf
.ptr
= new_buff
;
2863 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2864 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2865 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2872 /* let's assume utf-8 for now */
2873 RtlUTF8ToUnicodeN( NULL
, 0, &len
, buffer
, size
);
2874 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
2875 RtlUTF8ToUnicodeN( new_buff
, len
, &len
, buffer
, size
);
2876 xmlbuf
.ptr
= new_buff
;
2877 xmlbuf
.end
= xmlbuf
.ptr
+ len
/ sizeof(WCHAR
);
2878 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2879 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2884 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2886 OBJECT_ATTRIBUTES attr
;
2889 attr
.Length
= sizeof(attr
);
2890 attr
.RootDirectory
= 0;
2891 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2892 attr
.ObjectName
= name
;
2893 attr
.SecurityDescriptor
= NULL
;
2894 attr
.SecurityQualityOfService
= NULL
;
2895 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2898 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2899 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2900 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2903 UNICODE_STRING nameW
;
2904 LDR_RESOURCE_INFO info
;
2905 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2908 if (TRACE_ON(actctx
))
2910 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2912 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2913 hModule
, debugstr_w(nameW
.Buffer
) );
2914 RtlFreeUnicodeString( &nameW
);
2916 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2917 hModule
, debugstr_w(filename
) );
2920 if (!resname
) return STATUS_INVALID_PARAMETER
;
2922 info
.Type
= RT_MANIFEST
;
2923 info
.Language
= lang
;
2924 if (!((ULONG_PTR
)resname
>> 16))
2926 info
.Name
= (ULONG_PTR
)resname
;
2927 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2929 else if (resname
[0] == '#')
2932 RtlInitUnicodeString(&nameW
, resname
+ 1);
2933 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2934 return STATUS_INVALID_PARAMETER
;
2936 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2940 RtlCreateUnicodeString(&nameW
, resname
);
2941 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2942 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2943 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2944 RtlFreeUnicodeString(&nameW
);
2946 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2948 if (status
== STATUS_SUCCESS
)
2949 status
= parse_manifest(acl
, ai
, filename
, hModule
, directory
, shared
, ptr
, entry
->Size
);
2954 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2955 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2956 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2959 OBJECT_ATTRIBUTES attr
;
2961 LARGE_INTEGER offset
;
2966 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2968 attr
.Length
= sizeof(attr
);
2969 attr
.RootDirectory
= 0;
2970 attr
.ObjectName
= NULL
;
2971 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2972 attr
.SecurityDescriptor
= NULL
;
2973 attr
.SecurityQualityOfService
= NULL
;
2976 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2977 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2978 if (status
!= STATUS_SUCCESS
) return status
;
2980 offset
.QuadPart
= 0;
2983 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2984 &count
, ViewShare
, 0, PAGE_READONLY
);
2986 if (status
!= STATUS_SUCCESS
) return status
;
2988 if (RtlImageNtHeader(base
)) /* we got a PE file */
2990 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2991 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2993 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2995 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2999 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3000 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
3002 FILE_END_OF_FILE_INFORMATION info
;
3005 OBJECT_ATTRIBUTES attr
;
3007 LARGE_INTEGER offset
;
3012 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
3014 attr
.Length
= sizeof(attr
);
3015 attr
.RootDirectory
= 0;
3016 attr
.ObjectName
= NULL
;
3017 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3018 attr
.SecurityDescriptor
= NULL
;
3019 attr
.SecurityQualityOfService
= NULL
;
3022 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3023 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3024 if (status
!= STATUS_SUCCESS
) return status
;
3026 offset
.QuadPart
= 0;
3029 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3030 &count
, ViewShare
, 0, PAGE_READONLY
);
3032 if (status
!= STATUS_SUCCESS
) return status
;
3034 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
3035 if (status
== STATUS_SUCCESS
)
3036 status
= parse_manifest(acl
, ai
, filename
, NULL
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
3038 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3042 /* try to load the .manifest file associated to the file */
3043 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3044 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3046 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
3049 UNICODE_STRING nameW
;
3051 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3053 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
3055 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
3057 if (module
) /* use the module filename */
3059 UNICODE_STRING name
;
3061 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
3063 if (resid
!= 1) NTDLL_swprintf( name
.Buffer
+ wcslen(name
.Buffer
), fmtW
, resid
);
3064 wcscat( name
.Buffer
, dotManifestW
);
3065 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3066 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3067 RtlFreeUnicodeString( &name
);
3069 if (status
) return status
;
3073 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3074 (wcslen(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3075 return STATUS_NO_MEMORY
;
3076 wcscpy( buffer
, filename
);
3077 if (resid
!= 1) NTDLL_swprintf( buffer
+ wcslen(buffer
), fmtW
, resid
);
3078 wcscat( buffer
, dotManifestW
);
3079 RtlInitUnicodeString( &nameW
, buffer
);
3082 if (!open_nt_file( &file
, &nameW
))
3084 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3087 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
3088 RtlFreeUnicodeString( &nameW
);
3092 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3094 static const WCHAR lookup_fmtW
[] =
3095 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3096 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3097 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3099 WCHAR
*lookup
, *ret
= NULL
;
3100 UNICODE_STRING lookup_us
;
3102 const WCHAR
*lang
= ai
->language
;
3103 unsigned int data_pos
= 0, data_len
;
3106 if (!lang
|| !wcsicmp( lang
, neutralW
)) lang
= wildcardW
;
3108 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
3109 (wcslen(ai
->arch
) + wcslen(ai
->name
)
3110 + wcslen(ai
->public_key
) + wcslen(lang
) + 20) * sizeof(WCHAR
)
3111 + sizeof(lookup_fmtW
) )))
3113 NTDLL_swprintf( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3114 ai
->version
.major
, ai
->version
.minor
, lang
);
3115 RtlInitUnicodeString( &lookup_us
, lookup
);
3117 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3118 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3120 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3121 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3123 ULONG build
, revision
;
3125 data_len
= io
.Information
;
3129 if (data_pos
>= data_len
)
3131 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3132 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3134 data_len
= io
.Information
;
3137 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3139 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3140 else data_pos
= data_len
;
3142 tmp
= dir_info
->FileName
+ (wcschr(lookup
, '*') - lookup
);
3143 build
= wcstoul( tmp
, NULL
, 10 );
3144 if (build
< min_build
) continue;
3145 tmp
= wcschr(tmp
, '.') + 1;
3146 revision
= wcstoul( tmp
, NULL
, 10 );
3147 if (build
== min_build
&& revision
< min_revision
) continue;
3148 tmp
= wcschr(tmp
, '_') + 1;
3149 tmp
= wcschr(tmp
, '_') + 1;
3150 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3151 !wcsnicmp( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3153 /* prefer a non-Wine manifest if we already have one */
3154 /* we'll still load the builtin dll if specified through DllOverrides */
3160 min_revision
= revision
;
3162 ai
->version
.build
= build
;
3163 ai
->version
.revision
= revision
;
3164 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3165 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3167 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3168 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3172 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3173 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3177 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3179 struct assembly_identity sxs_ai
;
3180 UNICODE_STRING path_us
;
3181 OBJECT_ATTRIBUTES attr
;
3183 WCHAR
*path
, *file
= NULL
;
3186 static const WCHAR manifest_dirW
[] =
3187 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3189 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3191 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
3192 wcslen(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
3193 return STATUS_NO_MEMORY
;
3195 wcscpy( path
, user_shared_data
->NtSystemRoot
);
3196 memcpy( path
+ wcslen(path
), manifest_dirW
, sizeof(manifest_dirW
) );
3198 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3200 RtlFreeHeap( GetProcessHeap(), 0, path
);
3201 return STATUS_NO_SUCH_FILE
;
3203 RtlFreeHeap( GetProcessHeap(), 0, path
);
3205 attr
.Length
= sizeof(attr
);
3206 attr
.RootDirectory
= 0;
3207 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3208 attr
.ObjectName
= &path_us
;
3209 attr
.SecurityDescriptor
= NULL
;
3210 attr
.SecurityQualityOfService
= NULL
;
3212 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3213 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3216 file
= lookup_manifest_file( handle
, &sxs_ai
);
3221 RtlFreeUnicodeString( &path_us
);
3222 return STATUS_NO_SUCH_FILE
;
3225 /* append file name to directory path */
3226 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3227 path_us
.Length
+ (wcslen(file
) + 2) * sizeof(WCHAR
) )))
3229 RtlFreeHeap( GetProcessHeap(), 0, file
);
3230 RtlFreeUnicodeString( &path_us
);
3231 return STATUS_NO_MEMORY
;
3234 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3235 wcscpy( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3236 RtlInitUnicodeString( &path_us
, path
);
3237 *wcsrchr(file
, '.') = 0; /* remove .manifest extension */
3239 if (!open_nt_file( &handle
, &path_us
))
3241 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3244 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3246 RtlFreeHeap( GetProcessHeap(), 0, file
);
3247 RtlFreeUnicodeString( &path_us
);
3251 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3252 struct assembly_identity
* ai
)
3254 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3256 WCHAR
*buffer
, *p
, *directory
;
3258 UNICODE_STRING nameW
;
3262 TRACE( "looking for name=%s version=%s arch=%s\n",
3263 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3265 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3267 /* FIXME: add support for language specific lookup */
3269 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3270 wcslen(acl
->actctx
->appdir
.info
));
3272 nameW
.Buffer
= NULL
;
3273 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3274 (len
+ 2 * wcslen(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3275 return STATUS_NO_MEMORY
;
3277 if (!(directory
= build_assembly_dir( ai
)))
3279 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3280 return STATUS_NO_MEMORY
;
3283 /* Lookup in <dir>\name.dll
3284 * <dir>\name.manifest
3285 * <dir>\name\name.dll
3286 * <dir>\name\name.manifest
3288 * First 'appdir' is used as <dir>, if that failed
3289 * it tries application manifest file path.
3291 wcscpy( buffer
, acl
->actctx
->appdir
.info
);
3292 p
= buffer
+ wcslen(buffer
);
3293 for (i
= 0; i
< 4; i
++)
3297 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3298 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3302 wcscpy( p
, ai
->name
);
3305 wcscpy( p
, dotDllW
);
3306 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3308 status
= open_nt_file( &file
, &nameW
);
3311 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3312 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3314 if (status
== STATUS_SUCCESS
)
3317 RtlFreeUnicodeString( &nameW
);
3320 wcscpy( p
, dotManifestW
);
3321 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3323 status
= open_nt_file( &file
, &nameW
);
3326 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3330 RtlFreeUnicodeString( &nameW
);
3332 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3334 RtlFreeUnicodeString( &nameW
);
3335 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3336 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3340 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3342 NTSTATUS status
= STATUS_SUCCESS
;
3345 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3347 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3349 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3351 FIXME( "Could not find dependent assembly %s (%s)\n",
3352 debugstr_w(acl
->dependencies
[i
].name
),
3353 debugstr_version(&acl
->dependencies
[i
].version
) );
3354 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3359 /* FIXME should now iterate through all refs */
3363 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3364 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3366 NTSTATUS status
= STATUS_SUCCESS
;
3368 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3370 if (*handle
) return STATUS_INVALID_PARAMETER
;
3372 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3373 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3375 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3380 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3382 LdrLockLoaderLock( 0, NULL
, &magic
);
3383 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3385 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
3386 status
= STATUS_DLL_NOT_FOUND
;
3388 *handle
= pldr
->ActivationContext
;
3390 else status
= STATUS_DLL_NOT_FOUND
;
3391 LdrUnlockLoaderLock( 0, magic
);
3393 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3394 *handle
= process_actctx
;
3399 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3401 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3402 struct strsection_header
*header
;
3403 struct dllredirect_data
*data
;
3404 struct string_index
*index
;
3407 /* compute section length */
3408 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3410 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3411 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3413 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3415 /* each entry needs index, data and string data */
3416 total_len
+= sizeof(*index
);
3417 total_len
+= sizeof(*data
);
3418 total_len
+= aligned_string_len((wcslen(dll
->name
)+1)*sizeof(WCHAR
));
3421 dll_count
+= assembly
->num_dlls
;
3424 total_len
+= sizeof(*header
);
3426 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3427 if (!header
) return STATUS_NO_MEMORY
;
3429 memset(header
, 0, sizeof(*header
));
3430 header
->magic
= STRSECTION_MAGIC
;
3431 header
->size
= sizeof(*header
);
3432 header
->count
= dll_count
;
3433 header
->index_offset
= sizeof(*header
);
3434 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3435 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3437 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3439 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3440 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3442 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3446 /* setup new index entry */
3447 str
.Buffer
= dll
->name
;
3448 str
.Length
= wcslen(dll
->name
)*sizeof(WCHAR
);
3449 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3450 /* hash original class name */
3451 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3453 index
->name_offset
= name_offset
;
3454 index
->name_len
= str
.Length
;
3455 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3456 index
->data_len
= sizeof(*data
);
3457 index
->rosterindex
= i
+ 1;
3460 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3461 data
->size
= sizeof(*data
);
3462 data
->unk
= 2; /* FIXME: seems to be constant */
3463 memset(data
->res
, 0, sizeof(data
->res
));
3466 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3467 memcpy(ptrW
, dll
->name
, index
->name_len
);
3468 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3470 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3478 return STATUS_SUCCESS
;
3481 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3483 struct string_index
*iter
, *index
= NULL
;
3487 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3488 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3490 for (i
= 0; i
< section
->count
; i
++)
3492 if (iter
->hash
== hash
)
3494 str
.Buffer
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3495 str
.Length
= iter
->name_len
;
3496 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3502 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3510 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3512 struct guid_index
*iter
, *index
= NULL
;
3515 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3517 for (i
= 0; i
< section
->count
; i
++)
3519 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3530 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3532 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3535 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3536 PACTCTX_SECTION_KEYED_DATA data
)
3538 struct dllredirect_data
*dll
;
3539 struct string_index
*index
;
3541 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3543 if (!actctx
->dllredirect_section
)
3545 struct strsection_header
*section
;
3547 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3548 if (status
) return status
;
3550 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3551 RtlFreeHeap(GetProcessHeap(), 0, section
);
3554 index
= find_string_index(actctx
->dllredirect_section
, name
);
3555 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3559 dll
= get_dllredirect_data(actctx
, index
);
3561 data
->ulDataFormatVersion
= 1;
3563 data
->ulLength
= dll
->size
;
3564 data
->lpSectionGlobalData
= NULL
;
3565 data
->ulSectionGlobalDataLength
= 0;
3566 data
->lpSectionBase
= actctx
->dllredirect_section
;
3567 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3568 data
->hActCtx
= NULL
;
3570 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3571 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3574 return STATUS_SUCCESS
;
3577 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3579 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3582 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3584 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3587 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3589 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3590 struct wndclass_redirect_data
*data
;
3591 struct strsection_header
*header
;
3592 struct string_index
*index
;
3595 /* compute section length */
3596 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3598 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3599 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3601 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3602 for (k
= 0; k
< dll
->entities
.num
; k
++)
3604 struct entity
*entity
= &dll
->entities
.base
[k
];
3605 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3607 int class_len
= wcslen(entity
->u
.class.name
) + 1;
3610 /* each class entry needs index, data and string data */
3611 total_len
+= sizeof(*index
);
3612 total_len
+= sizeof(*data
);
3613 /* original name is stored separately */
3614 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3615 /* versioned name and module name are stored one after another */
3616 if (entity
->u
.class.versioned
)
3617 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3620 len
+= wcslen(dll
->name
) + 1;
3621 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3629 total_len
+= sizeof(*header
);
3631 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3632 if (!header
) return STATUS_NO_MEMORY
;
3634 memset(header
, 0, sizeof(*header
));
3635 header
->magic
= STRSECTION_MAGIC
;
3636 header
->size
= sizeof(*header
);
3637 header
->count
= class_count
;
3638 header
->index_offset
= sizeof(*header
);
3639 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3640 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3642 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3644 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3645 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3647 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3648 for (k
= 0; k
< dll
->entities
.num
; k
++)
3650 struct entity
*entity
= &dll
->entities
.base
[k
];
3651 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3653 static const WCHAR exclW
[] = {'!',0};
3654 ULONG versioned_len
, module_len
;
3658 /* setup new index entry */
3659 str
.Buffer
= entity
->u
.class.name
;
3660 str
.Length
= wcslen(entity
->u
.class.name
)*sizeof(WCHAR
);
3661 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3662 /* hash original class name */
3663 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3665 /* include '!' separator too */
3666 if (entity
->u
.class.versioned
)
3667 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3669 versioned_len
= str
.Length
;
3670 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3672 index
->name_offset
= name_offset
;
3673 index
->name_len
= str
.Length
;
3674 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3675 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3676 index
->rosterindex
= i
+ 1;
3679 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3680 data
->size
= sizeof(*data
);
3682 data
->name_len
= versioned_len
;
3683 data
->name_offset
= sizeof(*data
);
3684 data
->module_len
= module_len
;
3685 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3687 /* original class name */
3688 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3689 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3690 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3693 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3694 memcpy(ptrW
, dll
->name
, data
->module_len
);
3695 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3697 /* versioned name */
3698 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3699 if (entity
->u
.class.versioned
)
3701 get_assembly_version(assembly
, ptrW
);
3702 wcscat(ptrW
, exclW
);
3703 wcscat(ptrW
, entity
->u
.class.name
);
3707 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3708 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3711 name_offset
+= sizeof(*data
);
3712 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3722 return STATUS_SUCCESS
;
3725 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3726 PACTCTX_SECTION_KEYED_DATA data
)
3728 struct string_index
*iter
, *index
= NULL
;
3729 struct wndclass_redirect_data
*class;
3734 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3736 if (!actctx
->wndclass_section
)
3738 struct strsection_header
*section
;
3740 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3741 if (status
) return status
;
3743 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3744 RtlFreeHeap(GetProcessHeap(), 0, section
);
3748 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3749 iter
= get_wndclass_first_index(actctx
);
3751 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3753 if (iter
->hash
== hash
)
3755 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3756 str
.Length
= iter
->name_len
;
3757 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3763 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3768 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3772 class = get_wndclass_data(actctx
, index
);
3774 data
->ulDataFormatVersion
= 1;
3775 data
->lpData
= class;
3776 /* full length includes string length with nulls */
3777 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3778 data
->lpSectionGlobalData
= NULL
;
3779 data
->ulSectionGlobalDataLength
= 0;
3780 data
->lpSectionBase
= actctx
->wndclass_section
;
3781 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3782 data
->hActCtx
= NULL
;
3784 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3785 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3788 return STATUS_SUCCESS
;
3791 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3793 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3794 struct guidsection_header
*header
;
3795 ULONG module_offset
, data_offset
;
3796 struct tlibredirect_data
*data
;
3797 struct guid_index
*index
;
3799 /* compute section length */
3800 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3802 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3803 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3805 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3806 for (k
= 0; k
< dll
->entities
.num
; k
++)
3808 struct entity
*entity
= &dll
->entities
.base
[k
];
3809 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3811 /* each entry needs index, data and string data for module name and help string */
3812 total_len
+= sizeof(*index
);
3813 total_len
+= sizeof(*data
);
3814 /* help string is stored separately */
3815 if (*entity
->u
.typelib
.helpdir
)
3816 total_len
+= aligned_string_len((wcslen(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3818 /* module names are packed one after another */
3819 names_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
3827 total_len
+= aligned_string_len(names_len
);
3828 total_len
+= sizeof(*header
);
3830 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3831 if (!header
) return STATUS_NO_MEMORY
;
3833 memset(header
, 0, sizeof(*header
));
3834 header
->magic
= GUIDSECTION_MAGIC
;
3835 header
->size
= sizeof(*header
);
3836 header
->count
= tlib_count
;
3837 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3838 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3839 module_offset
= sizeof(*header
);
3840 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3842 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3844 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3845 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3847 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3848 for (k
= 0; k
< dll
->entities
.num
; k
++)
3850 struct entity
*entity
= &dll
->entities
.base
[k
];
3851 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3853 ULONG module_len
, help_len
;
3857 if (*entity
->u
.typelib
.helpdir
)
3858 help_len
= wcslen(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3862 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3864 /* setup new index entry */
3865 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3866 RtlGUIDFromString(&str
, &index
->guid
);
3867 index
->data_offset
= data_offset
;
3868 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3869 index
->rosterindex
= i
+ 1;
3872 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3873 data
->size
= sizeof(*data
);
3875 data
->name_len
= module_len
;
3876 data
->name_offset
= module_offset
;
3877 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3879 data
->flags
= entity
->u
.typelib
.flags
;
3880 data
->help_len
= help_len
;
3881 data
->help_offset
= sizeof(*data
);
3882 data
->major_version
= entity
->u
.typelib
.major
;
3883 data
->minor_version
= entity
->u
.typelib
.minor
;
3886 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3887 memcpy(ptrW
, dll
->name
, data
->name_len
);
3888 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3893 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3894 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3895 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3898 data_offset
+= sizeof(*data
);
3900 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3902 module_offset
+= module_len
+ sizeof(WCHAR
);
3912 return STATUS_SUCCESS
;
3915 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3917 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3920 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3922 struct guid_index
*index
= NULL
;
3923 struct tlibredirect_data
*tlib
;
3925 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3927 if (!actctx
->tlib_section
)
3929 struct guidsection_header
*section
;
3931 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3932 if (status
) return status
;
3934 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3935 RtlFreeHeap(GetProcessHeap(), 0, section
);
3938 index
= find_guid_index(actctx
->tlib_section
, guid
);
3939 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3941 tlib
= get_tlib_data(actctx
, index
);
3943 data
->ulDataFormatVersion
= 1;
3944 data
->lpData
= tlib
;
3945 /* full length includes string length with nulls */
3946 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3947 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3948 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3949 data
->lpSectionBase
= actctx
->tlib_section
;
3950 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3951 data
->hActCtx
= NULL
;
3953 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3954 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3956 return STATUS_SUCCESS
;
3959 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3961 ULONG
*ptr
= (ULONG
*)guid
;
3964 /* GUID is 16 bytes long */
3965 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3966 *ptr
= RtlUniform(seed
);
3968 guid
->Data3
&= 0x0fff;
3969 guid
->Data3
|= (4 << 12);
3970 guid
->Data4
[0] &= 0x3f;
3971 guid
->Data4
[0] |= 0x80;
3974 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3975 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3979 for (i
= 0; i
< entities
->num
; i
++)
3981 struct entity
*entity
= &entities
->base
[i
];
3982 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3984 /* each entry needs two index entries, extra one goes for alias GUID */
3985 *len
+= 2*sizeof(struct guid_index
);
3986 /* To save some memory we don't allocated two data structures,
3987 instead alias index and normal index point to the same data structure. */
3988 *len
+= sizeof(struct comclassredirect_data
);
3990 /* for clrClass store some more */
3991 if (entity
->u
.comclass
.name
)
3993 unsigned int str_len
;
3995 /* all string data is stored together in aligned block */
3996 str_len
= wcslen(entity
->u
.comclass
.name
)+1;
3997 if (entity
->u
.comclass
.progid
)
3998 str_len
+= wcslen(entity
->u
.comclass
.progid
)+1;
3999 if (entity
->u
.comclass
.version
)
4000 str_len
+= wcslen(entity
->u
.comclass
.version
)+1;
4002 *len
+= sizeof(struct clrclass_data
);
4003 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
4005 /* module name is forced to mscoree.dll, and stored two times with different case */
4006 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
4010 /* progid string is stored separately */
4011 if (entity
->u
.comclass
.progid
)
4012 *len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4014 *module_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
4022 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4023 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4024 ULONG
*seed
, ULONG rosterindex
)
4028 for (i
= 0; i
< entities
->num
; i
++)
4030 struct entity
*entity
= &entities
->base
[i
];
4031 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4033 ULONG module_len
, progid_len
, str_len
= 0;
4034 struct comclassredirect_data
*data
;
4035 struct guid_index
*alias_index
;
4036 struct clrclass_data
*clrdata
;
4040 if (entity
->u
.comclass
.progid
)
4041 progid_len
= wcslen(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4045 module_len
= dll
? wcslen(dll
->name
)*sizeof(WCHAR
) : wcslen(mscoreeW
)*sizeof(WCHAR
);
4047 /* setup new index entry */
4048 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4049 RtlGUIDFromString(&str
, &(*index
)->guid
);
4051 (*index
)->data_offset
= *data_offset
;
4052 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4053 (*index
)->rosterindex
= rosterindex
;
4055 /* Setup new index entry for alias guid. Alias index records are placed after
4056 normal records, so normal guids are hit first on search. Note that class count
4058 alias_index
= (*index
) + section
->count
/2;
4059 generate_uuid(seed
, &alias_index
->guid
);
4060 alias_index
->data_offset
= (*index
)->data_offset
;
4061 alias_index
->data_len
= 0;
4062 alias_index
->rosterindex
= (*index
)->rosterindex
;
4065 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4066 data
->size
= sizeof(*data
);
4070 data
->model
= entity
->u
.comclass
.model
;
4071 data
->clsid
= (*index
)->guid
;
4072 data
->alias
= alias_index
->guid
;
4073 data
->clsid2
= data
->clsid
;
4074 if (entity
->u
.comclass
.tlbid
)
4076 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4077 RtlGUIDFromString(&str
, &data
->tlbid
);
4080 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4081 data
->name_len
= module_len
;
4082 data
->name_offset
= *module_offset
;
4083 data
->progid_len
= progid_len
;
4084 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4085 data
->clrdata_len
= 0; /* will be set later */
4086 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4087 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4088 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4089 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4090 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4091 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4093 /* mask describes which misc* data is available */
4095 if (data
->miscstatus
)
4096 data
->miscmask
|= MiscStatus
;
4097 if (data
->miscstatuscontent
)
4098 data
->miscmask
|= MiscStatusContent
;
4099 if (data
->miscstatusthumbnail
)
4100 data
->miscmask
|= MiscStatusThumbnail
;
4101 if (data
->miscstatusicon
)
4102 data
->miscmask
|= MiscStatusIcon
;
4103 if (data
->miscstatusdocprint
)
4104 data
->miscmask
|= MiscStatusDocPrint
;
4106 if (data
->clrdata_offset
)
4108 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4110 clrdata
->size
= sizeof(*clrdata
);
4111 clrdata
->res
[0] = 0;
4112 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4113 clrdata
->module_len
= wcslen(mscoreeW
)*sizeof(WCHAR
);
4114 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4115 clrdata
->name_len
= wcslen(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4116 clrdata
->name_offset
= clrdata
->size
;
4117 clrdata
->version_len
= entity
->u
.comclass
.version
? wcslen(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4118 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4119 clrdata
->res2
[0] = 0;
4120 clrdata
->res2
[1] = 0;
4122 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4125 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4126 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
4127 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4129 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4130 memcpy(ptrW
, mscoreeW
, data
->name_len
);
4131 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4134 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4135 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4136 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4138 /* runtime version, optional */
4139 if (clrdata
->version_len
)
4141 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4143 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4144 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4145 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4148 if (data
->progid_len
)
4149 data
->progid_offset
+= data
->clrdata_len
;
4150 (*index
)->data_len
+= sizeof(*clrdata
);
4157 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4158 memcpy(ptrW
, dll
->name
, data
->name_len
);
4159 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4163 if (data
->progid_len
)
4165 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4166 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4167 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4170 /* string block length */
4174 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4175 if (clrdata
->version_len
)
4176 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4179 str_len
+= progid_len
+ sizeof(WCHAR
);
4181 (*index
)->data_len
+= aligned_string_len(str_len
);
4182 alias_index
->data_len
= (*index
)->data_len
;
4184 /* move to next data record */
4185 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4186 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4190 (*data_offset
) += sizeof(*clrdata
);
4191 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4198 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4200 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4201 struct guidsection_header
*header
;
4202 ULONG module_offset
, data_offset
;
4203 struct guid_index
*index
;
4206 /* compute section length */
4207 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4209 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4210 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4211 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4213 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4214 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4218 total_len
+= aligned_string_len(names_len
);
4219 total_len
+= sizeof(*header
);
4221 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4222 if (!header
) return STATUS_NO_MEMORY
;
4224 memset(header
, 0, sizeof(*header
));
4225 header
->magic
= GUIDSECTION_MAGIC
;
4226 header
->size
= sizeof(*header
);
4227 header
->count
= 2*class_count
;
4228 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4229 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4230 module_offset
= sizeof(*header
);
4231 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4233 seed
= NtGetTickCount();
4234 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4236 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4237 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4238 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4240 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4241 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4247 return STATUS_SUCCESS
;
4250 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4252 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4255 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4257 struct comclassredirect_data
*comclass
;
4258 struct guid_index
*index
= NULL
;
4260 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4262 if (!actctx
->comserver_section
)
4264 struct guidsection_header
*section
;
4266 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4267 if (status
) return status
;
4269 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4270 RtlFreeHeap(GetProcessHeap(), 0, section
);
4273 index
= find_guid_index(actctx
->comserver_section
, guid
);
4274 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4276 comclass
= get_comclass_data(actctx
, index
);
4278 data
->ulDataFormatVersion
= 1;
4279 data
->lpData
= comclass
;
4280 /* full length includes string length with nulls */
4281 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4282 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4283 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4284 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4285 data
->lpSectionBase
= actctx
->comserver_section
;
4286 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4287 data
->hActCtx
= NULL
;
4289 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4290 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4292 return STATUS_SUCCESS
;
4295 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4299 for (i
= 0; i
< entities
->num
; i
++)
4301 struct entity
*entity
= &entities
->base
[i
];
4302 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4304 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4305 if (entity
->u
.ifaceps
.name
)
4306 *len
+= aligned_string_len((wcslen(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4312 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4313 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4317 for (i
= 0; i
< entities
->num
; i
++)
4319 struct entity
*entity
= &entities
->base
[i
];
4320 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4322 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4326 if (entity
->u
.ifaceps
.name
)
4327 name_len
= wcslen(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4332 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4333 RtlGUIDFromString(&str
, &(*index
)->guid
);
4334 (*index
)->data_offset
= *data_offset
;
4335 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4336 (*index
)->rosterindex
= rosterindex
;
4338 /* setup data record */
4339 data
->size
= sizeof(*data
);
4340 data
->mask
= entity
->u
.ifaceps
.mask
;
4342 /* proxyStubClsid32 value is only stored for external PS,
4343 if set it's used as iid, otherwise 'iid' attribute value is used */
4344 if (entity
->u
.ifaceps
.ps32
)
4346 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4347 RtlGUIDFromString(&str
, &data
->iid
);
4350 data
->iid
= (*index
)->guid
;
4352 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4354 if (entity
->u
.ifaceps
.tlib
)
4356 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4357 RtlGUIDFromString(&str
, &data
->tlbid
);
4360 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4362 if (entity
->u
.ifaceps
.base
)
4364 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4365 RtlGUIDFromString(&str
, &data
->base
);
4368 memset(&data
->base
, 0, sizeof(data
->base
));
4370 data
->name_len
= name_len
;
4371 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4376 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4377 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4378 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4381 /* move to next record */
4383 *data_offset
+= sizeof(*data
);
4385 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4390 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4392 unsigned int i
, j
, total_len
= 0, count
= 0;
4393 struct guidsection_header
*header
;
4394 struct guid_index
*index
;
4397 /* compute section length */
4398 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4400 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4402 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4403 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4405 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4406 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4410 total_len
+= sizeof(*header
);
4412 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4413 if (!header
) return STATUS_NO_MEMORY
;
4415 memset(header
, 0, sizeof(*header
));
4416 header
->magic
= GUIDSECTION_MAGIC
;
4417 header
->size
= sizeof(*header
);
4418 header
->count
= count
;
4419 header
->index_offset
= sizeof(*header
);
4420 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4421 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4423 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4425 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4427 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4428 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4430 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4431 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4437 return STATUS_SUCCESS
;
4440 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4442 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4445 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4447 struct ifacepsredirect_data
*iface
;
4448 struct guid_index
*index
= NULL
;
4450 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4452 if (!actctx
->ifaceps_section
)
4454 struct guidsection_header
*section
;
4456 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4457 if (status
) return status
;
4459 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4460 RtlFreeHeap(GetProcessHeap(), 0, section
);
4463 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4464 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4466 iface
= get_ifaceps_data(actctx
, index
);
4468 data
->ulDataFormatVersion
= 1;
4469 data
->lpData
= iface
;
4470 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4471 data
->lpSectionGlobalData
= NULL
;
4472 data
->ulSectionGlobalDataLength
= 0;
4473 data
->lpSectionBase
= actctx
->ifaceps_section
;
4474 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4475 data
->hActCtx
= NULL
;
4477 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4478 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4480 return STATUS_SUCCESS
;
4483 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4485 unsigned int i
, j
, total_len
= 0, count
= 0;
4486 struct guidsection_header
*header
;
4487 struct clrsurrogate_data
*data
;
4488 struct guid_index
*index
;
4491 /* compute section length */
4492 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4494 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4495 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4497 struct entity
*entity
= &assembly
->entities
.base
[j
];
4498 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4502 total_len
+= sizeof(*index
) + sizeof(*data
);
4503 len
= wcslen(entity
->u
.clrsurrogate
.name
) + 1;
4504 if (entity
->u
.clrsurrogate
.version
)
4505 len
+= wcslen(entity
->u
.clrsurrogate
.version
) + 1;
4506 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4513 total_len
+= sizeof(*header
);
4515 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4516 if (!header
) return STATUS_NO_MEMORY
;
4518 memset(header
, 0, sizeof(*header
));
4519 header
->magic
= GUIDSECTION_MAGIC
;
4520 header
->size
= sizeof(*header
);
4521 header
->count
= count
;
4522 header
->index_offset
= sizeof(*header
);
4523 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4524 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4526 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4528 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4529 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4531 struct entity
*entity
= &assembly
->entities
.base
[j
];
4532 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4534 ULONG version_len
, name_len
;
4538 if (entity
->u
.clrsurrogate
.version
)
4539 version_len
= wcslen(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4542 name_len
= wcslen(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4544 /* setup new index entry */
4545 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4546 RtlGUIDFromString(&str
, &index
->guid
);
4548 index
->data_offset
= data_offset
;
4549 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4550 index
->rosterindex
= i
+ 1;
4553 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4554 data
->size
= sizeof(*data
);
4556 data
->clsid
= index
->guid
;
4557 data
->version_offset
= version_len
? data
->size
: 0;
4558 data
->version_len
= version_len
;
4559 data
->name_offset
= data
->size
+ version_len
;
4561 data
->name_offset
+= sizeof(WCHAR
);
4562 data
->name_len
= name_len
;
4564 /* surrogate name */
4565 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4566 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4567 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4569 /* runtime version */
4570 if (data
->version_len
)
4572 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4573 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4574 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4577 data_offset
+= index
->data_offset
;
4585 return STATUS_SUCCESS
;
4588 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4590 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4593 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4595 struct clrsurrogate_data
*surrogate
;
4596 struct guid_index
*index
= NULL
;
4598 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4600 if (!actctx
->clrsurrogate_section
)
4602 struct guidsection_header
*section
;
4604 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4605 if (status
) return status
;
4607 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4608 RtlFreeHeap(GetProcessHeap(), 0, section
);
4611 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4612 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4614 surrogate
= get_surrogate_data(actctx
, index
);
4616 data
->ulDataFormatVersion
= 1;
4617 data
->lpData
= surrogate
;
4618 /* full length includes string length with nulls */
4619 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4620 if (surrogate
->version_len
)
4621 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4623 data
->lpSectionGlobalData
= NULL
;
4624 data
->ulSectionGlobalDataLength
= 0;
4625 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4626 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4627 data
->hActCtx
= NULL
;
4629 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4630 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4632 return STATUS_SUCCESS
;
4635 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4637 unsigned int i
, j
, single_len
;
4639 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4640 for (i
= 0; i
< entities
->num
; i
++)
4642 struct entity
*entity
= &entities
->base
[i
];
4643 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4645 if (entity
->u
.comclass
.progid
)
4647 *total_len
+= single_len
+ aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4651 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4652 *total_len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4654 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4655 *count
+= entity
->u
.comclass
.progids
.num
;
4660 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4661 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4663 struct progidredirect_data
*data
;
4668 /* setup new index entry */
4670 /* hash progid name */
4671 RtlInitUnicodeString(&str
, progid
);
4672 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4674 (*index
)->name_offset
= *data_offset
;
4675 (*index
)->name_len
= str
.Length
;
4676 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4677 (*index
)->data_len
= sizeof(*data
);
4678 (*index
)->rosterindex
= rosterindex
;
4680 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4682 /* setup data structure */
4683 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4684 data
->size
= sizeof(*data
);
4686 data
->clsid_offset
= *global_offset
;
4688 /* write progid string */
4689 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4690 memcpy(ptrW
, progid
, (*index
)->name_len
);
4691 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4693 /* write guid to global area */
4694 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4698 *global_offset
+= sizeof(GUID
);
4699 *data_offset
+= data
->size
;
4703 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4704 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4708 for (i
= 0; i
< entities
->num
; i
++)
4710 struct entity
*entity
= &entities
->base
[i
];
4711 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4713 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4714 struct comclassredirect_data
*comclass
;
4715 struct guid_index
*guid_index
;
4719 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4720 RtlGUIDFromString(&str
, &clsid
);
4722 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4723 comclass
= get_comclass_data(actctx
, guid_index
);
4725 if (entity
->u
.comclass
.progid
)
4726 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4727 index
, data_offset
, global_offset
, rosterindex
);
4729 for (j
= 0; j
< progids
->num
; j
++)
4730 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4731 index
, data_offset
, global_offset
, rosterindex
);
4736 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4738 unsigned int i
, j
, total_len
= 0, count
= 0;
4739 struct strsection_header
*header
;
4740 ULONG data_offset
, global_offset
;
4741 struct string_index
*index
;
4743 /* compute section length */
4744 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4746 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4748 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4749 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4751 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4752 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4756 total_len
+= sizeof(*header
);
4758 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4759 if (!header
) return STATUS_NO_MEMORY
;
4761 memset(header
, 0, sizeof(*header
));
4762 header
->magic
= STRSECTION_MAGIC
;
4763 header
->size
= sizeof(*header
);
4764 header
->count
= count
;
4765 header
->global_offset
= header
->size
;
4766 header
->global_len
= count
*sizeof(GUID
);
4767 header
->index_offset
= header
->size
+ header
->global_len
;
4769 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4770 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4771 global_offset
= header
->global_offset
;
4773 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4775 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4777 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4778 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4780 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4781 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4787 return STATUS_SUCCESS
;
4790 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4792 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4795 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4796 PACTCTX_SECTION_KEYED_DATA data
)
4798 struct progidredirect_data
*progid
;
4799 struct string_index
*index
;
4801 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4803 if (!actctx
->comserver_section
)
4805 struct guidsection_header
*section
;
4807 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4808 if (status
) return status
;
4810 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4811 RtlFreeHeap(GetProcessHeap(), 0, section
);
4814 if (!actctx
->progid_section
)
4816 struct strsection_header
*section
;
4818 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4819 if (status
) return status
;
4821 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4822 RtlFreeHeap(GetProcessHeap(), 0, section
);
4825 index
= find_string_index(actctx
->progid_section
, name
);
4826 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4830 progid
= get_progid_data(actctx
, index
);
4832 data
->ulDataFormatVersion
= 1;
4833 data
->lpData
= progid
;
4834 data
->ulLength
= progid
->size
;
4835 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4836 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4837 data
->lpSectionBase
= actctx
->progid_section
;
4838 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4839 data
->hActCtx
= NULL
;
4841 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4842 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4845 return STATUS_SUCCESS
;
4848 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4849 const UNICODE_STRING
*section_name
,
4850 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4854 switch (section_kind
)
4856 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4857 status
= find_dll_redirection(actctx
, section_name
, data
);
4859 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4860 status
= find_window_class(actctx
, section_name
, data
);
4862 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4863 status
= find_progid_redirection(actctx
, section_name
, data
);
4865 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4866 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4867 return STATUS_SXS_SECTION_NOT_FOUND
;
4869 WARN("Unknown section_kind %x\n", section_kind
);
4870 return STATUS_SXS_SECTION_NOT_FOUND
;
4873 if (status
!= STATUS_SUCCESS
) return status
;
4875 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4877 actctx_addref(actctx
);
4878 data
->hActCtx
= actctx
;
4880 return STATUS_SUCCESS
;
4883 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4884 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4888 switch (section_kind
)
4890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4891 status
= find_tlib_redirection(actctx
, guid
, data
);
4893 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4894 status
= find_comserver_redirection(actctx
, guid
, data
);
4896 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4897 status
= find_cominterface_redirection(actctx
, guid
, data
);
4899 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4900 status
= find_clr_surrogate(actctx
, guid
, data
);
4903 WARN("Unknown section_kind %x\n", section_kind
);
4904 return STATUS_SXS_SECTION_NOT_FOUND
;
4907 if (status
!= STATUS_SUCCESS
) return status
;
4909 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4911 actctx_addref(actctx
);
4912 data
->hActCtx
= actctx
;
4914 return STATUS_SUCCESS
;
4917 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
4921 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4923 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4924 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4926 struct entity
*entity
= &assembly
->entities
.base
[j
];
4927 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
4928 !wcscmp( entity
->u
.settings
.name
, settings
) &&
4929 !wcscmp( entity
->u
.settings
.ns
, ns
))
4930 return entity
->u
.settings
.value
;
4936 /* initialize the activation context for the current process */
4937 void actctx_init(void)
4942 ctx
.cbSize
= sizeof(ctx
);
4943 ctx
.lpSource
= NULL
;
4944 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4945 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4946 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4948 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4950 NtCurrentTeb()->Peb
->ActivationContextData
= process_actctx
;
4954 /***********************************************************************
4955 * RtlCreateActivationContext (NTDLL.@)
4957 * Create an activation context.
4959 * FIXME: function signature/prototype is wrong
4961 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4963 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4964 const WCHAR
*directory
= NULL
;
4965 ACTIVATION_CONTEXT
*actctx
;
4966 UNICODE_STRING nameW
;
4968 NTSTATUS status
= STATUS_NO_MEMORY
;
4970 struct actctx_loader acl
;
4972 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4974 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4975 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4976 return STATUS_INVALID_PARAMETER
;
4978 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4979 return STATUS_NO_MEMORY
;
4981 actctx
->magic
= ACTCTX_MAGIC
;
4982 actctx
->ref_count
= 1;
4983 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4984 actctx
->config
.info
= NULL
;
4985 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4986 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4988 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4996 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4997 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4999 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
5000 if ((p
= wcsrchr( dir
.Buffer
, '\\' ))) p
[1] = 0;
5001 actctx
->appdir
.info
= dir
.Buffer
;
5004 nameW
.Buffer
= NULL
;
5006 /* open file only if it's going to be used */
5007 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
5008 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
5010 WCHAR
*source
= NULL
;
5013 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5014 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
5016 DWORD dir_len
, source_len
;
5018 dir_len
= wcslen(pActCtx
->lpAssemblyDirectory
);
5019 source_len
= wcslen(pActCtx
->lpSource
);
5020 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5022 status
= STATUS_NO_MEMORY
;
5026 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5027 source
[dir_len
] = '\\';
5028 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5031 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5032 RtlFreeHeap( GetProcessHeap(), 0, source
);
5035 status
= STATUS_NO_SUCH_FILE
;
5038 status
= open_nt_file( &file
, &nameW
);
5041 RtlFreeUnicodeString( &nameW
);
5046 acl
.actctx
= actctx
;
5047 acl
.dependencies
= NULL
;
5048 acl
.num_dependencies
= 0;
5049 acl
.allocated_dependencies
= 0;
5051 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5052 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5054 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5056 /* if we have a resource it's a PE file */
5057 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5059 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5060 pActCtx
->lpResourceName
, lang
);
5061 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5062 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5063 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5065 else if (pActCtx
->lpSource
)
5067 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5068 file
, pActCtx
->lpResourceName
, lang
);
5069 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5070 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5071 NULL
, pActCtx
->lpResourceName
);
5073 else status
= STATUS_INVALID_PARAMETER
;
5077 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5080 if (file
) NtClose( file
);
5081 RtlFreeUnicodeString( &nameW
);
5083 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
5084 free_depend_manifests( &acl
);
5086 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
5087 else actctx_release( actctx
);
5091 if (file
) NtClose( file
);
5092 actctx_release( actctx
);
5097 /***********************************************************************
5098 * RtlAddRefActivationContext (NTDLL.@)
5100 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
5102 ACTIVATION_CONTEXT
*actctx
;
5104 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5108 /******************************************************************
5109 * RtlReleaseActivationContext (NTDLL.@)
5111 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5113 ACTIVATION_CONTEXT
*actctx
;
5115 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5118 /******************************************************************
5119 * RtlZombifyActivationContext (NTDLL.@)
5121 * FIXME: function prototype might be wrong
5123 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5125 FIXME("%p: stub\n", handle
);
5126 return STATUS_NOT_IMPLEMENTED
;
5129 /******************************************************************
5130 * RtlActivateActivationContext (NTDLL.@)
5132 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5134 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5136 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5137 return STATUS_NO_MEMORY
;
5139 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5140 frame
->ActivationContext
= handle
;
5142 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
5143 RtlAddRefActivationContext( handle
);
5145 *cookie
= (ULONG_PTR
)frame
;
5146 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
5147 return STATUS_SUCCESS
;
5151 /***********************************************************************
5152 * RtlDeactivateActivationContext (NTDLL.@)
5154 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5156 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5158 TRACE( "%x cookie=%lx\n", flags
, cookie
);
5160 /* find the right frame */
5161 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5162 for (frame
= top
; frame
; frame
= frame
->Previous
)
5163 if ((ULONG_PTR
)frame
== cookie
) break;
5166 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5168 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5169 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5171 /* pop everything up to and including frame */
5172 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5174 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5176 frame
= top
->Previous
;
5177 RtlReleaseActivationContext( top
->ActivationContext
);
5178 RtlFreeHeap( GetProcessHeap(), 0, top
);
5184 /******************************************************************
5185 * RtlFreeThreadActivationContextStack (NTDLL.@)
5187 void WINAPI
RtlFreeThreadActivationContextStack(void)
5189 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5191 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5194 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5195 RtlReleaseActivationContext( frame
->ActivationContext
);
5196 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5199 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5203 /******************************************************************
5204 * RtlGetActiveActivationContext (NTDLL.@)
5206 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5208 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5210 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5211 RtlAddRefActivationContext( *handle
);
5216 return STATUS_SUCCESS
;
5220 /******************************************************************
5221 * RtlIsActivationContextActive (NTDLL.@)
5223 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5225 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5227 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5228 if (frame
->ActivationContext
== handle
) return TRUE
;
5233 /***********************************************************************
5234 * RtlQueryInformationActivationContext (NTDLL.@)
5236 * Get information about an activation context.
5237 * FIXME: function signature/prototype may be wrong
5239 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5240 ULONG
class, PVOID buffer
,
5241 SIZE_T bufsize
, SIZE_T
*retlen
)
5243 ACTIVATION_CONTEXT
*actctx
;
5246 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5247 subinst
, class, buffer
, bufsize
, retlen
);
5249 if (retlen
) *retlen
= 0;
5250 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5254 case ActivationContextBasicInformation
:
5256 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5258 if (retlen
) *retlen
= sizeof(*info
);
5259 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5261 info
->hActCtx
= handle
;
5262 info
->dwFlags
= 0; /* FIXME */
5263 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5267 case ActivationContextDetailedInformation
:
5269 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5270 struct assembly
*assembly
= NULL
;
5271 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5274 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5276 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5278 if (assembly
&& assembly
->manifest
.info
)
5279 manifest_len
= wcslen(assembly
->manifest
.info
) + 1;
5280 if (actctx
->config
.info
) config_len
= wcslen(actctx
->config
.info
) + 1;
5281 if (actctx
->appdir
.info
) appdir_len
= wcslen(actctx
->appdir
.info
) + 1;
5282 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5284 if (retlen
) *retlen
= len
;
5285 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5288 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5289 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5290 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5291 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5292 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5293 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5294 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5295 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5296 ptr
= (LPWSTR
)(acdi
+ 1);
5299 acdi
->lpRootManifestPath
= ptr
;
5300 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5301 ptr
+= manifest_len
;
5303 else acdi
->lpRootManifestPath
= NULL
;
5306 acdi
->lpRootConfigurationPath
= ptr
;
5307 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5310 else acdi
->lpRootConfigurationPath
= NULL
;
5313 acdi
->lpAppDirPath
= ptr
;
5314 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5316 else acdi
->lpAppDirPath
= NULL
;
5320 case AssemblyDetailedInformationInActivationContext
:
5322 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5323 struct assembly
*assembly
;
5326 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5329 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5330 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5332 index
= *(DWORD
*)subinst
;
5333 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5335 assembly
= &actctx
->assemblies
[index
- 1];
5337 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5338 id_len
= wcslen(assembly_id
) + 1;
5339 if (assembly
->directory
) ad_len
= wcslen(assembly
->directory
) + 1;
5341 if (assembly
->manifest
.info
&&
5342 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5343 path_len
= wcslen(assembly
->manifest
.info
) + 1;
5345 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5347 if (retlen
) *retlen
= len
;
5348 if (!buffer
|| bufsize
< len
)
5350 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5351 return STATUS_BUFFER_TOO_SMALL
;
5354 afdi
->ulFlags
= 0; /* FIXME */
5355 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5356 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5357 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5358 /* FIXME afdi->liManifestLastWriteTime = 0; */
5359 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5360 afdi
->ulPolicyPathLength
= 0;
5361 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5362 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5363 afdi
->ulManifestVersionMajor
= 1;
5364 afdi
->ulManifestVersionMinor
= 0;
5365 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5366 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5367 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5368 ptr
= (LPWSTR
)(afdi
+ 1);
5369 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5370 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5374 afdi
->lpAssemblyManifestPath
= ptr
;
5375 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5377 } else afdi
->lpAssemblyManifestPath
= NULL
;
5378 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5381 afdi
->lpAssemblyDirectoryName
= ptr
;
5382 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5384 else afdi
->lpAssemblyDirectoryName
= NULL
;
5385 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5389 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5391 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5392 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5393 struct assembly
*assembly
;
5394 struct dll_redirect
*dll
;
5395 SIZE_T len
, dll_len
= 0;
5398 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5399 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5401 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5402 return STATUS_INVALID_PARAMETER
;
5403 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5405 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5406 return STATUS_INVALID_PARAMETER
;
5407 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5409 if (dll
->name
) dll_len
= wcslen(dll
->name
) + 1;
5410 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5412 if (!buffer
|| bufsize
< len
)
5414 if (retlen
) *retlen
= len
;
5415 return STATUS_BUFFER_TOO_SMALL
;
5417 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5418 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5419 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5420 afdi
->ulPathLength
= 0; /* FIXME */
5421 ptr
= (LPWSTR
)(afdi
+ 1);
5424 afdi
->lpFileName
= ptr
;
5425 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5426 } else afdi
->lpFileName
= NULL
;
5427 afdi
->lpFilePath
= NULL
; /* FIXME */
5431 case CompatibilityInformationInActivationContext
:
5433 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5434 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5435 struct assembly
*assembly
= NULL
;
5436 ULONG num_compat_contexts
= 0, n
;
5439 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5441 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5444 num_compat_contexts
= assembly
->num_compat_contexts
;
5445 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5447 if (retlen
) *retlen
= len
;
5448 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5450 *acci
= num_compat_contexts
;
5451 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5452 for (n
= 0; n
< num_compat_contexts
; ++n
)
5454 elements
[n
] = assembly
->compat_contexts
[n
];
5459 case RunlevelInformationInActivationContext
:
5461 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5462 struct assembly
*assembly
;
5465 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5467 len
= sizeof(*acrli
);
5468 if (retlen
) *retlen
= len
;
5469 if (!buffer
|| bufsize
< len
)
5470 return STATUS_BUFFER_TOO_SMALL
;
5472 assembly
= actctx
->assemblies
;
5475 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5476 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5481 FIXME( "class %u not implemented\n", class );
5482 return STATUS_NOT_IMPLEMENTED
;
5484 return STATUS_SUCCESS
;
5487 /***********************************************************************
5488 * RtlFindActivationContextSectionString (NTDLL.@)
5490 * Find information about a string in an activation context.
5491 * FIXME: function signature/prototype may be wrong
5493 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5494 const UNICODE_STRING
*section_name
, PVOID ptr
)
5496 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5497 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5499 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5500 debugstr_us(section_name
), data
);
5504 FIXME("expected guid == NULL\n");
5505 return STATUS_INVALID_PARAMETER
;
5507 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5509 FIXME("unknown flags %08x\n", flags
);
5510 return STATUS_INVALID_PARAMETER
;
5512 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5513 !section_name
|| !section_name
->Buffer
)
5515 WARN("invalid parameter\n");
5516 return STATUS_INVALID_PARAMETER
;
5519 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5521 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5522 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5525 if (status
!= STATUS_SUCCESS
)
5526 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5531 /***********************************************************************
5532 * RtlFindActivationContextSectionGuid (NTDLL.@)
5534 * Find information about a GUID in an activation context.
5535 * FIXME: function signature/prototype may be wrong
5537 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5538 const GUID
*guid
, void *ptr
)
5540 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5541 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5543 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5547 FIXME("expected extguid == NULL\n");
5548 return STATUS_INVALID_PARAMETER
;
5551 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5553 FIXME("unknown flags %08x\n", flags
);
5554 return STATUS_INVALID_PARAMETER
;
5557 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5558 return STATUS_INVALID_PARAMETER
;
5560 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5562 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5563 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5566 if (status
!= STATUS_SUCCESS
)
5567 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5573 /***********************************************************************
5574 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5576 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5577 const WCHAR
*settings
, WCHAR
*buffer
,
5578 SIZE_T size
, SIZE_T
*written
)
5580 ACTIVATION_CONTEXT
*actctx
;
5585 WARN( "unknown flags %08x\n", flags
);
5586 return STATUS_INVALID_PARAMETER
;
5591 if (wcscmp( ns
, windowsSettings2005NSW
) &&
5592 wcscmp( ns
, windowsSettings2011NSW
) &&
5593 wcscmp( ns
, windowsSettings2016NSW
) &&
5594 wcscmp( ns
, windowsSettings2017NSW
))
5595 return STATUS_INVALID_PARAMETER
;
5597 else ns
= windowsSettings2005NSW
;
5599 if (!handle
) handle
= process_actctx
;
5600 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5602 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5604 if (written
) *written
= wcslen(res
) + 1;
5605 if (size
< wcslen(res
)) return STATUS_BUFFER_TOO_SMALL
;
5606 wcscpy( buffer
, res
);
5607 return STATUS_SUCCESS
;