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
30 #define WIN32_NO_STATUS
31 #define NONAMELESSUNION
34 #include "ntdll_misc.h"
35 #include "wine/exception.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
40 #define ACTCTX_FLAGS_ALL (\
41 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
42 ACTCTX_FLAG_LANGID_VALID |\
43 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
44 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
45 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
46 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
47 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
48 ACTCTX_FLAG_HMODULE_VALID )
50 #define ACTCTX_MAGIC 0xC07E3E11
51 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
52 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
54 /* we don't want to include winuser.h */
55 #define RT_MANIFEST ((ULONG_PTR)24)
56 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
59 typedef enum tagLIBFLAGS
{
60 LIBFLAG_FRESTRICTED
= 0x1,
61 LIBFLAG_FCONTROL
= 0x2,
62 LIBFLAG_FHIDDEN
= 0x4,
63 LIBFLAG_FHASDISKIMAGE
= 0x8
67 typedef enum tagOLEMISC
69 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
70 OLEMISC_ONLYICONIC
= 0x2,
71 OLEMISC_INSERTNOTREPLACE
= 0x4,
73 OLEMISC_CANTLINKINSIDE
= 0x10,
74 OLEMISC_CANLINKBYOLE1
= 0x20,
75 OLEMISC_ISLINKOBJECT
= 0x40,
76 OLEMISC_INSIDEOUT
= 0x80,
77 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
78 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
79 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
80 OLEMISC_ALWAYSRUN
= 0x800,
81 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
82 OLEMISC_ACTSLIKELABEL
= 0x2000,
83 OLEMISC_NOUIACTIVATE
= 0x4000,
84 OLEMISC_ALIGNABLE
= 0x8000,
85 OLEMISC_SIMPLEFRAME
= 0x10000,
86 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
87 OLEMISC_IMEMODE
= 0x40000,
88 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
89 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
90 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
93 #define MAX_NAMESPACES 64
118 struct xml_attr namespaces
[MAX_NAMESPACES
];
129 struct assembly_version
137 struct assembly_identity
144 struct assembly_version version
;
149 struct strsection_header
163 ULONG hash
; /* key string hash */
166 ULONG data_offset
; /* redirect data offset */
171 struct guidsection_header
191 struct wndclass_redirect_data
196 ULONG name_offset
; /* versioned name offset */
198 ULONG module_offset
;/* container name offset */
201 struct tlibredirect_data
215 enum comclass_threadingmodel
217 ThreadingModel_Apartment
= 1,
218 ThreadingModel_Free
= 2,
219 ThreadingModel_No
= 3,
220 ThreadingModel_Both
= 4,
221 ThreadingModel_Neutral
= 5
224 enum comclass_miscfields
228 MiscStatusContent
= 4,
229 MiscStatusThumbnail
= 8,
230 MiscStatusDocPrint
= 16
233 struct comclassredirect_data
247 ULONG clrdata_offset
;
249 DWORD miscstatuscontent
;
250 DWORD miscstatusthumbnail
;
251 DWORD miscstatusicon
;
252 DWORD miscstatusdocprint
;
261 struct ifacepsredirect_data
273 struct clrsurrogate_data
278 ULONG version_offset
;
293 ULONG version_offset
;
297 struct progidredirect_data
304 struct activatable_class_data
310 DWORD threading_model
;
317 Sections are accessible by string or guid key, that defines two types of sections.
318 All sections of each type have same magic value and header structure, index
319 data could be of two possible types too. So every string based section uses
320 the same index format, same applies to guid sections - they share same guid index
323 - window class redirection section is a plain buffer with following format:
327 <data[]> --- <original name>
332 Header is fixed length structure - struct strsection_header,
333 contains redirected classes count;
335 Index is an array of fixed length index records, each record is
338 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
340 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
341 others are relative to section itself.
343 - dll redirect section format:
347 <data[]> --- <dll name>
350 This section doesn't seem to carry any payload data except dll names.
352 - typelib section format:
360 Header is fixed length, index is an array of fixed length 'struct guid_index'.
361 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
362 4-bytes aligned as a whole.
364 Module name offsets are relative to section, helpstring offset is relative to data
367 - comclass section format:
372 <data[]> --- <data> --- <data>
378 This section uses two index records per comclass, one entry contains original guid
379 as specified by context, another one has a generated guid. Index and strings handling
380 is similar to typelib sections.
382 For CLR classes additional data is stored after main COM class data, it contains
383 class name and runtime version string, see 'struct clrclass_data'.
385 Module name offsets are relative to section, progid offset is relative to data
388 - COM interface section format:
395 Interface section contains data for proxy/stubs and external proxy/stubs. External
396 ones are defined at assembly level, so this section has no module information.
397 All records are indexed with 'iid' value from manifest. There an exception for
398 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
399 redirect data, but index is still 'iid' from manifest.
401 Interface name offset is relative to data structure itself.
403 - CLR surrogates section format:
411 There's nothing special about this section, same way to store strings is used,
412 no modules part as it belongs to assembly level, not a file.
414 - ProgID section format:
419 <data[]> --- <progid>
422 This sections uses generated alias guids from COM server section. This way
423 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
424 is stored too, aligned.
426 - WinRT activatable class section is a plain buffer with following format:
431 <data[]> --- <class name>
434 Header is fixed length structure - struct strsection_header,
435 contains classes count;
437 Index is an array of fixed length index records, each record is
440 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
442 All offsets are relative to section itself.
450 unsigned int allocated
;
471 WCHAR
*name
; /* clrClass: class name */
472 WCHAR
*version
; /* clrClass: CLR runtime version */
475 DWORD miscstatuscontent
;
476 DWORD miscstatusthumbnail
;
477 DWORD miscstatusicon
;
478 DWORD miscstatusdocprint
;
479 struct progids progids
;
486 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
510 DWORD threading_model
;
519 unsigned int allocated
;
527 struct entity_array entities
;
532 APPLICATION_MANIFEST
,
534 ASSEMBLY_SHARED_MANIFEST
,
539 enum assembly_type type
;
540 struct assembly_identity id
;
541 struct file_info manifest
;
544 struct dll_redirect
*dlls
;
545 unsigned int num_dlls
;
546 unsigned int allocated_dlls
;
547 struct entity_array entities
;
548 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
549 ULONG num_compat_contexts
;
550 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
554 enum context_sections
556 WINDOWCLASS_SECTION
= 1,
557 DLLREDIRECT_SECTION
= 2,
558 TLIBREDIRECT_SECTION
= 4,
559 SERVERREDIRECT_SECTION
= 8,
560 IFACEREDIRECT_SECTION
= 16,
561 CLRSURROGATES_SECTION
= 32,
562 PROGIDREDIRECT_SECTION
= 64,
563 ACTIVATABLE_CLASS_SECTION
= 128,
566 typedef struct _ACTIVATION_CONTEXT
570 struct file_info config
;
571 struct file_info appdir
;
572 struct assembly
*assemblies
;
573 unsigned int num_assemblies
;
574 unsigned int allocated_assemblies
;
577 struct strsection_header
*wndclass_section
;
578 struct strsection_header
*dllredirect_section
;
579 struct strsection_header
*progid_section
;
580 struct strsection_header
*activatable_class_section
;
581 struct guidsection_header
*tlib_section
;
582 struct guidsection_header
*comserver_section
;
583 struct guidsection_header
*ifaceps_section
;
584 struct guidsection_header
*clrsurrogate_section
;
585 } ACTIVATION_CONTEXT
;
589 ACTIVATION_CONTEXT
*actctx
;
590 struct assembly_identity
*dependencies
;
591 unsigned int num_dependencies
;
592 unsigned int allocated_dependencies
;
595 static const xmlstr_t empty_xmlstr
;
598 static const WCHAR current_archW
[] = L
"x86";
599 #elif defined __x86_64__
600 static const WCHAR current_archW
[] = L
"amd64";
601 #elif defined __arm__
602 static const WCHAR current_archW
[] = L
"arm";
603 #elif defined __aarch64__
604 static const WCHAR current_archW
[] = L
"arm64";
606 static const WCHAR current_archW
[] = L
"none";
609 static const WCHAR asmv1W
[] = L
"urn:schemas-microsoft-com:asm.v1";
610 static const WCHAR asmv2W
[] = L
"urn:schemas-microsoft-com:asm.v2";
611 static const WCHAR asmv3W
[] = L
"urn:schemas-microsoft-com:asm.v3";
612 static const WCHAR winrtv1W
[] = L
"urn:schemas-microsoft-com:winrt.v1";
613 static const WCHAR compatibilityNSW
[] = L
"urn:schemas-microsoft-com:compatibility.v1";
614 static const WCHAR windowsSettings2005NSW
[] = L
"http://schemas.microsoft.com/SMI/2005/WindowsSettings";
615 static const WCHAR windowsSettings2011NSW
[] = L
"http://schemas.microsoft.com/SMI/2011/WindowsSettings";
616 static const WCHAR windowsSettings2016NSW
[] = L
"http://schemas.microsoft.com/SMI/2016/WindowsSettings";
617 static const WCHAR windowsSettings2017NSW
[] = L
"http://schemas.microsoft.com/SMI/2017/WindowsSettings";
618 static const WCHAR windowsSettings2019NSW
[] = L
"http://schemas.microsoft.com/SMI/2019/WindowsSettings";
619 static const WCHAR windowsSettings2020NSW
[] = L
"http://schemas.microsoft.com/SMI/2020/WindowsSettings";
627 static const struct olemisc_entry olemisc_values
[] =
629 { L
"activatewhenvisible", OLEMISC_ACTIVATEWHENVISIBLE
},
630 { L
"actslikebutton", OLEMISC_ACTSLIKEBUTTON
},
631 { L
"actslikelabel", OLEMISC_ACTSLIKELABEL
},
632 { L
"alignable", OLEMISC_ALIGNABLE
},
633 { L
"alwaysrun", OLEMISC_ALWAYSRUN
},
634 { L
"canlinkbyole1", OLEMISC_CANLINKBYOLE1
},
635 { L
"cantlinkinside", OLEMISC_CANTLINKINSIDE
},
636 { L
"ignoreactivatewhenvisible", OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
637 { L
"imemode", OLEMISC_IMEMODE
},
638 { L
"insertnotreplace", OLEMISC_INSERTNOTREPLACE
},
639 { L
"insideout", OLEMISC_INSIDEOUT
},
640 { L
"invisibleatruntime", OLEMISC_INVISIBLEATRUNTIME
},
641 { L
"islinkobject", OLEMISC_ISLINKOBJECT
},
642 { L
"nouiactivate", OLEMISC_NOUIACTIVATE
},
643 { L
"onlyiconic", OLEMISC_ONLYICONIC
},
644 { L
"recomposeonresize", OLEMISC_RECOMPOSEONRESIZE
},
645 { L
"renderingisdeviceindependent", OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
646 { L
"setclientsitefirst", OLEMISC_SETCLIENTSITEFIRST
},
647 { L
"simpleframe", OLEMISC_SIMPLEFRAME
},
648 { L
"static", OLEMISC_STATIC
},
649 { L
"supportsmultilevelundo", OLEMISC_SUPPORTSMULTILEVELUNDO
},
650 { L
"wantstomenumerge", OLEMISC_WANTSTOMENUMERGE
}
653 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
654 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
656 static WCHAR
*strdupW(const WCHAR
* str
)
660 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str
) + 1) * sizeof(WCHAR
))))
662 return wcscpy(ptr
, str
);
665 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
669 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
671 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
677 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
679 return !wcsncmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
682 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
684 return !wcsnicmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
687 static BOOL
xml_attr_cmp( const struct xml_attr
*attr
, const WCHAR
*str
)
689 return xmlstr_cmp( &attr
->name
, str
);
692 static BOOL
xml_name_cmp( const struct xml_elem
*elem1
, const struct xml_elem
*elem2
)
694 return (elem1
->name
.len
== elem2
->name
.len
&&
695 elem1
->ns
.len
== elem2
->ns
.len
&&
696 !wcsncmp( elem1
->name
.ptr
, elem2
->name
.ptr
, elem1
->name
.len
) &&
697 !wcsncmp( elem1
->ns
.ptr
, elem2
->ns
.ptr
, elem1
->ns
.len
));
700 static inline BOOL
xml_elem_cmp(const struct xml_elem
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
702 if (!xmlstr_cmp( &elem
->name
, str
)) return FALSE
;
703 if (xmlstr_cmp( &elem
->ns
, namespace )) return TRUE
;
704 if (!wcscmp( namespace, asmv1W
))
706 if (xmlstr_cmp( &elem
->ns
, asmv2W
)) return TRUE
;
707 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
709 else if (!wcscmp( namespace, asmv2W
))
711 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
716 static inline BOOL
isxmlspace( WCHAR ch
)
718 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
721 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
723 return debugstr_wn(str
->ptr
, str
->len
);
726 static inline const char *debugstr_xml_elem( const struct xml_elem
*elem
)
728 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem
->name
.ptr
, elem
->name
.len
),
729 debugstr_wn( elem
->ns
.ptr
, elem
->ns
.len
));
732 static inline const char *debugstr_xml_attr( const struct xml_attr
*attr
)
734 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr
->name
.ptr
, attr
->name
.len
),
735 debugstr_wn( attr
->value
.ptr
, attr
->value
.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 NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
747 LDR_DATA_TABLE_ENTRY
*pldr
;
749 LdrLockLoaderLock(0, NULL
, &magic
);
750 status
= LdrFindEntryForAddress( module
, &pldr
);
751 if (status
== STATUS_SUCCESS
)
753 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
754 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
756 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
757 str
->Length
= pldr
->FullDllName
.Length
;
758 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
760 else status
= STATUS_NO_MEMORY
;
762 LdrUnlockLoaderLock(0, magic
);
766 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
768 struct assembly
*assembly
;
770 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
773 unsigned int new_count
;
774 if (actctx
->assemblies
)
776 new_count
= actctx
->allocated_assemblies
* 2;
777 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
778 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
783 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
785 if (!ptr
) return NULL
;
786 actctx
->assemblies
= ptr
;
787 actctx
->allocated_assemblies
= new_count
;
790 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
795 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
797 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
800 unsigned int new_count
;
803 new_count
= assembly
->allocated_dlls
* 2;
804 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
805 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
810 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
812 if (!ptr
) return NULL
;
813 assembly
->dlls
= ptr
;
814 assembly
->allocated_dlls
= new_count
;
816 return &assembly
->dlls
[assembly
->num_dlls
++];
819 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
822 if (assembly
->num_compat_contexts
)
824 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
825 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
826 assembly
->compat_contexts
,
827 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
831 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
833 if (!ptr
) return NULL
;
834 assembly
->compat_contexts
= ptr
;
835 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
838 static void free_assembly_identity(struct assembly_identity
*ai
)
840 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
841 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
842 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
843 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
844 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
847 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
849 struct entity
* entity
;
851 if (array
->num
== array
->allocated
)
854 unsigned int new_count
;
857 new_count
= array
->allocated
* 2;
858 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
859 array
->base
, new_count
* sizeof(*array
->base
) );
864 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
866 if (!ptr
) return NULL
;
868 array
->allocated
= new_count
;
870 entity
= &array
->base
[array
->num
++];
875 static void free_entity_array(struct entity_array
*array
)
878 for (i
= 0; i
< array
->num
; i
++)
880 struct entity
*entity
= &array
->base
[i
];
881 switch (entity
->kind
)
883 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
884 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
885 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
886 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
887 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
888 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
889 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
890 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
891 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
893 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
894 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
895 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
896 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
897 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
898 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
900 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
901 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
902 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
904 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
905 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
907 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
908 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
909 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
910 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
912 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
:
913 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.name
);
914 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.value
);
915 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.ns
);
917 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
:
918 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.activatable_class
.name
);
921 FIXME("Unknown entity kind %ld\n", entity
->kind
);
924 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
927 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
929 if (!str1
) return !str2
;
930 return str2
&& !RtlCompareUnicodeStrings( str1
, wcslen(str1
), str2
, wcslen(str2
), TRUE
);
933 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
934 const struct assembly_identity
*id2
)
936 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
937 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
938 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
940 if (id1
->language
&& id2
->language
&& !is_matching_string( id1
->language
, id2
->language
))
942 if (wcscmp( L
"*", id1
->language
) && wcscmp( L
"*", id2
->language
))
945 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
946 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
947 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
948 if (id1
->version
.build
== id2
->version
.build
&&
949 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
953 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
954 struct assembly_identity
* ai
)
958 /* check if we already have that assembly */
960 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
961 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
963 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
964 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
965 ai
->version
.build
, ai
->version
.revision
);
969 for (i
= 0; i
< acl
->num_dependencies
; i
++)
970 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
972 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
973 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
974 ai
->version
.build
, ai
->version
.revision
);
978 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
981 unsigned int new_count
;
982 if (acl
->dependencies
)
984 new_count
= acl
->allocated_dependencies
* 2;
985 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
986 new_count
* sizeof(acl
->dependencies
[0]));
991 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
993 if (!ptr
) return FALSE
;
994 acl
->dependencies
= ptr
;
995 acl
->allocated_dependencies
= new_count
;
997 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
1002 static void free_depend_manifests(struct actctx_loader
* acl
)
1005 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1006 free_assembly_identity(&acl
->dependencies
[i
]);
1007 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
1010 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
1012 static const WCHAR mskeyW
[] = L
"deadbeef";
1013 const WCHAR
*arch
= ai
->arch
? ai
->arch
: L
"none";
1014 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: L
"none";
1015 const WCHAR
*lang
= ai
->language
? ai
->language
: L
"none";
1016 const WCHAR
*name
= ai
->name
? ai
->name
: L
"none";
1017 SIZE_T size
= (wcslen(arch
) + 1 + wcslen(name
) + 1 + wcslen(key
) + 24 + 1 +
1018 wcslen(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1021 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
1023 wcscpy( ret
, arch
);
1024 wcscat( ret
, L
"_" );
1025 wcscat( ret
, name
);
1026 wcscat( ret
, L
"_" );
1028 wcscat( ret
, L
"_" );
1029 swprintf( ret
+ wcslen(ret
), size
- wcslen(ret
), L
"%u.%u.%u.%u",
1030 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1031 wcscat( ret
, L
"_" );
1032 wcscat( ret
, lang
);
1033 wcscat( ret
, L
"_" );
1034 wcscat( ret
, mskeyW
);
1038 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1043 wcscat( buffer
, prefix
);
1052 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1054 WCHAR version
[64], *ret
;
1057 swprintf( version
, ARRAY_SIZE(version
), L
"%u.%u.%u.%u",
1058 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1059 if (ai
->name
) size
+= wcslen(ai
->name
) * sizeof(WCHAR
);
1060 if (ai
->arch
) size
+= wcslen(L
",processorArchitecture=") + wcslen(ai
->arch
) + 2;
1061 if (ai
->public_key
) size
+= wcslen(L
",publicKeyToken=") + wcslen(ai
->public_key
) + 2;
1062 if (ai
->type
) size
+= wcslen(L
",type=") + wcslen(ai
->type
) + 2;
1063 size
+= wcslen(L
",version=") + wcslen(version
) + 2;
1065 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1068 if (ai
->name
) wcscpy( ret
, ai
->name
);
1070 append_string( ret
, L
",processorArchitecture=", ai
->arch
);
1071 append_string( ret
, L
",publicKeyToken=", ai
->public_key
);
1072 append_string( ret
, L
",type=", ai
->type
);
1073 append_string( ret
, L
",version=", version
);
1077 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1079 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1081 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1084 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1093 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1095 InterlockedIncrement( &actctx
->ref_count
);
1098 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1100 if (!InterlockedDecrement( &actctx
->ref_count
))
1104 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1106 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1107 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1109 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1110 free_entity_array( &dll
->entities
);
1111 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1112 RtlFreeHeap( GetProcessHeap(), 0, dll
->load_from
);
1113 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1115 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1116 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1117 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1118 RtlFreeHeap( GetProcessHeap(), 0, assembly
->compat_contexts
);
1119 free_entity_array( &assembly
->entities
);
1120 free_assembly_identity(&assembly
->id
);
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1125 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1127 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1128 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1129 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1130 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1131 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1132 RtlFreeHeap( GetProcessHeap(), 0, actctx
->activatable_class_section
);
1134 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1138 static BOOL
set_error( xmlbuf_t
*xmlbuf
)
1140 xmlbuf
->error
= TRUE
;
1144 static BOOL
is_xmlns_attr( const struct xml_attr
*attr
)
1146 const int len
= wcslen( L
"xmlns" );
1147 if (attr
->name
.len
< len
) return FALSE
;
1148 if (wcsncmp( attr
->name
.ptr
, L
"xmlns", len
)) return FALSE
;
1149 return (attr
->name
.len
== len
|| attr
->name
.ptr
[len
] == ':');
1152 static void push_xmlns( xmlbuf_t
*xmlbuf
, const struct xml_attr
*attr
)
1154 const int len
= wcslen( L
"xmlns" );
1155 struct xml_attr
*ns
;
1157 if (xmlbuf
->ns_pos
== MAX_NAMESPACES
- 1)
1159 FIXME( "too many namespaces in manifest\n" );
1160 set_error( xmlbuf
);
1163 ns
= &xmlbuf
->namespaces
[xmlbuf
->ns_pos
++];
1164 ns
->value
= attr
->value
;
1165 if (attr
->name
.len
> len
)
1167 ns
->name
.ptr
= attr
->name
.ptr
+ len
+ 1;
1168 ns
->name
.len
= attr
->name
.len
- len
- 1;
1170 else ns
->name
= empty_xmlstr
;
1173 static xmlstr_t
find_xmlns( xmlbuf_t
*xmlbuf
, const xmlstr_t
*name
)
1177 for (i
= xmlbuf
->ns_pos
- 1; i
>= 0; i
--)
1179 if (xmlbuf
->namespaces
[i
].name
.len
== name
->len
&&
1180 !wcsncmp( xmlbuf
->namespaces
[i
].name
.ptr
, name
->ptr
, name
->len
))
1181 return xmlbuf
->namespaces
[i
].value
;
1183 if (xmlbuf
->ns_pos
) WARN( "namespace %s not found\n", debugstr_xmlstr( name
));
1184 return empty_xmlstr
;
1187 static BOOL
next_xml_attr(xmlbuf_t
*xmlbuf
, struct xml_attr
*attr
, BOOL
*end
)
1192 if (xmlbuf
->error
) return FALSE
;
1194 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1197 if (xmlbuf
->ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1199 if (*xmlbuf
->ptr
== '/')
1202 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1203 return set_error( xmlbuf
);
1210 if (*xmlbuf
->ptr
== '>')
1217 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1219 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1221 attr
->name
.ptr
= xmlbuf
->ptr
;
1222 attr
->name
.len
= ptr
-xmlbuf
->ptr
;
1225 /* skip spaces before '=' */
1226 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1227 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return set_error( xmlbuf
);
1229 /* skip '=' itself */
1231 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1233 /* skip spaces after '=' */
1234 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1236 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return set_error( xmlbuf
);
1239 attr
->value
.ptr
= ptr
;
1240 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1242 while (ptr
< xmlbuf
->end
&& *ptr
!= quote
) ptr
++;
1243 if (ptr
== xmlbuf
->end
)
1245 xmlbuf
->ptr
= xmlbuf
->end
;
1246 return set_error( xmlbuf
);
1249 attr
->value
.len
= ptr
- attr
->value
.ptr
;
1250 xmlbuf
->ptr
= ptr
+ 1;
1251 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1253 return set_error( xmlbuf
);
1256 static void read_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
)
1258 const WCHAR
* ptr
= xmlbuf
->ptr
;
1260 elem
->ns
= empty_xmlstr
;
1261 elem
->name
.ptr
= ptr
;
1262 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && *ptr
!= '/')
1266 elem
->ns
.ptr
= elem
->name
.ptr
;
1267 elem
->ns
.len
= ptr
- elem
->ns
.ptr
;
1268 elem
->name
.ptr
= ptr
+ 1;
1272 elem
->name
.len
= ptr
- elem
->name
.ptr
;
1276 static BOOL
next_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
, const struct xml_elem
*parent
)
1279 struct xml_attr attr
;
1283 xmlbuf
->ns_pos
= parent
->ns_pos
; /* restore namespace stack to parent state */
1285 if (xmlbuf
->error
) return FALSE
;
1289 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1290 if (ptr
== xmlbuf
->end
)
1292 xmlbuf
->ptr
= xmlbuf
->end
;
1293 return set_error( xmlbuf
);
1296 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1298 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1299 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1301 if (ptr
+ 3 > xmlbuf
->end
)
1303 xmlbuf
->ptr
= xmlbuf
->end
;
1304 return set_error( xmlbuf
);
1306 xmlbuf
->ptr
= ptr
+ 3;
1312 /* check for element terminating the parent element */
1313 if (ptr
< xmlbuf
->end
&& *ptr
== '/')
1316 read_xml_elem( xmlbuf
, elem
);
1317 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1318 if (!xml_name_cmp( elem
, parent
))
1320 ERR( "wrong closing element %s for %s\n",
1321 debugstr_xmlstr(&elem
->name
), debugstr_xmlstr(&parent
->name
));
1322 return set_error( xmlbuf
);
1324 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
)) xmlbuf
->ptr
++;
1325 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
++ != '>') return set_error( xmlbuf
);
1329 read_xml_elem( xmlbuf
, elem
);
1331 /* parse namespace attributes */
1333 while (next_xml_attr( &attr_buf
, &attr
, &end
))
1335 if (is_xmlns_attr( &attr
)) push_xmlns( xmlbuf
, &attr
);
1337 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1338 elem
->ns_pos
= xmlbuf
->ns_pos
;
1340 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1342 return set_error( xmlbuf
);
1345 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1347 /* FIXME: parse attributes */
1350 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1352 if (ptr
[0] == '?' && ptr
[1] == '>')
1354 xmlbuf
->ptr
= ptr
+ 2;
1361 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1365 if (xmlbuf
->error
) return FALSE
;
1367 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1368 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1370 content
->ptr
= xmlbuf
->ptr
;
1371 content
->len
= ptr
- xmlbuf
->ptr
;
1377 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1379 unsigned int ver
[4];
1383 /* major.minor.build.revision */
1384 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1385 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1387 if (*curr
>= '0' && *curr
<= '9')
1389 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1390 if (ver
[pos
] >= 0x10000) goto error
;
1392 else if (*curr
== '.')
1394 if (++pos
>= 4) goto error
;
1398 version
->major
= ver
[0];
1399 version
->minor
= ver
[1];
1400 version
->build
= ver
[2];
1401 version
->revision
= ver
[3];
1405 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1409 static void parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1411 struct xml_attr attr
;
1413 while (next_xml_attr(xmlbuf
, &attr
, end
))
1415 if (!is_xmlns_attr( &attr
)) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr
));
1419 static void parse_expect_end_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1421 struct xml_elem elem
;
1423 if (next_xml_elem(xmlbuf
, &elem
, parent
))
1425 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem
) );
1426 set_error( xmlbuf
);
1430 static void parse_unknown_elem(xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1432 struct xml_elem elem
;
1433 struct xml_attr attr
;
1436 while (next_xml_attr(xmlbuf
, &attr
, &end
));
1439 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1440 parse_unknown_elem(xmlbuf
, &elem
);
1443 static void parse_assembly_identity_elem(xmlbuf_t
*xmlbuf
, ACTIVATION_CONTEXT
*actctx
,
1444 struct assembly_identity
* ai
, const struct xml_elem
*parent
)
1446 struct xml_attr attr
;
1449 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1451 if (xml_attr_cmp(&attr
, L
"name"))
1453 if (!(ai
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1455 else if (xml_attr_cmp(&attr
, L
"type"))
1457 if (!(ai
->type
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1459 else if (xml_attr_cmp(&attr
, L
"version"))
1461 if (!parse_version(&attr
.value
, &ai
->version
)) set_error( xmlbuf
);
1463 else if (xml_attr_cmp(&attr
, L
"processorArchitecture"))
1465 if (!(ai
->arch
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1467 else if (xml_attr_cmp(&attr
, L
"publicKeyToken"))
1469 if (!(ai
->public_key
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1471 else if (xml_attr_cmp(&attr
, L
"language"))
1473 if (!(ai
->language
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1475 else if (!is_xmlns_attr( &attr
))
1477 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1481 TRACE( "name=%s version=%s arch=%s\n",
1482 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1484 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1487 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1489 if (value
->len
== 0) return ThreadingModel_No
;
1490 if (xmlstr_cmp(value
, L
"Apartment"))
1491 return ThreadingModel_Apartment
;
1492 else if (xmlstr_cmp(value
, L
"Free"))
1493 return ThreadingModel_Free
;
1494 else if (xmlstr_cmp(value
, L
"Both"))
1495 return ThreadingModel_Both
;
1496 else if (xmlstr_cmp(value
, L
"Neutral"))
1497 return ThreadingModel_Neutral
;
1499 return ThreadingModel_No
;
1502 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1507 max
= ARRAY_SIZE(olemisc_values
) - 1;
1515 c
= wcsncmp(olemisc_values
[n
].name
, str
, len
);
1516 if (!c
&& !olemisc_values
[n
].name
[len
])
1517 return olemisc_values
[n
].value
;
1525 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1529 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1531 const WCHAR
*str
= value
->ptr
, *start
;
1535 /* it's comma separated list of flags */
1536 while (i
< value
->len
)
1539 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1541 flags
|= get_olemisc_value(start
, str
-start
);
1543 /* skip separator */
1551 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1553 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1555 if (progids
->allocated
== 0)
1557 progids
->allocated
= 4;
1558 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1561 if (progids
->allocated
== progids
->num
)
1563 WCHAR
**new_progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
,
1564 2 * progids
->allocated
* sizeof(WCHAR
*));
1565 if (!new_progids
) return FALSE
;
1566 progids
->allocated
*= 2;
1567 progids
->progids
= new_progids
;
1570 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1576 static void parse_com_class_progid(xmlbuf_t
*xmlbuf
, struct entity
*entity
, const struct xml_elem
*parent
)
1581 parse_expect_no_attr(xmlbuf
, &end
);
1582 if (end
) set_error( xmlbuf
);
1583 if (!parse_text_content(xmlbuf
, &content
)) return;
1585 if (!com_class_add_progid(&content
, entity
)) set_error( xmlbuf
);
1586 parse_expect_end_elem(xmlbuf
, parent
);
1589 static void parse_com_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
, struct actctx_loader
*acl
,
1590 const struct xml_elem
*parent
)
1592 struct xml_elem elem
;
1593 struct xml_attr attr
;
1595 struct entity
* entity
;
1597 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1599 set_error( xmlbuf
);
1603 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1605 if (xml_attr_cmp(&attr
, L
"clsid"))
1607 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1609 else if (xml_attr_cmp(&attr
, L
"progid"))
1611 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1613 else if (xml_attr_cmp(&attr
, L
"tlbid"))
1615 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1617 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
1619 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
1621 else if (xml_attr_cmp(&attr
, L
"miscStatus"))
1623 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr
.value
);
1625 else if (xml_attr_cmp(&attr
, L
"miscStatusContent"))
1627 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr
.value
);
1629 else if (xml_attr_cmp(&attr
, L
"miscStatusThumbnail"))
1631 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr
.value
);
1633 else if (xml_attr_cmp(&attr
, L
"miscStatusIcon"))
1635 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr
.value
);
1637 else if (xml_attr_cmp(&attr
, L
"miscStatusDocPrint"))
1639 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr
.value
);
1641 else if (xml_attr_cmp(&attr
, L
"description"))
1645 else if (!is_xmlns_attr( &attr
))
1647 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1651 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1652 if (entity
->u
.comclass
.progid
)
1653 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1657 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1659 if (xml_elem_cmp(&elem
, L
"progid", asmv1W
))
1661 parse_com_class_progid(xmlbuf
, entity
, &elem
);
1665 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1666 parse_unknown_elem(xmlbuf
, &elem
);
1670 if (entity
->u
.comclass
.progids
.num
)
1671 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1674 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1679 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1681 if (*curr
>= '0' && *curr
<= '9')
1682 num
= num
* 10 + *curr
- '0';
1685 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1689 entity
->u
.ifaceps
.nummethods
= num
;
1694 static void parse_add_interface_class( xmlbuf_t
*xmlbuf
, struct entity_array
*entities
,
1695 struct actctx_loader
*acl
, WCHAR
*clsid
)
1697 struct entity
*entity
;
1702 if (!(str
= strdupW(clsid
)))
1704 set_error( xmlbuf
);
1708 if (!(entity
= add_entity(entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1710 RtlFreeHeap(GetProcessHeap(), 0, str
);
1711 set_error( xmlbuf
);
1715 entity
->u
.comclass
.clsid
= str
;
1716 entity
->u
.comclass
.model
= ThreadingModel_Both
;
1718 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1721 static void parse_cominterface_proxy_stub_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1722 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1724 WCHAR
*psclsid
= NULL
;
1725 struct entity
*entity
;
1726 struct xml_attr attr
;
1729 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1731 set_error( xmlbuf
);
1735 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1737 if (xml_attr_cmp(&attr
, L
"iid"))
1739 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1741 else if (xml_attr_cmp(&attr
, L
"name"))
1743 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1745 else if (xml_attr_cmp(&attr
, L
"baseInterface"))
1747 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1748 entity
->u
.ifaceps
.mask
|= BaseIface
;
1750 else if (xml_attr_cmp(&attr
, L
"numMethods"))
1752 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
1753 entity
->u
.ifaceps
.mask
|= NumMethods
;
1755 else if (xml_attr_cmp(&attr
, L
"tlbid"))
1757 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1759 else if (xml_attr_cmp(&attr
, L
"proxyStubClsid32"))
1761 if (!(psclsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1764 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
1767 else if (!is_xmlns_attr( &attr
))
1769 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1773 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1774 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1776 parse_add_interface_class(xmlbuf
, &dll
->entities
, acl
, psclsid
? psclsid
: entity
->u
.ifaceps
.iid
);
1778 RtlFreeHeap(GetProcessHeap(), 0, psclsid
);
1781 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1783 WORD
*flags
= &entity
->u
.typelib
.flags
;
1784 const WCHAR
*str
= value
->ptr
, *start
;
1789 /* it's comma separated list of flags */
1790 while (i
< value
->len
)
1793 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1795 if (!wcsnicmp(start
, L
"RESTRICTED", str
-start
))
1796 *flags
|= LIBFLAG_FRESTRICTED
;
1797 else if (!wcsnicmp(start
, L
"CONTROL", str
-start
))
1798 *flags
|= LIBFLAG_FCONTROL
;
1799 else if (!wcsnicmp(start
, L
"HIDDEN", str
-start
))
1800 *flags
|= LIBFLAG_FHIDDEN
;
1801 else if (!wcsnicmp(start
, L
"HASDISKIMAGE", str
-start
))
1802 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1805 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1809 /* skip separator */
1817 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1819 unsigned int ver
[2];
1824 ver
[0] = ver
[1] = pos
= 0;
1825 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1827 if (*curr
>= '0' && *curr
<= '9')
1829 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1830 if (ver
[pos
] >= 0x10000) goto error
;
1832 else if (*curr
== '.')
1834 if (++pos
>= 2) goto error
;
1838 entity
->u
.typelib
.major
= ver
[0];
1839 entity
->u
.typelib
.minor
= ver
[1];
1843 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1847 static void parse_typelib_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1848 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1850 struct xml_attr attr
;
1852 struct entity
* entity
;
1854 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1856 set_error( xmlbuf
);
1860 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1862 if (xml_attr_cmp(&attr
, L
"tlbid"))
1864 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1866 else if (xml_attr_cmp(&attr
, L
"version"))
1868 if (!parse_typelib_version(&attr
.value
, entity
)) set_error( xmlbuf
);
1870 else if (xml_attr_cmp(&attr
, L
"helpdir"))
1872 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1874 else if (xml_attr_cmp(&attr
, L
"flags"))
1876 if (!parse_typelib_flags(&attr
.value
, entity
)) set_error( xmlbuf
);
1878 else if (!is_xmlns_attr( &attr
))
1880 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1884 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1885 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1888 static inline int aligned_string_len(int len
)
1890 return (len
+ 3) & ~3;
1893 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1895 struct assembly_version
*ver
= &assembly
->id
.version
;
1898 if (!ret
) ret
= buff
;
1899 return swprintf(ret
, ARRAY_SIZE(buff
), L
"%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1902 static void parse_window_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1903 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1905 struct xml_elem elem
;
1906 struct xml_attr attr
;
1909 struct entity
* entity
;
1911 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1913 set_error( xmlbuf
);
1916 entity
->u
.class.versioned
= TRUE
;
1917 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1919 if (xml_attr_cmp(&attr
, L
"versioned"))
1921 if (xmlstr_cmpi(&attr
.value
, L
"no"))
1922 entity
->u
.class.versioned
= FALSE
;
1923 else if (!xmlstr_cmpi(&attr
.value
, L
"yes"))
1924 set_error( xmlbuf
);
1926 else if (!is_xmlns_attr( &attr
))
1928 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1934 if (!parse_text_content(xmlbuf
, &content
)) return;
1935 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) set_error( xmlbuf
);
1937 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1939 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1941 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1942 parse_unknown_elem(xmlbuf
, &elem
);
1946 static void parse_binding_redirect_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1948 struct xml_attr attr
;
1951 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1953 if (xml_attr_cmp(&attr
, L
"oldVersion"))
1955 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1957 else if (xml_attr_cmp(&attr
, L
"newVersion"))
1959 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1961 else if (!is_xmlns_attr( &attr
))
1963 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1967 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1970 static void parse_description_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1972 struct xml_elem elem
;
1973 struct xml_attr attr
;
1977 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1979 if (!is_xmlns_attr( &attr
)) WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1983 if (!parse_text_content(xmlbuf
, &content
)) return;
1985 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1987 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1989 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1990 parse_unknown_elem(xmlbuf
, &elem
);
1994 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t
*xmlbuf
,
1995 struct assembly
* assembly
,
1996 struct actctx_loader
* acl
,
1997 const struct xml_elem
*parent
)
1999 struct xml_attr attr
;
2001 struct entity
* entity
;
2003 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
2005 set_error( xmlbuf
);
2009 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2011 if (xml_attr_cmp(&attr
, L
"iid"))
2013 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2015 else if (xml_attr_cmp(&attr
, L
"name"))
2017 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2019 else if (xml_attr_cmp(&attr
, L
"baseInterface"))
2021 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2022 entity
->u
.ifaceps
.mask
|= BaseIface
;
2024 else if (xml_attr_cmp(&attr
, L
"numMethods"))
2026 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
2027 entity
->u
.ifaceps
.mask
|= NumMethods
;
2029 else if (xml_attr_cmp(&attr
, L
"proxyStubClsid32"))
2031 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2033 else if (xml_attr_cmp(&attr
, L
"tlbid"))
2035 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2037 else if (!is_xmlns_attr( &attr
))
2039 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2043 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2044 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2047 static void parse_clr_class_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2048 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2051 struct xml_elem elem
;
2052 struct xml_attr attr
;
2054 struct entity
* entity
;
2056 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
2058 set_error( xmlbuf
);
2062 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2064 if (xml_attr_cmp(&attr
, L
"name"))
2066 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2068 else if (xml_attr_cmp(&attr
, L
"clsid"))
2070 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2072 else if (xml_attr_cmp(&attr
, L
"progid"))
2074 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2076 else if (xml_attr_cmp(&attr
, L
"tlbid"))
2078 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2080 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
2082 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
2084 else if (xml_attr_cmp(&attr
, L
"runtimeVersion"))
2086 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2088 else if (!is_xmlns_attr( &attr
))
2090 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2094 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2095 if (entity
->u
.comclass
.progid
)
2096 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2099 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2101 if (xml_elem_cmp(&elem
, L
"progid", asmv1W
))
2103 parse_com_class_progid(xmlbuf
, entity
, &elem
);
2107 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2108 parse_unknown_elem(xmlbuf
, &elem
);
2112 if (entity
->u
.comclass
.progids
.num
)
2113 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2116 static void parse_clr_surrogate_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2117 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2119 struct xml_attr attr
;
2121 struct entity
* entity
;
2123 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)))
2125 set_error( xmlbuf
);
2129 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2131 if (xml_attr_cmp(&attr
, L
"name"))
2133 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2135 else if (xml_attr_cmp(&attr
, L
"clsid"))
2137 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2139 else if (xml_attr_cmp(&attr
, L
"runtimeVersion"))
2141 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2143 else if (!is_xmlns_attr( &attr
))
2145 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2149 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2150 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2153 static void parse_dependent_assembly_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2154 const struct xml_elem
*parent
, BOOL optional
)
2156 struct xml_elem elem
;
2157 struct xml_attr attr
;
2158 struct assembly_identity ai
;
2161 memset(&ai
, 0, sizeof(ai
));
2162 ai
.optional
= optional
;
2164 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2166 if (xml_attr_cmp(&attr
, L
"allowDelayedBinding"))
2167 ai
.delayed
= xmlstr_cmp(&attr
.value
, L
"true");
2168 else if (!is_xmlns_attr( &attr
))
2169 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2174 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2176 if (xml_elem_cmp(&elem
, L
"assemblyIdentity", asmv1W
))
2178 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
, &elem
);
2179 /* store the newly found identity for later loading */
2180 if (ai
.arch
&& !wcscmp(ai
.arch
, L
"*"))
2182 RtlFreeHeap( GetProcessHeap(), 0, ai
.arch
);
2183 ai
.arch
= strdupW( current_archW
);
2185 TRACE( "adding name=%s version=%s arch=%s\n",
2186 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2187 if (!add_dependent_assembly_id(acl
, &ai
)) set_error( xmlbuf
);
2189 else if (xml_elem_cmp(&elem
, L
"bindingRedirect", asmv1W
))
2191 parse_binding_redirect_elem(xmlbuf
, &elem
);
2195 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2196 parse_unknown_elem(xmlbuf
, &elem
);
2201 static void parse_dependency_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2202 const struct xml_elem
*parent
)
2205 struct xml_elem elem
;
2206 struct xml_attr attr
;
2207 BOOL end
= FALSE
, optional
= FALSE
;
2209 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2211 if (xml_attr_cmp(&attr
, L
"optional"))
2213 optional
= xmlstr_cmpi( &attr
.value
, L
"yes" );
2214 TRACE("optional=%s\n", debugstr_xmlstr(&attr
.value
));
2216 else if (!is_xmlns_attr( &attr
))
2218 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2224 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2226 if (xml_elem_cmp(&elem
, L
"dependentAssembly", asmv1W
))
2228 parse_dependent_assembly_elem(xmlbuf
, acl
, &elem
, optional
);
2232 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2233 parse_unknown_elem(xmlbuf
, &elem
);
2238 static void parse_noinherit_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2242 parse_expect_no_attr(xmlbuf
, &end
);
2243 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2246 static void parse_noinheritable_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2250 parse_expect_no_attr(xmlbuf
, &end
);
2251 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2254 static void parse_activatable_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
2255 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2257 struct xml_elem elem
;
2258 struct xml_attr attr
;
2260 struct entity
*entity
;
2262 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)))
2264 set_error( xmlbuf
);
2267 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2269 if (xml_attr_cmp(&attr
, L
"name"))
2271 if (!(entity
->u
.activatable_class
.name
= xmlstrdupW(&attr
.value
)))
2272 set_error( xmlbuf
);
2274 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
2276 if (xmlstr_cmpi(&attr
.value
, L
"both"))
2277 entity
->u
.activatable_class
.threading_model
= 0;
2278 else if (xmlstr_cmpi(&attr
.value
, L
"sta"))
2279 entity
->u
.activatable_class
.threading_model
= 1;
2280 else if (xmlstr_cmpi(&attr
.value
, L
"mta"))
2281 entity
->u
.activatable_class
.threading_model
= 2;
2283 set_error( xmlbuf
);
2285 else if (!is_xmlns_attr( &attr
))
2287 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2291 acl
->actctx
->sections
|= ACTIVATABLE_CLASS_SECTION
;
2295 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2297 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2298 parse_unknown_elem(xmlbuf
, &elem
);
2302 static void parse_file_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2303 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2305 struct xml_elem elem
;
2306 struct xml_attr attr
;
2308 struct dll_redirect
* dll
;
2310 if (!(dll
= add_dll_redirect(assembly
)))
2312 set_error( xmlbuf
);
2316 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2318 if (xml_attr_cmp(&attr
, L
"name"))
2320 if (!(dll
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2321 TRACE("name=%s\n", debugstr_xmlstr(&attr
.value
));
2323 else if (xml_attr_cmp(&attr
, L
"loadFrom"))
2325 if (!(dll
->load_from
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2327 else if (xml_attr_cmp(&attr
, L
"hash"))
2329 if (!(dll
->hash
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2331 else if (xml_attr_cmp(&attr
, L
"hashalg"))
2333 if (!xmlstr_cmpi(&attr
.value
, L
"SHA1"))
2334 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr
.value
));
2336 else if (!is_xmlns_attr( &attr
))
2338 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2342 if (!dll
->name
) set_error( xmlbuf
);
2344 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2348 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2350 if (xml_elem_cmp(&elem
, L
"comClass", asmv1W
))
2352 parse_com_class_elem(xmlbuf
, dll
, acl
, &elem
);
2354 else if (xml_elem_cmp(&elem
, L
"comInterfaceProxyStub", asmv1W
))
2356 parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
, &elem
);
2358 else if (xml_elem_cmp(&elem
, L
"hash", asmv2W
))
2360 WARN("asmv2:hash (undocumented) not supported\n");
2361 parse_unknown_elem(xmlbuf
, &elem
);
2363 else if (xml_elem_cmp(&elem
, L
"typelib", asmv1W
))
2365 parse_typelib_elem(xmlbuf
, dll
, acl
, &elem
);
2367 else if (xml_elem_cmp(&elem
, L
"windowClass", asmv1W
))
2369 parse_window_class_elem(xmlbuf
, dll
, acl
, &elem
);
2371 else if (xml_elem_cmp(&elem
, L
"activatableClass", winrtv1W
))
2373 parse_activatable_class_elem(xmlbuf
, dll
, acl
, &elem
);
2377 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2378 parse_unknown_elem( xmlbuf
, &elem
);
2383 static void parse_supportedos_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2384 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2386 struct xml_attr attr
;
2389 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2391 if (xml_attr_cmp(&attr
, L
"Id"))
2393 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2397 str
.Buffer
= (PWSTR
)attr
.value
.ptr
;
2398 str
.Length
= str
.MaximumLength
= (USHORT
)attr
.value
.len
* sizeof(WCHAR
);
2399 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2401 if (!(compat
= add_compat_context(assembly
)))
2403 set_error( xmlbuf
);
2406 compat
->Type
= ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2407 compat
->Id
= compat_id
;
2411 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr
.value
));
2414 else if (!is_xmlns_attr( &attr
))
2416 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2420 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2423 static void parse_maxversiontested_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2424 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2426 struct xml_attr attr
;
2429 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2431 if (xml_attr_cmp(&attr
, L
"Id"))
2433 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2434 struct assembly_version version
;
2436 if (!(compat
= add_compat_context(assembly
)))
2438 set_error( xmlbuf
);
2441 parse_version( &attr
.value
, &version
);
2442 compat
->Type
= ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED
;
2443 compat
->MaxVersionTested
= (ULONGLONG
)version
.major
<< 48 |
2444 (ULONGLONG
)version
.minor
<< 32 | version
.build
<< 16 | version
.revision
;
2446 else if (!is_xmlns_attr( &attr
))
2448 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2452 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2455 static void parse_compatibility_application_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2456 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2458 struct xml_elem elem
;
2460 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2462 if (xml_elem_cmp(&elem
, L
"supportedOS", compatibilityNSW
))
2464 parse_supportedos_elem(xmlbuf
, assembly
, acl
, &elem
);
2466 else if (xml_elem_cmp(&elem
, L
"maxversiontested", compatibilityNSW
))
2468 parse_maxversiontested_elem(xmlbuf
, assembly
, acl
, &elem
);
2472 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2473 parse_unknown_elem(xmlbuf
, &elem
);
2478 static void parse_compatibility_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2479 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2481 struct xml_elem elem
;
2483 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2485 if (xml_elem_cmp(&elem
, L
"application", compatibilityNSW
))
2487 parse_compatibility_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2491 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2492 parse_unknown_elem(xmlbuf
, &elem
);
2497 static void parse_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
,
2498 struct xml_elem
*parent
)
2500 struct xml_elem elem
;
2501 struct xml_attr attr
;
2504 struct entity
*entity
;
2506 while (next_xml_attr( xmlbuf
, &attr
, &end
))
2508 if (!is_xmlns_attr( &attr
)) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr
) );
2513 if (!parse_text_content( xmlbuf
, &content
)) return;
2514 TRACE( "got %s %s\n", debugstr_xmlstr(&parent
->name
), debugstr_xmlstr(&content
) );
2516 entity
= add_entity( &assembly
->entities
, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
);
2519 set_error( xmlbuf
);
2522 entity
->u
.settings
.name
= xmlstrdupW( &parent
->name
);
2523 entity
->u
.settings
.value
= xmlstrdupW( &content
);
2524 entity
->u
.settings
.ns
= xmlstrdupW( &parent
->ns
);
2526 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2528 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2529 parse_unknown_elem( xmlbuf
, &elem
);
2533 static void parse_windows_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2534 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2536 struct xml_elem elem
;
2538 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2540 if (xml_elem_cmp( &elem
, L
"activeCodePage", windowsSettings2019NSW
) ||
2541 xml_elem_cmp( &elem
, L
"autoElevate", windowsSettings2005NSW
) ||
2542 xml_elem_cmp( &elem
, L
"disableTheming", windowsSettings2005NSW
) ||
2543 xml_elem_cmp( &elem
, L
"disableWindowFiltering", windowsSettings2011NSW
) ||
2544 xml_elem_cmp( &elem
, L
"dpiAware", windowsSettings2005NSW
) ||
2545 xml_elem_cmp( &elem
, L
"dpiAwareness", windowsSettings2016NSW
) ||
2546 xml_elem_cmp( &elem
, L
"gdiScaling", windowsSettings2017NSW
) ||
2547 xml_elem_cmp( &elem
, L
"heapType", windowsSettings2020NSW
) ||
2548 xml_elem_cmp( &elem
, L
"highResolutionScrollingAware", windowsSettings2017NSW
) ||
2549 xml_elem_cmp( &elem
, L
"longPathAware", windowsSettings2016NSW
) ||
2550 xml_elem_cmp( &elem
, L
"magicFutureSetting", windowsSettings2017NSW
) ||
2551 xml_elem_cmp( &elem
, L
"printerDriverIsolation", windowsSettings2011NSW
) ||
2552 xml_elem_cmp( &elem
, L
"ultraHighResolutionScrollingAware", windowsSettings2017NSW
))
2554 parse_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2558 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2559 parse_unknown_elem( xmlbuf
, &elem
);
2564 static void parse_application_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2565 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2567 struct xml_elem elem
;
2569 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2571 if (xml_elem_cmp( &elem
, L
"windowsSettings", asmv1W
))
2573 parse_windows_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2577 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2578 parse_unknown_elem( xmlbuf
, &elem
);
2583 static void parse_requested_execution_level_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2584 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2586 struct xml_elem elem
;
2587 struct xml_attr attr
;
2590 /* Multiple requestedExecutionLevel elements are not supported. */
2591 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
) set_error( xmlbuf
);
2593 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2595 if (xml_attr_cmp(&attr
, L
"level"))
2597 if (xmlstr_cmpi(&attr
.value
, L
"asInvoker"))
2598 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2599 else if (xmlstr_cmpi(&attr
.value
, L
"highestAvailable"))
2600 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2601 else if (xmlstr_cmpi(&attr
.value
, L
"requireAdministrator"))
2602 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2604 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr
.value
));
2606 else if (xml_attr_cmp(&attr
, L
"uiAccess"))
2608 if (xmlstr_cmpi(&attr
.value
, L
"false"))
2609 assembly
->ui_access
= FALSE
;
2610 else if (xmlstr_cmpi(&attr
.value
, L
"true"))
2611 assembly
->ui_access
= TRUE
;
2613 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr
.value
));
2615 else if (!is_xmlns_attr( &attr
))
2616 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2621 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2623 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2624 parse_unknown_elem(xmlbuf
, &elem
);
2628 static void parse_requested_privileges_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2629 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2631 struct xml_elem elem
;
2633 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2635 if (xml_elem_cmp(&elem
, L
"requestedExecutionLevel", asmv1W
))
2637 parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
, &elem
);
2641 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2642 parse_unknown_elem(xmlbuf
, &elem
);
2647 static void parse_security_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2648 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2650 struct xml_elem elem
;
2652 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2654 if (xml_elem_cmp(&elem
, L
"requestedPrivileges", asmv1W
))
2656 parse_requested_privileges_elem(xmlbuf
, assembly
, acl
, &elem
);
2660 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2661 parse_unknown_elem(xmlbuf
, &elem
);
2666 static void parse_trust_info_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2667 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2669 struct xml_elem elem
;
2671 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2673 if (xml_elem_cmp(&elem
, L
"security", asmv1W
))
2675 parse_security_elem(xmlbuf
, assembly
, acl
, &elem
);
2679 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2680 parse_unknown_elem(xmlbuf
, &elem
);
2685 static void parse_assembly_elem( xmlbuf_t
*xmlbuf
, struct assembly
* assembly
,
2686 struct actctx_loader
* acl
, const struct xml_elem
*parent
,
2687 struct assembly_identity
* expected_ai
)
2689 struct xml_elem elem
;
2690 struct xml_attr attr
;
2691 BOOL end
= FALSE
, version
= FALSE
;
2693 TRACE("(%p)\n", xmlbuf
);
2695 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2697 if (xml_attr_cmp(&attr
, L
"manifestVersion"))
2699 if (!xmlstr_cmp(&attr
.value
, L
"1.0"))
2701 FIXME("wrong version %s\n", debugstr_xmlstr(&attr
.value
));
2706 else if (!is_xmlns_attr( &attr
))
2708 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2712 if (end
|| !version
)
2714 set_error( xmlbuf
);
2718 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2720 if (assembly
->type
== APPLICATION_MANIFEST
&& xml_elem_cmp(&elem
, L
"noInherit", asmv1W
))
2722 parse_noinherit_elem(xmlbuf
, &elem
);
2723 assembly
->no_inherit
= TRUE
;
2725 else if (xml_elem_cmp(&elem
, L
"noInheritable", asmv1W
))
2727 parse_noinheritable_elem(xmlbuf
, &elem
);
2729 else if (xml_elem_cmp(&elem
, L
"description", asmv1W
))
2731 parse_description_elem(xmlbuf
, &elem
);
2733 else if (xml_elem_cmp(&elem
, L
"comInterfaceExternalProxyStub", asmv1W
))
2735 parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
, &elem
);
2737 else if (xml_elem_cmp(&elem
, L
"dependency", asmv1W
))
2739 parse_dependency_elem(xmlbuf
, acl
, &elem
);
2741 else if (xml_elem_cmp(&elem
, L
"file", asmv1W
))
2743 parse_file_elem(xmlbuf
, assembly
, acl
, &elem
);
2745 else if (xml_elem_cmp(&elem
, L
"clrClass", asmv1W
))
2747 parse_clr_class_elem(xmlbuf
, assembly
, acl
, &elem
);
2749 else if (xml_elem_cmp(&elem
, L
"clrSurrogate", asmv1W
))
2751 parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
, &elem
);
2753 else if (xml_elem_cmp(&elem
, L
"trustInfo", asmv1W
))
2755 parse_trust_info_elem(xmlbuf
, assembly
, acl
, &elem
);
2757 else if (xml_elem_cmp(&elem
, L
"assemblyIdentity", asmv1W
))
2759 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
, &elem
);
2761 if (!xmlbuf
->error
&& expected_ai
)
2763 /* FIXME: more tests */
2764 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2765 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2767 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2768 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2769 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2770 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2771 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2772 set_error( xmlbuf
);
2774 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2775 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2776 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2777 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2778 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2779 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2781 FIXME("wrong version for shared assembly manifest\n");
2782 set_error( xmlbuf
);
2786 else if (xml_elem_cmp(&elem
, L
"compatibility", compatibilityNSW
))
2788 parse_compatibility_elem(xmlbuf
, assembly
, acl
, &elem
);
2790 else if (xml_elem_cmp(&elem
, L
"application", asmv1W
))
2792 parse_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2796 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2797 parse_unknown_elem(xmlbuf
, &elem
);
2801 if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2802 assembly
->no_inherit
)
2804 set_error( xmlbuf
);
2808 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2809 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2811 struct xml_elem elem
;
2812 struct xml_elem parent
= {};
2814 xmlbuf
->error
= FALSE
;
2817 if (!next_xml_elem(xmlbuf
, &elem
, &parent
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2819 if (xmlstr_cmp(&elem
.name
, L
"?xml") &&
2820 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
, &parent
)))
2821 return STATUS_SXS_CANT_GEN_ACTCTX
;
2823 if (!xml_elem_cmp(&elem
, L
"assembly", asmv1W
))
2825 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem
));
2826 return STATUS_SXS_CANT_GEN_ACTCTX
;
2829 parse_assembly_elem(xmlbuf
, assembly
, acl
, &elem
, ai
);
2832 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2833 return STATUS_SXS_CANT_GEN_ACTCTX
;
2836 if (next_xml_elem(xmlbuf
, &elem
, &parent
))
2838 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem
));
2839 return STATUS_SXS_CANT_GEN_ACTCTX
;
2842 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2844 FIXME("parse error\n");
2845 return STATUS_SXS_CANT_GEN_ACTCTX
;
2847 return STATUS_SUCCESS
;
2850 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2851 LPCWSTR filename
, HANDLE module
, LPCWSTR directory
, BOOL shared
,
2852 const void *buffer
, SIZE_T size
)
2856 struct assembly
*assembly
;
2859 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2861 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2862 return STATUS_SXS_CANT_GEN_ACTCTX
;
2864 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2865 return STATUS_NO_MEMORY
;
2869 UNICODE_STRING module_path
;
2870 if ((status
= get_module_filename( module
, &module_path
, 0 ))) return status
;
2871 assembly
->manifest
.info
= module_path
.Buffer
;
2873 else if(!(assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY
;
2875 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2876 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2878 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2879 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2881 xmlbuf
.ptr
= buffer
;
2882 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2883 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2885 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2887 const WCHAR
*buf
= buffer
;
2891 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2892 return STATUS_NO_MEMORY
;
2893 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2894 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2895 xmlbuf
.ptr
= new_buff
;
2896 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2897 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2898 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2905 /* let's assume utf-8 for now */
2906 RtlUTF8ToUnicodeN( NULL
, 0, &len
, buffer
, size
);
2907 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
2908 RtlUTF8ToUnicodeN( new_buff
, len
, &len
, buffer
, size
);
2909 xmlbuf
.ptr
= new_buff
;
2910 xmlbuf
.end
= xmlbuf
.ptr
+ len
/ sizeof(WCHAR
);
2911 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2912 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2917 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2919 OBJECT_ATTRIBUTES attr
;
2922 attr
.Length
= sizeof(attr
);
2923 attr
.RootDirectory
= 0;
2924 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2925 attr
.ObjectName
= name
;
2926 attr
.SecurityDescriptor
= NULL
;
2927 attr
.SecurityQualityOfService
= NULL
;
2928 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2931 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2932 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2933 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2936 UNICODE_STRING nameW
;
2937 LDR_RESOURCE_INFO info
;
2938 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2941 if (TRACE_ON(actctx
))
2943 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2945 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2946 hModule
, debugstr_w(nameW
.Buffer
) );
2947 RtlFreeUnicodeString( &nameW
);
2949 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2950 hModule
, debugstr_w(filename
) );
2953 if (!resname
) return STATUS_INVALID_PARAMETER
;
2955 info
.Type
= RT_MANIFEST
;
2956 info
.Language
= lang
;
2957 if (!((ULONG_PTR
)resname
>> 16))
2959 info
.Name
= (ULONG_PTR
)resname
;
2960 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2962 else if (resname
[0] == '#')
2965 RtlInitUnicodeString(&nameW
, resname
+ 1);
2966 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2967 return STATUS_INVALID_PARAMETER
;
2969 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2973 RtlCreateUnicodeString(&nameW
, resname
);
2974 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2975 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2976 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2977 RtlFreeUnicodeString(&nameW
);
2979 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2981 if (status
== STATUS_SUCCESS
)
2982 status
= parse_manifest(acl
, ai
, filename
, hModule
, directory
, shared
, ptr
, entry
->Size
);
2987 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2988 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2989 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2992 OBJECT_ATTRIBUTES attr
;
2994 LARGE_INTEGER offset
;
2999 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
3001 attr
.Length
= sizeof(attr
);
3002 attr
.RootDirectory
= 0;
3003 attr
.ObjectName
= NULL
;
3004 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3005 attr
.SecurityDescriptor
= NULL
;
3006 attr
.SecurityQualityOfService
= NULL
;
3009 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3010 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3011 if (status
!= STATUS_SUCCESS
) return status
;
3013 offset
.QuadPart
= 0;
3016 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3017 &count
, ViewShare
, 0, PAGE_READONLY
);
3019 if (status
!= STATUS_SUCCESS
) return status
;
3021 if (RtlImageNtHeader(base
)) /* we got a PE file */
3023 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3024 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
3026 else status
= STATUS_INVALID_IMAGE_FORMAT
;
3028 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3032 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3033 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
3035 FILE_END_OF_FILE_INFORMATION info
;
3038 OBJECT_ATTRIBUTES attr
;
3040 LARGE_INTEGER offset
;
3045 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
3047 attr
.Length
= sizeof(attr
);
3048 attr
.RootDirectory
= 0;
3049 attr
.ObjectName
= NULL
;
3050 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3051 attr
.SecurityDescriptor
= NULL
;
3052 attr
.SecurityQualityOfService
= NULL
;
3055 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3056 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3057 if (status
!= STATUS_SUCCESS
) return status
;
3059 offset
.QuadPart
= 0;
3062 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3063 &count
, ViewShare
, 0, PAGE_READONLY
);
3065 if (status
!= STATUS_SUCCESS
) return status
;
3067 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
3068 if (status
== STATUS_SUCCESS
)
3069 status
= parse_manifest(acl
, ai
, filename
, NULL
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
3071 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3075 /* try to load the .manifest file associated to the file */
3076 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3077 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3081 UNICODE_STRING nameW
;
3083 UINT resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3085 if (!((ULONG_PTR
)resname
>> 16)) resid
= LOWORD(resname
);
3087 TRACE( "looking for manifest associated with %s id %u\n", debugstr_w(filename
), resid
);
3089 if (module
) /* use the module filename */
3091 UNICODE_STRING name
;
3093 if (!(status
= get_module_filename( module
, &name
, sizeof(L
".manifest") + 10*sizeof(WCHAR
) )))
3095 if (resid
!= 1) swprintf( name
.Buffer
+ wcslen(name
.Buffer
), 10, L
".%u", resid
);
3096 wcscat( name
.Buffer
, L
".manifest" );
3097 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3098 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3099 RtlFreeUnicodeString( &name
);
3101 if (status
) return status
;
3105 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3106 (wcslen(filename
) + 10) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
3107 return STATUS_NO_MEMORY
;
3108 wcscpy( buffer
, filename
);
3109 if (resid
!= 1) swprintf( buffer
+ wcslen(buffer
), 10, L
".%u", resid
);
3110 wcscat( buffer
, L
".manifest" );
3111 RtlInitUnicodeString( &nameW
, buffer
);
3114 if (!open_nt_file( &file
, &nameW
))
3116 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3119 else status
= STATUS_RESOURCE_NAME_NOT_FOUND
;
3120 RtlFreeUnicodeString( &nameW
);
3124 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3126 static const WCHAR lookup_fmtW
[] = L
"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3127 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3129 WCHAR
*lookup
, *ret
= NULL
;
3130 UNICODE_STRING lookup_us
;
3132 const WCHAR
*lang
= ai
->language
;
3133 unsigned int data_pos
= 0, data_len
, len
;
3136 if (!lang
|| !wcsicmp( lang
, L
"neutral" )) lang
= L
"*";
3138 len
= wcslen(ai
->arch
) + wcslen(ai
->name
) + wcslen(ai
->public_key
) + wcslen(lang
) + 20 + ARRAY_SIZE(lookup_fmtW
);
3139 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
3140 swprintf( lookup
, len
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3141 ai
->version
.major
, ai
->version
.minor
, lang
);
3142 RtlInitUnicodeString( &lookup_us
, lookup
);
3144 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3145 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3147 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3148 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3150 ULONG build
, revision
;
3152 data_len
= io
.Information
;
3156 if (data_pos
>= data_len
)
3158 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3159 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3161 data_len
= io
.Information
;
3164 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3166 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3167 else data_pos
= data_len
;
3169 tmp
= dir_info
->FileName
+ (wcschr(lookup
, '*') - lookup
);
3170 build
= wcstoul( tmp
, NULL
, 10 );
3171 if (build
< min_build
) continue;
3172 tmp
= wcschr(tmp
, '.') + 1;
3173 revision
= wcstoul( tmp
, NULL
, 10 );
3174 if (build
== min_build
&& revision
< min_revision
) continue;
3175 tmp
= wcschr(tmp
, '_') + 1;
3176 tmp
= wcschr(tmp
, '_') + 1;
3177 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3178 !wcsnicmp( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3180 /* prefer a non-Wine manifest if we already have one */
3181 /* we'll still load the builtin dll if specified through DllOverrides */
3187 min_revision
= revision
;
3189 ai
->version
.build
= build
;
3190 ai
->version
.revision
= revision
;
3191 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3192 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3194 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3195 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3199 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3200 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3204 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3206 struct assembly_identity sxs_ai
;
3207 UNICODE_STRING path_us
;
3208 OBJECT_ATTRIBUTES attr
;
3210 WCHAR
*path
, *file
= NULL
;
3213 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3215 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L
"\\winsxs\\manifests") +
3216 wcslen(windows_dir
) * sizeof(WCHAR
) )))
3217 return STATUS_NO_MEMORY
;
3219 wcscpy( path
, windows_dir
);
3220 wcscat( path
, L
"\\winsxs\\manifests" );
3222 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3224 RtlFreeHeap( GetProcessHeap(), 0, path
);
3225 return STATUS_NO_SUCH_FILE
;
3227 RtlFreeHeap( GetProcessHeap(), 0, path
);
3229 attr
.Length
= sizeof(attr
);
3230 attr
.RootDirectory
= 0;
3231 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3232 attr
.ObjectName
= &path_us
;
3233 attr
.SecurityDescriptor
= NULL
;
3234 attr
.SecurityQualityOfService
= NULL
;
3236 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3237 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3240 file
= lookup_manifest_file( handle
, &sxs_ai
);
3245 RtlFreeUnicodeString( &path_us
);
3246 return STATUS_NO_SUCH_FILE
;
3249 /* append file name to directory path */
3250 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3251 path_us
.Length
+ (wcslen(file
) + 2) * sizeof(WCHAR
) )))
3253 RtlFreeHeap( GetProcessHeap(), 0, file
);
3254 RtlFreeUnicodeString( &path_us
);
3255 return STATUS_NO_MEMORY
;
3258 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3259 wcscpy( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3260 RtlInitUnicodeString( &path_us
, path
);
3261 *wcsrchr(file
, '.') = 0; /* remove .manifest extension */
3263 if (!open_nt_file( &handle
, &path_us
))
3265 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3268 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3270 RtlFreeHeap( GetProcessHeap(), 0, file
);
3271 RtlFreeUnicodeString( &path_us
);
3275 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3276 struct assembly_identity
* ai
)
3279 WCHAR
*buffer
, *p
, *directory
;
3281 UNICODE_STRING nameW
;
3285 TRACE( "looking for name=%s version=%s arch=%s\n",
3286 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3288 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3290 /* FIXME: add support for language specific lookup */
3292 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3293 wcslen(acl
->actctx
->appdir
.info
));
3295 nameW
.Buffer
= NULL
;
3296 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3297 (len
+ 2 * wcslen(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
3298 return STATUS_NO_MEMORY
;
3300 if (!(directory
= build_assembly_dir( ai
)))
3302 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3303 return STATUS_NO_MEMORY
;
3306 /* Lookup in <dir>\name.dll
3307 * <dir>\name.manifest
3308 * <dir>\name\name.dll
3309 * <dir>\name\name.manifest
3311 * First 'appdir' is used as <dir>, if that failed
3312 * it tries application manifest file path.
3314 wcscpy( buffer
, acl
->actctx
->appdir
.info
);
3315 p
= buffer
+ wcslen(buffer
);
3316 for (i
= 0; i
< 4; i
++)
3320 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3321 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3325 wcscpy( p
, ai
->name
);
3328 wcscpy( p
, L
".dll" );
3329 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3331 status
= open_nt_file( &file
, &nameW
);
3334 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3335 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3337 if (status
== STATUS_SUCCESS
)
3340 RtlFreeUnicodeString( &nameW
);
3343 wcscpy( p
, L
".manifest" );
3344 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3346 status
= open_nt_file( &file
, &nameW
);
3349 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3353 RtlFreeUnicodeString( &nameW
);
3355 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3357 RtlFreeUnicodeString( &nameW
);
3358 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3359 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3363 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3365 NTSTATUS status
= STATUS_SUCCESS
;
3368 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3370 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3372 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3374 FIXME( "Could not find dependent assembly %s (%s)\n",
3375 debugstr_w(acl
->dependencies
[i
].name
),
3376 debugstr_version(&acl
->dependencies
[i
].version
) );
3377 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3382 /* FIXME should now iterate through all refs */
3386 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3387 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3389 NTSTATUS status
= STATUS_SUCCESS
;
3391 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3393 if (*handle
) return STATUS_INVALID_PARAMETER
;
3395 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3396 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3398 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3401 LDR_DATA_TABLE_ENTRY
*pldr
;
3403 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3405 LdrLockLoaderLock( 0, NULL
, &magic
);
3406 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3408 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3409 status
= STATUS_DLL_NOT_FOUND
;
3411 *handle
= pldr
->ActivationContext
;
3413 else status
= STATUS_DLL_NOT_FOUND
;
3414 LdrUnlockLoaderLock( 0, magic
);
3416 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3417 *handle
= process_actctx
;
3422 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3424 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3425 struct strsection_header
*header
;
3426 struct dllredirect_data
*data
;
3427 struct string_index
*index
;
3430 /* compute section length */
3431 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3433 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3434 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3436 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3438 /* each entry needs index, data and string data */
3439 total_len
+= sizeof(*index
);
3440 total_len
+= aligned_string_len((wcslen(dll
->name
)+1)*sizeof(WCHAR
));
3443 total_len
+= offsetof( struct dllredirect_data
, paths
[1] );
3444 total_len
+= aligned_string_len( wcslen(dll
->load_from
) * sizeof(WCHAR
) );
3446 else total_len
+= offsetof( struct dllredirect_data
, paths
[0] );
3449 dll_count
+= assembly
->num_dlls
;
3452 total_len
+= sizeof(*header
);
3454 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3455 if (!header
) return STATUS_NO_MEMORY
;
3457 memset(header
, 0, sizeof(*header
));
3458 header
->magic
= STRSECTION_MAGIC
;
3459 header
->size
= sizeof(*header
);
3460 header
->count
= dll_count
;
3461 header
->index_offset
= sizeof(*header
);
3462 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3463 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3465 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3467 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3468 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3470 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3474 /* setup new index entry */
3475 str
.Buffer
= dll
->name
;
3476 str
.Length
= wcslen(dll
->name
)*sizeof(WCHAR
);
3477 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3478 /* hash original class name */
3479 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3481 index
->name_offset
= name_offset
;
3482 index
->name_len
= str
.Length
;
3483 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3484 index
->data_len
= offsetof( struct dllredirect_data
, paths
[0] );
3485 index
->rosterindex
= i
+ 1;
3488 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3489 memcpy(ptrW
, dll
->name
, index
->name_len
);
3490 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3491 name_offset
+= aligned_string_len(str
.MaximumLength
);
3494 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3497 ULONG len
= wcslen(dll
->load_from
) * sizeof(WCHAR
);
3498 data
->size
= offsetof( struct dllredirect_data
, paths
[1] );
3500 data
->total_len
= aligned_string_len( len
);
3501 data
->paths_count
= 1;
3502 data
->paths_offset
= index
->data_offset
+ offsetof( struct dllredirect_data
, paths
[0] );
3503 data
->paths
[0].offset
= index
->data_offset
+ data
->size
;
3504 data
->paths
[0].len
= len
;
3505 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->paths
[0].offset
);
3506 memcpy( ptrW
, dll
->load_from
, len
);
3507 if (wcschr( dll
->load_from
, '%' )) data
->flags
|= DLL_REDIRECT_PATH_EXPAND
;
3511 data
->size
= offsetof( struct dllredirect_data
, paths
[0] );
3512 data
->flags
= DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT
;
3513 data
->total_len
= 0;
3514 data
->paths_count
= 0;
3515 data
->paths_offset
= 0;
3517 name_offset
+= data
->size
+ data
->total_len
;
3525 return STATUS_SUCCESS
;
3528 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3530 struct string_index
*iter
, *index
= NULL
;
3534 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3535 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3537 for (i
= 0; i
< section
->count
; i
++)
3539 if (iter
->hash
== hash
)
3541 str
.Buffer
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3542 str
.Length
= iter
->name_len
;
3543 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3549 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3557 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3559 struct guid_index
*iter
, *index
= NULL
;
3562 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3564 for (i
= 0; i
< section
->count
; i
++)
3566 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3577 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3579 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3582 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3583 PACTCTX_SECTION_KEYED_DATA data
)
3585 struct dllredirect_data
*dll
;
3586 struct string_index
*index
;
3588 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3590 if (!actctx
->dllredirect_section
)
3592 struct strsection_header
*section
;
3594 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3595 if (status
) return status
;
3597 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3598 RtlFreeHeap(GetProcessHeap(), 0, section
);
3601 index
= find_string_index(actctx
->dllredirect_section
, name
);
3602 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3606 dll
= get_dllredirect_data(actctx
, index
);
3608 data
->ulDataFormatVersion
= 1;
3610 data
->ulLength
= dll
->size
;
3611 data
->lpSectionGlobalData
= NULL
;
3612 data
->ulSectionGlobalDataLength
= 0;
3613 data
->lpSectionBase
= actctx
->dllredirect_section
;
3614 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3615 data
->hActCtx
= NULL
;
3617 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3618 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3621 return STATUS_SUCCESS
;
3624 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3626 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3629 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3631 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3634 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3636 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3637 struct wndclass_redirect_data
*data
;
3638 struct strsection_header
*header
;
3639 struct string_index
*index
;
3642 /* compute section length */
3643 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3645 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3646 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3648 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3649 for (k
= 0; k
< dll
->entities
.num
; k
++)
3651 struct entity
*entity
= &dll
->entities
.base
[k
];
3652 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3654 int class_len
= wcslen(entity
->u
.class.name
) + 1;
3657 /* each class entry needs index, data and string data */
3658 total_len
+= sizeof(*index
);
3659 total_len
+= sizeof(*data
);
3660 /* original name is stored separately */
3661 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3662 /* versioned name and module name are stored one after another */
3663 if (entity
->u
.class.versioned
)
3664 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3667 len
+= wcslen(dll
->name
) + 1;
3668 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3676 total_len
+= sizeof(*header
);
3678 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3679 if (!header
) return STATUS_NO_MEMORY
;
3681 memset(header
, 0, sizeof(*header
));
3682 header
->magic
= STRSECTION_MAGIC
;
3683 header
->size
= sizeof(*header
);
3684 header
->count
= class_count
;
3685 header
->index_offset
= sizeof(*header
);
3686 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3687 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3689 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3691 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3692 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3694 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3695 for (k
= 0; k
< dll
->entities
.num
; k
++)
3697 struct entity
*entity
= &dll
->entities
.base
[k
];
3698 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3700 ULONG versioned_len
, module_len
;
3704 /* setup new index entry */
3705 str
.Buffer
= entity
->u
.class.name
;
3706 str
.Length
= wcslen(entity
->u
.class.name
)*sizeof(WCHAR
);
3707 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3708 /* hash original class name */
3709 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3711 /* include '!' separator too */
3712 if (entity
->u
.class.versioned
)
3713 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3715 versioned_len
= str
.Length
;
3716 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3718 index
->name_offset
= name_offset
;
3719 index
->name_len
= str
.Length
;
3720 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3721 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3722 index
->rosterindex
= i
+ 1;
3725 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3726 data
->size
= sizeof(*data
);
3728 data
->name_len
= versioned_len
;
3729 data
->name_offset
= sizeof(*data
);
3730 data
->module_len
= module_len
;
3731 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3733 /* original class name */
3734 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3735 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3736 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3739 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3740 memcpy(ptrW
, dll
->name
, data
->module_len
);
3741 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3743 /* versioned name */
3744 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3745 if (entity
->u
.class.versioned
)
3747 get_assembly_version(assembly
, ptrW
);
3749 wcscat(ptrW
, entity
->u
.class.name
);
3753 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3754 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3757 name_offset
+= sizeof(*data
);
3758 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3768 return STATUS_SUCCESS
;
3771 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3772 PACTCTX_SECTION_KEYED_DATA data
)
3774 struct string_index
*iter
, *index
= NULL
;
3775 struct wndclass_redirect_data
*class;
3780 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3782 if (!actctx
->wndclass_section
)
3784 struct strsection_header
*section
;
3786 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3787 if (status
) return status
;
3789 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3790 RtlFreeHeap(GetProcessHeap(), 0, section
);
3794 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3795 iter
= get_wndclass_first_index(actctx
);
3797 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3799 if (iter
->hash
== hash
)
3801 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3802 str
.Length
= iter
->name_len
;
3803 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3809 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3814 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3818 class = get_wndclass_data(actctx
, index
);
3820 data
->ulDataFormatVersion
= 1;
3821 data
->lpData
= class;
3822 /* full length includes string length with nulls */
3823 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3824 data
->lpSectionGlobalData
= NULL
;
3825 data
->ulSectionGlobalDataLength
= 0;
3826 data
->lpSectionBase
= actctx
->wndclass_section
;
3827 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3828 data
->hActCtx
= NULL
;
3830 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3831 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3834 return STATUS_SUCCESS
;
3837 static inline struct string_index
*get_activatable_class_first_index(ACTIVATION_CONTEXT
*actctx
)
3839 return (struct string_index
*)((BYTE
*)actctx
->activatable_class_section
+ actctx
->activatable_class_section
->index_offset
);
3842 static inline struct activatable_class_data
*get_activatable_class_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3844 return (struct activatable_class_data
*)((BYTE
*)ctxt
->activatable_class_section
+ index
->data_offset
);
3847 static NTSTATUS
build_activatable_class_section(ACTIVATION_CONTEXT
*actctx
, struct strsection_header
**section
)
3849 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0, global_offset
= 0, global_len
= 0;
3850 struct activatable_class_data
*data
;
3851 struct strsection_header
*header
;
3852 struct string_index
*index
;
3855 /* compute section length */
3856 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3858 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3859 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3861 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3862 BOOL has_class
= FALSE
;
3864 for (k
= 0; k
< dll
->entities
.num
; k
++)
3866 struct entity
*entity
= &dll
->entities
.base
[k
];
3867 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
3869 int class_len
= wcslen(entity
->u
.activatable_class
.name
) + 1;
3871 /* each class entry needs index, data and string data */
3872 total_len
+= sizeof(*index
);
3873 total_len
+= aligned_string_len(class_len
* sizeof(WCHAR
));
3874 total_len
+= sizeof(*data
);
3883 int module_len
= wcslen(dll
->name
) + 1;
3884 global_len
+= aligned_string_len(module_len
* sizeof(WCHAR
));
3889 total_len
+= sizeof(*header
) + global_len
;
3891 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3892 if (!header
) return STATUS_NO_MEMORY
;
3894 memset(header
, 0, sizeof(*header
));
3895 header
->magic
= STRSECTION_MAGIC
;
3896 header
->size
= sizeof(*header
);
3897 header
->count
= class_count
;
3898 header
->global_offset
= header
->size
;
3899 header
->global_len
= global_len
;
3900 header
->index_offset
= header
->global_offset
+ header
->global_len
;
3901 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3902 name_offset
= header
->index_offset
+ header
->count
* sizeof(*index
);
3904 global_offset
= header
->size
;
3905 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3907 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3908 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3910 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3911 int module_len
= wcslen(dll
->name
) * sizeof(WCHAR
);
3912 BOOL has_class
= FALSE
;
3914 for (k
= 0; k
< dll
->entities
.num
; k
++)
3916 struct entity
*entity
= &dll
->entities
.base
[k
];
3918 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
3923 /* setup new index entry */
3924 str
.Buffer
= entity
->u
.activatable_class
.name
;
3925 str
.Length
= wcslen(entity
->u
.activatable_class
.name
) * sizeof(WCHAR
);
3926 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3927 /* hash class name */
3928 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3930 index
->name_offset
= name_offset
;
3931 index
->name_len
= str
.Length
;
3932 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3933 index
->data_len
= sizeof(*data
);
3934 index
->rosterindex
= i
+ 1;
3937 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3938 memcpy(ptrW
, entity
->u
.activatable_class
.name
, index
->name_len
);
3939 ptrW
[index
->name_len
/ sizeof(WCHAR
)] = 0;
3942 data
= (struct activatable_class_data
*)((BYTE
*)header
+ index
->data_offset
);
3943 data
->size
= sizeof(*data
);
3944 data
->threading_model
= entity
->u
.activatable_class
.threading_model
;
3945 data
->module_len
= module_len
;
3946 data
->module_offset
= global_offset
;
3948 name_offset
+= aligned_string_len(str
.MaximumLength
);
3949 name_offset
+= sizeof(*data
);
3958 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)header
+ global_offset
);
3959 memcpy(ptrW
, dll
->name
, module_len
);
3960 ptrW
[module_len
/ sizeof(WCHAR
)] = 0;
3961 global_offset
+= aligned_string_len(module_len
+ sizeof(WCHAR
));
3968 return STATUS_SUCCESS
;
3971 static NTSTATUS
find_activatable_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3972 PACTCTX_SECTION_KEYED_DATA data
)
3974 struct string_index
*iter
, *index
= NULL
;
3975 struct activatable_class_data
*class;
3980 if (!(actctx
->sections
& ACTIVATABLE_CLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3982 if (!actctx
->activatable_class_section
)
3984 struct strsection_header
*section
;
3986 NTSTATUS status
= build_activatable_class_section(actctx
, §ion
);
3987 if (status
) return status
;
3989 if (InterlockedCompareExchangePointer((void**)&actctx
->activatable_class_section
, section
, NULL
))
3990 RtlFreeHeap(GetProcessHeap(), 0, section
);
3994 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3995 iter
= get_activatable_class_first_index(actctx
);
3997 for (i
= 0; i
< actctx
->activatable_class_section
->count
; i
++)
3999 if (iter
->hash
== hash
)
4001 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->activatable_class_section
+ iter
->name_offset
);
4002 str
.Length
= iter
->name_len
;
4003 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
4009 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
4014 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4018 class = get_activatable_class_data(actctx
, index
);
4020 data
->ulDataFormatVersion
= 1;
4021 data
->lpData
= class;
4022 /* full length includes string length with nulls */
4023 data
->ulLength
= class->size
+ class->module_len
+ sizeof(WCHAR
);
4024 data
->lpSectionGlobalData
= (BYTE
*)actctx
->activatable_class_section
+ actctx
->activatable_class_section
->global_offset
;
4025 data
->ulSectionGlobalDataLength
= actctx
->activatable_class_section
->global_len
;
4026 data
->lpSectionBase
= actctx
->activatable_class_section
;
4027 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->activatable_class_section
);
4028 data
->hActCtx
= NULL
;
4030 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4031 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4034 return STATUS_SUCCESS
;
4037 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4039 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
4040 struct guidsection_header
*header
;
4041 ULONG module_offset
, data_offset
;
4042 struct tlibredirect_data
*data
;
4043 struct guid_index
*index
;
4045 /* compute section length */
4046 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4048 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4049 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4051 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4052 for (k
= 0; k
< dll
->entities
.num
; k
++)
4054 struct entity
*entity
= &dll
->entities
.base
[k
];
4055 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
4057 /* each entry needs index, data and string data for module name and help string */
4058 total_len
+= sizeof(*index
);
4059 total_len
+= sizeof(*data
);
4060 /* help string is stored separately */
4061 if (*entity
->u
.typelib
.helpdir
)
4062 total_len
+= aligned_string_len((wcslen(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
4064 /* module names are packed one after another */
4065 names_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
4073 total_len
+= aligned_string_len(names_len
);
4074 total_len
+= sizeof(*header
);
4076 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4077 if (!header
) return STATUS_NO_MEMORY
;
4079 memset(header
, 0, sizeof(*header
));
4080 header
->magic
= GUIDSECTION_MAGIC
;
4081 header
->size
= sizeof(*header
);
4082 header
->count
= tlib_count
;
4083 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4084 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4085 module_offset
= sizeof(*header
);
4086 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
4088 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4090 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4091 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4093 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4094 for (k
= 0; k
< dll
->entities
.num
; k
++)
4096 struct entity
*entity
= &dll
->entities
.base
[k
];
4097 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
4099 ULONG module_len
, help_len
;
4103 if (*entity
->u
.typelib
.helpdir
)
4104 help_len
= wcslen(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
4108 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
4110 /* setup new index entry */
4111 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
4112 RtlGUIDFromString(&str
, &index
->guid
);
4113 index
->data_offset
= data_offset
;
4114 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
4115 index
->rosterindex
= i
+ 1;
4118 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
4119 data
->size
= sizeof(*data
);
4121 data
->name_len
= module_len
;
4122 data
->name_offset
= module_offset
;
4123 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
4125 data
->flags
= entity
->u
.typelib
.flags
;
4126 data
->help_len
= help_len
;
4127 data
->help_offset
= sizeof(*data
);
4128 data
->major_version
= entity
->u
.typelib
.major
;
4129 data
->minor_version
= entity
->u
.typelib
.minor
;
4132 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
4133 memcpy(ptrW
, dll
->name
, data
->name_len
);
4134 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4139 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
4140 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
4141 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
4144 data_offset
+= sizeof(*data
);
4146 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
4148 module_offset
+= module_len
+ sizeof(WCHAR
);
4158 return STATUS_SUCCESS
;
4161 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4163 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
4166 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4168 struct guid_index
*index
= NULL
;
4169 struct tlibredirect_data
*tlib
;
4171 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4173 if (!actctx
->tlib_section
)
4175 struct guidsection_header
*section
;
4177 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
4178 if (status
) return status
;
4180 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
4181 RtlFreeHeap(GetProcessHeap(), 0, section
);
4184 index
= find_guid_index(actctx
->tlib_section
, guid
);
4185 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4187 tlib
= get_tlib_data(actctx
, index
);
4189 data
->ulDataFormatVersion
= 1;
4190 data
->lpData
= tlib
;
4191 /* full length includes string length with nulls */
4192 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
4193 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
4194 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
4195 data
->lpSectionBase
= actctx
->tlib_section
;
4196 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
4197 data
->hActCtx
= NULL
;
4199 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4200 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4202 return STATUS_SUCCESS
;
4205 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
4207 ULONG
*ptr
= (ULONG
*)guid
;
4210 /* GUID is 16 bytes long */
4211 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
4212 *ptr
= RtlUniform(seed
);
4214 guid
->Data3
&= 0x0fff;
4215 guid
->Data3
|= (4 << 12);
4216 guid
->Data4
[0] &= 0x3f;
4217 guid
->Data4
[0] |= 0x80;
4220 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
4221 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
4225 for (i
= 0; i
< entities
->num
; i
++)
4227 struct entity
*entity
= &entities
->base
[i
];
4228 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4230 /* each entry needs two index entries, extra one goes for alias GUID */
4231 *len
+= 2*sizeof(struct guid_index
);
4232 /* To save some memory we don't allocated two data structures,
4233 instead alias index and normal index point to the same data structure. */
4234 *len
+= sizeof(struct comclassredirect_data
);
4236 /* for clrClass store some more */
4237 if (entity
->u
.comclass
.name
)
4239 unsigned int str_len
;
4241 /* all string data is stored together in aligned block */
4242 str_len
= wcslen(entity
->u
.comclass
.name
)+1;
4243 if (entity
->u
.comclass
.progid
)
4244 str_len
+= wcslen(entity
->u
.comclass
.progid
)+1;
4245 if (entity
->u
.comclass
.version
)
4246 str_len
+= wcslen(entity
->u
.comclass
.version
)+1;
4248 *len
+= sizeof(struct clrclass_data
);
4249 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
4251 /* module name is forced to mscoree.dll, and stored two times with different case */
4252 *module_len
+= sizeof(L
"MSCOREE.DLL") + sizeof(L
"mscoree.dll");
4256 /* progid string is stored separately */
4257 if (entity
->u
.comclass
.progid
)
4258 *len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4260 *module_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
4268 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4269 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4270 ULONG
*seed
, ULONG rosterindex
)
4274 for (i
= 0; i
< entities
->num
; i
++)
4276 struct entity
*entity
= &entities
->base
[i
];
4277 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4279 ULONG module_len
, progid_len
, str_len
= 0, miscmask
;
4280 struct comclassredirect_data
*data
;
4281 struct guid_index
*alias_index
;
4282 struct clrclass_data
*clrdata
;
4286 if (entity
->u
.comclass
.progid
)
4287 progid_len
= wcslen(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4291 module_len
= dll
? wcslen(dll
->name
)*sizeof(WCHAR
) : wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
4293 /* setup new index entry */
4294 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4295 RtlGUIDFromString(&str
, &(*index
)->guid
);
4297 (*index
)->data_offset
= *data_offset
;
4298 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4299 (*index
)->rosterindex
= rosterindex
;
4301 /* Setup new index entry for alias guid. Alias index records are placed after
4302 normal records, so normal guids are hit first on search. Note that class count
4304 alias_index
= (*index
) + section
->count
/2;
4305 generate_uuid(seed
, &alias_index
->guid
);
4306 alias_index
->data_offset
= (*index
)->data_offset
;
4307 alias_index
->data_len
= 0;
4308 alias_index
->rosterindex
= (*index
)->rosterindex
;
4311 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4312 data
->size
= sizeof(*data
);
4313 data
->model
= entity
->u
.comclass
.model
;
4314 data
->clsid
= (*index
)->guid
;
4315 data
->alias
= alias_index
->guid
;
4316 data
->clsid2
= data
->clsid
;
4317 if (entity
->u
.comclass
.tlbid
)
4319 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4320 RtlGUIDFromString(&str
, &data
->tlbid
);
4323 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4324 data
->name_len
= module_len
;
4325 data
->name_offset
= *module_offset
;
4326 data
->progid_len
= progid_len
;
4327 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4328 data
->clrdata_len
= 0; /* will be set later */
4329 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4330 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4331 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4332 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4333 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4334 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4336 /* mask describes which misc* data is available */
4338 if (data
->miscstatus
)
4339 miscmask
|= MiscStatus
;
4340 if (data
->miscstatuscontent
)
4341 miscmask
|= MiscStatusContent
;
4342 if (data
->miscstatusthumbnail
)
4343 miscmask
|= MiscStatusThumbnail
;
4344 if (data
->miscstatusicon
)
4345 miscmask
|= MiscStatusIcon
;
4346 if (data
->miscstatusdocprint
)
4347 miscmask
|= MiscStatusDocPrint
;
4348 data
->flags
= miscmask
<< 8;
4350 if (data
->clrdata_offset
)
4352 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4354 clrdata
->size
= sizeof(*clrdata
);
4355 clrdata
->res
[0] = 0;
4356 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4357 clrdata
->module_len
= wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
4358 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4359 clrdata
->name_len
= wcslen(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4360 clrdata
->name_offset
= clrdata
->size
;
4361 clrdata
->version_len
= entity
->u
.comclass
.version
? wcslen(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4362 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4363 clrdata
->res2
[0] = 0;
4364 clrdata
->res2
[1] = 0;
4366 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4369 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4370 memcpy(ptrW
, L
"mscoree.dll", clrdata
->module_len
);
4371 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4373 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4374 memcpy(ptrW
, L
"MSCOREE.DLL", data
->name_len
);
4375 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4378 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4379 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4380 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4382 /* runtime version, optional */
4383 if (clrdata
->version_len
)
4385 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4387 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4388 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4389 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4392 if (data
->progid_len
)
4393 data
->progid_offset
+= data
->clrdata_len
;
4394 (*index
)->data_len
+= sizeof(*clrdata
);
4401 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4402 memcpy(ptrW
, dll
->name
, data
->name_len
);
4403 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4407 if (data
->progid_len
)
4409 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4410 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4411 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4414 /* string block length */
4418 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4419 if (clrdata
->version_len
)
4420 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4423 str_len
+= progid_len
+ sizeof(WCHAR
);
4425 (*index
)->data_len
+= aligned_string_len(str_len
);
4426 alias_index
->data_len
= (*index
)->data_len
;
4428 /* move to next data record */
4429 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4430 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4434 (*data_offset
) += sizeof(*clrdata
);
4435 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4442 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4444 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4445 struct guidsection_header
*header
;
4446 ULONG module_offset
, data_offset
;
4447 struct guid_index
*index
;
4450 /* compute section length */
4451 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4453 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4454 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4455 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4457 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4458 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4462 total_len
+= aligned_string_len(names_len
);
4463 total_len
+= sizeof(*header
);
4465 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4466 if (!header
) return STATUS_NO_MEMORY
;
4468 memset(header
, 0, sizeof(*header
));
4469 header
->magic
= GUIDSECTION_MAGIC
;
4470 header
->size
= sizeof(*header
);
4471 header
->count
= 2*class_count
;
4472 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4473 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4474 module_offset
= sizeof(*header
);
4475 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4477 seed
= NtGetTickCount();
4478 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4480 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4481 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4482 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4484 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4485 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4491 return STATUS_SUCCESS
;
4494 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4496 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4499 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4501 struct comclassredirect_data
*comclass
;
4502 struct guid_index
*index
= NULL
;
4504 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4506 if (!actctx
->comserver_section
)
4508 struct guidsection_header
*section
;
4510 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4511 if (status
) return status
;
4513 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4514 RtlFreeHeap(GetProcessHeap(), 0, section
);
4517 index
= find_guid_index(actctx
->comserver_section
, guid
);
4518 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4520 comclass
= get_comclass_data(actctx
, index
);
4522 data
->ulDataFormatVersion
= 1;
4523 data
->lpData
= comclass
;
4524 /* full length includes string length with nulls */
4525 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4526 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4527 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4528 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4529 data
->lpSectionBase
= actctx
->comserver_section
;
4530 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4531 data
->hActCtx
= NULL
;
4533 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4534 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4536 return STATUS_SUCCESS
;
4539 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4543 for (i
= 0; i
< entities
->num
; i
++)
4545 struct entity
*entity
= &entities
->base
[i
];
4546 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4548 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4549 if (entity
->u
.ifaceps
.name
)
4550 *len
+= aligned_string_len((wcslen(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4556 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4557 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4561 for (i
= 0; i
< entities
->num
; i
++)
4563 struct entity
*entity
= &entities
->base
[i
];
4564 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4566 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4570 if (entity
->u
.ifaceps
.name
)
4571 name_len
= wcslen(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4576 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4577 RtlGUIDFromString(&str
, &(*index
)->guid
);
4578 (*index
)->data_offset
= *data_offset
;
4579 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4580 (*index
)->rosterindex
= rosterindex
;
4582 /* setup data record */
4583 data
->size
= sizeof(*data
);
4584 data
->mask
= entity
->u
.ifaceps
.mask
;
4586 /* proxyStubClsid32 value is only stored for external PS,
4587 if set it's used as iid, otherwise 'iid' attribute value is used */
4588 if (entity
->u
.ifaceps
.ps32
)
4590 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4591 RtlGUIDFromString(&str
, &data
->iid
);
4594 data
->iid
= (*index
)->guid
;
4596 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4598 if (entity
->u
.ifaceps
.tlib
)
4600 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4601 RtlGUIDFromString(&str
, &data
->tlbid
);
4604 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4606 if (entity
->u
.ifaceps
.base
)
4608 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4609 RtlGUIDFromString(&str
, &data
->base
);
4612 memset(&data
->base
, 0, sizeof(data
->base
));
4614 data
->name_len
= name_len
;
4615 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4620 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4621 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4622 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4625 /* move to next record */
4627 *data_offset
+= sizeof(*data
);
4629 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4634 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4636 unsigned int i
, j
, total_len
= 0, count
= 0;
4637 struct guidsection_header
*header
;
4638 struct guid_index
*index
;
4641 /* compute section length */
4642 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4644 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4646 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4647 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4649 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4650 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4654 total_len
+= sizeof(*header
);
4656 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4657 if (!header
) return STATUS_NO_MEMORY
;
4659 memset(header
, 0, sizeof(*header
));
4660 header
->magic
= GUIDSECTION_MAGIC
;
4661 header
->size
= sizeof(*header
);
4662 header
->count
= count
;
4663 header
->index_offset
= sizeof(*header
);
4664 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4665 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4667 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4669 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4671 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4672 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4674 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4675 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4681 return STATUS_SUCCESS
;
4684 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4686 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4689 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4691 struct ifacepsredirect_data
*iface
;
4692 struct guid_index
*index
= NULL
;
4694 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4696 if (!actctx
->ifaceps_section
)
4698 struct guidsection_header
*section
;
4700 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4701 if (status
) return status
;
4703 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4704 RtlFreeHeap(GetProcessHeap(), 0, section
);
4707 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4708 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4710 iface
= get_ifaceps_data(actctx
, index
);
4712 data
->ulDataFormatVersion
= 1;
4713 data
->lpData
= iface
;
4714 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4715 data
->lpSectionGlobalData
= NULL
;
4716 data
->ulSectionGlobalDataLength
= 0;
4717 data
->lpSectionBase
= actctx
->ifaceps_section
;
4718 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4719 data
->hActCtx
= NULL
;
4721 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4722 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4724 return STATUS_SUCCESS
;
4727 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4729 unsigned int i
, j
, total_len
= 0, count
= 0;
4730 struct guidsection_header
*header
;
4731 struct clrsurrogate_data
*data
;
4732 struct guid_index
*index
;
4735 /* compute section length */
4736 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4738 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4739 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4741 struct entity
*entity
= &assembly
->entities
.base
[j
];
4742 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4746 total_len
+= sizeof(*index
) + sizeof(*data
);
4747 len
= wcslen(entity
->u
.clrsurrogate
.name
) + 1;
4748 if (entity
->u
.clrsurrogate
.version
)
4749 len
+= wcslen(entity
->u
.clrsurrogate
.version
) + 1;
4750 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4757 total_len
+= sizeof(*header
);
4759 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4760 if (!header
) return STATUS_NO_MEMORY
;
4762 memset(header
, 0, sizeof(*header
));
4763 header
->magic
= GUIDSECTION_MAGIC
;
4764 header
->size
= sizeof(*header
);
4765 header
->count
= count
;
4766 header
->index_offset
= sizeof(*header
);
4767 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4768 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4770 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4772 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4773 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4775 struct entity
*entity
= &assembly
->entities
.base
[j
];
4776 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4778 ULONG version_len
, name_len
;
4782 if (entity
->u
.clrsurrogate
.version
)
4783 version_len
= wcslen(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4786 name_len
= wcslen(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4788 /* setup new index entry */
4789 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4790 RtlGUIDFromString(&str
, &index
->guid
);
4792 index
->data_offset
= data_offset
;
4793 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4794 index
->rosterindex
= i
+ 1;
4797 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4798 data
->size
= sizeof(*data
);
4800 data
->clsid
= index
->guid
;
4801 data
->version_offset
= version_len
? data
->size
: 0;
4802 data
->version_len
= version_len
;
4803 data
->name_offset
= data
->size
+ version_len
;
4805 data
->name_offset
+= sizeof(WCHAR
);
4806 data
->name_len
= name_len
;
4808 /* surrogate name */
4809 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4810 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4811 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4813 /* runtime version */
4814 if (data
->version_len
)
4816 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4817 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4818 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4821 data_offset
+= index
->data_offset
;
4829 return STATUS_SUCCESS
;
4832 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4834 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4837 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4839 struct clrsurrogate_data
*surrogate
;
4840 struct guid_index
*index
= NULL
;
4842 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4844 if (!actctx
->clrsurrogate_section
)
4846 struct guidsection_header
*section
;
4848 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4849 if (status
) return status
;
4851 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4852 RtlFreeHeap(GetProcessHeap(), 0, section
);
4855 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4856 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4858 surrogate
= get_surrogate_data(actctx
, index
);
4860 data
->ulDataFormatVersion
= 1;
4861 data
->lpData
= surrogate
;
4862 /* full length includes string length with nulls */
4863 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4864 if (surrogate
->version_len
)
4865 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4867 data
->lpSectionGlobalData
= NULL
;
4868 data
->ulSectionGlobalDataLength
= 0;
4869 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4870 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4871 data
->hActCtx
= NULL
;
4873 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4874 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4876 return STATUS_SUCCESS
;
4879 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4881 unsigned int i
, j
, single_len
;
4883 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4884 for (i
= 0; i
< entities
->num
; i
++)
4886 struct entity
*entity
= &entities
->base
[i
];
4887 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4889 if (entity
->u
.comclass
.progid
)
4891 *total_len
+= single_len
+ aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4895 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4896 *total_len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4898 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4899 *count
+= entity
->u
.comclass
.progids
.num
;
4904 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4905 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4907 struct progidredirect_data
*data
;
4912 /* setup new index entry */
4914 /* hash progid name */
4915 RtlInitUnicodeString(&str
, progid
);
4916 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4918 (*index
)->name_offset
= *data_offset
;
4919 (*index
)->name_len
= str
.Length
;
4920 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4921 (*index
)->data_len
= sizeof(*data
);
4922 (*index
)->rosterindex
= rosterindex
;
4924 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4926 /* setup data structure */
4927 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4928 data
->size
= sizeof(*data
);
4930 data
->clsid_offset
= *global_offset
;
4932 /* write progid string */
4933 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4934 memcpy(ptrW
, progid
, (*index
)->name_len
);
4935 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4937 /* write guid to global area */
4938 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4942 *global_offset
+= sizeof(GUID
);
4943 *data_offset
+= data
->size
;
4947 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4948 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4952 for (i
= 0; i
< entities
->num
; i
++)
4954 struct entity
*entity
= &entities
->base
[i
];
4955 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4957 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4958 struct comclassredirect_data
*comclass
;
4959 struct guid_index
*guid_index
;
4963 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4964 RtlGUIDFromString(&str
, &clsid
);
4966 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4967 comclass
= get_comclass_data(actctx
, guid_index
);
4969 if (entity
->u
.comclass
.progid
)
4970 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4971 index
, data_offset
, global_offset
, rosterindex
);
4973 for (j
= 0; j
< progids
->num
; j
++)
4974 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4975 index
, data_offset
, global_offset
, rosterindex
);
4980 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4982 unsigned int i
, j
, total_len
= 0, count
= 0;
4983 struct strsection_header
*header
;
4984 ULONG data_offset
, global_offset
;
4985 struct string_index
*index
;
4987 /* compute section length */
4988 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4990 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4992 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4993 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4995 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4996 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
5000 total_len
+= sizeof(*header
);
5002 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
5003 if (!header
) return STATUS_NO_MEMORY
;
5005 memset(header
, 0, sizeof(*header
));
5006 header
->magic
= STRSECTION_MAGIC
;
5007 header
->size
= sizeof(*header
);
5008 header
->count
= count
;
5009 header
->global_offset
= header
->size
;
5010 header
->global_len
= count
*sizeof(GUID
);
5011 header
->index_offset
= header
->size
+ header
->global_len
;
5013 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
5014 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
5015 global_offset
= header
->global_offset
;
5017 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
5019 struct assembly
*assembly
= &actctx
->assemblies
[i
];
5021 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
5022 for (j
= 0; j
< assembly
->num_dlls
; j
++)
5024 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
5025 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
5031 return STATUS_SUCCESS
;
5034 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
5036 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
5039 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
5040 PACTCTX_SECTION_KEYED_DATA data
)
5042 struct progidredirect_data
*progid
;
5043 struct string_index
*index
;
5045 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
5047 if (!actctx
->comserver_section
)
5049 struct guidsection_header
*section
;
5051 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
5052 if (status
) return status
;
5054 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
5055 RtlFreeHeap(GetProcessHeap(), 0, section
);
5058 if (!actctx
->progid_section
)
5060 struct strsection_header
*section
;
5062 NTSTATUS status
= build_progid_section(actctx
, §ion
);
5063 if (status
) return status
;
5065 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
5066 RtlFreeHeap(GetProcessHeap(), 0, section
);
5069 index
= find_string_index(actctx
->progid_section
, name
);
5070 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
5074 progid
= get_progid_data(actctx
, index
);
5076 data
->ulDataFormatVersion
= 1;
5077 data
->lpData
= progid
;
5078 data
->ulLength
= progid
->size
;
5079 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
5080 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
5081 data
->lpSectionBase
= actctx
->progid_section
;
5082 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
5083 data
->hActCtx
= NULL
;
5085 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
5086 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
5089 return STATUS_SUCCESS
;
5092 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
5093 const UNICODE_STRING
*section_name
,
5094 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
5098 switch (section_kind
)
5100 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
5101 status
= find_dll_redirection(actctx
, section_name
, data
);
5103 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
5104 status
= find_window_class(actctx
, section_name
, data
);
5106 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
5107 status
= find_progid_redirection(actctx
, section_name
, data
);
5109 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
5110 FIXME("Unsupported yet section_kind %lx\n", section_kind
);
5111 return STATUS_SXS_SECTION_NOT_FOUND
;
5112 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
:
5113 status
= find_activatable_class(actctx
, section_name
, data
);
5116 WARN("Unknown section_kind %lx\n", section_kind
);
5117 return STATUS_SXS_SECTION_NOT_FOUND
;
5120 if (status
!= STATUS_SUCCESS
) return status
;
5122 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
5124 actctx_addref(actctx
);
5125 data
->hActCtx
= actctx
;
5127 return STATUS_SUCCESS
;
5130 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
5131 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
5135 switch (section_kind
)
5137 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
5138 status
= find_tlib_redirection(actctx
, guid
, data
);
5140 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
5141 status
= find_comserver_redirection(actctx
, guid
, data
);
5143 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
5144 status
= find_cominterface_redirection(actctx
, guid
, data
);
5146 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
5147 status
= find_clr_surrogate(actctx
, guid
, data
);
5150 WARN("Unknown section_kind %lx\n", section_kind
);
5151 return STATUS_SXS_SECTION_NOT_FOUND
;
5154 if (status
!= STATUS_SUCCESS
) return status
;
5156 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5158 actctx_addref(actctx
);
5159 data
->hActCtx
= actctx
;
5161 return STATUS_SUCCESS
;
5164 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
5168 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
5170 struct assembly
*assembly
= &actctx
->assemblies
[i
];
5171 for (j
= 0; j
< assembly
->entities
.num
; j
++)
5173 struct entity
*entity
= &assembly
->entities
.base
[j
];
5174 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
5175 !wcscmp( entity
->u
.settings
.name
, settings
) &&
5176 !wcscmp( entity
->u
.settings
.ns
, ns
))
5177 return entity
->u
.settings
.value
;
5183 /* initialize the activation context for the current process */
5184 void actctx_init(void)
5189 ctx
.cbSize
= sizeof(ctx
);
5190 ctx
.lpSource
= NULL
;
5191 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
5192 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
5193 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
5195 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
5197 NtCurrentTeb()->Peb
->ActivationContextData
= process_actctx
;
5201 /***********************************************************************
5202 * RtlCreateActivationContext (NTDLL.@)
5204 * Create an activation context.
5206 * FIXME: function signature/prototype is wrong
5208 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
5210 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
5211 const WCHAR
*directory
= NULL
;
5212 ACTIVATION_CONTEXT
*actctx
;
5213 UNICODE_STRING nameW
;
5215 NTSTATUS status
= STATUS_NO_MEMORY
;
5217 struct actctx_loader acl
;
5219 TRACE("%p %08lx\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
5221 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
5222 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
5223 return STATUS_INVALID_PARAMETER
;
5225 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
5226 return STATUS_NO_MEMORY
;
5228 actctx
->magic
= ACTCTX_MAGIC
;
5229 actctx
->ref_count
= 1;
5230 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
5231 actctx
->config
.info
= NULL
;
5232 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
5233 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
5235 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
5243 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
5244 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
5246 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
5247 if ((p
= wcsrchr( dir
.Buffer
, '\\' ))) p
[1] = 0;
5248 actctx
->appdir
.info
= dir
.Buffer
;
5251 nameW
.Buffer
= NULL
;
5253 /* open file only if it's going to be used */
5254 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
5255 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
5257 WCHAR
*source
= NULL
;
5260 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5261 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
5263 DWORD dir_len
, source_len
;
5265 dir_len
= wcslen(pActCtx
->lpAssemblyDirectory
);
5266 source_len
= wcslen(pActCtx
->lpSource
);
5267 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5269 status
= STATUS_NO_MEMORY
;
5273 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5274 source
[dir_len
] = '\\';
5275 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5278 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5279 RtlFreeHeap( GetProcessHeap(), 0, source
);
5282 status
= STATUS_NO_SUCH_FILE
;
5285 status
= open_nt_file( &file
, &nameW
);
5288 RtlFreeUnicodeString( &nameW
);
5293 acl
.actctx
= actctx
;
5294 acl
.dependencies
= NULL
;
5295 acl
.num_dependencies
= 0;
5296 acl
.allocated_dependencies
= 0;
5298 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5299 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5301 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5303 /* if we have a resource it's a PE file */
5304 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5306 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5307 pActCtx
->lpResourceName
, lang
);
5308 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5309 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5310 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5312 else if (pActCtx
->lpSource
)
5314 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5315 file
, pActCtx
->lpResourceName
, lang
);
5316 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5317 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5318 NULL
, pActCtx
->lpResourceName
);
5320 else status
= STATUS_INVALID_PARAMETER
;
5324 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5327 if (file
) NtClose( file
);
5328 RtlFreeUnicodeString( &nameW
);
5330 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
5331 free_depend_manifests( &acl
);
5333 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
5334 else actctx_release( actctx
);
5338 if (file
) NtClose( file
);
5339 actctx_release( actctx
);
5344 /***********************************************************************
5345 * RtlAddRefActivationContext (NTDLL.@)
5347 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
5349 ACTIVATION_CONTEXT
*actctx
;
5351 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5355 /******************************************************************
5356 * RtlReleaseActivationContext (NTDLL.@)
5358 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5360 ACTIVATION_CONTEXT
*actctx
;
5362 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5365 /******************************************************************
5366 * RtlZombifyActivationContext (NTDLL.@)
5368 * FIXME: function prototype might be wrong
5370 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5372 FIXME("%p: stub\n", handle
);
5373 return STATUS_NOT_IMPLEMENTED
;
5376 /******************************************************************
5377 * RtlActivateActivationContext (NTDLL.@)
5379 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5381 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle
, cookie
);
5385 /******************************************************************
5386 * RtlActivateActivationContextEx (NTDLL.@)
5388 NTSTATUS WINAPI
RtlActivateActivationContextEx( ULONG flags
, TEB
*teb
, HANDLE handle
, ULONG_PTR
*cookie
)
5390 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5392 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5393 return STATUS_NO_MEMORY
;
5395 frame
->Previous
= teb
->ActivationContextStack
.ActiveFrame
;
5396 frame
->ActivationContext
= handle
;
5398 teb
->ActivationContextStack
.ActiveFrame
= frame
;
5399 RtlAddRefActivationContext( handle
);
5401 *cookie
= (ULONG_PTR
)frame
;
5402 TRACE( "%p cookie=%Ix\n", handle
, *cookie
);
5403 return STATUS_SUCCESS
;
5407 /***********************************************************************
5408 * RtlDeactivateActivationContext (NTDLL.@)
5410 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5412 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5414 TRACE( "%lx cookie=%Ix\n", flags
, cookie
);
5416 /* find the right frame */
5417 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5418 for (frame
= top
; frame
; frame
= frame
->Previous
)
5419 if ((ULONG_PTR
)frame
== cookie
) break;
5422 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5424 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5425 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5427 /* pop everything up to and including frame */
5428 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5430 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5432 frame
= top
->Previous
;
5433 RtlReleaseActivationContext( top
->ActivationContext
);
5434 RtlFreeHeap( GetProcessHeap(), 0, top
);
5440 /******************************************************************
5441 * RtlFreeThreadActivationContextStack (NTDLL.@)
5443 void WINAPI
RtlFreeThreadActivationContextStack(void)
5445 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5447 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5450 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5451 RtlReleaseActivationContext( frame
->ActivationContext
);
5452 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5455 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5459 /******************************************************************
5460 * RtlGetActiveActivationContext (NTDLL.@)
5462 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5464 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5466 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5467 RtlAddRefActivationContext( *handle
);
5472 return STATUS_SUCCESS
;
5476 /******************************************************************
5477 * RtlIsActivationContextActive (NTDLL.@)
5479 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5481 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5483 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5484 if (frame
->ActivationContext
== handle
) return TRUE
;
5489 /***********************************************************************
5490 * RtlQueryInformationActivationContext (NTDLL.@)
5492 * Get information about an activation context.
5493 * FIXME: function signature/prototype may be wrong
5495 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5496 ULONG
class, PVOID buffer
,
5497 SIZE_T bufsize
, SIZE_T
*retlen
)
5499 ACTIVATION_CONTEXT
*actctx
;
5502 TRACE("%08lx %p %p %lu %p %Id %p\n", flags
, handle
,
5503 subinst
, class, buffer
, bufsize
, retlen
);
5505 if (retlen
) *retlen
= 0;
5506 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5510 case ActivationContextBasicInformation
:
5512 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5514 if (retlen
) *retlen
= sizeof(*info
);
5515 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5517 info
->hActCtx
= handle
;
5518 info
->dwFlags
= 0; /* FIXME */
5519 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5523 case ActivationContextDetailedInformation
:
5525 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5526 struct assembly
*assembly
= NULL
;
5527 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5530 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5532 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5534 if (assembly
&& assembly
->manifest
.info
)
5535 manifest_len
= wcslen(assembly
->manifest
.info
) + 1;
5536 if (actctx
->config
.info
) config_len
= wcslen(actctx
->config
.info
) + 1;
5537 if (actctx
->appdir
.info
) appdir_len
= wcslen(actctx
->appdir
.info
) + 1;
5538 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5540 if (retlen
) *retlen
= len
;
5541 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5544 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5545 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5546 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5547 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5548 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5549 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5550 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5551 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5552 ptr
= (LPWSTR
)(acdi
+ 1);
5555 acdi
->lpRootManifestPath
= ptr
;
5556 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5557 ptr
+= manifest_len
;
5559 else acdi
->lpRootManifestPath
= NULL
;
5562 acdi
->lpRootConfigurationPath
= ptr
;
5563 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5566 else acdi
->lpRootConfigurationPath
= NULL
;
5569 acdi
->lpAppDirPath
= ptr
;
5570 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5572 else acdi
->lpAppDirPath
= NULL
;
5576 case AssemblyDetailedInformationInActivationContext
:
5578 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5579 struct assembly
*assembly
;
5582 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5585 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5586 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5588 index
= *(DWORD
*)subinst
;
5589 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5591 assembly
= &actctx
->assemblies
[index
- 1];
5593 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5594 id_len
= wcslen(assembly_id
) + 1;
5595 if (assembly
->directory
) ad_len
= wcslen(assembly
->directory
) + 1;
5597 if (assembly
->manifest
.info
&&
5598 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5599 path_len
= wcslen(assembly
->manifest
.info
) + 1;
5601 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5603 if (retlen
) *retlen
= len
;
5604 if (!buffer
|| bufsize
< len
)
5606 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5607 return STATUS_BUFFER_TOO_SMALL
;
5610 afdi
->ulFlags
= 0; /* FIXME */
5611 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5612 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5613 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5614 /* FIXME afdi->liManifestLastWriteTime = 0; */
5615 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5616 afdi
->ulPolicyPathLength
= 0;
5617 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5618 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5619 afdi
->ulManifestVersionMajor
= 1;
5620 afdi
->ulManifestVersionMinor
= 0;
5621 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5622 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5623 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5624 ptr
= (LPWSTR
)(afdi
+ 1);
5625 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5626 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5630 afdi
->lpAssemblyManifestPath
= ptr
;
5631 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5633 } else afdi
->lpAssemblyManifestPath
= NULL
;
5634 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5637 afdi
->lpAssemblyDirectoryName
= ptr
;
5638 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5640 else afdi
->lpAssemblyDirectoryName
= NULL
;
5641 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5645 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5647 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5648 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5649 struct assembly
*assembly
;
5650 struct dll_redirect
*dll
;
5651 SIZE_T len
, dll_len
= 0;
5654 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5655 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5657 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5658 return STATUS_INVALID_PARAMETER
;
5659 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5661 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5662 return STATUS_INVALID_PARAMETER
;
5663 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5665 if (dll
->name
) dll_len
= wcslen(dll
->name
) + 1;
5666 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5668 if (!buffer
|| bufsize
< len
)
5670 if (retlen
) *retlen
= len
;
5671 return STATUS_BUFFER_TOO_SMALL
;
5673 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5674 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5675 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5676 afdi
->ulPathLength
= 0; /* FIXME */
5677 ptr
= (LPWSTR
)(afdi
+ 1);
5680 afdi
->lpFileName
= ptr
;
5681 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5682 } else afdi
->lpFileName
= NULL
;
5683 afdi
->lpFilePath
= NULL
; /* FIXME */
5687 case CompatibilityInformationInActivationContext
:
5692 COMPATIBILITY_CONTEXT_ELEMENT Elements
[1];
5694 struct assembly
*assembly
= NULL
;
5695 ULONG num_compat_contexts
= 0, n
;
5698 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5700 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5703 num_compat_contexts
= assembly
->num_compat_contexts
;
5704 len
= offsetof( struct acci
, Elements
[num_compat_contexts
] );
5706 if (retlen
) *retlen
= len
;
5707 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5709 acci
->ElementCount
= num_compat_contexts
;
5710 for (n
= 0; n
< num_compat_contexts
; ++n
)
5712 acci
->Elements
[n
] = assembly
->compat_contexts
[n
];
5717 case RunlevelInformationInActivationContext
:
5719 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5720 struct assembly
*assembly
;
5723 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5725 len
= sizeof(*acrli
);
5726 if (retlen
) *retlen
= len
;
5727 if (!buffer
|| bufsize
< len
)
5728 return STATUS_BUFFER_TOO_SMALL
;
5730 assembly
= actctx
->assemblies
;
5733 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5734 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5739 FIXME( "class %lu not implemented\n", class );
5740 return STATUS_NOT_IMPLEMENTED
;
5742 return STATUS_SUCCESS
;
5745 /***********************************************************************
5746 * RtlFindActivationContextSectionString (NTDLL.@)
5748 * Find information about a string in an activation context.
5749 * FIXME: function signature/prototype may be wrong
5751 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5752 const UNICODE_STRING
*section_name
, PVOID ptr
)
5754 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5755 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5757 TRACE("%08lx %s %lu %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5758 debugstr_us(section_name
), data
);
5762 FIXME("expected guid == NULL\n");
5763 return STATUS_INVALID_PARAMETER
;
5765 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5767 FIXME("unknown flags %08lx\n", flags
);
5768 return STATUS_INVALID_PARAMETER
;
5770 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5771 !section_name
|| !section_name
->Buffer
)
5773 WARN("invalid parameter\n");
5774 return STATUS_INVALID_PARAMETER
;
5777 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5779 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5780 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5783 if (status
!= STATUS_SUCCESS
)
5784 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5789 /***********************************************************************
5790 * RtlFindActivationContextSectionGuid (NTDLL.@)
5792 * Find information about a GUID in an activation context.
5793 * FIXME: function signature/prototype may be wrong
5795 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5796 const GUID
*guid
, void *ptr
)
5798 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5799 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5801 TRACE("%08lx %s %lu %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5805 FIXME("expected extguid == NULL\n");
5806 return STATUS_INVALID_PARAMETER
;
5809 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5811 FIXME("unknown flags %08lx\n", flags
);
5812 return STATUS_INVALID_PARAMETER
;
5815 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5816 return STATUS_INVALID_PARAMETER
;
5818 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5820 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5821 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5824 if (status
!= STATUS_SUCCESS
)
5825 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5831 /***********************************************************************
5832 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5834 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5835 const WCHAR
*settings
, WCHAR
*buffer
,
5836 SIZE_T size
, SIZE_T
*written
)
5838 ACTIVATION_CONTEXT
*actctx
;
5843 WARN( "unknown flags %08lx\n", flags
);
5844 return STATUS_INVALID_PARAMETER
;
5849 if (wcscmp( ns
, windowsSettings2005NSW
) &&
5850 wcscmp( ns
, windowsSettings2011NSW
) &&
5851 wcscmp( ns
, windowsSettings2016NSW
) &&
5852 wcscmp( ns
, windowsSettings2017NSW
) &&
5853 wcscmp( ns
, windowsSettings2019NSW
) &&
5854 wcscmp( ns
, windowsSettings2020NSW
))
5855 return STATUS_INVALID_PARAMETER
;
5857 else ns
= windowsSettings2005NSW
;
5859 if (!handle
) handle
= process_actctx
;
5860 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5862 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5864 if (written
) *written
= wcslen(res
) + 1;
5865 if (size
< wcslen(res
)) return STATUS_BUFFER_TOO_SMALL
;
5866 wcscpy( buffer
, res
);
5867 return STATUS_SUCCESS
;