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 dllredirect_data
208 struct tlibredirect_data
222 enum comclass_threadingmodel
224 ThreadingModel_Apartment
= 1,
225 ThreadingModel_Free
= 2,
226 ThreadingModel_No
= 3,
227 ThreadingModel_Both
= 4,
228 ThreadingModel_Neutral
= 5
231 enum comclass_miscfields
235 MiscStatusContent
= 4,
236 MiscStatusThumbnail
= 8,
237 MiscStatusDocPrint
= 16
240 struct comclassredirect_data
254 ULONG clrdata_offset
;
256 DWORD miscstatuscontent
;
257 DWORD miscstatusthumbnail
;
258 DWORD miscstatusicon
;
259 DWORD miscstatusdocprint
;
268 struct ifacepsredirect_data
280 struct clrsurrogate_data
285 ULONG version_offset
;
300 ULONG version_offset
;
304 struct progidredirect_data
315 Sections are accessible by string or guid key, that defines two types of sections.
316 All sections of each type have same magic value and header structure, index
317 data could be of two possible types too. So every string based section uses
318 the same index format, same applies to guid sections - they share same guid index
321 - window class redirection section is a plain buffer with following format:
325 <data[]> --- <original name>
330 Header is fixed length structure - struct strsection_header,
331 contains redirected classes count;
333 Index is an array of fixed length index records, each record is
336 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
338 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
339 others are relative to section itself.
341 - dll redirect section format:
345 <data[]> --- <dll name>
348 This section doesn't seem to carry any payload data except dll names.
350 - typelib section format:
358 Header is fixed length, index is an array of fixed length 'struct guid_index'.
359 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
360 4-bytes aligned as a whole.
362 Module name offsets are relative to section, helpstring offset is relative to data
365 - comclass section format:
370 <data[]> --- <data> --- <data>
376 This section uses two index records per comclass, one entry contains original guid
377 as specified by context, another one has a generated guid. Index and strings handling
378 is similar to typelib sections.
380 For CLR classes additional data is stored after main COM class data, it contains
381 class name and runtime version string, see 'struct clrclass_data'.
383 Module name offsets are relative to section, progid offset is relative to data
386 - COM interface section format:
393 Interface section contains data for proxy/stubs and external proxy/stubs. External
394 ones are defined at assembly level, so this section has no module information.
395 All records are indexed with 'iid' value from manifest. There an exception for
396 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
397 redirect data, but index is still 'iid' from manifest.
399 Interface name offset is relative to data structure itself.
401 - CLR surrogates section format:
409 There's nothing special about this section, same way to store strings is used,
410 no modules part as it belongs to assembly level, not a file.
412 - ProgID section format:
417 <data[]> --- <progid>
420 This sections uses generated alias guids from COM server section. This way
421 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
422 is stored too, aligned.
429 unsigned int allocated
;
450 WCHAR
*name
; /* clrClass: class name */
451 WCHAR
*version
; /* clrClass: CLR runtime version */
454 DWORD miscstatuscontent
;
455 DWORD miscstatusthumbnail
;
456 DWORD miscstatusicon
;
457 DWORD miscstatusdocprint
;
458 struct progids progids
;
465 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
493 unsigned int allocated
;
500 struct entity_array entities
;
505 APPLICATION_MANIFEST
,
507 ASSEMBLY_SHARED_MANIFEST
,
512 enum assembly_type type
;
513 struct assembly_identity id
;
514 struct file_info manifest
;
517 struct dll_redirect
*dlls
;
518 unsigned int num_dlls
;
519 unsigned int allocated_dlls
;
520 struct entity_array entities
;
521 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
522 ULONG num_compat_contexts
;
523 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
527 enum context_sections
529 WINDOWCLASS_SECTION
= 1,
530 DLLREDIRECT_SECTION
= 2,
531 TLIBREDIRECT_SECTION
= 4,
532 SERVERREDIRECT_SECTION
= 8,
533 IFACEREDIRECT_SECTION
= 16,
534 CLRSURROGATES_SECTION
= 32,
535 PROGIDREDIRECT_SECTION
= 64
538 typedef struct _ACTIVATION_CONTEXT
542 struct file_info config
;
543 struct file_info appdir
;
544 struct assembly
*assemblies
;
545 unsigned int num_assemblies
;
546 unsigned int allocated_assemblies
;
549 struct strsection_header
*wndclass_section
;
550 struct strsection_header
*dllredirect_section
;
551 struct strsection_header
*progid_section
;
552 struct guidsection_header
*tlib_section
;
553 struct guidsection_header
*comserver_section
;
554 struct guidsection_header
*ifaceps_section
;
555 struct guidsection_header
*clrsurrogate_section
;
556 } ACTIVATION_CONTEXT
;
560 ACTIVATION_CONTEXT
*actctx
;
561 struct assembly_identity
*dependencies
;
562 unsigned int num_dependencies
;
563 unsigned int allocated_dependencies
;
566 static const xmlstr_t empty_xmlstr
;
569 static const WCHAR current_archW
[] = L
"x86";
570 #elif defined __x86_64__
571 static const WCHAR current_archW
[] = L
"amd64";
572 #elif defined __arm__
573 static const WCHAR current_archW
[] = L
"arm";
574 #elif defined __aarch64__
575 static const WCHAR current_archW
[] = L
"arm64";
577 static const WCHAR current_archW
[] = L
"none";
580 static const WCHAR asmv1W
[] = L
"urn:schemas-microsoft-com:asm.v1";
581 static const WCHAR asmv2W
[] = L
"urn:schemas-microsoft-com:asm.v2";
582 static const WCHAR asmv3W
[] = L
"urn:schemas-microsoft-com:asm.v3";
583 static const WCHAR compatibilityNSW
[] = L
"urn:schemas-microsoft-com:compatibility.v1";
584 static const WCHAR windowsSettings2005NSW
[] = L
"http://schemas.microsoft.com/SMI/2005/WindowsSettings";
585 static const WCHAR windowsSettings2011NSW
[] = L
"http://schemas.microsoft.com/SMI/2011/WindowsSettings";
586 static const WCHAR windowsSettings2016NSW
[] = L
"http://schemas.microsoft.com/SMI/2016/WindowsSettings";
587 static const WCHAR windowsSettings2017NSW
[] = L
"http://schemas.microsoft.com/SMI/2017/WindowsSettings";
595 static const struct olemisc_entry olemisc_values
[] =
597 { L
"activatewhenvisible", OLEMISC_ACTIVATEWHENVISIBLE
},
598 { L
"actslikebutton", OLEMISC_ACTSLIKEBUTTON
},
599 { L
"actslikelabel", OLEMISC_ACTSLIKELABEL
},
600 { L
"alignable", OLEMISC_ALIGNABLE
},
601 { L
"alwaysrun", OLEMISC_ALWAYSRUN
},
602 { L
"canlinkbyole1", OLEMISC_CANLINKBYOLE1
},
603 { L
"cantlinkinside", OLEMISC_CANTLINKINSIDE
},
604 { L
"ignoreactivatewhenvisible", OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
605 { L
"imemode", OLEMISC_IMEMODE
},
606 { L
"insertnotreplace", OLEMISC_INSERTNOTREPLACE
},
607 { L
"insideout", OLEMISC_INSIDEOUT
},
608 { L
"invisibleatruntime", OLEMISC_INVISIBLEATRUNTIME
},
609 { L
"islinkobject", OLEMISC_ISLINKOBJECT
},
610 { L
"nouiactivate", OLEMISC_NOUIACTIVATE
},
611 { L
"onlyiconic", OLEMISC_ONLYICONIC
},
612 { L
"recomposeonresize", OLEMISC_RECOMPOSEONRESIZE
},
613 { L
"renderingisdeviceindependent", OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
614 { L
"setclientsitefirst", OLEMISC_SETCLIENTSITEFIRST
},
615 { L
"simpleframe", OLEMISC_SIMPLEFRAME
},
616 { L
"static", OLEMISC_STATIC
},
617 { L
"supportsmultilevelundo", OLEMISC_SUPPORTSMULTILEVELUNDO
},
618 { L
"wantstomenumerge", OLEMISC_WANTSTOMENUMERGE
}
621 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
622 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
624 static WCHAR
*strdupW(const WCHAR
* str
)
628 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str
) + 1) * sizeof(WCHAR
))))
630 return wcscpy(ptr
, str
);
633 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
637 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
639 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
645 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
647 return !wcsncmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
650 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
652 return !wcsnicmp(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
655 static BOOL
xml_attr_cmp( const struct xml_attr
*attr
, const WCHAR
*str
)
657 return xmlstr_cmp( &attr
->name
, str
);
660 static BOOL
xml_name_cmp( const struct xml_elem
*elem1
, const struct xml_elem
*elem2
)
662 return (elem1
->name
.len
== elem2
->name
.len
&&
663 elem1
->ns
.len
== elem2
->ns
.len
&&
664 !wcsncmp( elem1
->name
.ptr
, elem2
->name
.ptr
, elem1
->name
.len
) &&
665 !wcsncmp( elem1
->ns
.ptr
, elem2
->ns
.ptr
, elem1
->ns
.len
));
668 static inline BOOL
xml_elem_cmp(const struct xml_elem
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
670 if (!xmlstr_cmp( &elem
->name
, str
)) return FALSE
;
671 if (xmlstr_cmp( &elem
->ns
, namespace )) return TRUE
;
672 if (!wcscmp( namespace, asmv1W
))
674 if (xmlstr_cmp( &elem
->ns
, asmv2W
)) return TRUE
;
675 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
677 else if (!wcscmp( namespace, asmv2W
))
679 if (xmlstr_cmp( &elem
->ns
, asmv3W
)) return TRUE
;
684 static inline BOOL
isxmlspace( WCHAR ch
)
686 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
689 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
691 return debugstr_wn(str
->ptr
, str
->len
);
694 static inline const char *debugstr_xml_elem( const struct xml_elem
*elem
)
696 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem
->name
.ptr
, elem
->name
.len
),
697 debugstr_wn( elem
->ns
.ptr
, elem
->ns
.len
));
700 static inline const char *debugstr_xml_attr( const struct xml_attr
*attr
)
702 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr
->name
.ptr
, attr
->name
.len
),
703 debugstr_wn( attr
->value
.ptr
, attr
->value
.len
));
706 static inline const char* debugstr_version(const struct assembly_version
*ver
)
708 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
711 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
715 LDR_DATA_TABLE_ENTRY
*pldr
;
717 LdrLockLoaderLock(0, NULL
, &magic
);
718 status
= LdrFindEntryForAddress( module
, &pldr
);
719 if (status
== STATUS_SUCCESS
)
721 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
722 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
724 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
725 str
->Length
= pldr
->FullDllName
.Length
;
726 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
728 else status
= STATUS_NO_MEMORY
;
730 LdrUnlockLoaderLock(0, magic
);
734 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
736 struct assembly
*assembly
;
738 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
741 unsigned int new_count
;
742 if (actctx
->assemblies
)
744 new_count
= actctx
->allocated_assemblies
* 2;
745 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
746 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
751 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
753 if (!ptr
) return NULL
;
754 actctx
->assemblies
= ptr
;
755 actctx
->allocated_assemblies
= new_count
;
758 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
763 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
765 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
768 unsigned int new_count
;
771 new_count
= assembly
->allocated_dlls
* 2;
772 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
773 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
778 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
780 if (!ptr
) return NULL
;
781 assembly
->dlls
= ptr
;
782 assembly
->allocated_dlls
= new_count
;
784 return &assembly
->dlls
[assembly
->num_dlls
++];
787 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
790 if (assembly
->num_compat_contexts
)
792 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
793 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
794 assembly
->compat_contexts
,
795 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
799 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
801 if (!ptr
) return NULL
;
802 assembly
->compat_contexts
= ptr
;
803 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
806 static void free_assembly_identity(struct assembly_identity
*ai
)
808 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
809 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
810 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
811 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
812 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
815 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
817 struct entity
* entity
;
819 if (array
->num
== array
->allocated
)
822 unsigned int new_count
;
825 new_count
= array
->allocated
* 2;
826 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
827 array
->base
, new_count
* sizeof(*array
->base
) );
832 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
834 if (!ptr
) return NULL
;
836 array
->allocated
= new_count
;
838 entity
= &array
->base
[array
->num
++];
843 static void free_entity_array(struct entity_array
*array
)
846 for (i
= 0; i
< array
->num
; i
++)
848 struct entity
*entity
= &array
->base
[i
];
849 switch (entity
->kind
)
851 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
852 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
853 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
854 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
855 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.name
);
856 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.version
);
857 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
858 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
859 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
861 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
862 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
863 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
864 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
865 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
866 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
868 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
869 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
870 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
872 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
873 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
875 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
876 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
877 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
878 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
880 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
:
881 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.name
);
882 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.value
);
883 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.settings
.ns
);
886 FIXME("Unknown entity kind %d\n", entity
->kind
);
889 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
892 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
894 if (!str1
) return !str2
;
895 return str2
&& !RtlCompareUnicodeStrings( str1
, wcslen(str1
), str2
, wcslen(str2
), TRUE
);
898 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
899 const struct assembly_identity
*id2
)
901 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
902 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
903 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
905 if (id1
->language
&& id2
->language
&& !is_matching_string( id1
->language
, id2
->language
))
907 if (wcscmp( L
"*", id1
->language
) && wcscmp( L
"*", id2
->language
))
910 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
911 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
912 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
913 if (id1
->version
.build
== id2
->version
.build
&&
914 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
918 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
919 struct assembly_identity
* ai
)
923 /* check if we already have that assembly */
925 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
926 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
928 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
929 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
930 ai
->version
.build
, ai
->version
.revision
);
934 for (i
= 0; i
< acl
->num_dependencies
; i
++)
935 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
937 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
938 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
939 ai
->version
.build
, ai
->version
.revision
);
943 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
946 unsigned int new_count
;
947 if (acl
->dependencies
)
949 new_count
= acl
->allocated_dependencies
* 2;
950 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
951 new_count
* sizeof(acl
->dependencies
[0]));
956 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
958 if (!ptr
) return FALSE
;
959 acl
->dependencies
= ptr
;
960 acl
->allocated_dependencies
= new_count
;
962 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
967 static void free_depend_manifests(struct actctx_loader
* acl
)
970 for (i
= 0; i
< acl
->num_dependencies
; i
++)
971 free_assembly_identity(&acl
->dependencies
[i
]);
972 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
975 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
977 static const WCHAR mskeyW
[] = L
"deadbeef";
978 const WCHAR
*arch
= ai
->arch
? ai
->arch
: L
"none";
979 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: L
"none";
980 const WCHAR
*lang
= ai
->language
? ai
->language
: L
"none";
981 const WCHAR
*name
= ai
->name
? ai
->name
: L
"none";
982 SIZE_T size
= (wcslen(arch
) + 1 + wcslen(name
) + 1 + wcslen(key
) + 24 + 1 +
983 wcslen(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
986 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
994 swprintf( ret
+ wcslen(ret
), size
- wcslen(ret
), L
"%u.%u.%u.%u",
995 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
999 wcscat( ret
, mskeyW
);
1003 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1008 wcscat( buffer
, prefix
);
1017 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1019 WCHAR version
[64], *ret
;
1022 swprintf( version
, ARRAY_SIZE(version
), L
"%u.%u.%u.%u",
1023 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1024 if (ai
->name
) size
+= wcslen(ai
->name
) * sizeof(WCHAR
);
1025 if (ai
->arch
) size
+= wcslen(L
",processorArchitecture=") + wcslen(ai
->arch
) + 2;
1026 if (ai
->public_key
) size
+= wcslen(L
",publicKeyToken=") + wcslen(ai
->public_key
) + 2;
1027 if (ai
->type
) size
+= wcslen(L
",type=") + wcslen(ai
->type
) + 2;
1028 size
+= wcslen(L
",version=") + wcslen(version
) + 2;
1030 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1033 if (ai
->name
) wcscpy( ret
, ai
->name
);
1035 append_string( ret
, L
",processorArchitecture=", ai
->arch
);
1036 append_string( ret
, L
",publicKeyToken=", ai
->public_key
);
1037 append_string( ret
, L
",type=", ai
->type
);
1038 append_string( ret
, L
",version=", version
);
1042 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1044 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1046 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1049 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
1058 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1060 InterlockedIncrement( &actctx
->ref_count
);
1063 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1065 if (!InterlockedDecrement( &actctx
->ref_count
))
1069 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1071 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1072 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1074 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1075 free_entity_array( &dll
->entities
);
1076 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
1077 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
1079 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
1080 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
1081 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
1082 RtlFreeHeap( GetProcessHeap(), 0, assembly
->compat_contexts
);
1083 free_entity_array( &assembly
->entities
);
1084 free_assembly_identity(&assembly
->id
);
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
1091 RtlFreeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
1092 RtlFreeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
1093 RtlFreeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
1094 RtlFreeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1095 RtlFreeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
1097 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
1101 static BOOL
set_error( xmlbuf_t
*xmlbuf
)
1103 xmlbuf
->error
= TRUE
;
1107 static BOOL
is_xmlns_attr( const struct xml_attr
*attr
)
1109 const int len
= wcslen( L
"xmlns" );
1110 if (attr
->name
.len
< len
) return FALSE
;
1111 if (wcsncmp( attr
->name
.ptr
, L
"xmlns", len
)) return FALSE
;
1112 return (attr
->name
.len
== len
|| attr
->name
.ptr
[len
] == ':');
1115 static void push_xmlns( xmlbuf_t
*xmlbuf
, const struct xml_attr
*attr
)
1117 const int len
= wcslen( L
"xmlns" );
1118 struct xml_attr
*ns
;
1120 if (xmlbuf
->ns_pos
== MAX_NAMESPACES
- 1)
1122 FIXME( "too many namespaces in manifest\n" );
1123 set_error( xmlbuf
);
1126 ns
= &xmlbuf
->namespaces
[xmlbuf
->ns_pos
++];
1127 ns
->value
= attr
->value
;
1128 if (attr
->name
.len
> len
)
1130 ns
->name
.ptr
= attr
->name
.ptr
+ len
+ 1;
1131 ns
->name
.len
= attr
->name
.len
- len
- 1;
1133 else ns
->name
= empty_xmlstr
;
1136 static xmlstr_t
find_xmlns( xmlbuf_t
*xmlbuf
, const xmlstr_t
*name
)
1140 for (i
= xmlbuf
->ns_pos
- 1; i
>= 0; i
--)
1142 if (xmlbuf
->namespaces
[i
].name
.len
== name
->len
&&
1143 !wcsncmp( xmlbuf
->namespaces
[i
].name
.ptr
, name
->ptr
, name
->len
))
1144 return xmlbuf
->namespaces
[i
].value
;
1146 if (xmlbuf
->ns_pos
) WARN( "namespace %s not found\n", debugstr_xmlstr( name
));
1147 return empty_xmlstr
;
1150 static BOOL
next_xml_attr(xmlbuf_t
*xmlbuf
, struct xml_attr
*attr
, BOOL
*end
)
1155 if (xmlbuf
->error
) return FALSE
;
1157 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1160 if (xmlbuf
->ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1162 if (*xmlbuf
->ptr
== '/')
1165 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1166 return set_error( xmlbuf
);
1173 if (*xmlbuf
->ptr
== '>')
1180 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1182 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1184 attr
->name
.ptr
= xmlbuf
->ptr
;
1185 attr
->name
.len
= ptr
-xmlbuf
->ptr
;
1188 /* skip spaces before '=' */
1189 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1190 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return set_error( xmlbuf
);
1192 /* skip '=' itself */
1194 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1196 /* skip spaces after '=' */
1197 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1199 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return set_error( xmlbuf
);
1202 attr
->value
.ptr
= ptr
;
1203 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1205 while (ptr
< xmlbuf
->end
&& *ptr
!= quote
) ptr
++;
1206 if (ptr
== xmlbuf
->end
)
1208 xmlbuf
->ptr
= xmlbuf
->end
;
1209 return set_error( xmlbuf
);
1212 attr
->value
.len
= ptr
- attr
->value
.ptr
;
1213 xmlbuf
->ptr
= ptr
+ 1;
1214 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1216 return set_error( xmlbuf
);
1219 static void read_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
)
1221 const WCHAR
* ptr
= xmlbuf
->ptr
;
1223 elem
->ns
= empty_xmlstr
;
1224 elem
->name
.ptr
= ptr
;
1225 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && *ptr
!= '/')
1229 elem
->ns
.ptr
= elem
->name
.ptr
;
1230 elem
->ns
.len
= ptr
- elem
->ns
.ptr
;
1231 elem
->name
.ptr
= ptr
+ 1;
1235 elem
->name
.len
= ptr
- elem
->name
.ptr
;
1239 static BOOL
next_xml_elem( xmlbuf_t
*xmlbuf
, struct xml_elem
*elem
, const struct xml_elem
*parent
)
1242 struct xml_attr attr
;
1246 xmlbuf
->ns_pos
= parent
->ns_pos
; /* restore namespace stack to parent state */
1248 if (xmlbuf
->error
) return FALSE
;
1252 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1253 if (ptr
== xmlbuf
->end
)
1255 xmlbuf
->ptr
= xmlbuf
->end
;
1256 return set_error( xmlbuf
);
1259 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1261 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1262 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1264 if (ptr
+ 3 > xmlbuf
->end
)
1266 xmlbuf
->ptr
= xmlbuf
->end
;
1267 return set_error( xmlbuf
);
1269 xmlbuf
->ptr
= ptr
+ 3;
1275 /* check for element terminating the parent element */
1276 if (ptr
< xmlbuf
->end
&& *ptr
== '/')
1279 read_xml_elem( xmlbuf
, elem
);
1280 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1281 if (!xml_name_cmp( elem
, parent
))
1283 ERR( "wrong closing element %s for %s\n",
1284 debugstr_xmlstr(&elem
->name
), debugstr_xmlstr(&parent
->name
));
1285 return set_error( xmlbuf
);
1287 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
)) xmlbuf
->ptr
++;
1288 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
++ != '>') return set_error( xmlbuf
);
1292 read_xml_elem( xmlbuf
, elem
);
1294 /* parse namespace attributes */
1296 while (next_xml_attr( &attr_buf
, &attr
, &end
))
1298 if (is_xmlns_attr( &attr
)) push_xmlns( xmlbuf
, &attr
);
1300 elem
->ns
= find_xmlns( xmlbuf
, &elem
->ns
);
1301 elem
->ns_pos
= xmlbuf
->ns_pos
;
1303 if (xmlbuf
->ptr
!= xmlbuf
->end
) return TRUE
;
1305 return set_error( xmlbuf
);
1308 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1310 /* FIXME: parse attributes */
1313 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1315 if (ptr
[0] == '?' && ptr
[1] == '>')
1317 xmlbuf
->ptr
= ptr
+ 2;
1324 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1328 if (xmlbuf
->error
) return FALSE
;
1330 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
; ptr
++) if (*ptr
== '<') break;
1331 if (ptr
== xmlbuf
->end
) return set_error( xmlbuf
);
1333 content
->ptr
= xmlbuf
->ptr
;
1334 content
->len
= ptr
- xmlbuf
->ptr
;
1340 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1342 unsigned int ver
[4];
1346 /* major.minor.build.revision */
1347 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1348 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1350 if (*curr
>= '0' && *curr
<= '9')
1352 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1353 if (ver
[pos
] >= 0x10000) goto error
;
1355 else if (*curr
== '.')
1357 if (++pos
>= 4) goto error
;
1361 version
->major
= ver
[0];
1362 version
->minor
= ver
[1];
1363 version
->build
= ver
[2];
1364 version
->revision
= ver
[3];
1368 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1372 static void parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1374 struct xml_attr attr
;
1376 while (next_xml_attr(xmlbuf
, &attr
, end
))
1378 if (!is_xmlns_attr( &attr
)) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr
));
1382 static void parse_expect_end_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1384 struct xml_elem elem
;
1386 if (next_xml_elem(xmlbuf
, &elem
, parent
))
1388 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem
) );
1389 set_error( xmlbuf
);
1393 static void parse_unknown_elem(xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1395 struct xml_elem elem
;
1396 struct xml_attr attr
;
1399 while (next_xml_attr(xmlbuf
, &attr
, &end
));
1402 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1403 parse_unknown_elem(xmlbuf
, &elem
);
1406 static void parse_assembly_identity_elem(xmlbuf_t
*xmlbuf
, ACTIVATION_CONTEXT
*actctx
,
1407 struct assembly_identity
* ai
, const struct xml_elem
*parent
)
1409 struct xml_attr attr
;
1412 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1414 if (xml_attr_cmp(&attr
, L
"name"))
1416 if (!(ai
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1418 else if (xml_attr_cmp(&attr
, L
"type"))
1420 if (!(ai
->type
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1422 else if (xml_attr_cmp(&attr
, L
"version"))
1424 if (!parse_version(&attr
.value
, &ai
->version
)) set_error( xmlbuf
);
1426 else if (xml_attr_cmp(&attr
, L
"processorArchitecture"))
1428 if (!(ai
->arch
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1430 else if (xml_attr_cmp(&attr
, L
"publicKeyToken"))
1432 if (!(ai
->public_key
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1434 else if (xml_attr_cmp(&attr
, L
"language"))
1436 if (!(ai
->language
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1438 else if (!is_xmlns_attr( &attr
))
1440 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1444 TRACE( "name=%s version=%s arch=%s\n",
1445 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1447 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1450 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1452 if (value
->len
== 0) return ThreadingModel_No
;
1453 if (xmlstr_cmp(value
, L
"Apartment"))
1454 return ThreadingModel_Apartment
;
1455 else if (xmlstr_cmp(value
, L
"Free"))
1456 return ThreadingModel_Free
;
1457 else if (xmlstr_cmp(value
, L
"Both"))
1458 return ThreadingModel_Both
;
1459 else if (xmlstr_cmp(value
, L
"Neutral"))
1460 return ThreadingModel_Neutral
;
1462 return ThreadingModel_No
;
1465 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1470 max
= ARRAY_SIZE(olemisc_values
) - 1;
1478 c
= wcsncmp(olemisc_values
[n
].name
, str
, len
);
1479 if (!c
&& !olemisc_values
[n
].name
[len
])
1480 return olemisc_values
[n
].value
;
1488 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1492 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1494 const WCHAR
*str
= value
->ptr
, *start
;
1498 /* it's comma separated list of flags */
1499 while (i
< value
->len
)
1502 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1504 flags
|= get_olemisc_value(start
, str
-start
);
1506 /* skip separator */
1514 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1516 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1518 if (progids
->allocated
== 0)
1520 progids
->allocated
= 4;
1521 if (!(progids
->progids
= RtlAllocateHeap(GetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1524 if (progids
->allocated
== progids
->num
)
1526 WCHAR
**new_progids
= RtlReAllocateHeap(GetProcessHeap(), 0, progids
->progids
,
1527 2 * progids
->allocated
* sizeof(WCHAR
*));
1528 if (!new_progids
) return FALSE
;
1529 progids
->allocated
*= 2;
1530 progids
->progids
= new_progids
;
1533 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1539 static void parse_com_class_progid(xmlbuf_t
*xmlbuf
, struct entity
*entity
, const struct xml_elem
*parent
)
1544 parse_expect_no_attr(xmlbuf
, &end
);
1545 if (end
) set_error( xmlbuf
);
1546 if (!parse_text_content(xmlbuf
, &content
)) return;
1548 if (!com_class_add_progid(&content
, entity
)) set_error( xmlbuf
);
1549 parse_expect_end_elem(xmlbuf
, parent
);
1552 static void parse_com_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
, struct actctx_loader
*acl
,
1553 const struct xml_elem
*parent
)
1555 struct xml_elem elem
;
1556 struct xml_attr attr
;
1558 struct entity
* entity
;
1560 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1562 set_error( xmlbuf
);
1566 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1568 if (xml_attr_cmp(&attr
, L
"clsid"))
1570 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1572 else if (xml_attr_cmp(&attr
, L
"progid"))
1574 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1576 else if (xml_attr_cmp(&attr
, L
"tlbid"))
1578 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1580 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
1582 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
1584 else if (xml_attr_cmp(&attr
, L
"miscStatus"))
1586 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr
.value
);
1588 else if (xml_attr_cmp(&attr
, L
"miscStatusContent"))
1590 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr
.value
);
1592 else if (xml_attr_cmp(&attr
, L
"miscStatusThumbnail"))
1594 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr
.value
);
1596 else if (xml_attr_cmp(&attr
, L
"miscStatusIcon"))
1598 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr
.value
);
1600 else if (xml_attr_cmp(&attr
, L
"miscStatusDocPrint"))
1602 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr
.value
);
1604 else if (xml_attr_cmp(&attr
, L
"description"))
1608 else if (!is_xmlns_attr( &attr
))
1610 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1614 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1615 if (entity
->u
.comclass
.progid
)
1616 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1620 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1622 if (xml_elem_cmp(&elem
, L
"progid", asmv1W
))
1624 parse_com_class_progid(xmlbuf
, entity
, &elem
);
1628 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1629 parse_unknown_elem(xmlbuf
, &elem
);
1633 if (entity
->u
.comclass
.progids
.num
)
1634 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1637 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1642 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1644 if (*curr
>= '0' && *curr
<= '9')
1645 num
= num
* 10 + *curr
- '0';
1648 ERR("wrong numeric value %s\n", debugstr_xmlstr(str
));
1652 entity
->u
.ifaceps
.nummethods
= num
;
1657 static void parse_add_interface_class( xmlbuf_t
*xmlbuf
, struct entity_array
*entities
,
1658 struct actctx_loader
*acl
, WCHAR
*clsid
)
1660 struct entity
*entity
;
1665 if (!(str
= strdupW(clsid
)))
1667 set_error( xmlbuf
);
1671 if (!(entity
= add_entity(entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1673 RtlFreeHeap(GetProcessHeap(), 0, str
);
1674 set_error( xmlbuf
);
1678 entity
->u
.comclass
.clsid
= str
;
1679 entity
->u
.comclass
.model
= ThreadingModel_Both
;
1681 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1684 static void parse_cominterface_proxy_stub_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1685 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1687 WCHAR
*psclsid
= NULL
;
1688 struct entity
*entity
;
1689 struct xml_attr attr
;
1692 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1694 set_error( xmlbuf
);
1698 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1700 if (xml_attr_cmp(&attr
, L
"iid"))
1702 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1704 else if (xml_attr_cmp(&attr
, L
"name"))
1706 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1708 else if (xml_attr_cmp(&attr
, L
"baseInterface"))
1710 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1711 entity
->u
.ifaceps
.mask
|= BaseIface
;
1713 else if (xml_attr_cmp(&attr
, L
"numMethods"))
1715 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
1716 entity
->u
.ifaceps
.mask
|= NumMethods
;
1718 else if (xml_attr_cmp(&attr
, L
"tlbid"))
1720 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1722 else if (xml_attr_cmp(&attr
, L
"proxyStubClsid32"))
1724 if (!(psclsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1727 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
1730 else if (!is_xmlns_attr( &attr
))
1732 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1736 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1737 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1739 parse_add_interface_class(xmlbuf
, &dll
->entities
, acl
, psclsid
? psclsid
: entity
->u
.ifaceps
.iid
);
1741 RtlFreeHeap(GetProcessHeap(), 0, psclsid
);
1744 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1746 WORD
*flags
= &entity
->u
.typelib
.flags
;
1747 const WCHAR
*str
= value
->ptr
, *start
;
1752 /* it's comma separated list of flags */
1753 while (i
< value
->len
)
1756 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1758 if (!wcsnicmp(start
, L
"RESTRICTED", str
-start
))
1759 *flags
|= LIBFLAG_FRESTRICTED
;
1760 else if (!wcsnicmp(start
, L
"CONTROL", str
-start
))
1761 *flags
|= LIBFLAG_FCONTROL
;
1762 else if (!wcsnicmp(start
, L
"HIDDEN", str
-start
))
1763 *flags
|= LIBFLAG_FHIDDEN
;
1764 else if (!wcsnicmp(start
, L
"HASDISKIMAGE", str
-start
))
1765 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1768 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1772 /* skip separator */
1780 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1782 unsigned int ver
[2];
1787 ver
[0] = ver
[1] = pos
= 0;
1788 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1790 if (*curr
>= '0' && *curr
<= '9')
1792 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1793 if (ver
[pos
] >= 0x10000) goto error
;
1795 else if (*curr
== '.')
1797 if (++pos
>= 2) goto error
;
1801 entity
->u
.typelib
.major
= ver
[0];
1802 entity
->u
.typelib
.minor
= ver
[1];
1806 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1810 static void parse_typelib_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1811 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1813 struct xml_attr attr
;
1815 struct entity
* entity
;
1817 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1819 set_error( xmlbuf
);
1823 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1825 if (xml_attr_cmp(&attr
, L
"tlbid"))
1827 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1829 else if (xml_attr_cmp(&attr
, L
"version"))
1831 if (!parse_typelib_version(&attr
.value
, entity
)) set_error( xmlbuf
);
1833 else if (xml_attr_cmp(&attr
, L
"helpdir"))
1835 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1837 else if (xml_attr_cmp(&attr
, L
"flags"))
1839 if (!parse_typelib_flags(&attr
.value
, entity
)) set_error( xmlbuf
);
1841 else if (!is_xmlns_attr( &attr
))
1843 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1847 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1848 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1851 static inline int aligned_string_len(int len
)
1853 return (len
+ 3) & ~3;
1856 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1858 struct assembly_version
*ver
= &assembly
->id
.version
;
1861 if (!ret
) ret
= buff
;
1862 return swprintf(ret
, ARRAY_SIZE(buff
), L
"%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1865 static void parse_window_class_elem( xmlbuf_t
*xmlbuf
, struct dll_redirect
*dll
,
1866 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
1868 struct xml_elem elem
;
1869 struct xml_attr attr
;
1872 struct entity
* entity
;
1874 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1876 set_error( xmlbuf
);
1879 entity
->u
.class.versioned
= TRUE
;
1880 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1882 if (xml_attr_cmp(&attr
, L
"versioned"))
1884 if (xmlstr_cmpi(&attr
.value
, L
"no"))
1885 entity
->u
.class.versioned
= FALSE
;
1886 else if (!xmlstr_cmpi(&attr
.value
, L
"yes"))
1887 set_error( xmlbuf
);
1889 else if (!is_xmlns_attr( &attr
))
1891 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1897 if (!parse_text_content(xmlbuf
, &content
)) return;
1898 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) set_error( xmlbuf
);
1900 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1902 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1904 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1905 parse_unknown_elem(xmlbuf
, &elem
);
1909 static void parse_binding_redirect_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1911 struct xml_attr attr
;
1914 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1916 if (xml_attr_cmp(&attr
, L
"oldVersion"))
1918 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1920 else if (xml_attr_cmp(&attr
, L
"newVersion"))
1922 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr
));
1924 else if (!is_xmlns_attr( &attr
))
1926 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1930 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
1933 static void parse_description_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
1935 struct xml_elem elem
;
1936 struct xml_attr attr
;
1940 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1942 if (!is_xmlns_attr( &attr
)) WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
1946 if (!parse_text_content(xmlbuf
, &content
)) return;
1948 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1950 while (next_xml_elem(xmlbuf
, &elem
, parent
))
1952 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
1953 parse_unknown_elem(xmlbuf
, &elem
);
1957 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t
*xmlbuf
,
1958 struct assembly
* assembly
,
1959 struct actctx_loader
* acl
,
1960 const struct xml_elem
*parent
)
1962 struct xml_attr attr
;
1964 struct entity
* entity
;
1966 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1968 set_error( xmlbuf
);
1972 while (next_xml_attr(xmlbuf
, &attr
, &end
))
1974 if (xml_attr_cmp(&attr
, L
"iid"))
1976 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1978 else if (xml_attr_cmp(&attr
, L
"name"))
1980 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1982 else if (xml_attr_cmp(&attr
, L
"baseInterface"))
1984 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1985 entity
->u
.ifaceps
.mask
|= BaseIface
;
1987 else if (xml_attr_cmp(&attr
, L
"numMethods"))
1989 if (!(parse_nummethods(&attr
.value
, entity
))) set_error( xmlbuf
);
1990 entity
->u
.ifaceps
.mask
|= NumMethods
;
1992 else if (xml_attr_cmp(&attr
, L
"proxyStubClsid32"))
1994 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
1996 else if (xml_attr_cmp(&attr
, L
"tlbid"))
1998 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2000 else if (!is_xmlns_attr( &attr
))
2002 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2006 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2007 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2010 static void parse_clr_class_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2011 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2014 struct xml_elem elem
;
2015 struct xml_attr attr
;
2017 struct entity
* entity
;
2019 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
2021 set_error( xmlbuf
);
2025 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2027 if (xml_attr_cmp(&attr
, L
"name"))
2029 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2031 else if (xml_attr_cmp(&attr
, L
"clsid"))
2033 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2035 else if (xml_attr_cmp(&attr
, L
"progid"))
2037 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2039 else if (xml_attr_cmp(&attr
, L
"tlbid"))
2041 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2043 else if (xml_attr_cmp(&attr
, L
"threadingModel"))
2045 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr
.value
);
2047 else if (xml_attr_cmp(&attr
, L
"runtimeVersion"))
2049 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2051 else if (!is_xmlns_attr( &attr
))
2053 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2057 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2058 if (entity
->u
.comclass
.progid
)
2059 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2062 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2064 if (xml_elem_cmp(&elem
, L
"progid", asmv1W
))
2066 parse_com_class_progid(xmlbuf
, entity
, &elem
);
2070 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2071 parse_unknown_elem(xmlbuf
, &elem
);
2075 if (entity
->u
.comclass
.progids
.num
)
2076 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2079 static void parse_clr_surrogate_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2080 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2082 struct xml_attr attr
;
2084 struct entity
* entity
;
2086 if (!(entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)))
2088 set_error( xmlbuf
);
2092 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2094 if (xml_attr_cmp(&attr
, L
"name"))
2096 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2098 else if (xml_attr_cmp(&attr
, L
"clsid"))
2100 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2102 else if (xml_attr_cmp(&attr
, L
"runtimeVersion"))
2104 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2106 else if (!is_xmlns_attr( &attr
))
2108 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2112 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2113 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2116 static void parse_dependent_assembly_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2117 const struct xml_elem
*parent
, BOOL optional
)
2119 struct xml_elem elem
;
2120 struct xml_attr attr
;
2121 struct assembly_identity ai
;
2124 memset(&ai
, 0, sizeof(ai
));
2125 ai
.optional
= optional
;
2127 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2129 if (xml_attr_cmp(&attr
, L
"allowDelayedBinding"))
2130 ai
.delayed
= xmlstr_cmp(&attr
.value
, L
"true");
2131 else if (!is_xmlns_attr( &attr
))
2132 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2137 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2139 if (xml_elem_cmp(&elem
, L
"assemblyIdentity", asmv1W
))
2141 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
, &elem
);
2142 /* store the newly found identity for later loading */
2143 if (ai
.arch
&& !wcscmp(ai
.arch
, L
"*"))
2145 RtlFreeHeap( GetProcessHeap(), 0, ai
.arch
);
2146 ai
.arch
= strdupW( current_archW
);
2148 TRACE( "adding name=%s version=%s arch=%s\n",
2149 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
2150 if (!add_dependent_assembly_id(acl
, &ai
)) set_error( xmlbuf
);
2152 else if (xml_elem_cmp(&elem
, L
"bindingRedirect", asmv1W
))
2154 parse_binding_redirect_elem(xmlbuf
, &elem
);
2158 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2159 parse_unknown_elem(xmlbuf
, &elem
);
2164 static void parse_dependency_elem( xmlbuf_t
*xmlbuf
, struct actctx_loader
*acl
,
2165 const struct xml_elem
*parent
)
2168 struct xml_elem elem
;
2169 struct xml_attr attr
;
2170 BOOL end
= FALSE
, optional
= FALSE
;
2172 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2174 if (xml_attr_cmp(&attr
, L
"optional"))
2176 optional
= xmlstr_cmpi( &attr
.value
, L
"yes" );
2177 TRACE("optional=%s\n", debugstr_xmlstr(&attr
.value
));
2179 else if (!is_xmlns_attr( &attr
))
2181 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2187 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2189 if (xml_elem_cmp(&elem
, L
"dependentAssembly", asmv1W
))
2191 parse_dependent_assembly_elem(xmlbuf
, acl
, &elem
, optional
);
2195 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2196 parse_unknown_elem(xmlbuf
, &elem
);
2201 static void parse_noinherit_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2205 parse_expect_no_attr(xmlbuf
, &end
);
2206 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2209 static void parse_noinheritable_elem( xmlbuf_t
*xmlbuf
, const struct xml_elem
*parent
)
2213 parse_expect_no_attr(xmlbuf
, &end
);
2214 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2217 static void parse_file_elem( xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2218 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2220 struct xml_elem elem
;
2221 struct xml_attr attr
;
2223 struct dll_redirect
* dll
;
2225 if (!(dll
= add_dll_redirect(assembly
)))
2227 set_error( xmlbuf
);
2231 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2233 if (xml_attr_cmp(&attr
, L
"name"))
2235 if (!(dll
->name
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2236 TRACE("name=%s\n", debugstr_xmlstr(&attr
.value
));
2238 else if (xml_attr_cmp(&attr
, L
"hash"))
2240 if (!(dll
->hash
= xmlstrdupW(&attr
.value
))) set_error( xmlbuf
);
2242 else if (xml_attr_cmp(&attr
, L
"hashalg"))
2244 if (!xmlstr_cmpi(&attr
.value
, L
"SHA1"))
2245 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr
.value
));
2247 else if (!is_xmlns_attr( &attr
))
2249 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2253 if (!dll
->name
) set_error( xmlbuf
);
2255 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2259 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2261 if (xml_elem_cmp(&elem
, L
"comClass", asmv1W
))
2263 parse_com_class_elem(xmlbuf
, dll
, acl
, &elem
);
2265 else if (xml_elem_cmp(&elem
, L
"comInterfaceProxyStub", asmv1W
))
2267 parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
, &elem
);
2269 else if (xml_elem_cmp(&elem
, L
"hash", asmv2W
))
2271 WARN("asmv2:hash (undocumented) not supported\n");
2272 parse_unknown_elem(xmlbuf
, &elem
);
2274 else if (xml_elem_cmp(&elem
, L
"typelib", asmv1W
))
2276 parse_typelib_elem(xmlbuf
, dll
, acl
, &elem
);
2278 else if (xml_elem_cmp(&elem
, L
"windowClass", asmv1W
))
2280 parse_window_class_elem(xmlbuf
, dll
, acl
, &elem
);
2284 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2285 parse_unknown_elem( xmlbuf
, &elem
);
2290 static void parse_supportedos_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2291 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2293 struct xml_attr attr
;
2296 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2298 if (xml_attr_cmp(&attr
, L
"Id"))
2300 COMPATIBILITY_CONTEXT_ELEMENT
*compat
;
2304 str
.Buffer
= (PWSTR
)attr
.value
.ptr
;
2305 str
.Length
= str
.MaximumLength
= (USHORT
)attr
.value
.len
* sizeof(WCHAR
);
2306 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2308 if (!(compat
= add_compat_context(assembly
)))
2310 set_error( xmlbuf
);
2313 compat
->Type
= ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2314 compat
->Id
= compat_id
;
2318 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr
.value
));
2321 else if (!is_xmlns_attr( &attr
))
2323 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2327 if (!end
) parse_expect_end_elem(xmlbuf
, parent
);
2330 static void parse_compatibility_application_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2331 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2333 struct xml_elem elem
;
2335 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2337 if (xml_elem_cmp(&elem
, L
"supportedOS", compatibilityNSW
))
2339 parse_supportedos_elem(xmlbuf
, assembly
, acl
, &elem
);
2343 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2344 parse_unknown_elem(xmlbuf
, &elem
);
2349 static void parse_compatibility_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2350 struct actctx_loader
* acl
, const struct xml_elem
*parent
)
2352 struct xml_elem elem
;
2354 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2356 if (xml_elem_cmp(&elem
, L
"application", compatibilityNSW
))
2358 parse_compatibility_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2362 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2363 parse_unknown_elem(xmlbuf
, &elem
);
2368 static void parse_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
,
2369 struct xml_elem
*parent
)
2371 struct xml_elem elem
;
2372 struct xml_attr attr
;
2375 struct entity
*entity
;
2377 while (next_xml_attr( xmlbuf
, &attr
, &end
))
2379 if (!is_xmlns_attr( &attr
)) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr
) );
2384 if (!parse_text_content( xmlbuf
, &content
)) return;
2385 TRACE( "got %s %s\n", debugstr_xmlstr(&parent
->name
), debugstr_xmlstr(&content
) );
2387 entity
= add_entity( &assembly
->entities
, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
);
2390 set_error( xmlbuf
);
2393 entity
->u
.settings
.name
= xmlstrdupW( &parent
->name
);
2394 entity
->u
.settings
.value
= xmlstrdupW( &content
);
2395 entity
->u
.settings
.ns
= xmlstrdupW( &parent
->ns
);
2397 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2399 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2400 parse_unknown_elem( xmlbuf
, &elem
);
2404 static void parse_windows_settings_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2405 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2407 struct xml_elem elem
;
2409 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2411 if (xml_elem_cmp( &elem
, L
"autoElevate", windowsSettings2005NSW
) ||
2412 xml_elem_cmp( &elem
, L
"disableTheming", windowsSettings2005NSW
) ||
2413 xml_elem_cmp( &elem
, L
"disableWindowFiltering", windowsSettings2011NSW
) ||
2414 xml_elem_cmp( &elem
, L
"dpiAware", windowsSettings2005NSW
) ||
2415 xml_elem_cmp( &elem
, L
"dpiAwareness", windowsSettings2016NSW
) ||
2416 xml_elem_cmp( &elem
, L
"gdiScaling", windowsSettings2017NSW
) ||
2417 xml_elem_cmp( &elem
, L
"highResolutionScrollingAware", windowsSettings2017NSW
) ||
2418 xml_elem_cmp( &elem
, L
"longPathAware", windowsSettings2016NSW
) ||
2419 xml_elem_cmp( &elem
, L
"magicFutureSetting", windowsSettings2017NSW
) ||
2420 xml_elem_cmp( &elem
, L
"printerDriverIsolation", windowsSettings2011NSW
) ||
2421 xml_elem_cmp( &elem
, L
"ultraHighResolutionScrollingAware", windowsSettings2017NSW
))
2423 parse_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2427 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2428 parse_unknown_elem( xmlbuf
, &elem
);
2433 static void parse_application_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2434 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2436 struct xml_elem elem
;
2438 while (next_xml_elem( xmlbuf
, &elem
, parent
))
2440 if (xml_elem_cmp( &elem
, L
"windowsSettings", asmv3W
))
2442 parse_windows_settings_elem( xmlbuf
, assembly
, acl
, &elem
);
2446 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem
) );
2447 parse_unknown_elem( xmlbuf
, &elem
);
2452 static void parse_requested_execution_level_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2453 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2455 struct xml_elem elem
;
2456 struct xml_attr attr
;
2459 /* Multiple requestedExecutionLevel elements are not supported. */
2460 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
) set_error( xmlbuf
);
2462 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2464 if (xml_attr_cmp(&attr
, L
"level"))
2466 if (xmlstr_cmpi(&attr
.value
, L
"asInvoker"))
2467 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2468 else if (xmlstr_cmpi(&attr
.value
, L
"highestAvailable"))
2469 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2470 else if (xmlstr_cmpi(&attr
.value
, L
"requireAdministrator"))
2471 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2473 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr
.value
));
2475 else if (xml_attr_cmp(&attr
, L
"uiAccess"))
2477 if (xmlstr_cmpi(&attr
.value
, L
"false"))
2478 assembly
->ui_access
= FALSE
;
2479 else if (xmlstr_cmpi(&attr
.value
, L
"true"))
2480 assembly
->ui_access
= TRUE
;
2482 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr
.value
));
2484 else if (!is_xmlns_attr( &attr
))
2485 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2490 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2492 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2493 parse_unknown_elem(xmlbuf
, &elem
);
2497 static void parse_requested_privileges_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2498 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2500 struct xml_elem elem
;
2502 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2504 if (xml_elem_cmp(&elem
, L
"requestedExecutionLevel", asmv1W
))
2506 parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
, &elem
);
2510 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2511 parse_unknown_elem(xmlbuf
, &elem
);
2516 static void parse_security_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2517 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2519 struct xml_elem elem
;
2521 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2523 if (xml_elem_cmp(&elem
, L
"requestedPrivileges", asmv1W
))
2525 parse_requested_privileges_elem(xmlbuf
, assembly
, acl
, &elem
);
2529 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2530 parse_unknown_elem(xmlbuf
, &elem
);
2535 static void parse_trust_info_elem( xmlbuf_t
*xmlbuf
, struct assembly
*assembly
,
2536 struct actctx_loader
*acl
, const struct xml_elem
*parent
)
2538 struct xml_elem elem
;
2540 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2542 if (xml_elem_cmp(&elem
, L
"security", asmv1W
))
2544 parse_security_elem(xmlbuf
, assembly
, acl
, &elem
);
2548 WARN("unknown elem %s\n", debugstr_xml_elem(&elem
));
2549 parse_unknown_elem(xmlbuf
, &elem
);
2554 static void parse_assembly_elem( xmlbuf_t
*xmlbuf
, struct assembly
* assembly
,
2555 struct actctx_loader
* acl
, const struct xml_elem
*parent
,
2556 struct assembly_identity
* expected_ai
)
2558 struct xml_elem elem
;
2559 struct xml_attr attr
;
2560 BOOL end
= FALSE
, version
= FALSE
;
2562 TRACE("(%p)\n", xmlbuf
);
2564 while (next_xml_attr(xmlbuf
, &attr
, &end
))
2566 if (xml_attr_cmp(&attr
, L
"manifestVersion"))
2568 if (!xmlstr_cmp(&attr
.value
, L
"1.0"))
2570 FIXME("wrong version %s\n", debugstr_xmlstr(&attr
.value
));
2575 else if (!is_xmlns_attr( &attr
))
2577 WARN("unknown attr %s\n", debugstr_xml_attr(&attr
));
2581 if (end
|| !version
)
2583 set_error( xmlbuf
);
2587 while (next_xml_elem(xmlbuf
, &elem
, parent
))
2589 if (assembly
->type
== APPLICATION_MANIFEST
&& xml_elem_cmp(&elem
, L
"noInherit", asmv1W
))
2591 parse_noinherit_elem(xmlbuf
, &elem
);
2592 assembly
->no_inherit
= TRUE
;
2594 else if (xml_elem_cmp(&elem
, L
"noInheritable", asmv1W
))
2596 parse_noinheritable_elem(xmlbuf
, &elem
);
2598 else if (xml_elem_cmp(&elem
, L
"description", asmv1W
))
2600 parse_description_elem(xmlbuf
, &elem
);
2602 else if (xml_elem_cmp(&elem
, L
"comInterfaceExternalProxyStub", asmv1W
))
2604 parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
, &elem
);
2606 else if (xml_elem_cmp(&elem
, L
"dependency", asmv1W
))
2608 parse_dependency_elem(xmlbuf
, acl
, &elem
);
2610 else if (xml_elem_cmp(&elem
, L
"file", asmv1W
))
2612 parse_file_elem(xmlbuf
, assembly
, acl
, &elem
);
2614 else if (xml_elem_cmp(&elem
, L
"clrClass", asmv1W
))
2616 parse_clr_class_elem(xmlbuf
, assembly
, acl
, &elem
);
2618 else if (xml_elem_cmp(&elem
, L
"clrSurrogate", asmv1W
))
2620 parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
, &elem
);
2622 else if (xml_elem_cmp(&elem
, L
"trustInfo", asmv1W
))
2624 parse_trust_info_elem(xmlbuf
, assembly
, acl
, &elem
);
2626 else if (xml_elem_cmp(&elem
, L
"assemblyIdentity", asmv1W
))
2628 parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
, &elem
);
2630 if (!xmlbuf
->error
&& expected_ai
)
2632 /* FIXME: more tests */
2633 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2634 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2636 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2637 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2638 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2639 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2640 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2641 set_error( xmlbuf
);
2643 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2644 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2645 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2646 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2647 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2648 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2650 FIXME("wrong version for shared assembly manifest\n");
2651 set_error( xmlbuf
);
2655 else if (xml_elem_cmp(&elem
, L
"compatibility", compatibilityNSW
))
2657 parse_compatibility_elem(xmlbuf
, assembly
, acl
, &elem
);
2659 else if (xml_elem_cmp(&elem
, L
"application", asmv3W
))
2661 parse_application_elem(xmlbuf
, assembly
, acl
, &elem
);
2665 WARN("unknown element %s\n", debugstr_xml_elem(&elem
));
2666 parse_unknown_elem(xmlbuf
, &elem
);
2670 if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2671 assembly
->no_inherit
)
2673 set_error( xmlbuf
);
2677 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2678 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2680 struct xml_elem elem
;
2681 struct xml_elem parent
= {};
2683 xmlbuf
->error
= FALSE
;
2686 if (!next_xml_elem(xmlbuf
, &elem
, &parent
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2688 if (xmlstr_cmp(&elem
.name
, L
"?xml") &&
2689 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
, &parent
)))
2690 return STATUS_SXS_CANT_GEN_ACTCTX
;
2692 if (!xml_elem_cmp(&elem
, L
"assembly", asmv1W
))
2694 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem
));
2695 return STATUS_SXS_CANT_GEN_ACTCTX
;
2698 parse_assembly_elem(xmlbuf
, assembly
, acl
, &elem
, ai
);
2701 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
2702 return STATUS_SXS_CANT_GEN_ACTCTX
;
2705 if (next_xml_elem(xmlbuf
, &elem
, &parent
))
2707 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem
));
2708 return STATUS_SXS_CANT_GEN_ACTCTX
;
2711 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2713 FIXME("parse error\n");
2714 return STATUS_SXS_CANT_GEN_ACTCTX
;
2716 return STATUS_SUCCESS
;
2719 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2720 LPCWSTR filename
, HANDLE module
, LPCWSTR directory
, BOOL shared
,
2721 const void *buffer
, SIZE_T size
)
2725 struct assembly
*assembly
;
2728 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2730 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2731 return STATUS_SXS_CANT_GEN_ACTCTX
;
2733 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2734 return STATUS_NO_MEMORY
;
2738 UNICODE_STRING module_path
;
2739 if ((status
= get_module_filename( module
, &module_path
, 0 ))) return status
;
2740 assembly
->manifest
.info
= module_path
.Buffer
;
2742 else if(!(assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY
;
2744 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2745 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2747 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2748 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2750 xmlbuf
.ptr
= buffer
;
2751 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2752 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2754 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2756 const WCHAR
*buf
= buffer
;
2760 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2761 return STATUS_NO_MEMORY
;
2762 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2763 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2764 xmlbuf
.ptr
= new_buff
;
2765 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2766 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2767 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2774 /* let's assume utf-8 for now */
2775 RtlUTF8ToUnicodeN( NULL
, 0, &len
, buffer
, size
);
2776 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
))) return STATUS_NO_MEMORY
;
2777 RtlUTF8ToUnicodeN( new_buff
, len
, &len
, buffer
, size
);
2778 xmlbuf
.ptr
= new_buff
;
2779 xmlbuf
.end
= xmlbuf
.ptr
+ len
/ sizeof(WCHAR
);
2780 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2781 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2786 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2788 OBJECT_ATTRIBUTES attr
;
2791 attr
.Length
= sizeof(attr
);
2792 attr
.RootDirectory
= 0;
2793 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2794 attr
.ObjectName
= name
;
2795 attr
.SecurityDescriptor
= NULL
;
2796 attr
.SecurityQualityOfService
= NULL
;
2797 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2800 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2801 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2802 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2805 UNICODE_STRING nameW
;
2806 LDR_RESOURCE_INFO info
;
2807 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2810 if (TRACE_ON(actctx
))
2812 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2814 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2815 hModule
, debugstr_w(nameW
.Buffer
) );
2816 RtlFreeUnicodeString( &nameW
);
2818 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2819 hModule
, debugstr_w(filename
) );
2822 if (!resname
) return STATUS_INVALID_PARAMETER
;
2824 info
.Type
= RT_MANIFEST
;
2825 info
.Language
= lang
;
2826 if (!((ULONG_PTR
)resname
>> 16))
2828 info
.Name
= (ULONG_PTR
)resname
;
2829 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2831 else if (resname
[0] == '#')
2834 RtlInitUnicodeString(&nameW
, resname
+ 1);
2835 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2836 return STATUS_INVALID_PARAMETER
;
2838 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2842 RtlCreateUnicodeString(&nameW
, resname
);
2843 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2844 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2845 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2846 RtlFreeUnicodeString(&nameW
);
2848 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2850 if (status
== STATUS_SUCCESS
)
2851 status
= parse_manifest(acl
, ai
, filename
, hModule
, directory
, shared
, ptr
, entry
->Size
);
2856 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2857 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2858 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2861 OBJECT_ATTRIBUTES attr
;
2863 LARGE_INTEGER offset
;
2868 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2870 attr
.Length
= sizeof(attr
);
2871 attr
.RootDirectory
= 0;
2872 attr
.ObjectName
= NULL
;
2873 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2874 attr
.SecurityDescriptor
= NULL
;
2875 attr
.SecurityQualityOfService
= NULL
;
2878 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2879 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2880 if (status
!= STATUS_SUCCESS
) return status
;
2882 offset
.QuadPart
= 0;
2885 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2886 &count
, ViewShare
, 0, PAGE_READONLY
);
2888 if (status
!= STATUS_SUCCESS
) return status
;
2890 if (RtlImageNtHeader(base
)) /* we got a PE file */
2892 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2893 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2895 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2897 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2901 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2902 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2904 FILE_END_OF_FILE_INFORMATION info
;
2907 OBJECT_ATTRIBUTES attr
;
2909 LARGE_INTEGER offset
;
2914 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2916 attr
.Length
= sizeof(attr
);
2917 attr
.RootDirectory
= 0;
2918 attr
.ObjectName
= NULL
;
2919 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2920 attr
.SecurityDescriptor
= NULL
;
2921 attr
.SecurityQualityOfService
= NULL
;
2924 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2925 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2926 if (status
!= STATUS_SUCCESS
) return status
;
2928 offset
.QuadPart
= 0;
2931 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2932 &count
, ViewShare
, 0, PAGE_READONLY
);
2934 if (status
!= STATUS_SUCCESS
) return status
;
2936 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2937 if (status
== STATUS_SUCCESS
)
2938 status
= parse_manifest(acl
, ai
, filename
, NULL
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2940 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2944 /* try to load the .manifest file associated to the file */
2945 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2946 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2950 UNICODE_STRING nameW
;
2952 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2954 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2956 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2958 if (module
) /* use the module filename */
2960 UNICODE_STRING name
;
2962 if (!(status
= get_module_filename( module
, &name
, sizeof(L
".manifest") + 10*sizeof(WCHAR
) )))
2964 if (resid
!= 1) swprintf( name
.Buffer
+ wcslen(name
.Buffer
), 10, L
".%lu", resid
);
2965 wcscat( name
.Buffer
, L
".manifest" );
2966 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2967 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2968 RtlFreeUnicodeString( &name
);
2970 if (status
) return status
;
2974 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2975 (wcslen(filename
) + 10) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
2976 return STATUS_NO_MEMORY
;
2977 wcscpy( buffer
, filename
);
2978 if (resid
!= 1) swprintf( buffer
+ wcslen(buffer
), 10, L
".%lu", resid
);
2979 wcscat( buffer
, L
".manifest" );
2980 RtlInitUnicodeString( &nameW
, buffer
);
2983 if (!open_nt_file( &file
, &nameW
))
2985 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2988 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2989 RtlFreeUnicodeString( &nameW
);
2993 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2995 static const WCHAR lookup_fmtW
[] = L
"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
2996 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2998 WCHAR
*lookup
, *ret
= NULL
;
2999 UNICODE_STRING lookup_us
;
3001 const WCHAR
*lang
= ai
->language
;
3002 unsigned int data_pos
= 0, data_len
, len
;
3005 if (!lang
|| !wcsicmp( lang
, L
"neutral" )) lang
= L
"*";
3007 len
= wcslen(ai
->arch
) + wcslen(ai
->name
) + wcslen(ai
->public_key
) + wcslen(lang
) + 20 + ARRAY_SIZE(lookup_fmtW
);
3008 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) return NULL
;
3009 swprintf( lookup
, len
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3010 ai
->version
.major
, ai
->version
.minor
, lang
);
3011 RtlInitUnicodeString( &lookup_us
, lookup
);
3013 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3014 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3016 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3017 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3019 ULONG build
, revision
;
3021 data_len
= io
.Information
;
3025 if (data_pos
>= data_len
)
3027 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3028 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3030 data_len
= io
.Information
;
3033 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3035 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3036 else data_pos
= data_len
;
3038 tmp
= dir_info
->FileName
+ (wcschr(lookup
, '*') - lookup
);
3039 build
= wcstoul( tmp
, NULL
, 10 );
3040 if (build
< min_build
) continue;
3041 tmp
= wcschr(tmp
, '.') + 1;
3042 revision
= wcstoul( tmp
, NULL
, 10 );
3043 if (build
== min_build
&& revision
< min_revision
) continue;
3044 tmp
= wcschr(tmp
, '_') + 1;
3045 tmp
= wcschr(tmp
, '_') + 1;
3046 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3047 !wcsnicmp( tmp
, wine_trailerW
, ARRAY_SIZE( wine_trailerW
)))
3049 /* prefer a non-Wine manifest if we already have one */
3050 /* we'll still load the builtin dll if specified through DllOverrides */
3056 min_revision
= revision
;
3058 ai
->version
.build
= build
;
3059 ai
->version
.revision
= revision
;
3060 RtlFreeHeap( GetProcessHeap(), 0, ret
);
3061 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3063 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3064 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3068 else WARN("no matching file for %s\n", debugstr_w(lookup
));
3069 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
3073 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3075 struct assembly_identity sxs_ai
;
3076 UNICODE_STRING path_us
;
3077 OBJECT_ATTRIBUTES attr
;
3079 WCHAR
*path
, *file
= NULL
;
3082 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3084 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L
"\\winsxs\\manifests") +
3085 wcslen(windows_dir
) * sizeof(WCHAR
) )))
3086 return STATUS_NO_MEMORY
;
3088 wcscpy( path
, windows_dir
);
3089 wcscat( path
, L
"\\winsxs\\manifests" );
3091 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3093 RtlFreeHeap( GetProcessHeap(), 0, path
);
3094 return STATUS_NO_SUCH_FILE
;
3096 RtlFreeHeap( GetProcessHeap(), 0, path
);
3098 attr
.Length
= sizeof(attr
);
3099 attr
.RootDirectory
= 0;
3100 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3101 attr
.ObjectName
= &path_us
;
3102 attr
.SecurityDescriptor
= NULL
;
3103 attr
.SecurityQualityOfService
= NULL
;
3105 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3106 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3109 file
= lookup_manifest_file( handle
, &sxs_ai
);
3114 RtlFreeUnicodeString( &path_us
);
3115 return STATUS_NO_SUCH_FILE
;
3118 /* append file name to directory path */
3119 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
3120 path_us
.Length
+ (wcslen(file
) + 2) * sizeof(WCHAR
) )))
3122 RtlFreeHeap( GetProcessHeap(), 0, file
);
3123 RtlFreeUnicodeString( &path_us
);
3124 return STATUS_NO_MEMORY
;
3127 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3128 wcscpy( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3129 RtlInitUnicodeString( &path_us
, path
);
3130 *wcsrchr(file
, '.') = 0; /* remove .manifest extension */
3132 if (!open_nt_file( &handle
, &path_us
))
3134 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3137 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
3139 RtlFreeHeap( GetProcessHeap(), 0, file
);
3140 RtlFreeUnicodeString( &path_us
);
3144 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3145 struct assembly_identity
* ai
)
3148 WCHAR
*buffer
, *p
, *directory
;
3150 UNICODE_STRING nameW
;
3154 TRACE( "looking for name=%s version=%s arch=%s\n",
3155 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
3157 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3159 /* FIXME: add support for language specific lookup */
3161 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3162 wcslen(acl
->actctx
->appdir
.info
));
3164 nameW
.Buffer
= NULL
;
3165 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
3166 (len
+ 2 * wcslen(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(L
".manifest") )))
3167 return STATUS_NO_MEMORY
;
3169 if (!(directory
= build_assembly_dir( ai
)))
3171 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3172 return STATUS_NO_MEMORY
;
3175 /* Lookup in <dir>\name.dll
3176 * <dir>\name.manifest
3177 * <dir>\name\name.dll
3178 * <dir>\name\name.manifest
3180 * First 'appdir' is used as <dir>, if that failed
3181 * it tries application manifest file path.
3183 wcscpy( buffer
, acl
->actctx
->appdir
.info
);
3184 p
= buffer
+ wcslen(buffer
);
3185 for (i
= 0; i
< 4; i
++)
3189 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3190 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3194 wcscpy( p
, ai
->name
);
3197 wcscpy( p
, L
".dll" );
3198 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3200 status
= open_nt_file( &file
, &nameW
);
3203 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3204 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3206 if (status
== STATUS_SUCCESS
)
3209 RtlFreeUnicodeString( &nameW
);
3212 wcscpy( p
, L
".manifest" );
3213 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3215 status
= open_nt_file( &file
, &nameW
);
3218 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3222 RtlFreeUnicodeString( &nameW
);
3224 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3226 RtlFreeUnicodeString( &nameW
);
3227 RtlFreeHeap( GetProcessHeap(), 0, directory
);
3228 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
3232 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3234 NTSTATUS status
= STATUS_SUCCESS
;
3237 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3239 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3241 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3243 FIXME( "Could not find dependent assembly %s (%s)\n",
3244 debugstr_w(acl
->dependencies
[i
].name
),
3245 debugstr_version(&acl
->dependencies
[i
].version
) );
3246 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3251 /* FIXME should now iterate through all refs */
3255 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3256 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3258 NTSTATUS status
= STATUS_SUCCESS
;
3260 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
3262 if (*handle
) return STATUS_INVALID_PARAMETER
;
3264 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3265 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3267 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
3270 LDR_DATA_TABLE_ENTRY
*pldr
;
3272 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3274 LdrLockLoaderLock( 0, NULL
, &magic
);
3275 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3277 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3278 status
= STATUS_DLL_NOT_FOUND
;
3280 *handle
= pldr
->ActivationContext
;
3282 else status
= STATUS_DLL_NOT_FOUND
;
3283 LdrUnlockLoaderLock( 0, magic
);
3285 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3286 *handle
= process_actctx
;
3291 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3293 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3294 struct strsection_header
*header
;
3295 struct dllredirect_data
*data
;
3296 struct string_index
*index
;
3299 /* compute section length */
3300 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3302 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3303 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3305 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3307 /* each entry needs index, data and string data */
3308 total_len
+= sizeof(*index
);
3309 total_len
+= sizeof(*data
);
3310 total_len
+= aligned_string_len((wcslen(dll
->name
)+1)*sizeof(WCHAR
));
3313 dll_count
+= assembly
->num_dlls
;
3316 total_len
+= sizeof(*header
);
3318 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3319 if (!header
) return STATUS_NO_MEMORY
;
3321 memset(header
, 0, sizeof(*header
));
3322 header
->magic
= STRSECTION_MAGIC
;
3323 header
->size
= sizeof(*header
);
3324 header
->count
= dll_count
;
3325 header
->index_offset
= sizeof(*header
);
3326 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3327 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3329 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3331 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3332 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3334 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3338 /* setup new index entry */
3339 str
.Buffer
= dll
->name
;
3340 str
.Length
= wcslen(dll
->name
)*sizeof(WCHAR
);
3341 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3342 /* hash original class name */
3343 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3345 index
->name_offset
= name_offset
;
3346 index
->name_len
= str
.Length
;
3347 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3348 index
->data_len
= sizeof(*data
);
3349 index
->rosterindex
= i
+ 1;
3352 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3353 data
->size
= sizeof(*data
);
3354 data
->unk
= 2; /* FIXME: seems to be constant */
3355 memset(data
->res
, 0, sizeof(data
->res
));
3358 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3359 memcpy(ptrW
, dll
->name
, index
->name_len
);
3360 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3362 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3370 return STATUS_SUCCESS
;
3373 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3375 struct string_index
*iter
, *index
= NULL
;
3379 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3380 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3382 for (i
= 0; i
< section
->count
; i
++)
3384 if (iter
->hash
== hash
)
3386 str
.Buffer
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3387 str
.Length
= iter
->name_len
;
3388 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3394 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3402 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3404 struct guid_index
*iter
, *index
= NULL
;
3407 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3409 for (i
= 0; i
< section
->count
; i
++)
3411 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3422 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3424 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3427 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3428 PACTCTX_SECTION_KEYED_DATA data
)
3430 struct dllredirect_data
*dll
;
3431 struct string_index
*index
;
3433 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3435 if (!actctx
->dllredirect_section
)
3437 struct strsection_header
*section
;
3439 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3440 if (status
) return status
;
3442 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3443 RtlFreeHeap(GetProcessHeap(), 0, section
);
3446 index
= find_string_index(actctx
->dllredirect_section
, name
);
3447 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3451 dll
= get_dllredirect_data(actctx
, index
);
3453 data
->ulDataFormatVersion
= 1;
3455 data
->ulLength
= dll
->size
;
3456 data
->lpSectionGlobalData
= NULL
;
3457 data
->ulSectionGlobalDataLength
= 0;
3458 data
->lpSectionBase
= actctx
->dllredirect_section
;
3459 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
3460 data
->hActCtx
= NULL
;
3462 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3463 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3466 return STATUS_SUCCESS
;
3469 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3471 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3474 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3476 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3479 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3481 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3482 struct wndclass_redirect_data
*data
;
3483 struct strsection_header
*header
;
3484 struct string_index
*index
;
3487 /* compute section length */
3488 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3490 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3491 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3493 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3494 for (k
= 0; k
< dll
->entities
.num
; k
++)
3496 struct entity
*entity
= &dll
->entities
.base
[k
];
3497 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3499 int class_len
= wcslen(entity
->u
.class.name
) + 1;
3502 /* each class entry needs index, data and string data */
3503 total_len
+= sizeof(*index
);
3504 total_len
+= sizeof(*data
);
3505 /* original name is stored separately */
3506 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3507 /* versioned name and module name are stored one after another */
3508 if (entity
->u
.class.versioned
)
3509 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3512 len
+= wcslen(dll
->name
) + 1;
3513 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3521 total_len
+= sizeof(*header
);
3523 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3524 if (!header
) return STATUS_NO_MEMORY
;
3526 memset(header
, 0, sizeof(*header
));
3527 header
->magic
= STRSECTION_MAGIC
;
3528 header
->size
= sizeof(*header
);
3529 header
->count
= class_count
;
3530 header
->index_offset
= sizeof(*header
);
3531 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3532 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3534 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3536 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3537 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3539 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3540 for (k
= 0; k
< dll
->entities
.num
; k
++)
3542 struct entity
*entity
= &dll
->entities
.base
[k
];
3543 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3545 ULONG versioned_len
, module_len
;
3549 /* setup new index entry */
3550 str
.Buffer
= entity
->u
.class.name
;
3551 str
.Length
= wcslen(entity
->u
.class.name
)*sizeof(WCHAR
);
3552 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3553 /* hash original class name */
3554 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3556 /* include '!' separator too */
3557 if (entity
->u
.class.versioned
)
3558 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3560 versioned_len
= str
.Length
;
3561 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3563 index
->name_offset
= name_offset
;
3564 index
->name_len
= str
.Length
;
3565 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3566 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3567 index
->rosterindex
= i
+ 1;
3570 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3571 data
->size
= sizeof(*data
);
3573 data
->name_len
= versioned_len
;
3574 data
->name_offset
= sizeof(*data
);
3575 data
->module_len
= module_len
;
3576 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3578 /* original class name */
3579 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3580 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3581 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3584 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3585 memcpy(ptrW
, dll
->name
, data
->module_len
);
3586 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3588 /* versioned name */
3589 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3590 if (entity
->u
.class.versioned
)
3592 get_assembly_version(assembly
, ptrW
);
3594 wcscat(ptrW
, entity
->u
.class.name
);
3598 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3599 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3602 name_offset
+= sizeof(*data
);
3603 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3613 return STATUS_SUCCESS
;
3616 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3617 PACTCTX_SECTION_KEYED_DATA data
)
3619 struct string_index
*iter
, *index
= NULL
;
3620 struct wndclass_redirect_data
*class;
3625 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3627 if (!actctx
->wndclass_section
)
3629 struct strsection_header
*section
;
3631 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3632 if (status
) return status
;
3634 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3635 RtlFreeHeap(GetProcessHeap(), 0, section
);
3639 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3640 iter
= get_wndclass_first_index(actctx
);
3642 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3644 if (iter
->hash
== hash
)
3646 str
.Buffer
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3647 str
.Length
= iter
->name_len
;
3648 if (RtlEqualUnicodeString( &str
, name
, TRUE
))
3654 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_us(&str
));
3659 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3663 class = get_wndclass_data(actctx
, index
);
3665 data
->ulDataFormatVersion
= 1;
3666 data
->lpData
= class;
3667 /* full length includes string length with nulls */
3668 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3669 data
->lpSectionGlobalData
= NULL
;
3670 data
->ulSectionGlobalDataLength
= 0;
3671 data
->lpSectionBase
= actctx
->wndclass_section
;
3672 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
3673 data
->hActCtx
= NULL
;
3675 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3676 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3679 return STATUS_SUCCESS
;
3682 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3684 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3685 struct guidsection_header
*header
;
3686 ULONG module_offset
, data_offset
;
3687 struct tlibredirect_data
*data
;
3688 struct guid_index
*index
;
3690 /* compute section length */
3691 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3693 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3694 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3696 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3697 for (k
= 0; k
< dll
->entities
.num
; k
++)
3699 struct entity
*entity
= &dll
->entities
.base
[k
];
3700 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3702 /* each entry needs index, data and string data for module name and help string */
3703 total_len
+= sizeof(*index
);
3704 total_len
+= sizeof(*data
);
3705 /* help string is stored separately */
3706 if (*entity
->u
.typelib
.helpdir
)
3707 total_len
+= aligned_string_len((wcslen(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3709 /* module names are packed one after another */
3710 names_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
3718 total_len
+= aligned_string_len(names_len
);
3719 total_len
+= sizeof(*header
);
3721 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3722 if (!header
) return STATUS_NO_MEMORY
;
3724 memset(header
, 0, sizeof(*header
));
3725 header
->magic
= GUIDSECTION_MAGIC
;
3726 header
->size
= sizeof(*header
);
3727 header
->count
= tlib_count
;
3728 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3729 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3730 module_offset
= sizeof(*header
);
3731 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3733 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3735 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3736 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3738 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3739 for (k
= 0; k
< dll
->entities
.num
; k
++)
3741 struct entity
*entity
= &dll
->entities
.base
[k
];
3742 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3744 ULONG module_len
, help_len
;
3748 if (*entity
->u
.typelib
.helpdir
)
3749 help_len
= wcslen(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3753 module_len
= wcslen(dll
->name
)*sizeof(WCHAR
);
3755 /* setup new index entry */
3756 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3757 RtlGUIDFromString(&str
, &index
->guid
);
3758 index
->data_offset
= data_offset
;
3759 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3760 index
->rosterindex
= i
+ 1;
3763 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3764 data
->size
= sizeof(*data
);
3766 data
->name_len
= module_len
;
3767 data
->name_offset
= module_offset
;
3768 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3770 data
->flags
= entity
->u
.typelib
.flags
;
3771 data
->help_len
= help_len
;
3772 data
->help_offset
= sizeof(*data
);
3773 data
->major_version
= entity
->u
.typelib
.major
;
3774 data
->minor_version
= entity
->u
.typelib
.minor
;
3777 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3778 memcpy(ptrW
, dll
->name
, data
->name_len
);
3779 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3784 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3785 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3786 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3789 data_offset
+= sizeof(*data
);
3791 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3793 module_offset
+= module_len
+ sizeof(WCHAR
);
3803 return STATUS_SUCCESS
;
3806 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3808 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3811 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3813 struct guid_index
*index
= NULL
;
3814 struct tlibredirect_data
*tlib
;
3816 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3818 if (!actctx
->tlib_section
)
3820 struct guidsection_header
*section
;
3822 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3823 if (status
) return status
;
3825 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3826 RtlFreeHeap(GetProcessHeap(), 0, section
);
3829 index
= find_guid_index(actctx
->tlib_section
, guid
);
3830 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3832 tlib
= get_tlib_data(actctx
, index
);
3834 data
->ulDataFormatVersion
= 1;
3835 data
->lpData
= tlib
;
3836 /* full length includes string length with nulls */
3837 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3838 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3839 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3840 data
->lpSectionBase
= actctx
->tlib_section
;
3841 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3842 data
->hActCtx
= NULL
;
3844 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3845 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3847 return STATUS_SUCCESS
;
3850 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3852 ULONG
*ptr
= (ULONG
*)guid
;
3855 /* GUID is 16 bytes long */
3856 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3857 *ptr
= RtlUniform(seed
);
3859 guid
->Data3
&= 0x0fff;
3860 guid
->Data3
|= (4 << 12);
3861 guid
->Data4
[0] &= 0x3f;
3862 guid
->Data4
[0] |= 0x80;
3865 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3866 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3870 for (i
= 0; i
< entities
->num
; i
++)
3872 struct entity
*entity
= &entities
->base
[i
];
3873 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3875 /* each entry needs two index entries, extra one goes for alias GUID */
3876 *len
+= 2*sizeof(struct guid_index
);
3877 /* To save some memory we don't allocated two data structures,
3878 instead alias index and normal index point to the same data structure. */
3879 *len
+= sizeof(struct comclassredirect_data
);
3881 /* for clrClass store some more */
3882 if (entity
->u
.comclass
.name
)
3884 unsigned int str_len
;
3886 /* all string data is stored together in aligned block */
3887 str_len
= wcslen(entity
->u
.comclass
.name
)+1;
3888 if (entity
->u
.comclass
.progid
)
3889 str_len
+= wcslen(entity
->u
.comclass
.progid
)+1;
3890 if (entity
->u
.comclass
.version
)
3891 str_len
+= wcslen(entity
->u
.comclass
.version
)+1;
3893 *len
+= sizeof(struct clrclass_data
);
3894 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3896 /* module name is forced to mscoree.dll, and stored two times with different case */
3897 *module_len
+= sizeof(L
"MSCOREE.DLL") + sizeof(L
"mscoree.dll");
3901 /* progid string is stored separately */
3902 if (entity
->u
.comclass
.progid
)
3903 *len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3905 *module_len
+= (wcslen(dll
->name
)+1)*sizeof(WCHAR
);
3913 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3914 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3915 ULONG
*seed
, ULONG rosterindex
)
3919 for (i
= 0; i
< entities
->num
; i
++)
3921 struct entity
*entity
= &entities
->base
[i
];
3922 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3924 ULONG module_len
, progid_len
, str_len
= 0, miscmask
;
3925 struct comclassredirect_data
*data
;
3926 struct guid_index
*alias_index
;
3927 struct clrclass_data
*clrdata
;
3931 if (entity
->u
.comclass
.progid
)
3932 progid_len
= wcslen(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3936 module_len
= dll
? wcslen(dll
->name
)*sizeof(WCHAR
) : wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
3938 /* setup new index entry */
3939 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3940 RtlGUIDFromString(&str
, &(*index
)->guid
);
3942 (*index
)->data_offset
= *data_offset
;
3943 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3944 (*index
)->rosterindex
= rosterindex
;
3946 /* Setup new index entry for alias guid. Alias index records are placed after
3947 normal records, so normal guids are hit first on search. Note that class count
3949 alias_index
= (*index
) + section
->count
/2;
3950 generate_uuid(seed
, &alias_index
->guid
);
3951 alias_index
->data_offset
= (*index
)->data_offset
;
3952 alias_index
->data_len
= 0;
3953 alias_index
->rosterindex
= (*index
)->rosterindex
;
3956 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3957 data
->size
= sizeof(*data
);
3958 data
->model
= entity
->u
.comclass
.model
;
3959 data
->clsid
= (*index
)->guid
;
3960 data
->alias
= alias_index
->guid
;
3961 data
->clsid2
= data
->clsid
;
3962 if (entity
->u
.comclass
.tlbid
)
3964 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3965 RtlGUIDFromString(&str
, &data
->tlbid
);
3968 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3969 data
->name_len
= module_len
;
3970 data
->name_offset
= *module_offset
;
3971 data
->progid_len
= progid_len
;
3972 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3973 data
->clrdata_len
= 0; /* will be set later */
3974 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3975 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3976 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3977 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3978 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3979 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3981 /* mask describes which misc* data is available */
3983 if (data
->miscstatus
)
3984 miscmask
|= MiscStatus
;
3985 if (data
->miscstatuscontent
)
3986 miscmask
|= MiscStatusContent
;
3987 if (data
->miscstatusthumbnail
)
3988 miscmask
|= MiscStatusThumbnail
;
3989 if (data
->miscstatusicon
)
3990 miscmask
|= MiscStatusIcon
;
3991 if (data
->miscstatusdocprint
)
3992 miscmask
|= MiscStatusDocPrint
;
3993 data
->flags
= miscmask
<< 8;
3995 if (data
->clrdata_offset
)
3997 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3999 clrdata
->size
= sizeof(*clrdata
);
4000 clrdata
->res
[0] = 0;
4001 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4002 clrdata
->module_len
= wcslen(L
"MSCOREE.DLL")*sizeof(WCHAR
);
4003 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4004 clrdata
->name_len
= wcslen(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4005 clrdata
->name_offset
= clrdata
->size
;
4006 clrdata
->version_len
= entity
->u
.comclass
.version
? wcslen(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4007 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4008 clrdata
->res2
[0] = 0;
4009 clrdata
->res2
[1] = 0;
4011 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4014 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4015 memcpy(ptrW
, L
"mscoree.dll", clrdata
->module_len
);
4016 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4018 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4019 memcpy(ptrW
, L
"MSCOREE.DLL", data
->name_len
);
4020 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4023 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4024 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4025 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4027 /* runtime version, optional */
4028 if (clrdata
->version_len
)
4030 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4032 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4033 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4034 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4037 if (data
->progid_len
)
4038 data
->progid_offset
+= data
->clrdata_len
;
4039 (*index
)->data_len
+= sizeof(*clrdata
);
4046 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4047 memcpy(ptrW
, dll
->name
, data
->name_len
);
4048 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4052 if (data
->progid_len
)
4054 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4055 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4056 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4059 /* string block length */
4063 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4064 if (clrdata
->version_len
)
4065 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4068 str_len
+= progid_len
+ sizeof(WCHAR
);
4070 (*index
)->data_len
+= aligned_string_len(str_len
);
4071 alias_index
->data_len
= (*index
)->data_len
;
4073 /* move to next data record */
4074 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4075 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4079 (*data_offset
) += sizeof(*clrdata
);
4080 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4087 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4089 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4090 struct guidsection_header
*header
;
4091 ULONG module_offset
, data_offset
;
4092 struct guid_index
*index
;
4095 /* compute section length */
4096 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4098 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4099 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4100 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4102 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4103 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4107 total_len
+= aligned_string_len(names_len
);
4108 total_len
+= sizeof(*header
);
4110 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4111 if (!header
) return STATUS_NO_MEMORY
;
4113 memset(header
, 0, sizeof(*header
));
4114 header
->magic
= GUIDSECTION_MAGIC
;
4115 header
->size
= sizeof(*header
);
4116 header
->count
= 2*class_count
;
4117 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4118 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4119 module_offset
= sizeof(*header
);
4120 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4122 seed
= NtGetTickCount();
4123 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4125 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4126 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4127 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4129 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4130 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4136 return STATUS_SUCCESS
;
4139 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4141 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4144 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4146 struct comclassredirect_data
*comclass
;
4147 struct guid_index
*index
= NULL
;
4149 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4151 if (!actctx
->comserver_section
)
4153 struct guidsection_header
*section
;
4155 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4156 if (status
) return status
;
4158 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4159 RtlFreeHeap(GetProcessHeap(), 0, section
);
4162 index
= find_guid_index(actctx
->comserver_section
, guid
);
4163 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4165 comclass
= get_comclass_data(actctx
, index
);
4167 data
->ulDataFormatVersion
= 1;
4168 data
->lpData
= comclass
;
4169 /* full length includes string length with nulls */
4170 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4171 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4172 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4173 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4174 data
->lpSectionBase
= actctx
->comserver_section
;
4175 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->comserver_section
);
4176 data
->hActCtx
= NULL
;
4178 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4179 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4181 return STATUS_SUCCESS
;
4184 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4188 for (i
= 0; i
< entities
->num
; i
++)
4190 struct entity
*entity
= &entities
->base
[i
];
4191 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4193 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4194 if (entity
->u
.ifaceps
.name
)
4195 *len
+= aligned_string_len((wcslen(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4201 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4202 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4206 for (i
= 0; i
< entities
->num
; i
++)
4208 struct entity
*entity
= &entities
->base
[i
];
4209 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4211 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4215 if (entity
->u
.ifaceps
.name
)
4216 name_len
= wcslen(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4221 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4222 RtlGUIDFromString(&str
, &(*index
)->guid
);
4223 (*index
)->data_offset
= *data_offset
;
4224 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4225 (*index
)->rosterindex
= rosterindex
;
4227 /* setup data record */
4228 data
->size
= sizeof(*data
);
4229 data
->mask
= entity
->u
.ifaceps
.mask
;
4231 /* proxyStubClsid32 value is only stored for external PS,
4232 if set it's used as iid, otherwise 'iid' attribute value is used */
4233 if (entity
->u
.ifaceps
.ps32
)
4235 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4236 RtlGUIDFromString(&str
, &data
->iid
);
4239 data
->iid
= (*index
)->guid
;
4241 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4243 if (entity
->u
.ifaceps
.tlib
)
4245 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4246 RtlGUIDFromString(&str
, &data
->tlbid
);
4249 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4251 if (entity
->u
.ifaceps
.base
)
4253 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4254 RtlGUIDFromString(&str
, &data
->base
);
4257 memset(&data
->base
, 0, sizeof(data
->base
));
4259 data
->name_len
= name_len
;
4260 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4265 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4266 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4267 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4270 /* move to next record */
4272 *data_offset
+= sizeof(*data
);
4274 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4279 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4281 unsigned int i
, j
, total_len
= 0, count
= 0;
4282 struct guidsection_header
*header
;
4283 struct guid_index
*index
;
4286 /* compute section length */
4287 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4289 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4291 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4292 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4294 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4295 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4299 total_len
+= sizeof(*header
);
4301 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4302 if (!header
) return STATUS_NO_MEMORY
;
4304 memset(header
, 0, sizeof(*header
));
4305 header
->magic
= GUIDSECTION_MAGIC
;
4306 header
->size
= sizeof(*header
);
4307 header
->count
= count
;
4308 header
->index_offset
= sizeof(*header
);
4309 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4310 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4312 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4314 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4316 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4317 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4319 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4320 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4326 return STATUS_SUCCESS
;
4329 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4331 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4334 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4336 struct ifacepsredirect_data
*iface
;
4337 struct guid_index
*index
= NULL
;
4339 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4341 if (!actctx
->ifaceps_section
)
4343 struct guidsection_header
*section
;
4345 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4346 if (status
) return status
;
4348 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4349 RtlFreeHeap(GetProcessHeap(), 0, section
);
4352 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4353 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4355 iface
= get_ifaceps_data(actctx
, index
);
4357 data
->ulDataFormatVersion
= 1;
4358 data
->lpData
= iface
;
4359 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4360 data
->lpSectionGlobalData
= NULL
;
4361 data
->ulSectionGlobalDataLength
= 0;
4362 data
->lpSectionBase
= actctx
->ifaceps_section
;
4363 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->ifaceps_section
);
4364 data
->hActCtx
= NULL
;
4366 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4367 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4369 return STATUS_SUCCESS
;
4372 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4374 unsigned int i
, j
, total_len
= 0, count
= 0;
4375 struct guidsection_header
*header
;
4376 struct clrsurrogate_data
*data
;
4377 struct guid_index
*index
;
4380 /* compute section length */
4381 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4383 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4384 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4386 struct entity
*entity
= &assembly
->entities
.base
[j
];
4387 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4391 total_len
+= sizeof(*index
) + sizeof(*data
);
4392 len
= wcslen(entity
->u
.clrsurrogate
.name
) + 1;
4393 if (entity
->u
.clrsurrogate
.version
)
4394 len
+= wcslen(entity
->u
.clrsurrogate
.version
) + 1;
4395 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4402 total_len
+= sizeof(*header
);
4404 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4405 if (!header
) return STATUS_NO_MEMORY
;
4407 memset(header
, 0, sizeof(*header
));
4408 header
->magic
= GUIDSECTION_MAGIC
;
4409 header
->size
= sizeof(*header
);
4410 header
->count
= count
;
4411 header
->index_offset
= sizeof(*header
);
4412 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4413 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4415 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4417 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4418 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4420 struct entity
*entity
= &assembly
->entities
.base
[j
];
4421 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4423 ULONG version_len
, name_len
;
4427 if (entity
->u
.clrsurrogate
.version
)
4428 version_len
= wcslen(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4431 name_len
= wcslen(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4433 /* setup new index entry */
4434 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4435 RtlGUIDFromString(&str
, &index
->guid
);
4437 index
->data_offset
= data_offset
;
4438 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4439 index
->rosterindex
= i
+ 1;
4442 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4443 data
->size
= sizeof(*data
);
4445 data
->clsid
= index
->guid
;
4446 data
->version_offset
= version_len
? data
->size
: 0;
4447 data
->version_len
= version_len
;
4448 data
->name_offset
= data
->size
+ version_len
;
4450 data
->name_offset
+= sizeof(WCHAR
);
4451 data
->name_len
= name_len
;
4453 /* surrogate name */
4454 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4455 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4456 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4458 /* runtime version */
4459 if (data
->version_len
)
4461 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4462 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4463 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4466 data_offset
+= index
->data_offset
;
4474 return STATUS_SUCCESS
;
4477 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4479 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4482 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4484 struct clrsurrogate_data
*surrogate
;
4485 struct guid_index
*index
= NULL
;
4487 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4489 if (!actctx
->clrsurrogate_section
)
4491 struct guidsection_header
*section
;
4493 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4494 if (status
) return status
;
4496 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4497 RtlFreeHeap(GetProcessHeap(), 0, section
);
4500 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4501 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4503 surrogate
= get_surrogate_data(actctx
, index
);
4505 data
->ulDataFormatVersion
= 1;
4506 data
->lpData
= surrogate
;
4507 /* full length includes string length with nulls */
4508 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4509 if (surrogate
->version_len
)
4510 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4512 data
->lpSectionGlobalData
= NULL
;
4513 data
->ulSectionGlobalDataLength
= 0;
4514 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4515 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4516 data
->hActCtx
= NULL
;
4518 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4519 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4521 return STATUS_SUCCESS
;
4524 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4526 unsigned int i
, j
, single_len
;
4528 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4529 for (i
= 0; i
< entities
->num
; i
++)
4531 struct entity
*entity
= &entities
->base
[i
];
4532 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4534 if (entity
->u
.comclass
.progid
)
4536 *total_len
+= single_len
+ aligned_string_len((wcslen(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4540 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4541 *total_len
+= aligned_string_len((wcslen(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4543 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4544 *count
+= entity
->u
.comclass
.progids
.num
;
4549 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4550 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4552 struct progidredirect_data
*data
;
4557 /* setup new index entry */
4559 /* hash progid name */
4560 RtlInitUnicodeString(&str
, progid
);
4561 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4563 (*index
)->name_offset
= *data_offset
;
4564 (*index
)->name_len
= str
.Length
;
4565 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4566 (*index
)->data_len
= sizeof(*data
);
4567 (*index
)->rosterindex
= rosterindex
;
4569 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4571 /* setup data structure */
4572 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4573 data
->size
= sizeof(*data
);
4575 data
->clsid_offset
= *global_offset
;
4577 /* write progid string */
4578 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4579 memcpy(ptrW
, progid
, (*index
)->name_len
);
4580 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4582 /* write guid to global area */
4583 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4587 *global_offset
+= sizeof(GUID
);
4588 *data_offset
+= data
->size
;
4592 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4593 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4597 for (i
= 0; i
< entities
->num
; i
++)
4599 struct entity
*entity
= &entities
->base
[i
];
4600 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4602 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4603 struct comclassredirect_data
*comclass
;
4604 struct guid_index
*guid_index
;
4608 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4609 RtlGUIDFromString(&str
, &clsid
);
4611 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4612 comclass
= get_comclass_data(actctx
, guid_index
);
4614 if (entity
->u
.comclass
.progid
)
4615 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4616 index
, data_offset
, global_offset
, rosterindex
);
4618 for (j
= 0; j
< progids
->num
; j
++)
4619 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4620 index
, data_offset
, global_offset
, rosterindex
);
4625 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4627 unsigned int i
, j
, total_len
= 0, count
= 0;
4628 struct strsection_header
*header
;
4629 ULONG data_offset
, global_offset
;
4630 struct string_index
*index
;
4632 /* compute section length */
4633 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4635 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4637 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4638 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4640 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4641 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4645 total_len
+= sizeof(*header
);
4647 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
4648 if (!header
) return STATUS_NO_MEMORY
;
4650 memset(header
, 0, sizeof(*header
));
4651 header
->magic
= STRSECTION_MAGIC
;
4652 header
->size
= sizeof(*header
);
4653 header
->count
= count
;
4654 header
->global_offset
= header
->size
;
4655 header
->global_len
= count
*sizeof(GUID
);
4656 header
->index_offset
= header
->size
+ header
->global_len
;
4658 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4659 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4660 global_offset
= header
->global_offset
;
4662 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4664 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4666 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4667 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4669 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4670 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4676 return STATUS_SUCCESS
;
4679 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4681 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4684 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4685 PACTCTX_SECTION_KEYED_DATA data
)
4687 struct progidredirect_data
*progid
;
4688 struct string_index
*index
;
4690 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4692 if (!actctx
->comserver_section
)
4694 struct guidsection_header
*section
;
4696 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4697 if (status
) return status
;
4699 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4700 RtlFreeHeap(GetProcessHeap(), 0, section
);
4703 if (!actctx
->progid_section
)
4705 struct strsection_header
*section
;
4707 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4708 if (status
) return status
;
4710 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4711 RtlFreeHeap(GetProcessHeap(), 0, section
);
4714 index
= find_string_index(actctx
->progid_section
, name
);
4715 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4719 progid
= get_progid_data(actctx
, index
);
4721 data
->ulDataFormatVersion
= 1;
4722 data
->lpData
= progid
;
4723 data
->ulLength
= progid
->size
;
4724 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4725 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4726 data
->lpSectionBase
= actctx
->progid_section
;
4727 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->progid_section
);
4728 data
->hActCtx
= NULL
;
4730 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4731 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4734 return STATUS_SUCCESS
;
4737 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4738 const UNICODE_STRING
*section_name
,
4739 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4743 switch (section_kind
)
4745 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4746 status
= find_dll_redirection(actctx
, section_name
, data
);
4748 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4749 status
= find_window_class(actctx
, section_name
, data
);
4751 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4752 status
= find_progid_redirection(actctx
, section_name
, data
);
4754 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4755 FIXME("Unsupported yet section_kind %x\n", section_kind
);
4756 return STATUS_SXS_SECTION_NOT_FOUND
;
4758 WARN("Unknown section_kind %x\n", section_kind
);
4759 return STATUS_SXS_SECTION_NOT_FOUND
;
4762 if (status
!= STATUS_SUCCESS
) return status
;
4764 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4766 actctx_addref(actctx
);
4767 data
->hActCtx
= actctx
;
4769 return STATUS_SUCCESS
;
4772 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4773 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4777 switch (section_kind
)
4779 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4780 status
= find_tlib_redirection(actctx
, guid
, data
);
4782 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4783 status
= find_comserver_redirection(actctx
, guid
, data
);
4785 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4786 status
= find_cominterface_redirection(actctx
, guid
, data
);
4788 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4789 status
= find_clr_surrogate(actctx
, guid
, data
);
4792 WARN("Unknown section_kind %x\n", section_kind
);
4793 return STATUS_SXS_SECTION_NOT_FOUND
;
4796 if (status
!= STATUS_SUCCESS
) return status
;
4798 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4800 actctx_addref(actctx
);
4801 data
->hActCtx
= actctx
;
4803 return STATUS_SUCCESS
;
4806 static const WCHAR
*find_app_settings( ACTIVATION_CONTEXT
*actctx
, const WCHAR
*settings
, const WCHAR
*ns
)
4810 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4812 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4813 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4815 struct entity
*entity
= &assembly
->entities
.base
[j
];
4816 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS
&&
4817 !wcscmp( entity
->u
.settings
.name
, settings
) &&
4818 !wcscmp( entity
->u
.settings
.ns
, ns
))
4819 return entity
->u
.settings
.value
;
4825 /* initialize the activation context for the current process */
4826 void actctx_init(void)
4831 ctx
.cbSize
= sizeof(ctx
);
4832 ctx
.lpSource
= NULL
;
4833 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4834 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4835 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4837 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
4839 NtCurrentTeb()->Peb
->ActivationContextData
= process_actctx
;
4843 /***********************************************************************
4844 * RtlCreateActivationContext (NTDLL.@)
4846 * Create an activation context.
4848 * FIXME: function signature/prototype is wrong
4850 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
4852 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
4853 const WCHAR
*directory
= NULL
;
4854 ACTIVATION_CONTEXT
*actctx
;
4855 UNICODE_STRING nameW
;
4857 NTSTATUS status
= STATUS_NO_MEMORY
;
4859 struct actctx_loader acl
;
4861 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
4863 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4864 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4865 return STATUS_INVALID_PARAMETER
;
4867 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
4868 return STATUS_NO_MEMORY
;
4870 actctx
->magic
= ACTCTX_MAGIC
;
4871 actctx
->ref_count
= 1;
4872 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4873 actctx
->config
.info
= NULL
;
4874 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4875 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4877 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4885 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4886 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
4888 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
4889 if ((p
= wcsrchr( dir
.Buffer
, '\\' ))) p
[1] = 0;
4890 actctx
->appdir
.info
= dir
.Buffer
;
4893 nameW
.Buffer
= NULL
;
4895 /* open file only if it's going to be used */
4896 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4897 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4899 WCHAR
*source
= NULL
;
4902 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4903 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RELATIVE_PATH
)
4905 DWORD dir_len
, source_len
;
4907 dir_len
= wcslen(pActCtx
->lpAssemblyDirectory
);
4908 source_len
= wcslen(pActCtx
->lpSource
);
4909 if (!(source
= RtlAllocateHeap( GetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4911 status
= STATUS_NO_MEMORY
;
4915 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4916 source
[dir_len
] = '\\';
4917 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4920 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4921 RtlFreeHeap( GetProcessHeap(), 0, source
);
4924 status
= STATUS_NO_SUCH_FILE
;
4927 status
= open_nt_file( &file
, &nameW
);
4930 RtlFreeUnicodeString( &nameW
);
4935 acl
.actctx
= actctx
;
4936 acl
.dependencies
= NULL
;
4937 acl
.num_dependencies
= 0;
4938 acl
.allocated_dependencies
= 0;
4940 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4941 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4943 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4945 /* if we have a resource it's a PE file */
4946 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4948 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4949 pActCtx
->lpResourceName
, lang
);
4950 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4951 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4952 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4954 else if (pActCtx
->lpSource
)
4956 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4957 file
, pActCtx
->lpResourceName
, lang
);
4958 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4959 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4960 NULL
, pActCtx
->lpResourceName
);
4962 else status
= STATUS_INVALID_PARAMETER
;
4966 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4969 if (file
) NtClose( file
);
4970 RtlFreeUnicodeString( &nameW
);
4972 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
4973 free_depend_manifests( &acl
);
4975 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
4976 else actctx_release( actctx
);
4980 if (file
) NtClose( file
);
4981 actctx_release( actctx
);
4986 /***********************************************************************
4987 * RtlAddRefActivationContext (NTDLL.@)
4989 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
4991 ACTIVATION_CONTEXT
*actctx
;
4993 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4997 /******************************************************************
4998 * RtlReleaseActivationContext (NTDLL.@)
5000 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
5002 ACTIVATION_CONTEXT
*actctx
;
5004 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5007 /******************************************************************
5008 * RtlZombifyActivationContext (NTDLL.@)
5010 * FIXME: function prototype might be wrong
5012 NTSTATUS WINAPI
RtlZombifyActivationContext( HANDLE handle
)
5014 FIXME("%p: stub\n", handle
);
5015 return STATUS_NOT_IMPLEMENTED
;
5018 /******************************************************************
5019 * RtlActivateActivationContext (NTDLL.@)
5021 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
5023 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle
, cookie
);
5027 /******************************************************************
5028 * RtlActivateActivationContextEx (NTDLL.@)
5030 NTSTATUS WINAPI
RtlActivateActivationContextEx( ULONG flags
, TEB
*teb
, HANDLE handle
, ULONG_PTR
*cookie
)
5032 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5034 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
5035 return STATUS_NO_MEMORY
;
5037 frame
->Previous
= teb
->ActivationContextStack
.ActiveFrame
;
5038 frame
->ActivationContext
= handle
;
5040 teb
->ActivationContextStack
.ActiveFrame
= frame
;
5041 RtlAddRefActivationContext( handle
);
5043 *cookie
= (ULONG_PTR
)frame
;
5044 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
5045 return STATUS_SUCCESS
;
5049 /***********************************************************************
5050 * RtlDeactivateActivationContext (NTDLL.@)
5052 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5054 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5056 TRACE( "%x cookie=%lx\n", flags
, cookie
);
5058 /* find the right frame */
5059 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5060 for (frame
= top
; frame
; frame
= frame
->Previous
)
5061 if ((ULONG_PTR
)frame
== cookie
) break;
5064 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5066 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
5067 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5069 /* pop everything up to and including frame */
5070 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
5072 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5074 frame
= top
->Previous
;
5075 RtlReleaseActivationContext( top
->ActivationContext
);
5076 RtlFreeHeap( GetProcessHeap(), 0, top
);
5082 /******************************************************************
5083 * RtlFreeThreadActivationContextStack (NTDLL.@)
5085 void WINAPI
RtlFreeThreadActivationContextStack(void)
5087 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5089 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
5092 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
5093 RtlReleaseActivationContext( frame
->ActivationContext
);
5094 RtlFreeHeap( GetProcessHeap(), 0, frame
);
5097 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
5101 /******************************************************************
5102 * RtlGetActiveActivationContext (NTDLL.@)
5104 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5106 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5108 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
5109 RtlAddRefActivationContext( *handle
);
5114 return STATUS_SUCCESS
;
5118 /******************************************************************
5119 * RtlIsActivationContextActive (NTDLL.@)
5121 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
5123 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5125 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
5126 if (frame
->ActivationContext
== handle
) return TRUE
;
5131 /***********************************************************************
5132 * RtlQueryInformationActivationContext (NTDLL.@)
5134 * Get information about an activation context.
5135 * FIXME: function signature/prototype may be wrong
5137 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5138 ULONG
class, PVOID buffer
,
5139 SIZE_T bufsize
, SIZE_T
*retlen
)
5141 ACTIVATION_CONTEXT
*actctx
;
5144 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
5145 subinst
, class, buffer
, bufsize
, retlen
);
5147 if (retlen
) *retlen
= 0;
5148 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5152 case ActivationContextBasicInformation
:
5154 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5156 if (retlen
) *retlen
= sizeof(*info
);
5157 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5159 info
->hActCtx
= handle
;
5160 info
->dwFlags
= 0; /* FIXME */
5161 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
5165 case ActivationContextDetailedInformation
:
5167 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5168 struct assembly
*assembly
= NULL
;
5169 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5172 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5174 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5176 if (assembly
&& assembly
->manifest
.info
)
5177 manifest_len
= wcslen(assembly
->manifest
.info
) + 1;
5178 if (actctx
->config
.info
) config_len
= wcslen(actctx
->config
.info
) + 1;
5179 if (actctx
->appdir
.info
) appdir_len
= wcslen(actctx
->appdir
.info
) + 1;
5180 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5182 if (retlen
) *retlen
= len
;
5183 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5186 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5187 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5188 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5189 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
5190 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5191 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
5192 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5193 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
5194 ptr
= (LPWSTR
)(acdi
+ 1);
5197 acdi
->lpRootManifestPath
= ptr
;
5198 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5199 ptr
+= manifest_len
;
5201 else acdi
->lpRootManifestPath
= NULL
;
5204 acdi
->lpRootConfigurationPath
= ptr
;
5205 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5208 else acdi
->lpRootConfigurationPath
= NULL
;
5211 acdi
->lpAppDirPath
= ptr
;
5212 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5214 else acdi
->lpAppDirPath
= NULL
;
5218 case AssemblyDetailedInformationInActivationContext
:
5220 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5221 struct assembly
*assembly
;
5224 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5227 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5228 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5230 index
= *(DWORD
*)subinst
;
5231 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5233 assembly
= &actctx
->assemblies
[index
- 1];
5235 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5236 id_len
= wcslen(assembly_id
) + 1;
5237 if (assembly
->directory
) ad_len
= wcslen(assembly
->directory
) + 1;
5239 if (assembly
->manifest
.info
&&
5240 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5241 path_len
= wcslen(assembly
->manifest
.info
) + 1;
5243 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5245 if (retlen
) *retlen
= len
;
5246 if (!buffer
|| bufsize
< len
)
5248 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5249 return STATUS_BUFFER_TOO_SMALL
;
5252 afdi
->ulFlags
= 0; /* FIXME */
5253 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
5254 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5255 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
5256 /* FIXME afdi->liManifestLastWriteTime = 0; */
5257 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5258 afdi
->ulPolicyPathLength
= 0;
5259 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5260 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5261 afdi
->ulManifestVersionMajor
= 1;
5262 afdi
->ulManifestVersionMinor
= 0;
5263 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5264 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5265 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
5266 ptr
= (LPWSTR
)(afdi
+ 1);
5267 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5268 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5272 afdi
->lpAssemblyManifestPath
= ptr
;
5273 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5275 } else afdi
->lpAssemblyManifestPath
= NULL
;
5276 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5279 afdi
->lpAssemblyDirectoryName
= ptr
;
5280 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5282 else afdi
->lpAssemblyDirectoryName
= NULL
;
5283 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
5287 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5289 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5290 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5291 struct assembly
*assembly
;
5292 struct dll_redirect
*dll
;
5293 SIZE_T len
, dll_len
= 0;
5296 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5297 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5299 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5300 return STATUS_INVALID_PARAMETER
;
5301 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5303 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5304 return STATUS_INVALID_PARAMETER
;
5305 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5307 if (dll
->name
) dll_len
= wcslen(dll
->name
) + 1;
5308 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5310 if (!buffer
|| bufsize
< len
)
5312 if (retlen
) *retlen
= len
;
5313 return STATUS_BUFFER_TOO_SMALL
;
5315 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5316 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5317 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
5318 afdi
->ulPathLength
= 0; /* FIXME */
5319 ptr
= (LPWSTR
)(afdi
+ 1);
5322 afdi
->lpFileName
= ptr
;
5323 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5324 } else afdi
->lpFileName
= NULL
;
5325 afdi
->lpFilePath
= NULL
; /* FIXME */
5329 case CompatibilityInformationInActivationContext
:
5331 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5332 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5333 struct assembly
*assembly
= NULL
;
5334 ULONG num_compat_contexts
= 0, n
;
5337 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5339 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5342 num_compat_contexts
= assembly
->num_compat_contexts
;
5343 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5345 if (retlen
) *retlen
= len
;
5346 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5348 *acci
= num_compat_contexts
;
5349 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5350 for (n
= 0; n
< num_compat_contexts
; ++n
)
5352 elements
[n
] = assembly
->compat_contexts
[n
];
5357 case RunlevelInformationInActivationContext
:
5359 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5360 struct assembly
*assembly
;
5363 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5365 len
= sizeof(*acrli
);
5366 if (retlen
) *retlen
= len
;
5367 if (!buffer
|| bufsize
< len
)
5368 return STATUS_BUFFER_TOO_SMALL
;
5370 assembly
= actctx
->assemblies
;
5373 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5374 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5379 FIXME( "class %u not implemented\n", class );
5380 return STATUS_NOT_IMPLEMENTED
;
5382 return STATUS_SUCCESS
;
5385 /***********************************************************************
5386 * RtlFindActivationContextSectionString (NTDLL.@)
5388 * Find information about a string in an activation context.
5389 * FIXME: function signature/prototype may be wrong
5391 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5392 const UNICODE_STRING
*section_name
, PVOID ptr
)
5394 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5395 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5397 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
5398 debugstr_us(section_name
), data
);
5402 FIXME("expected guid == NULL\n");
5403 return STATUS_INVALID_PARAMETER
;
5405 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5407 FIXME("unknown flags %08x\n", flags
);
5408 return STATUS_INVALID_PARAMETER
;
5410 if ((data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)) ||
5411 !section_name
|| !section_name
->Buffer
)
5413 WARN("invalid parameter\n");
5414 return STATUS_INVALID_PARAMETER
;
5417 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5419 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5420 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5423 if (status
!= STATUS_SUCCESS
)
5424 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5429 /***********************************************************************
5430 * RtlFindActivationContextSectionGuid (NTDLL.@)
5432 * Find information about a GUID in an activation context.
5433 * FIXME: function signature/prototype may be wrong
5435 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5436 const GUID
*guid
, void *ptr
)
5438 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5439 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5441 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
5445 FIXME("expected extguid == NULL\n");
5446 return STATUS_INVALID_PARAMETER
;
5449 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5451 FIXME("unknown flags %08x\n", flags
);
5452 return STATUS_INVALID_PARAMETER
;
5455 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5456 return STATUS_INVALID_PARAMETER
;
5458 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
5460 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
5461 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5464 if (status
!= STATUS_SUCCESS
)
5465 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5471 /***********************************************************************
5472 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5474 NTSTATUS WINAPI
RtlQueryActivationContextApplicationSettings( DWORD flags
, HANDLE handle
, const WCHAR
*ns
,
5475 const WCHAR
*settings
, WCHAR
*buffer
,
5476 SIZE_T size
, SIZE_T
*written
)
5478 ACTIVATION_CONTEXT
*actctx
;
5483 WARN( "unknown flags %08x\n", flags
);
5484 return STATUS_INVALID_PARAMETER
;
5489 if (wcscmp( ns
, windowsSettings2005NSW
) &&
5490 wcscmp( ns
, windowsSettings2011NSW
) &&
5491 wcscmp( ns
, windowsSettings2016NSW
) &&
5492 wcscmp( ns
, windowsSettings2017NSW
))
5493 return STATUS_INVALID_PARAMETER
;
5495 else ns
= windowsSettings2005NSW
;
5497 if (!handle
) handle
= process_actctx
;
5498 if (!(actctx
= check_actctx( handle
))) return STATUS_INVALID_PARAMETER
;
5500 if (!(res
= find_app_settings( actctx
, settings
, ns
))) return STATUS_SXS_KEY_NOT_FOUND
;
5502 if (written
) *written
= wcslen(res
) + 1;
5503 if (size
< wcslen(res
)) return STATUS_BUFFER_TOO_SMALL
;
5504 wcscpy( buffer
, res
);
5505 return STATUS_SUCCESS
;