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"
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
34 #define WIN32_NO_STATUS
37 #include "ntdll_misc.h"
38 #include "wine/exception.h"
39 #include "wine/debug.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
44 #define ACTCTX_FLAGS_ALL (\
45 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
46 ACTCTX_FLAG_LANGID_VALID |\
47 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
48 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
49 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
50 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
51 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
52 ACTCTX_FLAG_HMODULE_VALID )
54 #define ACTCTX_MAGIC 0xC07E3E11
55 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
56 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
58 /* we don't want to include winuser.h */
59 #define RT_MANIFEST ((ULONG_PTR)24)
60 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
63 typedef enum tagLIBFLAGS
{
64 LIBFLAG_FRESTRICTED
= 0x1,
65 LIBFLAG_FCONTROL
= 0x2,
66 LIBFLAG_FHIDDEN
= 0x4,
67 LIBFLAG_FHASDISKIMAGE
= 0x8
71 typedef enum tagOLEMISC
73 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
74 OLEMISC_ONLYICONIC
= 0x2,
75 OLEMISC_INSERTNOTREPLACE
= 0x4,
77 OLEMISC_CANTLINKINSIDE
= 0x10,
78 OLEMISC_CANLINKBYOLE1
= 0x20,
79 OLEMISC_ISLINKOBJECT
= 0x40,
80 OLEMISC_INSIDEOUT
= 0x80,
81 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
82 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
83 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
84 OLEMISC_ALWAYSRUN
= 0x800,
85 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
86 OLEMISC_ACTSLIKELABEL
= 0x2000,
87 OLEMISC_NOUIACTIVATE
= 0x4000,
88 OLEMISC_ALIGNABLE
= 0x8000,
89 OLEMISC_SIMPLEFRAME
= 0x10000,
90 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
91 OLEMISC_IMEMODE
= 0x40000,
92 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
93 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
94 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
115 struct assembly_version
123 struct assembly_identity
130 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
;
504 enum context_sections
506 WINDOWCLASS_SECTION
= 1,
507 DLLREDIRECT_SECTION
= 2,
508 TLIBREDIRECT_SECTION
= 4,
509 SERVERREDIRECT_SECTION
= 8,
510 IFACEREDIRECT_SECTION
= 16,
511 CLRSURROGATES_SECTION
= 32,
512 PROGIDREDIRECT_SECTION
= 64
515 typedef struct _ACTIVATION_CONTEXT
519 struct file_info config
;
520 struct file_info appdir
;
521 struct assembly
*assemblies
;
522 unsigned int num_assemblies
;
523 unsigned int allocated_assemblies
;
526 struct strsection_header
*wndclass_section
;
527 struct strsection_header
*dllredirect_section
;
528 struct strsection_header
*progid_section
;
529 struct guidsection_header
*tlib_section
;
530 struct guidsection_header
*comserver_section
;
531 struct guidsection_header
*ifaceps_section
;
532 struct guidsection_header
*clrsurrogate_section
;
533 } ACTIVATION_CONTEXT
;
537 ACTIVATION_CONTEXT
*actctx
;
538 struct assembly_identity
*dependencies
;
539 unsigned int num_dependencies
;
540 unsigned int allocated_dependencies
;
543 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
544 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
545 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
546 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
547 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
548 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
549 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
550 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
551 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};
552 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};
553 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
554 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
555 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
556 static const WCHAR fileW
[] = {'f','i','l','e',0};
557 static const WCHAR hashW
[] = {'h','a','s','h',0};
558 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
559 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
560 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
561 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
563 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
564 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
565 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
566 static const WCHAR iidW
[] = {'i','i','d',0};
567 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
568 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
569 static const WCHAR nameW
[] = {'n','a','m','e',0};
570 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
571 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
572 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
573 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
574 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};
575 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
576 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
577 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
578 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
579 static const WCHAR typeW
[] = {'t','y','p','e',0};
580 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
581 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
582 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
583 static const WCHAR yesW
[] = {'y','e','s',0};
584 static const WCHAR noW
[] = {'n','o',0};
585 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
586 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
587 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
588 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
589 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
590 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
591 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
592 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
593 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
594 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
595 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
596 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
597 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
598 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
599 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
600 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
602 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
603 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
604 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
605 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
606 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
607 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
608 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
609 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};
610 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
611 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
612 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
613 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
614 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
615 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
616 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
617 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
618 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};
619 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
620 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
621 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
622 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};
623 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
631 static const struct olemisc_entry olemisc_values
[] =
633 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
634 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
635 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
636 { alignableW
, OLEMISC_ALIGNABLE
},
637 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
638 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
639 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
640 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
641 { imemodeW
, OLEMISC_IMEMODE
},
642 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
643 { insideoutW
, OLEMISC_INSIDEOUT
},
644 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
645 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
646 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
647 { onlyiconicW
, OLEMISC_ONLYICONIC
},
648 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
649 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
650 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
651 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
652 { staticW
, OLEMISC_STATIC
},
653 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
654 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
657 static const WCHAR xmlW
[] = {'?','x','m','l',0};
658 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};
659 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};
661 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
662 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
663 static const WCHAR wildcardW
[] = {'*',0};
665 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
666 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
668 static WCHAR
*strdupW(const WCHAR
* str
)
672 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
674 return strcpyW(ptr
, str
);
677 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
681 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
683 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
689 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
691 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
694 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
696 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
699 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
701 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
702 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
705 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
707 UINT len
= strlenW( namespace );
709 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
710 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
711 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
714 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
716 if (elem
->len
&& elem
->ptr
[0] == '/')
719 elem_end
.ptr
= elem
->ptr
+ 1;
720 elem_end
.len
= elem
->len
- 1;
721 return xml_elem_cmp( &elem_end
, str
, namespace );
726 static inline BOOL
isxmlspace( WCHAR ch
)
728 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
731 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
733 return debugstr_wn(str
->ptr
, str
->len
);
736 static inline const char* debugstr_version(const struct assembly_version
*ver
)
738 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
741 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
743 struct assembly
*assembly
;
745 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
748 unsigned int new_count
;
749 if (actctx
->assemblies
)
751 new_count
= actctx
->allocated_assemblies
* 2;
752 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
753 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
758 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
760 if (!ptr
) return NULL
;
761 actctx
->assemblies
= ptr
;
762 actctx
->allocated_assemblies
= new_count
;
765 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
770 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
772 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
775 unsigned int new_count
;
778 new_count
= assembly
->allocated_dlls
* 2;
779 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
780 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
785 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
787 if (!ptr
) return NULL
;
788 assembly
->dlls
= ptr
;
789 assembly
->allocated_dlls
= new_count
;
791 return &assembly
->dlls
[assembly
->num_dlls
++];
794 static void free_assembly_identity(struct assembly_identity
*ai
)
796 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
797 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
798 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
799 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
800 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
803 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
805 struct entity
* entity
;
807 if (array
->num
== array
->allocated
)
810 unsigned int new_count
;
813 new_count
= array
->allocated
* 2;
814 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
815 array
->base
, new_count
* sizeof(*array
->base
) );
820 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
822 if (!ptr
) return NULL
;
824 array
->allocated
= new_count
;
826 entity
= &array
->base
[array
->num
++];
831 static void free_entity_array(struct entity_array
*array
)
834 for (i
= 0; i
< array
->num
; i
++)
836 struct entity
*entity
= &array
->base
[i
];
837 switch (entity
->kind
)
839 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
840 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
841 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
842 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
843 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
844 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
845 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
846 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
847 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
849 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
850 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
851 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
852 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
853 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
855 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
856 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
857 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
859 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
860 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
862 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
863 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
864 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
865 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
868 FIXME("Unknown entity kind %d\n", entity
->kind
);
871 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
874 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
876 if (!str1
) return !str2
;
877 return str2
&& !strcmpiW( str1
, str2
);
880 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
881 const struct assembly_identity
*id2
)
883 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
884 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
885 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
887 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
889 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
892 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
893 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
894 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
895 if (id1
->version
.build
== id2
->version
.build
&&
896 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
900 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
901 struct assembly_identity
* ai
)
905 /* check if we already have that assembly */
907 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
908 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
910 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
911 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
912 ai
->version
.build
, ai
->version
.revision
);
916 for (i
= 0; i
< acl
->num_dependencies
; i
++)
917 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
919 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
920 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
921 ai
->version
.build
, ai
->version
.revision
);
925 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
928 unsigned int new_count
;
929 if (acl
->dependencies
)
931 new_count
= acl
->allocated_dependencies
* 2;
932 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
933 new_count
* sizeof(acl
->dependencies
[0]));
938 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
940 if (!ptr
) return FALSE
;
941 acl
->dependencies
= ptr
;
942 acl
->allocated_dependencies
= new_count
;
944 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
949 static void free_depend_manifests(struct actctx_loader
* acl
)
952 for (i
= 0; i
< acl
->num_dependencies
; i
++)
953 free_assembly_identity(&acl
->dependencies
[i
]);
954 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
957 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
959 static const WCHAR undW
[] = {'_',0};
960 static const WCHAR noneW
[] = {'n','o','n','e',0};
961 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
963 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
964 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
965 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
966 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
967 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
968 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
971 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
973 strcpyW( ret
, arch
);
974 strcatW( ret
, undW
);
975 strcatW( ret
, name
);
976 strcatW( ret
, undW
);
978 strcatW( ret
, undW
);
979 sprintfW( ret
+ strlenW(ret
), version_formatW
,
980 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
981 strcatW( ret
, undW
);
982 strcatW( ret
, lang
);
983 strcatW( ret
, undW
);
984 strcatW( ret
, mskeyW
);
988 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
993 strcatW( buffer
, prefix
);
1002 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1004 static const WCHAR archW
[] =
1005 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1006 static const WCHAR public_keyW
[] =
1007 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1008 static const WCHAR typeW
[] =
1009 {',','t','y','p','e','=',0};
1010 static const WCHAR versionW
[] =
1011 {',','v','e','r','s','i','o','n','=',0};
1013 WCHAR version
[64], *ret
;
1016 sprintfW( version
, version_formatW
,
1017 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1018 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1019 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1020 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1021 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
1022 size
+= strlenW(versionW
) + strlenW(version
) + 2;
1024 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1027 if (ai
->name
) strcpyW( ret
, ai
->name
);
1029 append_string( ret
, archW
, ai
->arch
);
1030 append_string( ret
, public_keyW
, ai
->public_key
);
1031 append_string( ret
, typeW
, ai
->type
);
1032 append_string( ret
, versionW
, version
);
1036 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1038 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1040 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1043 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1052 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1054 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1057 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1059 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1063 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1065 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1066 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1068 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1069 free_entity_array( &dll
->entities
);
1070 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1071 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1073 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1074 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1076 free_entity_array( &assembly
->entities
);
1077 free_assembly_identity(&assembly
->id
);
1079 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1080 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1094 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1095 BOOL
* error
, BOOL
* end
)
1101 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1104 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1106 if (*xmlbuf
->ptr
== '/')
1109 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1118 if (*xmlbuf
->ptr
== '>')
1126 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1128 if (ptr
== xmlbuf
->end
) return FALSE
;
1130 name
->ptr
= xmlbuf
->ptr
;
1131 name
->len
= ptr
-xmlbuf
->ptr
;
1134 /* skip spaces before '=' */
1135 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1136 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1138 /* skip '=' itself */
1140 if (ptr
== xmlbuf
->end
) return FALSE
;
1142 /* skip spaces after '=' */
1143 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1145 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1148 if (ptr
== xmlbuf
->end
) return FALSE
;
1150 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1153 xmlbuf
->ptr
= xmlbuf
->end
;
1157 value
->len
= ptr
- value
->ptr
;
1158 xmlbuf
->ptr
= ptr
+ 1;
1160 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1166 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1172 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1175 xmlbuf
->ptr
= xmlbuf
->end
;
1179 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1181 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1182 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1184 if (ptr
+ 3 > xmlbuf
->end
)
1186 xmlbuf
->ptr
= xmlbuf
->end
;
1189 xmlbuf
->ptr
= ptr
+ 3;
1195 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1198 elem
->ptr
= xmlbuf
->ptr
;
1199 elem
->len
= ptr
- xmlbuf
->ptr
;
1201 return xmlbuf
->ptr
!= xmlbuf
->end
;
1204 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1206 /* FIXME: parse attributes */
1209 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1211 if (ptr
[0] == '?' && ptr
[1] == '>')
1213 xmlbuf
->ptr
= ptr
+ 2;
1220 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1222 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1224 if (!ptr
) return FALSE
;
1226 content
->ptr
= xmlbuf
->ptr
;
1227 content
->len
= ptr
- xmlbuf
->ptr
;
1233 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1235 unsigned int ver
[4];
1239 /* major.minor.build.revision */
1240 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1241 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1243 if (*curr
>= '0' && *curr
<= '9')
1245 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1246 if (ver
[pos
] >= 0x10000) goto error
;
1248 else if (*curr
== '.')
1250 if (++pos
>= 4) goto error
;
1254 version
->major
= ver
[0];
1255 version
->minor
= ver
[1];
1256 version
->build
= ver
[2];
1257 version
->revision
= ver
[3];
1261 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1265 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1268 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1269 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1270 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1274 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1276 xmlstr_t attr_name
, attr_value
;
1279 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1281 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1282 debugstr_xmlstr(&attr_value
));
1287 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1290 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1293 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1296 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1297 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1299 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1302 return parse_end_element(xmlbuf
);
1305 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1307 xmlstr_t attr_name
, attr_value
, elem
;
1308 BOOL end
= FALSE
, error
, ret
= TRUE
;
1310 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1311 if(error
|| end
) return end
;
1313 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1315 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1316 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1319 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1322 return ret
&& parse_end_element(xmlbuf
);
1325 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1326 struct assembly_identity
* ai
)
1328 xmlstr_t attr_name
, attr_value
;
1329 BOOL end
= FALSE
, error
;
1331 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1333 if (xmlstr_cmp(&attr_name
, nameW
))
1335 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1337 else if (xmlstr_cmp(&attr_name
, typeW
))
1339 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1341 else if (xmlstr_cmp(&attr_name
, versionW
))
1343 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1345 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1347 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1349 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1351 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1353 else if (xmlstr_cmp(&attr_name
, languageW
))
1355 WARN("Unsupported yet language attribute (%s)\n",
1356 debugstr_xmlstr(&attr_value
));
1357 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1361 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1362 debugstr_xmlstr(&attr_value
));
1366 TRACE( "name=%s version=%s arch=%s\n",
1367 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1369 if (error
|| end
) return end
;
1370 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1373 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1375 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1376 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1377 static const WCHAR freeW
[] = {'F','r','e','e',0};
1378 static const WCHAR bothW
[] = {'B','o','t','h',0};
1380 if (value
->len
== 0) return ThreadingModel_No
;
1381 if (xmlstr_cmp(value
, apartW
))
1382 return ThreadingModel_Apartment
;
1383 else if (xmlstr_cmp(value
, freeW
))
1384 return ThreadingModel_Free
;
1385 else if (xmlstr_cmp(value
, bothW
))
1386 return ThreadingModel_Both
;
1387 else if (xmlstr_cmp(value
, neutralW
))
1388 return ThreadingModel_Neutral
;
1390 return ThreadingModel_No
;
1393 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1398 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1406 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1407 if (!c
&& !olemisc_values
[n
].name
[len
])
1408 return olemisc_values
[n
].value
;
1416 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1420 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1422 const WCHAR
*str
= value
->ptr
, *start
;
1426 /* it's comma separated list of flags */
1427 while (i
< value
->len
)
1430 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1432 flags
|= get_olemisc_value(start
, str
-start
);
1434 /* skip separator */
1442 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1444 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1446 if (progids
->allocated
== 0)
1448 progids
->allocated
= 4;
1449 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1452 if (progids
->allocated
== progids
->num
)
1454 progids
->allocated
*= 2;
1455 progids
->progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
, progids
->allocated
* sizeof(WCHAR
*));
1458 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1464 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1469 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1472 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1473 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1476 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1478 xmlstr_t elem
, attr_name
, attr_value
;
1479 BOOL ret
= TRUE
, end
= FALSE
, error
;
1480 struct entity
* entity
;
1482 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1485 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1487 if (xmlstr_cmp(&attr_name
, clsidW
))
1489 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1491 else if (xmlstr_cmp(&attr_name
, progidW
))
1493 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1495 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1497 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1499 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1501 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1503 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1505 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1507 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1509 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1511 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1513 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1515 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1517 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1519 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1521 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1523 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1529 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1533 if (error
) return FALSE
;
1535 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1536 if (entity
->u
.comclass
.progid
)
1537 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1539 if (end
) return TRUE
;
1541 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1543 if (xmlstr_cmp_end(&elem
, comClassW
))
1545 ret
= parse_end_element(xmlbuf
);
1548 else if (xmlstr_cmp(&elem
, progidW
))
1550 ret
= parse_com_class_progid(xmlbuf
, entity
);
1554 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1555 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1559 if (entity
->u
.comclass
.progids
.num
)
1560 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1565 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1570 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1572 if (*curr
>= '0' && *curr
<= '9')
1573 num
= num
* 10 + *curr
- '0';
1576 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1580 entity
->u
.ifaceps
.nummethods
= num
;
1585 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1587 xmlstr_t attr_name
, attr_value
;
1588 BOOL end
= FALSE
, error
;
1589 struct entity
* entity
;
1591 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1594 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1596 if (xmlstr_cmp(&attr_name
, iidW
))
1598 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1600 else if (xmlstr_cmp(&attr_name
, nameW
))
1602 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1604 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1606 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1607 entity
->u
.ifaceps
.mask
|= BaseIface
;
1609 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1611 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1612 entity
->u
.ifaceps
.mask
|= NumMethods
;
1614 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1616 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1619 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1624 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1628 if (error
) return FALSE
;
1629 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1630 if (end
) return TRUE
;
1632 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1635 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1637 WORD
*flags
= &entity
->u
.typelib
.flags
;
1638 const WCHAR
*str
= value
->ptr
, *start
;
1643 /* it's comma separated list of flags */
1644 while (i
< value
->len
)
1647 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1649 if (!strncmpiW(start
, restrictedW
, str
-start
))
1650 *flags
|= LIBFLAG_FRESTRICTED
;
1651 else if (!strncmpiW(start
, controlW
, str
-start
))
1652 *flags
|= LIBFLAG_FCONTROL
;
1653 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1654 *flags
|= LIBFLAG_FHIDDEN
;
1655 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1656 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1659 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1663 /* skip separator */
1671 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1673 unsigned int ver
[2];
1678 ver
[0] = ver
[1] = pos
= 0;
1679 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1681 if (*curr
>= '0' && *curr
<= '9')
1683 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1684 if (ver
[pos
] >= 0x10000) goto error
;
1686 else if (*curr
== '.')
1688 if (++pos
>= 2) goto error
;
1692 entity
->u
.typelib
.major
= ver
[0];
1693 entity
->u
.typelib
.minor
= ver
[1];
1697 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1701 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1703 xmlstr_t attr_name
, attr_value
;
1704 BOOL end
= FALSE
, error
;
1705 struct entity
* entity
;
1707 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1710 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1712 if (xmlstr_cmp(&attr_name
, tlbidW
))
1714 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1716 else if (xmlstr_cmp(&attr_name
, versionW
))
1718 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1720 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1722 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1724 else if (xmlstr_cmp(&attr_name
, flagsW
))
1726 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1730 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1734 if (error
) return FALSE
;
1736 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1738 if (end
) return TRUE
;
1740 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1743 static inline int aligned_string_len(int len
)
1745 return (len
+ 3) & ~3;
1748 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1750 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1751 struct assembly_version
*ver
= &assembly
->id
.version
;
1754 if (!ret
) ret
= buff
;
1755 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1758 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1760 xmlstr_t elem
, content
, attr_name
, attr_value
;
1761 BOOL end
= FALSE
, ret
= TRUE
, error
;
1762 struct entity
* entity
;
1764 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1767 entity
->u
.class.versioned
= TRUE
;
1768 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1770 if (xmlstr_cmp(&attr_name
, versionedW
))
1772 if (xmlstr_cmpi(&attr_value
, noW
))
1773 entity
->u
.class.versioned
= FALSE
;
1774 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1779 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1783 if (error
|| end
) return end
;
1785 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1787 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1789 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1791 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1793 if (xmlstr_cmp_end(&elem
, windowClassW
))
1795 ret
= parse_end_element(xmlbuf
);
1800 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1801 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1808 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1810 xmlstr_t attr_name
, attr_value
;
1811 BOOL end
= FALSE
, error
;
1813 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1815 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1817 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value
));
1819 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1821 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value
));
1825 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1829 if (error
|| end
) return end
;
1830 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1833 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1835 xmlstr_t elem
, content
;
1836 BOOL end
= FALSE
, ret
= TRUE
;
1838 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
||
1839 !parse_text_content(xmlbuf
, &content
))
1842 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1844 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1846 if (xmlstr_cmp_end(&elem
, descriptionW
))
1848 ret
= parse_end_element(xmlbuf
);
1853 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1854 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1861 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1862 struct assembly
* assembly
,
1863 struct actctx_loader
* acl
)
1865 xmlstr_t attr_name
, attr_value
;
1866 BOOL end
= FALSE
, error
;
1867 struct entity
* entity
;
1869 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1870 if (!entity
) return FALSE
;
1872 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1874 if (xmlstr_cmp(&attr_name
, iidW
))
1876 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1878 else if (xmlstr_cmp(&attr_name
, nameW
))
1880 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1882 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1884 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1885 entity
->u
.ifaceps
.mask
|= BaseIface
;
1887 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1889 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1890 entity
->u
.ifaceps
.mask
|= NumMethods
;
1892 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1894 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1896 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1898 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1902 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1906 if (error
) return FALSE
;
1907 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1908 if (end
) return TRUE
;
1910 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
1913 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1915 xmlstr_t attr_name
, attr_value
, elem
;
1916 BOOL end
= FALSE
, error
, ret
= TRUE
;
1917 struct entity
* entity
;
1919 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
1920 if (!entity
) return FALSE
;
1922 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1924 if (xmlstr_cmp(&attr_name
, nameW
))
1926 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1928 else if (xmlstr_cmp(&attr_name
, clsidW
))
1930 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1932 else if (xmlstr_cmp(&attr_name
, progidW
))
1934 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1936 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1938 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1940 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1942 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1944 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
1946 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
1950 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1954 if (error
) return FALSE
;
1955 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1956 if (entity
->u
.comclass
.progid
)
1957 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1958 if (end
) return TRUE
;
1960 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1962 if (xmlstr_cmp_end(&elem
, clrClassW
))
1964 ret
= parse_end_element(xmlbuf
);
1967 else if (xmlstr_cmp(&elem
, progidW
))
1969 ret
= parse_com_class_progid(xmlbuf
, entity
);
1973 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1974 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1978 if (entity
->u
.comclass
.progids
.num
)
1979 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1984 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1986 xmlstr_t attr_name
, attr_value
;
1987 BOOL end
= FALSE
, error
;
1988 struct entity
* entity
;
1990 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
1991 if (!entity
) return FALSE
;
1993 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1995 if (xmlstr_cmp(&attr_name
, nameW
))
1997 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1999 else if (xmlstr_cmp(&attr_name
, clsidW
))
2001 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2003 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2005 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2009 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2013 if (error
) return FALSE
;
2014 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2015 if (end
) return TRUE
;
2017 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2020 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2022 struct assembly_identity ai
;
2024 BOOL end
= FALSE
, ret
= TRUE
;
2026 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
) return end
;
2028 memset(&ai
, 0, sizeof(ai
));
2029 ai
.optional
= optional
;
2031 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2032 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2035 TRACE( "adding name=%s version=%s arch=%s\n",
2036 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2038 /* store the newly found identity for later loading */
2039 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2041 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2043 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2045 ret
= parse_end_element(xmlbuf
);
2048 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2050 ret
= parse_binding_redirect_elem(xmlbuf
);
2054 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2055 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2062 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2064 xmlstr_t attr_name
, attr_value
, elem
;
2065 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2067 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2069 if (xmlstr_cmp(&attr_name
, optionalW
))
2071 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2072 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value
));
2076 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2080 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2082 if (xmlstr_cmp_end(&elem
, dependencyW
))
2084 ret
= parse_end_element(xmlbuf
);
2087 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2089 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2093 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2094 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2101 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2105 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2106 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2109 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2113 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2114 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2117 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2119 xmlstr_t attr_name
, attr_value
, elem
;
2120 BOOL end
= FALSE
, error
, ret
= TRUE
;
2121 struct dll_redirect
* dll
;
2123 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2125 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2127 if (xmlstr_cmp(&attr_name
, nameW
))
2129 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2130 TRACE("name=%s\n", debugstr_xmlstr(&attr_value
));
2132 else if (xmlstr_cmp(&attr_name
, hashW
))
2134 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2136 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2138 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2139 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2140 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value
));
2144 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2148 if (error
|| !dll
->name
) return FALSE
;
2150 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2152 if (end
) return TRUE
;
2154 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2156 if (xmlstr_cmp_end(&elem
, fileW
))
2158 ret
= parse_end_element(xmlbuf
);
2161 else if (xmlstr_cmp(&elem
, comClassW
))
2163 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2165 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2167 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2169 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2171 WARN("asmv2:hash (undocumented) not supported\n");
2172 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2174 else if (xmlstr_cmp(&elem
, typelibW
))
2176 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2178 else if (xmlstr_cmp(&elem
, windowClassW
))
2180 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2184 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2185 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2192 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2193 struct assembly
* assembly
,
2194 struct assembly_identity
* expected_ai
)
2196 xmlstr_t attr_name
, attr_value
, elem
;
2197 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2199 TRACE("(%p)\n", xmlbuf
);
2201 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2203 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2205 static const WCHAR v10W
[] = {'1','.','0',0};
2206 if (!xmlstr_cmp(&attr_value
, v10W
))
2208 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
2213 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2215 if (!xmlstr_cmp(&attr_value
, manifestv1W
) && !xmlstr_cmp(&attr_value
, manifestv3W
))
2217 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
2224 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2228 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2229 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2231 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2233 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2235 assembly
->no_inherit
= TRUE
;
2238 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2240 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2243 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2244 assembly
->no_inherit
)
2249 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2251 ret
= parse_end_element(xmlbuf
);
2254 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2256 ret
= parse_description_elem(xmlbuf
);
2258 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2260 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2262 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2264 ret
= parse_dependency_elem(xmlbuf
, acl
);
2266 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2268 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2270 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2272 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2274 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2276 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2278 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2280 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2284 /* FIXME: more tests */
2285 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2286 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2288 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2289 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2290 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2291 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2292 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2295 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2296 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2297 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2298 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2299 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2300 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2302 FIXME("wrong version for shared assembly manifest\n");
2309 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2310 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2312 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2318 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2319 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2323 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2325 if (xmlstr_cmp(&elem
, xmlW
) &&
2326 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2327 return STATUS_SXS_CANT_GEN_ACTCTX
;
2329 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2331 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
2332 return STATUS_SXS_CANT_GEN_ACTCTX
;
2335 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2337 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2338 return STATUS_SXS_CANT_GEN_ACTCTX
;
2341 if (next_xml_elem(xmlbuf
, &elem
))
2343 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2344 return STATUS_SXS_CANT_GEN_ACTCTX
;
2347 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2349 FIXME("parse error\n");
2350 return STATUS_SXS_CANT_GEN_ACTCTX
;
2352 return STATUS_SUCCESS
;
2355 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2356 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2357 const void *buffer
, SIZE_T size
)
2361 struct assembly
*assembly
;
2364 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2366 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2367 return STATUS_SXS_CANT_GEN_ACTCTX
;
2369 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2370 return STATUS_NO_MEMORY
;
2372 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2373 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2374 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2376 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2377 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2379 xmlbuf
.ptr
= buffer
;
2380 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2381 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2383 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2385 const WCHAR
*buf
= buffer
;
2389 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2390 return STATUS_NO_MEMORY
;
2391 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2392 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2393 xmlbuf
.ptr
= new_buff
;
2394 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2395 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2396 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2400 /* let's assume utf-8 for now */
2401 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2406 FIXME( "utf-8 conversion failed\n" );
2407 return STATUS_SXS_CANT_GEN_ACTCTX
;
2409 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2410 return STATUS_NO_MEMORY
;
2411 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2412 xmlbuf
.ptr
= new_buff
;
2413 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2414 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2415 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2420 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2422 OBJECT_ATTRIBUTES attr
;
2425 attr
.Length
= sizeof(attr
);
2426 attr
.RootDirectory
= 0;
2427 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2428 attr
.ObjectName
= name
;
2429 attr
.SecurityDescriptor
= NULL
;
2430 attr
.SecurityQualityOfService
= NULL
;
2431 return NtOpenFile( handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2434 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2440 LdrLockLoaderLock(0, NULL
, &magic
);
2441 status
= LdrFindEntryForAddress( module
, &pldr
);
2442 if (status
== STATUS_SUCCESS
)
2444 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2445 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2447 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2448 str
->Length
= pldr
->FullDllName
.Length
;
2449 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2451 else status
= STATUS_NO_MEMORY
;
2453 LdrUnlockLoaderLock(0, magic
);
2457 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2458 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2459 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2462 UNICODE_STRING nameW
;
2463 LDR_RESOURCE_INFO info
;
2464 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2467 if (TRACE_ON(actctx
))
2469 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2471 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2472 hModule
, debugstr_w(nameW
.Buffer
) );
2473 RtlFreeUnicodeString( &nameW
);
2475 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2476 hModule
, debugstr_w(filename
) );
2479 if (!resname
) return STATUS_INVALID_PARAMETER
;
2481 info
.Type
= RT_MANIFEST
;
2482 info
.Language
= lang
;
2483 if (!((ULONG_PTR
)resname
>> 16))
2485 info
.Name
= (ULONG_PTR
)resname
;
2486 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2488 else if (resname
[0] == '#')
2491 RtlInitUnicodeString(&nameW
, resname
+ 1);
2492 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2493 return STATUS_INVALID_PARAMETER
;
2495 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2499 RtlCreateUnicodeString(&nameW
, resname
);
2500 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2501 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2502 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2503 RtlFreeUnicodeString(&nameW
);
2505 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2507 if (status
== STATUS_SUCCESS
)
2508 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2513 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2514 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2515 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2518 OBJECT_ATTRIBUTES attr
;
2520 LARGE_INTEGER offset
;
2525 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2527 attr
.Length
= sizeof(attr
);
2528 attr
.RootDirectory
= 0;
2529 attr
.ObjectName
= NULL
;
2530 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2531 attr
.SecurityDescriptor
= NULL
;
2532 attr
.SecurityQualityOfService
= NULL
;
2535 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2536 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2537 if (status
!= STATUS_SUCCESS
) return status
;
2539 offset
.QuadPart
= 0;
2542 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2543 &count
, ViewShare
, 0, PAGE_READONLY
);
2545 if (status
!= STATUS_SUCCESS
) return status
;
2547 if (RtlImageNtHeader(base
)) /* we got a PE file */
2549 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2550 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2552 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2554 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2558 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2559 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2561 FILE_END_OF_FILE_INFORMATION info
;
2564 OBJECT_ATTRIBUTES attr
;
2566 LARGE_INTEGER offset
;
2571 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2573 attr
.Length
= sizeof(attr
);
2574 attr
.RootDirectory
= 0;
2575 attr
.ObjectName
= NULL
;
2576 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2577 attr
.SecurityDescriptor
= NULL
;
2578 attr
.SecurityQualityOfService
= NULL
;
2581 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2582 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2583 if (status
!= STATUS_SUCCESS
) return status
;
2585 offset
.QuadPart
= 0;
2588 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2589 &count
, ViewShare
, 0, PAGE_READONLY
);
2591 if (status
!= STATUS_SUCCESS
) return status
;
2593 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2594 if (status
== STATUS_SUCCESS
)
2595 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2597 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2601 /* try to load the .manifest file associated to the file */
2602 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2603 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2605 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2608 UNICODE_STRING nameW
;
2610 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2612 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2614 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2616 if (module
) /* use the module filename */
2618 UNICODE_STRING name
;
2620 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2622 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2623 strcatW( name
.Buffer
, dotManifestW
);
2624 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2625 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2626 RtlFreeUnicodeString( &name
);
2628 if (status
) return status
;
2632 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2633 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2634 return STATUS_NO_MEMORY
;
2635 strcpyW( buffer
, filename
);
2636 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2637 strcatW( buffer
, dotManifestW
);
2638 RtlInitUnicodeString( &nameW
, buffer
);
2641 if (!open_nt_file( &file
, &nameW
))
2643 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2646 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2647 RtlFreeUnicodeString( &nameW
);
2651 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2653 static const WCHAR lookup_fmtW
[] =
2654 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2655 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2656 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2658 WCHAR
*lookup
, *ret
= NULL
;
2659 UNICODE_STRING lookup_us
;
2661 const WCHAR
*lang
= ai
->language
;
2662 unsigned int data_pos
= 0, data_len
;
2665 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2666 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2667 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2668 + sizeof(lookup_fmtW
) )))
2671 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2672 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2673 ai
->version
.major
, ai
->version
.minor
, lang
);
2674 RtlInitUnicodeString( &lookup_us
, lookup
);
2676 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2677 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2678 if (io
.u
.Status
== STATUS_SUCCESS
)
2680 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2681 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2683 ULONG build
, revision
;
2685 data_len
= io
.Information
;
2689 if (data_pos
>= data_len
)
2691 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2692 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2693 if (io
.u
.Status
!= STATUS_SUCCESS
) break;
2694 data_len
= io
.Information
;
2697 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2699 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2700 else data_pos
= data_len
;
2702 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2704 if (build
< min_build
) continue;
2705 tmp
= strchrW(tmp
, '.') + 1;
2706 revision
= atoiW(tmp
);
2707 if (build
== min_build
&& revision
< min_revision
) continue;
2708 tmp
= strchrW(tmp
, '_') + 1;
2709 tmp
= strchrW(tmp
, '_') + 1;
2710 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2711 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2713 /* prefer a non-Wine manifest if we already have one */
2714 /* we'll still load the builtin dll if specified through DllOverrides */
2720 min_revision
= revision
;
2722 ai
->version
.build
= build
;
2723 ai
->version
.revision
= revision
;
2724 RtlFreeHeap( GetProcessHeap(), 0, ret
);
2725 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2727 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2728 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2732 else WARN("no matching file for %s\n", debugstr_w(lookup
));
2733 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
2737 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2739 struct assembly_identity sxs_ai
;
2740 UNICODE_STRING path_us
;
2741 OBJECT_ATTRIBUTES attr
;
2743 WCHAR
*path
, *file
= NULL
;
2746 static const WCHAR manifest_dirW
[] =
2747 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2749 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2751 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
2752 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
2753 return STATUS_NO_MEMORY
;
2755 strcpyW( path
, user_shared_data
->NtSystemRoot
);
2756 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
2758 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2760 RtlFreeHeap( GetProcessHeap(), 0, path
);
2761 return STATUS_NO_SUCH_FILE
;
2763 RtlFreeHeap( GetProcessHeap(), 0, path
);
2765 attr
.Length
= sizeof(attr
);
2766 attr
.RootDirectory
= 0;
2767 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2768 attr
.ObjectName
= &path_us
;
2769 attr
.SecurityDescriptor
= NULL
;
2770 attr
.SecurityQualityOfService
= NULL
;
2772 if (!NtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2773 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2776 file
= lookup_manifest_file( handle
, &sxs_ai
);
2781 RtlFreeUnicodeString( &path_us
);
2782 return STATUS_NO_SUCH_FILE
;
2785 /* append file name to directory path */
2786 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
2787 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2789 RtlFreeHeap( GetProcessHeap(), 0, file
);
2790 RtlFreeUnicodeString( &path_us
);
2791 return STATUS_NO_MEMORY
;
2794 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2795 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2796 RtlInitUnicodeString( &path_us
, path
);
2797 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2799 if (!open_nt_file( &handle
, &path_us
))
2801 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2804 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
2806 RtlFreeHeap( GetProcessHeap(), 0, file
);
2807 RtlFreeUnicodeString( &path_us
);
2811 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2812 struct assembly_identity
* ai
)
2814 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2816 WCHAR
*buffer
, *p
, *directory
;
2818 UNICODE_STRING nameW
;
2822 TRACE( "looking for name=%s version=%s arch=%s\n",
2823 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
2825 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2827 /* FIXME: add support for language specific lookup */
2829 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2830 strlenW(acl
->actctx
->appdir
.info
));
2832 nameW
.Buffer
= NULL
;
2833 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2834 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2835 return STATUS_NO_MEMORY
;
2837 if (!(directory
= build_assembly_dir( ai
)))
2839 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2840 return STATUS_NO_MEMORY
;
2843 /* Lookup in <dir>\name.dll
2844 * <dir>\name.manifest
2845 * <dir>\name\name.dll
2846 * <dir>\name\name.manifest
2848 * First 'appdir' is used as <dir>, if that failed
2849 * it tries application manifest file path.
2851 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
2852 p
= buffer
+ strlenW(buffer
);
2853 for (i
= 0; i
< 4; i
++)
2857 struct assembly
*assembly
= acl
->actctx
->assemblies
;
2858 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
2862 strcpyW( p
, ai
->name
);
2865 strcpyW( p
, dotDllW
);
2866 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2868 status
= open_nt_file( &file
, &nameW
);
2871 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
2872 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
2876 RtlFreeUnicodeString( &nameW
);
2879 strcpyW( p
, dotManifestW
);
2880 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2882 status
= open_nt_file( &file
, &nameW
);
2885 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2889 RtlFreeUnicodeString( &nameW
);
2891 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
2893 RtlFreeUnicodeString( &nameW
);
2894 RtlFreeHeap( GetProcessHeap(), 0, directory
);
2895 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2899 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
2901 NTSTATUS status
= STATUS_SUCCESS
;
2904 for (i
= 0; i
< acl
->num_dependencies
; i
++)
2906 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
2908 if (!acl
->dependencies
[i
].optional
)
2910 FIXME( "Could not find dependent assembly %s (%s)\n",
2911 debugstr_w(acl
->dependencies
[i
].name
),
2912 debugstr_version(&acl
->dependencies
[i
].version
) );
2913 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
2918 /* FIXME should now iterate through all refs */
2922 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2923 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
2925 NTSTATUS status
= STATUS_SUCCESS
;
2927 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
2929 if (*handle
) return STATUS_INVALID_PARAMETER
;
2931 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
2932 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
2934 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
2939 if (!*handle
) return STATUS_INVALID_PARAMETER
;
2941 LdrLockLoaderLock( 0, NULL
, &magic
);
2942 if (!LdrFindEntryForAddress( *handle
, &pldr
))
2944 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
2945 status
= STATUS_DLL_NOT_FOUND
;
2947 *handle
= pldr
->ActivationContext
;
2949 else status
= STATUS_DLL_NOT_FOUND
;
2950 LdrUnlockLoaderLock( 0, magic
);
2952 else if (!*handle
&& (class != ActivationContextBasicInformation
))
2953 *handle
= process_actctx
;
2958 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
2960 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
2961 struct strsection_header
*header
;
2962 struct dllredirect_data
*data
;
2963 struct string_index
*index
;
2966 /* compute section length */
2967 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2969 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2970 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2972 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2974 /* each entry needs index, data and string data */
2975 total_len
+= sizeof(*index
);
2976 total_len
+= sizeof(*data
);
2977 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
2980 dll_count
+= assembly
->num_dlls
;
2983 total_len
+= sizeof(*header
);
2985 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
2986 if (!header
) return STATUS_NO_MEMORY
;
2988 memset(header
, 0, sizeof(*header
));
2989 header
->magic
= STRSECTION_MAGIC
;
2990 header
->size
= sizeof(*header
);
2991 header
->count
= dll_count
;
2992 header
->index_offset
= sizeof(*header
);
2993 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
2994 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
2996 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2998 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2999 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3001 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3005 /* setup new index entry */
3006 str
.Buffer
= dll
->name
;
3007 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3008 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3009 /* hash original class name */
3010 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3012 index
->name_offset
= name_offset
;
3013 index
->name_len
= str
.Length
;
3014 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3015 index
->data_len
= sizeof(*data
);
3016 index
->rosterindex
= i
+ 1;
3019 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3020 data
->size
= sizeof(*data
);
3021 data
->unk
= 2; /* FIXME: seems to be constant */
3022 memset(data
->res
, 0, sizeof(data
->res
));
3025 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3026 memcpy(ptrW
, dll
->name
, index
->name_len
);
3027 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3029 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3037 return STATUS_SUCCESS
;
3040 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3042 struct string_index
*iter
, *index
= NULL
;
3045 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3046 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3048 for (i
= 0; i
< section
->count
; i
++)
3050 if (iter
->hash
== hash
)
3052 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3054 if (!strcmpiW(nameW
, name
->Buffer
))
3060 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3068 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3070 struct guid_index
*iter
, *index
= NULL
;
3073 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3075 for (i
= 0; i
< section
->count
; i
++)
3077 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3088 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3090 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3093 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3094 PACTCTX_SECTION_KEYED_DATA data
)
3096 struct dllredirect_data
*dll
;
3097 struct string_index
*index
;
3099 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3101 if (!actctx
->dllredirect_section
)
3103 struct strsection_header
*section
;
3105 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3106 if (status
) return status
;
3108 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3109 RtlFreeHeap(GetProcessHeap(), 0, section
);
3112 index
= find_string_index(actctx
->dllredirect_section
, name
);
3113 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3115 dll
= get_dllredirect_data(actctx
, index
);
3117 data
->ulDataFormatVersion
= 1;
3119 data
->ulLength
= dll
->size
;
3120 data
->lpSectionGlobalData
= NULL
;
3121 data
->ulSectionGlobalDataLength
= 0;
3122 data
->lpSectionBase
= actctx
->dllredirect_section
;
3123 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3124 data
->hActCtx
= NULL
;
3126 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3127 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3129 return STATUS_SUCCESS
;
3132 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3134 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3137 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3139 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3142 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3144 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3145 struct wndclass_redirect_data
*data
;
3146 struct strsection_header
*header
;
3147 struct string_index
*index
;
3150 /* compute section length */
3151 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3153 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3154 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3156 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3157 for (k
= 0; k
< dll
->entities
.num
; k
++)
3159 struct entity
*entity
= &dll
->entities
.base
[k
];
3160 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3162 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3165 /* each class entry needs index, data and string data */
3166 total_len
+= sizeof(*index
);
3167 total_len
+= sizeof(*data
);
3168 /* original name is stored separately */
3169 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3170 /* versioned name and module name are stored one after another */
3171 if (entity
->u
.class.versioned
)
3172 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3175 len
+= strlenW(dll
->name
) + 1;
3176 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3184 total_len
+= sizeof(*header
);
3186 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3187 if (!header
) return STATUS_NO_MEMORY
;
3189 memset(header
, 0, sizeof(*header
));
3190 header
->magic
= STRSECTION_MAGIC
;
3191 header
->size
= sizeof(*header
);
3192 header
->count
= class_count
;
3193 header
->index_offset
= sizeof(*header
);
3194 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3195 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3197 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3199 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3200 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3202 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3203 for (k
= 0; k
< dll
->entities
.num
; k
++)
3205 struct entity
*entity
= &dll
->entities
.base
[k
];
3206 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3208 static const WCHAR exclW
[] = {'!',0};
3209 ULONG versioned_len
, module_len
;
3213 /* setup new index entry */
3214 str
.Buffer
= entity
->u
.class.name
;
3215 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3216 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3217 /* hash original class name */
3218 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3220 /* include '!' separator too */
3221 if (entity
->u
.class.versioned
)
3222 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3224 versioned_len
= str
.Length
;
3225 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3227 index
->name_offset
= name_offset
;
3228 index
->name_len
= str
.Length
;
3229 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3230 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3231 index
->rosterindex
= i
+ 1;
3234 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3235 data
->size
= sizeof(*data
);
3237 data
->name_len
= versioned_len
;
3238 data
->name_offset
= sizeof(*data
);
3239 data
->module_len
= module_len
;
3240 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3242 /* original class name */
3243 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3244 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3245 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3248 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3249 memcpy(ptrW
, dll
->name
, data
->module_len
);
3250 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3252 /* versioned name */
3253 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3254 if (entity
->u
.class.versioned
)
3256 get_assembly_version(assembly
, ptrW
);
3257 strcatW(ptrW
, exclW
);
3258 strcatW(ptrW
, entity
->u
.class.name
);
3262 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3263 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3266 name_offset
+= sizeof(*data
);
3267 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3277 return STATUS_SUCCESS
;
3280 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3281 PACTCTX_SECTION_KEYED_DATA data
)
3283 struct string_index
*iter
, *index
= NULL
;
3284 struct wndclass_redirect_data
*class;
3288 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3290 if (!actctx
->wndclass_section
)
3292 struct strsection_header
*section
;
3294 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3295 if (status
) return status
;
3297 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3298 RtlFreeHeap(GetProcessHeap(), 0, section
);
3302 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3303 iter
= get_wndclass_first_index(actctx
);
3305 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3307 if (iter
->hash
== hash
)
3309 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3311 if (!strcmpW(nameW
, name
->Buffer
))
3317 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3322 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3324 class = get_wndclass_data(actctx
, index
);
3326 data
->ulDataFormatVersion
= 1;
3327 data
->lpData
= class;
3328 /* full length includes string length with nulls */
3329 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3330 data
->lpSectionGlobalData
= NULL
;
3331 data
->ulSectionGlobalDataLength
= 0;
3332 data
->lpSectionBase
= actctx
->wndclass_section
;
3333 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3334 data
->hActCtx
= NULL
;
3336 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3337 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3339 return STATUS_SUCCESS
;
3342 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3344 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3345 struct guidsection_header
*header
;
3346 ULONG module_offset
, data_offset
;
3347 struct tlibredirect_data
*data
;
3348 struct guid_index
*index
;
3350 /* compute section length */
3351 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3353 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3354 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3356 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3357 for (k
= 0; k
< dll
->entities
.num
; k
++)
3359 struct entity
*entity
= &dll
->entities
.base
[k
];
3360 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3362 /* each entry needs index, data and string data for module name and help string */
3363 total_len
+= sizeof(*index
);
3364 total_len
+= sizeof(*data
);
3365 /* help string is stored separately */
3366 if (*entity
->u
.typelib
.helpdir
)
3367 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3369 /* module names are packed one after another */
3370 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3378 total_len
+= aligned_string_len(names_len
);
3379 total_len
+= sizeof(*header
);
3381 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3382 if (!header
) return STATUS_NO_MEMORY
;
3384 memset(header
, 0, sizeof(*header
));
3385 header
->magic
= GUIDSECTION_MAGIC
;
3386 header
->size
= sizeof(*header
);
3387 header
->count
= tlib_count
;
3388 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3389 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3390 module_offset
= sizeof(*header
);
3391 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3393 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3395 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3396 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3398 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3399 for (k
= 0; k
< dll
->entities
.num
; k
++)
3401 struct entity
*entity
= &dll
->entities
.base
[k
];
3402 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3404 ULONG module_len
, help_len
;
3408 if (*entity
->u
.typelib
.helpdir
)
3409 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3413 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3415 /* setup new index entry */
3416 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3417 RtlGUIDFromString(&str
, &index
->guid
);
3418 index
->data_offset
= data_offset
;
3419 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3420 index
->rosterindex
= i
+ 1;
3423 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3424 data
->size
= sizeof(*data
);
3426 data
->name_len
= module_len
;
3427 data
->name_offset
= module_offset
;
3428 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3430 data
->flags
= entity
->u
.typelib
.flags
;
3431 data
->help_len
= help_len
;
3432 data
->help_offset
= sizeof(*data
);
3433 data
->major_version
= entity
->u
.typelib
.major
;
3434 data
->minor_version
= entity
->u
.typelib
.minor
;
3437 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3438 memcpy(ptrW
, dll
->name
, data
->name_len
);
3439 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3444 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3445 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3446 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3449 data_offset
+= sizeof(*data
);
3451 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3453 module_offset
+= module_len
+ sizeof(WCHAR
);
3463 return STATUS_SUCCESS
;
3466 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3468 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3471 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3473 struct guid_index
*index
= NULL
;
3474 struct tlibredirect_data
*tlib
;
3476 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3478 if (!actctx
->tlib_section
)
3480 struct guidsection_header
*section
;
3482 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3483 if (status
) return status
;
3485 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3486 RtlFreeHeap(GetProcessHeap(), 0, section
);
3489 index
= find_guid_index(actctx
->tlib_section
, guid
);
3490 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3492 tlib
= get_tlib_data(actctx
, index
);
3494 data
->ulDataFormatVersion
= 1;
3495 data
->lpData
= tlib
;
3496 /* full length includes string length with nulls */
3497 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3498 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3499 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3500 data
->lpSectionBase
= actctx
->tlib_section
;
3501 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3502 data
->hActCtx
= NULL
;
3504 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3505 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3507 return STATUS_SUCCESS
;
3510 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3512 ULONG
*ptr
= (ULONG
*)guid
;
3515 /* GUID is 16 bytes long */
3516 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3517 *ptr
= RtlUniform(seed
);
3519 guid
->Data3
&= 0x0fff;
3520 guid
->Data3
|= (4 << 12);
3521 guid
->Data4
[0] &= 0x3f;
3522 guid
->Data4
[0] |= 0x80;
3525 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3526 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3530 for (i
= 0; i
< entities
->num
; i
++)
3532 struct entity
*entity
= &entities
->base
[i
];
3533 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3535 /* each entry needs two index entries, extra one goes for alias GUID */
3536 *len
+= 2*sizeof(struct guid_index
);
3537 /* To save some memory we don't allocated two data structures,
3538 instead alias index and normal index point to the same data structure. */
3539 *len
+= sizeof(struct comclassredirect_data
);
3541 /* for clrClass store some more */
3542 if (entity
->u
.comclass
.name
)
3544 unsigned int str_len
;
3546 /* all string data is stored together in aligned block */
3547 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3548 if (entity
->u
.comclass
.progid
)
3549 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3550 if (entity
->u
.comclass
.version
)
3551 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3553 *len
+= sizeof(struct clrclass_data
);
3554 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3556 /* module name is forced to mscoree.dll, and stored two times with different case */
3557 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3561 /* progid string is stored separately */
3562 if (entity
->u
.comclass
.progid
)
3563 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3565 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3573 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3574 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3575 ULONG
*seed
, ULONG rosterindex
)
3579 for (i
= 0; i
< entities
->num
; i
++)
3581 struct entity
*entity
= &entities
->base
[i
];
3582 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3584 ULONG module_len
, progid_len
, str_len
= 0;
3585 struct comclassredirect_data
*data
;
3586 struct guid_index
*alias_index
;
3587 struct clrclass_data
*clrdata
;
3591 if (entity
->u
.comclass
.progid
)
3592 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3596 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3598 /* setup new index entry */
3599 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3600 RtlGUIDFromString(&str
, &(*index
)->guid
);
3602 (*index
)->data_offset
= *data_offset
;
3603 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3604 (*index
)->rosterindex
= rosterindex
;
3606 /* Setup new index entry for alias guid. Alias index records are placed after
3607 normal records, so normal guids are hit first on search. Note that class count
3609 alias_index
= (*index
) + section
->count
/2;
3610 generate_uuid(seed
, &alias_index
->guid
);
3611 alias_index
->data_offset
= (*index
)->data_offset
;
3612 alias_index
->data_len
= 0;
3613 alias_index
->rosterindex
= (*index
)->rosterindex
;
3616 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3617 data
->size
= sizeof(*data
);
3621 data
->model
= entity
->u
.comclass
.model
;
3622 data
->clsid
= (*index
)->guid
;
3623 data
->alias
= alias_index
->guid
;
3624 data
->clsid2
= data
->clsid
;
3625 if (entity
->u
.comclass
.tlbid
)
3627 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3628 RtlGUIDFromString(&str
, &data
->tlbid
);
3631 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3632 data
->name_len
= module_len
;
3633 data
->name_offset
= *module_offset
;
3634 data
->progid_len
= progid_len
;
3635 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3636 data
->clrdata_len
= 0; /* will be set later */
3637 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3638 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3639 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3640 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3641 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3642 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3644 /* mask describes which misc* data is available */
3646 if (data
->miscstatus
)
3647 data
->miscmask
|= MiscStatus
;
3648 if (data
->miscstatuscontent
)
3649 data
->miscmask
|= MiscStatusContent
;
3650 if (data
->miscstatusthumbnail
)
3651 data
->miscmask
|= MiscStatusThumbnail
;
3652 if (data
->miscstatusicon
)
3653 data
->miscmask
|= MiscStatusIcon
;
3654 if (data
->miscstatusdocprint
)
3655 data
->miscmask
|= MiscStatusDocPrint
;
3657 if (data
->clrdata_offset
)
3659 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3661 clrdata
->size
= sizeof(*clrdata
);
3662 clrdata
->res
[0] = 0;
3663 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3664 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3665 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3666 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3667 clrdata
->name_offset
= clrdata
->size
;
3668 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3669 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3670 clrdata
->res2
[0] = 0;
3671 clrdata
->res2
[1] = 0;
3673 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3676 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3677 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3678 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3680 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3681 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3682 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3685 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3686 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3687 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3689 /* runtime version, optional */
3690 if (clrdata
->version_len
)
3692 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3694 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3695 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3696 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3699 if (data
->progid_len
)
3700 data
->progid_offset
+= data
->clrdata_len
;
3701 (*index
)->data_len
+= sizeof(*clrdata
);
3708 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3709 memcpy(ptrW
, dll
->name
, data
->name_len
);
3710 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3714 if (data
->progid_len
)
3716 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3717 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3718 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3721 /* string block length */
3725 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3726 if (clrdata
->version_len
)
3727 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3730 str_len
+= progid_len
+ sizeof(WCHAR
);
3732 (*index
)->data_len
+= aligned_string_len(str_len
);
3733 alias_index
->data_len
= (*index
)->data_len
;
3735 /* move to next data record */
3736 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3737 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3741 (*data_offset
) += sizeof(*clrdata
);
3742 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3749 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3751 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3752 struct guidsection_header
*header
;
3753 ULONG module_offset
, data_offset
;
3754 struct guid_index
*index
;
3757 /* compute section length */
3758 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3760 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3761 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3762 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3764 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3765 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3769 total_len
+= aligned_string_len(names_len
);
3770 total_len
+= sizeof(*header
);
3772 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3773 if (!header
) return STATUS_NO_MEMORY
;
3775 memset(header
, 0, sizeof(*header
));
3776 header
->magic
= GUIDSECTION_MAGIC
;
3777 header
->size
= sizeof(*header
);
3778 header
->count
= 2*class_count
;
3779 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3780 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3781 module_offset
= sizeof(*header
);
3782 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3784 seed
= NtGetTickCount();
3785 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3787 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3788 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3789 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3791 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3792 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3798 return STATUS_SUCCESS
;
3801 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3803 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3806 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3808 struct comclassredirect_data
*comclass
;
3809 struct guid_index
*index
= NULL
;
3811 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3813 if (!actctx
->comserver_section
)
3815 struct guidsection_header
*section
;
3817 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
3818 if (status
) return status
;
3820 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
3821 RtlFreeHeap(GetProcessHeap(), 0, section
);
3824 index
= find_guid_index(actctx
->comserver_section
, guid
);
3825 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3827 comclass
= get_comclass_data(actctx
, index
);
3829 data
->ulDataFormatVersion
= 1;
3830 data
->lpData
= comclass
;
3831 /* full length includes string length with nulls */
3832 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
3833 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
3834 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
3835 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
3836 data
->lpSectionBase
= actctx
->comserver_section
;
3837 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
3838 data
->hActCtx
= NULL
;
3840 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3841 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3843 return STATUS_SUCCESS
;
3846 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
3850 for (i
= 0; i
< entities
->num
; i
++)
3852 struct entity
*entity
= &entities
->base
[i
];
3853 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3855 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
3856 if (entity
->u
.ifaceps
.name
)
3857 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
3863 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
3864 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
3868 for (i
= 0; i
< entities
->num
; i
++)
3870 struct entity
*entity
= &entities
->base
[i
];
3871 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3873 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
3877 if (entity
->u
.ifaceps
.name
)
3878 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
3883 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
3884 RtlGUIDFromString(&str
, &(*index
)->guid
);
3885 (*index
)->data_offset
= *data_offset
;
3886 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
3887 (*index
)->rosterindex
= rosterindex
;
3889 /* setup data record */
3890 data
->size
= sizeof(*data
);
3891 data
->mask
= entity
->u
.ifaceps
.mask
;
3893 /* proxyStubClsid32 value is only stored for external PS,
3894 if set it's used as iid, otherwise 'iid' attribute value is used */
3895 if (entity
->u
.ifaceps
.ps32
)
3897 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
3898 RtlGUIDFromString(&str
, &data
->iid
);
3901 data
->iid
= (*index
)->guid
;
3903 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
3905 if (entity
->u
.ifaceps
.tlib
)
3907 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
3908 RtlGUIDFromString(&str
, &data
->tlbid
);
3911 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3913 if (entity
->u
.ifaceps
.base
)
3915 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
3916 RtlGUIDFromString(&str
, &data
->base
);
3919 memset(&data
->base
, 0, sizeof(data
->base
));
3921 data
->name_len
= name_len
;
3922 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
3927 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3928 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
3929 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3932 /* move to next record */
3934 *data_offset
+= sizeof(*data
);
3936 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
3941 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3943 unsigned int i
, j
, total_len
= 0, count
= 0;
3944 struct guidsection_header
*header
;
3945 struct guid_index
*index
;
3948 /* compute section length */
3949 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3951 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3953 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
3954 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3956 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3957 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
3961 total_len
+= sizeof(*header
);
3963 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3964 if (!header
) return STATUS_NO_MEMORY
;
3966 memset(header
, 0, sizeof(*header
));
3967 header
->magic
= GUIDSECTION_MAGIC
;
3968 header
->size
= sizeof(*header
);
3969 header
->count
= count
;
3970 header
->index_offset
= sizeof(*header
);
3971 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3972 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
3974 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3976 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3978 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
3979 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3981 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3982 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
3988 return STATUS_SUCCESS
;
3991 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3993 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
3996 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3998 struct ifacepsredirect_data
*iface
;
3999 struct guid_index
*index
= NULL
;
4001 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4003 if (!actctx
->ifaceps_section
)
4005 struct guidsection_header
*section
;
4007 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4008 if (status
) return status
;
4010 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4011 RtlFreeHeap(GetProcessHeap(), 0, section
);
4014 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4015 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4017 iface
= get_ifaceps_data(actctx
, index
);
4019 data
->ulDataFormatVersion
= 1;
4020 data
->lpData
= iface
;
4021 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4022 data
->lpSectionGlobalData
= NULL
;
4023 data
->ulSectionGlobalDataLength
= 0;
4024 data
->lpSectionBase
= actctx
->ifaceps_section
;
4025 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4026 data
->hActCtx
= NULL
;
4028 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4029 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4031 return STATUS_SUCCESS
;
4034 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4036 unsigned int i
, j
, total_len
= 0, count
= 0;
4037 struct guidsection_header
*header
;
4038 struct clrsurrogate_data
*data
;
4039 struct guid_index
*index
;
4042 /* compute section length */
4043 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4045 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4046 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4048 struct entity
*entity
= &assembly
->entities
.base
[j
];
4049 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4053 total_len
+= sizeof(*index
) + sizeof(*data
);
4054 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4055 if (entity
->u
.clrsurrogate
.version
)
4056 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4057 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4064 total_len
+= sizeof(*header
);
4066 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4067 if (!header
) return STATUS_NO_MEMORY
;
4069 memset(header
, 0, sizeof(*header
));
4070 header
->magic
= GUIDSECTION_MAGIC
;
4071 header
->size
= sizeof(*header
);
4072 header
->count
= count
;
4073 header
->index_offset
= sizeof(*header
);
4074 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4075 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4077 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4079 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4080 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4082 struct entity
*entity
= &assembly
->entities
.base
[j
];
4083 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4085 ULONG version_len
, name_len
;
4089 if (entity
->u
.clrsurrogate
.version
)
4090 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4093 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4095 /* setup new index entry */
4096 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4097 RtlGUIDFromString(&str
, &index
->guid
);
4099 index
->data_offset
= data_offset
;
4100 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4101 index
->rosterindex
= i
+ 1;
4104 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4105 data
->size
= sizeof(*data
);
4107 data
->clsid
= index
->guid
;
4108 data
->version_offset
= version_len
? data
->size
: 0;
4109 data
->version_len
= version_len
;
4110 data
->name_offset
= data
->size
+ version_len
;
4112 data
->name_offset
+= sizeof(WCHAR
);
4113 data
->name_len
= name_len
;
4115 /* surrogate name */
4116 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4117 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4118 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4120 /* runtime version */
4121 if (data
->version_len
)
4123 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4124 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4125 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4128 data_offset
+= index
->data_offset
;
4136 return STATUS_SUCCESS
;
4139 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4141 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4144 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4146 struct clrsurrogate_data
*surrogate
;
4147 struct guid_index
*index
= NULL
;
4149 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4151 if (!actctx
->clrsurrogate_section
)
4153 struct guidsection_header
*section
;
4155 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4156 if (status
) return status
;
4158 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4159 RtlFreeHeap(GetProcessHeap(), 0, section
);
4162 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4163 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4165 surrogate
= get_surrogate_data(actctx
, index
);
4167 data
->ulDataFormatVersion
= 1;
4168 data
->lpData
= surrogate
;
4169 /* full length includes string length with nulls */
4170 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4171 if (surrogate
->version_len
)
4172 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4174 data
->lpSectionGlobalData
= NULL
;
4175 data
->ulSectionGlobalDataLength
= 0;
4176 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4177 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4178 data
->hActCtx
= NULL
;
4180 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4181 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4183 return STATUS_SUCCESS
;
4186 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4188 unsigned int i
, j
, single_len
;
4190 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4191 for (i
= 0; i
< entities
->num
; i
++)
4193 struct entity
*entity
= &entities
->base
[i
];
4194 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4196 if (entity
->u
.comclass
.progid
)
4198 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4202 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4203 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4205 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4206 *count
+= entity
->u
.comclass
.progids
.num
;
4211 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4212 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4214 struct progidredirect_data
*data
;
4219 /* setup new index entry */
4221 /* hash progid name */
4222 RtlInitUnicodeString(&str
, progid
);
4223 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4225 (*index
)->name_offset
= *data_offset
;
4226 (*index
)->name_len
= str
.Length
;
4227 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4228 (*index
)->data_len
= sizeof(*data
);
4229 (*index
)->rosterindex
= rosterindex
;
4231 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4233 /* setup data structure */
4234 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4235 data
->size
= sizeof(*data
);
4237 data
->clsid_offset
= *global_offset
;
4239 /* write progid string */
4240 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4241 memcpy(ptrW
, progid
, (*index
)->name_len
);
4242 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4244 /* write guid to global area */
4245 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4249 *global_offset
+= sizeof(GUID
);
4250 *data_offset
+= data
->size
;
4254 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4255 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4259 for (i
= 0; i
< entities
->num
; i
++)
4261 struct entity
*entity
= &entities
->base
[i
];
4262 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4264 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4265 struct comclassredirect_data
*comclass
;
4266 struct guid_index
*guid_index
;
4270 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4271 RtlGUIDFromString(&str
, &clsid
);
4273 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4274 comclass
= get_comclass_data(actctx
, guid_index
);
4276 if (entity
->u
.comclass
.progid
)
4277 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4278 index
, data_offset
, global_offset
, rosterindex
);
4280 for (j
= 0; j
< progids
->num
; j
++)
4281 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4282 index
, data_offset
, global_offset
, rosterindex
);
4287 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4289 unsigned int i
, j
, total_len
= 0, count
= 0;
4290 struct strsection_header
*header
;
4291 ULONG data_offset
, global_offset
;
4292 struct string_index
*index
;
4294 /* compute section length */
4295 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4297 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4299 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4300 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4302 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4303 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4307 total_len
+= sizeof(*header
);
4309 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4310 if (!header
) return STATUS_NO_MEMORY
;
4312 memset(header
, 0, sizeof(*header
));
4313 header
->magic
= STRSECTION_MAGIC
;
4314 header
->size
= sizeof(*header
);
4315 header
->count
= count
;
4316 header
->global_offset
= header
->size
;
4317 header
->global_len
= count
*sizeof(GUID
);
4318 header
->index_offset
= header
->size
+ header
->global_len
;
4320 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4321 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4322 global_offset
= header
->global_offset
;
4324 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4326 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4328 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4329 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4331 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4332 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4338 return STATUS_SUCCESS
;
4341 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4343 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4346 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4347 PACTCTX_SECTION_KEYED_DATA data
)
4349 struct progidredirect_data
*progid
;
4350 struct string_index
*index
;
4352 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4354 if (!actctx
->comserver_section
)
4356 struct guidsection_header
*section
;
4358 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4359 if (status
) return status
;
4361 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4362 RtlFreeHeap(GetProcessHeap(), 0, section
);
4365 if (!actctx
->progid_section
)
4367 struct strsection_header
*section
;
4369 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4370 if (status
) return status
;
4372 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4373 RtlFreeHeap(GetProcessHeap(), 0, section
);
4376 index
= find_string_index(actctx
->progid_section
, name
);
4377 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4379 progid
= get_progid_data(actctx
, index
);
4381 data
->ulDataFormatVersion
= 1;
4382 data
->lpData
= progid
;
4383 data
->ulLength
= progid
->size
;
4384 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4385 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4386 data
->lpSectionBase
= actctx
->progid_section
;
4387 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4388 data
->hActCtx
= NULL
;
4390 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4391 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4393 return STATUS_SUCCESS
;
4396 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4397 const UNICODE_STRING
*section_name
,
4398 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4402 switch (section_kind
)
4404 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4405 status
= find_dll_redirection(actctx
, section_name
, data
);
4407 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4408 status
= find_window_class(actctx
, section_name
, data
);
4410 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4411 status
= find_progid_redirection(actctx
, section_name
, data
);
4413 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4414 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4415 return STATUS_SXS_SECTION_NOT_FOUND
;
4417 WARN("Unknown section_kind %x\n", section_kind
);
4418 return STATUS_SXS_SECTION_NOT_FOUND
;
4421 if (status
!= STATUS_SUCCESS
) return status
;
4423 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4425 actctx_addref(actctx
);
4426 data
->hActCtx
= actctx
;
4428 return STATUS_SUCCESS
;
4431 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4432 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4436 switch (section_kind
)
4438 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4439 status
= find_tlib_redirection(actctx
, guid
, data
);
4441 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4442 status
= find_comserver_redirection(actctx
, guid
, data
);
4444 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4445 status
= find_cominterface_redirection(actctx
, guid
, data
);
4447 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4448 status
= find_clr_surrogate(actctx
, guid
, data
);
4451 WARN("Unknown section_kind %x\n", section_kind
);
4452 return STATUS_SXS_SECTION_NOT_FOUND
;
4455 if (status
!= STATUS_SUCCESS
) return status
;
4457 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4459 actctx_addref(actctx
);
4460 data
->hActCtx
= actctx
;
4462 return STATUS_SUCCESS
;
4465 /* initialize the activation context for the current process */
4466 void actctx_init(void)
4471 ctx
.cbSize
= sizeof(ctx
);
4472 ctx
.lpSource
= NULL
;
4473 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4474 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4475 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4477 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4481 /***********************************************************************
4482 * RtlCreateActivationContext (NTDLL.@)
4484 * Create an activation context.
4486 * FIXME: function signature/prototype is wrong
4488 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4490 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4491 const WCHAR
*directory
= NULL
;
4492 ACTIVATION_CONTEXT
*actctx
;
4493 UNICODE_STRING nameW
;
4495 NTSTATUS status
= STATUS_NO_MEMORY
;
4497 struct actctx_loader acl
;
4499 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4501 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4502 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4503 return STATUS_INVALID_PARAMETER
;
4505 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4506 return STATUS_NO_MEMORY
;
4508 actctx
->magic
= ACTCTX_MAGIC
;
4509 actctx
->ref_count
= 1;
4510 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4511 actctx
->config
.info
= NULL
;
4512 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4513 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4515 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4523 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4524 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4526 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4527 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4528 actctx
->appdir
.info
= dir
.Buffer
;
4531 nameW
.Buffer
= NULL
;
4533 /* open file only if it's going to be used */
4534 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4535 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4537 if (!RtlDosPathNameToNtPathName_U(pActCtx
->lpSource
, &nameW
, NULL
, NULL
))
4539 status
= STATUS_NO_SUCH_FILE
;
4542 status
= open_nt_file( &file
, &nameW
);
4545 RtlFreeUnicodeString( &nameW
);
4550 acl
.actctx
= actctx
;
4551 acl
.dependencies
= NULL
;
4552 acl
.num_dependencies
= 0;
4553 acl
.allocated_dependencies
= 0;
4555 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4556 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4558 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4560 /* if we have a resource it's a PE file */
4561 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4563 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4564 pActCtx
->lpResourceName
, lang
);
4565 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4566 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4567 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4569 else if (pActCtx
->lpSource
)
4571 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4572 file
, pActCtx
->lpResourceName
, lang
);
4573 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4574 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4575 NULL
, pActCtx
->lpResourceName
);
4577 else status
= STATUS_INVALID_PARAMETER
;
4581 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4584 if (file
) NtClose( file
);
4585 RtlFreeUnicodeString( &nameW
);
4587 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4588 free_depend_manifests( &acl
);
4590 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4591 else actctx_release( actctx
);
4595 if (file
) NtClose( file
);
4596 actctx_release( actctx
);
4601 /***********************************************************************
4602 * RtlAddRefActivationContext (NTDLL.@)
4604 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4606 ACTIVATION_CONTEXT
*actctx
;
4608 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4612 /******************************************************************
4613 * RtlReleaseActivationContext (NTDLL.@)
4615 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
4617 ACTIVATION_CONTEXT
*actctx
;
4619 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4622 /******************************************************************
4623 * RtlZombifyActivationContext (NTDLL.@)
4625 * FIXME: function prototype might be wrong
4627 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
4629 FIXME("%p: stub\n", handle
);
4630 return STATUS_NOT_IMPLEMENTED
;
4633 /******************************************************************
4634 * RtlActivateActivationContext (NTDLL.@)
4636 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
4638 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4640 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
4641 return STATUS_NO_MEMORY
;
4643 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4644 frame
->ActivationContext
= handle
;
4646 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
4647 RtlAddRefActivationContext( handle
);
4649 *cookie
= (ULONG_PTR
)frame
;
4650 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
4651 return STATUS_SUCCESS
;
4655 /***********************************************************************
4656 * RtlDeactivateActivationContext (NTDLL.@)
4658 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4660 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4662 TRACE( "%x cookie=%lx\n", flags
, cookie
);
4664 /* find the right frame */
4665 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4666 for (frame
= top
; frame
; frame
= frame
->Previous
)
4667 if ((ULONG_PTR
)frame
== cookie
) break;
4670 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4672 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
4673 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4675 /* pop everything up to and including frame */
4676 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
4678 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4680 frame
= top
->Previous
;
4681 RtlReleaseActivationContext( top
->ActivationContext
);
4682 RtlFreeHeap( GetProcessHeap(), 0, top
);
4688 /******************************************************************
4689 * RtlFreeThreadActivationContextStack (NTDLL.@)
4691 void WINAPI
RtlFreeThreadActivationContextStack(void)
4693 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4695 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4698 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
4699 RtlReleaseActivationContext( frame
->ActivationContext
);
4700 RtlFreeHeap( GetProcessHeap(), 0, frame
);
4703 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
4707 /******************************************************************
4708 * RtlGetActiveActivationContext (NTDLL.@)
4710 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
4712 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4714 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
4715 RtlAddRefActivationContext( *handle
);
4720 return STATUS_SUCCESS
;
4724 /******************************************************************
4725 * RtlIsActivationContextActive (NTDLL.@)
4727 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
4729 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4731 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
4732 if (frame
->ActivationContext
== handle
) return TRUE
;
4737 /***********************************************************************
4738 * RtlQueryInformationActivationContext (NTDLL.@)
4740 * Get information about an activation context.
4741 * FIXME: function signature/prototype may be wrong
4743 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
4744 ULONG
class, PVOID buffer
,
4745 SIZE_T bufsize
, SIZE_T
*retlen
)
4747 ACTIVATION_CONTEXT
*actctx
;
4750 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
4751 subinst
, class, buffer
, bufsize
, retlen
);
4753 if (retlen
) *retlen
= 0;
4754 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
4758 case ActivationContextBasicInformation
:
4760 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
4762 if (retlen
) *retlen
= sizeof(*info
);
4763 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
4765 info
->hActCtx
= handle
;
4766 info
->dwFlags
= 0; /* FIXME */
4767 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
4771 case ActivationContextDetailedInformation
:
4773 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
4774 struct assembly
*assembly
= NULL
;
4775 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
4778 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4780 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
4782 if (assembly
&& assembly
->manifest
.info
)
4783 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
4784 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
4785 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
4786 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
4788 if (retlen
) *retlen
= len
;
4789 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
4792 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
4793 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
4794 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
4795 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
4796 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
4797 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
4798 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
4799 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
4800 ptr
= (LPWSTR
)(acdi
+ 1);
4803 acdi
->lpRootManifestPath
= ptr
;
4804 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
4805 ptr
+= manifest_len
;
4807 else acdi
->lpRootManifestPath
= NULL
;
4810 acdi
->lpRootConfigurationPath
= ptr
;
4811 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
4814 else acdi
->lpRootConfigurationPath
= NULL
;
4817 acdi
->lpAppDirPath
= ptr
;
4818 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
4820 else acdi
->lpAppDirPath
= NULL
;
4824 case AssemblyDetailedInformationInActivationContext
:
4826 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
4827 struct assembly
*assembly
;
4830 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
4833 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4834 if (!subinst
) return STATUS_INVALID_PARAMETER
;
4836 index
= *(DWORD
*)subinst
;
4837 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
4839 assembly
= &actctx
->assemblies
[index
- 1];
4841 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
4842 id_len
= strlenW(assembly_id
) + 1;
4843 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
4845 if (assembly
->manifest
.info
&&
4846 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
4847 path_len
= strlenW(assembly
->manifest
.info
) + 1;
4849 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
4851 if (retlen
) *retlen
= len
;
4852 if (!buffer
|| bufsize
< len
)
4854 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4855 return STATUS_BUFFER_TOO_SMALL
;
4858 afdi
->ulFlags
= 0; /* FIXME */
4859 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
4860 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
4861 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
4862 /* FIXME afdi->liManifestLastWriteTime = 0; */
4863 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
4864 afdi
->ulPolicyPathLength
= 0;
4865 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4866 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
4867 afdi
->ulManifestVersionMajor
= 1;
4868 afdi
->ulManifestVersionMinor
= 0;
4869 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
4870 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
4871 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
4872 ptr
= (LPWSTR
)(afdi
+ 1);
4873 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
4874 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
4878 afdi
->lpAssemblyManifestPath
= ptr
;
4879 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
4881 } else afdi
->lpAssemblyManifestPath
= NULL
;
4882 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
4885 afdi
->lpAssemblyDirectoryName
= ptr
;
4886 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
4888 else afdi
->lpAssemblyDirectoryName
= NULL
;
4889 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4893 case FileInformationInAssemblyOfAssemblyInActivationContext
:
4895 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
4896 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
4897 struct assembly
*assembly
;
4898 struct dll_redirect
*dll
;
4899 SIZE_T len
, dll_len
= 0;
4902 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4903 if (!acqi
) return STATUS_INVALID_PARAMETER
;
4905 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
4906 return STATUS_INVALID_PARAMETER
;
4907 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
4909 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
4910 return STATUS_INVALID_PARAMETER
;
4911 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
4913 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
4914 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
4916 if (!buffer
|| bufsize
< len
)
4918 if (retlen
) *retlen
= len
;
4919 return STATUS_BUFFER_TOO_SMALL
;
4921 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
4922 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
4923 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
4924 afdi
->ulPathLength
= 0; /* FIXME */
4925 ptr
= (LPWSTR
)(afdi
+ 1);
4928 afdi
->lpFileName
= ptr
;
4929 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
4930 } else afdi
->lpFileName
= NULL
;
4931 afdi
->lpFilePath
= NULL
; /* FIXME */
4936 FIXME( "class %u not implemented\n", class );
4937 return STATUS_NOT_IMPLEMENTED
;
4939 return STATUS_SUCCESS
;
4942 /***********************************************************************
4943 * RtlFindActivationContextSectionString (NTDLL.@)
4945 * Find information about a string in an activation context.
4946 * FIXME: function signature/prototype may be wrong
4948 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
4949 const UNICODE_STRING
*section_name
, PVOID ptr
)
4951 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
4952 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
4954 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
4955 debugstr_us(section_name
), data
);
4959 FIXME("expected guid == NULL\n");
4960 return STATUS_INVALID_PARAMETER
;
4962 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4964 FIXME("unknown flags %08x\n", flags
);
4965 return STATUS_INVALID_PARAMETER
;
4967 if (!data
|| data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) ||
4968 !section_name
|| !section_name
->Buffer
)
4970 WARN("invalid parameter\n");
4971 return STATUS_INVALID_PARAMETER
;
4974 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4976 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
4977 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
4980 if (status
!= STATUS_SUCCESS
)
4981 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
4986 /***********************************************************************
4987 * RtlFindActivationContextSectionGuid (NTDLL.@)
4989 * Find information about a GUID in an activation context.
4990 * FIXME: function signature/prototype may be wrong
4992 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
4993 const GUID
*guid
, void *ptr
)
4995 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
4996 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
4998 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5002 FIXME("expected extguid == NULL\n");
5003 return STATUS_INVALID_PARAMETER
;
5006 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5008 FIXME("unknown flags %08x\n", flags
);
5009 return STATUS_INVALID_PARAMETER
;
5012 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5013 return STATUS_INVALID_PARAMETER
;
5015 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5017 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5018 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5021 if (status
!= STATUS_SUCCESS
)
5022 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);