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_supportedos_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2250 xmlstr_t attr_name
, attr_value
;
2251 BOOL end
= FALSE
, error
;
2253 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2255 if (xmlstr_cmp(&attr_name
, IdW
))
2257 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2261 str
.Buffer
= (PWSTR
)attr_value
.ptr
;
2262 str
.Length
= str
.MaximumLength
= (USHORT
)attr_value
.len
* sizeof(WCHAR
);
2263 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2265 if (!(compat
= add_compat_context(assembly
))) return FALSE
;
2266 compat
->Type
= ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2267 compat
->Id
= compat_id
;
2271 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value
));
2276 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
2277 debugstr_xmlstr(&attr_value
));
2281 if (error
) return FALSE
;
2282 if (end
) return TRUE
;
2284 return parse_expect_end_elem(xmlbuf
, supportedOSW
, asmv1W
);
2287 static BOOL
parse_compatibility_application_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2288 struct actctx_loader
* acl
)
2293 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2295 if (xmlstr_cmp_end(&elem
, applicationW
))
2297 ret
= parse_end_element(xmlbuf
);
2300 else if (xmlstr_cmp(&elem
, supportedOSW
))
2302 ret
= parse_supportedos_elem(xmlbuf
, assembly
, acl
);
2306 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2307 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2314 static BOOL
parse_compatibility_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2315 struct actctx_loader
* acl
)
2320 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2322 if (xmlstr_cmp_end(&elem
, compatibilityW
))
2324 ret
= parse_end_element(xmlbuf
);
2327 else if (xmlstr_cmp(&elem
, applicationW
))
2329 ret
= parse_compatibility_application_elem(xmlbuf
, assembly
, acl
);
2333 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2334 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2340 static BOOL
parse_requested_execution_level_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2342 static const WCHAR levelW
[] = {'l','e','v','e','l',0};
2343 static const WCHAR asInvokerW
[] = {'a','s','I','n','v','o','k','e','r',0};
2344 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};
2345 static const WCHAR highestAvailableW
[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2346 static const WCHAR uiAccessW
[] = {'u','i','A','c','c','e','s','s',0};
2347 static const WCHAR falseW
[] = {'f','a','l','s','e',0};
2348 static const WCHAR trueW
[] = {'t','r','u','e',0};
2350 xmlstr_t attr_name
, attr_value
, elem
;
2351 BOOL end
= FALSE
, ret
= TRUE
, error
;
2353 /* Multiple requestedExecutionLevel elements are not supported. */
2354 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
)
2357 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2359 if (xmlstr_cmp(&attr_name
, levelW
))
2361 if (xmlstr_cmpi(&attr_value
, asInvokerW
))
2362 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2363 else if (xmlstr_cmpi(&attr_value
, highestAvailableW
))
2364 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2365 else if (xmlstr_cmpi(&attr_value
, requireAdministratorW
))
2366 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2368 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr_value
));
2370 else if (xmlstr_cmp(&attr_name
, uiAccessW
))
2372 if (xmlstr_cmpi(&attr_value
, falseW
))
2373 assembly
->ui_access
= FALSE
;
2374 else if (xmlstr_cmpi(&attr_value
, trueW
))
2375 assembly
->ui_access
= TRUE
;
2377 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr_value
));
2380 FIXME("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2383 if (error
) return FALSE
;
2384 if (end
) return TRUE
;
2386 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2388 if (xmlstr_cmp_end(&elem
, requestedExecutionLevelW
))
2390 ret
= parse_end_element(xmlbuf
);
2395 FIXME("unknown element %s\n", debugstr_xmlstr(&elem
));
2396 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2403 static BOOL
parse_requested_privileges_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2408 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2410 if (xmlstr_cmp_end(&elem
, requestedPrivilegesW
))
2412 ret
= parse_end_element(xmlbuf
);
2415 else if (xmlstr_cmp(&elem
, requestedExecutionLevelW
))
2416 ret
= parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
);
2419 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2420 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2427 static BOOL
parse_security_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2432 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2434 if (xmlstr_cmp_end(&elem
, securityW
))
2436 ret
= parse_end_element(xmlbuf
);
2439 else if (xmlstr_cmp(&elem
, requestedPrivilegesW
))
2440 ret
= parse_requested_privileges_elem(xmlbuf
, assembly
, acl
);
2443 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2444 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2451 static BOOL
parse_trust_info_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2456 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2458 if (xmlstr_cmp_end(&elem
, trustInfoW
))
2460 ret
= parse_end_element(xmlbuf
);
2463 else if (xmlstr_cmp(&elem
, securityW
))
2464 ret
= parse_security_elem(xmlbuf
, assembly
, acl
);
2467 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2468 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2475 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2476 struct assembly
* assembly
,
2477 struct assembly_identity
* expected_ai
)
2479 xmlstr_t attr_name
, attr_value
, elem
;
2480 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2482 TRACE("(%p)\n", xmlbuf
);
2484 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2486 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2488 static const WCHAR v10W
[] = {'1','.','0',0};
2489 if (!xmlstr_cmp(&attr_value
, v10W
))
2491 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
2496 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2498 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2499 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2500 !xmlstr_cmp(&attr_value
, manifestv3W
))
2502 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
2509 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2513 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2514 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2516 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2518 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2520 assembly
->no_inherit
= TRUE
;
2523 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2525 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2528 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2529 assembly
->no_inherit
)
2534 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2536 ret
= parse_end_element(xmlbuf
);
2539 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2541 ret
= parse_description_elem(xmlbuf
);
2543 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2545 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2547 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2549 ret
= parse_dependency_elem(xmlbuf
, acl
);
2551 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2553 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2555 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2557 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2559 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2561 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2563 else if (xml_elem_cmp(&elem
, trustInfoW
, asmv2W
) ||
2564 xml_elem_cmp(&elem
, trustInfoW
, asmv1W
))
2566 ret
= parse_trust_info_elem(xmlbuf
, assembly
, acl
);
2568 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2570 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2574 /* FIXME: more tests */
2575 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2576 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2578 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2579 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2580 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2581 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2582 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2585 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2586 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2587 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2588 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2589 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2590 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2592 FIXME("wrong version for shared assembly manifest\n");
2597 else if (xml_elem_cmp(&elem
, compatibilityW
, compatibilityNSW
))
2599 ret
= parse_compatibility_elem(xmlbuf
, assembly
, acl
);
2603 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2604 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2606 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2612 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2613 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2617 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2619 if (xmlstr_cmp(&elem
, xmlW
) &&
2620 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2621 return STATUS_SXS_CANT_GEN_ACTCTX
;
2623 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2625 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
2626 return STATUS_SXS_CANT_GEN_ACTCTX
;
2629 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2631 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2632 return STATUS_SXS_CANT_GEN_ACTCTX
;
2635 if (next_xml_elem(xmlbuf
, &elem
))
2637 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2638 return STATUS_SXS_CANT_GEN_ACTCTX
;
2641 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2643 FIXME("parse error\n");
2644 return STATUS_SXS_CANT_GEN_ACTCTX
;
2646 return STATUS_SUCCESS
;
2649 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2650 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2651 const void *buffer
, SIZE_T size
)
2655 struct assembly
*assembly
;
2658 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2660 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2661 return STATUS_SXS_CANT_GEN_ACTCTX
;
2663 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2664 return STATUS_NO_MEMORY
;
2666 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2667 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2668 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2670 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2671 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2673 xmlbuf
.ptr
= buffer
;
2674 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2675 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2677 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2679 const WCHAR
*buf
= buffer
;
2683 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2684 return STATUS_NO_MEMORY
;
2685 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2686 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2687 xmlbuf
.ptr
= new_buff
;
2688 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2689 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2690 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2694 /* let's assume utf-8 for now */
2695 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2700 FIXME( "utf-8 conversion failed\n" );
2701 return STATUS_SXS_CANT_GEN_ACTCTX
;
2703 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2704 return STATUS_NO_MEMORY
;
2705 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2706 xmlbuf
.ptr
= new_buff
;
2707 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2708 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2709 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2714 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2716 OBJECT_ATTRIBUTES attr
;
2719 attr
.Length
= sizeof(attr
);
2720 attr
.RootDirectory
= 0;
2721 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2722 attr
.ObjectName
= name
;
2723 attr
.SecurityDescriptor
= NULL
;
2724 attr
.SecurityQualityOfService
= NULL
;
2725 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2728 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2734 LdrLockLoaderLock(0, NULL
, &magic
);
2735 status
= LdrFindEntryForAddress( module
, &pldr
);
2736 if (status
== STATUS_SUCCESS
)
2738 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2739 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2741 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2742 str
->Length
= pldr
->FullDllName
.Length
;
2743 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2745 else status
= STATUS_NO_MEMORY
;
2747 LdrUnlockLoaderLock(0, magic
);
2751 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2752 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2753 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2756 UNICODE_STRING nameW
;
2757 LDR_RESOURCE_INFO info
;
2758 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2761 if (TRACE_ON(actctx
))
2763 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2765 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2766 hModule
, debugstr_w(nameW
.Buffer
) );
2767 RtlFreeUnicodeString( &nameW
);
2769 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2770 hModule
, debugstr_w(filename
) );
2773 if (!resname
) return STATUS_INVALID_PARAMETER
;
2775 info
.Type
= RT_MANIFEST
;
2776 info
.Language
= lang
;
2777 if (!((ULONG_PTR
)resname
>> 16))
2779 info
.Name
= (ULONG_PTR
)resname
;
2780 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2782 else if (resname
[0] == '#')
2785 RtlInitUnicodeString(&nameW
, resname
+ 1);
2786 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2787 return STATUS_INVALID_PARAMETER
;
2789 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2793 RtlCreateUnicodeString(&nameW
, resname
);
2794 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2795 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2796 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2797 RtlFreeUnicodeString(&nameW
);
2799 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2801 if (status
== STATUS_SUCCESS
)
2802 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2807 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2808 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2809 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2812 OBJECT_ATTRIBUTES attr
;
2814 LARGE_INTEGER offset
;
2819 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2821 attr
.Length
= sizeof(attr
);
2822 attr
.RootDirectory
= 0;
2823 attr
.ObjectName
= NULL
;
2824 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2825 attr
.SecurityDescriptor
= NULL
;
2826 attr
.SecurityQualityOfService
= NULL
;
2829 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2830 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2831 if (status
!= STATUS_SUCCESS
) return status
;
2833 offset
.QuadPart
= 0;
2836 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2837 &count
, ViewShare
, 0, PAGE_READONLY
);
2839 if (status
!= STATUS_SUCCESS
) return status
;
2841 if (RtlImageNtHeader(base
)) /* we got a PE file */
2843 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2844 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2846 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2848 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2852 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2853 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2855 FILE_END_OF_FILE_INFORMATION info
;
2858 OBJECT_ATTRIBUTES attr
;
2860 LARGE_INTEGER offset
;
2865 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2867 attr
.Length
= sizeof(attr
);
2868 attr
.RootDirectory
= 0;
2869 attr
.ObjectName
= NULL
;
2870 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2871 attr
.SecurityDescriptor
= NULL
;
2872 attr
.SecurityQualityOfService
= NULL
;
2875 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2876 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2877 if (status
!= STATUS_SUCCESS
) return status
;
2879 offset
.QuadPart
= 0;
2882 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2883 &count
, ViewShare
, 0, PAGE_READONLY
);
2885 if (status
!= STATUS_SUCCESS
) return status
;
2887 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2888 if (status
== STATUS_SUCCESS
)
2889 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2891 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2895 /* try to load the .manifest file associated to the file */
2896 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2897 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2899 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2902 UNICODE_STRING nameW
;
2904 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2906 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2908 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2910 if (module
) /* use the module filename */
2912 UNICODE_STRING name
;
2914 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2916 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2917 strcatW( name
.Buffer
, dotManifestW
);
2918 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2919 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2920 RtlFreeUnicodeString( &name
);
2922 if (status
) return status
;
2926 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2927 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2928 return STATUS_NO_MEMORY
;
2929 strcpyW( buffer
, filename
);
2930 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2931 strcatW( buffer
, dotManifestW
);
2932 RtlInitUnicodeString( &nameW
, buffer
);
2935 if (!open_nt_file( &file
, &nameW
))
2937 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2940 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2941 RtlFreeUnicodeString( &nameW
);
2945 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2947 static const WCHAR lookup_fmtW
[] =
2948 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2949 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2950 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2952 WCHAR
*lookup
, *ret
= NULL
;
2953 UNICODE_STRING lookup_us
;
2955 const WCHAR
*lang
= ai
->language
;
2956 unsigned int data_pos
= 0, data_len
;
2959 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2960 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2961 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2962 + sizeof(lookup_fmtW
) )))
2965 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2966 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2967 ai
->version
.major
, ai
->version
.minor
, lang
);
2968 RtlInitUnicodeString( &lookup_us
, lookup
);
2970 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2971 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
2973 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2974 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2976 ULONG build
, revision
;
2978 data_len
= io
.Information
;
2982 if (data_pos
>= data_len
)
2984 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2985 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
2987 data_len
= io
.Information
;
2990 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2992 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2993 else data_pos
= data_len
;
2995 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2997 if (build
< min_build
) continue;
2998 tmp
= strchrW(tmp
, '.') + 1;
2999 revision
= atoiW(tmp
);
3000 if (build
== min_build
&& revision
< min_revision
) continue;
3001 tmp
= strchrW(tmp
, '_') + 1;
3002 tmp
= strchrW(tmp
, '_') + 1;
3003 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3004 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
3006 /* prefer a non-Wine manifest if we already have one */
3007 /* we'll still load the builtin dll if specified through DllOverrides */
3013 min_revision
= revision
;
3015 ai
->version
.build
= build
;
3016 ai
->version
.revision
= revision
;
3017 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3018 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3020 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3021 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3025 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3026 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3030 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3032 struct assembly_identity sxs_ai
;
3033 UNICODE_STRING path_us
;
3034 OBJECT_ATTRIBUTES attr
;
3036 WCHAR
*path
, *file
= NULL
;
3039 static const WCHAR manifest_dirW
[] =
3040 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3042 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3044 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
3045 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
3046 return STATUS_NO_MEMORY
;
3048 strcpyW( path
, user_shared_data
->NtSystemRoot
);
3049 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
3051 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3053 RtlFreeHeap( GetProcessHeap(), 0, path
);
3054 return STATUS_NO_SUCH_FILE
;
3056 RtlFreeHeap( GetProcessHeap(), 0, path
);
3058 attr
.Length
= sizeof(attr
);
3059 attr
.RootDirectory
= 0;
3060 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3061 attr
.ObjectName
= &path_us
;
3062 attr
.SecurityDescriptor
= NULL
;
3063 attr
.SecurityQualityOfService
= NULL
;
3065 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3066 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3069 file
= lookup_manifest_file( handle
, &sxs_ai
);
3074 RtlFreeUnicodeString( &path_us
);
3075 return STATUS_NO_SUCH_FILE
;
3078 /* append file name to directory path */
3079 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3080 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
3082 RtlFreeHeap( GetProcessHeap(), 0, file
);
3083 RtlFreeUnicodeString( &path_us
);
3084 return STATUS_NO_MEMORY
;
3087 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3088 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3089 RtlInitUnicodeString( &path_us
, path
);
3090 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
3092 if (!open_nt_file( &handle
, &path_us
))
3094 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3097 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3099 RtlFreeHeap( GetProcessHeap(), 0, file
);
3100 RtlFreeUnicodeString( &path_us
);
3104 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3105 struct assembly_identity
* ai
)
3107 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3109 WCHAR
*buffer
, *p
, *directory
;
3111 UNICODE_STRING nameW
;
3115 TRACE( "looking for name=%s version=%s arch=%s\n",
3116 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3118 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3120 /* FIXME: add support for language specific lookup */
3122 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3123 strlenW(acl
->actctx
->appdir
.info
));
3125 nameW
.Buffer
= NULL
;
3126 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3127 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3128 return STATUS_NO_MEMORY
;
3130 if (!(directory
= build_assembly_dir( ai
)))
3132 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3133 return STATUS_NO_MEMORY
;
3136 /* Lookup in <dir>\name.dll
3137 * <dir>\name.manifest
3138 * <dir>\name\name.dll
3139 * <dir>\name\name.manifest
3141 * First 'appdir' is used as <dir>, if that failed
3142 * it tries application manifest file path.
3144 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3145 p
= buffer
+ strlenW(buffer
);
3146 for (i
= 0; i
< 4; i
++)
3150 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3151 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3155 strcpyW( p
, ai
->name
);
3158 strcpyW( p
, dotDllW
);
3159 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3161 status
= open_nt_file( &file
, &nameW
);
3164 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3165 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3169 RtlFreeUnicodeString( &nameW
);
3172 strcpyW( p
, dotManifestW
);
3173 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3175 status
= open_nt_file( &file
, &nameW
);
3178 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3182 RtlFreeUnicodeString( &nameW
);
3184 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3186 RtlFreeUnicodeString( &nameW
);
3187 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3188 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3192 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3194 NTSTATUS status
= STATUS_SUCCESS
;
3197 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3199 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3201 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3203 FIXME( "Could not find dependent assembly %s (%s)\n",
3204 debugstr_w(acl
->dependencies
[i
].name
),
3205 debugstr_version(&acl
->dependencies
[i
].version
) );
3206 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3211 /* FIXME should now iterate through all refs */
3215 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3216 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3218 NTSTATUS status
= STATUS_SUCCESS
;
3220 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3222 if (*handle
) return STATUS_INVALID_PARAMETER
;
3224 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3225 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3227 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3232 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3234 LdrLockLoaderLock( 0, NULL
, &magic
);
3235 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3237 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
3238 status
= STATUS_DLL_NOT_FOUND
;
3240 *handle
= pldr
->ActivationContext
;
3242 else status
= STATUS_DLL_NOT_FOUND
;
3243 LdrUnlockLoaderLock( 0, magic
);
3245 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3246 *handle
= process_actctx
;
3251 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3253 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3254 struct strsection_header
*header
;
3255 struct dllredirect_data
*data
;
3256 struct string_index
*index
;
3259 /* compute section length */
3260 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3262 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3263 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3265 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3267 /* each entry needs index, data and string data */
3268 total_len
+= sizeof(*index
);
3269 total_len
+= sizeof(*data
);
3270 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3273 dll_count
+= assembly
->num_dlls
;
3276 total_len
+= sizeof(*header
);
3278 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3279 if (!header
) return STATUS_NO_MEMORY
;
3281 memset(header
, 0, sizeof(*header
));
3282 header
->magic
= STRSECTION_MAGIC
;
3283 header
->size
= sizeof(*header
);
3284 header
->count
= dll_count
;
3285 header
->index_offset
= sizeof(*header
);
3286 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3287 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3289 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3291 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3292 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3294 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3298 /* setup new index entry */
3299 str
.Buffer
= dll
->name
;
3300 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3301 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3302 /* hash original class name */
3303 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3305 index
->name_offset
= name_offset
;
3306 index
->name_len
= str
.Length
;
3307 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3308 index
->data_len
= sizeof(*data
);
3309 index
->rosterindex
= i
+ 1;
3312 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3313 data
->size
= sizeof(*data
);
3314 data
->unk
= 2; /* FIXME: seems to be constant */
3315 memset(data
->res
, 0, sizeof(data
->res
));
3318 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3319 memcpy(ptrW
, dll
->name
, index
->name_len
);
3320 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3322 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3330 return STATUS_SUCCESS
;
3333 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3335 struct string_index
*iter
, *index
= NULL
;
3338 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3339 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3341 for (i
= 0; i
< section
->count
; i
++)
3343 if (iter
->hash
== hash
)
3345 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3347 if (!strcmpiW(nameW
, name
->Buffer
))
3353 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3361 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3363 struct guid_index
*iter
, *index
= NULL
;
3366 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3368 for (i
= 0; i
< section
->count
; i
++)
3370 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3381 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3383 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3386 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3387 PACTCTX_SECTION_KEYED_DATA data
)
3389 struct dllredirect_data
*dll
;
3390 struct string_index
*index
;
3392 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3394 if (!actctx
->dllredirect_section
)
3396 struct strsection_header
*section
;
3398 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3399 if (status
) return status
;
3401 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3402 RtlFreeHeap(GetProcessHeap(), 0, section
);
3405 index
= find_string_index(actctx
->dllredirect_section
, name
);
3406 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3410 dll
= get_dllredirect_data(actctx
, index
);
3412 data
->ulDataFormatVersion
= 1;
3414 data
->ulLength
= dll
->size
;
3415 data
->lpSectionGlobalData
= NULL
;
3416 data
->ulSectionGlobalDataLength
= 0;
3417 data
->lpSectionBase
= actctx
->dllredirect_section
;
3418 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3419 data
->hActCtx
= NULL
;
3421 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3422 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3425 return STATUS_SUCCESS
;
3428 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3430 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3433 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3435 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3438 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3440 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3441 struct wndclass_redirect_data
*data
;
3442 struct strsection_header
*header
;
3443 struct string_index
*index
;
3446 /* compute section length */
3447 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3449 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3450 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3452 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3453 for (k
= 0; k
< dll
->entities
.num
; k
++)
3455 struct entity
*entity
= &dll
->entities
.base
[k
];
3456 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3458 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3461 /* each class entry needs index, data and string data */
3462 total_len
+= sizeof(*index
);
3463 total_len
+= sizeof(*data
);
3464 /* original name is stored separately */
3465 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3466 /* versioned name and module name are stored one after another */
3467 if (entity
->u
.class.versioned
)
3468 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3471 len
+= strlenW(dll
->name
) + 1;
3472 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3480 total_len
+= sizeof(*header
);
3482 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3483 if (!header
) return STATUS_NO_MEMORY
;
3485 memset(header
, 0, sizeof(*header
));
3486 header
->magic
= STRSECTION_MAGIC
;
3487 header
->size
= sizeof(*header
);
3488 header
->count
= class_count
;
3489 header
->index_offset
= sizeof(*header
);
3490 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3491 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3493 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3495 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3496 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3498 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3499 for (k
= 0; k
< dll
->entities
.num
; k
++)
3501 struct entity
*entity
= &dll
->entities
.base
[k
];
3502 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3504 static const WCHAR exclW
[] = {'!',0};
3505 ULONG versioned_len
, module_len
;
3509 /* setup new index entry */
3510 str
.Buffer
= entity
->u
.class.name
;
3511 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3512 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3513 /* hash original class name */
3514 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3516 /* include '!' separator too */
3517 if (entity
->u
.class.versioned
)
3518 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3520 versioned_len
= str
.Length
;
3521 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3523 index
->name_offset
= name_offset
;
3524 index
->name_len
= str
.Length
;
3525 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3526 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3527 index
->rosterindex
= i
+ 1;
3530 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3531 data
->size
= sizeof(*data
);
3533 data
->name_len
= versioned_len
;
3534 data
->name_offset
= sizeof(*data
);
3535 data
->module_len
= module_len
;
3536 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3538 /* original class name */
3539 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3540 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3541 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3544 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3545 memcpy(ptrW
, dll
->name
, data
->module_len
);
3546 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3548 /* versioned name */
3549 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3550 if (entity
->u
.class.versioned
)
3552 get_assembly_version(assembly
, ptrW
);
3553 strcatW(ptrW
, exclW
);
3554 strcatW(ptrW
, entity
->u
.class.name
);
3558 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3559 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3562 name_offset
+= sizeof(*data
);
3563 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3573 return STATUS_SUCCESS
;
3576 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3577 PACTCTX_SECTION_KEYED_DATA data
)
3579 struct string_index
*iter
, *index
= NULL
;
3580 struct wndclass_redirect_data
*class;
3584 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3586 if (!actctx
->wndclass_section
)
3588 struct strsection_header
*section
;
3590 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3591 if (status
) return status
;
3593 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3594 RtlFreeHeap(GetProcessHeap(), 0, section
);
3598 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3599 iter
= get_wndclass_first_index(actctx
);
3601 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3603 if (iter
->hash
== hash
)
3605 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3607 if (!strcmpiW(nameW
, name
->Buffer
))
3613 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3618 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3622 class = get_wndclass_data(actctx
, index
);
3624 data
->ulDataFormatVersion
= 1;
3625 data
->lpData
= class;
3626 /* full length includes string length with nulls */
3627 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3628 data
->lpSectionGlobalData
= NULL
;
3629 data
->ulSectionGlobalDataLength
= 0;
3630 data
->lpSectionBase
= actctx
->wndclass_section
;
3631 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3632 data
->hActCtx
= NULL
;
3634 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3635 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3638 return STATUS_SUCCESS
;
3641 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3643 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3644 struct guidsection_header
*header
;
3645 ULONG module_offset
, data_offset
;
3646 struct tlibredirect_data
*data
;
3647 struct guid_index
*index
;
3649 /* compute section length */
3650 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3652 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3653 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3655 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3656 for (k
= 0; k
< dll
->entities
.num
; k
++)
3658 struct entity
*entity
= &dll
->entities
.base
[k
];
3659 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3661 /* each entry needs index, data and string data for module name and help string */
3662 total_len
+= sizeof(*index
);
3663 total_len
+= sizeof(*data
);
3664 /* help string is stored separately */
3665 if (*entity
->u
.typelib
.helpdir
)
3666 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3668 /* module names are packed one after another */
3669 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3677 total_len
+= aligned_string_len(names_len
);
3678 total_len
+= sizeof(*header
);
3680 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3681 if (!header
) return STATUS_NO_MEMORY
;
3683 memset(header
, 0, sizeof(*header
));
3684 header
->magic
= GUIDSECTION_MAGIC
;
3685 header
->size
= sizeof(*header
);
3686 header
->count
= tlib_count
;
3687 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3688 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3689 module_offset
= sizeof(*header
);
3690 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3692 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3694 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3695 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3697 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3698 for (k
= 0; k
< dll
->entities
.num
; k
++)
3700 struct entity
*entity
= &dll
->entities
.base
[k
];
3701 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3703 ULONG module_len
, help_len
;
3707 if (*entity
->u
.typelib
.helpdir
)
3708 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3712 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3714 /* setup new index entry */
3715 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3716 RtlGUIDFromString(&str
, &index
->guid
);
3717 index
->data_offset
= data_offset
;
3718 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3719 index
->rosterindex
= i
+ 1;
3722 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3723 data
->size
= sizeof(*data
);
3725 data
->name_len
= module_len
;
3726 data
->name_offset
= module_offset
;
3727 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3729 data
->flags
= entity
->u
.typelib
.flags
;
3730 data
->help_len
= help_len
;
3731 data
->help_offset
= sizeof(*data
);
3732 data
->major_version
= entity
->u
.typelib
.major
;
3733 data
->minor_version
= entity
->u
.typelib
.minor
;
3736 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3737 memcpy(ptrW
, dll
->name
, data
->name_len
);
3738 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3743 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3744 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3745 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3748 data_offset
+= sizeof(*data
);
3750 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3752 module_offset
+= module_len
+ sizeof(WCHAR
);
3762 return STATUS_SUCCESS
;
3765 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3767 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3770 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3772 struct guid_index
*index
= NULL
;
3773 struct tlibredirect_data
*tlib
;
3775 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3777 if (!actctx
->tlib_section
)
3779 struct guidsection_header
*section
;
3781 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3782 if (status
) return status
;
3784 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3785 RtlFreeHeap(GetProcessHeap(), 0, section
);
3788 index
= find_guid_index(actctx
->tlib_section
, guid
);
3789 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3791 tlib
= get_tlib_data(actctx
, index
);
3793 data
->ulDataFormatVersion
= 1;
3794 data
->lpData
= tlib
;
3795 /* full length includes string length with nulls */
3796 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3797 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3798 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3799 data
->lpSectionBase
= actctx
->tlib_section
;
3800 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3801 data
->hActCtx
= NULL
;
3803 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3804 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3806 return STATUS_SUCCESS
;
3809 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3811 ULONG
*ptr
= (ULONG
*)guid
;
3814 /* GUID is 16 bytes long */
3815 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3816 *ptr
= RtlUniform(seed
);
3818 guid
->Data3
&= 0x0fff;
3819 guid
->Data3
|= (4 << 12);
3820 guid
->Data4
[0] &= 0x3f;
3821 guid
->Data4
[0] |= 0x80;
3824 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3825 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3829 for (i
= 0; i
< entities
->num
; i
++)
3831 struct entity
*entity
= &entities
->base
[i
];
3832 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3834 /* each entry needs two index entries, extra one goes for alias GUID */
3835 *len
+= 2*sizeof(struct guid_index
);
3836 /* To save some memory we don't allocated two data structures,
3837 instead alias index and normal index point to the same data structure. */
3838 *len
+= sizeof(struct comclassredirect_data
);
3840 /* for clrClass store some more */
3841 if (entity
->u
.comclass
.name
)
3843 unsigned int str_len
;
3845 /* all string data is stored together in aligned block */
3846 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3847 if (entity
->u
.comclass
.progid
)
3848 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3849 if (entity
->u
.comclass
.version
)
3850 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3852 *len
+= sizeof(struct clrclass_data
);
3853 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3855 /* module name is forced to mscoree.dll, and stored two times with different case */
3856 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3860 /* progid string is stored separately */
3861 if (entity
->u
.comclass
.progid
)
3862 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3864 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3872 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3873 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3874 ULONG
*seed
, ULONG rosterindex
)
3878 for (i
= 0; i
< entities
->num
; i
++)
3880 struct entity
*entity
= &entities
->base
[i
];
3881 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3883 ULONG module_len
, progid_len
, str_len
= 0;
3884 struct comclassredirect_data
*data
;
3885 struct guid_index
*alias_index
;
3886 struct clrclass_data
*clrdata
;
3890 if (entity
->u
.comclass
.progid
)
3891 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3895 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3897 /* setup new index entry */
3898 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3899 RtlGUIDFromString(&str
, &(*index
)->guid
);
3901 (*index
)->data_offset
= *data_offset
;
3902 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3903 (*index
)->rosterindex
= rosterindex
;
3905 /* Setup new index entry for alias guid. Alias index records are placed after
3906 normal records, so normal guids are hit first on search. Note that class count
3908 alias_index
= (*index
) + section
->count
/2;
3909 generate_uuid(seed
, &alias_index
->guid
);
3910 alias_index
->data_offset
= (*index
)->data_offset
;
3911 alias_index
->data_len
= 0;
3912 alias_index
->rosterindex
= (*index
)->rosterindex
;
3915 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3916 data
->size
= sizeof(*data
);
3920 data
->model
= entity
->u
.comclass
.model
;
3921 data
->clsid
= (*index
)->guid
;
3922 data
->alias
= alias_index
->guid
;
3923 data
->clsid2
= data
->clsid
;
3924 if (entity
->u
.comclass
.tlbid
)
3926 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3927 RtlGUIDFromString(&str
, &data
->tlbid
);
3930 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3931 data
->name_len
= module_len
;
3932 data
->name_offset
= *module_offset
;
3933 data
->progid_len
= progid_len
;
3934 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3935 data
->clrdata_len
= 0; /* will be set later */
3936 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3937 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3938 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3939 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3940 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3941 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3943 /* mask describes which misc* data is available */
3945 if (data
->miscstatus
)
3946 data
->miscmask
|= MiscStatus
;
3947 if (data
->miscstatuscontent
)
3948 data
->miscmask
|= MiscStatusContent
;
3949 if (data
->miscstatusthumbnail
)
3950 data
->miscmask
|= MiscStatusThumbnail
;
3951 if (data
->miscstatusicon
)
3952 data
->miscmask
|= MiscStatusIcon
;
3953 if (data
->miscstatusdocprint
)
3954 data
->miscmask
|= MiscStatusDocPrint
;
3956 if (data
->clrdata_offset
)
3958 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3960 clrdata
->size
= sizeof(*clrdata
);
3961 clrdata
->res
[0] = 0;
3962 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3963 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3964 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3965 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3966 clrdata
->name_offset
= clrdata
->size
;
3967 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3968 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3969 clrdata
->res2
[0] = 0;
3970 clrdata
->res2
[1] = 0;
3972 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3975 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3976 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3977 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3979 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3980 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3981 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3984 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3985 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3986 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3988 /* runtime version, optional */
3989 if (clrdata
->version_len
)
3991 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3993 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3994 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3995 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3998 if (data
->progid_len
)
3999 data
->progid_offset
+= data
->clrdata_len
;
4000 (*index
)->data_len
+= sizeof(*clrdata
);
4007 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4008 memcpy(ptrW
, dll
->name
, data
->name_len
);
4009 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4013 if (data
->progid_len
)
4015 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4016 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4017 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4020 /* string block length */
4024 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4025 if (clrdata
->version_len
)
4026 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4029 str_len
+= progid_len
+ sizeof(WCHAR
);
4031 (*index
)->data_len
+= aligned_string_len(str_len
);
4032 alias_index
->data_len
= (*index
)->data_len
;
4034 /* move to next data record */
4035 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4036 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4040 (*data_offset
) += sizeof(*clrdata
);
4041 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4048 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4050 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4051 struct guidsection_header
*header
;
4052 ULONG module_offset
, data_offset
;
4053 struct guid_index
*index
;
4056 /* compute section length */
4057 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4059 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4060 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4061 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4063 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4064 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4068 total_len
+= aligned_string_len(names_len
);
4069 total_len
+= sizeof(*header
);
4071 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4072 if (!header
) return STATUS_NO_MEMORY
;
4074 memset(header
, 0, sizeof(*header
));
4075 header
->magic
= GUIDSECTION_MAGIC
;
4076 header
->size
= sizeof(*header
);
4077 header
->count
= 2*class_count
;
4078 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4079 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4080 module_offset
= sizeof(*header
);
4081 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4083 seed
= NtGetTickCount();
4084 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4086 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4087 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4088 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4090 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4091 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4097 return STATUS_SUCCESS
;
4100 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4102 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4105 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4107 struct comclassredirect_data
*comclass
;
4108 struct guid_index
*index
= NULL
;
4110 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4112 if (!actctx
->comserver_section
)
4114 struct guidsection_header
*section
;
4116 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4117 if (status
) return status
;
4119 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4120 RtlFreeHeap(GetProcessHeap(), 0, section
);
4123 index
= find_guid_index(actctx
->comserver_section
, guid
);
4124 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4126 comclass
= get_comclass_data(actctx
, index
);
4128 data
->ulDataFormatVersion
= 1;
4129 data
->lpData
= comclass
;
4130 /* full length includes string length with nulls */
4131 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4132 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4133 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4134 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4135 data
->lpSectionBase
= actctx
->comserver_section
;
4136 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4137 data
->hActCtx
= NULL
;
4139 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4140 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4142 return STATUS_SUCCESS
;
4145 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4149 for (i
= 0; i
< entities
->num
; i
++)
4151 struct entity
*entity
= &entities
->base
[i
];
4152 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4154 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4155 if (entity
->u
.ifaceps
.name
)
4156 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4162 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4163 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4167 for (i
= 0; i
< entities
->num
; i
++)
4169 struct entity
*entity
= &entities
->base
[i
];
4170 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4172 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4176 if (entity
->u
.ifaceps
.name
)
4177 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4182 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4183 RtlGUIDFromString(&str
, &(*index
)->guid
);
4184 (*index
)->data_offset
= *data_offset
;
4185 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4186 (*index
)->rosterindex
= rosterindex
;
4188 /* setup data record */
4189 data
->size
= sizeof(*data
);
4190 data
->mask
= entity
->u
.ifaceps
.mask
;
4192 /* proxyStubClsid32 value is only stored for external PS,
4193 if set it's used as iid, otherwise 'iid' attribute value is used */
4194 if (entity
->u
.ifaceps
.ps32
)
4196 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4197 RtlGUIDFromString(&str
, &data
->iid
);
4200 data
->iid
= (*index
)->guid
;
4202 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4204 if (entity
->u
.ifaceps
.tlib
)
4206 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4207 RtlGUIDFromString(&str
, &data
->tlbid
);
4210 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4212 if (entity
->u
.ifaceps
.base
)
4214 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4215 RtlGUIDFromString(&str
, &data
->base
);
4218 memset(&data
->base
, 0, sizeof(data
->base
));
4220 data
->name_len
= name_len
;
4221 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4226 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4227 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4228 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4231 /* move to next record */
4233 *data_offset
+= sizeof(*data
);
4235 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4240 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4242 unsigned int i
, j
, total_len
= 0, count
= 0;
4243 struct guidsection_header
*header
;
4244 struct guid_index
*index
;
4247 /* compute section length */
4248 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4250 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4252 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4253 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4255 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4256 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4260 total_len
+= sizeof(*header
);
4262 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4263 if (!header
) return STATUS_NO_MEMORY
;
4265 memset(header
, 0, sizeof(*header
));
4266 header
->magic
= GUIDSECTION_MAGIC
;
4267 header
->size
= sizeof(*header
);
4268 header
->count
= count
;
4269 header
->index_offset
= sizeof(*header
);
4270 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4271 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4273 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4275 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4277 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4278 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4280 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4281 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4287 return STATUS_SUCCESS
;
4290 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4292 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4295 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4297 struct ifacepsredirect_data
*iface
;
4298 struct guid_index
*index
= NULL
;
4300 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4302 if (!actctx
->ifaceps_section
)
4304 struct guidsection_header
*section
;
4306 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4307 if (status
) return status
;
4309 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4310 RtlFreeHeap(GetProcessHeap(), 0, section
);
4313 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4314 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4316 iface
= get_ifaceps_data(actctx
, index
);
4318 data
->ulDataFormatVersion
= 1;
4319 data
->lpData
= iface
;
4320 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4321 data
->lpSectionGlobalData
= NULL
;
4322 data
->ulSectionGlobalDataLength
= 0;
4323 data
->lpSectionBase
= actctx
->ifaceps_section
;
4324 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4325 data
->hActCtx
= NULL
;
4327 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4328 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4330 return STATUS_SUCCESS
;
4333 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4335 unsigned int i
, j
, total_len
= 0, count
= 0;
4336 struct guidsection_header
*header
;
4337 struct clrsurrogate_data
*data
;
4338 struct guid_index
*index
;
4341 /* compute section length */
4342 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4344 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4345 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4347 struct entity
*entity
= &assembly
->entities
.base
[j
];
4348 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4352 total_len
+= sizeof(*index
) + sizeof(*data
);
4353 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4354 if (entity
->u
.clrsurrogate
.version
)
4355 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4356 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4363 total_len
+= sizeof(*header
);
4365 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4366 if (!header
) return STATUS_NO_MEMORY
;
4368 memset(header
, 0, sizeof(*header
));
4369 header
->magic
= GUIDSECTION_MAGIC
;
4370 header
->size
= sizeof(*header
);
4371 header
->count
= count
;
4372 header
->index_offset
= sizeof(*header
);
4373 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4374 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4376 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4378 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4379 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4381 struct entity
*entity
= &assembly
->entities
.base
[j
];
4382 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4384 ULONG version_len
, name_len
;
4388 if (entity
->u
.clrsurrogate
.version
)
4389 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4392 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4394 /* setup new index entry */
4395 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4396 RtlGUIDFromString(&str
, &index
->guid
);
4398 index
->data_offset
= data_offset
;
4399 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4400 index
->rosterindex
= i
+ 1;
4403 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4404 data
->size
= sizeof(*data
);
4406 data
->clsid
= index
->guid
;
4407 data
->version_offset
= version_len
? data
->size
: 0;
4408 data
->version_len
= version_len
;
4409 data
->name_offset
= data
->size
+ version_len
;
4411 data
->name_offset
+= sizeof(WCHAR
);
4412 data
->name_len
= name_len
;
4414 /* surrogate name */
4415 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4416 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4417 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4419 /* runtime version */
4420 if (data
->version_len
)
4422 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4423 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4424 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4427 data_offset
+= index
->data_offset
;
4435 return STATUS_SUCCESS
;
4438 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4440 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4443 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4445 struct clrsurrogate_data
*surrogate
;
4446 struct guid_index
*index
= NULL
;
4448 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4450 if (!actctx
->clrsurrogate_section
)
4452 struct guidsection_header
*section
;
4454 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4455 if (status
) return status
;
4457 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4458 RtlFreeHeap(GetProcessHeap(), 0, section
);
4461 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4462 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4464 surrogate
= get_surrogate_data(actctx
, index
);
4466 data
->ulDataFormatVersion
= 1;
4467 data
->lpData
= surrogate
;
4468 /* full length includes string length with nulls */
4469 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4470 if (surrogate
->version_len
)
4471 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4473 data
->lpSectionGlobalData
= NULL
;
4474 data
->ulSectionGlobalDataLength
= 0;
4475 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4476 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4477 data
->hActCtx
= NULL
;
4479 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4480 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4482 return STATUS_SUCCESS
;
4485 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4487 unsigned int i
, j
, single_len
;
4489 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4490 for (i
= 0; i
< entities
->num
; i
++)
4492 struct entity
*entity
= &entities
->base
[i
];
4493 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4495 if (entity
->u
.comclass
.progid
)
4497 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4501 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4502 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4504 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4505 *count
+= entity
->u
.comclass
.progids
.num
;
4510 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4511 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4513 struct progidredirect_data
*data
;
4518 /* setup new index entry */
4520 /* hash progid name */
4521 RtlInitUnicodeString(&str
, progid
);
4522 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4524 (*index
)->name_offset
= *data_offset
;
4525 (*index
)->name_len
= str
.Length
;
4526 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4527 (*index
)->data_len
= sizeof(*data
);
4528 (*index
)->rosterindex
= rosterindex
;
4530 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4532 /* setup data structure */
4533 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4534 data
->size
= sizeof(*data
);
4536 data
->clsid_offset
= *global_offset
;
4538 /* write progid string */
4539 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4540 memcpy(ptrW
, progid
, (*index
)->name_len
);
4541 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4543 /* write guid to global area */
4544 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4548 *global_offset
+= sizeof(GUID
);
4549 *data_offset
+= data
->size
;
4553 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4554 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4558 for (i
= 0; i
< entities
->num
; i
++)
4560 struct entity
*entity
= &entities
->base
[i
];
4561 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4563 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4564 struct comclassredirect_data
*comclass
;
4565 struct guid_index
*guid_index
;
4569 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4570 RtlGUIDFromString(&str
, &clsid
);
4572 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4573 comclass
= get_comclass_data(actctx
, guid_index
);
4575 if (entity
->u
.comclass
.progid
)
4576 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4577 index
, data_offset
, global_offset
, rosterindex
);
4579 for (j
= 0; j
< progids
->num
; j
++)
4580 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4581 index
, data_offset
, global_offset
, rosterindex
);
4586 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4588 unsigned int i
, j
, total_len
= 0, count
= 0;
4589 struct strsection_header
*header
;
4590 ULONG data_offset
, global_offset
;
4591 struct string_index
*index
;
4593 /* compute section length */
4594 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4596 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4598 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4599 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4601 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4602 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4606 total_len
+= sizeof(*header
);
4608 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4609 if (!header
) return STATUS_NO_MEMORY
;
4611 memset(header
, 0, sizeof(*header
));
4612 header
->magic
= STRSECTION_MAGIC
;
4613 header
->size
= sizeof(*header
);
4614 header
->count
= count
;
4615 header
->global_offset
= header
->size
;
4616 header
->global_len
= count
*sizeof(GUID
);
4617 header
->index_offset
= header
->size
+ header
->global_len
;
4619 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4620 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4621 global_offset
= header
->global_offset
;
4623 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4625 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4627 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4628 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4630 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4631 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4637 return STATUS_SUCCESS
;
4640 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4642 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4645 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4646 PACTCTX_SECTION_KEYED_DATA data
)
4648 struct progidredirect_data
*progid
;
4649 struct string_index
*index
;
4651 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4653 if (!actctx
->comserver_section
)
4655 struct guidsection_header
*section
;
4657 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4658 if (status
) return status
;
4660 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4661 RtlFreeHeap(GetProcessHeap(), 0, section
);
4664 if (!actctx
->progid_section
)
4666 struct strsection_header
*section
;
4668 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4669 if (status
) return status
;
4671 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4672 RtlFreeHeap(GetProcessHeap(), 0, section
);
4675 index
= find_string_index(actctx
->progid_section
, name
);
4676 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4680 progid
= get_progid_data(actctx
, index
);
4682 data
->ulDataFormatVersion
= 1;
4683 data
->lpData
= progid
;
4684 data
->ulLength
= progid
->size
;
4685 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4686 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4687 data
->lpSectionBase
= actctx
->progid_section
;
4688 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4689 data
->hActCtx
= NULL
;
4691 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4692 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4695 return STATUS_SUCCESS
;
4698 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4699 const UNICODE_STRING
*section_name
,
4700 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4704 switch (section_kind
)
4706 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4707 status
= find_dll_redirection(actctx
, section_name
, data
);
4709 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4710 status
= find_window_class(actctx
, section_name
, data
);
4712 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4713 status
= find_progid_redirection(actctx
, section_name
, data
);
4715 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4716 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4717 return STATUS_SXS_SECTION_NOT_FOUND
;
4719 WARN("Unknown section_kind %x\n", section_kind
);
4720 return STATUS_SXS_SECTION_NOT_FOUND
;
4723 if (status
!= STATUS_SUCCESS
) return status
;
4725 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4727 actctx_addref(actctx
);
4728 data
->hActCtx
= actctx
;
4730 return STATUS_SUCCESS
;
4733 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4734 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4738 switch (section_kind
)
4740 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4741 status
= find_tlib_redirection(actctx
, guid
, data
);
4743 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4744 status
= find_comserver_redirection(actctx
, guid
, data
);
4746 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4747 status
= find_cominterface_redirection(actctx
, guid
, data
);
4749 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4750 status
= find_clr_surrogate(actctx
, guid
, data
);
4753 WARN("Unknown section_kind %x\n", section_kind
);
4754 return STATUS_SXS_SECTION_NOT_FOUND
;
4757 if (status
!= STATUS_SUCCESS
) return status
;
4759 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4761 actctx_addref(actctx
);
4762 data
->hActCtx
= actctx
;
4764 return STATUS_SUCCESS
;
4767 /* initialize the activation context for the current process */
4768 void actctx_init(void)
4773 ctx
.cbSize
= sizeof(ctx
);
4774 ctx
.lpSource
= NULL
;
4775 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4776 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4777 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4779 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4783 /***********************************************************************
4784 * RtlCreateActivationContext (NTDLL.@)
4786 * Create an activation context.
4788 * FIXME: function signature/prototype is wrong
4790 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4792 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4793 const WCHAR
*directory
= NULL
;
4794 ACTIVATION_CONTEXT
*actctx
;
4795 UNICODE_STRING nameW
;
4797 NTSTATUS status
= STATUS_NO_MEMORY
;
4799 struct actctx_loader acl
;
4801 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4803 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4804 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4805 return STATUS_INVALID_PARAMETER
;
4807 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4808 return STATUS_NO_MEMORY
;
4810 actctx
->magic
= ACTCTX_MAGIC
;
4811 actctx
->ref_count
= 1;
4812 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4813 actctx
->config
.info
= NULL
;
4814 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4815 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4817 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4825 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4826 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4828 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4829 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4830 actctx
->appdir
.info
= dir
.Buffer
;
4833 nameW
.Buffer
= NULL
;
4835 /* open file only if it's going to be used */
4836 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4837 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4839 WCHAR
*source
= NULL
;
4842 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4843 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
4845 DWORD dir_len
, source_len
;
4847 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4848 source_len
= strlenW(pActCtx
->lpSource
);
4849 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4851 status
= STATUS_NO_MEMORY
;
4855 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4856 source
[dir_len
] = '\\';
4857 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4860 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4861 RtlFreeHeap( GetProcessHeap(), 0, source
);
4864 status
= STATUS_NO_SUCH_FILE
;
4867 status
= open_nt_file( &file
, &nameW
);
4870 RtlFreeUnicodeString( &nameW
);
4875 acl
.actctx
= actctx
;
4876 acl
.dependencies
= NULL
;
4877 acl
.num_dependencies
= 0;
4878 acl
.allocated_dependencies
= 0;
4880 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4881 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4883 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4885 /* if we have a resource it's a PE file */
4886 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4888 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4889 pActCtx
->lpResourceName
, lang
);
4890 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4891 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4892 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4894 else if (pActCtx
->lpSource
)
4896 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4897 file
, pActCtx
->lpResourceName
, lang
);
4898 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4899 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4900 NULL
, pActCtx
->lpResourceName
);
4902 else status
= STATUS_INVALID_PARAMETER
;
4906 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4909 if (file
) NtClose( file
);
4910 RtlFreeUnicodeString( &nameW
);
4912 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4913 free_depend_manifests( &acl
);
4915 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4916 else actctx_release( actctx
);
4920 if (file
) NtClose( file
);
4921 actctx_release( actctx
);
4926 /***********************************************************************
4927 * RtlAddRefActivationContext (NTDLL.@)
4929 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4931 ACTIVATION_CONTEXT
*actctx
;
4933 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4937 /******************************************************************
4938 * RtlReleaseActivationContext (NTDLL.@)
4940 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
4942 ACTIVATION_CONTEXT
*actctx
;
4944 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4947 /******************************************************************
4948 * RtlZombifyActivationContext (NTDLL.@)
4950 * FIXME: function prototype might be wrong
4952 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
4954 FIXME("%p: stub\n", handle
);
4955 return STATUS_NOT_IMPLEMENTED
;
4958 /******************************************************************
4959 * RtlActivateActivationContext (NTDLL.@)
4961 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
4963 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4965 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
4966 return STATUS_NO_MEMORY
;
4968 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4969 frame
->ActivationContext
= handle
;
4971 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
4972 RtlAddRefActivationContext( handle
);
4974 *cookie
= (ULONG_PTR
)frame
;
4975 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
4976 return STATUS_SUCCESS
;
4980 /***********************************************************************
4981 * RtlDeactivateActivationContext (NTDLL.@)
4983 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4985 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4987 TRACE( "%x cookie=%lx\n", flags
, cookie
);
4989 /* find the right frame */
4990 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4991 for (frame
= top
; frame
; frame
= frame
->Previous
)
4992 if ((ULONG_PTR
)frame
== cookie
) break;
4995 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4997 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
4998 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5000 /* pop everything up to and including frame */
5001 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5003 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5005 frame
= top
->Previous
;
5006 RtlReleaseActivationContext( top
->ActivationContext
);
5007 RtlFreeHeap( GetProcessHeap(), 0, top
);
5013 /******************************************************************
5014 * RtlFreeThreadActivationContextStack (NTDLL.@)
5016 void WINAPI
RtlFreeThreadActivationContextStack(void)
5018 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5020 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5023 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5024 RtlReleaseActivationContext( frame
->ActivationContext
);
5025 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5028 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5032 /******************************************************************
5033 * RtlGetActiveActivationContext (NTDLL.@)
5035 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5037 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5039 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5040 RtlAddRefActivationContext( *handle
);
5045 return STATUS_SUCCESS
;
5049 /******************************************************************
5050 * RtlIsActivationContextActive (NTDLL.@)
5052 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5054 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5056 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5057 if (frame
->ActivationContext
== handle
) return TRUE
;
5062 /***********************************************************************
5063 * RtlQueryInformationActivationContext (NTDLL.@)
5065 * Get information about an activation context.
5066 * FIXME: function signature/prototype may be wrong
5068 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5069 ULONG
class, PVOID buffer
,
5070 SIZE_T bufsize
, SIZE_T
*retlen
)
5072 ACTIVATION_CONTEXT
*actctx
;
5075 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5076 subinst
, class, buffer
, bufsize
, retlen
);
5078 if (retlen
) *retlen
= 0;
5079 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5083 case ActivationContextBasicInformation
:
5085 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5087 if (retlen
) *retlen
= sizeof(*info
);
5088 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5090 info
->hActCtx
= handle
;
5091 info
->dwFlags
= 0; /* FIXME */
5092 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5096 case ActivationContextDetailedInformation
:
5098 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5099 struct assembly
*assembly
= NULL
;
5100 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5103 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5105 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5107 if (assembly
&& assembly
->manifest
.info
)
5108 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5109 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5110 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5111 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5113 if (retlen
) *retlen
= len
;
5114 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5117 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5118 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5119 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5120 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5121 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5122 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5123 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5124 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5125 ptr
= (LPWSTR
)(acdi
+ 1);
5128 acdi
->lpRootManifestPath
= ptr
;
5129 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5130 ptr
+= manifest_len
;
5132 else acdi
->lpRootManifestPath
= NULL
;
5135 acdi
->lpRootConfigurationPath
= ptr
;
5136 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5139 else acdi
->lpRootConfigurationPath
= NULL
;
5142 acdi
->lpAppDirPath
= ptr
;
5143 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5145 else acdi
->lpAppDirPath
= NULL
;
5149 case AssemblyDetailedInformationInActivationContext
:
5151 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5152 struct assembly
*assembly
;
5155 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5158 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5159 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5161 index
= *(DWORD
*)subinst
;
5162 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5164 assembly
= &actctx
->assemblies
[index
- 1];
5166 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5167 id_len
= strlenW(assembly_id
) + 1;
5168 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5170 if (assembly
->manifest
.info
&&
5171 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5172 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5174 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5176 if (retlen
) *retlen
= len
;
5177 if (!buffer
|| bufsize
< len
)
5179 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5180 return STATUS_BUFFER_TOO_SMALL
;
5183 afdi
->ulFlags
= 0; /* FIXME */
5184 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5185 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5186 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5187 /* FIXME afdi->liManifestLastWriteTime = 0; */
5188 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5189 afdi
->ulPolicyPathLength
= 0;
5190 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5191 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5192 afdi
->ulManifestVersionMajor
= 1;
5193 afdi
->ulManifestVersionMinor
= 0;
5194 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5195 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5196 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5197 ptr
= (LPWSTR
)(afdi
+ 1);
5198 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5199 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5203 afdi
->lpAssemblyManifestPath
= ptr
;
5204 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5206 } else afdi
->lpAssemblyManifestPath
= NULL
;
5207 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5210 afdi
->lpAssemblyDirectoryName
= ptr
;
5211 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5213 else afdi
->lpAssemblyDirectoryName
= NULL
;
5214 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5218 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5220 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5221 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5222 struct assembly
*assembly
;
5223 struct dll_redirect
*dll
;
5224 SIZE_T len
, dll_len
= 0;
5227 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5228 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5230 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5231 return STATUS_INVALID_PARAMETER
;
5232 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5234 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5235 return STATUS_INVALID_PARAMETER
;
5236 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5238 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5239 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5241 if (!buffer
|| bufsize
< len
)
5243 if (retlen
) *retlen
= len
;
5244 return STATUS_BUFFER_TOO_SMALL
;
5246 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5247 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5248 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5249 afdi
->ulPathLength
= 0; /* FIXME */
5250 ptr
= (LPWSTR
)(afdi
+ 1);
5253 afdi
->lpFileName
= ptr
;
5254 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5255 } else afdi
->lpFileName
= NULL
;
5256 afdi
->lpFilePath
= NULL
; /* FIXME */
5260 case CompatibilityInformationInActivationContext
:
5262 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5263 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5264 struct assembly
*assembly
= NULL
;
5265 ULONG num_compat_contexts
= 0, n
;
5268 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5270 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5273 num_compat_contexts
= assembly
->num_compat_contexts
;
5274 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5276 if (retlen
) *retlen
= len
;
5277 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5279 *acci
= num_compat_contexts
;
5280 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5281 for (n
= 0; n
< num_compat_contexts
; ++n
)
5283 elements
[n
] = assembly
->compat_contexts
[n
];
5288 case RunlevelInformationInActivationContext
:
5290 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5291 struct assembly
*assembly
;
5294 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5296 len
= sizeof(*acrli
);
5297 if (retlen
) *retlen
= len
;
5298 if (!buffer
|| bufsize
< len
)
5299 return STATUS_BUFFER_TOO_SMALL
;
5301 assembly
= actctx
->assemblies
;
5304 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5305 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5310 FIXME( "class %u not implemented\n", class );
5311 return STATUS_NOT_IMPLEMENTED
;
5313 return STATUS_SUCCESS
;
5316 /***********************************************************************
5317 * RtlFindActivationContextSectionString (NTDLL.@)
5319 * Find information about a string in an activation context.
5320 * FIXME: function signature/prototype may be wrong
5322 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5323 const UNICODE_STRING
*section_name
, PVOID ptr
)
5325 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5326 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5328 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5329 debugstr_us(section_name
), data
);
5333 FIXME("expected guid == NULL\n");
5334 return STATUS_INVALID_PARAMETER
;
5336 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5338 FIXME("unknown flags %08x\n", flags
);
5339 return STATUS_INVALID_PARAMETER
;
5341 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5342 !section_name
|| !section_name
->Buffer
)
5344 WARN("invalid parameter\n");
5345 return STATUS_INVALID_PARAMETER
;
5348 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5350 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5351 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5354 if (status
!= STATUS_SUCCESS
)
5355 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5360 /***********************************************************************
5361 * RtlFindActivationContextSectionGuid (NTDLL.@)
5363 * Find information about a GUID in an activation context.
5364 * FIXME: function signature/prototype may be wrong
5366 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5367 const GUID
*guid
, void *ptr
)
5369 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5370 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5372 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5376 FIXME("expected extguid == NULL\n");
5377 return STATUS_INVALID_PARAMETER
;
5380 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5382 FIXME("unknown flags %08x\n", flags
);
5383 return STATUS_INVALID_PARAMETER
;
5386 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5387 return STATUS_INVALID_PARAMETER
;
5389 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5391 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5392 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5395 if (status
!= STATUS_SUCCESS
)
5396 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);