4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/port.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
62 typedef enum tagLIBFLAGS
{
63 LIBFLAG_FRESTRICTED
= 0x1,
64 LIBFLAG_FCONTROL
= 0x2,
65 LIBFLAG_FHIDDEN
= 0x4,
66 LIBFLAG_FHASDISKIMAGE
= 0x8
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
73 OLEMISC_ONLYICONIC
= 0x2,
74 OLEMISC_INSERTNOTREPLACE
= 0x4,
76 OLEMISC_CANTLINKINSIDE
= 0x10,
77 OLEMISC_CANLINKBYOLE1
= 0x20,
78 OLEMISC_ISLINKOBJECT
= 0x40,
79 OLEMISC_INSIDEOUT
= 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
82 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
83 OLEMISC_ALWAYSRUN
= 0x800,
84 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
85 OLEMISC_ACTSLIKELABEL
= 0x2000,
86 OLEMISC_NOUIACTIVATE
= 0x4000,
87 OLEMISC_ALIGNABLE
= 0x8000,
88 OLEMISC_SIMPLEFRAME
= 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
90 OLEMISC_IMEMODE
= 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
92 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
114 struct assembly_version
122 struct assembly_identity
129 struct assembly_version version
;
134 struct strsection_header
148 ULONG hash
; /* key string hash */
151 ULONG data_offset
; /* redirect data offset */
156 struct guidsection_header
176 struct wndclass_redirect_data
181 ULONG name_offset
; /* versioned name offset */
183 ULONG module_offset
;/* container name offset */
186 struct dllredirect_data
193 struct tlibredirect_data
207 enum comclass_threadingmodel
209 ThreadingModel_Apartment
= 1,
210 ThreadingModel_Free
= 2,
211 ThreadingModel_No
= 3,
212 ThreadingModel_Both
= 4,
213 ThreadingModel_Neutral
= 5
216 enum comclass_miscfields
220 MiscStatusContent
= 4,
221 MiscStatusThumbnail
= 8,
222 MiscStatusDocPrint
= 16
225 struct comclassredirect_data
241 ULONG clrdata_offset
;
243 DWORD miscstatuscontent
;
244 DWORD miscstatusthumbnail
;
245 DWORD miscstatusicon
;
246 DWORD miscstatusdocprint
;
255 struct ifacepsredirect_data
267 struct clrsurrogate_data
272 ULONG version_offset
;
287 ULONG version_offset
;
291 struct progidredirect_data
302 Sections are accessible by string or guid key, that defines two types of sections.
303 All sections of each type have same magic value and header structure, index
304 data could be of two possible types too. So every string based section uses
305 the same index format, same applies to guid sections - they share same guid index
308 - window class redirection section is a plain buffer with following format:
312 <data[]> --- <original name>
317 Header is fixed length structure - struct strsection_header,
318 contains redirected classes count;
320 Index is an array of fixed length index records, each record is
323 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
325 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
326 others are relative to section itself.
328 - dll redirect section format:
332 <data[]> --- <dll name>
335 This section doesn't seem to carry any payload data except dll names.
337 - typelib section format:
345 Header is fixed length, index is an array of fixed length 'struct guid_index'.
346 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
347 4-bytes aligned as a whole.
349 Module name offsets are relative to section, helpstring offset is relative to data
352 - comclass section format:
357 <data[]> --- <data> --- <data>
363 This section uses two index records per comclass, one entry contains original guid
364 as specified by context, another one has a generated guid. Index and strings handling
365 is similar to typelib sections.
367 For CLR classes additional data is stored after main COM class data, it contains
368 class name and runtime version string, see 'struct clrclass_data'.
370 Module name offsets are relative to section, progid offset is relative to data
373 - COM interface section format:
380 Interface section contains data for proxy/stubs and external proxy/stubs. External
381 ones are defined at assembly level, so this section has no module information.
382 All records are indexed with 'iid' value from manifest. There an exception for
383 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
384 redirect data, but index is still 'iid' from manifest.
386 Interface name offset is relative to data structure itself.
388 - CLR surrogates section format:
396 There's nothing special about this section, same way to store strings is used,
397 no modules part as it belongs to assembly level, not a file.
399 - ProgID section format:
404 <data[]> --- <progid>
407 This sections uses generated alias guids from COM server section. This way
408 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
409 is stored too, aligned.
416 unsigned int allocated
;
437 WCHAR
*name
; /* clrClass: class name */
438 WCHAR
*version
; /* clrClass: CLR runtime version */
441 DWORD miscstatuscontent
;
442 DWORD miscstatusthumbnail
;
443 DWORD miscstatusicon
;
444 DWORD miscstatusdocprint
;
445 struct progids progids
;
452 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
474 unsigned int allocated
;
481 struct entity_array entities
;
486 APPLICATION_MANIFEST
,
488 ASSEMBLY_SHARED_MANIFEST
,
493 enum assembly_type type
;
494 struct assembly_identity id
;
495 struct file_info manifest
;
498 struct dll_redirect
*dlls
;
499 unsigned int num_dlls
;
500 unsigned int allocated_dlls
;
501 struct entity_array entities
;
502 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
503 ULONG num_compat_contexts
;
504 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
508 enum context_sections
510 WINDOWCLASS_SECTION
= 1,
511 DLLREDIRECT_SECTION
= 2,
512 TLIBREDIRECT_SECTION
= 4,
513 SERVERREDIRECT_SECTION
= 8,
514 IFACEREDIRECT_SECTION
= 16,
515 CLRSURROGATES_SECTION
= 32,
516 PROGIDREDIRECT_SECTION
= 64
519 typedef struct _ACTIVATION_CONTEXT
523 struct file_info config
;
524 struct file_info appdir
;
525 struct assembly
*assemblies
;
526 unsigned int num_assemblies
;
527 unsigned int allocated_assemblies
;
530 struct strsection_header
*wndclass_section
;
531 struct strsection_header
*dllredirect_section
;
532 struct strsection_header
*progid_section
;
533 struct guidsection_header
*tlib_section
;
534 struct guidsection_header
*comserver_section
;
535 struct guidsection_header
*ifaceps_section
;
536 struct guidsection_header
*clrsurrogate_section
;
537 } ACTIVATION_CONTEXT
;
541 ACTIVATION_CONTEXT
*actctx
;
542 struct assembly_identity
*dependencies
;
543 unsigned int num_dependencies
;
544 unsigned int allocated_dependencies
;
547 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
548 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
549 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
550 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
551 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
552 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
553 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
554 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
555 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};
556 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};
557 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
558 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
559 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
560 static const WCHAR fileW
[] = {'f','i','l','e',0};
561 static const WCHAR hashW
[] = {'h','a','s','h',0};
562 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
563 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
564 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
565 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
567 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
568 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
569 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
570 static const WCHAR iidW
[] = {'i','i','d',0};
571 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
572 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
573 static const WCHAR nameW
[] = {'n','a','m','e',0};
574 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
575 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
576 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
577 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
578 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};
579 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
580 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
581 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
582 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
583 static const WCHAR typeW
[] = {'t','y','p','e',0};
584 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
585 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
586 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
587 static const WCHAR yesW
[] = {'y','e','s',0};
588 static const WCHAR noW
[] = {'n','o',0};
589 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
590 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
591 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
592 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
593 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
594 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
595 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
596 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
597 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
598 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
599 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
600 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
601 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
602 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
603 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
604 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
606 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
607 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
608 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
609 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
610 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
611 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
612 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
613 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};
614 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
615 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
616 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
617 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
618 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
619 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
620 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
621 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
622 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};
623 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
624 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
625 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
626 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};
627 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
629 static const WCHAR compatibilityW
[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
630 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};
631 static const WCHAR applicationW
[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
632 static const WCHAR supportedOSW
[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
633 static const WCHAR IdW
[] = {'I','d',0};
634 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};
635 static const WCHAR requestedPrivilegesW
[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
636 static const WCHAR securityW
[] = {'s','e','c','u','r','i','t','y',0};
637 static const WCHAR trustInfoW
[] = {'t','r','u','s','t','I','n','f','o',0};
645 static const struct olemisc_entry olemisc_values
[] =
647 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
648 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
649 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
650 { alignableW
, OLEMISC_ALIGNABLE
},
651 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
652 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
653 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
654 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
655 { imemodeW
, OLEMISC_IMEMODE
},
656 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
657 { insideoutW
, OLEMISC_INSIDEOUT
},
658 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
659 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
660 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
661 { onlyiconicW
, OLEMISC_ONLYICONIC
},
662 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
663 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
664 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
665 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
666 { staticW
, OLEMISC_STATIC
},
667 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
668 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
671 static const WCHAR xmlW
[] = {'?','x','m','l',0};
672 static const WCHAR manifestv1W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
673 static const WCHAR manifestv2W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
674 static const WCHAR manifestv3W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
676 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
677 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
678 static const WCHAR wildcardW
[] = {'*',0};
680 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
681 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
683 static WCHAR
*strdupW(const WCHAR
* str
)
687 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
689 return strcpyW(ptr
, str
);
692 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
696 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
698 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
704 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
706 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
709 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
711 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
714 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
716 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
717 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
720 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
722 UINT len
= strlenW( namespace );
724 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
725 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
726 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
729 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
731 if (elem
->len
&& elem
->ptr
[0] == '/')
734 elem_end
.ptr
= elem
->ptr
+ 1;
735 elem_end
.len
= elem
->len
- 1;
736 return xml_elem_cmp( &elem_end
, str
, namespace );
741 static inline BOOL
isxmlspace( WCHAR ch
)
743 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
746 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
748 return debugstr_wn(str
->ptr
, str
->len
);
751 static inline const char* debugstr_version(const struct assembly_version
*ver
)
753 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
756 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
758 struct assembly
*assembly
;
760 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
763 unsigned int new_count
;
764 if (actctx
->assemblies
)
766 new_count
= actctx
->allocated_assemblies
* 2;
767 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
768 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
773 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
775 if (!ptr
) return NULL
;
776 actctx
->assemblies
= ptr
;
777 actctx
->allocated_assemblies
= new_count
;
780 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
785 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
787 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
790 unsigned int new_count
;
793 new_count
= assembly
->allocated_dlls
* 2;
794 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
795 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
800 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
802 if (!ptr
) return NULL
;
803 assembly
->dlls
= ptr
;
804 assembly
->allocated_dlls
= new_count
;
806 return &assembly
->dlls
[assembly
->num_dlls
++];
809 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
812 if (assembly
->num_compat_contexts
)
814 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
815 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
816 assembly
->compat_contexts
,
817 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
821 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
823 if (!ptr
) return NULL
;
824 assembly
->compat_contexts
= ptr
;
825 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
828 static void free_assembly_identity(struct assembly_identity
*ai
)
830 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
831 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
832 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
833 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
834 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
837 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
839 struct entity
* entity
;
841 if (array
->num
== array
->allocated
)
844 unsigned int new_count
;
847 new_count
= array
->allocated
* 2;
848 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
849 array
->base
, new_count
* sizeof(*array
->base
) );
854 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
856 if (!ptr
) return NULL
;
858 array
->allocated
= new_count
;
860 entity
= &array
->base
[array
->num
++];
865 static void free_entity_array(struct entity_array
*array
)
868 for (i
= 0; i
< array
->num
; i
++)
870 struct entity
*entity
= &array
->base
[i
];
871 switch (entity
->kind
)
873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
874 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
875 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
876 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
877 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
878 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
879 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
880 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
881 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
883 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
884 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
885 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
886 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
887 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
888 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
891 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
892 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
894 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
895 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
897 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
898 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
899 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
900 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
903 FIXME("Unknown entity kind %d\n", entity
->kind
);
906 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
909 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
911 if (!str1
) return !str2
;
912 return str2
&& !strcmpiW( str1
, str2
);
915 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
916 const struct assembly_identity
*id2
)
918 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
919 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
920 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
922 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
924 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
927 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
928 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
929 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
930 if (id1
->version
.build
== id2
->version
.build
&&
931 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
935 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
936 struct assembly_identity
* ai
)
940 /* check if we already have that assembly */
942 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
943 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
945 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
946 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
947 ai
->version
.build
, ai
->version
.revision
);
951 for (i
= 0; i
< acl
->num_dependencies
; i
++)
952 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
954 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
955 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
956 ai
->version
.build
, ai
->version
.revision
);
960 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
963 unsigned int new_count
;
964 if (acl
->dependencies
)
966 new_count
= acl
->allocated_dependencies
* 2;
967 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
968 new_count
* sizeof(acl
->dependencies
[0]));
973 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
975 if (!ptr
) return FALSE
;
976 acl
->dependencies
= ptr
;
977 acl
->allocated_dependencies
= new_count
;
979 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
984 static void free_depend_manifests(struct actctx_loader
* acl
)
987 for (i
= 0; i
< acl
->num_dependencies
; i
++)
988 free_assembly_identity(&acl
->dependencies
[i
]);
989 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
992 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
994 static const WCHAR undW
[] = {'_',0};
995 static const WCHAR noneW
[] = {'n','o','n','e',0};
996 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
998 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
999 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1000 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1001 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1002 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
1003 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1006 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
1008 strcpyW( ret
, arch
);
1009 strcatW( ret
, undW
);
1010 strcatW( ret
, name
);
1011 strcatW( ret
, undW
);
1012 strcatW( ret
, key
);
1013 strcatW( ret
, undW
);
1014 sprintfW( ret
+ strlenW(ret
), version_formatW
,
1015 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1016 strcatW( ret
, undW
);
1017 strcatW( ret
, lang
);
1018 strcatW( ret
, undW
);
1019 strcatW( ret
, mskeyW
);
1023 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1028 strcatW( buffer
, prefix
);
1037 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1039 static const WCHAR archW
[] =
1040 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1041 static const WCHAR public_keyW
[] =
1042 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1043 static const WCHAR typeW
[] =
1044 {',','t','y','p','e','=',0};
1045 static const WCHAR versionW
[] =
1046 {',','v','e','r','s','i','o','n','=',0};
1048 WCHAR version
[64], *ret
;
1051 sprintfW( version
, version_formatW
,
1052 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1053 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1054 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1055 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1056 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
1057 size
+= strlenW(versionW
) + strlenW(version
) + 2;
1059 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1062 if (ai
->name
) strcpyW( ret
, ai
->name
);
1064 append_string( ret
, archW
, ai
->arch
);
1065 append_string( ret
, public_keyW
, ai
->public_key
);
1066 append_string( ret
, typeW
, ai
->type
);
1067 append_string( ret
, versionW
, version
);
1071 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1073 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1075 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1078 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1087 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1089 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1092 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1094 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1098 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1100 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1101 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1103 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1104 free_entity_array( &dll
->entities
);
1105 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1106 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1108 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1109 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1110 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1111 RtlFreeHeap( GetProcessHeap(), 0, assembly
->compat_contexts
);
1112 free_entity_array( &assembly
->entities
);
1113 free_assembly_identity(&assembly
->id
);
1115 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1116 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1117 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1118 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1119 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1120 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1121 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1130 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1131 BOOL
* error
, BOOL
* end
)
1137 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1140 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1142 if (*xmlbuf
->ptr
== '/')
1145 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1154 if (*xmlbuf
->ptr
== '>')
1162 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1164 if (ptr
== xmlbuf
->end
) return FALSE
;
1166 name
->ptr
= xmlbuf
->ptr
;
1167 name
->len
= ptr
-xmlbuf
->ptr
;
1170 /* skip spaces before '=' */
1171 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1172 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1174 /* skip '=' itself */
1176 if (ptr
== xmlbuf
->end
) return FALSE
;
1178 /* skip spaces after '=' */
1179 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1181 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1184 if (ptr
== xmlbuf
->end
) return FALSE
;
1186 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1189 xmlbuf
->ptr
= xmlbuf
->end
;
1193 value
->len
= ptr
- value
->ptr
;
1194 xmlbuf
->ptr
= ptr
+ 1;
1196 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1202 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1208 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1211 xmlbuf
->ptr
= xmlbuf
->end
;
1215 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1217 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1218 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1220 if (ptr
+ 3 > xmlbuf
->end
)
1222 xmlbuf
->ptr
= xmlbuf
->end
;
1225 xmlbuf
->ptr
= ptr
+ 3;
1231 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1234 elem
->ptr
= xmlbuf
->ptr
;
1235 elem
->len
= ptr
- xmlbuf
->ptr
;
1237 return xmlbuf
->ptr
!= xmlbuf
->end
;
1240 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1242 /* FIXME: parse attributes */
1245 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1247 if (ptr
[0] == '?' && ptr
[1] == '>')
1249 xmlbuf
->ptr
= ptr
+ 2;
1256 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1258 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1260 if (!ptr
) return FALSE
;
1262 content
->ptr
= xmlbuf
->ptr
;
1263 content
->len
= ptr
- xmlbuf
->ptr
;
1269 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1271 unsigned int ver
[4];
1275 /* major.minor.build.revision */
1276 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1277 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1279 if (*curr
>= '0' && *curr
<= '9')
1281 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1282 if (ver
[pos
] >= 0x10000) goto error
;
1284 else if (*curr
== '.')
1286 if (++pos
>= 4) goto error
;
1290 version
->major
= ver
[0];
1291 version
->minor
= ver
[1];
1292 version
->build
= ver
[2];
1293 version
->revision
= ver
[3];
1297 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1301 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1304 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1305 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1306 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1310 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1312 xmlstr_t attr_name
, attr_value
;
1315 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1317 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1318 debugstr_xmlstr(&attr_value
));
1323 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1326 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1329 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1332 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1333 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1335 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1338 return parse_end_element(xmlbuf
);
1341 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1343 xmlstr_t attr_name
, attr_value
, elem
;
1344 BOOL end
= FALSE
, error
, ret
= TRUE
;
1346 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1347 if(error
|| end
) return end
;
1349 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1351 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1352 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1355 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1358 return ret
&& parse_end_element(xmlbuf
);
1361 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1362 struct assembly_identity
* ai
)
1364 xmlstr_t attr_name
, attr_value
;
1365 BOOL end
= FALSE
, error
;
1367 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1369 if (xmlstr_cmp(&attr_name
, nameW
))
1371 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1373 else if (xmlstr_cmp(&attr_name
, typeW
))
1375 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1377 else if (xmlstr_cmp(&attr_name
, versionW
))
1379 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1381 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1383 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1385 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1387 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1389 else if (xmlstr_cmp(&attr_name
, languageW
))
1391 WARN("Unsupported yet language attribute (%s)\n",
1392 debugstr_xmlstr(&attr_value
));
1393 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1397 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1398 debugstr_xmlstr(&attr_value
));
1402 TRACE( "name=%s version=%s arch=%s\n",
1403 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1405 if (error
|| end
) return end
;
1406 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1409 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1411 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1412 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1413 static const WCHAR freeW
[] = {'F','r','e','e',0};
1414 static const WCHAR bothW
[] = {'B','o','t','h',0};
1416 if (value
->len
== 0) return ThreadingModel_No
;
1417 if (xmlstr_cmp(value
, apartW
))
1418 return ThreadingModel_Apartment
;
1419 else if (xmlstr_cmp(value
, freeW
))
1420 return ThreadingModel_Free
;
1421 else if (xmlstr_cmp(value
, bothW
))
1422 return ThreadingModel_Both
;
1423 else if (xmlstr_cmp(value
, neutralW
))
1424 return ThreadingModel_Neutral
;
1426 return ThreadingModel_No
;
1429 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1434 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1442 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1443 if (!c
&& !olemisc_values
[n
].name
[len
])
1444 return olemisc_values
[n
].value
;
1452 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1456 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1458 const WCHAR
*str
= value
->ptr
, *start
;
1462 /* it's comma separated list of flags */
1463 while (i
< value
->len
)
1466 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1468 flags
|= get_olemisc_value(start
, str
-start
);
1470 /* skip separator */
1478 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1480 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1482 if (progids
->allocated
== 0)
1484 progids
->allocated
= 4;
1485 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1488 if (progids
->allocated
== progids
->num
)
1490 WCHAR
**new_progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
,
1491 2 * progids
->allocated
* sizeof(WCHAR
*));
1492 if (!new_progids
) return FALSE
;
1493 progids
->allocated
*= 2;
1494 progids
->progids
= new_progids
;
1497 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1503 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1508 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1511 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1512 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1515 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1517 xmlstr_t elem
, attr_name
, attr_value
;
1518 BOOL ret
= TRUE
, end
= FALSE
, error
;
1519 struct entity
* entity
;
1521 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1524 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1526 if (xmlstr_cmp(&attr_name
, clsidW
))
1528 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1530 else if (xmlstr_cmp(&attr_name
, progidW
))
1532 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1534 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1536 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1538 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1540 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1542 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1544 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1546 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1548 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1550 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1552 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1554 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1556 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1558 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1560 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1562 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1568 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1572 if (error
) return FALSE
;
1574 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1575 if (entity
->u
.comclass
.progid
)
1576 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1578 if (end
) return TRUE
;
1580 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1582 if (xmlstr_cmp_end(&elem
, comClassW
))
1584 ret
= parse_end_element(xmlbuf
);
1587 else if (xmlstr_cmp(&elem
, progidW
))
1589 ret
= parse_com_class_progid(xmlbuf
, entity
);
1593 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1594 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1598 if (entity
->u
.comclass
.progids
.num
)
1599 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1604 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1609 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1611 if (*curr
>= '0' && *curr
<= '9')
1612 num
= num
* 10 + *curr
- '0';
1615 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1619 entity
->u
.ifaceps
.nummethods
= num
;
1624 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1626 xmlstr_t attr_name
, attr_value
;
1627 BOOL end
= FALSE
, error
;
1628 struct entity
* entity
;
1630 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1633 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1635 if (xmlstr_cmp(&attr_name
, iidW
))
1637 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1639 else if (xmlstr_cmp(&attr_name
, nameW
))
1641 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1643 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1645 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1646 entity
->u
.ifaceps
.mask
|= BaseIface
;
1648 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1650 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1651 entity
->u
.ifaceps
.mask
|= NumMethods
;
1653 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1655 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1658 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1663 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1667 if (error
) return FALSE
;
1668 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1669 if (end
) return TRUE
;
1671 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1674 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1676 WORD
*flags
= &entity
->u
.typelib
.flags
;
1677 const WCHAR
*str
= value
->ptr
, *start
;
1682 /* it's comma separated list of flags */
1683 while (i
< value
->len
)
1686 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1688 if (!strncmpiW(start
, restrictedW
, str
-start
))
1689 *flags
|= LIBFLAG_FRESTRICTED
;
1690 else if (!strncmpiW(start
, controlW
, str
-start
))
1691 *flags
|= LIBFLAG_FCONTROL
;
1692 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1693 *flags
|= LIBFLAG_FHIDDEN
;
1694 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1695 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1698 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1702 /* skip separator */
1710 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1712 unsigned int ver
[2];
1717 ver
[0] = ver
[1] = pos
= 0;
1718 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1720 if (*curr
>= '0' && *curr
<= '9')
1722 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1723 if (ver
[pos
] >= 0x10000) goto error
;
1725 else if (*curr
== '.')
1727 if (++pos
>= 2) goto error
;
1731 entity
->u
.typelib
.major
= ver
[0];
1732 entity
->u
.typelib
.minor
= ver
[1];
1736 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1740 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1742 xmlstr_t attr_name
, attr_value
;
1743 BOOL end
= FALSE
, error
;
1744 struct entity
* entity
;
1746 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1749 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1751 if (xmlstr_cmp(&attr_name
, tlbidW
))
1753 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1755 else if (xmlstr_cmp(&attr_name
, versionW
))
1757 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1759 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1761 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1763 else if (xmlstr_cmp(&attr_name
, flagsW
))
1765 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1769 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1773 if (error
) return FALSE
;
1775 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1777 if (end
) return TRUE
;
1779 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1782 static inline int aligned_string_len(int len
)
1784 return (len
+ 3) & ~3;
1787 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1789 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1790 struct assembly_version
*ver
= &assembly
->id
.version
;
1793 if (!ret
) ret
= buff
;
1794 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1797 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1799 xmlstr_t elem
, content
, attr_name
, attr_value
;
1800 BOOL end
= FALSE
, ret
= TRUE
, error
;
1801 struct entity
* entity
;
1803 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1806 entity
->u
.class.versioned
= TRUE
;
1807 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1809 if (xmlstr_cmp(&attr_name
, versionedW
))
1811 if (xmlstr_cmpi(&attr_value
, noW
))
1812 entity
->u
.class.versioned
= FALSE
;
1813 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1818 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1822 if (error
|| end
) return end
;
1824 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1826 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1828 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1830 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1832 if (xmlstr_cmp_end(&elem
, windowClassW
))
1834 ret
= parse_end_element(xmlbuf
);
1839 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1840 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1847 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1849 xmlstr_t attr_name
, attr_value
;
1850 BOOL end
= FALSE
, error
;
1852 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1854 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1856 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value
));
1858 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1860 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value
));
1864 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1868 if (error
|| end
) return end
;
1869 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1872 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1874 xmlstr_t elem
, content
, attr_name
, attr_value
;
1875 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1877 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1878 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1880 if (error
) return FALSE
;
1881 if (end
) return TRUE
;
1883 if (!parse_text_content(xmlbuf
, &content
))
1886 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1888 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1890 if (xmlstr_cmp_end(&elem
, descriptionW
))
1892 ret
= parse_end_element(xmlbuf
);
1897 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1898 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1905 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1906 struct assembly
* assembly
,
1907 struct actctx_loader
* acl
)
1909 xmlstr_t attr_name
, attr_value
;
1910 BOOL end
= FALSE
, error
;
1911 struct entity
* entity
;
1913 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1914 if (!entity
) return FALSE
;
1916 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1918 if (xmlstr_cmp(&attr_name
, iidW
))
1920 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1922 else if (xmlstr_cmp(&attr_name
, nameW
))
1924 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1926 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1928 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1929 entity
->u
.ifaceps
.mask
|= BaseIface
;
1931 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1933 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1934 entity
->u
.ifaceps
.mask
|= NumMethods
;
1936 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1938 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1940 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1942 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1946 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1950 if (error
) return FALSE
;
1951 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1952 if (end
) return TRUE
;
1954 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
1957 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1959 xmlstr_t attr_name
, attr_value
, elem
;
1960 BOOL end
= FALSE
, error
, ret
= TRUE
;
1961 struct entity
* entity
;
1963 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
1964 if (!entity
) return FALSE
;
1966 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1968 if (xmlstr_cmp(&attr_name
, nameW
))
1970 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1972 else if (xmlstr_cmp(&attr_name
, clsidW
))
1974 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1976 else if (xmlstr_cmp(&attr_name
, progidW
))
1978 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1980 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1982 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1984 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1986 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1988 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
1990 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
1994 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1998 if (error
) return FALSE
;
1999 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2000 if (entity
->u
.comclass
.progid
)
2001 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2002 if (end
) return TRUE
;
2004 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2006 if (xmlstr_cmp_end(&elem
, clrClassW
))
2008 ret
= parse_end_element(xmlbuf
);
2011 else if (xmlstr_cmp(&elem
, progidW
))
2013 ret
= parse_com_class_progid(xmlbuf
, entity
);
2017 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2018 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2022 if (entity
->u
.comclass
.progids
.num
)
2023 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2028 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2030 xmlstr_t attr_name
, attr_value
;
2031 BOOL end
= FALSE
, error
;
2032 struct entity
* entity
;
2034 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
2035 if (!entity
) return FALSE
;
2037 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2039 if (xmlstr_cmp(&attr_name
, nameW
))
2041 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2043 else if (xmlstr_cmp(&attr_name
, clsidW
))
2045 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2047 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2049 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2053 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2057 if (error
) return FALSE
;
2058 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2059 if (end
) return TRUE
;
2061 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2064 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2066 struct assembly_identity ai
;
2067 xmlstr_t elem
, attr_name
, attr_value
;
2068 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2070 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2072 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2073 static const WCHAR trueW
[] = {'t','r','u','e',0};
2075 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2076 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2078 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2081 if (error
|| end
) return end
;
2083 memset(&ai
, 0, sizeof(ai
));
2084 ai
.optional
= optional
;
2085 ai
.delayed
= delayed
;
2087 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2088 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2091 TRACE( "adding name=%s version=%s arch=%s\n",
2092 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2094 /* store the newly found identity for later loading */
2095 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2097 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2099 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2101 ret
= parse_end_element(xmlbuf
);
2104 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2106 ret
= parse_binding_redirect_elem(xmlbuf
);
2110 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2111 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2118 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2120 xmlstr_t attr_name
, attr_value
, elem
;
2121 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2123 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2125 if (xmlstr_cmp(&attr_name
, optionalW
))
2127 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2128 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value
));
2132 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2136 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2138 if (xmlstr_cmp_end(&elem
, dependencyW
))
2140 ret
= parse_end_element(xmlbuf
);
2143 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2145 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2149 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2150 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2157 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2161 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2162 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2165 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2169 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2170 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2173 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2175 xmlstr_t attr_name
, attr_value
, elem
;
2176 BOOL end
= FALSE
, error
, ret
= TRUE
;
2177 struct dll_redirect
* dll
;
2179 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2181 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2183 if (xmlstr_cmp(&attr_name
, nameW
))
2185 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2186 TRACE("name=%s\n", debugstr_xmlstr(&attr_value
));
2188 else if (xmlstr_cmp(&attr_name
, hashW
))
2190 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2192 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2194 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2195 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2196 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value
));
2200 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2204 if (error
|| !dll
->name
) return FALSE
;
2206 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2208 if (end
) return TRUE
;
2210 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2212 if (xmlstr_cmp_end(&elem
, fileW
))
2214 ret
= parse_end_element(xmlbuf
);
2217 else if (xmlstr_cmp(&elem
, comClassW
))
2219 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2221 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2223 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2225 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2227 WARN("asmv2:hash (undocumented) not supported\n");
2228 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2230 else if (xmlstr_cmp(&elem
, typelibW
))
2232 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2234 else if (xmlstr_cmp(&elem
, windowClassW
))
2236 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2240 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2241 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2248 static BOOL
parse_compatibility_application_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2249 struct actctx_loader
* acl
)
2251 xmlstr_t attr_name
, attr_value
, elem
;
2252 BOOL end
= FALSE
, ret
= TRUE
, error
;
2254 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2256 if (xmlstr_cmp_end(&elem
, applicationW
))
2258 ret
= parse_end_element(xmlbuf
);
2261 else if (xmlstr_cmp(&elem
, supportedOSW
))
2263 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2265 if (xmlstr_cmp(&attr_name
, IdW
))
2268 COMPATIBILITY_CONTEXT_ELEMENT
* compat
;
2270 str
.Buffer
= (PWSTR
)attr_value
.ptr
;
2271 str
.Length
= str
.MaximumLength
= (USHORT
)attr_value
.len
* sizeof(WCHAR
);
2272 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2274 if (!(compat
= add_compat_context(assembly
))) return FALSE
;
2275 compat
->Type
= ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2276 compat
->Id
= compat_id
;
2280 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value
));
2285 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
2286 debugstr_xmlstr(&attr_value
));
2292 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2293 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2300 static BOOL
parse_compatibility_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2301 struct actctx_loader
* acl
)
2306 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2308 if (xmlstr_cmp_end(&elem
, compatibilityW
))
2310 ret
= parse_end_element(xmlbuf
);
2313 else if (xmlstr_cmp(&elem
, applicationW
))
2315 ret
= parse_compatibility_application_elem(xmlbuf
, assembly
, acl
);
2319 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2320 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2326 static BOOL
parse_requested_execution_level_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2328 static const WCHAR levelW
[] = {'l','e','v','e','l',0};
2329 static const WCHAR asInvokerW
[] = {'a','s','I','n','v','o','k','e','r',0};
2330 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};
2331 static const WCHAR highestAvailableW
[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2332 static const WCHAR uiAccessW
[] = {'u','i','A','c','c','e','s','s',0};
2333 static const WCHAR falseW
[] = {'f','a','l','s','e',0};
2334 static const WCHAR trueW
[] = {'t','r','u','e',0};
2336 xmlstr_t attr_name
, attr_value
, elem
;
2337 BOOL end
= FALSE
, ret
= TRUE
, error
;
2339 /* Multiple requestedExecutionLevel elements are not supported. */
2340 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
)
2343 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2345 if (xmlstr_cmp(&attr_name
, levelW
))
2347 if (xmlstr_cmpi(&attr_value
, asInvokerW
))
2348 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2349 else if (xmlstr_cmpi(&attr_value
, highestAvailableW
))
2350 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2351 else if (xmlstr_cmpi(&attr_value
, requireAdministratorW
))
2352 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2354 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr_value
));
2356 else if (xmlstr_cmp(&attr_name
, uiAccessW
))
2358 if (xmlstr_cmpi(&attr_value
, falseW
))
2359 assembly
->ui_access
= FALSE
;
2360 else if (xmlstr_cmpi(&attr_value
, trueW
))
2361 assembly
->ui_access
= TRUE
;
2363 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr_value
));
2366 FIXME("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2369 if (error
) return FALSE
;
2370 if (end
) return TRUE
;
2372 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2374 if (xmlstr_cmp_end(&elem
, requestedExecutionLevelW
))
2376 ret
= parse_end_element(xmlbuf
);
2381 FIXME("unknown element %s\n", debugstr_xmlstr(&elem
));
2382 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2389 static BOOL
parse_requested_privileges_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2394 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2396 if (xmlstr_cmp_end(&elem
, requestedPrivilegesW
))
2398 ret
= parse_end_element(xmlbuf
);
2401 else if (xmlstr_cmp(&elem
, requestedExecutionLevelW
))
2402 ret
= parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
);
2405 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2406 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2413 static BOOL
parse_security_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2418 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2420 if (xmlstr_cmp_end(&elem
, securityW
))
2422 ret
= parse_end_element(xmlbuf
);
2425 else if (xmlstr_cmp(&elem
, requestedPrivilegesW
))
2426 ret
= parse_requested_privileges_elem(xmlbuf
, assembly
, acl
);
2429 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2430 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2437 static BOOL
parse_trust_info_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2442 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2444 if (xmlstr_cmp_end(&elem
, trustInfoW
))
2446 ret
= parse_end_element(xmlbuf
);
2449 else if (xmlstr_cmp(&elem
, securityW
))
2450 ret
= parse_security_elem(xmlbuf
, assembly
, acl
);
2453 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2454 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2461 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2462 struct assembly
* assembly
,
2463 struct assembly_identity
* expected_ai
)
2465 xmlstr_t attr_name
, attr_value
, elem
;
2466 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2468 TRACE("(%p)\n", xmlbuf
);
2470 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2472 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2474 static const WCHAR v10W
[] = {'1','.','0',0};
2475 if (!xmlstr_cmp(&attr_value
, v10W
))
2477 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
2482 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2484 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2485 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2486 !xmlstr_cmp(&attr_value
, manifestv3W
))
2488 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
2495 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2499 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2500 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2502 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2504 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2506 assembly
->no_inherit
= TRUE
;
2509 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2511 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2514 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2515 assembly
->no_inherit
)
2520 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2522 ret
= parse_end_element(xmlbuf
);
2525 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2527 ret
= parse_description_elem(xmlbuf
);
2529 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2531 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2533 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2535 ret
= parse_dependency_elem(xmlbuf
, acl
);
2537 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2539 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2541 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2543 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2545 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2547 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2549 else if (xml_elem_cmp(&elem
, trustInfoW
, asmv2W
) ||
2550 xml_elem_cmp(&elem
, trustInfoW
, asmv1W
))
2552 ret
= parse_trust_info_elem(xmlbuf
, assembly
, acl
);
2554 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2556 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2560 /* FIXME: more tests */
2561 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2562 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2564 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2565 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2566 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2567 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2568 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2571 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2572 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2573 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2574 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2575 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2576 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2578 FIXME("wrong version for shared assembly manifest\n");
2583 else if (xml_elem_cmp(&elem
, compatibilityW
, compatibilityNSW
))
2585 ret
= parse_compatibility_elem(xmlbuf
, assembly
, acl
);
2589 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2590 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2592 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2598 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2599 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2603 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2605 if (xmlstr_cmp(&elem
, xmlW
) &&
2606 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2607 return STATUS_SXS_CANT_GEN_ACTCTX
;
2609 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2611 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
2612 return STATUS_SXS_CANT_GEN_ACTCTX
;
2615 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2617 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2618 return STATUS_SXS_CANT_GEN_ACTCTX
;
2621 if (next_xml_elem(xmlbuf
, &elem
))
2623 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2624 return STATUS_SXS_CANT_GEN_ACTCTX
;
2627 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2629 FIXME("parse error\n");
2630 return STATUS_SXS_CANT_GEN_ACTCTX
;
2632 return STATUS_SUCCESS
;
2635 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2636 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2637 const void *buffer
, SIZE_T size
)
2641 struct assembly
*assembly
;
2644 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2646 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2647 return STATUS_SXS_CANT_GEN_ACTCTX
;
2649 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2650 return STATUS_NO_MEMORY
;
2652 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2653 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2654 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2656 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2657 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2659 xmlbuf
.ptr
= buffer
;
2660 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2661 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2663 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2665 const WCHAR
*buf
= buffer
;
2669 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2670 return STATUS_NO_MEMORY
;
2671 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2672 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2673 xmlbuf
.ptr
= new_buff
;
2674 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2675 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2676 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2680 /* let's assume utf-8 for now */
2681 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2686 FIXME( "utf-8 conversion failed\n" );
2687 return STATUS_SXS_CANT_GEN_ACTCTX
;
2689 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2690 return STATUS_NO_MEMORY
;
2691 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2692 xmlbuf
.ptr
= new_buff
;
2693 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2694 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2695 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2700 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2702 OBJECT_ATTRIBUTES attr
;
2705 attr
.Length
= sizeof(attr
);
2706 attr
.RootDirectory
= 0;
2707 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2708 attr
.ObjectName
= name
;
2709 attr
.SecurityDescriptor
= NULL
;
2710 attr
.SecurityQualityOfService
= NULL
;
2711 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2714 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2720 LdrLockLoaderLock(0, NULL
, &magic
);
2721 status
= LdrFindEntryForAddress( module
, &pldr
);
2722 if (status
== STATUS_SUCCESS
)
2724 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2725 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2727 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2728 str
->Length
= pldr
->FullDllName
.Length
;
2729 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2731 else status
= STATUS_NO_MEMORY
;
2733 LdrUnlockLoaderLock(0, magic
);
2737 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2738 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2739 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2742 UNICODE_STRING nameW
;
2743 LDR_RESOURCE_INFO info
;
2744 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2747 if (TRACE_ON(actctx
))
2749 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2751 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2752 hModule
, debugstr_w(nameW
.Buffer
) );
2753 RtlFreeUnicodeString( &nameW
);
2755 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2756 hModule
, debugstr_w(filename
) );
2759 if (!resname
) return STATUS_INVALID_PARAMETER
;
2761 info
.Type
= RT_MANIFEST
;
2762 info
.Language
= lang
;
2763 if (!((ULONG_PTR
)resname
>> 16))
2765 info
.Name
= (ULONG_PTR
)resname
;
2766 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2768 else if (resname
[0] == '#')
2771 RtlInitUnicodeString(&nameW
, resname
+ 1);
2772 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2773 return STATUS_INVALID_PARAMETER
;
2775 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2779 RtlCreateUnicodeString(&nameW
, resname
);
2780 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2781 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2782 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2783 RtlFreeUnicodeString(&nameW
);
2785 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2787 if (status
== STATUS_SUCCESS
)
2788 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2793 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2794 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2795 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2798 OBJECT_ATTRIBUTES attr
;
2800 LARGE_INTEGER offset
;
2805 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2807 attr
.Length
= sizeof(attr
);
2808 attr
.RootDirectory
= 0;
2809 attr
.ObjectName
= NULL
;
2810 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2811 attr
.SecurityDescriptor
= NULL
;
2812 attr
.SecurityQualityOfService
= NULL
;
2815 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2816 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2817 if (status
!= STATUS_SUCCESS
) return status
;
2819 offset
.QuadPart
= 0;
2822 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2823 &count
, ViewShare
, 0, PAGE_READONLY
);
2825 if (status
!= STATUS_SUCCESS
) return status
;
2827 if (RtlImageNtHeader(base
)) /* we got a PE file */
2829 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2830 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2832 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2834 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2838 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2839 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2841 FILE_END_OF_FILE_INFORMATION info
;
2844 OBJECT_ATTRIBUTES attr
;
2846 LARGE_INTEGER offset
;
2851 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2853 attr
.Length
= sizeof(attr
);
2854 attr
.RootDirectory
= 0;
2855 attr
.ObjectName
= NULL
;
2856 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2857 attr
.SecurityDescriptor
= NULL
;
2858 attr
.SecurityQualityOfService
= NULL
;
2861 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2862 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2863 if (status
!= STATUS_SUCCESS
) return status
;
2865 offset
.QuadPart
= 0;
2868 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2869 &count
, ViewShare
, 0, PAGE_READONLY
);
2871 if (status
!= STATUS_SUCCESS
) return status
;
2873 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2874 if (status
== STATUS_SUCCESS
)
2875 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2877 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2881 /* try to load the .manifest file associated to the file */
2882 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2883 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2885 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2888 UNICODE_STRING nameW
;
2890 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2892 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2894 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2896 if (module
) /* use the module filename */
2898 UNICODE_STRING name
;
2900 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2902 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2903 strcatW( name
.Buffer
, dotManifestW
);
2904 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2905 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2906 RtlFreeUnicodeString( &name
);
2908 if (status
) return status
;
2912 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2913 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2914 return STATUS_NO_MEMORY
;
2915 strcpyW( buffer
, filename
);
2916 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2917 strcatW( buffer
, dotManifestW
);
2918 RtlInitUnicodeString( &nameW
, buffer
);
2921 if (!open_nt_file( &file
, &nameW
))
2923 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2926 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2927 RtlFreeUnicodeString( &nameW
);
2931 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2933 static const WCHAR lookup_fmtW
[] =
2934 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2935 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2936 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2938 WCHAR
*lookup
, *ret
= NULL
;
2939 UNICODE_STRING lookup_us
;
2941 const WCHAR
*lang
= ai
->language
;
2942 unsigned int data_pos
= 0, data_len
;
2945 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2946 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2947 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2948 + sizeof(lookup_fmtW
) )))
2951 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2952 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2953 ai
->version
.major
, ai
->version
.minor
, lang
);
2954 RtlInitUnicodeString( &lookup_us
, lookup
);
2956 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2957 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
2959 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2960 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2962 ULONG build
, revision
;
2964 data_len
= io
.Information
;
2968 if (data_pos
>= data_len
)
2970 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2971 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
2973 data_len
= io
.Information
;
2976 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2978 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2979 else data_pos
= data_len
;
2981 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2983 if (build
< min_build
) continue;
2984 tmp
= strchrW(tmp
, '.') + 1;
2985 revision
= atoiW(tmp
);
2986 if (build
== min_build
&& revision
< min_revision
) continue;
2987 tmp
= strchrW(tmp
, '_') + 1;
2988 tmp
= strchrW(tmp
, '_') + 1;
2989 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2990 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2992 /* prefer a non-Wine manifest if we already have one */
2993 /* we'll still load the builtin dll if specified through DllOverrides */
2999 min_revision
= revision
;
3001 ai
->version
.build
= build
;
3002 ai
->version
.revision
= revision
;
3003 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3004 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3006 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3007 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3011 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3012 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3016 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3018 struct assembly_identity sxs_ai
;
3019 UNICODE_STRING path_us
;
3020 OBJECT_ATTRIBUTES attr
;
3022 WCHAR
*path
, *file
= NULL
;
3025 static const WCHAR manifest_dirW
[] =
3026 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3028 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3030 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
3031 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
3032 return STATUS_NO_MEMORY
;
3034 strcpyW( path
, user_shared_data
->NtSystemRoot
);
3035 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
3037 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3039 RtlFreeHeap( GetProcessHeap(), 0, path
);
3040 return STATUS_NO_SUCH_FILE
;
3042 RtlFreeHeap( GetProcessHeap(), 0, path
);
3044 attr
.Length
= sizeof(attr
);
3045 attr
.RootDirectory
= 0;
3046 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3047 attr
.ObjectName
= &path_us
;
3048 attr
.SecurityDescriptor
= NULL
;
3049 attr
.SecurityQualityOfService
= NULL
;
3051 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3052 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3055 file
= lookup_manifest_file( handle
, &sxs_ai
);
3060 RtlFreeUnicodeString( &path_us
);
3061 return STATUS_NO_SUCH_FILE
;
3064 /* append file name to directory path */
3065 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3066 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
3068 RtlFreeHeap( GetProcessHeap(), 0, file
);
3069 RtlFreeUnicodeString( &path_us
);
3070 return STATUS_NO_MEMORY
;
3073 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3074 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3075 RtlInitUnicodeString( &path_us
, path
);
3076 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
3078 if (!open_nt_file( &handle
, &path_us
))
3080 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3083 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3085 RtlFreeHeap( GetProcessHeap(), 0, file
);
3086 RtlFreeUnicodeString( &path_us
);
3090 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3091 struct assembly_identity
* ai
)
3093 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3095 WCHAR
*buffer
, *p
, *directory
;
3097 UNICODE_STRING nameW
;
3101 TRACE( "looking for name=%s version=%s arch=%s\n",
3102 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3104 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3106 /* FIXME: add support for language specific lookup */
3108 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3109 strlenW(acl
->actctx
->appdir
.info
));
3111 nameW
.Buffer
= NULL
;
3112 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3113 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3114 return STATUS_NO_MEMORY
;
3116 if (!(directory
= build_assembly_dir( ai
)))
3118 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3119 return STATUS_NO_MEMORY
;
3122 /* Lookup in <dir>\name.dll
3123 * <dir>\name.manifest
3124 * <dir>\name\name.dll
3125 * <dir>\name\name.manifest
3127 * First 'appdir' is used as <dir>, if that failed
3128 * it tries application manifest file path.
3130 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3131 p
= buffer
+ strlenW(buffer
);
3132 for (i
= 0; i
< 4; i
++)
3136 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3137 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3141 strcpyW( p
, ai
->name
);
3144 strcpyW( p
, dotDllW
);
3145 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3147 status
= open_nt_file( &file
, &nameW
);
3150 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3151 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3155 RtlFreeUnicodeString( &nameW
);
3158 strcpyW( p
, dotManifestW
);
3159 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3161 status
= open_nt_file( &file
, &nameW
);
3164 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3168 RtlFreeUnicodeString( &nameW
);
3170 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3172 RtlFreeUnicodeString( &nameW
);
3173 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3174 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3178 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3180 NTSTATUS status
= STATUS_SUCCESS
;
3183 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3185 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3187 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3189 FIXME( "Could not find dependent assembly %s (%s)\n",
3190 debugstr_w(acl
->dependencies
[i
].name
),
3191 debugstr_version(&acl
->dependencies
[i
].version
) );
3192 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3197 /* FIXME should now iterate through all refs */
3201 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3202 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3204 NTSTATUS status
= STATUS_SUCCESS
;
3206 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3208 if (*handle
) return STATUS_INVALID_PARAMETER
;
3210 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3211 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3213 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3218 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3220 LdrLockLoaderLock( 0, NULL
, &magic
);
3221 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3223 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
3224 status
= STATUS_DLL_NOT_FOUND
;
3226 *handle
= pldr
->ActivationContext
;
3228 else status
= STATUS_DLL_NOT_FOUND
;
3229 LdrUnlockLoaderLock( 0, magic
);
3231 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3232 *handle
= process_actctx
;
3237 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3239 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3240 struct strsection_header
*header
;
3241 struct dllredirect_data
*data
;
3242 struct string_index
*index
;
3245 /* compute section length */
3246 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3248 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3249 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3251 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3253 /* each entry needs index, data and string data */
3254 total_len
+= sizeof(*index
);
3255 total_len
+= sizeof(*data
);
3256 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3259 dll_count
+= assembly
->num_dlls
;
3262 total_len
+= sizeof(*header
);
3264 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3265 if (!header
) return STATUS_NO_MEMORY
;
3267 memset(header
, 0, sizeof(*header
));
3268 header
->magic
= STRSECTION_MAGIC
;
3269 header
->size
= sizeof(*header
);
3270 header
->count
= dll_count
;
3271 header
->index_offset
= sizeof(*header
);
3272 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3273 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3275 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3277 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3278 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3280 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3284 /* setup new index entry */
3285 str
.Buffer
= dll
->name
;
3286 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3287 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3288 /* hash original class name */
3289 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3291 index
->name_offset
= name_offset
;
3292 index
->name_len
= str
.Length
;
3293 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3294 index
->data_len
= sizeof(*data
);
3295 index
->rosterindex
= i
+ 1;
3298 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3299 data
->size
= sizeof(*data
);
3300 data
->unk
= 2; /* FIXME: seems to be constant */
3301 memset(data
->res
, 0, sizeof(data
->res
));
3304 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3305 memcpy(ptrW
, dll
->name
, index
->name_len
);
3306 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3308 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3316 return STATUS_SUCCESS
;
3319 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3321 struct string_index
*iter
, *index
= NULL
;
3324 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3325 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3327 for (i
= 0; i
< section
->count
; i
++)
3329 if (iter
->hash
== hash
)
3331 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3333 if (!strcmpiW(nameW
, name
->Buffer
))
3339 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3347 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3349 struct guid_index
*iter
, *index
= NULL
;
3352 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3354 for (i
= 0; i
< section
->count
; i
++)
3356 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3367 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3369 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3372 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3373 PACTCTX_SECTION_KEYED_DATA data
)
3375 struct dllredirect_data
*dll
;
3376 struct string_index
*index
;
3378 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3380 if (!actctx
->dllredirect_section
)
3382 struct strsection_header
*section
;
3384 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3385 if (status
) return status
;
3387 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3388 RtlFreeHeap(GetProcessHeap(), 0, section
);
3391 index
= find_string_index(actctx
->dllredirect_section
, name
);
3392 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3396 dll
= get_dllredirect_data(actctx
, index
);
3398 data
->ulDataFormatVersion
= 1;
3400 data
->ulLength
= dll
->size
;
3401 data
->lpSectionGlobalData
= NULL
;
3402 data
->ulSectionGlobalDataLength
= 0;
3403 data
->lpSectionBase
= actctx
->dllredirect_section
;
3404 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3405 data
->hActCtx
= NULL
;
3407 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3408 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3411 return STATUS_SUCCESS
;
3414 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3416 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3419 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3421 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3424 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3426 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3427 struct wndclass_redirect_data
*data
;
3428 struct strsection_header
*header
;
3429 struct string_index
*index
;
3432 /* compute section length */
3433 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3435 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3436 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3438 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3439 for (k
= 0; k
< dll
->entities
.num
; k
++)
3441 struct entity
*entity
= &dll
->entities
.base
[k
];
3442 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3444 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3447 /* each class entry needs index, data and string data */
3448 total_len
+= sizeof(*index
);
3449 total_len
+= sizeof(*data
);
3450 /* original name is stored separately */
3451 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3452 /* versioned name and module name are stored one after another */
3453 if (entity
->u
.class.versioned
)
3454 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3457 len
+= strlenW(dll
->name
) + 1;
3458 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3466 total_len
+= sizeof(*header
);
3468 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3469 if (!header
) return STATUS_NO_MEMORY
;
3471 memset(header
, 0, sizeof(*header
));
3472 header
->magic
= STRSECTION_MAGIC
;
3473 header
->size
= sizeof(*header
);
3474 header
->count
= class_count
;
3475 header
->index_offset
= sizeof(*header
);
3476 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3477 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3479 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3481 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3482 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3484 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3485 for (k
= 0; k
< dll
->entities
.num
; k
++)
3487 struct entity
*entity
= &dll
->entities
.base
[k
];
3488 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3490 static const WCHAR exclW
[] = {'!',0};
3491 ULONG versioned_len
, module_len
;
3495 /* setup new index entry */
3496 str
.Buffer
= entity
->u
.class.name
;
3497 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3498 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3499 /* hash original class name */
3500 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3502 /* include '!' separator too */
3503 if (entity
->u
.class.versioned
)
3504 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3506 versioned_len
= str
.Length
;
3507 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3509 index
->name_offset
= name_offset
;
3510 index
->name_len
= str
.Length
;
3511 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3512 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3513 index
->rosterindex
= i
+ 1;
3516 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3517 data
->size
= sizeof(*data
);
3519 data
->name_len
= versioned_len
;
3520 data
->name_offset
= sizeof(*data
);
3521 data
->module_len
= module_len
;
3522 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3524 /* original class name */
3525 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3526 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3527 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3530 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3531 memcpy(ptrW
, dll
->name
, data
->module_len
);
3532 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3534 /* versioned name */
3535 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3536 if (entity
->u
.class.versioned
)
3538 get_assembly_version(assembly
, ptrW
);
3539 strcatW(ptrW
, exclW
);
3540 strcatW(ptrW
, entity
->u
.class.name
);
3544 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3545 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3548 name_offset
+= sizeof(*data
);
3549 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3559 return STATUS_SUCCESS
;
3562 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3563 PACTCTX_SECTION_KEYED_DATA data
)
3565 struct string_index
*iter
, *index
= NULL
;
3566 struct wndclass_redirect_data
*class;
3570 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3572 if (!actctx
->wndclass_section
)
3574 struct strsection_header
*section
;
3576 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3577 if (status
) return status
;
3579 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3580 RtlFreeHeap(GetProcessHeap(), 0, section
);
3584 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3585 iter
= get_wndclass_first_index(actctx
);
3587 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3589 if (iter
->hash
== hash
)
3591 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3593 if (!strcmpiW(nameW
, name
->Buffer
))
3599 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3604 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3608 class = get_wndclass_data(actctx
, index
);
3610 data
->ulDataFormatVersion
= 1;
3611 data
->lpData
= class;
3612 /* full length includes string length with nulls */
3613 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3614 data
->lpSectionGlobalData
= NULL
;
3615 data
->ulSectionGlobalDataLength
= 0;
3616 data
->lpSectionBase
= actctx
->wndclass_section
;
3617 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3618 data
->hActCtx
= NULL
;
3620 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3621 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3624 return STATUS_SUCCESS
;
3627 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3629 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3630 struct guidsection_header
*header
;
3631 ULONG module_offset
, data_offset
;
3632 struct tlibredirect_data
*data
;
3633 struct guid_index
*index
;
3635 /* compute section length */
3636 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3638 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3639 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3641 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3642 for (k
= 0; k
< dll
->entities
.num
; k
++)
3644 struct entity
*entity
= &dll
->entities
.base
[k
];
3645 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3647 /* each entry needs index, data and string data for module name and help string */
3648 total_len
+= sizeof(*index
);
3649 total_len
+= sizeof(*data
);
3650 /* help string is stored separately */
3651 if (*entity
->u
.typelib
.helpdir
)
3652 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3654 /* module names are packed one after another */
3655 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3663 total_len
+= aligned_string_len(names_len
);
3664 total_len
+= sizeof(*header
);
3666 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3667 if (!header
) return STATUS_NO_MEMORY
;
3669 memset(header
, 0, sizeof(*header
));
3670 header
->magic
= GUIDSECTION_MAGIC
;
3671 header
->size
= sizeof(*header
);
3672 header
->count
= tlib_count
;
3673 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3674 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3675 module_offset
= sizeof(*header
);
3676 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3678 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3680 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3681 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3683 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3684 for (k
= 0; k
< dll
->entities
.num
; k
++)
3686 struct entity
*entity
= &dll
->entities
.base
[k
];
3687 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3689 ULONG module_len
, help_len
;
3693 if (*entity
->u
.typelib
.helpdir
)
3694 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3698 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3700 /* setup new index entry */
3701 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3702 RtlGUIDFromString(&str
, &index
->guid
);
3703 index
->data_offset
= data_offset
;
3704 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3705 index
->rosterindex
= i
+ 1;
3708 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3709 data
->size
= sizeof(*data
);
3711 data
->name_len
= module_len
;
3712 data
->name_offset
= module_offset
;
3713 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3715 data
->flags
= entity
->u
.typelib
.flags
;
3716 data
->help_len
= help_len
;
3717 data
->help_offset
= sizeof(*data
);
3718 data
->major_version
= entity
->u
.typelib
.major
;
3719 data
->minor_version
= entity
->u
.typelib
.minor
;
3722 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3723 memcpy(ptrW
, dll
->name
, data
->name_len
);
3724 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3729 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3730 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3731 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3734 data_offset
+= sizeof(*data
);
3736 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3738 module_offset
+= module_len
+ sizeof(WCHAR
);
3748 return STATUS_SUCCESS
;
3751 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3753 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3756 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3758 struct guid_index
*index
= NULL
;
3759 struct tlibredirect_data
*tlib
;
3761 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3763 if (!actctx
->tlib_section
)
3765 struct guidsection_header
*section
;
3767 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3768 if (status
) return status
;
3770 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3771 RtlFreeHeap(GetProcessHeap(), 0, section
);
3774 index
= find_guid_index(actctx
->tlib_section
, guid
);
3775 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3777 tlib
= get_tlib_data(actctx
, index
);
3779 data
->ulDataFormatVersion
= 1;
3780 data
->lpData
= tlib
;
3781 /* full length includes string length with nulls */
3782 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3783 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3784 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3785 data
->lpSectionBase
= actctx
->tlib_section
;
3786 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3787 data
->hActCtx
= NULL
;
3789 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3790 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3792 return STATUS_SUCCESS
;
3795 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3797 ULONG
*ptr
= (ULONG
*)guid
;
3800 /* GUID is 16 bytes long */
3801 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3802 *ptr
= RtlUniform(seed
);
3804 guid
->Data3
&= 0x0fff;
3805 guid
->Data3
|= (4 << 12);
3806 guid
->Data4
[0] &= 0x3f;
3807 guid
->Data4
[0] |= 0x80;
3810 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3811 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3815 for (i
= 0; i
< entities
->num
; i
++)
3817 struct entity
*entity
= &entities
->base
[i
];
3818 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3820 /* each entry needs two index entries, extra one goes for alias GUID */
3821 *len
+= 2*sizeof(struct guid_index
);
3822 /* To save some memory we don't allocated two data structures,
3823 instead alias index and normal index point to the same data structure. */
3824 *len
+= sizeof(struct comclassredirect_data
);
3826 /* for clrClass store some more */
3827 if (entity
->u
.comclass
.name
)
3829 unsigned int str_len
;
3831 /* all string data is stored together in aligned block */
3832 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3833 if (entity
->u
.comclass
.progid
)
3834 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3835 if (entity
->u
.comclass
.version
)
3836 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3838 *len
+= sizeof(struct clrclass_data
);
3839 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3841 /* module name is forced to mscoree.dll, and stored two times with different case */
3842 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3846 /* progid string is stored separately */
3847 if (entity
->u
.comclass
.progid
)
3848 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3850 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3858 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3859 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3860 ULONG
*seed
, ULONG rosterindex
)
3864 for (i
= 0; i
< entities
->num
; i
++)
3866 struct entity
*entity
= &entities
->base
[i
];
3867 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3869 ULONG module_len
, progid_len
, str_len
= 0;
3870 struct comclassredirect_data
*data
;
3871 struct guid_index
*alias_index
;
3872 struct clrclass_data
*clrdata
;
3876 if (entity
->u
.comclass
.progid
)
3877 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3881 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3883 /* setup new index entry */
3884 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3885 RtlGUIDFromString(&str
, &(*index
)->guid
);
3887 (*index
)->data_offset
= *data_offset
;
3888 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3889 (*index
)->rosterindex
= rosterindex
;
3891 /* Setup new index entry for alias guid. Alias index records are placed after
3892 normal records, so normal guids are hit first on search. Note that class count
3894 alias_index
= (*index
) + section
->count
/2;
3895 generate_uuid(seed
, &alias_index
->guid
);
3896 alias_index
->data_offset
= (*index
)->data_offset
;
3897 alias_index
->data_len
= 0;
3898 alias_index
->rosterindex
= (*index
)->rosterindex
;
3901 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3902 data
->size
= sizeof(*data
);
3906 data
->model
= entity
->u
.comclass
.model
;
3907 data
->clsid
= (*index
)->guid
;
3908 data
->alias
= alias_index
->guid
;
3909 data
->clsid2
= data
->clsid
;
3910 if (entity
->u
.comclass
.tlbid
)
3912 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3913 RtlGUIDFromString(&str
, &data
->tlbid
);
3916 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3917 data
->name_len
= module_len
;
3918 data
->name_offset
= *module_offset
;
3919 data
->progid_len
= progid_len
;
3920 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3921 data
->clrdata_len
= 0; /* will be set later */
3922 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3923 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3924 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3925 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3926 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3927 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3929 /* mask describes which misc* data is available */
3931 if (data
->miscstatus
)
3932 data
->miscmask
|= MiscStatus
;
3933 if (data
->miscstatuscontent
)
3934 data
->miscmask
|= MiscStatusContent
;
3935 if (data
->miscstatusthumbnail
)
3936 data
->miscmask
|= MiscStatusThumbnail
;
3937 if (data
->miscstatusicon
)
3938 data
->miscmask
|= MiscStatusIcon
;
3939 if (data
->miscstatusdocprint
)
3940 data
->miscmask
|= MiscStatusDocPrint
;
3942 if (data
->clrdata_offset
)
3944 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3946 clrdata
->size
= sizeof(*clrdata
);
3947 clrdata
->res
[0] = 0;
3948 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3949 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3950 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3951 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3952 clrdata
->name_offset
= clrdata
->size
;
3953 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3954 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3955 clrdata
->res2
[0] = 0;
3956 clrdata
->res2
[1] = 0;
3958 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3961 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3962 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3963 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3965 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3966 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3967 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3970 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3971 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3972 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3974 /* runtime version, optional */
3975 if (clrdata
->version_len
)
3977 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3979 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3980 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3981 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3984 if (data
->progid_len
)
3985 data
->progid_offset
+= data
->clrdata_len
;
3986 (*index
)->data_len
+= sizeof(*clrdata
);
3993 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3994 memcpy(ptrW
, dll
->name
, data
->name_len
);
3995 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3999 if (data
->progid_len
)
4001 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4002 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4003 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4006 /* string block length */
4010 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4011 if (clrdata
->version_len
)
4012 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4015 str_len
+= progid_len
+ sizeof(WCHAR
);
4017 (*index
)->data_len
+= aligned_string_len(str_len
);
4018 alias_index
->data_len
= (*index
)->data_len
;
4020 /* move to next data record */
4021 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4022 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4026 (*data_offset
) += sizeof(*clrdata
);
4027 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4034 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4036 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4037 struct guidsection_header
*header
;
4038 ULONG module_offset
, data_offset
;
4039 struct guid_index
*index
;
4042 /* compute section length */
4043 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4045 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4046 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4047 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4049 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4050 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4054 total_len
+= aligned_string_len(names_len
);
4055 total_len
+= sizeof(*header
);
4057 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4058 if (!header
) return STATUS_NO_MEMORY
;
4060 memset(header
, 0, sizeof(*header
));
4061 header
->magic
= GUIDSECTION_MAGIC
;
4062 header
->size
= sizeof(*header
);
4063 header
->count
= 2*class_count
;
4064 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4065 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4066 module_offset
= sizeof(*header
);
4067 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4069 seed
= NtGetTickCount();
4070 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4072 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4073 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4074 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4076 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4077 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4083 return STATUS_SUCCESS
;
4086 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4088 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4091 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4093 struct comclassredirect_data
*comclass
;
4094 struct guid_index
*index
= NULL
;
4096 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4098 if (!actctx
->comserver_section
)
4100 struct guidsection_header
*section
;
4102 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4103 if (status
) return status
;
4105 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4106 RtlFreeHeap(GetProcessHeap(), 0, section
);
4109 index
= find_guid_index(actctx
->comserver_section
, guid
);
4110 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4112 comclass
= get_comclass_data(actctx
, index
);
4114 data
->ulDataFormatVersion
= 1;
4115 data
->lpData
= comclass
;
4116 /* full length includes string length with nulls */
4117 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4118 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4119 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4120 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4121 data
->lpSectionBase
= actctx
->comserver_section
;
4122 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4123 data
->hActCtx
= NULL
;
4125 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4126 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4128 return STATUS_SUCCESS
;
4131 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4135 for (i
= 0; i
< entities
->num
; i
++)
4137 struct entity
*entity
= &entities
->base
[i
];
4138 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4140 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4141 if (entity
->u
.ifaceps
.name
)
4142 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4148 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4149 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4153 for (i
= 0; i
< entities
->num
; i
++)
4155 struct entity
*entity
= &entities
->base
[i
];
4156 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4158 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4162 if (entity
->u
.ifaceps
.name
)
4163 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4168 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4169 RtlGUIDFromString(&str
, &(*index
)->guid
);
4170 (*index
)->data_offset
= *data_offset
;
4171 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4172 (*index
)->rosterindex
= rosterindex
;
4174 /* setup data record */
4175 data
->size
= sizeof(*data
);
4176 data
->mask
= entity
->u
.ifaceps
.mask
;
4178 /* proxyStubClsid32 value is only stored for external PS,
4179 if set it's used as iid, otherwise 'iid' attribute value is used */
4180 if (entity
->u
.ifaceps
.ps32
)
4182 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4183 RtlGUIDFromString(&str
, &data
->iid
);
4186 data
->iid
= (*index
)->guid
;
4188 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4190 if (entity
->u
.ifaceps
.tlib
)
4192 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4193 RtlGUIDFromString(&str
, &data
->tlbid
);
4196 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4198 if (entity
->u
.ifaceps
.base
)
4200 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4201 RtlGUIDFromString(&str
, &data
->base
);
4204 memset(&data
->base
, 0, sizeof(data
->base
));
4206 data
->name_len
= name_len
;
4207 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4212 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4213 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4214 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4217 /* move to next record */
4219 *data_offset
+= sizeof(*data
);
4221 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4226 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4228 unsigned int i
, j
, total_len
= 0, count
= 0;
4229 struct guidsection_header
*header
;
4230 struct guid_index
*index
;
4233 /* compute section length */
4234 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4236 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4238 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4239 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4241 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4242 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4246 total_len
+= sizeof(*header
);
4248 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4249 if (!header
) return STATUS_NO_MEMORY
;
4251 memset(header
, 0, sizeof(*header
));
4252 header
->magic
= GUIDSECTION_MAGIC
;
4253 header
->size
= sizeof(*header
);
4254 header
->count
= count
;
4255 header
->index_offset
= sizeof(*header
);
4256 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4257 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4259 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4261 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4263 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4264 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4266 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4267 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4273 return STATUS_SUCCESS
;
4276 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4278 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4281 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4283 struct ifacepsredirect_data
*iface
;
4284 struct guid_index
*index
= NULL
;
4286 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4288 if (!actctx
->ifaceps_section
)
4290 struct guidsection_header
*section
;
4292 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4293 if (status
) return status
;
4295 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4296 RtlFreeHeap(GetProcessHeap(), 0, section
);
4299 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4300 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4302 iface
= get_ifaceps_data(actctx
, index
);
4304 data
->ulDataFormatVersion
= 1;
4305 data
->lpData
= iface
;
4306 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4307 data
->lpSectionGlobalData
= NULL
;
4308 data
->ulSectionGlobalDataLength
= 0;
4309 data
->lpSectionBase
= actctx
->ifaceps_section
;
4310 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4311 data
->hActCtx
= NULL
;
4313 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4314 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4316 return STATUS_SUCCESS
;
4319 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4321 unsigned int i
, j
, total_len
= 0, count
= 0;
4322 struct guidsection_header
*header
;
4323 struct clrsurrogate_data
*data
;
4324 struct guid_index
*index
;
4327 /* compute section length */
4328 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4330 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4331 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4333 struct entity
*entity
= &assembly
->entities
.base
[j
];
4334 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4338 total_len
+= sizeof(*index
) + sizeof(*data
);
4339 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4340 if (entity
->u
.clrsurrogate
.version
)
4341 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4342 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4349 total_len
+= sizeof(*header
);
4351 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4352 if (!header
) return STATUS_NO_MEMORY
;
4354 memset(header
, 0, sizeof(*header
));
4355 header
->magic
= GUIDSECTION_MAGIC
;
4356 header
->size
= sizeof(*header
);
4357 header
->count
= count
;
4358 header
->index_offset
= sizeof(*header
);
4359 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4360 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4362 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4364 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4365 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4367 struct entity
*entity
= &assembly
->entities
.base
[j
];
4368 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4370 ULONG version_len
, name_len
;
4374 if (entity
->u
.clrsurrogate
.version
)
4375 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4378 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4380 /* setup new index entry */
4381 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4382 RtlGUIDFromString(&str
, &index
->guid
);
4384 index
->data_offset
= data_offset
;
4385 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4386 index
->rosterindex
= i
+ 1;
4389 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4390 data
->size
= sizeof(*data
);
4392 data
->clsid
= index
->guid
;
4393 data
->version_offset
= version_len
? data
->size
: 0;
4394 data
->version_len
= version_len
;
4395 data
->name_offset
= data
->size
+ version_len
;
4397 data
->name_offset
+= sizeof(WCHAR
);
4398 data
->name_len
= name_len
;
4400 /* surrogate name */
4401 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4402 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4403 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4405 /* runtime version */
4406 if (data
->version_len
)
4408 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4409 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4410 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4413 data_offset
+= index
->data_offset
;
4421 return STATUS_SUCCESS
;
4424 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4426 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4429 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4431 struct clrsurrogate_data
*surrogate
;
4432 struct guid_index
*index
= NULL
;
4434 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4436 if (!actctx
->clrsurrogate_section
)
4438 struct guidsection_header
*section
;
4440 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4441 if (status
) return status
;
4443 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4444 RtlFreeHeap(GetProcessHeap(), 0, section
);
4447 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4448 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4450 surrogate
= get_surrogate_data(actctx
, index
);
4452 data
->ulDataFormatVersion
= 1;
4453 data
->lpData
= surrogate
;
4454 /* full length includes string length with nulls */
4455 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4456 if (surrogate
->version_len
)
4457 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4459 data
->lpSectionGlobalData
= NULL
;
4460 data
->ulSectionGlobalDataLength
= 0;
4461 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4462 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4463 data
->hActCtx
= NULL
;
4465 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4466 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4468 return STATUS_SUCCESS
;
4471 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4473 unsigned int i
, j
, single_len
;
4475 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4476 for (i
= 0; i
< entities
->num
; i
++)
4478 struct entity
*entity
= &entities
->base
[i
];
4479 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4481 if (entity
->u
.comclass
.progid
)
4483 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4487 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4488 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4490 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4491 *count
+= entity
->u
.comclass
.progids
.num
;
4496 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4497 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4499 struct progidredirect_data
*data
;
4504 /* setup new index entry */
4506 /* hash progid name */
4507 RtlInitUnicodeString(&str
, progid
);
4508 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4510 (*index
)->name_offset
= *data_offset
;
4511 (*index
)->name_len
= str
.Length
;
4512 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4513 (*index
)->data_len
= sizeof(*data
);
4514 (*index
)->rosterindex
= rosterindex
;
4516 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4518 /* setup data structure */
4519 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4520 data
->size
= sizeof(*data
);
4522 data
->clsid_offset
= *global_offset
;
4524 /* write progid string */
4525 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4526 memcpy(ptrW
, progid
, (*index
)->name_len
);
4527 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4529 /* write guid to global area */
4530 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4534 *global_offset
+= sizeof(GUID
);
4535 *data_offset
+= data
->size
;
4539 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4540 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4544 for (i
= 0; i
< entities
->num
; i
++)
4546 struct entity
*entity
= &entities
->base
[i
];
4547 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4549 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4550 struct comclassredirect_data
*comclass
;
4551 struct guid_index
*guid_index
;
4555 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4556 RtlGUIDFromString(&str
, &clsid
);
4558 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4559 comclass
= get_comclass_data(actctx
, guid_index
);
4561 if (entity
->u
.comclass
.progid
)
4562 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4563 index
, data_offset
, global_offset
, rosterindex
);
4565 for (j
= 0; j
< progids
->num
; j
++)
4566 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4567 index
, data_offset
, global_offset
, rosterindex
);
4572 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4574 unsigned int i
, j
, total_len
= 0, count
= 0;
4575 struct strsection_header
*header
;
4576 ULONG data_offset
, global_offset
;
4577 struct string_index
*index
;
4579 /* compute section length */
4580 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4582 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4584 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4585 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4587 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4588 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4592 total_len
+= sizeof(*header
);
4594 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4595 if (!header
) return STATUS_NO_MEMORY
;
4597 memset(header
, 0, sizeof(*header
));
4598 header
->magic
= STRSECTION_MAGIC
;
4599 header
->size
= sizeof(*header
);
4600 header
->count
= count
;
4601 header
->global_offset
= header
->size
;
4602 header
->global_len
= count
*sizeof(GUID
);
4603 header
->index_offset
= header
->size
+ header
->global_len
;
4605 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4606 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4607 global_offset
= header
->global_offset
;
4609 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4611 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4613 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4614 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4616 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4617 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4623 return STATUS_SUCCESS
;
4626 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4628 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4631 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4632 PACTCTX_SECTION_KEYED_DATA data
)
4634 struct progidredirect_data
*progid
;
4635 struct string_index
*index
;
4637 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4639 if (!actctx
->comserver_section
)
4641 struct guidsection_header
*section
;
4643 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4644 if (status
) return status
;
4646 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4647 RtlFreeHeap(GetProcessHeap(), 0, section
);
4650 if (!actctx
->progid_section
)
4652 struct strsection_header
*section
;
4654 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4655 if (status
) return status
;
4657 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4658 RtlFreeHeap(GetProcessHeap(), 0, section
);
4661 index
= find_string_index(actctx
->progid_section
, name
);
4662 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4666 progid
= get_progid_data(actctx
, index
);
4668 data
->ulDataFormatVersion
= 1;
4669 data
->lpData
= progid
;
4670 data
->ulLength
= progid
->size
;
4671 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4672 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4673 data
->lpSectionBase
= actctx
->progid_section
;
4674 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4675 data
->hActCtx
= NULL
;
4677 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4678 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4681 return STATUS_SUCCESS
;
4684 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4685 const UNICODE_STRING
*section_name
,
4686 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4690 switch (section_kind
)
4692 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4693 status
= find_dll_redirection(actctx
, section_name
, data
);
4695 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4696 status
= find_window_class(actctx
, section_name
, data
);
4698 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4699 status
= find_progid_redirection(actctx
, section_name
, data
);
4701 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4702 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4703 return STATUS_SXS_SECTION_NOT_FOUND
;
4705 WARN("Unknown section_kind %x\n", section_kind
);
4706 return STATUS_SXS_SECTION_NOT_FOUND
;
4709 if (status
!= STATUS_SUCCESS
) return status
;
4711 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4713 actctx_addref(actctx
);
4714 data
->hActCtx
= actctx
;
4716 return STATUS_SUCCESS
;
4719 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4720 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4724 switch (section_kind
)
4726 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4727 status
= find_tlib_redirection(actctx
, guid
, data
);
4729 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4730 status
= find_comserver_redirection(actctx
, guid
, data
);
4732 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4733 status
= find_cominterface_redirection(actctx
, guid
, data
);
4735 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4736 status
= find_clr_surrogate(actctx
, guid
, data
);
4739 WARN("Unknown section_kind %x\n", section_kind
);
4740 return STATUS_SXS_SECTION_NOT_FOUND
;
4743 if (status
!= STATUS_SUCCESS
) return status
;
4745 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4747 actctx_addref(actctx
);
4748 data
->hActCtx
= actctx
;
4750 return STATUS_SUCCESS
;
4753 /* initialize the activation context for the current process */
4754 void actctx_init(void)
4759 ctx
.cbSize
= sizeof(ctx
);
4760 ctx
.lpSource
= NULL
;
4761 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4762 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4763 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4765 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4769 /***********************************************************************
4770 * RtlCreateActivationContext (NTDLL.@)
4772 * Create an activation context.
4774 * FIXME: function signature/prototype is wrong
4776 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4778 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4779 const WCHAR
*directory
= NULL
;
4780 ACTIVATION_CONTEXT
*actctx
;
4781 UNICODE_STRING nameW
;
4783 NTSTATUS status
= STATUS_NO_MEMORY
;
4785 struct actctx_loader acl
;
4787 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4789 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4790 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4791 return STATUS_INVALID_PARAMETER
;
4793 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4794 return STATUS_NO_MEMORY
;
4796 actctx
->magic
= ACTCTX_MAGIC
;
4797 actctx
->ref_count
= 1;
4798 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4799 actctx
->config
.info
= NULL
;
4800 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4801 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4803 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4811 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4812 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4814 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4815 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4816 actctx
->appdir
.info
= dir
.Buffer
;
4819 nameW
.Buffer
= NULL
;
4821 /* open file only if it's going to be used */
4822 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4823 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4825 WCHAR
*source
= NULL
;
4828 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4829 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
4831 DWORD dir_len
, source_len
;
4833 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4834 source_len
= strlenW(pActCtx
->lpSource
);
4835 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4837 status
= STATUS_NO_MEMORY
;
4841 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4842 source
[dir_len
] = '\\';
4843 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4846 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4847 RtlFreeHeap( GetProcessHeap(), 0, source
);
4850 status
= STATUS_NO_SUCH_FILE
;
4853 status
= open_nt_file( &file
, &nameW
);
4856 RtlFreeUnicodeString( &nameW
);
4861 acl
.actctx
= actctx
;
4862 acl
.dependencies
= NULL
;
4863 acl
.num_dependencies
= 0;
4864 acl
.allocated_dependencies
= 0;
4866 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4867 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4869 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4871 /* if we have a resource it's a PE file */
4872 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4874 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4875 pActCtx
->lpResourceName
, lang
);
4876 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4877 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4878 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4880 else if (pActCtx
->lpSource
)
4882 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4883 file
, pActCtx
->lpResourceName
, lang
);
4884 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4885 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4886 NULL
, pActCtx
->lpResourceName
);
4888 else status
= STATUS_INVALID_PARAMETER
;
4892 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4895 if (file
) NtClose( file
);
4896 RtlFreeUnicodeString( &nameW
);
4898 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4899 free_depend_manifests( &acl
);
4901 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4902 else actctx_release( actctx
);
4906 if (file
) NtClose( file
);
4907 actctx_release( actctx
);
4912 /***********************************************************************
4913 * RtlAddRefActivationContext (NTDLL.@)
4915 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4917 ACTIVATION_CONTEXT
*actctx
;
4919 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4923 /******************************************************************
4924 * RtlReleaseActivationContext (NTDLL.@)
4926 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
4928 ACTIVATION_CONTEXT
*actctx
;
4930 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4933 /******************************************************************
4934 * RtlZombifyActivationContext (NTDLL.@)
4936 * FIXME: function prototype might be wrong
4938 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
4940 FIXME("%p: stub\n", handle
);
4941 return STATUS_NOT_IMPLEMENTED
;
4944 /******************************************************************
4945 * RtlActivateActivationContext (NTDLL.@)
4947 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
4949 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4951 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
4952 return STATUS_NO_MEMORY
;
4954 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4955 frame
->ActivationContext
= handle
;
4957 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
4958 RtlAddRefActivationContext( handle
);
4960 *cookie
= (ULONG_PTR
)frame
;
4961 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
4962 return STATUS_SUCCESS
;
4966 /***********************************************************************
4967 * RtlDeactivateActivationContext (NTDLL.@)
4969 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4971 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4973 TRACE( "%x cookie=%lx\n", flags
, cookie
);
4975 /* find the right frame */
4976 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4977 for (frame
= top
; frame
; frame
= frame
->Previous
)
4978 if ((ULONG_PTR
)frame
== cookie
) break;
4981 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4983 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
4984 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4986 /* pop everything up to and including frame */
4987 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
4989 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4991 frame
= top
->Previous
;
4992 RtlReleaseActivationContext( top
->ActivationContext
);
4993 RtlFreeHeap( GetProcessHeap(), 0, top
);
4999 /******************************************************************
5000 * RtlFreeThreadActivationContextStack (NTDLL.@)
5002 void WINAPI
RtlFreeThreadActivationContextStack(void)
5004 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5006 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5009 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5010 RtlReleaseActivationContext( frame
->ActivationContext
);
5011 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5014 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5018 /******************************************************************
5019 * RtlGetActiveActivationContext (NTDLL.@)
5021 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5023 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5025 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5026 RtlAddRefActivationContext( *handle
);
5031 return STATUS_SUCCESS
;
5035 /******************************************************************
5036 * RtlIsActivationContextActive (NTDLL.@)
5038 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5040 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5042 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5043 if (frame
->ActivationContext
== handle
) return TRUE
;
5048 /***********************************************************************
5049 * RtlQueryInformationActivationContext (NTDLL.@)
5051 * Get information about an activation context.
5052 * FIXME: function signature/prototype may be wrong
5054 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5055 ULONG
class, PVOID buffer
,
5056 SIZE_T bufsize
, SIZE_T
*retlen
)
5058 ACTIVATION_CONTEXT
*actctx
;
5061 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5062 subinst
, class, buffer
, bufsize
, retlen
);
5064 if (retlen
) *retlen
= 0;
5065 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5069 case ActivationContextBasicInformation
:
5071 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5073 if (retlen
) *retlen
= sizeof(*info
);
5074 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5076 info
->hActCtx
= handle
;
5077 info
->dwFlags
= 0; /* FIXME */
5078 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5082 case ActivationContextDetailedInformation
:
5084 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5085 struct assembly
*assembly
= NULL
;
5086 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5089 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5091 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5093 if (assembly
&& assembly
->manifest
.info
)
5094 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5095 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5096 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5097 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5099 if (retlen
) *retlen
= len
;
5100 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5103 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5104 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5105 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5106 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5107 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5108 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5109 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5110 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5111 ptr
= (LPWSTR
)(acdi
+ 1);
5114 acdi
->lpRootManifestPath
= ptr
;
5115 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5116 ptr
+= manifest_len
;
5118 else acdi
->lpRootManifestPath
= NULL
;
5121 acdi
->lpRootConfigurationPath
= ptr
;
5122 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5125 else acdi
->lpRootConfigurationPath
= NULL
;
5128 acdi
->lpAppDirPath
= ptr
;
5129 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5131 else acdi
->lpAppDirPath
= NULL
;
5135 case AssemblyDetailedInformationInActivationContext
:
5137 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5138 struct assembly
*assembly
;
5141 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5144 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5145 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5147 index
= *(DWORD
*)subinst
;
5148 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5150 assembly
= &actctx
->assemblies
[index
- 1];
5152 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5153 id_len
= strlenW(assembly_id
) + 1;
5154 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5156 if (assembly
->manifest
.info
&&
5157 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5158 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5160 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5162 if (retlen
) *retlen
= len
;
5163 if (!buffer
|| bufsize
< len
)
5165 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5166 return STATUS_BUFFER_TOO_SMALL
;
5169 afdi
->ulFlags
= 0; /* FIXME */
5170 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5171 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5172 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5173 /* FIXME afdi->liManifestLastWriteTime = 0; */
5174 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5175 afdi
->ulPolicyPathLength
= 0;
5176 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5177 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5178 afdi
->ulManifestVersionMajor
= 1;
5179 afdi
->ulManifestVersionMinor
= 0;
5180 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5181 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5182 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5183 ptr
= (LPWSTR
)(afdi
+ 1);
5184 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5185 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5189 afdi
->lpAssemblyManifestPath
= ptr
;
5190 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5192 } else afdi
->lpAssemblyManifestPath
= NULL
;
5193 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5196 afdi
->lpAssemblyDirectoryName
= ptr
;
5197 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5199 else afdi
->lpAssemblyDirectoryName
= NULL
;
5200 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5204 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5206 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5207 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5208 struct assembly
*assembly
;
5209 struct dll_redirect
*dll
;
5210 SIZE_T len
, dll_len
= 0;
5213 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5214 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5216 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5217 return STATUS_INVALID_PARAMETER
;
5218 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5220 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5221 return STATUS_INVALID_PARAMETER
;
5222 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5224 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5225 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5227 if (!buffer
|| bufsize
< len
)
5229 if (retlen
) *retlen
= len
;
5230 return STATUS_BUFFER_TOO_SMALL
;
5232 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5233 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5234 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5235 afdi
->ulPathLength
= 0; /* FIXME */
5236 ptr
= (LPWSTR
)(afdi
+ 1);
5239 afdi
->lpFileName
= ptr
;
5240 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5241 } else afdi
->lpFileName
= NULL
;
5242 afdi
->lpFilePath
= NULL
; /* FIXME */
5246 case CompatibilityInformationInActivationContext
:
5248 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5249 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5250 struct assembly
*assembly
= NULL
;
5251 ULONG num_compat_contexts
= 0, n
;
5254 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5256 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5259 num_compat_contexts
= assembly
->num_compat_contexts
;
5260 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5262 if (retlen
) *retlen
= len
;
5263 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5265 *acci
= num_compat_contexts
;
5266 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5267 for (n
= 0; n
< num_compat_contexts
; ++n
)
5269 elements
[n
] = assembly
->compat_contexts
[n
];
5274 case RunlevelInformationInActivationContext
:
5276 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5277 struct assembly
*assembly
;
5280 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5282 len
= sizeof(*acrli
);
5283 if (retlen
) *retlen
= len
;
5284 if (!buffer
|| bufsize
< len
)
5285 return STATUS_BUFFER_TOO_SMALL
;
5287 assembly
= actctx
->assemblies
;
5290 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5291 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5296 FIXME( "class %u not implemented\n", class );
5297 return STATUS_NOT_IMPLEMENTED
;
5299 return STATUS_SUCCESS
;
5302 /***********************************************************************
5303 * RtlFindActivationContextSectionString (NTDLL.@)
5305 * Find information about a string in an activation context.
5306 * FIXME: function signature/prototype may be wrong
5308 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5309 const UNICODE_STRING
*section_name
, PVOID ptr
)
5311 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5312 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5314 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5315 debugstr_us(section_name
), data
);
5319 FIXME("expected guid == NULL\n");
5320 return STATUS_INVALID_PARAMETER
;
5322 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5324 FIXME("unknown flags %08x\n", flags
);
5325 return STATUS_INVALID_PARAMETER
;
5327 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5328 !section_name
|| !section_name
->Buffer
)
5330 WARN("invalid parameter\n");
5331 return STATUS_INVALID_PARAMETER
;
5334 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5336 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5337 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5340 if (status
!= STATUS_SUCCESS
)
5341 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5346 /***********************************************************************
5347 * RtlFindActivationContextSectionGuid (NTDLL.@)
5349 * Find information about a GUID in an activation context.
5350 * FIXME: function signature/prototype may be wrong
5352 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5353 const GUID
*guid
, void *ptr
)
5355 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5356 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5358 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5362 FIXME("expected extguid == NULL\n");
5363 return STATUS_INVALID_PARAMETER
;
5366 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5368 FIXME("unknown flags %08x\n", flags
);
5369 return STATUS_INVALID_PARAMETER
;
5372 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5373 return STATUS_INVALID_PARAMETER
;
5375 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5377 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5378 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5381 if (status
!= STATUS_SUCCESS
)
5382 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);