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
);
854 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
856 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
857 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
858 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
860 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
861 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
863 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
864 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
865 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
866 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
869 FIXME("Unknown entity kind %d\n", entity
->kind
);
872 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
875 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
877 if (!str1
) return !str2
;
878 return str2
&& !strcmpiW( str1
, str2
);
881 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
882 const struct assembly_identity
*id2
)
884 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
885 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
886 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
888 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
890 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
893 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
894 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
895 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
896 if (id1
->version
.build
== id2
->version
.build
&&
897 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
901 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
902 struct assembly_identity
* ai
)
906 /* check if we already have that assembly */
908 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
909 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
911 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
912 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
913 ai
->version
.build
, ai
->version
.revision
);
917 for (i
= 0; i
< acl
->num_dependencies
; i
++)
918 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
920 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
921 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
922 ai
->version
.build
, ai
->version
.revision
);
926 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
929 unsigned int new_count
;
930 if (acl
->dependencies
)
932 new_count
= acl
->allocated_dependencies
* 2;
933 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
934 new_count
* sizeof(acl
->dependencies
[0]));
939 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
941 if (!ptr
) return FALSE
;
942 acl
->dependencies
= ptr
;
943 acl
->allocated_dependencies
= new_count
;
945 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
950 static void free_depend_manifests(struct actctx_loader
* acl
)
953 for (i
= 0; i
< acl
->num_dependencies
; i
++)
954 free_assembly_identity(&acl
->dependencies
[i
]);
955 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
958 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
960 static const WCHAR undW
[] = {'_',0};
961 static const WCHAR noneW
[] = {'n','o','n','e',0};
962 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
964 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
965 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
966 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
967 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
968 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
969 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
972 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
974 strcpyW( ret
, arch
);
975 strcatW( ret
, undW
);
976 strcatW( ret
, name
);
977 strcatW( ret
, undW
);
979 strcatW( ret
, undW
);
980 sprintfW( ret
+ strlenW(ret
), version_formatW
,
981 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
982 strcatW( ret
, undW
);
983 strcatW( ret
, lang
);
984 strcatW( ret
, undW
);
985 strcatW( ret
, mskeyW
);
989 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
994 strcatW( buffer
, prefix
);
1003 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1005 static const WCHAR archW
[] =
1006 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1007 static const WCHAR public_keyW
[] =
1008 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1009 static const WCHAR typeW
[] =
1010 {',','t','y','p','e','=',0};
1011 static const WCHAR versionW
[] =
1012 {',','v','e','r','s','i','o','n','=',0};
1014 WCHAR version
[64], *ret
;
1017 sprintfW( version
, version_formatW
,
1018 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1019 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1020 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1021 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1022 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
1023 size
+= strlenW(versionW
) + strlenW(version
) + 2;
1025 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1028 if (ai
->name
) strcpyW( ret
, ai
->name
);
1030 append_string( ret
, archW
, ai
->arch
);
1031 append_string( ret
, public_keyW
, ai
->public_key
);
1032 append_string( ret
, typeW
, ai
->type
);
1033 append_string( ret
, versionW
, version
);
1037 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1039 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1041 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1044 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1053 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1055 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1058 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1060 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1064 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1066 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1067 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1069 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1070 free_entity_array( &dll
->entities
);
1071 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1072 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1074 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1077 free_entity_array( &assembly
->entities
);
1078 free_assembly_identity(&assembly
->id
);
1080 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1091 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1095 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1096 BOOL
* error
, BOOL
* end
)
1102 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1105 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1107 if (*xmlbuf
->ptr
== '/')
1110 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1119 if (*xmlbuf
->ptr
== '>')
1127 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1129 if (ptr
== xmlbuf
->end
) return FALSE
;
1131 name
->ptr
= xmlbuf
->ptr
;
1132 name
->len
= ptr
-xmlbuf
->ptr
;
1135 /* skip spaces before '=' */
1136 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1137 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1139 /* skip '=' itself */
1141 if (ptr
== xmlbuf
->end
) return FALSE
;
1143 /* skip spaces after '=' */
1144 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1146 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1149 if (ptr
== xmlbuf
->end
) return FALSE
;
1151 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1154 xmlbuf
->ptr
= xmlbuf
->end
;
1158 value
->len
= ptr
- value
->ptr
;
1159 xmlbuf
->ptr
= ptr
+ 1;
1161 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1167 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1173 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1176 xmlbuf
->ptr
= xmlbuf
->end
;
1180 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1182 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1183 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1185 if (ptr
+ 3 > xmlbuf
->end
)
1187 xmlbuf
->ptr
= xmlbuf
->end
;
1190 xmlbuf
->ptr
= ptr
+ 3;
1196 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1199 elem
->ptr
= xmlbuf
->ptr
;
1200 elem
->len
= ptr
- xmlbuf
->ptr
;
1202 return xmlbuf
->ptr
!= xmlbuf
->end
;
1205 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1207 /* FIXME: parse attributes */
1210 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1212 if (ptr
[0] == '?' && ptr
[1] == '>')
1214 xmlbuf
->ptr
= ptr
+ 2;
1221 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1223 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1225 if (!ptr
) return FALSE
;
1227 content
->ptr
= xmlbuf
->ptr
;
1228 content
->len
= ptr
- xmlbuf
->ptr
;
1234 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1236 unsigned int ver
[4];
1240 /* major.minor.build.revision */
1241 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1242 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1244 if (*curr
>= '0' && *curr
<= '9')
1246 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1247 if (ver
[pos
] >= 0x10000) goto error
;
1249 else if (*curr
== '.')
1251 if (++pos
>= 4) goto error
;
1255 version
->major
= ver
[0];
1256 version
->minor
= ver
[1];
1257 version
->build
= ver
[2];
1258 version
->revision
= ver
[3];
1262 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1266 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1269 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1270 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1271 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1275 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1277 xmlstr_t attr_name
, attr_value
;
1280 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1282 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1283 debugstr_xmlstr(&attr_value
));
1288 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1291 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1294 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1297 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1298 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1300 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1303 return parse_end_element(xmlbuf
);
1306 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1308 xmlstr_t attr_name
, attr_value
, elem
;
1309 BOOL end
= FALSE
, error
, ret
= TRUE
;
1311 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1312 if(error
|| end
) return end
;
1314 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1316 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1317 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1320 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1323 return ret
&& parse_end_element(xmlbuf
);
1326 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1327 struct assembly_identity
* ai
)
1329 xmlstr_t attr_name
, attr_value
;
1330 BOOL end
= FALSE
, error
;
1332 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1334 if (xmlstr_cmp(&attr_name
, nameW
))
1336 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1338 else if (xmlstr_cmp(&attr_name
, typeW
))
1340 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1342 else if (xmlstr_cmp(&attr_name
, versionW
))
1344 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1346 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1348 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1350 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1352 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1354 else if (xmlstr_cmp(&attr_name
, languageW
))
1356 WARN("Unsupported yet language attribute (%s)\n",
1357 debugstr_xmlstr(&attr_value
));
1358 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1362 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1363 debugstr_xmlstr(&attr_value
));
1367 TRACE( "name=%s version=%s arch=%s\n",
1368 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1370 if (error
|| end
) return end
;
1371 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1374 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1376 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1377 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1378 static const WCHAR freeW
[] = {'F','r','e','e',0};
1379 static const WCHAR bothW
[] = {'B','o','t','h',0};
1381 if (value
->len
== 0) return ThreadingModel_No
;
1382 if (xmlstr_cmp(value
, apartW
))
1383 return ThreadingModel_Apartment
;
1384 else if (xmlstr_cmp(value
, freeW
))
1385 return ThreadingModel_Free
;
1386 else if (xmlstr_cmp(value
, bothW
))
1387 return ThreadingModel_Both
;
1388 else if (xmlstr_cmp(value
, neutralW
))
1389 return ThreadingModel_Neutral
;
1391 return ThreadingModel_No
;
1394 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1399 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1407 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1408 if (!c
&& !olemisc_values
[n
].name
[len
])
1409 return olemisc_values
[n
].value
;
1417 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1421 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1423 const WCHAR
*str
= value
->ptr
, *start
;
1427 /* it's comma separated list of flags */
1428 while (i
< value
->len
)
1431 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1433 flags
|= get_olemisc_value(start
, str
-start
);
1435 /* skip separator */
1443 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1445 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1447 if (progids
->allocated
== 0)
1449 progids
->allocated
= 4;
1450 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1453 if (progids
->allocated
== progids
->num
)
1455 progids
->allocated
*= 2;
1456 progids
->progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
, progids
->allocated
* sizeof(WCHAR
*));
1459 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1465 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1470 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1473 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1474 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1477 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1479 xmlstr_t elem
, attr_name
, attr_value
;
1480 BOOL ret
= TRUE
, end
= FALSE
, error
;
1481 struct entity
* entity
;
1483 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1486 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1488 if (xmlstr_cmp(&attr_name
, clsidW
))
1490 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1492 else if (xmlstr_cmp(&attr_name
, progidW
))
1494 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1496 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1498 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1500 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1502 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1504 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1506 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1508 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1510 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1512 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1514 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1516 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1518 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1520 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1522 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1524 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1530 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1534 if (error
) return FALSE
;
1536 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1537 if (entity
->u
.comclass
.progid
)
1538 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1540 if (end
) return TRUE
;
1542 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1544 if (xmlstr_cmp_end(&elem
, comClassW
))
1546 ret
= parse_end_element(xmlbuf
);
1549 else if (xmlstr_cmp(&elem
, progidW
))
1551 ret
= parse_com_class_progid(xmlbuf
, entity
);
1555 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1556 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1560 if (entity
->u
.comclass
.progids
.num
)
1561 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1566 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1571 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1573 if (*curr
>= '0' && *curr
<= '9')
1574 num
= num
* 10 + *curr
- '0';
1577 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1581 entity
->u
.ifaceps
.nummethods
= num
;
1586 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1588 xmlstr_t attr_name
, attr_value
;
1589 BOOL end
= FALSE
, error
;
1590 struct entity
* entity
;
1592 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1595 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1597 if (xmlstr_cmp(&attr_name
, iidW
))
1599 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1601 else if (xmlstr_cmp(&attr_name
, nameW
))
1603 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1605 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1607 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1608 entity
->u
.ifaceps
.mask
|= BaseIface
;
1610 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1612 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1613 entity
->u
.ifaceps
.mask
|= NumMethods
;
1615 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1617 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1620 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1625 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1629 if (error
) return FALSE
;
1630 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1631 if (end
) return TRUE
;
1633 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1636 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1638 WORD
*flags
= &entity
->u
.typelib
.flags
;
1639 const WCHAR
*str
= value
->ptr
, *start
;
1644 /* it's comma separated list of flags */
1645 while (i
< value
->len
)
1648 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1650 if (!strncmpiW(start
, restrictedW
, str
-start
))
1651 *flags
|= LIBFLAG_FRESTRICTED
;
1652 else if (!strncmpiW(start
, controlW
, str
-start
))
1653 *flags
|= LIBFLAG_FCONTROL
;
1654 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1655 *flags
|= LIBFLAG_FHIDDEN
;
1656 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1657 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1660 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1664 /* skip separator */
1672 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1674 unsigned int ver
[2];
1679 ver
[0] = ver
[1] = pos
= 0;
1680 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1682 if (*curr
>= '0' && *curr
<= '9')
1684 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1685 if (ver
[pos
] >= 0x10000) goto error
;
1687 else if (*curr
== '.')
1689 if (++pos
>= 2) goto error
;
1693 entity
->u
.typelib
.major
= ver
[0];
1694 entity
->u
.typelib
.minor
= ver
[1];
1698 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1702 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1704 xmlstr_t attr_name
, attr_value
;
1705 BOOL end
= FALSE
, error
;
1706 struct entity
* entity
;
1708 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1711 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1713 if (xmlstr_cmp(&attr_name
, tlbidW
))
1715 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1717 else if (xmlstr_cmp(&attr_name
, versionW
))
1719 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1721 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1723 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1725 else if (xmlstr_cmp(&attr_name
, flagsW
))
1727 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1731 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1735 if (error
) return FALSE
;
1737 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1739 if (end
) return TRUE
;
1741 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1744 static inline int aligned_string_len(int len
)
1746 return (len
+ 3) & ~3;
1749 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1751 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1752 struct assembly_version
*ver
= &assembly
->id
.version
;
1755 if (!ret
) ret
= buff
;
1756 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1759 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1761 xmlstr_t elem
, content
, attr_name
, attr_value
;
1762 BOOL end
= FALSE
, ret
= TRUE
, error
;
1763 struct entity
* entity
;
1765 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1768 entity
->u
.class.versioned
= TRUE
;
1769 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1771 if (xmlstr_cmp(&attr_name
, versionedW
))
1773 if (xmlstr_cmpi(&attr_value
, noW
))
1774 entity
->u
.class.versioned
= FALSE
;
1775 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1780 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1784 if (error
|| end
) return end
;
1786 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1788 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1790 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1792 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1794 if (xmlstr_cmp_end(&elem
, windowClassW
))
1796 ret
= parse_end_element(xmlbuf
);
1801 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1802 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1809 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1811 xmlstr_t attr_name
, attr_value
;
1812 BOOL end
= FALSE
, error
;
1814 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1816 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1818 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value
));
1820 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1822 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value
));
1826 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1830 if (error
|| end
) return end
;
1831 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1834 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1836 xmlstr_t elem
, content
;
1837 BOOL end
= FALSE
, ret
= TRUE
;
1839 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
||
1840 !parse_text_content(xmlbuf
, &content
))
1843 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1845 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1847 if (xmlstr_cmp_end(&elem
, descriptionW
))
1849 ret
= parse_end_element(xmlbuf
);
1854 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1855 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1862 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1863 struct assembly
* assembly
,
1864 struct actctx_loader
* acl
)
1866 xmlstr_t attr_name
, attr_value
;
1867 BOOL end
= FALSE
, error
;
1868 struct entity
* entity
;
1870 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1871 if (!entity
) return FALSE
;
1873 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1875 if (xmlstr_cmp(&attr_name
, iidW
))
1877 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1879 else if (xmlstr_cmp(&attr_name
, nameW
))
1881 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1883 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1885 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1886 entity
->u
.ifaceps
.mask
|= BaseIface
;
1888 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1890 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1891 entity
->u
.ifaceps
.mask
|= NumMethods
;
1893 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1895 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1897 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1899 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1903 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1907 if (error
) return FALSE
;
1908 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1909 if (end
) return TRUE
;
1911 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
1914 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1916 xmlstr_t attr_name
, attr_value
, elem
;
1917 BOOL end
= FALSE
, error
, ret
= TRUE
;
1918 struct entity
* entity
;
1920 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
1921 if (!entity
) return FALSE
;
1923 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1925 if (xmlstr_cmp(&attr_name
, nameW
))
1927 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1929 else if (xmlstr_cmp(&attr_name
, clsidW
))
1931 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1933 else if (xmlstr_cmp(&attr_name
, progidW
))
1935 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1937 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1939 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1941 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1943 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1945 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
1947 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
1951 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1955 if (error
) return FALSE
;
1956 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1957 if (entity
->u
.comclass
.progid
)
1958 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1959 if (end
) return TRUE
;
1961 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1963 if (xmlstr_cmp_end(&elem
, clrClassW
))
1965 ret
= parse_end_element(xmlbuf
);
1968 else if (xmlstr_cmp(&elem
, progidW
))
1970 ret
= parse_com_class_progid(xmlbuf
, entity
);
1974 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1975 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1979 if (entity
->u
.comclass
.progids
.num
)
1980 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1985 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1987 xmlstr_t attr_name
, attr_value
;
1988 BOOL end
= FALSE
, error
;
1989 struct entity
* entity
;
1991 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
1992 if (!entity
) return FALSE
;
1994 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1996 if (xmlstr_cmp(&attr_name
, nameW
))
1998 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2000 else if (xmlstr_cmp(&attr_name
, clsidW
))
2002 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2004 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2006 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2010 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2014 if (error
) return FALSE
;
2015 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2016 if (end
) return TRUE
;
2018 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2021 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2023 struct assembly_identity ai
;
2025 BOOL end
= FALSE
, ret
= TRUE
;
2027 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
) return end
;
2029 memset(&ai
, 0, sizeof(ai
));
2030 ai
.optional
= optional
;
2032 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2033 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2036 TRACE( "adding name=%s version=%s arch=%s\n",
2037 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2039 /* store the newly found identity for later loading */
2040 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2042 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2044 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2046 ret
= parse_end_element(xmlbuf
);
2049 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2051 ret
= parse_binding_redirect_elem(xmlbuf
);
2055 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2056 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2063 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2065 xmlstr_t attr_name
, attr_value
, elem
;
2066 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2068 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2070 if (xmlstr_cmp(&attr_name
, optionalW
))
2072 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2073 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value
));
2077 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2081 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2083 if (xmlstr_cmp_end(&elem
, dependencyW
))
2085 ret
= parse_end_element(xmlbuf
);
2088 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2090 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2094 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2095 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2102 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2106 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2107 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2110 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2114 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2115 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2118 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2120 xmlstr_t attr_name
, attr_value
, elem
;
2121 BOOL end
= FALSE
, error
, ret
= TRUE
;
2122 struct dll_redirect
* dll
;
2124 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2126 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2128 if (xmlstr_cmp(&attr_name
, nameW
))
2130 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2131 TRACE("name=%s\n", debugstr_xmlstr(&attr_value
));
2133 else if (xmlstr_cmp(&attr_name
, hashW
))
2135 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2137 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2139 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2140 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2141 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value
));
2145 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2149 if (error
|| !dll
->name
) return FALSE
;
2151 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2153 if (end
) return TRUE
;
2155 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2157 if (xmlstr_cmp_end(&elem
, fileW
))
2159 ret
= parse_end_element(xmlbuf
);
2162 else if (xmlstr_cmp(&elem
, comClassW
))
2164 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2166 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2168 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2170 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2172 WARN("asmv2:hash (undocumented) not supported\n");
2173 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2175 else if (xmlstr_cmp(&elem
, typelibW
))
2177 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2179 else if (xmlstr_cmp(&elem
, windowClassW
))
2181 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2185 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2186 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2193 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2194 struct assembly
* assembly
,
2195 struct assembly_identity
* expected_ai
)
2197 xmlstr_t attr_name
, attr_value
, elem
;
2198 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2200 TRACE("(%p)\n", xmlbuf
);
2202 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2204 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2206 static const WCHAR v10W
[] = {'1','.','0',0};
2207 if (!xmlstr_cmp(&attr_value
, v10W
))
2209 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
2214 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2216 if (!xmlstr_cmp(&attr_value
, manifestv1W
) && !xmlstr_cmp(&attr_value
, manifestv3W
))
2218 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
2225 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2229 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2230 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2232 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2234 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2236 assembly
->no_inherit
= TRUE
;
2239 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2241 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2244 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2245 assembly
->no_inherit
)
2250 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2252 ret
= parse_end_element(xmlbuf
);
2255 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2257 ret
= parse_description_elem(xmlbuf
);
2259 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2261 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2263 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2265 ret
= parse_dependency_elem(xmlbuf
, acl
);
2267 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2269 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2271 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2273 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2275 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2277 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2279 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2281 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2285 /* FIXME: more tests */
2286 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2287 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2289 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2290 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2291 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2292 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2293 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2296 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2297 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2298 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2299 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2300 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2301 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2303 FIXME("wrong version for shared assembly manifest\n");
2310 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2311 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2313 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2319 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2320 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2324 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2326 if (xmlstr_cmp(&elem
, xmlW
) &&
2327 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2328 return STATUS_SXS_CANT_GEN_ACTCTX
;
2330 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2332 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
2333 return STATUS_SXS_CANT_GEN_ACTCTX
;
2336 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2338 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2339 return STATUS_SXS_CANT_GEN_ACTCTX
;
2342 if (next_xml_elem(xmlbuf
, &elem
))
2344 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2345 return STATUS_SXS_CANT_GEN_ACTCTX
;
2348 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2350 FIXME("parse error\n");
2351 return STATUS_SXS_CANT_GEN_ACTCTX
;
2353 return STATUS_SUCCESS
;
2356 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2357 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2358 const void *buffer
, SIZE_T size
)
2362 struct assembly
*assembly
;
2365 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2367 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2368 return STATUS_SXS_CANT_GEN_ACTCTX
;
2370 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2371 return STATUS_NO_MEMORY
;
2373 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2374 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2375 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2377 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2378 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2380 xmlbuf
.ptr
= buffer
;
2381 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2382 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2384 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2386 const WCHAR
*buf
= buffer
;
2390 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2391 return STATUS_NO_MEMORY
;
2392 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2393 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2394 xmlbuf
.ptr
= new_buff
;
2395 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2396 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2397 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2401 /* let's assume utf-8 for now */
2402 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2407 FIXME( "utf-8 conversion failed\n" );
2408 return STATUS_SXS_CANT_GEN_ACTCTX
;
2410 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2411 return STATUS_NO_MEMORY
;
2412 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2413 xmlbuf
.ptr
= new_buff
;
2414 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2415 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2416 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2421 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2423 OBJECT_ATTRIBUTES attr
;
2426 attr
.Length
= sizeof(attr
);
2427 attr
.RootDirectory
= 0;
2428 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2429 attr
.ObjectName
= name
;
2430 attr
.SecurityDescriptor
= NULL
;
2431 attr
.SecurityQualityOfService
= NULL
;
2432 return NtOpenFile( handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2435 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2441 LdrLockLoaderLock(0, NULL
, &magic
);
2442 status
= LdrFindEntryForAddress( module
, &pldr
);
2443 if (status
== STATUS_SUCCESS
)
2445 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2446 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2448 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2449 str
->Length
= pldr
->FullDllName
.Length
;
2450 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2452 else status
= STATUS_NO_MEMORY
;
2454 LdrUnlockLoaderLock(0, magic
);
2458 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2459 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2460 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2463 UNICODE_STRING nameW
;
2464 LDR_RESOURCE_INFO info
;
2465 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2468 if (TRACE_ON(actctx
))
2470 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2472 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2473 hModule
, debugstr_w(nameW
.Buffer
) );
2474 RtlFreeUnicodeString( &nameW
);
2476 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2477 hModule
, debugstr_w(filename
) );
2480 if (!resname
) return STATUS_INVALID_PARAMETER
;
2482 info
.Type
= RT_MANIFEST
;
2483 info
.Language
= lang
;
2484 if (!((ULONG_PTR
)resname
>> 16))
2486 info
.Name
= (ULONG_PTR
)resname
;
2487 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2489 else if (resname
[0] == '#')
2492 RtlInitUnicodeString(&nameW
, resname
+ 1);
2493 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2494 return STATUS_INVALID_PARAMETER
;
2496 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2500 RtlCreateUnicodeString(&nameW
, resname
);
2501 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2502 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2503 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2504 RtlFreeUnicodeString(&nameW
);
2506 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2508 if (status
== STATUS_SUCCESS
)
2509 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2514 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2515 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2516 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2519 OBJECT_ATTRIBUTES attr
;
2521 LARGE_INTEGER offset
;
2526 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2528 attr
.Length
= sizeof(attr
);
2529 attr
.RootDirectory
= 0;
2530 attr
.ObjectName
= NULL
;
2531 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2532 attr
.SecurityDescriptor
= NULL
;
2533 attr
.SecurityQualityOfService
= NULL
;
2536 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2537 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2538 if (status
!= STATUS_SUCCESS
) return status
;
2540 offset
.QuadPart
= 0;
2543 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2544 &count
, ViewShare
, 0, PAGE_READONLY
);
2546 if (status
!= STATUS_SUCCESS
) return status
;
2548 if (RtlImageNtHeader(base
)) /* we got a PE file */
2550 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2551 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2553 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2555 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2559 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2560 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2562 FILE_END_OF_FILE_INFORMATION info
;
2565 OBJECT_ATTRIBUTES attr
;
2567 LARGE_INTEGER offset
;
2572 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2574 attr
.Length
= sizeof(attr
);
2575 attr
.RootDirectory
= 0;
2576 attr
.ObjectName
= NULL
;
2577 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2578 attr
.SecurityDescriptor
= NULL
;
2579 attr
.SecurityQualityOfService
= NULL
;
2582 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2583 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2584 if (status
!= STATUS_SUCCESS
) return status
;
2586 offset
.QuadPart
= 0;
2589 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2590 &count
, ViewShare
, 0, PAGE_READONLY
);
2592 if (status
!= STATUS_SUCCESS
) return status
;
2594 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2595 if (status
== STATUS_SUCCESS
)
2596 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2598 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2602 /* try to load the .manifest file associated to the file */
2603 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2604 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2606 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2609 UNICODE_STRING nameW
;
2611 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2613 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2615 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2617 if (module
) /* use the module filename */
2619 UNICODE_STRING name
;
2621 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2623 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2624 strcatW( name
.Buffer
, dotManifestW
);
2625 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2626 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2627 RtlFreeUnicodeString( &name
);
2629 if (status
) return status
;
2633 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2634 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2635 return STATUS_NO_MEMORY
;
2636 strcpyW( buffer
, filename
);
2637 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2638 strcatW( buffer
, dotManifestW
);
2639 RtlInitUnicodeString( &nameW
, buffer
);
2642 if (!open_nt_file( &file
, &nameW
))
2644 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2647 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2648 RtlFreeUnicodeString( &nameW
);
2652 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2654 static const WCHAR lookup_fmtW
[] =
2655 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2656 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2657 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2659 WCHAR
*lookup
, *ret
= NULL
;
2660 UNICODE_STRING lookup_us
;
2662 const WCHAR
*lang
= ai
->language
;
2663 unsigned int data_pos
= 0, data_len
;
2666 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2667 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2668 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2669 + sizeof(lookup_fmtW
) )))
2672 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2673 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2674 ai
->version
.major
, ai
->version
.minor
, lang
);
2675 RtlInitUnicodeString( &lookup_us
, lookup
);
2677 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2678 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2679 if (io
.u
.Status
== STATUS_SUCCESS
)
2681 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2682 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2684 ULONG build
, revision
;
2686 data_len
= io
.Information
;
2690 if (data_pos
>= data_len
)
2692 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2693 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2694 if (io
.u
.Status
!= STATUS_SUCCESS
) break;
2695 data_len
= io
.Information
;
2698 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2700 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2701 else data_pos
= data_len
;
2703 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2705 if (build
< min_build
) continue;
2706 tmp
= strchrW(tmp
, '.') + 1;
2707 revision
= atoiW(tmp
);
2708 if (build
== min_build
&& revision
< min_revision
) continue;
2709 tmp
= strchrW(tmp
, '_') + 1;
2710 tmp
= strchrW(tmp
, '_') + 1;
2711 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2712 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2714 /* prefer a non-Wine manifest if we already have one */
2715 /* we'll still load the builtin dll if specified through DllOverrides */
2721 min_revision
= revision
;
2723 ai
->version
.build
= build
;
2724 ai
->version
.revision
= revision
;
2725 RtlFreeHeap( GetProcessHeap(), 0, ret
);
2726 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2728 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2729 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2733 else WARN("no matching file for %s\n", debugstr_w(lookup
));
2734 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
2738 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2740 struct assembly_identity sxs_ai
;
2741 UNICODE_STRING path_us
;
2742 OBJECT_ATTRIBUTES attr
;
2744 WCHAR
*path
, *file
= NULL
;
2747 static const WCHAR manifest_dirW
[] =
2748 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2750 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2752 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
2753 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
2754 return STATUS_NO_MEMORY
;
2756 strcpyW( path
, user_shared_data
->NtSystemRoot
);
2757 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
2759 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2761 RtlFreeHeap( GetProcessHeap(), 0, path
);
2762 return STATUS_NO_SUCH_FILE
;
2764 RtlFreeHeap( GetProcessHeap(), 0, path
);
2766 attr
.Length
= sizeof(attr
);
2767 attr
.RootDirectory
= 0;
2768 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2769 attr
.ObjectName
= &path_us
;
2770 attr
.SecurityDescriptor
= NULL
;
2771 attr
.SecurityQualityOfService
= NULL
;
2773 if (!NtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2774 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2777 file
= lookup_manifest_file( handle
, &sxs_ai
);
2782 RtlFreeUnicodeString( &path_us
);
2783 return STATUS_NO_SUCH_FILE
;
2786 /* append file name to directory path */
2787 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
2788 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2790 RtlFreeHeap( GetProcessHeap(), 0, file
);
2791 RtlFreeUnicodeString( &path_us
);
2792 return STATUS_NO_MEMORY
;
2795 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2796 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2797 RtlInitUnicodeString( &path_us
, path
);
2798 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2800 if (!open_nt_file( &handle
, &path_us
))
2802 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2805 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
2807 RtlFreeHeap( GetProcessHeap(), 0, file
);
2808 RtlFreeUnicodeString( &path_us
);
2812 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2813 struct assembly_identity
* ai
)
2815 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2817 WCHAR
*buffer
, *p
, *directory
;
2819 UNICODE_STRING nameW
;
2823 TRACE( "looking for name=%s version=%s arch=%s\n",
2824 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
2826 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2828 /* FIXME: add support for language specific lookup */
2830 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2831 strlenW(acl
->actctx
->appdir
.info
));
2833 nameW
.Buffer
= NULL
;
2834 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2835 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2836 return STATUS_NO_MEMORY
;
2838 if (!(directory
= build_assembly_dir( ai
)))
2840 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2841 return STATUS_NO_MEMORY
;
2844 /* Lookup in <dir>\name.dll
2845 * <dir>\name.manifest
2846 * <dir>\name\name.dll
2847 * <dir>\name\name.manifest
2849 * First 'appdir' is used as <dir>, if that failed
2850 * it tries application manifest file path.
2852 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
2853 p
= buffer
+ strlenW(buffer
);
2854 for (i
= 0; i
< 4; i
++)
2858 struct assembly
*assembly
= acl
->actctx
->assemblies
;
2859 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
2863 strcpyW( p
, ai
->name
);
2866 strcpyW( p
, dotDllW
);
2867 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2869 status
= open_nt_file( &file
, &nameW
);
2872 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
2873 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
2877 RtlFreeUnicodeString( &nameW
);
2880 strcpyW( p
, dotManifestW
);
2881 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2883 status
= open_nt_file( &file
, &nameW
);
2886 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2890 RtlFreeUnicodeString( &nameW
);
2892 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
2894 RtlFreeUnicodeString( &nameW
);
2895 RtlFreeHeap( GetProcessHeap(), 0, directory
);
2896 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2900 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
2902 NTSTATUS status
= STATUS_SUCCESS
;
2905 for (i
= 0; i
< acl
->num_dependencies
; i
++)
2907 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
2909 if (!acl
->dependencies
[i
].optional
)
2911 FIXME( "Could not find dependent assembly %s (%s)\n",
2912 debugstr_w(acl
->dependencies
[i
].name
),
2913 debugstr_version(&acl
->dependencies
[i
].version
) );
2914 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
2919 /* FIXME should now iterate through all refs */
2923 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2924 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
2926 NTSTATUS status
= STATUS_SUCCESS
;
2928 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
2930 if (*handle
) return STATUS_INVALID_PARAMETER
;
2932 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
2933 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
2935 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
2940 if (!*handle
) return STATUS_INVALID_PARAMETER
;
2942 LdrLockLoaderLock( 0, NULL
, &magic
);
2943 if (!LdrFindEntryForAddress( *handle
, &pldr
))
2945 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
2946 status
= STATUS_DLL_NOT_FOUND
;
2948 *handle
= pldr
->ActivationContext
;
2950 else status
= STATUS_DLL_NOT_FOUND
;
2951 LdrUnlockLoaderLock( 0, magic
);
2953 else if (!*handle
&& (class != ActivationContextBasicInformation
))
2954 *handle
= process_actctx
;
2959 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
2961 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
2962 struct strsection_header
*header
;
2963 struct dllredirect_data
*data
;
2964 struct string_index
*index
;
2967 /* compute section length */
2968 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2970 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2971 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2973 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2975 /* each entry needs index, data and string data */
2976 total_len
+= sizeof(*index
);
2977 total_len
+= sizeof(*data
);
2978 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
2981 dll_count
+= assembly
->num_dlls
;
2984 total_len
+= sizeof(*header
);
2986 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
2987 if (!header
) return STATUS_NO_MEMORY
;
2989 memset(header
, 0, sizeof(*header
));
2990 header
->magic
= STRSECTION_MAGIC
;
2991 header
->size
= sizeof(*header
);
2992 header
->count
= dll_count
;
2993 header
->index_offset
= sizeof(*header
);
2994 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
2995 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
2997 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2999 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3000 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3002 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3006 /* setup new index entry */
3007 str
.Buffer
= dll
->name
;
3008 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3009 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3010 /* hash original class name */
3011 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3013 index
->name_offset
= name_offset
;
3014 index
->name_len
= str
.Length
;
3015 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3016 index
->data_len
= sizeof(*data
);
3017 index
->rosterindex
= i
+ 1;
3020 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3021 data
->size
= sizeof(*data
);
3022 data
->unk
= 2; /* FIXME: seems to be constant */
3023 memset(data
->res
, 0, sizeof(data
->res
));
3026 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3027 memcpy(ptrW
, dll
->name
, index
->name_len
);
3028 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3030 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3038 return STATUS_SUCCESS
;
3041 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3043 struct string_index
*iter
, *index
= NULL
;
3046 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3047 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3049 for (i
= 0; i
< section
->count
; i
++)
3051 if (iter
->hash
== hash
)
3053 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3055 if (!strcmpiW(nameW
, name
->Buffer
))
3061 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3069 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3071 struct guid_index
*iter
, *index
= NULL
;
3074 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3076 for (i
= 0; i
< section
->count
; i
++)
3078 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3089 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3091 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3094 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3095 PACTCTX_SECTION_KEYED_DATA data
)
3097 struct dllredirect_data
*dll
;
3098 struct string_index
*index
;
3100 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3102 if (!actctx
->dllredirect_section
)
3104 struct strsection_header
*section
;
3106 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3107 if (status
) return status
;
3109 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3110 RtlFreeHeap(GetProcessHeap(), 0, section
);
3113 index
= find_string_index(actctx
->dllredirect_section
, name
);
3114 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3116 dll
= get_dllredirect_data(actctx
, index
);
3118 data
->ulDataFormatVersion
= 1;
3120 data
->ulLength
= dll
->size
;
3121 data
->lpSectionGlobalData
= NULL
;
3122 data
->ulSectionGlobalDataLength
= 0;
3123 data
->lpSectionBase
= actctx
->dllredirect_section
;
3124 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3125 data
->hActCtx
= NULL
;
3127 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3128 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3130 return STATUS_SUCCESS
;
3133 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3135 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3138 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3140 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3143 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3145 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3146 struct wndclass_redirect_data
*data
;
3147 struct strsection_header
*header
;
3148 struct string_index
*index
;
3151 /* compute section length */
3152 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3154 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3155 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3157 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3158 for (k
= 0; k
< dll
->entities
.num
; k
++)
3160 struct entity
*entity
= &dll
->entities
.base
[k
];
3161 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3163 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3166 /* each class entry needs index, data and string data */
3167 total_len
+= sizeof(*index
);
3168 total_len
+= sizeof(*data
);
3169 /* original name is stored separately */
3170 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3171 /* versioned name and module name are stored one after another */
3172 if (entity
->u
.class.versioned
)
3173 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3176 len
+= strlenW(dll
->name
) + 1;
3177 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3185 total_len
+= sizeof(*header
);
3187 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3188 if (!header
) return STATUS_NO_MEMORY
;
3190 memset(header
, 0, sizeof(*header
));
3191 header
->magic
= STRSECTION_MAGIC
;
3192 header
->size
= sizeof(*header
);
3193 header
->count
= class_count
;
3194 header
->index_offset
= sizeof(*header
);
3195 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3196 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3198 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3200 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3201 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3203 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3204 for (k
= 0; k
< dll
->entities
.num
; k
++)
3206 struct entity
*entity
= &dll
->entities
.base
[k
];
3207 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3209 static const WCHAR exclW
[] = {'!',0};
3210 ULONG versioned_len
, module_len
;
3214 /* setup new index entry */
3215 str
.Buffer
= entity
->u
.class.name
;
3216 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3217 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3218 /* hash original class name */
3219 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3221 /* include '!' separator too */
3222 if (entity
->u
.class.versioned
)
3223 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3225 versioned_len
= str
.Length
;
3226 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3228 index
->name_offset
= name_offset
;
3229 index
->name_len
= str
.Length
;
3230 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3231 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3232 index
->rosterindex
= i
+ 1;
3235 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3236 data
->size
= sizeof(*data
);
3238 data
->name_len
= versioned_len
;
3239 data
->name_offset
= sizeof(*data
);
3240 data
->module_len
= module_len
;
3241 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3243 /* original class name */
3244 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3245 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3246 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3249 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3250 memcpy(ptrW
, dll
->name
, data
->module_len
);
3251 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3253 /* versioned name */
3254 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3255 if (entity
->u
.class.versioned
)
3257 get_assembly_version(assembly
, ptrW
);
3258 strcatW(ptrW
, exclW
);
3259 strcatW(ptrW
, entity
->u
.class.name
);
3263 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3264 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3267 name_offset
+= sizeof(*data
);
3268 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3278 return STATUS_SUCCESS
;
3281 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3282 PACTCTX_SECTION_KEYED_DATA data
)
3284 struct string_index
*iter
, *index
= NULL
;
3285 struct wndclass_redirect_data
*class;
3289 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3291 if (!actctx
->wndclass_section
)
3293 struct strsection_header
*section
;
3295 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3296 if (status
) return status
;
3298 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3299 RtlFreeHeap(GetProcessHeap(), 0, section
);
3303 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3304 iter
= get_wndclass_first_index(actctx
);
3306 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3308 if (iter
->hash
== hash
)
3310 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3312 if (!strcmpW(nameW
, name
->Buffer
))
3318 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3323 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3325 class = get_wndclass_data(actctx
, index
);
3327 data
->ulDataFormatVersion
= 1;
3328 data
->lpData
= class;
3329 /* full length includes string length with nulls */
3330 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3331 data
->lpSectionGlobalData
= NULL
;
3332 data
->ulSectionGlobalDataLength
= 0;
3333 data
->lpSectionBase
= actctx
->wndclass_section
;
3334 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3335 data
->hActCtx
= NULL
;
3337 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3338 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3340 return STATUS_SUCCESS
;
3343 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3345 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3346 struct guidsection_header
*header
;
3347 ULONG module_offset
, data_offset
;
3348 struct tlibredirect_data
*data
;
3349 struct guid_index
*index
;
3351 /* compute section length */
3352 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3354 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3355 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3357 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3358 for (k
= 0; k
< dll
->entities
.num
; k
++)
3360 struct entity
*entity
= &dll
->entities
.base
[k
];
3361 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3363 /* each entry needs index, data and string data for module name and help string */
3364 total_len
+= sizeof(*index
);
3365 total_len
+= sizeof(*data
);
3366 /* help string is stored separately */
3367 if (*entity
->u
.typelib
.helpdir
)
3368 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3370 /* module names are packed one after another */
3371 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3379 total_len
+= aligned_string_len(names_len
);
3380 total_len
+= sizeof(*header
);
3382 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3383 if (!header
) return STATUS_NO_MEMORY
;
3385 memset(header
, 0, sizeof(*header
));
3386 header
->magic
= GUIDSECTION_MAGIC
;
3387 header
->size
= sizeof(*header
);
3388 header
->count
= tlib_count
;
3389 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3390 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3391 module_offset
= sizeof(*header
);
3392 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3394 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3396 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3397 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3399 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3400 for (k
= 0; k
< dll
->entities
.num
; k
++)
3402 struct entity
*entity
= &dll
->entities
.base
[k
];
3403 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3405 ULONG module_len
, help_len
;
3409 if (*entity
->u
.typelib
.helpdir
)
3410 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3414 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3416 /* setup new index entry */
3417 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3418 RtlGUIDFromString(&str
, &index
->guid
);
3419 index
->data_offset
= data_offset
;
3420 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3421 index
->rosterindex
= i
+ 1;
3424 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3425 data
->size
= sizeof(*data
);
3427 data
->name_len
= module_len
;
3428 data
->name_offset
= module_offset
;
3429 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3431 data
->flags
= entity
->u
.typelib
.flags
;
3432 data
->help_len
= help_len
;
3433 data
->help_offset
= sizeof(*data
);
3434 data
->major_version
= entity
->u
.typelib
.major
;
3435 data
->minor_version
= entity
->u
.typelib
.minor
;
3438 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3439 memcpy(ptrW
, dll
->name
, data
->name_len
);
3440 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3445 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3446 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3447 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3450 data_offset
+= sizeof(*data
);
3452 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3454 module_offset
+= module_len
+ sizeof(WCHAR
);
3464 return STATUS_SUCCESS
;
3467 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3469 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3472 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3474 struct guid_index
*index
= NULL
;
3475 struct tlibredirect_data
*tlib
;
3477 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3479 if (!actctx
->tlib_section
)
3481 struct guidsection_header
*section
;
3483 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3484 if (status
) return status
;
3486 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3487 RtlFreeHeap(GetProcessHeap(), 0, section
);
3490 index
= find_guid_index(actctx
->tlib_section
, guid
);
3491 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3493 tlib
= get_tlib_data(actctx
, index
);
3495 data
->ulDataFormatVersion
= 1;
3496 data
->lpData
= tlib
;
3497 /* full length includes string length with nulls */
3498 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3499 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3500 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3501 data
->lpSectionBase
= actctx
->tlib_section
;
3502 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3503 data
->hActCtx
= NULL
;
3505 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3506 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3508 return STATUS_SUCCESS
;
3511 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3513 ULONG
*ptr
= (ULONG
*)guid
;
3516 /* GUID is 16 bytes long */
3517 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3518 *ptr
= RtlUniform(seed
);
3520 guid
->Data3
&= 0x0fff;
3521 guid
->Data3
|= (4 << 12);
3522 guid
->Data4
[0] &= 0x3f;
3523 guid
->Data4
[0] |= 0x80;
3526 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3527 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3531 for (i
= 0; i
< entities
->num
; i
++)
3533 struct entity
*entity
= &entities
->base
[i
];
3534 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3536 /* each entry needs two index entries, extra one goes for alias GUID */
3537 *len
+= 2*sizeof(struct guid_index
);
3538 /* To save some memory we don't allocated two data structures,
3539 instead alias index and normal index point to the same data structure. */
3540 *len
+= sizeof(struct comclassredirect_data
);
3542 /* for clrClass store some more */
3543 if (entity
->u
.comclass
.name
)
3545 unsigned int str_len
;
3547 /* all string data is stored together in aligned block */
3548 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3549 if (entity
->u
.comclass
.progid
)
3550 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3551 if (entity
->u
.comclass
.version
)
3552 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3554 *len
+= sizeof(struct clrclass_data
);
3555 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3557 /* module name is forced to mscoree.dll, and stored two times with different case */
3558 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3562 /* progid string is stored separately */
3563 if (entity
->u
.comclass
.progid
)
3564 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3566 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3574 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3575 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3576 ULONG
*seed
, ULONG rosterindex
)
3580 for (i
= 0; i
< entities
->num
; i
++)
3582 struct entity
*entity
= &entities
->base
[i
];
3583 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3585 ULONG module_len
, progid_len
, str_len
= 0;
3586 struct comclassredirect_data
*data
;
3587 struct guid_index
*alias_index
;
3588 struct clrclass_data
*clrdata
;
3592 if (entity
->u
.comclass
.progid
)
3593 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3597 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3599 /* setup new index entry */
3600 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3601 RtlGUIDFromString(&str
, &(*index
)->guid
);
3603 (*index
)->data_offset
= *data_offset
;
3604 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3605 (*index
)->rosterindex
= rosterindex
;
3607 /* Setup new index entry for alias guid. Alias index records are placed after
3608 normal records, so normal guids are hit first on search. Note that class count
3610 alias_index
= (*index
) + section
->count
/2;
3611 generate_uuid(seed
, &alias_index
->guid
);
3612 alias_index
->data_offset
= (*index
)->data_offset
;
3613 alias_index
->data_len
= 0;
3614 alias_index
->rosterindex
= (*index
)->rosterindex
;
3617 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3618 data
->size
= sizeof(*data
);
3622 data
->model
= entity
->u
.comclass
.model
;
3623 data
->clsid
= (*index
)->guid
;
3624 data
->alias
= alias_index
->guid
;
3625 data
->clsid2
= data
->clsid
;
3626 if (entity
->u
.comclass
.tlbid
)
3628 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3629 RtlGUIDFromString(&str
, &data
->tlbid
);
3632 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3633 data
->name_len
= module_len
;
3634 data
->name_offset
= *module_offset
;
3635 data
->progid_len
= progid_len
;
3636 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3637 data
->clrdata_len
= 0; /* will be set later */
3638 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3639 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3640 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3641 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3642 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3643 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3645 /* mask describes which misc* data is available */
3647 if (data
->miscstatus
)
3648 data
->miscmask
|= MiscStatus
;
3649 if (data
->miscstatuscontent
)
3650 data
->miscmask
|= MiscStatusContent
;
3651 if (data
->miscstatusthumbnail
)
3652 data
->miscmask
|= MiscStatusThumbnail
;
3653 if (data
->miscstatusicon
)
3654 data
->miscmask
|= MiscStatusIcon
;
3655 if (data
->miscstatusdocprint
)
3656 data
->miscmask
|= MiscStatusDocPrint
;
3658 if (data
->clrdata_offset
)
3660 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3662 clrdata
->size
= sizeof(*clrdata
);
3663 clrdata
->res
[0] = 0;
3664 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3665 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3666 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3667 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3668 clrdata
->name_offset
= clrdata
->size
;
3669 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3670 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3671 clrdata
->res2
[0] = 0;
3672 clrdata
->res2
[1] = 0;
3674 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3677 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3678 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3679 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3681 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3682 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3683 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3686 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3687 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3688 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3690 /* runtime version, optional */
3691 if (clrdata
->version_len
)
3693 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3695 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3696 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3697 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3700 if (data
->progid_len
)
3701 data
->progid_offset
+= data
->clrdata_len
;
3702 (*index
)->data_len
+= sizeof(*clrdata
);
3709 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3710 memcpy(ptrW
, dll
->name
, data
->name_len
);
3711 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3715 if (data
->progid_len
)
3717 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3718 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3719 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3722 /* string block length */
3726 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3727 if (clrdata
->version_len
)
3728 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3731 str_len
+= progid_len
+ sizeof(WCHAR
);
3733 (*index
)->data_len
+= aligned_string_len(str_len
);
3734 alias_index
->data_len
= (*index
)->data_len
;
3736 /* move to next data record */
3737 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3738 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3742 (*data_offset
) += sizeof(*clrdata
);
3743 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3750 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3752 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3753 struct guidsection_header
*header
;
3754 ULONG module_offset
, data_offset
;
3755 struct guid_index
*index
;
3758 /* compute section length */
3759 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3761 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3762 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3763 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3765 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3766 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3770 total_len
+= aligned_string_len(names_len
);
3771 total_len
+= sizeof(*header
);
3773 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3774 if (!header
) return STATUS_NO_MEMORY
;
3776 memset(header
, 0, sizeof(*header
));
3777 header
->magic
= GUIDSECTION_MAGIC
;
3778 header
->size
= sizeof(*header
);
3779 header
->count
= 2*class_count
;
3780 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3781 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3782 module_offset
= sizeof(*header
);
3783 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3785 seed
= NtGetTickCount();
3786 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3788 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3789 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3790 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3792 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3793 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3799 return STATUS_SUCCESS
;
3802 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3804 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3807 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3809 struct comclassredirect_data
*comclass
;
3810 struct guid_index
*index
= NULL
;
3812 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3814 if (!actctx
->comserver_section
)
3816 struct guidsection_header
*section
;
3818 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
3819 if (status
) return status
;
3821 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
3822 RtlFreeHeap(GetProcessHeap(), 0, section
);
3825 index
= find_guid_index(actctx
->comserver_section
, guid
);
3826 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3828 comclass
= get_comclass_data(actctx
, index
);
3830 data
->ulDataFormatVersion
= 1;
3831 data
->lpData
= comclass
;
3832 /* full length includes string length with nulls */
3833 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
3834 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
3835 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
3836 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
3837 data
->lpSectionBase
= actctx
->comserver_section
;
3838 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
3839 data
->hActCtx
= NULL
;
3841 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3842 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3844 return STATUS_SUCCESS
;
3847 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
3851 for (i
= 0; i
< entities
->num
; i
++)
3853 struct entity
*entity
= &entities
->base
[i
];
3854 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3856 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
3857 if (entity
->u
.ifaceps
.name
)
3858 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
3864 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
3865 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
3869 for (i
= 0; i
< entities
->num
; i
++)
3871 struct entity
*entity
= &entities
->base
[i
];
3872 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3874 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
3878 if (entity
->u
.ifaceps
.name
)
3879 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
3884 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
3885 RtlGUIDFromString(&str
, &(*index
)->guid
);
3886 (*index
)->data_offset
= *data_offset
;
3887 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
3888 (*index
)->rosterindex
= rosterindex
;
3890 /* setup data record */
3891 data
->size
= sizeof(*data
);
3892 data
->mask
= entity
->u
.ifaceps
.mask
;
3894 /* proxyStubClsid32 value is only stored for external PS,
3895 if set it's used as iid, otherwise 'iid' attribute value is used */
3896 if (entity
->u
.ifaceps
.ps32
)
3898 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
3899 RtlGUIDFromString(&str
, &data
->iid
);
3902 data
->iid
= (*index
)->guid
;
3904 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
3906 if (entity
->u
.ifaceps
.tlib
)
3908 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
3909 RtlGUIDFromString(&str
, &data
->tlbid
);
3912 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3914 if (entity
->u
.ifaceps
.base
)
3916 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
3917 RtlGUIDFromString(&str
, &data
->base
);
3920 memset(&data
->base
, 0, sizeof(data
->base
));
3922 data
->name_len
= name_len
;
3923 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
3928 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3929 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
3930 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3933 /* move to next record */
3935 *data_offset
+= sizeof(*data
);
3937 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
3942 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3944 unsigned int i
, j
, total_len
= 0, count
= 0;
3945 struct guidsection_header
*header
;
3946 struct guid_index
*index
;
3949 /* compute section length */
3950 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3952 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3954 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
3955 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3957 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3958 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
3962 total_len
+= sizeof(*header
);
3964 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3965 if (!header
) return STATUS_NO_MEMORY
;
3967 memset(header
, 0, sizeof(*header
));
3968 header
->magic
= GUIDSECTION_MAGIC
;
3969 header
->size
= sizeof(*header
);
3970 header
->count
= count
;
3971 header
->index_offset
= sizeof(*header
);
3972 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3973 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
3975 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3977 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3979 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
3980 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3982 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3983 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
3989 return STATUS_SUCCESS
;
3992 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3994 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
3997 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3999 struct ifacepsredirect_data
*iface
;
4000 struct guid_index
*index
= NULL
;
4002 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4004 if (!actctx
->ifaceps_section
)
4006 struct guidsection_header
*section
;
4008 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4009 if (status
) return status
;
4011 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4012 RtlFreeHeap(GetProcessHeap(), 0, section
);
4015 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4016 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4018 iface
= get_ifaceps_data(actctx
, index
);
4020 data
->ulDataFormatVersion
= 1;
4021 data
->lpData
= iface
;
4022 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4023 data
->lpSectionGlobalData
= NULL
;
4024 data
->ulSectionGlobalDataLength
= 0;
4025 data
->lpSectionBase
= actctx
->ifaceps_section
;
4026 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4027 data
->hActCtx
= NULL
;
4029 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4030 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4032 return STATUS_SUCCESS
;
4035 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4037 unsigned int i
, j
, total_len
= 0, count
= 0;
4038 struct guidsection_header
*header
;
4039 struct clrsurrogate_data
*data
;
4040 struct guid_index
*index
;
4043 /* compute section length */
4044 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4046 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4047 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4049 struct entity
*entity
= &assembly
->entities
.base
[j
];
4050 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4054 total_len
+= sizeof(*index
) + sizeof(*data
);
4055 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4056 if (entity
->u
.clrsurrogate
.version
)
4057 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4058 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4065 total_len
+= sizeof(*header
);
4067 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4068 if (!header
) return STATUS_NO_MEMORY
;
4070 memset(header
, 0, sizeof(*header
));
4071 header
->magic
= GUIDSECTION_MAGIC
;
4072 header
->size
= sizeof(*header
);
4073 header
->count
= count
;
4074 header
->index_offset
= sizeof(*header
);
4075 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4076 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4078 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4080 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4081 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4083 struct entity
*entity
= &assembly
->entities
.base
[j
];
4084 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4086 ULONG version_len
, name_len
;
4090 if (entity
->u
.clrsurrogate
.version
)
4091 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4094 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4096 /* setup new index entry */
4097 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4098 RtlGUIDFromString(&str
, &index
->guid
);
4100 index
->data_offset
= data_offset
;
4101 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4102 index
->rosterindex
= i
+ 1;
4105 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4106 data
->size
= sizeof(*data
);
4108 data
->clsid
= index
->guid
;
4109 data
->version_offset
= version_len
? data
->size
: 0;
4110 data
->version_len
= version_len
;
4111 data
->name_offset
= data
->size
+ version_len
;
4113 data
->name_offset
+= sizeof(WCHAR
);
4114 data
->name_len
= name_len
;
4116 /* surrogate name */
4117 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4118 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4119 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4121 /* runtime version */
4122 if (data
->version_len
)
4124 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4125 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4126 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4129 data_offset
+= index
->data_offset
;
4137 return STATUS_SUCCESS
;
4140 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4142 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4145 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4147 struct clrsurrogate_data
*surrogate
;
4148 struct guid_index
*index
= NULL
;
4150 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4152 if (!actctx
->clrsurrogate_section
)
4154 struct guidsection_header
*section
;
4156 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4157 if (status
) return status
;
4159 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4160 RtlFreeHeap(GetProcessHeap(), 0, section
);
4163 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4164 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4166 surrogate
= get_surrogate_data(actctx
, index
);
4168 data
->ulDataFormatVersion
= 1;
4169 data
->lpData
= surrogate
;
4170 /* full length includes string length with nulls */
4171 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4172 if (surrogate
->version_len
)
4173 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4175 data
->lpSectionGlobalData
= NULL
;
4176 data
->ulSectionGlobalDataLength
= 0;
4177 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4178 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4179 data
->hActCtx
= NULL
;
4181 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4182 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4184 return STATUS_SUCCESS
;
4187 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4189 unsigned int i
, j
, single_len
;
4191 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4192 for (i
= 0; i
< entities
->num
; i
++)
4194 struct entity
*entity
= &entities
->base
[i
];
4195 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4197 if (entity
->u
.comclass
.progid
)
4199 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4203 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4204 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4206 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4207 *count
+= entity
->u
.comclass
.progids
.num
;
4212 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4213 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4215 struct progidredirect_data
*data
;
4220 /* setup new index entry */
4222 /* hash progid name */
4223 RtlInitUnicodeString(&str
, progid
);
4224 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4226 (*index
)->name_offset
= *data_offset
;
4227 (*index
)->name_len
= str
.Length
;
4228 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4229 (*index
)->data_len
= sizeof(*data
);
4230 (*index
)->rosterindex
= rosterindex
;
4232 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4234 /* setup data structure */
4235 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4236 data
->size
= sizeof(*data
);
4238 data
->clsid_offset
= *global_offset
;
4240 /* write progid string */
4241 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4242 memcpy(ptrW
, progid
, (*index
)->name_len
);
4243 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4245 /* write guid to global area */
4246 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4250 *global_offset
+= sizeof(GUID
);
4251 *data_offset
+= data
->size
;
4255 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4256 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4260 for (i
= 0; i
< entities
->num
; i
++)
4262 struct entity
*entity
= &entities
->base
[i
];
4263 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4265 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4266 struct comclassredirect_data
*comclass
;
4267 struct guid_index
*guid_index
;
4271 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4272 RtlGUIDFromString(&str
, &clsid
);
4274 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4275 comclass
= get_comclass_data(actctx
, guid_index
);
4277 if (entity
->u
.comclass
.progid
)
4278 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4279 index
, data_offset
, global_offset
, rosterindex
);
4281 for (j
= 0; j
< progids
->num
; j
++)
4282 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4283 index
, data_offset
, global_offset
, rosterindex
);
4288 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4290 unsigned int i
, j
, total_len
= 0, count
= 0;
4291 struct strsection_header
*header
;
4292 ULONG data_offset
, global_offset
;
4293 struct string_index
*index
;
4295 /* compute section length */
4296 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4298 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4300 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4301 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4303 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4304 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4308 total_len
+= sizeof(*header
);
4310 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4311 if (!header
) return STATUS_NO_MEMORY
;
4313 memset(header
, 0, sizeof(*header
));
4314 header
->magic
= STRSECTION_MAGIC
;
4315 header
->size
= sizeof(*header
);
4316 header
->count
= count
;
4317 header
->global_offset
= header
->size
;
4318 header
->global_len
= count
*sizeof(GUID
);
4319 header
->index_offset
= header
->size
+ header
->global_len
;
4321 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4322 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4323 global_offset
= header
->global_offset
;
4325 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4327 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4329 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4330 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4332 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4333 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4339 return STATUS_SUCCESS
;
4342 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4344 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4347 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4348 PACTCTX_SECTION_KEYED_DATA data
)
4350 struct progidredirect_data
*progid
;
4351 struct string_index
*index
;
4353 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4355 if (!actctx
->comserver_section
)
4357 struct guidsection_header
*section
;
4359 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4360 if (status
) return status
;
4362 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4363 RtlFreeHeap(GetProcessHeap(), 0, section
);
4366 if (!actctx
->progid_section
)
4368 struct strsection_header
*section
;
4370 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4371 if (status
) return status
;
4373 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4374 RtlFreeHeap(GetProcessHeap(), 0, section
);
4377 index
= find_string_index(actctx
->progid_section
, name
);
4378 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4380 progid
= get_progid_data(actctx
, index
);
4382 data
->ulDataFormatVersion
= 1;
4383 data
->lpData
= progid
;
4384 data
->ulLength
= progid
->size
;
4385 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4386 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4387 data
->lpSectionBase
= actctx
->progid_section
;
4388 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4389 data
->hActCtx
= NULL
;
4391 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4392 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4394 return STATUS_SUCCESS
;
4397 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4398 const UNICODE_STRING
*section_name
,
4399 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4403 switch (section_kind
)
4405 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4406 status
= find_dll_redirection(actctx
, section_name
, data
);
4408 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4409 status
= find_window_class(actctx
, section_name
, data
);
4411 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4412 status
= find_progid_redirection(actctx
, section_name
, data
);
4414 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4415 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4416 return STATUS_SXS_SECTION_NOT_FOUND
;
4418 WARN("Unknown section_kind %x\n", section_kind
);
4419 return STATUS_SXS_SECTION_NOT_FOUND
;
4422 if (status
!= STATUS_SUCCESS
) return status
;
4424 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4426 actctx_addref(actctx
);
4427 data
->hActCtx
= actctx
;
4429 return STATUS_SUCCESS
;
4432 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4433 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4437 switch (section_kind
)
4439 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4440 status
= find_tlib_redirection(actctx
, guid
, data
);
4442 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4443 status
= find_comserver_redirection(actctx
, guid
, data
);
4445 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4446 status
= find_cominterface_redirection(actctx
, guid
, data
);
4448 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4449 status
= find_clr_surrogate(actctx
, guid
, data
);
4452 WARN("Unknown section_kind %x\n", section_kind
);
4453 return STATUS_SXS_SECTION_NOT_FOUND
;
4456 if (status
!= STATUS_SUCCESS
) return status
;
4458 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4460 actctx_addref(actctx
);
4461 data
->hActCtx
= actctx
;
4463 return STATUS_SUCCESS
;
4466 /* initialize the activation context for the current process */
4467 void actctx_init(void)
4472 ctx
.cbSize
= sizeof(ctx
);
4473 ctx
.lpSource
= NULL
;
4474 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4475 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4476 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4478 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4482 /***********************************************************************
4483 * RtlCreateActivationContext (NTDLL.@)
4485 * Create an activation context.
4487 * FIXME: function signature/prototype is wrong
4489 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4491 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4492 const WCHAR
*directory
= NULL
;
4493 ACTIVATION_CONTEXT
*actctx
;
4494 UNICODE_STRING nameW
;
4496 NTSTATUS status
= STATUS_NO_MEMORY
;
4498 struct actctx_loader acl
;
4500 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4502 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4503 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4504 return STATUS_INVALID_PARAMETER
;
4506 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4507 return STATUS_NO_MEMORY
;
4509 actctx
->magic
= ACTCTX_MAGIC
;
4510 actctx
->ref_count
= 1;
4511 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4512 actctx
->config
.info
= NULL
;
4513 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4514 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4516 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4524 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4525 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4527 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4528 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4529 actctx
->appdir
.info
= dir
.Buffer
;
4532 nameW
.Buffer
= NULL
;
4534 /* open file only if it's going to be used */
4535 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4536 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4538 if (!RtlDosPathNameToNtPathName_U(pActCtx
->lpSource
, &nameW
, NULL
, NULL
))
4540 status
= STATUS_NO_SUCH_FILE
;
4543 status
= open_nt_file( &file
, &nameW
);
4546 RtlFreeUnicodeString( &nameW
);
4551 acl
.actctx
= actctx
;
4552 acl
.dependencies
= NULL
;
4553 acl
.num_dependencies
= 0;
4554 acl
.allocated_dependencies
= 0;
4556 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4557 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4559 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4561 /* if we have a resource it's a PE file */
4562 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4564 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4565 pActCtx
->lpResourceName
, lang
);
4566 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4567 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4568 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4570 else if (pActCtx
->lpSource
)
4572 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4573 file
, pActCtx
->lpResourceName
, lang
);
4574 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4575 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4576 NULL
, pActCtx
->lpResourceName
);
4578 else status
= STATUS_INVALID_PARAMETER
;
4582 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4585 if (file
) NtClose( file
);
4586 RtlFreeUnicodeString( &nameW
);
4588 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4589 free_depend_manifests( &acl
);
4591 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4592 else actctx_release( actctx
);
4596 if (file
) NtClose( file
);
4597 actctx_release( actctx
);
4602 /***********************************************************************
4603 * RtlAddRefActivationContext (NTDLL.@)
4605 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4607 ACTIVATION_CONTEXT
*actctx
;
4609 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4613 /******************************************************************
4614 * RtlReleaseActivationContext (NTDLL.@)
4616 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
4618 ACTIVATION_CONTEXT
*actctx
;
4620 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4623 /******************************************************************
4624 * RtlZombifyActivationContext (NTDLL.@)
4626 * FIXME: function prototype might be wrong
4628 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
4630 FIXME("%p: stub\n", handle
);
4631 return STATUS_NOT_IMPLEMENTED
;
4634 /******************************************************************
4635 * RtlActivateActivationContext (NTDLL.@)
4637 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
4639 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4641 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
4642 return STATUS_NO_MEMORY
;
4644 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4645 frame
->ActivationContext
= handle
;
4647 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
4648 RtlAddRefActivationContext( handle
);
4650 *cookie
= (ULONG_PTR
)frame
;
4651 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
4652 return STATUS_SUCCESS
;
4656 /***********************************************************************
4657 * RtlDeactivateActivationContext (NTDLL.@)
4659 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4661 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4663 TRACE( "%x cookie=%lx\n", flags
, cookie
);
4665 /* find the right frame */
4666 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4667 for (frame
= top
; frame
; frame
= frame
->Previous
)
4668 if ((ULONG_PTR
)frame
== cookie
) break;
4671 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4673 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
4674 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4676 /* pop everything up to and including frame */
4677 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
4679 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4681 frame
= top
->Previous
;
4682 RtlReleaseActivationContext( top
->ActivationContext
);
4683 RtlFreeHeap( GetProcessHeap(), 0, top
);
4689 /******************************************************************
4690 * RtlFreeThreadActivationContextStack (NTDLL.@)
4692 void WINAPI
RtlFreeThreadActivationContextStack(void)
4694 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4696 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4699 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
4700 RtlReleaseActivationContext( frame
->ActivationContext
);
4701 RtlFreeHeap( GetProcessHeap(), 0, frame
);
4704 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
4708 /******************************************************************
4709 * RtlGetActiveActivationContext (NTDLL.@)
4711 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
4713 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4715 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
4716 RtlAddRefActivationContext( *handle
);
4721 return STATUS_SUCCESS
;
4725 /******************************************************************
4726 * RtlIsActivationContextActive (NTDLL.@)
4728 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
4730 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4732 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
4733 if (frame
->ActivationContext
== handle
) return TRUE
;
4738 /***********************************************************************
4739 * RtlQueryInformationActivationContext (NTDLL.@)
4741 * Get information about an activation context.
4742 * FIXME: function signature/prototype may be wrong
4744 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
4745 ULONG
class, PVOID buffer
,
4746 SIZE_T bufsize
, SIZE_T
*retlen
)
4748 ACTIVATION_CONTEXT
*actctx
;
4751 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
4752 subinst
, class, buffer
, bufsize
, retlen
);
4754 if (retlen
) *retlen
= 0;
4755 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
4759 case ActivationContextBasicInformation
:
4761 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
4763 if (retlen
) *retlen
= sizeof(*info
);
4764 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
4766 info
->hActCtx
= handle
;
4767 info
->dwFlags
= 0; /* FIXME */
4768 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
4772 case ActivationContextDetailedInformation
:
4774 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
4775 struct assembly
*assembly
= NULL
;
4776 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
4779 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4781 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
4783 if (assembly
&& assembly
->manifest
.info
)
4784 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
4785 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
4786 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
4787 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
4789 if (retlen
) *retlen
= len
;
4790 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
4793 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
4794 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
4795 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
4796 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
4797 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
4798 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
4799 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
4800 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
4801 ptr
= (LPWSTR
)(acdi
+ 1);
4804 acdi
->lpRootManifestPath
= ptr
;
4805 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
4806 ptr
+= manifest_len
;
4808 else acdi
->lpRootManifestPath
= NULL
;
4811 acdi
->lpRootConfigurationPath
= ptr
;
4812 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
4815 else acdi
->lpRootConfigurationPath
= NULL
;
4818 acdi
->lpAppDirPath
= ptr
;
4819 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
4821 else acdi
->lpAppDirPath
= NULL
;
4825 case AssemblyDetailedInformationInActivationContext
:
4827 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
4828 struct assembly
*assembly
;
4831 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
4834 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4835 if (!subinst
) return STATUS_INVALID_PARAMETER
;
4837 index
= *(DWORD
*)subinst
;
4838 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
4840 assembly
= &actctx
->assemblies
[index
- 1];
4842 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
4843 id_len
= strlenW(assembly_id
) + 1;
4844 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
4846 if (assembly
->manifest
.info
&&
4847 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
4848 path_len
= strlenW(assembly
->manifest
.info
) + 1;
4850 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
4852 if (retlen
) *retlen
= len
;
4853 if (!buffer
|| bufsize
< len
)
4855 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4856 return STATUS_BUFFER_TOO_SMALL
;
4859 afdi
->ulFlags
= 0; /* FIXME */
4860 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
4861 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
4862 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
4863 /* FIXME afdi->liManifestLastWriteTime = 0; */
4864 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
4865 afdi
->ulPolicyPathLength
= 0;
4866 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4867 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
4868 afdi
->ulManifestVersionMajor
= 1;
4869 afdi
->ulManifestVersionMinor
= 0;
4870 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
4871 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
4872 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
4873 ptr
= (LPWSTR
)(afdi
+ 1);
4874 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
4875 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
4879 afdi
->lpAssemblyManifestPath
= ptr
;
4880 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
4882 } else afdi
->lpAssemblyManifestPath
= NULL
;
4883 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
4886 afdi
->lpAssemblyDirectoryName
= ptr
;
4887 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
4889 else afdi
->lpAssemblyDirectoryName
= NULL
;
4890 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4894 case FileInformationInAssemblyOfAssemblyInActivationContext
:
4896 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
4897 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
4898 struct assembly
*assembly
;
4899 struct dll_redirect
*dll
;
4900 SIZE_T len
, dll_len
= 0;
4903 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4904 if (!acqi
) return STATUS_INVALID_PARAMETER
;
4906 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
4907 return STATUS_INVALID_PARAMETER
;
4908 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
4910 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
4911 return STATUS_INVALID_PARAMETER
;
4912 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
4914 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
4915 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
4917 if (!buffer
|| bufsize
< len
)
4919 if (retlen
) *retlen
= len
;
4920 return STATUS_BUFFER_TOO_SMALL
;
4922 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
4923 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
4924 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
4925 afdi
->ulPathLength
= 0; /* FIXME */
4926 ptr
= (LPWSTR
)(afdi
+ 1);
4929 afdi
->lpFileName
= ptr
;
4930 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
4931 } else afdi
->lpFileName
= NULL
;
4932 afdi
->lpFilePath
= NULL
; /* FIXME */
4937 FIXME( "class %u not implemented\n", class );
4938 return STATUS_NOT_IMPLEMENTED
;
4940 return STATUS_SUCCESS
;
4943 /***********************************************************************
4944 * RtlFindActivationContextSectionString (NTDLL.@)
4946 * Find information about a string in an activation context.
4947 * FIXME: function signature/prototype may be wrong
4949 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
4950 const UNICODE_STRING
*section_name
, PVOID ptr
)
4952 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
4953 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
4955 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
4956 debugstr_us(section_name
), data
);
4960 FIXME("expected guid == NULL\n");
4961 return STATUS_INVALID_PARAMETER
;
4963 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4965 FIXME("unknown flags %08x\n", flags
);
4966 return STATUS_INVALID_PARAMETER
;
4968 if (!data
|| data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) ||
4969 !section_name
|| !section_name
->Buffer
)
4971 WARN("invalid parameter\n");
4972 return STATUS_INVALID_PARAMETER
;
4975 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4977 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
4978 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
4981 if (status
!= STATUS_SUCCESS
)
4982 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
4987 /***********************************************************************
4988 * RtlFindActivationContextSectionGuid (NTDLL.@)
4990 * Find information about a GUID in an activation context.
4991 * FIXME: function signature/prototype may be wrong
4993 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
4994 const GUID
*guid
, void *ptr
)
4996 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
4997 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
4999 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5003 FIXME("expected extguid == NULL\n");
5004 return STATUS_INVALID_PARAMETER
;
5007 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5009 FIXME("unknown flags %08x\n", flags
);
5010 return STATUS_INVALID_PARAMETER
;
5013 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5014 return STATUS_INVALID_PARAMETER
;
5016 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5018 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5019 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5022 if (status
!= STATUS_SUCCESS
)
5023 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);