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
,
2929 FILE_SHARE_READ
| FILE_SHARE_DELETE
, FILE_SYNCHRONOUS_IO_ALERT
);
2932 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2933 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2934 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2937 UNICODE_STRING nameW
;
2938 LDR_RESOURCE_INFO info
;
2939 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2942 if (TRACE_ON(actctx
))
2944 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2946 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2947 hModule
, debugstr_w(nameW
.Buffer
) );
2948 RtlFreeUnicodeString( &nameW
);
2950 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2951 hModule
, debugstr_w(filename
) );
2954 if (!resname
) return STATUS_INVALID_PARAMETER
;
2956 info
.Type
= RT_MANIFEST
;
2957 info
.Language
= lang
;
2958 if (!((ULONG_PTR
)resname
>> 16))
2960 info
.Name
= (ULONG_PTR
)resname
;
2961 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2963 else if (resname
[0] == '#')
2966 RtlInitUnicodeString(&nameW
, resname
+ 1);
2967 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2968 return STATUS_INVALID_PARAMETER
;
2970 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2974 RtlCreateUnicodeString(&nameW
, resname
);
2975 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2976 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2977 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2978 RtlFreeUnicodeString(&nameW
);
2980 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2982 if (status
== STATUS_SUCCESS
)
2983 status
= parse_manifest(acl
, ai
, filename
, hModule
, directory
, shared
, ptr
, entry
->Size
);
2988 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2989 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2990 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2993 OBJECT_ATTRIBUTES attr
;
2995 LARGE_INTEGER offset
;
3000 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
3002 attr
.Length
= sizeof(attr
);
3003 attr
.RootDirectory
= 0;
3004 attr
.ObjectName
= NULL
;
3005 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3006 attr
.SecurityDescriptor
= NULL
;
3007 attr
.SecurityQualityOfService
= NULL
;
3010 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3011 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3012 if (status
!= STATUS_SUCCESS
) return status
;
3014 offset
.QuadPart
= 0;
3017 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3018 &count
, ViewShare
, 0, PAGE_READONLY
);
3020 if (status
!= STATUS_SUCCESS
) return status
;
3022 if (RtlImageNtHeader(base
)) /* we got a PE file */
3024 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3025 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
3027 else status
= STATUS_INVALID_IMAGE_FORMAT
;
3029 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3033 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3034 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
3036 FILE_END_OF_FILE_INFORMATION info
;
3039 OBJECT_ATTRIBUTES attr
;
3041 LARGE_INTEGER offset
;
3046 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
3048 attr
.Length
= sizeof(attr
);
3049 attr
.RootDirectory
= 0;
3050 attr
.ObjectName
= NULL
;
3051 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
3052 attr
.SecurityDescriptor
= NULL
;
3053 attr
.SecurityQualityOfService
= NULL
;
3056 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3057 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3058 if (status
!= STATUS_SUCCESS
) return status
;
3060 offset
.QuadPart
= 0;
3063 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
3064 &count
, ViewShare
, 0, PAGE_READONLY
);
3066 if (status
!= STATUS_SUCCESS
) return status
;
3068 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
3069 if (status
== STATUS_SUCCESS
)
3070 status
= parse_manifest(acl
, ai
, filename
, NULL
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
3072 NtUnmapViewOfSection( GetCurrentProcess(), base
);
3076 /* try to load the .manifest file associated to the file */
3077 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3078 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3082 UNICODE_STRING nameW
;
3084 UINT resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3086 if (!((ULONG_PTR
)resname
>> 16)) resid
= LOWORD(resname
);
3088 TRACE( "looking for manifest associated with %s id %u\n", debugstr_w(filename
), resid
);
3090 if (module
) /* use the module filename */
3092 UNICODE_STRING name
;
3094 if (!(status
= get_module_filename( module
, &name
, sizeof(L
".manifest") + 10*sizeof(WCHAR
) )))
3096 if (resid
!= 1) swprintf( name
.Buffer
+ wcslen(name
.Buffer
), 10, L
".%u", resid
);
3097 wcscat( name
.Buffer
, L
".manifest" );
3098 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3099 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3100 RtlFreeUnicodeString( &name
);
3102 if (status
) return status
;
3106 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3107 (wcslen(filename
) + 10) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
3108 return STATUS_NO_MEMORY
;
3109 wcscpy( buffer
, filename
);
3110 if (resid
!= 1) swprintf( buffer
+ wcslen(buffer
), 10, L
".%u", resid
);
3111 wcscat( buffer
, L
".manifest" );
3112 RtlInitUnicodeString( &nameW
, buffer
);
3115 if (!open_nt_file( &file
, &nameW
))
3117 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3120 else status
= STATUS_RESOURCE_NAME_NOT_FOUND
;
3121 RtlFreeUnicodeString( &nameW
);
3125 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3127 static const WCHAR lookup_fmtW
[] = L
"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3128 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3130 WCHAR
*lookup
, *ret
= NULL
;
3131 UNICODE_STRING lookup_us
;
3133 const WCHAR
*lang
= ai
->language
;
3134 unsigned int data_pos
= 0, data_len
, len
;
3137 if (!lang
|| !wcsicmp( lang
, L
"neutral" )) lang
= L
"*";
3139 len
= wcslen(ai
->arch
) + wcslen(ai
->name
) + wcslen(ai
->public_key
) + wcslen(lang
) + 20 + ARRAY_SIZE(lookup_fmtW
);
3140 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
3141 swprintf( lookup
, len
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3142 ai
->version
.major
, ai
->version
.minor
, lang
);
3143 RtlInitUnicodeString( &lookup_us
, lookup
);
3145 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3146 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3148 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3149 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3151 ULONG build
, revision
;
3153 data_len
= io
.Information
;
3157 if (data_pos
>= data_len
)
3159 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3160 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3162 data_len
= io
.Information
;
3165 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3167 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3168 else data_pos
= data_len
;
3170 tmp
= dir_info
->FileName
+ (wcschr(lookup
, '*') - lookup
);
3171 build
= wcstoul( tmp
, NULL
, 10 );
3172 if (build
< min_build
) continue;
3173 tmp
= wcschr(tmp
, '.') + 1;
3174 revision
= wcstoul( tmp
, NULL
, 10 );
3175 if (build
== min_build
&& revision
< min_revision
) continue;
3176 tmp
= wcschr(tmp
, '_') + 1;
3177 tmp
= wcschr(tmp
, '_') + 1;
3178 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3179 !wcsnicmp( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3181 /* prefer a non-Wine manifest if we already have one */
3182 /* we'll still load the builtin dll if specified through DllOverrides */
3188 min_revision
= revision
;
3190 ai
->version
.build
= build
;
3191 ai
->version
.revision
= revision
;
3192 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3193 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3195 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3196 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3200 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3201 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3205 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3207 struct assembly_identity sxs_ai
;
3208 UNICODE_STRING path_us
;
3209 OBJECT_ATTRIBUTES attr
;
3211 WCHAR
*path
, *file
= NULL
;
3214 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3216 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L
"\\winsxs\\manifests") +
3217 wcslen(windows_dir
) * sizeof(WCHAR
) )))
3218 return STATUS_NO_MEMORY
;
3220 wcscpy( path
, windows_dir
);
3221 wcscat( path
, L
"\\winsxs\\manifests" );
3223 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3225 RtlFreeHeap( GetProcessHeap(), 0, path
);
3226 return STATUS_NO_SUCH_FILE
;
3228 RtlFreeHeap( GetProcessHeap(), 0, path
);
3230 attr
.Length
= sizeof(attr
);
3231 attr
.RootDirectory
= 0;
3232 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3233 attr
.ObjectName
= &path_us
;
3234 attr
.SecurityDescriptor
= NULL
;
3235 attr
.SecurityQualityOfService
= NULL
;
3237 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3238 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3241 file
= lookup_manifest_file( handle
, &sxs_ai
);
3246 RtlFreeUnicodeString( &path_us
);
3247 return STATUS_NO_SUCH_FILE
;
3250 /* append file name to directory path */
3251 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3252 path_us
.Length
+ (wcslen(file
) + 2) * sizeof(WCHAR
) )))
3254 RtlFreeHeap( GetProcessHeap(), 0, file
);
3255 RtlFreeUnicodeString( &path_us
);
3256 return STATUS_NO_MEMORY
;
3259 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3260 wcscpy( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3261 RtlInitUnicodeString( &path_us
, path
);
3262 *wcsrchr(file
, '.') = 0; /* remove .manifest extension */
3264 if (!open_nt_file( &handle
, &path_us
))
3266 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3269 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3271 RtlFreeHeap( GetProcessHeap(), 0, file
);
3272 RtlFreeUnicodeString( &path_us
);
3276 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3277 struct assembly_identity
* ai
)
3280 WCHAR
*buffer
, *p
, *directory
;
3282 UNICODE_STRING nameW
;
3286 TRACE( "looking for name=%s version=%s arch=%s\n",
3287 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3289 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3291 /* FIXME: add support for language specific lookup */
3293 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3294 wcslen(acl
->actctx
->appdir
.info
));
3296 nameW
.Buffer
= NULL
;
3297 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3298 (len
+ 2 * wcslen(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
3299 return STATUS_NO_MEMORY
;
3301 if (!(directory
= build_assembly_dir( ai
)))
3303 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3304 return STATUS_NO_MEMORY
;
3307 /* Lookup in <dir>\name.dll
3308 * <dir>\name.manifest
3309 * <dir>\name\name.dll
3310 * <dir>\name\name.manifest
3312 * First 'appdir' is used as <dir>, if that failed
3313 * it tries application manifest file path.
3315 wcscpy( buffer
, acl
->actctx
->appdir
.info
);
3316 p
= buffer
+ wcslen(buffer
);
3317 for (i
= 0; i
< 4; i
++)
3321 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3322 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3326 wcscpy( p
, ai
->name
);
3329 wcscpy( p
, L
".dll" );
3330 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3332 status
= open_nt_file( &file
, &nameW
);
3335 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3336 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3338 if (status
== STATUS_SUCCESS
)
3341 RtlFreeUnicodeString( &nameW
);
3344 wcscpy( p
, L
".manifest" );
3345 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3347 status
= open_nt_file( &file
, &nameW
);
3350 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3354 RtlFreeUnicodeString( &nameW
);
3356 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3358 RtlFreeUnicodeString( &nameW
);
3359 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3360 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3364 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3366 NTSTATUS status
= STATUS_SUCCESS
;
3369 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3371 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3373 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3375 FIXME( "Could not find dependent assembly %s (%s)\n",
3376 debugstr_w(acl
->dependencies
[i
].name
),
3377 debugstr_version(&acl
->dependencies
[i
].version
) );
3378 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3383 /* FIXME should now iterate through all refs */
3387 static HANDLE
get_current_actctx_no_addref(void)
3389 ACTIVATION_CONTEXT_STACK
*actctx_stack
= NtCurrentTeb()->ActivationContextStackPointer
;
3391 if (actctx_stack
->ActiveFrame
)
3392 return actctx_stack
->ActiveFrame
->ActivationContext
;
3397 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3398 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3400 NTSTATUS status
= STATUS_SUCCESS
;
3402 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3404 if (*handle
) return STATUS_INVALID_PARAMETER
;
3406 *handle
= get_current_actctx_no_addref();
3408 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3411 LDR_DATA_TABLE_ENTRY
*pldr
;
3413 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3415 LdrLockLoaderLock( 0, NULL
, &magic
);
3416 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3418 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3419 status
= STATUS_DLL_NOT_FOUND
;
3421 *handle
= pldr
->ActivationContext
;
3423 else status
= STATUS_DLL_NOT_FOUND
;
3424 LdrUnlockLoaderLock( 0, magic
);
3426 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3427 *handle
= process_actctx
;
3432 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3434 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3435 struct strsection_header
*header
;
3436 struct dllredirect_data
*data
;
3437 struct string_index
*index
;
3440 /* compute section length */
3441 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3443 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3444 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3446 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3448 /* each entry needs index, data and string data */
3449 total_len
+= sizeof(*index
);
3450 total_len
+= aligned_string_len((wcslen(dll
->name
)+1)*sizeof(WCHAR
));
3453 total_len
+= offsetof( struct dllredirect_data
, paths
[1] );
3454 total_len
+= aligned_string_len( wcslen(dll
->load_from
) * sizeof(WCHAR
) );
3456 else total_len
+= offsetof( struct dllredirect_data
, paths
[0] );
3459 dll_count
+= assembly
->num_dlls
;
3462 total_len
+= sizeof(*header
);
3464 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3465 if (!header
) return STATUS_NO_MEMORY
;
3467 memset(header
, 0, sizeof(*header
));
3468 header
->magic
= STRSECTION_MAGIC
;
3469 header
->size
= sizeof(*header
);
3470 header
->count
= dll_count
;
3471 header
->index_offset
= sizeof(*header
);
3472 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3473 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3475 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3477 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3478 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3480 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3484 /* setup new index entry */
3485 str
.Buffer
= dll
->name
;
3486 str
.Length
= wcslen(dll
->name
)*sizeof(WCHAR
);
3487 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3488 /* hash original class name */
3489 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3491 index
->name_offset
= name_offset
;
3492 index
->name_len
= str
.Length
;
3493 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3494 index
->data_len
= offsetof( struct dllredirect_data
, paths
[0] );
3495 index
->rosterindex
= i
+ 1;
3498 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3499 memcpy(ptrW
, dll
->name
, index
->name_len
);
3500 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3501 name_offset
+= aligned_string_len(str
.MaximumLength
);
3504 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3507 ULONG len
= wcslen(dll
->load_from
) * sizeof(WCHAR
);
3508 data
->size
= offsetof( struct dllredirect_data
, paths
[1] );
3510 data
->total_len
= aligned_string_len( len
);
3511 data
->paths_count
= 1;
3512 data
->paths_offset
= index
->data_offset
+ offsetof( struct dllredirect_data
, paths
[0] );
3513 data
->paths
[0].offset
= index
->data_offset
+ data
->size
;
3514 data
->paths
[0].len
= len
;
3515 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->paths
[0].offset
);
3516 memcpy( ptrW
, dll
->load_from
, len
);
3517 if (wcschr( dll
->load_from
, '%' )) data
->flags
|= DLL_REDIRECT_PATH_EXPAND
;
3521 data
->size
= offsetof( struct dllredirect_data
, paths
[0] );
3522 data
->flags
= DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT
;
3523 data
->total_len
= 0;
3524 data
->paths_count
= 0;
3525 data
->paths_offset
= 0;
3527 name_offset
+= data
->size
+ data
->total_len
;
3535 return STATUS_SUCCESS
;
3538 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3540 struct string_index
*iter
, *index
= NULL
;
3544 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3545 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3547 for (i
= 0; i
< section
->count
; i
++)
3549 if (iter
->hash
== hash
)
3551 str
.Buffer
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3552 str
.Length
= iter
->name_len
;
3553 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3559 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3567 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3569 struct guid_index
*iter
, *index
= NULL
;
3572 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3574 for (i
= 0; i
< section
->count
; i
++)
3576 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3587 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3589 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3592 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3593 PACTCTX_SECTION_KEYED_DATA data
)
3595 struct dllredirect_data
*dll
;
3596 struct string_index
*index
;
3598 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3600 if (!actctx
->dllredirect_section
)
3602 struct strsection_header
*section
;
3604 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3605 if (status
) return status
;
3607 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3608 RtlFreeHeap(GetProcessHeap(), 0, section
);
3611 index
= find_string_index(actctx
->dllredirect_section
, name
);
3612 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3616 dll
= get_dllredirect_data(actctx
, index
);
3618 data
->ulDataFormatVersion
= 1;
3620 data
->ulLength
= dll
->size
;
3621 data
->lpSectionGlobalData
= NULL
;
3622 data
->ulSectionGlobalDataLength
= 0;
3623 data
->lpSectionBase
= actctx
->dllredirect_section
;
3624 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3625 data
->hActCtx
= NULL
;
3627 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3628 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3631 return STATUS_SUCCESS
;
3634 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3636 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3639 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3641 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3644 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3646 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3647 struct wndclass_redirect_data
*data
;
3648 struct strsection_header
*header
;
3649 struct string_index
*index
;
3652 /* compute section length */
3653 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3655 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3656 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3658 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3659 for (k
= 0; k
< dll
->entities
.num
; k
++)
3661 struct entity
*entity
= &dll
->entities
.base
[k
];
3662 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3664 int class_len
= wcslen(entity
->u
.class.name
) + 1;
3667 /* each class entry needs index, data and string data */
3668 total_len
+= sizeof(*index
);
3669 total_len
+= sizeof(*data
);
3670 /* original name is stored separately */
3671 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3672 /* versioned name and module name are stored one after another */
3673 if (entity
->u
.class.versioned
)
3674 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3677 len
+= wcslen(dll
->name
) + 1;
3678 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3686 total_len
+= sizeof(*header
);
3688 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3689 if (!header
) return STATUS_NO_MEMORY
;
3691 memset(header
, 0, sizeof(*header
));
3692 header
->magic
= STRSECTION_MAGIC
;
3693 header
->size
= sizeof(*header
);
3694 header
->count
= class_count
;
3695 header
->index_offset
= sizeof(*header
);
3696 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3697 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3699 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3701 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3702 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3704 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3705 for (k
= 0; k
< dll
->entities
.num
; k
++)
3707 struct entity
*entity
= &dll
->entities
.base
[k
];
3708 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3710 ULONG versioned_len
, module_len
;
3714 /* setup new index entry */
3715 str
.Buffer
= entity
->u
.class.name
;
3716 str
.Length
= wcslen(entity
->u
.class.name
)*sizeof(WCHAR
);
3717 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3718 /* hash original class name */
3719 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3721 /* include '!' separator too */
3722 if (entity
->u
.class.versioned
)
3723 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3725 versioned_len
= str
.Length
;
3726 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3728 index
->name_offset
= name_offset
;
3729 index
->name_len
= str
.Length
;
3730 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3731 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3732 index
->rosterindex
= i
+ 1;
3735 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3736 data
->size
= sizeof(*data
);
3738 data
->name_len
= versioned_len
;
3739 data
->name_offset
= sizeof(*data
);
3740 data
->module_len
= module_len
;
3741 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3743 /* original class name */
3744 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3745 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3746 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3749 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3750 memcpy(ptrW
, dll
->name
, data
->module_len
);
3751 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3753 /* versioned name */
3754 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3755 if (entity
->u
.class.versioned
)
3757 get_assembly_version(assembly
, ptrW
);
3759 wcscat(ptrW
, entity
->u
.class.name
);
3763 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3764 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3767 name_offset
+= sizeof(*data
);
3768 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3778 return STATUS_SUCCESS
;
3781 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3782 PACTCTX_SECTION_KEYED_DATA data
)
3784 struct string_index
*iter
, *index
= NULL
;
3785 struct wndclass_redirect_data
*class;
3790 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3792 if (!actctx
->wndclass_section
)
3794 struct strsection_header
*section
;
3796 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3797 if (status
) return status
;
3799 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3800 RtlFreeHeap(GetProcessHeap(), 0, section
);
3804 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3805 iter
= get_wndclass_first_index(actctx
);
3807 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3809 if (iter
->hash
== hash
)
3811 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3812 str
.Length
= iter
->name_len
;
3813 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3819 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3824 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3828 class = get_wndclass_data(actctx
, index
);
3830 data
->ulDataFormatVersion
= 1;
3831 data
->lpData
= class;
3832 /* full length includes string length with nulls */
3833 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3834 data
->lpSectionGlobalData
= NULL
;
3835 data
->ulSectionGlobalDataLength
= 0;
3836 data
->lpSectionBase
= actctx
->wndclass_section
;
3837 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3838 data
->hActCtx
= NULL
;
3840 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3841 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3844 return STATUS_SUCCESS
;
3847 static inline struct string_index
*get_activatable_class_first_index(ACTIVATION_CONTEXT
*actctx
)
3849 return (struct string_index
*)((BYTE
*)actctx
->activatable_class_section
+ actctx
->activatable_class_section
->index_offset
);
3852 static inline struct activatable_class_data
*get_activatable_class_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3854 return (struct activatable_class_data
*)((BYTE
*)ctxt
->activatable_class_section
+ index
->data_offset
);
3857 static NTSTATUS
build_activatable_class_section(ACTIVATION_CONTEXT
*actctx
, struct strsection_header
**section
)
3859 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0, global_offset
= 0, global_len
= 0;
3860 struct activatable_class_data
*data
;
3861 struct strsection_header
*header
;
3862 struct string_index
*index
;
3865 /* compute section length */
3866 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3868 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3869 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3871 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3872 BOOL has_class
= FALSE
;
3874 for (k
= 0; k
< dll
->entities
.num
; k
++)
3876 struct entity
*entity
= &dll
->entities
.base
[k
];
3877 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
3879 int class_len
= wcslen(entity
->u
.activatable_class
.name
) + 1;
3881 /* each class entry needs index, data and string data */
3882 total_len
+= sizeof(*index
);
3883 total_len
+= aligned_string_len(class_len
* sizeof(WCHAR
));
3884 total_len
+= sizeof(*data
);
3893 int module_len
= wcslen(dll
->name
) + 1;
3894 global_len
+= aligned_string_len(module_len
* sizeof(WCHAR
));
3899 total_len
+= sizeof(*header
) + global_len
;
3901 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3902 if (!header
) return STATUS_NO_MEMORY
;
3904 memset(header
, 0, sizeof(*header
));
3905 header
->magic
= STRSECTION_MAGIC
;
3906 header
->size
= sizeof(*header
);
3907 header
->count
= class_count
;
3908 header
->global_offset
= header
->size
;
3909 header
->global_len
= global_len
;
3910 header
->index_offset
= header
->global_offset
+ header
->global_len
;
3911 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3912 name_offset
= header
->index_offset
+ header
->count
* sizeof(*index
);
3914 global_offset
= header
->size
;
3915 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3917 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3918 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3920 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3921 int module_len
= wcslen(dll
->name
) * sizeof(WCHAR
);
3922 BOOL has_class
= FALSE
;
3924 for (k
= 0; k
< dll
->entities
.num
; k
++)
3926 struct entity
*entity
= &dll
->entities
.base
[k
];
3928 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
)
3933 /* setup new index entry */
3934 str
.Buffer
= entity
->u
.activatable_class
.name
;
3935 str
.Length
= wcslen(entity
->u
.activatable_class
.name
) * sizeof(WCHAR
);
3936 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3937 /* hash class name */
3938 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3940 index
->name_offset
= name_offset
;
3941 index
->name_len
= str
.Length
;
3942 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3943 index
->data_len
= sizeof(*data
);
3944 index
->rosterindex
= i
+ 1;
3947 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3948 memcpy(ptrW
, entity
->u
.activatable_class
.name
, index
->name_len
);
3949 ptrW
[index
->name_len
/ sizeof(WCHAR
)] = 0;
3952 data
= (struct activatable_class_data
*)((BYTE
*)header
+ index
->data_offset
);
3953 data
->size
= sizeof(*data
);
3954 data
->threading_model
= entity
->u
.activatable_class
.threading_model
;
3955 data
->module_len
= module_len
;
3956 data
->module_offset
= global_offset
;
3958 name_offset
+= aligned_string_len(str
.MaximumLength
);
3959 name_offset
+= sizeof(*data
);
3968 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)header
+ global_offset
);
3969 memcpy(ptrW
, dll
->name
, module_len
);
3970 ptrW
[module_len
/ sizeof(WCHAR
)] = 0;
3971 global_offset
+= aligned_string_len(module_len
+ sizeof(WCHAR
));
3978 return STATUS_SUCCESS
;
3981 static NTSTATUS
find_activatable_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3982 PACTCTX_SECTION_KEYED_DATA data
)
3984 struct string_index
*iter
, *index
= NULL
;
3985 struct activatable_class_data
*class;
3990 if (!(actctx
->sections
& ACTIVATABLE_CLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3992 if (!actctx
->activatable_class_section
)
3994 struct strsection_header
*section
;
3996 NTSTATUS status
= build_activatable_class_section(actctx
, §ion
);
3997 if (status
) return status
;
3999 if (InterlockedCompareExchangePointer((void**)&actctx
->activatable_class_section
, section
, NULL
))
4000 RtlFreeHeap(GetProcessHeap(), 0, section
);
4004 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
4005 iter
= get_activatable_class_first_index(actctx
);
4007 for (i
= 0; i
< actctx
->activatable_class_section
->count
; i
++)
4009 if (iter
->hash
== hash
)
4011 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->activatable_class_section
+ iter
->name_offset
);
4012 str
.Length
= iter
->name_len
;
4013 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
4019 WARN("hash collision 0x%08lx, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
4024 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4028 class = get_activatable_class_data(actctx
, index
);
4030 data
->ulDataFormatVersion
= 1;
4031 data
->lpData
= class;
4032 /* full length includes string length with nulls */
4033 data
->ulLength
= class->size
+ class->module_len
+ sizeof(WCHAR
);
4034 data
->lpSectionGlobalData
= (BYTE
*)actctx
->activatable_class_section
+ actctx
->activatable_class_section
->global_offset
;
4035 data
->ulSectionGlobalDataLength
= actctx
->activatable_class_section
->global_len
;
4036 data
->lpSectionBase
= actctx
->activatable_class_section
;
4037 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->activatable_class_section
);
4038 data
->hActCtx
= NULL
;
4040 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4041 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4044 return STATUS_SUCCESS
;
4047 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4049 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
4050 struct guidsection_header
*header
;
4051 ULONG module_offset
, data_offset
;
4052 struct tlibredirect_data
*data
;
4053 struct guid_index
*index
;
4055 /* compute section length */
4056 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4058 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4059 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4061 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4062 for (k
= 0; k
< dll
->entities
.num
; k
++)
4064 struct entity
*entity
= &dll
->entities
.base
[k
];
4065 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
4067 /* each entry needs index, data and string data for module name and help string */
4068 total_len
+= sizeof(*index
);
4069 total_len
+= sizeof(*data
);
4070 /* help string is stored separately */
4071 if (*entity
->u
.typelib
.helpdir
)
4072 total_len
+= aligned_string_len((wcslen(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
4074 /* module names are packed one after another */
4075 names_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
4083 total_len
+= aligned_string_len(names_len
);
4084 total_len
+= sizeof(*header
);
4086 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4087 if (!header
) return STATUS_NO_MEMORY
;
4089 memset(header
, 0, sizeof(*header
));
4090 header
->magic
= GUIDSECTION_MAGIC
;
4091 header
->size
= sizeof(*header
);
4092 header
->count
= tlib_count
;
4093 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4094 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4095 module_offset
= sizeof(*header
);
4096 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
4098 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4100 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4101 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4103 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4104 for (k
= 0; k
< dll
->entities
.num
; k
++)
4106 struct entity
*entity
= &dll
->entities
.base
[k
];
4107 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
4109 ULONG module_len
, help_len
;
4113 if (*entity
->u
.typelib
.helpdir
)
4114 help_len
= wcslen(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
4118 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
4120 /* setup new index entry */
4121 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
4122 RtlGUIDFromString(&str
, &index
->guid
);
4123 index
->data_offset
= data_offset
;
4124 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
4125 index
->rosterindex
= i
+ 1;
4128 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
4129 data
->size
= sizeof(*data
);
4131 data
->name_len
= module_len
;
4132 data
->name_offset
= module_offset
;
4133 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
4135 data
->flags
= entity
->u
.typelib
.flags
;
4136 data
->help_len
= help_len
;
4137 data
->help_offset
= sizeof(*data
);
4138 data
->major_version
= entity
->u
.typelib
.major
;
4139 data
->minor_version
= entity
->u
.typelib
.minor
;
4142 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
4143 memcpy(ptrW
, dll
->name
, data
->name_len
);
4144 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4149 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
4150 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
4151 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
4154 data_offset
+= sizeof(*data
);
4156 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
4158 module_offset
+= module_len
+ sizeof(WCHAR
);
4168 return STATUS_SUCCESS
;
4171 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4173 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
4176 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4178 struct guid_index
*index
= NULL
;
4179 struct tlibredirect_data
*tlib
;
4181 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4183 if (!actctx
->tlib_section
)
4185 struct guidsection_header
*section
;
4187 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
4188 if (status
) return status
;
4190 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
4191 RtlFreeHeap(GetProcessHeap(), 0, section
);
4194 index
= find_guid_index(actctx
->tlib_section
, guid
);
4195 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4197 tlib
= get_tlib_data(actctx
, index
);
4199 data
->ulDataFormatVersion
= 1;
4200 data
->lpData
= tlib
;
4201 /* full length includes string length with nulls */
4202 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
4203 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
4204 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
4205 data
->lpSectionBase
= actctx
->tlib_section
;
4206 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
4207 data
->hActCtx
= NULL
;
4209 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4210 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4212 return STATUS_SUCCESS
;
4215 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
4217 ULONG
*ptr
= (ULONG
*)guid
;
4220 /* GUID is 16 bytes long */
4221 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
4222 *ptr
= RtlUniform(seed
);
4224 guid
->Data3
&= 0x0fff;
4225 guid
->Data3
|= (4 << 12);
4226 guid
->Data4
[0] &= 0x3f;
4227 guid
->Data4
[0] |= 0x80;
4230 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
4231 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
4235 for (i
= 0; i
< entities
->num
; i
++)
4237 struct entity
*entity
= &entities
->base
[i
];
4238 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4240 /* each entry needs two index entries, extra one goes for alias GUID */
4241 *len
+= 2*sizeof(struct guid_index
);
4242 /* To save some memory we don't allocated two data structures,
4243 instead alias index and normal index point to the same data structure. */
4244 *len
+= sizeof(struct comclassredirect_data
);
4246 /* for clrClass store some more */
4247 if (entity
->u
.comclass
.name
)
4249 unsigned int str_len
;
4251 /* all string data is stored together in aligned block */
4252 str_len
= wcslen(entity
->u
.comclass
.name
)+1;
4253 if (entity
->u
.comclass
.progid
)
4254 str_len
+= wcslen(entity
->u
.comclass
.progid
)+1;
4255 if (entity
->u
.comclass
.version
)
4256 str_len
+= wcslen(entity
->u
.comclass
.version
)+1;
4258 *len
+= sizeof(struct clrclass_data
);
4259 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
4261 /* module name is forced to mscoree.dll, and stored two times with different case */
4262 *module_len
+= sizeof(L
"MSCOREE.DLL") + sizeof(L
"mscoree.dll");
4266 /* progid string is stored separately */
4267 if (entity
->u
.comclass
.progid
)
4268 *len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4270 *module_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
4278 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4279 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4280 ULONG
*seed
, ULONG rosterindex
)
4284 for (i
= 0; i
< entities
->num
; i
++)
4286 struct entity
*entity
= &entities
->base
[i
];
4287 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4289 ULONG module_len
, progid_len
, str_len
= 0, miscmask
;
4290 struct comclassredirect_data
*data
;
4291 struct guid_index
*alias_index
;
4292 struct clrclass_data
*clrdata
;
4296 if (entity
->u
.comclass
.progid
)
4297 progid_len
= wcslen(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4301 module_len
= dll
? wcslen(dll
->name
)*sizeof(WCHAR
) : wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
4303 /* setup new index entry */
4304 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4305 RtlGUIDFromString(&str
, &(*index
)->guid
);
4307 (*index
)->data_offset
= *data_offset
;
4308 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4309 (*index
)->rosterindex
= rosterindex
;
4311 /* Setup new index entry for alias guid. Alias index records are placed after
4312 normal records, so normal guids are hit first on search. Note that class count
4314 alias_index
= (*index
) + section
->count
/2;
4315 generate_uuid(seed
, &alias_index
->guid
);
4316 alias_index
->data_offset
= (*index
)->data_offset
;
4317 alias_index
->data_len
= 0;
4318 alias_index
->rosterindex
= (*index
)->rosterindex
;
4321 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4322 data
->size
= sizeof(*data
);
4323 data
->model
= entity
->u
.comclass
.model
;
4324 data
->clsid
= (*index
)->guid
;
4325 data
->alias
= alias_index
->guid
;
4326 data
->clsid2
= data
->clsid
;
4327 if (entity
->u
.comclass
.tlbid
)
4329 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4330 RtlGUIDFromString(&str
, &data
->tlbid
);
4333 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4334 data
->name_len
= module_len
;
4335 data
->name_offset
= *module_offset
;
4336 data
->progid_len
= progid_len
;
4337 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4338 data
->clrdata_len
= 0; /* will be set later */
4339 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4340 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4341 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4342 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4343 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4344 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4346 /* mask describes which misc* data is available */
4348 if (data
->miscstatus
)
4349 miscmask
|= MiscStatus
;
4350 if (data
->miscstatuscontent
)
4351 miscmask
|= MiscStatusContent
;
4352 if (data
->miscstatusthumbnail
)
4353 miscmask
|= MiscStatusThumbnail
;
4354 if (data
->miscstatusicon
)
4355 miscmask
|= MiscStatusIcon
;
4356 if (data
->miscstatusdocprint
)
4357 miscmask
|= MiscStatusDocPrint
;
4358 data
->flags
= miscmask
<< 8;
4360 if (data
->clrdata_offset
)
4362 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4364 clrdata
->size
= sizeof(*clrdata
);
4365 clrdata
->res
[0] = 0;
4366 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4367 clrdata
->module_len
= wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
4368 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4369 clrdata
->name_len
= wcslen(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4370 clrdata
->name_offset
= clrdata
->size
;
4371 clrdata
->version_len
= entity
->u
.comclass
.version
? wcslen(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4372 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4373 clrdata
->res2
[0] = 0;
4374 clrdata
->res2
[1] = 0;
4376 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4379 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4380 memcpy(ptrW
, L
"mscoree.dll", clrdata
->module_len
);
4381 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4383 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4384 memcpy(ptrW
, L
"MSCOREE.DLL", data
->name_len
);
4385 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4388 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4389 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4390 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4392 /* runtime version, optional */
4393 if (clrdata
->version_len
)
4395 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4397 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4398 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4399 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4402 if (data
->progid_len
)
4403 data
->progid_offset
+= data
->clrdata_len
;
4404 (*index
)->data_len
+= sizeof(*clrdata
);
4411 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4412 memcpy(ptrW
, dll
->name
, data
->name_len
);
4413 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4417 if (data
->progid_len
)
4419 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4420 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4421 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4424 /* string block length */
4428 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4429 if (clrdata
->version_len
)
4430 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4433 str_len
+= progid_len
+ sizeof(WCHAR
);
4435 (*index
)->data_len
+= aligned_string_len(str_len
);
4436 alias_index
->data_len
= (*index
)->data_len
;
4438 /* move to next data record */
4439 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4440 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4444 (*data_offset
) += sizeof(*clrdata
);
4445 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4452 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4454 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4455 struct guidsection_header
*header
;
4456 ULONG module_offset
, data_offset
;
4457 struct guid_index
*index
;
4460 /* compute section length */
4461 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4463 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4464 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4465 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4467 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4468 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4472 total_len
+= aligned_string_len(names_len
);
4473 total_len
+= sizeof(*header
);
4475 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4476 if (!header
) return STATUS_NO_MEMORY
;
4478 memset(header
, 0, sizeof(*header
));
4479 header
->magic
= GUIDSECTION_MAGIC
;
4480 header
->size
= sizeof(*header
);
4481 header
->count
= 2*class_count
;
4482 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4483 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4484 module_offset
= sizeof(*header
);
4485 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4487 seed
= NtGetTickCount();
4488 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4490 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4491 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4492 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4494 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4495 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4501 return STATUS_SUCCESS
;
4504 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4506 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4509 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4511 struct comclassredirect_data
*comclass
;
4512 struct guid_index
*index
= NULL
;
4514 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4516 if (!actctx
->comserver_section
)
4518 struct guidsection_header
*section
;
4520 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4521 if (status
) return status
;
4523 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4524 RtlFreeHeap(GetProcessHeap(), 0, section
);
4527 index
= find_guid_index(actctx
->comserver_section
, guid
);
4528 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4530 comclass
= get_comclass_data(actctx
, index
);
4532 data
->ulDataFormatVersion
= 1;
4533 data
->lpData
= comclass
;
4534 /* full length includes string length with nulls */
4535 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4536 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4537 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4538 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4539 data
->lpSectionBase
= actctx
->comserver_section
;
4540 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4541 data
->hActCtx
= NULL
;
4543 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4544 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4546 return STATUS_SUCCESS
;
4549 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4553 for (i
= 0; i
< entities
->num
; i
++)
4555 struct entity
*entity
= &entities
->base
[i
];
4556 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4558 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4559 if (entity
->u
.ifaceps
.name
)
4560 *len
+= aligned_string_len((wcslen(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4566 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4567 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4571 for (i
= 0; i
< entities
->num
; i
++)
4573 struct entity
*entity
= &entities
->base
[i
];
4574 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4576 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4580 if (entity
->u
.ifaceps
.name
)
4581 name_len
= wcslen(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4586 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4587 RtlGUIDFromString(&str
, &(*index
)->guid
);
4588 (*index
)->data_offset
= *data_offset
;
4589 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4590 (*index
)->rosterindex
= rosterindex
;
4592 /* setup data record */
4593 data
->size
= sizeof(*data
);
4594 data
->mask
= entity
->u
.ifaceps
.mask
;
4596 /* proxyStubClsid32 value is only stored for external PS,
4597 if set it's used as iid, otherwise 'iid' attribute value is used */
4598 if (entity
->u
.ifaceps
.ps32
)
4600 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4601 RtlGUIDFromString(&str
, &data
->iid
);
4604 data
->iid
= (*index
)->guid
;
4606 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4608 if (entity
->u
.ifaceps
.tlib
)
4610 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4611 RtlGUIDFromString(&str
, &data
->tlbid
);
4614 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4616 if (entity
->u
.ifaceps
.base
)
4618 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4619 RtlGUIDFromString(&str
, &data
->base
);
4622 memset(&data
->base
, 0, sizeof(data
->base
));
4624 data
->name_len
= name_len
;
4625 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4630 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4631 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4632 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4635 /* move to next record */
4637 *data_offset
+= sizeof(*data
);
4639 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4644 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4646 unsigned int i
, j
, total_len
= 0, count
= 0;
4647 struct guidsection_header
*header
;
4648 struct guid_index
*index
;
4651 /* compute section length */
4652 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4654 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4656 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4657 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4659 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4660 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4664 total_len
+= sizeof(*header
);
4666 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4667 if (!header
) return STATUS_NO_MEMORY
;
4669 memset(header
, 0, sizeof(*header
));
4670 header
->magic
= GUIDSECTION_MAGIC
;
4671 header
->size
= sizeof(*header
);
4672 header
->count
= count
;
4673 header
->index_offset
= sizeof(*header
);
4674 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4675 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4677 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4679 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4681 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4682 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4684 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4685 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4691 return STATUS_SUCCESS
;
4694 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4696 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4699 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4701 struct ifacepsredirect_data
*iface
;
4702 struct guid_index
*index
= NULL
;
4704 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4706 if (!actctx
->ifaceps_section
)
4708 struct guidsection_header
*section
;
4710 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4711 if (status
) return status
;
4713 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4714 RtlFreeHeap(GetProcessHeap(), 0, section
);
4717 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4718 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4720 iface
= get_ifaceps_data(actctx
, index
);
4722 data
->ulDataFormatVersion
= 1;
4723 data
->lpData
= iface
;
4724 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4725 data
->lpSectionGlobalData
= NULL
;
4726 data
->ulSectionGlobalDataLength
= 0;
4727 data
->lpSectionBase
= actctx
->ifaceps_section
;
4728 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4729 data
->hActCtx
= NULL
;
4731 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4732 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4734 return STATUS_SUCCESS
;
4737 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4739 unsigned int i
, j
, total_len
= 0, count
= 0;
4740 struct guidsection_header
*header
;
4741 struct clrsurrogate_data
*data
;
4742 struct guid_index
*index
;
4745 /* compute section length */
4746 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4748 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4749 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4751 struct entity
*entity
= &assembly
->entities
.base
[j
];
4752 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4756 total_len
+= sizeof(*index
) + sizeof(*data
);
4757 len
= wcslen(entity
->u
.clrsurrogate
.name
) + 1;
4758 if (entity
->u
.clrsurrogate
.version
)
4759 len
+= wcslen(entity
->u
.clrsurrogate
.version
) + 1;
4760 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4767 total_len
+= sizeof(*header
);
4769 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4770 if (!header
) return STATUS_NO_MEMORY
;
4772 memset(header
, 0, sizeof(*header
));
4773 header
->magic
= GUIDSECTION_MAGIC
;
4774 header
->size
= sizeof(*header
);
4775 header
->count
= count
;
4776 header
->index_offset
= sizeof(*header
);
4777 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4778 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4780 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4782 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4783 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4785 struct entity
*entity
= &assembly
->entities
.base
[j
];
4786 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4788 ULONG version_len
, name_len
;
4792 if (entity
->u
.clrsurrogate
.version
)
4793 version_len
= wcslen(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4796 name_len
= wcslen(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4798 /* setup new index entry */
4799 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4800 RtlGUIDFromString(&str
, &index
->guid
);
4802 index
->data_offset
= data_offset
;
4803 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4804 index
->rosterindex
= i
+ 1;
4807 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4808 data
->size
= sizeof(*data
);
4810 data
->clsid
= index
->guid
;
4811 data
->version_offset
= version_len
? data
->size
: 0;
4812 data
->version_len
= version_len
;
4813 data
->name_offset
= data
->size
+ version_len
;
4815 data
->name_offset
+= sizeof(WCHAR
);
4816 data
->name_len
= name_len
;
4818 /* surrogate name */
4819 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4820 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4821 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4823 /* runtime version */
4824 if (data
->version_len
)
4826 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4827 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4828 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4831 data_offset
+= index
->data_len
;
4839 return STATUS_SUCCESS
;
4842 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4844 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4847 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4849 struct clrsurrogate_data
*surrogate
;
4850 struct guid_index
*index
= NULL
;
4852 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4854 if (!actctx
->clrsurrogate_section
)
4856 struct guidsection_header
*section
;
4858 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4859 if (status
) return status
;
4861 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4862 RtlFreeHeap(GetProcessHeap(), 0, section
);
4865 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4866 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4868 surrogate
= get_surrogate_data(actctx
, index
);
4870 data
->ulDataFormatVersion
= 1;
4871 data
->lpData
= surrogate
;
4872 /* full length includes string length with nulls */
4873 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4874 if (surrogate
->version_len
)
4875 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4877 data
->lpSectionGlobalData
= NULL
;
4878 data
->ulSectionGlobalDataLength
= 0;
4879 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4880 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4881 data
->hActCtx
= NULL
;
4883 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4884 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4886 return STATUS_SUCCESS
;
4889 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4891 unsigned int i
, j
, single_len
;
4893 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4894 for (i
= 0; i
< entities
->num
; i
++)
4896 struct entity
*entity
= &entities
->base
[i
];
4897 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4899 if (entity
->u
.comclass
.progid
)
4901 *total_len
+= single_len
+ aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4905 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4906 *total_len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4908 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4909 *count
+= entity
->u
.comclass
.progids
.num
;
4914 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4915 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4917 struct progidredirect_data
*data
;
4922 /* setup new index entry */
4924 /* hash progid name */
4925 RtlInitUnicodeString(&str
, progid
);
4926 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4928 (*index
)->name_offset
= *data_offset
;
4929 (*index
)->name_len
= str
.Length
;
4930 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4931 (*index
)->data_len
= sizeof(*data
);
4932 (*index
)->rosterindex
= rosterindex
;
4934 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4936 /* setup data structure */
4937 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4938 data
->size
= sizeof(*data
);
4940 data
->clsid_offset
= *global_offset
;
4942 /* write progid string */
4943 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4944 memcpy(ptrW
, progid
, (*index
)->name_len
);
4945 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4947 /* write guid to global area */
4948 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4952 *global_offset
+= sizeof(GUID
);
4953 *data_offset
+= data
->size
;
4957 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4958 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4962 for (i
= 0; i
< entities
->num
; i
++)
4964 struct entity
*entity
= &entities
->base
[i
];
4965 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4967 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4968 struct comclassredirect_data
*comclass
;
4969 struct guid_index
*guid_index
;
4973 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4974 RtlGUIDFromString(&str
, &clsid
);
4976 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4977 comclass
= get_comclass_data(actctx
, guid_index
);
4979 if (entity
->u
.comclass
.progid
)
4980 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4981 index
, data_offset
, global_offset
, rosterindex
);
4983 for (j
= 0; j
< progids
->num
; j
++)
4984 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4985 index
, data_offset
, global_offset
, rosterindex
);
4990 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4992 unsigned int i
, j
, total_len
= 0, count
= 0;
4993 struct strsection_header
*header
;
4994 ULONG data_offset
, global_offset
;
4995 struct string_index
*index
;
4997 /* compute section length */
4998 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
5000 struct assembly
*assembly
= &actctx
->assemblies
[i
];
5002 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
5003 for (j
= 0; j
< assembly
->num_dlls
; j
++)
5005 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
5006 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
5010 total_len
+= sizeof(*header
);
5012 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
5013 if (!header
) return STATUS_NO_MEMORY
;
5015 memset(header
, 0, sizeof(*header
));
5016 header
->magic
= STRSECTION_MAGIC
;
5017 header
->size
= sizeof(*header
);
5018 header
->count
= count
;
5019 header
->global_offset
= header
->size
;
5020 header
->global_len
= count
*sizeof(GUID
);
5021 header
->index_offset
= header
->size
+ header
->global_len
;
5023 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
5024 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
5025 global_offset
= header
->global_offset
;
5027 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
5029 struct assembly
*assembly
= &actctx
->assemblies
[i
];
5031 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
5032 for (j
= 0; j
< assembly
->num_dlls
; j
++)
5034 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
5035 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
5041 return STATUS_SUCCESS
;
5044 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
5046 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
5049 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
5050 PACTCTX_SECTION_KEYED_DATA data
)
5052 struct progidredirect_data
*progid
;
5053 struct string_index
*index
;
5055 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
5057 if (!actctx
->comserver_section
)
5059 struct guidsection_header
*section
;
5061 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
5062 if (status
) return status
;
5064 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
5065 RtlFreeHeap(GetProcessHeap(), 0, section
);
5068 if (!actctx
->progid_section
)
5070 struct strsection_header
*section
;
5072 NTSTATUS status
= build_progid_section(actctx
, §ion
);
5073 if (status
) return status
;
5075 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
5076 RtlFreeHeap(GetProcessHeap(), 0, section
);
5079 index
= find_string_index(actctx
->progid_section
, name
);
5080 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
5084 progid
= get_progid_data(actctx
, index
);
5086 data
->ulDataFormatVersion
= 1;
5087 data
->lpData
= progid
;
5088 data
->ulLength
= progid
->size
;
5089 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
5090 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
5091 data
->lpSectionBase
= actctx
->progid_section
;
5092 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
5093 data
->hActCtx
= NULL
;
5095 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
5096 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
5099 return STATUS_SUCCESS
;
5102 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
5103 const UNICODE_STRING
*section_name
,
5104 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
5108 switch (section_kind
)
5110 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
5111 status
= find_dll_redirection(actctx
, section_name
, data
);
5113 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
5114 status
= find_window_class(actctx
, section_name
, data
);
5116 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
5117 status
= find_progid_redirection(actctx
, section_name
, data
);
5119 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
5120 FIXME("Unsupported yet section_kind %lx\n", section_kind
);
5121 return STATUS_SXS_SECTION_NOT_FOUND
;
5122 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES
:
5123 status
= find_activatable_class(actctx
, section_name
, data
);
5126 WARN("Unknown section_kind %lx\n", section_kind
);
5127 return STATUS_SXS_SECTION_NOT_FOUND
;
5130 if (status
!= STATUS_SUCCESS
) return status
;
5132 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
5134 actctx_addref(actctx
);
5135 data
->hActCtx
= actctx
;
5137 return STATUS_SUCCESS
;
5140 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
5141 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
5145 switch (section_kind
)
5147 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
5148 status
= find_tlib_redirection(actctx
, guid
, data
);
5150 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
5151 status
= find_comserver_redirection(actctx
, guid
, data
);
5153 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
5154 status
= find_cominterface_redirection(actctx
, guid
, data
);
5156 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
5157 status
= find_clr_surrogate(actctx
, guid
, data
);
5160 WARN("Unknown section_kind %lx\n", section_kind
);
5161 return STATUS_SXS_SECTION_NOT_FOUND
;
5164 if (status
!= STATUS_SUCCESS
) return status
;
5166 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5168 actctx_addref(actctx
);
5169 data
->hActCtx
= actctx
;
5171 return STATUS_SUCCESS
;
5174 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
5178 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
5180 struct assembly
*assembly
= &actctx
->assemblies
[i
];
5181 for (j
= 0; j
< assembly
->entities
.num
; j
++)
5183 struct entity
*entity
= &assembly
->entities
.base
[j
];
5184 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
5185 !wcscmp( entity
->u
.settings
.name
, settings
) &&
5186 !wcscmp( entity
->u
.settings
.ns
, ns
))
5187 return entity
->u
.settings
.value
;
5193 /* initialize the activation context for the current process */
5194 void actctx_init(void)
5199 ctx
.cbSize
= sizeof(ctx
);
5200 ctx
.lpSource
= NULL
;
5201 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
5202 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
5203 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
5205 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
5207 NtCurrentTeb()->Peb
->ActivationContextData
= process_actctx
;
5211 /***********************************************************************
5212 * RtlCreateActivationContext (NTDLL.@)
5214 * Create an activation context.
5216 * FIXME: function signature/prototype is wrong
5218 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
5220 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
5221 const WCHAR
*directory
= NULL
;
5222 ACTIVATION_CONTEXT
*actctx
;
5223 UNICODE_STRING nameW
;
5225 NTSTATUS status
= STATUS_NO_MEMORY
;
5227 struct actctx_loader acl
;
5229 TRACE("%p %08lx\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
5231 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
5232 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
5233 return STATUS_INVALID_PARAMETER
;
5235 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
5236 return STATUS_NO_MEMORY
;
5238 actctx
->magic
= ACTCTX_MAGIC
;
5239 actctx
->ref_count
= 1;
5240 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
5241 actctx
->config
.info
= NULL
;
5242 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
5243 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
5245 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
5253 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
5254 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
5256 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
5257 if ((p
= wcsrchr( dir
.Buffer
, '\\' ))) p
[1] = 0;
5258 actctx
->appdir
.info
= dir
.Buffer
;
5261 nameW
.Buffer
= NULL
;
5263 /* open file only if it's going to be used */
5264 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
5265 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
5267 WCHAR
*source
= NULL
;
5270 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5271 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
5273 DWORD dir_len
, source_len
;
5275 dir_len
= wcslen(pActCtx
->lpAssemblyDirectory
);
5276 source_len
= wcslen(pActCtx
->lpSource
);
5277 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5279 status
= STATUS_NO_MEMORY
;
5283 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5284 source
[dir_len
] = '\\';
5285 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5288 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5289 RtlFreeHeap( GetProcessHeap(), 0, source
);
5292 status
= STATUS_NO_SUCH_FILE
;
5295 status
= open_nt_file( &file
, &nameW
);
5298 RtlFreeUnicodeString( &nameW
);
5303 acl
.actctx
= actctx
;
5304 acl
.dependencies
= NULL
;
5305 acl
.num_dependencies
= 0;
5306 acl
.allocated_dependencies
= 0;
5308 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5309 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5311 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5313 /* if we have a resource it's a PE file */
5314 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5316 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5317 pActCtx
->lpResourceName
, lang
);
5318 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5319 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5320 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5322 else if (pActCtx
->lpSource
)
5324 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5325 file
, pActCtx
->lpResourceName
, lang
);
5326 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5327 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5328 NULL
, pActCtx
->lpResourceName
);
5330 else status
= STATUS_INVALID_PARAMETER
;
5334 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5337 if (file
) NtClose( file
);
5338 RtlFreeUnicodeString( &nameW
);
5340 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
5341 free_depend_manifests( &acl
);
5343 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
5344 else actctx_release( actctx
);
5348 if (file
) NtClose( file
);
5349 actctx_release( actctx
);
5354 /***********************************************************************
5355 * RtlAddRefActivationContext (NTDLL.@)
5357 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
5359 ACTIVATION_CONTEXT
*actctx
;
5361 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5365 /******************************************************************
5366 * RtlReleaseActivationContext (NTDLL.@)
5368 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5370 ACTIVATION_CONTEXT
*actctx
;
5372 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5375 /******************************************************************
5376 * RtlZombifyActivationContext (NTDLL.@)
5378 * FIXME: function prototype might be wrong
5380 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5382 FIXME("%p: stub\n", handle
);
5383 return STATUS_NOT_IMPLEMENTED
;
5386 /******************************************************************
5387 * RtlActivateActivationContext (NTDLL.@)
5389 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5391 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle
, cookie
);
5395 /******************************************************************
5396 * RtlActivateActivationContextEx (NTDLL.@)
5398 NTSTATUS WINAPI
RtlActivateActivationContextEx( ULONG flags
, TEB
*teb
, HANDLE handle
, ULONG_PTR
*cookie
)
5400 ACTIVATION_CONTEXT_STACK
*actctx_stack
= teb
->ActivationContextStackPointer
;
5401 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5403 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5404 return STATUS_NO_MEMORY
;
5406 frame
->Previous
= actctx_stack
->ActiveFrame
;
5407 frame
->ActivationContext
= handle
;
5409 actctx_stack
->ActiveFrame
= frame
;
5410 RtlAddRefActivationContext( handle
);
5412 *cookie
= (ULONG_PTR
)frame
;
5413 TRACE( "%p cookie=%Ix\n", handle
, *cookie
);
5414 return STATUS_SUCCESS
;
5418 /***********************************************************************
5419 * RtlDeactivateActivationContext (NTDLL.@)
5421 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5423 ACTIVATION_CONTEXT_STACK
*actctx_stack
= NtCurrentTeb()->ActivationContextStackPointer
;
5424 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5426 TRACE( "%lx cookie=%Ix\n", flags
, cookie
);
5428 /* find the right frame */
5429 top
= actctx_stack
->ActiveFrame
;
5430 for (frame
= top
; frame
; frame
= frame
->Previous
)
5431 if ((ULONG_PTR
)frame
== cookie
) break;
5434 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5436 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5437 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5439 /* pop everything up to and including frame */
5440 actctx_stack
->ActiveFrame
= frame
->Previous
;
5442 while (top
!= actctx_stack
->ActiveFrame
)
5444 frame
= top
->Previous
;
5445 RtlReleaseActivationContext( top
->ActivationContext
);
5446 RtlFreeHeap( GetProcessHeap(), 0, top
);
5452 /******************************************************************
5453 * RtlFreeThreadActivationContextStack (NTDLL.@)
5455 void WINAPI
RtlFreeThreadActivationContextStack(void)
5457 RtlFreeActivationContextStack( NtCurrentTeb()->ActivationContextStackPointer
);
5461 /******************************************************************
5462 * RtlFreeActivationContextStack (NTDLL.@)
5464 void WINAPI
RtlFreeActivationContextStack( ACTIVATION_CONTEXT_STACK
*actctx_stack
)
5466 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5468 frame
= actctx_stack
->ActiveFrame
;
5471 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5472 RtlReleaseActivationContext( frame
->ActivationContext
);
5473 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5476 actctx_stack
->ActiveFrame
= NULL
;
5480 /******************************************************************
5481 * RtlGetActiveActivationContext (NTDLL.@)
5483 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5485 RtlAddRefActivationContext( *handle
= get_current_actctx_no_addref() );
5486 return STATUS_SUCCESS
;
5490 /******************************************************************
5491 * RtlIsActivationContextActive (NTDLL.@)
5493 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5495 ACTIVATION_CONTEXT_STACK
*actctx_stack
= NtCurrentTeb()->ActivationContextStackPointer
;
5496 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5498 for (frame
= actctx_stack
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5499 if (frame
->ActivationContext
== handle
) return TRUE
;
5504 /***********************************************************************
5505 * RtlQueryInformationActivationContext (NTDLL.@)
5507 * Get information about an activation context.
5508 * FIXME: function signature/prototype may be wrong
5510 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5511 ULONG
class, PVOID buffer
,
5512 SIZE_T bufsize
, SIZE_T
*retlen
)
5514 ACTIVATION_CONTEXT
*actctx
;
5517 TRACE("%08lx %p %p %lu %p %Id %p\n", flags
, handle
,
5518 subinst
, class, buffer
, bufsize
, retlen
);
5520 if (retlen
) *retlen
= 0;
5521 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5525 case ActivationContextBasicInformation
:
5527 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5529 if (retlen
) *retlen
= sizeof(*info
);
5530 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5532 info
->hActCtx
= handle
;
5533 info
->dwFlags
= 0; /* FIXME */
5534 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5538 case ActivationContextDetailedInformation
:
5540 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5541 struct assembly
*assembly
= NULL
;
5542 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5545 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5547 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5549 if (assembly
&& assembly
->manifest
.info
)
5550 manifest_len
= wcslen(assembly
->manifest
.info
) + 1;
5551 if (actctx
->config
.info
) config_len
= wcslen(actctx
->config
.info
) + 1;
5552 if (actctx
->appdir
.info
) appdir_len
= wcslen(actctx
->appdir
.info
) + 1;
5553 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5555 if (retlen
) *retlen
= len
;
5556 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5559 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5560 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5561 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5562 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5563 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5564 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5565 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5566 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5567 ptr
= (LPWSTR
)(acdi
+ 1);
5570 acdi
->lpRootManifestPath
= ptr
;
5571 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5572 ptr
+= manifest_len
;
5574 else acdi
->lpRootManifestPath
= NULL
;
5577 acdi
->lpRootConfigurationPath
= ptr
;
5578 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5581 else acdi
->lpRootConfigurationPath
= NULL
;
5584 acdi
->lpAppDirPath
= ptr
;
5585 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5587 else acdi
->lpAppDirPath
= NULL
;
5591 case AssemblyDetailedInformationInActivationContext
:
5593 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5594 struct assembly
*assembly
;
5597 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5600 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5601 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5603 index
= *(DWORD
*)subinst
;
5604 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5606 assembly
= &actctx
->assemblies
[index
- 1];
5608 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5609 id_len
= wcslen(assembly_id
) + 1;
5610 if (assembly
->directory
) ad_len
= wcslen(assembly
->directory
) + 1;
5612 if (assembly
->manifest
.info
&&
5613 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5614 path_len
= wcslen(assembly
->manifest
.info
) + 1;
5616 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5618 if (retlen
) *retlen
= len
;
5619 if (!buffer
|| bufsize
< len
)
5621 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5622 return STATUS_BUFFER_TOO_SMALL
;
5625 afdi
->ulFlags
= 0; /* FIXME */
5626 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5627 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5628 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5629 /* FIXME afdi->liManifestLastWriteTime = 0; */
5630 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5631 afdi
->ulPolicyPathLength
= 0;
5632 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5633 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5634 afdi
->ulManifestVersionMajor
= 1;
5635 afdi
->ulManifestVersionMinor
= 0;
5636 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5637 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5638 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5639 ptr
= (LPWSTR
)(afdi
+ 1);
5640 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5641 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5645 afdi
->lpAssemblyManifestPath
= ptr
;
5646 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5648 } else afdi
->lpAssemblyManifestPath
= NULL
;
5649 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5652 afdi
->lpAssemblyDirectoryName
= ptr
;
5653 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5655 else afdi
->lpAssemblyDirectoryName
= NULL
;
5656 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5660 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5662 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5663 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5664 struct assembly
*assembly
;
5665 struct dll_redirect
*dll
;
5666 SIZE_T len
, dll_len
= 0;
5669 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5670 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5672 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5673 return STATUS_INVALID_PARAMETER
;
5674 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5676 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5677 return STATUS_INVALID_PARAMETER
;
5678 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5680 if (dll
->name
) dll_len
= wcslen(dll
->name
) + 1;
5681 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5683 if (!buffer
|| bufsize
< len
)
5685 if (retlen
) *retlen
= len
;
5686 return STATUS_BUFFER_TOO_SMALL
;
5688 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5689 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5690 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5691 afdi
->ulPathLength
= 0; /* FIXME */
5692 ptr
= (LPWSTR
)(afdi
+ 1);
5695 afdi
->lpFileName
= ptr
;
5696 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5697 } else afdi
->lpFileName
= NULL
;
5698 afdi
->lpFilePath
= NULL
; /* FIXME */
5702 case CompatibilityInformationInActivationContext
:
5707 COMPATIBILITY_CONTEXT_ELEMENT Elements
[1];
5709 struct assembly
*assembly
= NULL
;
5710 ULONG num_compat_contexts
= 0, n
;
5713 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5715 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5718 num_compat_contexts
= assembly
->num_compat_contexts
;
5719 len
= offsetof( struct acci
, Elements
[num_compat_contexts
] );
5721 if (retlen
) *retlen
= len
;
5722 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5724 acci
->ElementCount
= num_compat_contexts
;
5725 for (n
= 0; n
< num_compat_contexts
; ++n
)
5727 acci
->Elements
[n
] = assembly
->compat_contexts
[n
];
5732 case RunlevelInformationInActivationContext
:
5734 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5735 struct assembly
*assembly
;
5738 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5740 len
= sizeof(*acrli
);
5741 if (retlen
) *retlen
= len
;
5742 if (!buffer
|| bufsize
< len
)
5743 return STATUS_BUFFER_TOO_SMALL
;
5745 assembly
= actctx
->assemblies
;
5748 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5749 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5754 FIXME( "class %lu not implemented\n", class );
5755 return STATUS_NOT_IMPLEMENTED
;
5757 return STATUS_SUCCESS
;
5760 /***********************************************************************
5761 * RtlFindActivationContextSectionString (NTDLL.@)
5763 * Find information about a string in an activation context.
5764 * FIXME: function signature/prototype may be wrong
5766 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5767 const UNICODE_STRING
*section_name
, PVOID ptr
)
5769 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5770 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5771 ACTIVATION_CONTEXT
*actctx
;
5773 TRACE("%08lx %s %lu %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5774 debugstr_us(section_name
), data
);
5778 FIXME("expected guid == NULL\n");
5779 return STATUS_INVALID_PARAMETER
;
5781 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5783 FIXME("unknown flags %08lx\n", flags
);
5784 return STATUS_INVALID_PARAMETER
;
5786 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5787 !section_name
|| !section_name
->Buffer
)
5789 WARN("invalid parameter\n");
5790 return STATUS_INVALID_PARAMETER
;
5793 actctx
= check_actctx( get_current_actctx_no_addref() );
5794 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5796 if (status
!= STATUS_SUCCESS
)
5797 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5802 /***********************************************************************
5803 * RtlFindActivationContextSectionGuid (NTDLL.@)
5805 * Find information about a GUID in an activation context.
5806 * FIXME: function signature/prototype may be wrong
5808 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5809 const GUID
*guid
, void *ptr
)
5811 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5812 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5813 ACTIVATION_CONTEXT
*actctx
;
5815 TRACE("%08lx %s %lu %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5819 FIXME("expected extguid == NULL\n");
5820 return STATUS_INVALID_PARAMETER
;
5823 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5825 FIXME("unknown flags %08lx\n", flags
);
5826 return STATUS_INVALID_PARAMETER
;
5829 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5830 return STATUS_INVALID_PARAMETER
;
5832 actctx
= check_actctx( get_current_actctx_no_addref() );
5833 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5835 if (status
!= STATUS_SUCCESS
)
5836 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5842 /***********************************************************************
5843 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5845 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5846 const WCHAR
*settings
, WCHAR
*buffer
,
5847 SIZE_T size
, SIZE_T
*written
)
5849 ACTIVATION_CONTEXT
*actctx
;
5854 WARN( "unknown flags %08lx\n", flags
);
5855 return STATUS_INVALID_PARAMETER
;
5860 if (wcscmp( ns
, windowsSettings2005NSW
) &&
5861 wcscmp( ns
, windowsSettings2011NSW
) &&
5862 wcscmp( ns
, windowsSettings2016NSW
) &&
5863 wcscmp( ns
, windowsSettings2017NSW
) &&
5864 wcscmp( ns
, windowsSettings2019NSW
) &&
5865 wcscmp( ns
, windowsSettings2020NSW
))
5866 return STATUS_INVALID_PARAMETER
;
5868 else ns
= windowsSettings2005NSW
;
5870 if (!handle
) handle
= process_actctx
;
5871 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5873 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5875 if (written
) *written
= wcslen(res
) + 1;
5876 if (size
< wcslen(res
)) return STATUS_BUFFER_TOO_SMALL
;
5877 wcscpy( buffer
, res
);
5878 return STATUS_SUCCESS
;