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
;
135 struct strsection_header
149 ULONG hash
; /* key string hash */
152 ULONG data_offset
; /* redirect data offset */
157 struct guidsection_header
177 struct wndclass_redirect_data
182 ULONG name_offset
; /* versioned name offset */
184 ULONG module_offset
;/* container name offset */
187 struct dllredirect_data
194 struct tlibredirect_data
208 enum comclass_threadingmodel
210 ThreadingModel_Apartment
= 1,
211 ThreadingModel_Free
= 2,
212 ThreadingModel_No
= 3,
213 ThreadingModel_Both
= 4,
214 ThreadingModel_Neutral
= 5
217 enum comclass_miscfields
221 MiscStatusContent
= 4,
222 MiscStatusThumbnail
= 8,
223 MiscStatusDocPrint
= 16
226 struct comclassredirect_data
242 ULONG clrdata_offset
;
244 DWORD miscstatuscontent
;
245 DWORD miscstatusthumbnail
;
246 DWORD miscstatusicon
;
247 DWORD miscstatusdocprint
;
256 struct ifacepsredirect_data
268 struct clrsurrogate_data
273 ULONG version_offset
;
288 ULONG version_offset
;
292 struct progidredirect_data
303 Sections are accessible by string or guid key, that defines two types of sections.
304 All sections of each type have same magic value and header structure, index
305 data could be of two possible types too. So every string based section uses
306 the same index format, same applies to guid sections - they share same guid index
309 - window class redirection section is a plain buffer with following format:
313 <data[]> --- <original name>
318 Header is fixed length structure - struct strsection_header,
319 contains redirected classes count;
321 Index is an array of fixed length index records, each record is
324 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
326 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
327 others are relative to section itself.
329 - dll redirect section format:
333 <data[]> --- <dll name>
336 This section doesn't seem to carry any payload data except dll names.
338 - typelib section format:
346 Header is fixed length, index is an array of fixed length 'struct guid_index'.
347 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
348 4-bytes aligned as a whole.
350 Module name offsets are relative to section, helpstring offset is relative to data
353 - comclass section format:
358 <data[]> --- <data> --- <data>
364 This section uses two index records per comclass, one entry contains original guid
365 as specified by context, another one has a generated guid. Index and strings handling
366 is similar to typelib sections.
368 For CLR classes additional data is stored after main COM class data, it contains
369 class name and runtime version string, see 'struct clrclass_data'.
371 Module name offsets are relative to section, progid offset is relative to data
374 - COM interface section format:
381 Interface section contains data for proxy/stubs and external proxy/stubs. External
382 ones are defined at assembly level, so this section has no module information.
383 All records are indexed with 'iid' value from manifest. There an exception for
384 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
385 redirect data, but index is still 'iid' from manifest.
387 Interface name offset is relative to data structure itself.
389 - CLR surrogates section format:
397 There's nothing special about this section, same way to store strings is used,
398 no modules part as it belongs to assembly level, not a file.
400 - ProgID section format:
405 <data[]> --- <progid>
408 This sections uses generated alias guids from COM server section. This way
409 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
410 is stored too, aligned.
417 unsigned int allocated
;
438 WCHAR
*name
; /* clrClass: class name */
439 WCHAR
*version
; /* clrClass: CLR runtime version */
442 DWORD miscstatuscontent
;
443 DWORD miscstatusthumbnail
;
444 DWORD miscstatusicon
;
445 DWORD miscstatusdocprint
;
446 struct progids progids
;
453 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
475 unsigned int allocated
;
482 struct entity_array entities
;
487 APPLICATION_MANIFEST
,
489 ASSEMBLY_SHARED_MANIFEST
,
494 enum assembly_type type
;
495 struct assembly_identity id
;
496 struct file_info manifest
;
499 struct dll_redirect
*dlls
;
500 unsigned int num_dlls
;
501 unsigned int allocated_dlls
;
502 struct entity_array entities
;
505 enum context_sections
507 WINDOWCLASS_SECTION
= 1,
508 DLLREDIRECT_SECTION
= 2,
509 TLIBREDIRECT_SECTION
= 4,
510 SERVERREDIRECT_SECTION
= 8,
511 IFACEREDIRECT_SECTION
= 16,
512 CLRSURROGATES_SECTION
= 32,
513 PROGIDREDIRECT_SECTION
= 64
516 typedef struct _ACTIVATION_CONTEXT
520 struct file_info config
;
521 struct file_info appdir
;
522 struct assembly
*assemblies
;
523 unsigned int num_assemblies
;
524 unsigned int allocated_assemblies
;
527 struct strsection_header
*wndclass_section
;
528 struct strsection_header
*dllredirect_section
;
529 struct strsection_header
*progid_section
;
530 struct guidsection_header
*tlib_section
;
531 struct guidsection_header
*comserver_section
;
532 struct guidsection_header
*ifaceps_section
;
533 struct guidsection_header
*clrsurrogate_section
;
534 } ACTIVATION_CONTEXT
;
538 ACTIVATION_CONTEXT
*actctx
;
539 struct assembly_identity
*dependencies
;
540 unsigned int num_dependencies
;
541 unsigned int allocated_dependencies
;
544 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
545 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
546 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
547 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
548 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
549 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
550 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
551 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
552 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};
553 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};
554 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
555 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
556 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
557 static const WCHAR fileW
[] = {'f','i','l','e',0};
558 static const WCHAR hashW
[] = {'h','a','s','h',0};
559 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
560 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
561 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
562 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
564 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
565 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
566 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
567 static const WCHAR iidW
[] = {'i','i','d',0};
568 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
569 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
570 static const WCHAR nameW
[] = {'n','a','m','e',0};
571 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
572 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
573 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
574 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
575 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};
576 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
577 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
578 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
579 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
580 static const WCHAR typeW
[] = {'t','y','p','e',0};
581 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
582 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
583 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
584 static const WCHAR yesW
[] = {'y','e','s',0};
585 static const WCHAR noW
[] = {'n','o',0};
586 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
587 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
588 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
589 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
590 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
591 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
592 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
593 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
594 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
595 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
596 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
597 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
598 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
599 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
600 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
601 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
603 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
604 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
605 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
606 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
607 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
608 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
609 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
610 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};
611 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
612 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
613 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
614 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
615 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
616 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
617 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
618 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
619 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};
620 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
621 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
622 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
623 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};
624 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
632 static const struct olemisc_entry olemisc_values
[] =
634 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
635 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
636 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
637 { alignableW
, OLEMISC_ALIGNABLE
},
638 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
639 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
640 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
641 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
642 { imemodeW
, OLEMISC_IMEMODE
},
643 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
644 { insideoutW
, OLEMISC_INSIDEOUT
},
645 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
646 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
647 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
648 { onlyiconicW
, OLEMISC_ONLYICONIC
},
649 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
650 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
651 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
652 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
653 { staticW
, OLEMISC_STATIC
},
654 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
655 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
658 static const WCHAR xmlW
[] = {'?','x','m','l',0};
659 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};
660 static const WCHAR manifestv2W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
661 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};
663 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
664 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
665 static const WCHAR wildcardW
[] = {'*',0};
667 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
668 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
670 static WCHAR
*strdupW(const WCHAR
* str
)
674 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
676 return strcpyW(ptr
, str
);
679 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
683 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
685 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
691 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
693 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
696 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
698 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
701 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
703 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
704 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
707 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
709 UINT len
= strlenW( namespace );
711 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
712 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
713 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
716 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
718 if (elem
->len
&& elem
->ptr
[0] == '/')
721 elem_end
.ptr
= elem
->ptr
+ 1;
722 elem_end
.len
= elem
->len
- 1;
723 return xml_elem_cmp( &elem_end
, str
, namespace );
728 static inline BOOL
isxmlspace( WCHAR ch
)
730 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
733 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
735 return debugstr_wn(str
->ptr
, str
->len
);
738 static inline const char* debugstr_version(const struct assembly_version
*ver
)
740 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
743 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
745 struct assembly
*assembly
;
747 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
750 unsigned int new_count
;
751 if (actctx
->assemblies
)
753 new_count
= actctx
->allocated_assemblies
* 2;
754 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
755 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
760 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
762 if (!ptr
) return NULL
;
763 actctx
->assemblies
= ptr
;
764 actctx
->allocated_assemblies
= new_count
;
767 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
772 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
774 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
777 unsigned int new_count
;
780 new_count
= assembly
->allocated_dlls
* 2;
781 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
782 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
787 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
789 if (!ptr
) return NULL
;
790 assembly
->dlls
= ptr
;
791 assembly
->allocated_dlls
= new_count
;
793 return &assembly
->dlls
[assembly
->num_dlls
++];
796 static void free_assembly_identity(struct assembly_identity
*ai
)
798 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
799 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
800 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
801 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
802 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
805 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
807 struct entity
* entity
;
809 if (array
->num
== array
->allocated
)
812 unsigned int new_count
;
815 new_count
= array
->allocated
* 2;
816 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
817 array
->base
, new_count
* sizeof(*array
->base
) );
822 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
824 if (!ptr
) return NULL
;
826 array
->allocated
= new_count
;
828 entity
= &array
->base
[array
->num
++];
833 static void free_entity_array(struct entity_array
*array
)
836 for (i
= 0; i
< array
->num
; i
++)
838 struct entity
*entity
= &array
->base
[i
];
839 switch (entity
->kind
)
841 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
842 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
843 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
844 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
845 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
846 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
847 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
848 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
849 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
851 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
852 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
853 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
854 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
855 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
856 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
858 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
859 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
860 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
862 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
863 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
865 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
866 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
867 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
868 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
871 FIXME("Unknown entity kind %d\n", entity
->kind
);
874 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
877 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
879 if (!str1
) return !str2
;
880 return str2
&& !strcmpiW( str1
, str2
);
883 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
884 const struct assembly_identity
*id2
)
886 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
887 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
888 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
890 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
892 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
895 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
896 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
897 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
898 if (id1
->version
.build
== id2
->version
.build
&&
899 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
903 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
904 struct assembly_identity
* ai
)
908 /* check if we already have that assembly */
910 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
911 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
913 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
914 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
915 ai
->version
.build
, ai
->version
.revision
);
919 for (i
= 0; i
< acl
->num_dependencies
; i
++)
920 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
922 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
923 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
924 ai
->version
.build
, ai
->version
.revision
);
928 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
931 unsigned int new_count
;
932 if (acl
->dependencies
)
934 new_count
= acl
->allocated_dependencies
* 2;
935 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
936 new_count
* sizeof(acl
->dependencies
[0]));
941 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
943 if (!ptr
) return FALSE
;
944 acl
->dependencies
= ptr
;
945 acl
->allocated_dependencies
= new_count
;
947 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
952 static void free_depend_manifests(struct actctx_loader
* acl
)
955 for (i
= 0; i
< acl
->num_dependencies
; i
++)
956 free_assembly_identity(&acl
->dependencies
[i
]);
957 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
960 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
962 static const WCHAR undW
[] = {'_',0};
963 static const WCHAR noneW
[] = {'n','o','n','e',0};
964 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
966 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
967 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
968 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
969 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
970 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
971 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
974 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
976 strcpyW( ret
, arch
);
977 strcatW( ret
, undW
);
978 strcatW( ret
, name
);
979 strcatW( ret
, undW
);
981 strcatW( ret
, undW
);
982 sprintfW( ret
+ strlenW(ret
), version_formatW
,
983 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
984 strcatW( ret
, undW
);
985 strcatW( ret
, lang
);
986 strcatW( ret
, undW
);
987 strcatW( ret
, mskeyW
);
991 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
996 strcatW( buffer
, prefix
);
1005 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1007 static const WCHAR archW
[] =
1008 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1009 static const WCHAR public_keyW
[] =
1010 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1011 static const WCHAR typeW
[] =
1012 {',','t','y','p','e','=',0};
1013 static const WCHAR versionW
[] =
1014 {',','v','e','r','s','i','o','n','=',0};
1016 WCHAR version
[64], *ret
;
1019 sprintfW( version
, version_formatW
,
1020 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1021 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1022 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1023 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1024 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
1025 size
+= strlenW(versionW
) + strlenW(version
) + 2;
1027 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1030 if (ai
->name
) strcpyW( ret
, ai
->name
);
1032 append_string( ret
, archW
, ai
->arch
);
1033 append_string( ret
, public_keyW
, ai
->public_key
);
1034 append_string( ret
, typeW
, ai
->type
);
1035 append_string( ret
, versionW
, version
);
1039 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1041 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1043 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1046 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1055 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1057 interlocked_xchg_add( &actctx
->ref_count
, 1 );
1060 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1062 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
1066 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1068 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1069 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1071 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1072 free_entity_array( &dll
->entities
);
1073 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1074 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1077 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1078 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1079 free_entity_array( &assembly
->entities
);
1080 free_assembly_identity(&assembly
->id
);
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1091 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1093 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1097 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1098 BOOL
* error
, BOOL
* end
)
1104 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1107 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1109 if (*xmlbuf
->ptr
== '/')
1112 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1121 if (*xmlbuf
->ptr
== '>')
1129 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1131 if (ptr
== xmlbuf
->end
) return FALSE
;
1133 name
->ptr
= xmlbuf
->ptr
;
1134 name
->len
= ptr
-xmlbuf
->ptr
;
1137 /* skip spaces before '=' */
1138 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1139 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1141 /* skip '=' itself */
1143 if (ptr
== xmlbuf
->end
) return FALSE
;
1145 /* skip spaces after '=' */
1146 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1148 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1151 if (ptr
== xmlbuf
->end
) return FALSE
;
1153 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1156 xmlbuf
->ptr
= xmlbuf
->end
;
1160 value
->len
= ptr
- value
->ptr
;
1161 xmlbuf
->ptr
= ptr
+ 1;
1163 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1169 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1175 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1178 xmlbuf
->ptr
= xmlbuf
->end
;
1182 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1184 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1185 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1187 if (ptr
+ 3 > xmlbuf
->end
)
1189 xmlbuf
->ptr
= xmlbuf
->end
;
1192 xmlbuf
->ptr
= ptr
+ 3;
1198 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1201 elem
->ptr
= xmlbuf
->ptr
;
1202 elem
->len
= ptr
- xmlbuf
->ptr
;
1204 return xmlbuf
->ptr
!= xmlbuf
->end
;
1207 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1209 /* FIXME: parse attributes */
1212 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1214 if (ptr
[0] == '?' && ptr
[1] == '>')
1216 xmlbuf
->ptr
= ptr
+ 2;
1223 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1225 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1227 if (!ptr
) return FALSE
;
1229 content
->ptr
= xmlbuf
->ptr
;
1230 content
->len
= ptr
- xmlbuf
->ptr
;
1236 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1238 unsigned int ver
[4];
1242 /* major.minor.build.revision */
1243 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1244 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1246 if (*curr
>= '0' && *curr
<= '9')
1248 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1249 if (ver
[pos
] >= 0x10000) goto error
;
1251 else if (*curr
== '.')
1253 if (++pos
>= 4) goto error
;
1257 version
->major
= ver
[0];
1258 version
->minor
= ver
[1];
1259 version
->build
= ver
[2];
1260 version
->revision
= ver
[3];
1264 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1268 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1271 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1272 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1273 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1277 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1279 xmlstr_t attr_name
, attr_value
;
1282 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1284 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1285 debugstr_xmlstr(&attr_value
));
1290 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1293 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1296 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1299 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1300 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1302 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1305 return parse_end_element(xmlbuf
);
1308 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1310 xmlstr_t attr_name
, attr_value
, elem
;
1311 BOOL end
= FALSE
, error
, ret
= TRUE
;
1313 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1314 if(error
|| end
) return end
;
1316 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1318 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1319 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1322 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1325 return ret
&& parse_end_element(xmlbuf
);
1328 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1329 struct assembly_identity
* ai
)
1331 xmlstr_t attr_name
, attr_value
;
1332 BOOL end
= FALSE
, error
;
1334 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1336 if (xmlstr_cmp(&attr_name
, nameW
))
1338 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1340 else if (xmlstr_cmp(&attr_name
, typeW
))
1342 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1344 else if (xmlstr_cmp(&attr_name
, versionW
))
1346 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1348 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1350 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1352 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1354 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1356 else if (xmlstr_cmp(&attr_name
, languageW
))
1358 WARN("Unsupported yet language attribute (%s)\n",
1359 debugstr_xmlstr(&attr_value
));
1360 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1364 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1365 debugstr_xmlstr(&attr_value
));
1369 TRACE( "name=%s version=%s arch=%s\n",
1370 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1372 if (error
|| end
) return end
;
1373 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1376 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1378 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1379 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1380 static const WCHAR freeW
[] = {'F','r','e','e',0};
1381 static const WCHAR bothW
[] = {'B','o','t','h',0};
1383 if (value
->len
== 0) return ThreadingModel_No
;
1384 if (xmlstr_cmp(value
, apartW
))
1385 return ThreadingModel_Apartment
;
1386 else if (xmlstr_cmp(value
, freeW
))
1387 return ThreadingModel_Free
;
1388 else if (xmlstr_cmp(value
, bothW
))
1389 return ThreadingModel_Both
;
1390 else if (xmlstr_cmp(value
, neutralW
))
1391 return ThreadingModel_Neutral
;
1393 return ThreadingModel_No
;
1396 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1401 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1409 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1410 if (!c
&& !olemisc_values
[n
].name
[len
])
1411 return olemisc_values
[n
].value
;
1419 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1423 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1425 const WCHAR
*str
= value
->ptr
, *start
;
1429 /* it's comma separated list of flags */
1430 while (i
< value
->len
)
1433 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1435 flags
|= get_olemisc_value(start
, str
-start
);
1437 /* skip separator */
1445 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1447 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1449 if (progids
->allocated
== 0)
1451 progids
->allocated
= 4;
1452 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1455 if (progids
->allocated
== progids
->num
)
1457 progids
->allocated
*= 2;
1458 progids
->progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
, progids
->allocated
* sizeof(WCHAR
*));
1461 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1467 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1472 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1475 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1476 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1479 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1481 xmlstr_t elem
, attr_name
, attr_value
;
1482 BOOL ret
= TRUE
, end
= FALSE
, error
;
1483 struct entity
* entity
;
1485 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1488 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1490 if (xmlstr_cmp(&attr_name
, clsidW
))
1492 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1494 else if (xmlstr_cmp(&attr_name
, progidW
))
1496 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1498 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1500 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1502 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1504 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1506 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1508 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1510 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1512 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1514 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1516 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1518 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1520 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1522 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1524 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1526 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1532 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1536 if (error
) return FALSE
;
1538 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1539 if (entity
->u
.comclass
.progid
)
1540 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1542 if (end
) return TRUE
;
1544 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1546 if (xmlstr_cmp_end(&elem
, comClassW
))
1548 ret
= parse_end_element(xmlbuf
);
1551 else if (xmlstr_cmp(&elem
, progidW
))
1553 ret
= parse_com_class_progid(xmlbuf
, entity
);
1557 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1558 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1562 if (entity
->u
.comclass
.progids
.num
)
1563 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1568 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1573 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1575 if (*curr
>= '0' && *curr
<= '9')
1576 num
= num
* 10 + *curr
- '0';
1579 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1583 entity
->u
.ifaceps
.nummethods
= num
;
1588 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1590 xmlstr_t attr_name
, attr_value
;
1591 BOOL end
= FALSE
, error
;
1592 struct entity
* entity
;
1594 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1597 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1599 if (xmlstr_cmp(&attr_name
, iidW
))
1601 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1603 else if (xmlstr_cmp(&attr_name
, nameW
))
1605 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1607 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1609 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1610 entity
->u
.ifaceps
.mask
|= BaseIface
;
1612 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1614 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1615 entity
->u
.ifaceps
.mask
|= NumMethods
;
1617 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1619 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1622 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1627 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1631 if (error
) return FALSE
;
1632 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1633 if (end
) return TRUE
;
1635 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1638 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1640 WORD
*flags
= &entity
->u
.typelib
.flags
;
1641 const WCHAR
*str
= value
->ptr
, *start
;
1646 /* it's comma separated list of flags */
1647 while (i
< value
->len
)
1650 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1652 if (!strncmpiW(start
, restrictedW
, str
-start
))
1653 *flags
|= LIBFLAG_FRESTRICTED
;
1654 else if (!strncmpiW(start
, controlW
, str
-start
))
1655 *flags
|= LIBFLAG_FCONTROL
;
1656 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1657 *flags
|= LIBFLAG_FHIDDEN
;
1658 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1659 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1662 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1666 /* skip separator */
1674 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1676 unsigned int ver
[2];
1681 ver
[0] = ver
[1] = pos
= 0;
1682 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1684 if (*curr
>= '0' && *curr
<= '9')
1686 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1687 if (ver
[pos
] >= 0x10000) goto error
;
1689 else if (*curr
== '.')
1691 if (++pos
>= 2) goto error
;
1695 entity
->u
.typelib
.major
= ver
[0];
1696 entity
->u
.typelib
.minor
= ver
[1];
1700 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1704 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1706 xmlstr_t attr_name
, attr_value
;
1707 BOOL end
= FALSE
, error
;
1708 struct entity
* entity
;
1710 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1713 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1715 if (xmlstr_cmp(&attr_name
, tlbidW
))
1717 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1719 else if (xmlstr_cmp(&attr_name
, versionW
))
1721 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1723 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1725 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1727 else if (xmlstr_cmp(&attr_name
, flagsW
))
1729 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1733 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1737 if (error
) return FALSE
;
1739 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1741 if (end
) return TRUE
;
1743 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1746 static inline int aligned_string_len(int len
)
1748 return (len
+ 3) & ~3;
1751 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1753 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1754 struct assembly_version
*ver
= &assembly
->id
.version
;
1757 if (!ret
) ret
= buff
;
1758 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1761 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1763 xmlstr_t elem
, content
, attr_name
, attr_value
;
1764 BOOL end
= FALSE
, ret
= TRUE
, error
;
1765 struct entity
* entity
;
1767 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1770 entity
->u
.class.versioned
= TRUE
;
1771 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1773 if (xmlstr_cmp(&attr_name
, versionedW
))
1775 if (xmlstr_cmpi(&attr_value
, noW
))
1776 entity
->u
.class.versioned
= FALSE
;
1777 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1782 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1786 if (error
|| end
) return end
;
1788 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1790 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1792 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1794 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1796 if (xmlstr_cmp_end(&elem
, windowClassW
))
1798 ret
= parse_end_element(xmlbuf
);
1803 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1804 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1811 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1813 xmlstr_t attr_name
, attr_value
;
1814 BOOL end
= FALSE
, error
;
1816 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1818 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1820 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value
));
1822 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1824 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value
));
1828 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1832 if (error
|| end
) return end
;
1833 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1836 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1838 xmlstr_t elem
, content
, attr_name
, attr_value
;
1839 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1841 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1842 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1844 if (error
) return FALSE
;
1845 if (end
) return TRUE
;
1847 if (!parse_text_content(xmlbuf
, &content
))
1850 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1852 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1854 if (xmlstr_cmp_end(&elem
, descriptionW
))
1856 ret
= parse_end_element(xmlbuf
);
1861 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1862 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1869 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1870 struct assembly
* assembly
,
1871 struct actctx_loader
* acl
)
1873 xmlstr_t attr_name
, attr_value
;
1874 BOOL end
= FALSE
, error
;
1875 struct entity
* entity
;
1877 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1878 if (!entity
) return FALSE
;
1880 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1882 if (xmlstr_cmp(&attr_name
, iidW
))
1884 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1886 else if (xmlstr_cmp(&attr_name
, nameW
))
1888 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1890 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1892 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1893 entity
->u
.ifaceps
.mask
|= BaseIface
;
1895 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1897 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1898 entity
->u
.ifaceps
.mask
|= NumMethods
;
1900 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1902 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1904 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1906 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1910 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1914 if (error
) return FALSE
;
1915 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1916 if (end
) return TRUE
;
1918 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
1921 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1923 xmlstr_t attr_name
, attr_value
, elem
;
1924 BOOL end
= FALSE
, error
, ret
= TRUE
;
1925 struct entity
* entity
;
1927 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
1928 if (!entity
) return FALSE
;
1930 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1932 if (xmlstr_cmp(&attr_name
, nameW
))
1934 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1936 else if (xmlstr_cmp(&attr_name
, clsidW
))
1938 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1940 else if (xmlstr_cmp(&attr_name
, progidW
))
1942 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1944 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1946 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1948 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1950 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1952 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
1954 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
1958 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1962 if (error
) return FALSE
;
1963 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1964 if (entity
->u
.comclass
.progid
)
1965 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1966 if (end
) return TRUE
;
1968 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1970 if (xmlstr_cmp_end(&elem
, clrClassW
))
1972 ret
= parse_end_element(xmlbuf
);
1975 else if (xmlstr_cmp(&elem
, progidW
))
1977 ret
= parse_com_class_progid(xmlbuf
, entity
);
1981 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1982 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1986 if (entity
->u
.comclass
.progids
.num
)
1987 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1992 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
1994 xmlstr_t attr_name
, attr_value
;
1995 BOOL end
= FALSE
, error
;
1996 struct entity
* entity
;
1998 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
1999 if (!entity
) return FALSE
;
2001 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2003 if (xmlstr_cmp(&attr_name
, nameW
))
2005 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2007 else if (xmlstr_cmp(&attr_name
, clsidW
))
2009 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2011 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2013 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2017 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2021 if (error
) return FALSE
;
2022 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2023 if (end
) return TRUE
;
2025 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2028 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2030 struct assembly_identity ai
;
2031 xmlstr_t elem
, attr_name
, attr_value
;
2032 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2034 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2036 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2037 static const WCHAR trueW
[] = {'t','r','u','e',0};
2039 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2040 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2042 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2045 if (error
|| end
) return end
;
2047 memset(&ai
, 0, sizeof(ai
));
2048 ai
.optional
= optional
;
2049 ai
.delayed
= delayed
;
2051 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2052 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2055 TRACE( "adding name=%s version=%s arch=%s\n",
2056 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2058 /* store the newly found identity for later loading */
2059 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2061 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2063 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2065 ret
= parse_end_element(xmlbuf
);
2068 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2070 ret
= parse_binding_redirect_elem(xmlbuf
);
2074 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2075 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2082 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2084 xmlstr_t attr_name
, attr_value
, elem
;
2085 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2087 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2089 if (xmlstr_cmp(&attr_name
, optionalW
))
2091 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2092 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value
));
2096 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2100 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2102 if (xmlstr_cmp_end(&elem
, dependencyW
))
2104 ret
= parse_end_element(xmlbuf
);
2107 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2109 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2113 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2114 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2121 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2125 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2126 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2129 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2133 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2134 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2137 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2139 xmlstr_t attr_name
, attr_value
, elem
;
2140 BOOL end
= FALSE
, error
, ret
= TRUE
;
2141 struct dll_redirect
* dll
;
2143 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2145 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2147 if (xmlstr_cmp(&attr_name
, nameW
))
2149 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2150 TRACE("name=%s\n", debugstr_xmlstr(&attr_value
));
2152 else if (xmlstr_cmp(&attr_name
, hashW
))
2154 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2156 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2158 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2159 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2160 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value
));
2164 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2168 if (error
|| !dll
->name
) return FALSE
;
2170 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2172 if (end
) return TRUE
;
2174 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2176 if (xmlstr_cmp_end(&elem
, fileW
))
2178 ret
= parse_end_element(xmlbuf
);
2181 else if (xmlstr_cmp(&elem
, comClassW
))
2183 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2185 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2187 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2189 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2191 WARN("asmv2:hash (undocumented) not supported\n");
2192 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2194 else if (xmlstr_cmp(&elem
, typelibW
))
2196 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2198 else if (xmlstr_cmp(&elem
, windowClassW
))
2200 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2204 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
2205 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2212 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2213 struct assembly
* assembly
,
2214 struct assembly_identity
* expected_ai
)
2216 xmlstr_t attr_name
, attr_value
, elem
;
2217 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2219 TRACE("(%p)\n", xmlbuf
);
2221 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2223 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2225 static const WCHAR v10W
[] = {'1','.','0',0};
2226 if (!xmlstr_cmp(&attr_value
, v10W
))
2228 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
2233 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2235 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2236 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2237 !xmlstr_cmp(&attr_value
, manifestv3W
))
2239 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
2246 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
2250 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2251 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2253 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2255 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2257 assembly
->no_inherit
= TRUE
;
2260 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2262 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2265 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2266 assembly
->no_inherit
)
2271 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2273 ret
= parse_end_element(xmlbuf
);
2276 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2278 ret
= parse_description_elem(xmlbuf
);
2280 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2282 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2284 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2286 ret
= parse_dependency_elem(xmlbuf
, acl
);
2288 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2290 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2292 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2294 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2296 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2298 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2300 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2302 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2306 /* FIXME: more tests */
2307 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2308 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2310 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2311 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2312 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2313 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2314 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2317 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2318 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2319 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2320 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2321 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2322 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2324 FIXME("wrong version for shared assembly manifest\n");
2331 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
2332 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2334 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2340 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2341 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2345 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2347 if (xmlstr_cmp(&elem
, xmlW
) &&
2348 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2349 return STATUS_SXS_CANT_GEN_ACTCTX
;
2351 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2353 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
2354 return STATUS_SXS_CANT_GEN_ACTCTX
;
2357 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2359 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2360 return STATUS_SXS_CANT_GEN_ACTCTX
;
2363 if (next_xml_elem(xmlbuf
, &elem
))
2365 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2366 return STATUS_SXS_CANT_GEN_ACTCTX
;
2369 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2371 FIXME("parse error\n");
2372 return STATUS_SXS_CANT_GEN_ACTCTX
;
2374 return STATUS_SUCCESS
;
2377 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2378 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2379 const void *buffer
, SIZE_T size
)
2383 struct assembly
*assembly
;
2386 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2388 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2389 return STATUS_SXS_CANT_GEN_ACTCTX
;
2391 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2392 return STATUS_NO_MEMORY
;
2394 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2395 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2396 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2398 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2399 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2401 xmlbuf
.ptr
= buffer
;
2402 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2403 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2405 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2407 const WCHAR
*buf
= buffer
;
2411 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2412 return STATUS_NO_MEMORY
;
2413 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2414 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2415 xmlbuf
.ptr
= new_buff
;
2416 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2417 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2418 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2422 /* let's assume utf-8 for now */
2423 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2428 FIXME( "utf-8 conversion failed\n" );
2429 return STATUS_SXS_CANT_GEN_ACTCTX
;
2431 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2432 return STATUS_NO_MEMORY
;
2433 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2434 xmlbuf
.ptr
= new_buff
;
2435 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2436 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2437 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2442 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2444 OBJECT_ATTRIBUTES attr
;
2447 attr
.Length
= sizeof(attr
);
2448 attr
.RootDirectory
= 0;
2449 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2450 attr
.ObjectName
= name
;
2451 attr
.SecurityDescriptor
= NULL
;
2452 attr
.SecurityQualityOfService
= NULL
;
2453 return NtOpenFile( handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2456 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2462 LdrLockLoaderLock(0, NULL
, &magic
);
2463 status
= LdrFindEntryForAddress( module
, &pldr
);
2464 if (status
== STATUS_SUCCESS
)
2466 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2467 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2469 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2470 str
->Length
= pldr
->FullDllName
.Length
;
2471 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2473 else status
= STATUS_NO_MEMORY
;
2475 LdrUnlockLoaderLock(0, magic
);
2479 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2480 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2481 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2484 UNICODE_STRING nameW
;
2485 LDR_RESOURCE_INFO info
;
2486 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2489 if (TRACE_ON(actctx
))
2491 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2493 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2494 hModule
, debugstr_w(nameW
.Buffer
) );
2495 RtlFreeUnicodeString( &nameW
);
2497 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2498 hModule
, debugstr_w(filename
) );
2501 if (!resname
) return STATUS_INVALID_PARAMETER
;
2503 info
.Type
= RT_MANIFEST
;
2504 info
.Language
= lang
;
2505 if (!((ULONG_PTR
)resname
>> 16))
2507 info
.Name
= (ULONG_PTR
)resname
;
2508 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2510 else if (resname
[0] == '#')
2513 RtlInitUnicodeString(&nameW
, resname
+ 1);
2514 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2515 return STATUS_INVALID_PARAMETER
;
2517 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2521 RtlCreateUnicodeString(&nameW
, resname
);
2522 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2523 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2524 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2525 RtlFreeUnicodeString(&nameW
);
2527 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2529 if (status
== STATUS_SUCCESS
)
2530 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2535 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2536 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2537 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2540 OBJECT_ATTRIBUTES attr
;
2542 LARGE_INTEGER offset
;
2547 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2549 attr
.Length
= sizeof(attr
);
2550 attr
.RootDirectory
= 0;
2551 attr
.ObjectName
= NULL
;
2552 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2553 attr
.SecurityDescriptor
= NULL
;
2554 attr
.SecurityQualityOfService
= NULL
;
2557 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2558 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2559 if (status
!= STATUS_SUCCESS
) return status
;
2561 offset
.QuadPart
= 0;
2564 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2565 &count
, ViewShare
, 0, PAGE_READONLY
);
2567 if (status
!= STATUS_SUCCESS
) return status
;
2569 if (RtlImageNtHeader(base
)) /* we got a PE file */
2571 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2572 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2574 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2576 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2580 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2581 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2583 FILE_END_OF_FILE_INFORMATION info
;
2586 OBJECT_ATTRIBUTES attr
;
2588 LARGE_INTEGER offset
;
2593 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2595 attr
.Length
= sizeof(attr
);
2596 attr
.RootDirectory
= 0;
2597 attr
.ObjectName
= NULL
;
2598 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2599 attr
.SecurityDescriptor
= NULL
;
2600 attr
.SecurityQualityOfService
= NULL
;
2603 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2604 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2605 if (status
!= STATUS_SUCCESS
) return status
;
2607 offset
.QuadPart
= 0;
2610 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2611 &count
, ViewShare
, 0, PAGE_READONLY
);
2613 if (status
!= STATUS_SUCCESS
) return status
;
2615 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2616 if (status
== STATUS_SUCCESS
)
2617 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2619 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2623 /* try to load the .manifest file associated to the file */
2624 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2625 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2627 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2630 UNICODE_STRING nameW
;
2632 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2634 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2636 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2638 if (module
) /* use the module filename */
2640 UNICODE_STRING name
;
2642 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2644 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2645 strcatW( name
.Buffer
, dotManifestW
);
2646 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2647 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2648 RtlFreeUnicodeString( &name
);
2650 if (status
) return status
;
2654 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2655 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2656 return STATUS_NO_MEMORY
;
2657 strcpyW( buffer
, filename
);
2658 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2659 strcatW( buffer
, dotManifestW
);
2660 RtlInitUnicodeString( &nameW
, buffer
);
2663 if (!open_nt_file( &file
, &nameW
))
2665 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2668 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2669 RtlFreeUnicodeString( &nameW
);
2673 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2675 static const WCHAR lookup_fmtW
[] =
2676 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2677 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2678 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2680 WCHAR
*lookup
, *ret
= NULL
;
2681 UNICODE_STRING lookup_us
;
2683 const WCHAR
*lang
= ai
->language
;
2684 unsigned int data_pos
= 0, data_len
;
2687 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2688 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2689 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2690 + sizeof(lookup_fmtW
) )))
2693 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2694 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2695 ai
->version
.major
, ai
->version
.minor
, lang
);
2696 RtlInitUnicodeString( &lookup_us
, lookup
);
2698 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2699 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2700 if (io
.u
.Status
== STATUS_SUCCESS
)
2702 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2703 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2705 ULONG build
, revision
;
2707 data_len
= io
.Information
;
2711 if (data_pos
>= data_len
)
2713 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2714 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2715 if (io
.u
.Status
!= STATUS_SUCCESS
) break;
2716 data_len
= io
.Information
;
2719 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2721 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2722 else data_pos
= data_len
;
2724 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2726 if (build
< min_build
) continue;
2727 tmp
= strchrW(tmp
, '.') + 1;
2728 revision
= atoiW(tmp
);
2729 if (build
== min_build
&& revision
< min_revision
) continue;
2730 tmp
= strchrW(tmp
, '_') + 1;
2731 tmp
= strchrW(tmp
, '_') + 1;
2732 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2733 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2735 /* prefer a non-Wine manifest if we already have one */
2736 /* we'll still load the builtin dll if specified through DllOverrides */
2742 min_revision
= revision
;
2744 ai
->version
.build
= build
;
2745 ai
->version
.revision
= revision
;
2746 RtlFreeHeap( GetProcessHeap(), 0, ret
);
2747 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2749 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2750 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2754 else WARN("no matching file for %s\n", debugstr_w(lookup
));
2755 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
2759 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2761 struct assembly_identity sxs_ai
;
2762 UNICODE_STRING path_us
;
2763 OBJECT_ATTRIBUTES attr
;
2765 WCHAR
*path
, *file
= NULL
;
2768 static const WCHAR manifest_dirW
[] =
2769 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2771 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2773 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
2774 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
2775 return STATUS_NO_MEMORY
;
2777 strcpyW( path
, user_shared_data
->NtSystemRoot
);
2778 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
2780 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2782 RtlFreeHeap( GetProcessHeap(), 0, path
);
2783 return STATUS_NO_SUCH_FILE
;
2785 RtlFreeHeap( GetProcessHeap(), 0, path
);
2787 attr
.Length
= sizeof(attr
);
2788 attr
.RootDirectory
= 0;
2789 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2790 attr
.ObjectName
= &path_us
;
2791 attr
.SecurityDescriptor
= NULL
;
2792 attr
.SecurityQualityOfService
= NULL
;
2794 if (!NtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2795 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2798 file
= lookup_manifest_file( handle
, &sxs_ai
);
2803 RtlFreeUnicodeString( &path_us
);
2804 return STATUS_NO_SUCH_FILE
;
2807 /* append file name to directory path */
2808 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
2809 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2811 RtlFreeHeap( GetProcessHeap(), 0, file
);
2812 RtlFreeUnicodeString( &path_us
);
2813 return STATUS_NO_MEMORY
;
2816 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2817 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2818 RtlInitUnicodeString( &path_us
, path
);
2819 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2821 if (!open_nt_file( &handle
, &path_us
))
2823 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2826 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
2828 RtlFreeHeap( GetProcessHeap(), 0, file
);
2829 RtlFreeUnicodeString( &path_us
);
2833 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2834 struct assembly_identity
* ai
)
2836 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2838 WCHAR
*buffer
, *p
, *directory
;
2840 UNICODE_STRING nameW
;
2844 TRACE( "looking for name=%s version=%s arch=%s\n",
2845 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
2847 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2849 /* FIXME: add support for language specific lookup */
2851 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2852 strlenW(acl
->actctx
->appdir
.info
));
2854 nameW
.Buffer
= NULL
;
2855 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2856 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2857 return STATUS_NO_MEMORY
;
2859 if (!(directory
= build_assembly_dir( ai
)))
2861 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2862 return STATUS_NO_MEMORY
;
2865 /* Lookup in <dir>\name.dll
2866 * <dir>\name.manifest
2867 * <dir>\name\name.dll
2868 * <dir>\name\name.manifest
2870 * First 'appdir' is used as <dir>, if that failed
2871 * it tries application manifest file path.
2873 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
2874 p
= buffer
+ strlenW(buffer
);
2875 for (i
= 0; i
< 4; i
++)
2879 struct assembly
*assembly
= acl
->actctx
->assemblies
;
2880 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
2884 strcpyW( p
, ai
->name
);
2887 strcpyW( p
, dotDllW
);
2888 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2890 status
= open_nt_file( &file
, &nameW
);
2893 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
2894 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
2898 RtlFreeUnicodeString( &nameW
);
2901 strcpyW( p
, dotManifestW
);
2902 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2904 status
= open_nt_file( &file
, &nameW
);
2907 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2911 RtlFreeUnicodeString( &nameW
);
2913 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
2915 RtlFreeUnicodeString( &nameW
);
2916 RtlFreeHeap( GetProcessHeap(), 0, directory
);
2917 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2921 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
2923 NTSTATUS status
= STATUS_SUCCESS
;
2926 for (i
= 0; i
< acl
->num_dependencies
; i
++)
2928 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
2930 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
2932 FIXME( "Could not find dependent assembly %s (%s)\n",
2933 debugstr_w(acl
->dependencies
[i
].name
),
2934 debugstr_version(&acl
->dependencies
[i
].version
) );
2935 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
2940 /* FIXME should now iterate through all refs */
2944 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2945 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
2947 NTSTATUS status
= STATUS_SUCCESS
;
2949 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
2951 if (*handle
) return STATUS_INVALID_PARAMETER
;
2953 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
2954 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
2956 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
2961 if (!*handle
) return STATUS_INVALID_PARAMETER
;
2963 LdrLockLoaderLock( 0, NULL
, &magic
);
2964 if (!LdrFindEntryForAddress( *handle
, &pldr
))
2966 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
2967 status
= STATUS_DLL_NOT_FOUND
;
2969 *handle
= pldr
->ActivationContext
;
2971 else status
= STATUS_DLL_NOT_FOUND
;
2972 LdrUnlockLoaderLock( 0, magic
);
2974 else if (!*handle
&& (class != ActivationContextBasicInformation
))
2975 *handle
= process_actctx
;
2980 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
2982 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
2983 struct strsection_header
*header
;
2984 struct dllredirect_data
*data
;
2985 struct string_index
*index
;
2988 /* compute section length */
2989 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2991 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2992 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2994 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2996 /* each entry needs index, data and string data */
2997 total_len
+= sizeof(*index
);
2998 total_len
+= sizeof(*data
);
2999 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3002 dll_count
+= assembly
->num_dlls
;
3005 total_len
+= sizeof(*header
);
3007 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3008 if (!header
) return STATUS_NO_MEMORY
;
3010 memset(header
, 0, sizeof(*header
));
3011 header
->magic
= STRSECTION_MAGIC
;
3012 header
->size
= sizeof(*header
);
3013 header
->count
= dll_count
;
3014 header
->index_offset
= sizeof(*header
);
3015 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3016 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3018 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3020 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3021 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3023 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3027 /* setup new index entry */
3028 str
.Buffer
= dll
->name
;
3029 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
3030 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3031 /* hash original class name */
3032 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3034 index
->name_offset
= name_offset
;
3035 index
->name_len
= str
.Length
;
3036 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3037 index
->data_len
= sizeof(*data
);
3038 index
->rosterindex
= i
+ 1;
3041 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3042 data
->size
= sizeof(*data
);
3043 data
->unk
= 2; /* FIXME: seems to be constant */
3044 memset(data
->res
, 0, sizeof(data
->res
));
3047 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3048 memcpy(ptrW
, dll
->name
, index
->name_len
);
3049 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3051 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3059 return STATUS_SUCCESS
;
3062 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3064 struct string_index
*iter
, *index
= NULL
;
3067 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3068 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3070 for (i
= 0; i
< section
->count
; i
++)
3072 if (iter
->hash
== hash
)
3074 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3076 if (!strcmpiW(nameW
, name
->Buffer
))
3082 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3090 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3092 struct guid_index
*iter
, *index
= NULL
;
3095 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3097 for (i
= 0; i
< section
->count
; i
++)
3099 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3110 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3112 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3115 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3116 PACTCTX_SECTION_KEYED_DATA data
)
3118 struct dllredirect_data
*dll
;
3119 struct string_index
*index
;
3121 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3123 if (!actctx
->dllredirect_section
)
3125 struct strsection_header
*section
;
3127 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3128 if (status
) return status
;
3130 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
3131 RtlFreeHeap(GetProcessHeap(), 0, section
);
3134 index
= find_string_index(actctx
->dllredirect_section
, name
);
3135 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3137 dll
= get_dllredirect_data(actctx
, index
);
3139 data
->ulDataFormatVersion
= 1;
3141 data
->ulLength
= dll
->size
;
3142 data
->lpSectionGlobalData
= NULL
;
3143 data
->ulSectionGlobalDataLength
= 0;
3144 data
->lpSectionBase
= actctx
->dllredirect_section
;
3145 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3146 data
->hActCtx
= NULL
;
3148 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3149 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3151 return STATUS_SUCCESS
;
3154 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3156 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3159 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3161 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3164 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3166 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3167 struct wndclass_redirect_data
*data
;
3168 struct strsection_header
*header
;
3169 struct string_index
*index
;
3172 /* compute section length */
3173 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3175 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3176 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3178 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3179 for (k
= 0; k
< dll
->entities
.num
; k
++)
3181 struct entity
*entity
= &dll
->entities
.base
[k
];
3182 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3184 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3187 /* each class entry needs index, data and string data */
3188 total_len
+= sizeof(*index
);
3189 total_len
+= sizeof(*data
);
3190 /* original name is stored separately */
3191 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3192 /* versioned name and module name are stored one after another */
3193 if (entity
->u
.class.versioned
)
3194 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3197 len
+= strlenW(dll
->name
) + 1;
3198 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3206 total_len
+= sizeof(*header
);
3208 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3209 if (!header
) return STATUS_NO_MEMORY
;
3211 memset(header
, 0, sizeof(*header
));
3212 header
->magic
= STRSECTION_MAGIC
;
3213 header
->size
= sizeof(*header
);
3214 header
->count
= class_count
;
3215 header
->index_offset
= sizeof(*header
);
3216 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3217 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3219 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3221 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3222 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3224 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3225 for (k
= 0; k
< dll
->entities
.num
; k
++)
3227 struct entity
*entity
= &dll
->entities
.base
[k
];
3228 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3230 static const WCHAR exclW
[] = {'!',0};
3231 ULONG versioned_len
, module_len
;
3235 /* setup new index entry */
3236 str
.Buffer
= entity
->u
.class.name
;
3237 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3238 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3239 /* hash original class name */
3240 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3242 /* include '!' separator too */
3243 if (entity
->u
.class.versioned
)
3244 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3246 versioned_len
= str
.Length
;
3247 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3249 index
->name_offset
= name_offset
;
3250 index
->name_len
= str
.Length
;
3251 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3252 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3253 index
->rosterindex
= i
+ 1;
3256 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3257 data
->size
= sizeof(*data
);
3259 data
->name_len
= versioned_len
;
3260 data
->name_offset
= sizeof(*data
);
3261 data
->module_len
= module_len
;
3262 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3264 /* original class name */
3265 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3266 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3267 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3270 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3271 memcpy(ptrW
, dll
->name
, data
->module_len
);
3272 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3274 /* versioned name */
3275 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3276 if (entity
->u
.class.versioned
)
3278 get_assembly_version(assembly
, ptrW
);
3279 strcatW(ptrW
, exclW
);
3280 strcatW(ptrW
, entity
->u
.class.name
);
3284 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3285 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3288 name_offset
+= sizeof(*data
);
3289 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3299 return STATUS_SUCCESS
;
3302 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3303 PACTCTX_SECTION_KEYED_DATA data
)
3305 struct string_index
*iter
, *index
= NULL
;
3306 struct wndclass_redirect_data
*class;
3310 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3312 if (!actctx
->wndclass_section
)
3314 struct strsection_header
*section
;
3316 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3317 if (status
) return status
;
3319 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
3320 RtlFreeHeap(GetProcessHeap(), 0, section
);
3324 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3325 iter
= get_wndclass_first_index(actctx
);
3327 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3329 if (iter
->hash
== hash
)
3331 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3333 if (!strcmpW(nameW
, name
->Buffer
))
3339 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
3344 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3346 class = get_wndclass_data(actctx
, index
);
3348 data
->ulDataFormatVersion
= 1;
3349 data
->lpData
= class;
3350 /* full length includes string length with nulls */
3351 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3352 data
->lpSectionGlobalData
= NULL
;
3353 data
->ulSectionGlobalDataLength
= 0;
3354 data
->lpSectionBase
= actctx
->wndclass_section
;
3355 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3356 data
->hActCtx
= NULL
;
3358 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3359 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3361 return STATUS_SUCCESS
;
3364 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3366 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3367 struct guidsection_header
*header
;
3368 ULONG module_offset
, data_offset
;
3369 struct tlibredirect_data
*data
;
3370 struct guid_index
*index
;
3372 /* compute section length */
3373 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3375 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3376 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3378 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3379 for (k
= 0; k
< dll
->entities
.num
; k
++)
3381 struct entity
*entity
= &dll
->entities
.base
[k
];
3382 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3384 /* each entry needs index, data and string data for module name and help string */
3385 total_len
+= sizeof(*index
);
3386 total_len
+= sizeof(*data
);
3387 /* help string is stored separately */
3388 if (*entity
->u
.typelib
.helpdir
)
3389 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3391 /* module names are packed one after another */
3392 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3400 total_len
+= aligned_string_len(names_len
);
3401 total_len
+= sizeof(*header
);
3403 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3404 if (!header
) return STATUS_NO_MEMORY
;
3406 memset(header
, 0, sizeof(*header
));
3407 header
->magic
= GUIDSECTION_MAGIC
;
3408 header
->size
= sizeof(*header
);
3409 header
->count
= tlib_count
;
3410 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3411 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3412 module_offset
= sizeof(*header
);
3413 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3415 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3417 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3418 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3420 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3421 for (k
= 0; k
< dll
->entities
.num
; k
++)
3423 struct entity
*entity
= &dll
->entities
.base
[k
];
3424 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3426 ULONG module_len
, help_len
;
3430 if (*entity
->u
.typelib
.helpdir
)
3431 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3435 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3437 /* setup new index entry */
3438 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3439 RtlGUIDFromString(&str
, &index
->guid
);
3440 index
->data_offset
= data_offset
;
3441 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3442 index
->rosterindex
= i
+ 1;
3445 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3446 data
->size
= sizeof(*data
);
3448 data
->name_len
= module_len
;
3449 data
->name_offset
= module_offset
;
3450 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3452 data
->flags
= entity
->u
.typelib
.flags
;
3453 data
->help_len
= help_len
;
3454 data
->help_offset
= sizeof(*data
);
3455 data
->major_version
= entity
->u
.typelib
.major
;
3456 data
->minor_version
= entity
->u
.typelib
.minor
;
3459 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3460 memcpy(ptrW
, dll
->name
, data
->name_len
);
3461 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3466 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3467 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3468 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3471 data_offset
+= sizeof(*data
);
3473 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3475 module_offset
+= module_len
+ sizeof(WCHAR
);
3485 return STATUS_SUCCESS
;
3488 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3490 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3493 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3495 struct guid_index
*index
= NULL
;
3496 struct tlibredirect_data
*tlib
;
3498 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3500 if (!actctx
->tlib_section
)
3502 struct guidsection_header
*section
;
3504 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3505 if (status
) return status
;
3507 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3508 RtlFreeHeap(GetProcessHeap(), 0, section
);
3511 index
= find_guid_index(actctx
->tlib_section
, guid
);
3512 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3514 tlib
= get_tlib_data(actctx
, index
);
3516 data
->ulDataFormatVersion
= 1;
3517 data
->lpData
= tlib
;
3518 /* full length includes string length with nulls */
3519 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3520 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3521 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3522 data
->lpSectionBase
= actctx
->tlib_section
;
3523 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3524 data
->hActCtx
= NULL
;
3526 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3527 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3529 return STATUS_SUCCESS
;
3532 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3534 ULONG
*ptr
= (ULONG
*)guid
;
3537 /* GUID is 16 bytes long */
3538 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3539 *ptr
= RtlUniform(seed
);
3541 guid
->Data3
&= 0x0fff;
3542 guid
->Data3
|= (4 << 12);
3543 guid
->Data4
[0] &= 0x3f;
3544 guid
->Data4
[0] |= 0x80;
3547 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3548 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3552 for (i
= 0; i
< entities
->num
; i
++)
3554 struct entity
*entity
= &entities
->base
[i
];
3555 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3557 /* each entry needs two index entries, extra one goes for alias GUID */
3558 *len
+= 2*sizeof(struct guid_index
);
3559 /* To save some memory we don't allocated two data structures,
3560 instead alias index and normal index point to the same data structure. */
3561 *len
+= sizeof(struct comclassredirect_data
);
3563 /* for clrClass store some more */
3564 if (entity
->u
.comclass
.name
)
3566 unsigned int str_len
;
3568 /* all string data is stored together in aligned block */
3569 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3570 if (entity
->u
.comclass
.progid
)
3571 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3572 if (entity
->u
.comclass
.version
)
3573 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3575 *len
+= sizeof(struct clrclass_data
);
3576 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3578 /* module name is forced to mscoree.dll, and stored two times with different case */
3579 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3583 /* progid string is stored separately */
3584 if (entity
->u
.comclass
.progid
)
3585 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3587 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3595 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3596 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3597 ULONG
*seed
, ULONG rosterindex
)
3601 for (i
= 0; i
< entities
->num
; i
++)
3603 struct entity
*entity
= &entities
->base
[i
];
3604 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3606 ULONG module_len
, progid_len
, str_len
= 0;
3607 struct comclassredirect_data
*data
;
3608 struct guid_index
*alias_index
;
3609 struct clrclass_data
*clrdata
;
3613 if (entity
->u
.comclass
.progid
)
3614 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3618 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3620 /* setup new index entry */
3621 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3622 RtlGUIDFromString(&str
, &(*index
)->guid
);
3624 (*index
)->data_offset
= *data_offset
;
3625 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3626 (*index
)->rosterindex
= rosterindex
;
3628 /* Setup new index entry for alias guid. Alias index records are placed after
3629 normal records, so normal guids are hit first on search. Note that class count
3631 alias_index
= (*index
) + section
->count
/2;
3632 generate_uuid(seed
, &alias_index
->guid
);
3633 alias_index
->data_offset
= (*index
)->data_offset
;
3634 alias_index
->data_len
= 0;
3635 alias_index
->rosterindex
= (*index
)->rosterindex
;
3638 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3639 data
->size
= sizeof(*data
);
3643 data
->model
= entity
->u
.comclass
.model
;
3644 data
->clsid
= (*index
)->guid
;
3645 data
->alias
= alias_index
->guid
;
3646 data
->clsid2
= data
->clsid
;
3647 if (entity
->u
.comclass
.tlbid
)
3649 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3650 RtlGUIDFromString(&str
, &data
->tlbid
);
3653 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3654 data
->name_len
= module_len
;
3655 data
->name_offset
= *module_offset
;
3656 data
->progid_len
= progid_len
;
3657 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3658 data
->clrdata_len
= 0; /* will be set later */
3659 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3660 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3661 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3662 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3663 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3664 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3666 /* mask describes which misc* data is available */
3668 if (data
->miscstatus
)
3669 data
->miscmask
|= MiscStatus
;
3670 if (data
->miscstatuscontent
)
3671 data
->miscmask
|= MiscStatusContent
;
3672 if (data
->miscstatusthumbnail
)
3673 data
->miscmask
|= MiscStatusThumbnail
;
3674 if (data
->miscstatusicon
)
3675 data
->miscmask
|= MiscStatusIcon
;
3676 if (data
->miscstatusdocprint
)
3677 data
->miscmask
|= MiscStatusDocPrint
;
3679 if (data
->clrdata_offset
)
3681 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3683 clrdata
->size
= sizeof(*clrdata
);
3684 clrdata
->res
[0] = 0;
3685 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3686 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3687 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3688 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3689 clrdata
->name_offset
= clrdata
->size
;
3690 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3691 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3692 clrdata
->res2
[0] = 0;
3693 clrdata
->res2
[1] = 0;
3695 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3698 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3699 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3700 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3702 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3703 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3704 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3707 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3708 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3709 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3711 /* runtime version, optional */
3712 if (clrdata
->version_len
)
3714 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3716 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3717 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3718 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3721 if (data
->progid_len
)
3722 data
->progid_offset
+= data
->clrdata_len
;
3723 (*index
)->data_len
+= sizeof(*clrdata
);
3730 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3731 memcpy(ptrW
, dll
->name
, data
->name_len
);
3732 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3736 if (data
->progid_len
)
3738 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3739 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3740 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3743 /* string block length */
3747 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3748 if (clrdata
->version_len
)
3749 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3752 str_len
+= progid_len
+ sizeof(WCHAR
);
3754 (*index
)->data_len
+= aligned_string_len(str_len
);
3755 alias_index
->data_len
= (*index
)->data_len
;
3757 /* move to next data record */
3758 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3759 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3763 (*data_offset
) += sizeof(*clrdata
);
3764 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3771 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3773 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3774 struct guidsection_header
*header
;
3775 ULONG module_offset
, data_offset
;
3776 struct guid_index
*index
;
3779 /* compute section length */
3780 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3782 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3783 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3784 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3786 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3787 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3791 total_len
+= aligned_string_len(names_len
);
3792 total_len
+= sizeof(*header
);
3794 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3795 if (!header
) return STATUS_NO_MEMORY
;
3797 memset(header
, 0, sizeof(*header
));
3798 header
->magic
= GUIDSECTION_MAGIC
;
3799 header
->size
= sizeof(*header
);
3800 header
->count
= 2*class_count
;
3801 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3802 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3803 module_offset
= sizeof(*header
);
3804 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3806 seed
= NtGetTickCount();
3807 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3809 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3810 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3811 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3813 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3814 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3820 return STATUS_SUCCESS
;
3823 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3825 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3828 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3830 struct comclassredirect_data
*comclass
;
3831 struct guid_index
*index
= NULL
;
3833 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3835 if (!actctx
->comserver_section
)
3837 struct guidsection_header
*section
;
3839 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
3840 if (status
) return status
;
3842 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
3843 RtlFreeHeap(GetProcessHeap(), 0, section
);
3846 index
= find_guid_index(actctx
->comserver_section
, guid
);
3847 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3849 comclass
= get_comclass_data(actctx
, index
);
3851 data
->ulDataFormatVersion
= 1;
3852 data
->lpData
= comclass
;
3853 /* full length includes string length with nulls */
3854 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
3855 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
3856 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
3857 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
3858 data
->lpSectionBase
= actctx
->comserver_section
;
3859 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
3860 data
->hActCtx
= NULL
;
3862 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3863 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3865 return STATUS_SUCCESS
;
3868 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
3872 for (i
= 0; i
< entities
->num
; i
++)
3874 struct entity
*entity
= &entities
->base
[i
];
3875 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3877 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
3878 if (entity
->u
.ifaceps
.name
)
3879 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
3885 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
3886 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
3890 for (i
= 0; i
< entities
->num
; i
++)
3892 struct entity
*entity
= &entities
->base
[i
];
3893 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
3895 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
3899 if (entity
->u
.ifaceps
.name
)
3900 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
3905 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
3906 RtlGUIDFromString(&str
, &(*index
)->guid
);
3907 (*index
)->data_offset
= *data_offset
;
3908 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
3909 (*index
)->rosterindex
= rosterindex
;
3911 /* setup data record */
3912 data
->size
= sizeof(*data
);
3913 data
->mask
= entity
->u
.ifaceps
.mask
;
3915 /* proxyStubClsid32 value is only stored for external PS,
3916 if set it's used as iid, otherwise 'iid' attribute value is used */
3917 if (entity
->u
.ifaceps
.ps32
)
3919 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
3920 RtlGUIDFromString(&str
, &data
->iid
);
3923 data
->iid
= (*index
)->guid
;
3925 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
3927 if (entity
->u
.ifaceps
.tlib
)
3929 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
3930 RtlGUIDFromString(&str
, &data
->tlbid
);
3933 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3935 if (entity
->u
.ifaceps
.base
)
3937 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
3938 RtlGUIDFromString(&str
, &data
->base
);
3941 memset(&data
->base
, 0, sizeof(data
->base
));
3943 data
->name_len
= name_len
;
3944 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
3949 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3950 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
3951 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3954 /* move to next record */
3956 *data_offset
+= sizeof(*data
);
3958 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
3963 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3965 unsigned int i
, j
, total_len
= 0, count
= 0;
3966 struct guidsection_header
*header
;
3967 struct guid_index
*index
;
3970 /* compute section length */
3971 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3973 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3975 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
3976 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3978 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3979 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
3983 total_len
+= sizeof(*header
);
3985 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3986 if (!header
) return STATUS_NO_MEMORY
;
3988 memset(header
, 0, sizeof(*header
));
3989 header
->magic
= GUIDSECTION_MAGIC
;
3990 header
->size
= sizeof(*header
);
3991 header
->count
= count
;
3992 header
->index_offset
= sizeof(*header
);
3993 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3994 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
3996 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3998 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4000 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4001 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4003 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4004 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4010 return STATUS_SUCCESS
;
4013 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4015 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4018 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4020 struct ifacepsredirect_data
*iface
;
4021 struct guid_index
*index
= NULL
;
4023 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4025 if (!actctx
->ifaceps_section
)
4027 struct guidsection_header
*section
;
4029 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4030 if (status
) return status
;
4032 if (interlocked_cmpxchg_ptr((void**)&actctx
->ifaceps_section
, section
, NULL
))
4033 RtlFreeHeap(GetProcessHeap(), 0, section
);
4036 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4037 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4039 iface
= get_ifaceps_data(actctx
, index
);
4041 data
->ulDataFormatVersion
= 1;
4042 data
->lpData
= iface
;
4043 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4044 data
->lpSectionGlobalData
= NULL
;
4045 data
->ulSectionGlobalDataLength
= 0;
4046 data
->lpSectionBase
= actctx
->ifaceps_section
;
4047 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4048 data
->hActCtx
= NULL
;
4050 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4051 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4053 return STATUS_SUCCESS
;
4056 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4058 unsigned int i
, j
, total_len
= 0, count
= 0;
4059 struct guidsection_header
*header
;
4060 struct clrsurrogate_data
*data
;
4061 struct guid_index
*index
;
4064 /* compute section length */
4065 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4067 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4068 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4070 struct entity
*entity
= &assembly
->entities
.base
[j
];
4071 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4075 total_len
+= sizeof(*index
) + sizeof(*data
);
4076 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4077 if (entity
->u
.clrsurrogate
.version
)
4078 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4079 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4086 total_len
+= sizeof(*header
);
4088 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4089 if (!header
) return STATUS_NO_MEMORY
;
4091 memset(header
, 0, sizeof(*header
));
4092 header
->magic
= GUIDSECTION_MAGIC
;
4093 header
->size
= sizeof(*header
);
4094 header
->count
= count
;
4095 header
->index_offset
= sizeof(*header
);
4096 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4097 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4099 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4101 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4102 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4104 struct entity
*entity
= &assembly
->entities
.base
[j
];
4105 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4107 ULONG version_len
, name_len
;
4111 if (entity
->u
.clrsurrogate
.version
)
4112 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4115 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4117 /* setup new index entry */
4118 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4119 RtlGUIDFromString(&str
, &index
->guid
);
4121 index
->data_offset
= data_offset
;
4122 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4123 index
->rosterindex
= i
+ 1;
4126 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4127 data
->size
= sizeof(*data
);
4129 data
->clsid
= index
->guid
;
4130 data
->version_offset
= version_len
? data
->size
: 0;
4131 data
->version_len
= version_len
;
4132 data
->name_offset
= data
->size
+ version_len
;
4134 data
->name_offset
+= sizeof(WCHAR
);
4135 data
->name_len
= name_len
;
4137 /* surrogate name */
4138 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4139 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4140 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4142 /* runtime version */
4143 if (data
->version_len
)
4145 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4146 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4147 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4150 data_offset
+= index
->data_offset
;
4158 return STATUS_SUCCESS
;
4161 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4163 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4166 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4168 struct clrsurrogate_data
*surrogate
;
4169 struct guid_index
*index
= NULL
;
4171 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4173 if (!actctx
->clrsurrogate_section
)
4175 struct guidsection_header
*section
;
4177 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4178 if (status
) return status
;
4180 if (interlocked_cmpxchg_ptr((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4181 RtlFreeHeap(GetProcessHeap(), 0, section
);
4184 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4185 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4187 surrogate
= get_surrogate_data(actctx
, index
);
4189 data
->ulDataFormatVersion
= 1;
4190 data
->lpData
= surrogate
;
4191 /* full length includes string length with nulls */
4192 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4193 if (surrogate
->version_len
)
4194 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4196 data
->lpSectionGlobalData
= NULL
;
4197 data
->ulSectionGlobalDataLength
= 0;
4198 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4199 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4200 data
->hActCtx
= NULL
;
4202 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4203 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4205 return STATUS_SUCCESS
;
4208 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4210 unsigned int i
, j
, single_len
;
4212 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4213 for (i
= 0; i
< entities
->num
; i
++)
4215 struct entity
*entity
= &entities
->base
[i
];
4216 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4218 if (entity
->u
.comclass
.progid
)
4220 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4224 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4225 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4227 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4228 *count
+= entity
->u
.comclass
.progids
.num
;
4233 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4234 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4236 struct progidredirect_data
*data
;
4241 /* setup new index entry */
4243 /* hash progid name */
4244 RtlInitUnicodeString(&str
, progid
);
4245 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4247 (*index
)->name_offset
= *data_offset
;
4248 (*index
)->name_len
= str
.Length
;
4249 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4250 (*index
)->data_len
= sizeof(*data
);
4251 (*index
)->rosterindex
= rosterindex
;
4253 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4255 /* setup data structure */
4256 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4257 data
->size
= sizeof(*data
);
4259 data
->clsid_offset
= *global_offset
;
4261 /* write progid string */
4262 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4263 memcpy(ptrW
, progid
, (*index
)->name_len
);
4264 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4266 /* write guid to global area */
4267 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4271 *global_offset
+= sizeof(GUID
);
4272 *data_offset
+= data
->size
;
4276 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4277 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4281 for (i
= 0; i
< entities
->num
; i
++)
4283 struct entity
*entity
= &entities
->base
[i
];
4284 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4286 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4287 struct comclassredirect_data
*comclass
;
4288 struct guid_index
*guid_index
;
4292 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4293 RtlGUIDFromString(&str
, &clsid
);
4295 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4296 comclass
= get_comclass_data(actctx
, guid_index
);
4298 if (entity
->u
.comclass
.progid
)
4299 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4300 index
, data_offset
, global_offset
, rosterindex
);
4302 for (j
= 0; j
< progids
->num
; j
++)
4303 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4304 index
, data_offset
, global_offset
, rosterindex
);
4309 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4311 unsigned int i
, j
, total_len
= 0, count
= 0;
4312 struct strsection_header
*header
;
4313 ULONG data_offset
, global_offset
;
4314 struct string_index
*index
;
4316 /* compute section length */
4317 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4319 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4321 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4322 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4324 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4325 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4329 total_len
+= sizeof(*header
);
4331 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4332 if (!header
) return STATUS_NO_MEMORY
;
4334 memset(header
, 0, sizeof(*header
));
4335 header
->magic
= STRSECTION_MAGIC
;
4336 header
->size
= sizeof(*header
);
4337 header
->count
= count
;
4338 header
->global_offset
= header
->size
;
4339 header
->global_len
= count
*sizeof(GUID
);
4340 header
->index_offset
= header
->size
+ header
->global_len
;
4342 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4343 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4344 global_offset
= header
->global_offset
;
4346 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4348 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4350 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4351 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4353 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4354 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4360 return STATUS_SUCCESS
;
4363 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4365 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4368 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4369 PACTCTX_SECTION_KEYED_DATA data
)
4371 struct progidredirect_data
*progid
;
4372 struct string_index
*index
;
4374 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4376 if (!actctx
->comserver_section
)
4378 struct guidsection_header
*section
;
4380 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4381 if (status
) return status
;
4383 if (interlocked_cmpxchg_ptr((void**)&actctx
->comserver_section
, section
, NULL
))
4384 RtlFreeHeap(GetProcessHeap(), 0, section
);
4387 if (!actctx
->progid_section
)
4389 struct strsection_header
*section
;
4391 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4392 if (status
) return status
;
4394 if (interlocked_cmpxchg_ptr((void**)&actctx
->progid_section
, section
, NULL
))
4395 RtlFreeHeap(GetProcessHeap(), 0, section
);
4398 index
= find_string_index(actctx
->progid_section
, name
);
4399 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4401 progid
= get_progid_data(actctx
, index
);
4403 data
->ulDataFormatVersion
= 1;
4404 data
->lpData
= progid
;
4405 data
->ulLength
= progid
->size
;
4406 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4407 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4408 data
->lpSectionBase
= actctx
->progid_section
;
4409 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4410 data
->hActCtx
= NULL
;
4412 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4413 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4415 return STATUS_SUCCESS
;
4418 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4419 const UNICODE_STRING
*section_name
,
4420 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4424 switch (section_kind
)
4426 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4427 status
= find_dll_redirection(actctx
, section_name
, data
);
4429 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4430 status
= find_window_class(actctx
, section_name
, data
);
4432 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4433 status
= find_progid_redirection(actctx
, section_name
, data
);
4435 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4436 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4437 return STATUS_SXS_SECTION_NOT_FOUND
;
4439 WARN("Unknown section_kind %x\n", section_kind
);
4440 return STATUS_SXS_SECTION_NOT_FOUND
;
4443 if (status
!= STATUS_SUCCESS
) return status
;
4445 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4447 actctx_addref(actctx
);
4448 data
->hActCtx
= actctx
;
4450 return STATUS_SUCCESS
;
4453 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4454 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4458 switch (section_kind
)
4460 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4461 status
= find_tlib_redirection(actctx
, guid
, data
);
4463 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4464 status
= find_comserver_redirection(actctx
, guid
, data
);
4466 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4467 status
= find_cominterface_redirection(actctx
, guid
, data
);
4469 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4470 status
= find_clr_surrogate(actctx
, guid
, data
);
4473 WARN("Unknown section_kind %x\n", section_kind
);
4474 return STATUS_SXS_SECTION_NOT_FOUND
;
4477 if (status
!= STATUS_SUCCESS
) return status
;
4479 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4481 actctx_addref(actctx
);
4482 data
->hActCtx
= actctx
;
4484 return STATUS_SUCCESS
;
4487 /* initialize the activation context for the current process */
4488 void actctx_init(void)
4493 ctx
.cbSize
= sizeof(ctx
);
4494 ctx
.lpSource
= NULL
;
4495 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4496 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4497 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4499 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4503 /***********************************************************************
4504 * RtlCreateActivationContext (NTDLL.@)
4506 * Create an activation context.
4508 * FIXME: function signature/prototype is wrong
4510 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4512 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4513 const WCHAR
*directory
= NULL
;
4514 ACTIVATION_CONTEXT
*actctx
;
4515 UNICODE_STRING nameW
;
4517 NTSTATUS status
= STATUS_NO_MEMORY
;
4519 struct actctx_loader acl
;
4521 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4523 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4524 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4525 return STATUS_INVALID_PARAMETER
;
4527 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4528 return STATUS_NO_MEMORY
;
4530 actctx
->magic
= ACTCTX_MAGIC
;
4531 actctx
->ref_count
= 1;
4532 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4533 actctx
->config
.info
= NULL
;
4534 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4535 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4537 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4545 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4546 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4548 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4549 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4550 actctx
->appdir
.info
= dir
.Buffer
;
4553 nameW
.Buffer
= NULL
;
4555 /* open file only if it's going to be used */
4556 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4557 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4559 WCHAR
*source
= NULL
;
4562 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4563 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
4565 DWORD dir_len
, source_len
;
4567 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4568 source_len
= strlenW(pActCtx
->lpSource
);
4569 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4571 status
= STATUS_NO_MEMORY
;
4575 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4576 source
[dir_len
] = '\\';
4577 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4580 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4581 if (source
) RtlFreeHeap( GetProcessHeap(), 0, source
);
4584 status
= STATUS_NO_SUCH_FILE
;
4587 status
= open_nt_file( &file
, &nameW
);
4590 RtlFreeUnicodeString( &nameW
);
4595 acl
.actctx
= actctx
;
4596 acl
.dependencies
= NULL
;
4597 acl
.num_dependencies
= 0;
4598 acl
.allocated_dependencies
= 0;
4600 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4601 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4603 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4605 /* if we have a resource it's a PE file */
4606 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4608 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4609 pActCtx
->lpResourceName
, lang
);
4610 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4611 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4612 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4614 else if (pActCtx
->lpSource
)
4616 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4617 file
, pActCtx
->lpResourceName
, lang
);
4618 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4619 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4620 NULL
, pActCtx
->lpResourceName
);
4622 else status
= STATUS_INVALID_PARAMETER
;
4626 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4629 if (file
) NtClose( file
);
4630 RtlFreeUnicodeString( &nameW
);
4632 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4633 free_depend_manifests( &acl
);
4635 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4636 else actctx_release( actctx
);
4640 if (file
) NtClose( file
);
4641 actctx_release( actctx
);
4646 /***********************************************************************
4647 * RtlAddRefActivationContext (NTDLL.@)
4649 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4651 ACTIVATION_CONTEXT
*actctx
;
4653 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4657 /******************************************************************
4658 * RtlReleaseActivationContext (NTDLL.@)
4660 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
4662 ACTIVATION_CONTEXT
*actctx
;
4664 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4667 /******************************************************************
4668 * RtlZombifyActivationContext (NTDLL.@)
4670 * FIXME: function prototype might be wrong
4672 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
4674 FIXME("%p: stub\n", handle
);
4675 return STATUS_NOT_IMPLEMENTED
;
4678 /******************************************************************
4679 * RtlActivateActivationContext (NTDLL.@)
4681 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
4683 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4685 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
4686 return STATUS_NO_MEMORY
;
4688 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4689 frame
->ActivationContext
= handle
;
4691 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
4692 RtlAddRefActivationContext( handle
);
4694 *cookie
= (ULONG_PTR
)frame
;
4695 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
4696 return STATUS_SUCCESS
;
4700 /***********************************************************************
4701 * RtlDeactivateActivationContext (NTDLL.@)
4703 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4705 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4707 TRACE( "%x cookie=%lx\n", flags
, cookie
);
4709 /* find the right frame */
4710 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4711 for (frame
= top
; frame
; frame
= frame
->Previous
)
4712 if ((ULONG_PTR
)frame
== cookie
) break;
4715 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4717 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
4718 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4720 /* pop everything up to and including frame */
4721 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
4723 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4725 frame
= top
->Previous
;
4726 RtlReleaseActivationContext( top
->ActivationContext
);
4727 RtlFreeHeap( GetProcessHeap(), 0, top
);
4733 /******************************************************************
4734 * RtlFreeThreadActivationContextStack (NTDLL.@)
4736 void WINAPI
RtlFreeThreadActivationContextStack(void)
4738 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4740 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
4743 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
4744 RtlReleaseActivationContext( frame
->ActivationContext
);
4745 RtlFreeHeap( GetProcessHeap(), 0, frame
);
4748 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
4752 /******************************************************************
4753 * RtlGetActiveActivationContext (NTDLL.@)
4755 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
4757 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
4759 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
4760 RtlAddRefActivationContext( *handle
);
4765 return STATUS_SUCCESS
;
4769 /******************************************************************
4770 * RtlIsActivationContextActive (NTDLL.@)
4772 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
4774 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4776 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
4777 if (frame
->ActivationContext
== handle
) return TRUE
;
4782 /***********************************************************************
4783 * RtlQueryInformationActivationContext (NTDLL.@)
4785 * Get information about an activation context.
4786 * FIXME: function signature/prototype may be wrong
4788 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
4789 ULONG
class, PVOID buffer
,
4790 SIZE_T bufsize
, SIZE_T
*retlen
)
4792 ACTIVATION_CONTEXT
*actctx
;
4795 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
4796 subinst
, class, buffer
, bufsize
, retlen
);
4798 if (retlen
) *retlen
= 0;
4799 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
4803 case ActivationContextBasicInformation
:
4805 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
4807 if (retlen
) *retlen
= sizeof(*info
);
4808 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
4810 info
->hActCtx
= handle
;
4811 info
->dwFlags
= 0; /* FIXME */
4812 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
4816 case ActivationContextDetailedInformation
:
4818 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
4819 struct assembly
*assembly
= NULL
;
4820 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
4823 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4825 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
4827 if (assembly
&& assembly
->manifest
.info
)
4828 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
4829 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
4830 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
4831 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
4833 if (retlen
) *retlen
= len
;
4834 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
4837 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
4838 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
4839 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
4840 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
4841 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
4842 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
4843 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
4844 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
4845 ptr
= (LPWSTR
)(acdi
+ 1);
4848 acdi
->lpRootManifestPath
= ptr
;
4849 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
4850 ptr
+= manifest_len
;
4852 else acdi
->lpRootManifestPath
= NULL
;
4855 acdi
->lpRootConfigurationPath
= ptr
;
4856 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
4859 else acdi
->lpRootConfigurationPath
= NULL
;
4862 acdi
->lpAppDirPath
= ptr
;
4863 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
4865 else acdi
->lpAppDirPath
= NULL
;
4869 case AssemblyDetailedInformationInActivationContext
:
4871 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
4872 struct assembly
*assembly
;
4875 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
4878 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4879 if (!subinst
) return STATUS_INVALID_PARAMETER
;
4881 index
= *(DWORD
*)subinst
;
4882 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
4884 assembly
= &actctx
->assemblies
[index
- 1];
4886 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
4887 id_len
= strlenW(assembly_id
) + 1;
4888 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
4890 if (assembly
->manifest
.info
&&
4891 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
4892 path_len
= strlenW(assembly
->manifest
.info
) + 1;
4894 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
4896 if (retlen
) *retlen
= len
;
4897 if (!buffer
|| bufsize
< len
)
4899 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4900 return STATUS_BUFFER_TOO_SMALL
;
4903 afdi
->ulFlags
= 0; /* FIXME */
4904 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
4905 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
4906 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
4907 /* FIXME afdi->liManifestLastWriteTime = 0; */
4908 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
4909 afdi
->ulPolicyPathLength
= 0;
4910 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4911 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
4912 afdi
->ulManifestVersionMajor
= 1;
4913 afdi
->ulManifestVersionMinor
= 0;
4914 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
4915 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
4916 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
4917 ptr
= (LPWSTR
)(afdi
+ 1);
4918 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
4919 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
4923 afdi
->lpAssemblyManifestPath
= ptr
;
4924 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
4926 } else afdi
->lpAssemblyManifestPath
= NULL
;
4927 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
4930 afdi
->lpAssemblyDirectoryName
= ptr
;
4931 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
4933 else afdi
->lpAssemblyDirectoryName
= NULL
;
4934 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
4938 case FileInformationInAssemblyOfAssemblyInActivationContext
:
4940 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
4941 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
4942 struct assembly
*assembly
;
4943 struct dll_redirect
*dll
;
4944 SIZE_T len
, dll_len
= 0;
4947 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
4948 if (!acqi
) return STATUS_INVALID_PARAMETER
;
4950 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
4951 return STATUS_INVALID_PARAMETER
;
4952 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
4954 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
4955 return STATUS_INVALID_PARAMETER
;
4956 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
4958 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
4959 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
4961 if (!buffer
|| bufsize
< len
)
4963 if (retlen
) *retlen
= len
;
4964 return STATUS_BUFFER_TOO_SMALL
;
4966 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
4967 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
4968 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
4969 afdi
->ulPathLength
= 0; /* FIXME */
4970 ptr
= (LPWSTR
)(afdi
+ 1);
4973 afdi
->lpFileName
= ptr
;
4974 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
4975 } else afdi
->lpFileName
= NULL
;
4976 afdi
->lpFilePath
= NULL
; /* FIXME */
4981 FIXME( "class %u not implemented\n", class );
4982 return STATUS_NOT_IMPLEMENTED
;
4984 return STATUS_SUCCESS
;
4987 /***********************************************************************
4988 * RtlFindActivationContextSectionString (NTDLL.@)
4990 * Find information about a string in an activation context.
4991 * FIXME: function signature/prototype may be wrong
4993 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
4994 const UNICODE_STRING
*section_name
, PVOID ptr
)
4996 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
4997 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
4999 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5000 debugstr_us(section_name
), data
);
5004 FIXME("expected guid == NULL\n");
5005 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
;
5012 if (!data
|| data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) ||
5013 !section_name
|| !section_name
->Buffer
)
5015 WARN("invalid parameter\n");
5016 return STATUS_INVALID_PARAMETER
;
5019 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5021 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5022 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5025 if (status
!= STATUS_SUCCESS
)
5026 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5031 /***********************************************************************
5032 * RtlFindActivationContextSectionGuid (NTDLL.@)
5034 * Find information about a GUID in an activation context.
5035 * FIXME: function signature/prototype may be wrong
5037 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5038 const GUID
*guid
, void *ptr
)
5040 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5041 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5043 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5047 FIXME("expected extguid == NULL\n");
5048 return STATUS_INVALID_PARAMETER
;
5051 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5053 FIXME("unknown flags %08x\n", flags
);
5054 return STATUS_INVALID_PARAMETER
;
5057 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5058 return STATUS_INVALID_PARAMETER
;
5060 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5062 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5063 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5066 if (status
!= STATUS_SUCCESS
)
5067 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);