2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Runtime Library
4 * PURPOSE: Activation Context Support
5 * FILE: lib/rtl/actctx.c
9 * Jacek Caban for CodeWeavers
11 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
15 /* Based on Wine Staging 1.7.37 */
22 #include <wine/unicode.h>
24 BOOLEAN RtlpNotAllowingMultipleActivation
;
26 #define ACTCTX_FLAGS_ALL (\
27 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
28 ACTCTX_FLAG_LANGID_VALID |\
29 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
30 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
31 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
32 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
33 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
34 ACTCTX_FLAG_HMODULE_VALID )
36 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
37 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
39 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
41 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
42 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
64 struct assembly_version
72 struct assembly_identity
79 struct assembly_version version
;
84 struct strsection_header
98 ULONG hash
; /* key string hash */
101 ULONG data_offset
; /* redirect data offset */
106 struct guidsection_header
126 struct wndclass_redirect_data
131 ULONG name_offset
; /* versioned name offset */
133 ULONG module_offset
;/* container name offset */
136 struct dllredirect_data
143 struct tlibredirect_data
157 enum comclass_threadingmodel
159 ThreadingModel_Apartment
= 1,
160 ThreadingModel_Free
= 2,
161 ThreadingModel_No
= 3,
162 ThreadingModel_Both
= 4,
163 ThreadingModel_Neutral
= 5
166 enum comclass_miscfields
170 MiscStatusContent
= 4,
171 MiscStatusThumbnail
= 8,
172 MiscStatusDocPrint
= 16
175 struct comclassredirect_data
191 ULONG clrdata_offset
;
193 DWORD miscstatuscontent
;
194 DWORD miscstatusthumbnail
;
195 DWORD miscstatusicon
;
196 DWORD miscstatusdocprint
;
205 struct ifacepsredirect_data
217 struct clrsurrogate_data
222 ULONG version_offset
;
237 ULONG version_offset
;
241 struct progidredirect_data
252 Sections are accessible by string or guid key, that defines two types of sections.
253 All sections of each type have same magic value and header structure, index
254 data could be of two possible types too. So every string based section uses
255 the same index format, same applies to guid sections - they share same guid index
258 - window class redirection section is a plain buffer with following format:
262 <data[]> --- <original name>
267 Header is fixed length structure - struct strsection_header,
268 contains redirected classes count;
270 Index is an array of fixed length index records, each record is
273 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
275 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
276 others are relative to section itself.
278 - dll redirect section format:
282 <data[]> --- <dll name>
285 This section doesn't seem to carry any payload data except dll names.
287 - typelib section format:
295 Header is fixed length, index is an array of fixed length 'struct guid_index'.
296 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
297 4-bytes aligned as a whole.
299 Module name offsets are relative to section, helpstring offset is relative to data
302 - comclass section format:
307 <data[]> --- <data> --- <data>
313 This section uses two index records per comclass, one entry contains original guid
314 as specified by context, another one has a generated guid. Index and strings handling
315 is similar to typelib sections.
317 For CLR classes additional data is stored after main COM class data, it contains
318 class name and runtime version string, see 'struct clrclass_data'.
320 Module name offsets are relative to section, progid offset is relative to data
323 - COM interface section format:
330 Interface section contains data for proxy/stubs and external proxy/stubs. External
331 ones are defined at assembly level, so this section has no module information.
332 All records are indexed with 'iid' value from manifest. There an exception for
333 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
334 redirect data, but index is still 'iid' from manifest.
336 Interface name offset is relative to data structure itself.
338 - CLR surrogates section format:
346 There's nothing special about this section, same way to store strings is used,
347 no modules part as it belongs to assembly level, not a file.
349 - ProgID section format:
354 <data[]> --- <progid>
357 This sections uses generated alias guids from COM server section. This way
358 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
359 is stored too, aligned.
366 unsigned int allocated
;
387 WCHAR
*name
; /* clrClass: class name */
388 WCHAR
*version
; /* clrClass: CLR runtime version */
391 DWORD miscstatuscontent
;
392 DWORD miscstatusthumbnail
;
393 DWORD miscstatusicon
;
394 DWORD miscstatusdocprint
;
395 struct progids progids
;
402 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
424 unsigned int allocated
;
431 struct entity_array entities
;
436 APPLICATION_MANIFEST
,
438 ASSEMBLY_SHARED_MANIFEST
,
443 enum assembly_type type
;
444 struct assembly_identity id
;
445 struct file_info manifest
;
448 struct dll_redirect
*dlls
;
449 unsigned int num_dlls
;
450 unsigned int allocated_dlls
;
451 struct entity_array entities
;
454 enum context_sections
456 WINDOWCLASS_SECTION
= 1,
457 DLLREDIRECT_SECTION
= 2,
458 TLIBREDIRECT_SECTION
= 4,
459 SERVERREDIRECT_SECTION
= 8,
460 IFACEREDIRECT_SECTION
= 16,
461 CLRSURROGATES_SECTION
= 32,
462 PROGIDREDIRECT_SECTION
= 64
465 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
468 UNICODE_STRING DosPath
;
470 } ASSEMBLY_STORAGE_MAP_ENTRY
, *PASSEMBLY_STORAGE_MAP_ENTRY
;
472 typedef struct _ASSEMBLY_STORAGE_MAP
476 PASSEMBLY_STORAGE_MAP_ENTRY
*AssemblyArray
;
477 } ASSEMBLY_STORAGE_MAP
, *PASSEMBLY_STORAGE_MAP
;
479 typedef struct _ACTIVATION_CONTEXT
484 PACTIVATION_CONTEXT_DATA ActivationContextData
;
485 PVOID NotificationRoutine
;
486 PVOID NotificationContext
;
487 ULONG SentNotifications
[8];
488 ULONG DisabledNotifications
[8];
489 ASSEMBLY_STORAGE_MAP StorageMap
;
490 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries
;
491 ULONG StackTraceIndex
;
492 PVOID StackTraces
[4][4];
493 struct file_info config
;
494 struct file_info appdir
;
495 struct assembly
*assemblies
;
496 unsigned int num_assemblies
;
497 unsigned int allocated_assemblies
;
500 struct strsection_header
*wndclass_section
;
501 struct strsection_header
*dllredirect_section
;
502 struct strsection_header
*progid_section
;
503 struct guidsection_header
*tlib_section
;
504 struct guidsection_header
*comserver_section
;
505 struct guidsection_header
*ifaceps_section
;
506 struct guidsection_header
*clrsurrogate_section
;
507 } ACTIVATION_CONTEXT
, *PIACTIVATION_CONTEXT
;
511 ACTIVATION_CONTEXT
*actctx
;
512 struct assembly_identity
*dependencies
;
513 unsigned int num_dependencies
;
514 unsigned int allocated_dependencies
;
517 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
518 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
520 typedef struct _ACTIVATION_CONTEXT_WRAPPED
523 ACTIVATION_CONTEXT ActivationContext
;
524 } ACTIVATION_CONTEXT_WRAPPED
, *PACTIVATION_CONTEXT_WRAPPED
;
528 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx
,
529 IN ULONG FailureCode
)
531 EXCEPTION_RECORD ExceptionRecord
;
533 /* Fatal SxS exception header */
534 ExceptionRecord
.ExceptionRecord
= NULL
;
535 ExceptionRecord
.ExceptionCode
= STATUS_SXS_CORRUPTION
;
536 ExceptionRecord
.ExceptionFlags
= EXCEPTION_NONCONTINUABLE
;
538 /* With SxS-specific information plus the context itself */
539 ExceptionRecord
.ExceptionInformation
[0] = 1;
540 ExceptionRecord
.ExceptionInformation
[1] = FailureCode
;
541 ExceptionRecord
.ExceptionInformation
[2] = (ULONG_PTR
)ActCtx
;
542 ExceptionRecord
.NumberParameters
= 3;
545 RtlRaiseException(&ExceptionRecord
);
550 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx
)
552 PACTIVATION_CONTEXT_WRAPPED pActual
;
554 /* Get the caller-opaque header */
555 pActual
= CONTAINING_RECORD(ActCtx
,
556 ACTIVATION_CONTEXT_WRAPPED
,
559 /* Check if the header matches as expected */
560 if (pActual
->MagicMarker
!= ACTCTX_MAGIC_MARKER
)
562 /* Nope, print out a warning, assert, and then throw an exception */
563 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
564 " This means someone stepped on the allocation, or someone is using a\n"
565 " deallocated activation context\n",
567 pActual
->MagicMarker
,
569 ASSERT(pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
);
570 RtlpSxsBreakOnInvalidMarker(ActCtx
, 1);
574 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
575 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
576 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
577 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
578 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
579 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
580 static const WCHAR comInterfaceExternalProxyStubW
[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
581 static const WCHAR comInterfaceProxyStubW
[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
582 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
583 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
584 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
585 static const WCHAR fileW
[] = {'f','i','l','e',0};
586 static const WCHAR hashW
[] = {'h','a','s','h',0};
587 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
588 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
589 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
590 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
592 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
593 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
594 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
595 static const WCHAR iidW
[] = {'i','i','d',0};
596 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
597 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
598 static const WCHAR g_nameW
[] = {'n','a','m','e',0};
599 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
600 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
601 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
602 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
603 static const WCHAR processorArchitectureW
[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
604 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
605 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
606 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
607 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
608 static const WCHAR typeW
[] = {'t','y','p','e',0};
609 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
610 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
611 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
612 static const WCHAR yesW
[] = {'y','e','s',0};
613 static const WCHAR noW
[] = {'n','o',0};
614 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
615 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
616 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
617 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
618 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
619 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
620 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
621 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
622 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
623 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
624 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
625 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
626 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
627 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
628 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
629 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
631 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
632 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
633 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
634 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
635 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
636 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
637 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
638 static const WCHAR ignoreactivatewhenvisibleW
[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
639 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
640 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
641 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
642 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
643 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
644 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
645 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
646 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
647 static const WCHAR renderingisdeviceindependentW
[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
648 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
649 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
650 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
651 static const WCHAR supportsmultilevelundoW
[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
652 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
660 static const struct olemisc_entry olemisc_values
[] =
662 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
663 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
664 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
665 { alignableW
, OLEMISC_ALIGNABLE
},
666 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
667 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
668 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
669 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
670 { imemodeW
, OLEMISC_IMEMODE
},
671 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
672 { insideoutW
, OLEMISC_INSIDEOUT
},
673 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
674 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
675 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
676 { onlyiconicW
, OLEMISC_ONLYICONIC
},
677 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
678 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
679 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
680 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
681 { staticW
, OLEMISC_STATIC
},
682 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
683 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
686 static const WCHAR g_xmlW
[] = {'?','x','m','l',0};
687 static const WCHAR manifestv1W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
688 static const WCHAR manifestv2W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
689 static const WCHAR manifestv3W
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
691 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
692 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
693 static const WCHAR wildcardW
[] = {'*',0};
695 static ACTIVATION_CONTEXT_WRAPPED system_actctx
= { ACTCTX_MAGIC_MARKER
, { 1 } };
696 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
.ActivationContext
;
698 static WCHAR
*strdupW(const WCHAR
* str
)
702 if (!(ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
704 return strcpyW(ptr
, str
);
707 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
711 if ((strW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
713 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
719 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
721 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
724 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
726 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
729 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
731 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
732 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
735 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
737 UINT len
= strlenW( namespace );
739 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
740 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
741 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
744 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
746 if (elem
->len
&& elem
->ptr
[0] == '/')
749 elem_end
.ptr
= elem
->ptr
+ 1;
750 elem_end
.len
= elem
->len
- 1;
751 return xml_elem_cmp( &elem_end
, str
, namespace );
756 static inline BOOL
isxmlspace( WCHAR ch
)
758 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
761 static UNICODE_STRING
xmlstr2unicode(const xmlstr_t
*xmlstr
)
765 res
.Buffer
= (PWSTR
)xmlstr
->ptr
;
766 res
.Length
= res
.MaximumLength
= (USHORT
)xmlstr
->len
* sizeof(WCHAR
);
771 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
773 struct assembly
*assembly
;
775 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx
);
777 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
780 unsigned int new_count
;
781 if (actctx
->assemblies
)
783 new_count
= actctx
->allocated_assemblies
* 2;
784 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
785 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
790 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
792 if (!ptr
) return NULL
;
793 actctx
->assemblies
= ptr
;
794 actctx
->allocated_assemblies
= new_count
;
797 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
802 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
804 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly
, assembly
->allocated_dlls
);
806 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
809 unsigned int new_count
;
812 new_count
= assembly
->allocated_dlls
* 2;
813 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
814 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
819 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
821 if (!ptr
) return NULL
;
822 assembly
->dlls
= ptr
;
823 assembly
->allocated_dlls
= new_count
;
825 return &assembly
->dlls
[assembly
->num_dlls
++];
828 static void free_assembly_identity(struct assembly_identity
*ai
)
830 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->name
);
831 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->arch
);
832 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->public_key
);
833 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->language
);
834 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->type
);
837 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
839 struct entity
* entity
;
841 if (array
->num
== array
->allocated
)
844 unsigned int new_count
;
847 new_count
= array
->allocated
* 2;
848 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
849 array
->base
, new_count
* sizeof(*array
->base
) );
854 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
856 if (!ptr
) return NULL
;
858 array
->allocated
= new_count
;
860 entity
= &array
->base
[array
->num
++];
865 static void free_entity_array(struct entity_array
*array
)
868 for (i
= 0; i
< array
->num
; i
++)
870 struct entity
*entity
= &array
->base
[i
];
871 switch (entity
->kind
)
873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
874 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
875 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
876 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progid
);
877 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.name
);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.version
);
879 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
880 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
881 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
883 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
884 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
885 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
886 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
887 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
888 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
891 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
892 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
894 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
895 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.class.name
);
897 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
898 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
899 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
900 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
903 DPRINT1("Unknown entity kind %u\n", entity
->kind
);
906 RtlFreeHeap( RtlGetProcessHeap(), 0, array
->base
);
909 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
911 if (!str1
) return !str2
;
912 return str2
&& !strcmpiW( str1
, str2
);
915 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
916 const struct assembly_identity
*id2
)
918 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
919 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
920 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
922 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
924 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
927 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
928 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
929 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
930 if (id1
->version
.build
== id2
->version
.build
&&
931 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
935 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
936 struct assembly_identity
* ai
)
940 /* check if we already have that assembly */
942 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
943 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
945 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
946 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
947 ai
->version
.build
, ai
->version
.revision
);
951 for (i
= 0; i
< acl
->num_dependencies
; i
++)
952 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
954 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
955 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
956 ai
->version
.build
, ai
->version
.revision
);
960 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
963 unsigned int new_count
;
964 if (acl
->dependencies
)
966 new_count
= acl
->allocated_dependencies
* 2;
967 ptr
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl
->dependencies
,
968 new_count
* sizeof(acl
->dependencies
[0]));
973 ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
975 if (!ptr
) return FALSE
;
976 acl
->dependencies
= ptr
;
977 acl
->allocated_dependencies
= new_count
;
979 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
984 static void free_depend_manifests(struct actctx_loader
* acl
)
987 for (i
= 0; i
< acl
->num_dependencies
; i
++)
988 free_assembly_identity(&acl
->dependencies
[i
]);
989 RtlFreeHeap(RtlGetProcessHeap(), 0, acl
->dependencies
);
992 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
994 static const WCHAR undW
[] = {'_',0};
995 static const WCHAR noneW
[] = {'n','o','n','e',0};
996 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
998 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
999 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1000 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1001 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1002 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
1003 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1006 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
))) return NULL
;
1008 strcpyW( ret
, arch
);
1009 strcatW( ret
, undW
);
1010 strcatW( ret
, name
);
1011 strcatW( ret
, undW
);
1012 strcatW( ret
, key
);
1013 strcatW( ret
, undW
);
1014 sprintfW( ret
+ strlenW(ret
), version_formatW
,
1015 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1016 strcatW( ret
, undW
);
1017 strcatW( ret
, lang
);
1018 strcatW( ret
, undW
);
1019 strcatW( ret
, mskeyW
);
1023 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1028 strcatW( buffer
, prefix
);
1037 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1039 static const WCHAR archW
[] =
1040 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1041 static const WCHAR public_keyW
[] =
1042 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1043 static const WCHAR typeW2
[] =
1044 {',','t','y','p','e','=',0};
1045 static const WCHAR versionW2
[] =
1046 {',','v','e','r','s','i','o','n','=',0};
1048 WCHAR version
[64], *ret
;
1051 sprintfW( version
, version_formatW
,
1052 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1053 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1054 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1055 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1056 if (ai
->type
) size
+= strlenW(typeW2
) + strlenW(ai
->type
) + 2;
1057 size
+= strlenW(versionW2
) + strlenW(version
) + 2;
1059 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1062 if (ai
->name
) strcpyW( ret
, ai
->name
);
1064 append_string( ret
, archW
, ai
->arch
);
1065 append_string( ret
, public_keyW
, ai
->public_key
);
1066 append_string( ret
, typeW2
, ai
->type
);
1067 append_string( ret
, versionW2
, version
);
1071 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1073 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1074 PACTIVATION_CONTEXT_WRAPPED pActual
;
1076 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1081 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1082 if (pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
) ret
= &pActual
->ActivationContext
;
1085 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1087 DPRINT1("Invalid activation context handle!\n");
1093 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1095 InterlockedExchangeAdd( &actctx
->RefCount
, 1 );
1098 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1100 PACTIVATION_CONTEXT_WRAPPED pActual
;
1102 if (InterlockedExchangeAdd(&actctx
->RefCount
, -1) == 1)
1106 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1108 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1109 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1111 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1112 free_entity_array( &dll
->entities
);
1113 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->name
);
1114 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->hash
);
1116 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->dlls
);
1117 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->manifest
.info
);
1118 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->directory
);
1119 free_entity_array( &assembly
->entities
);
1120 free_assembly_identity(&assembly
->id
);
1122 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->config
.info
);
1123 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->appdir
.info
);
1124 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->assemblies
);
1125 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
1126 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
1127 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
1128 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
1129 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
1130 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1131 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
1133 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1134 pActual
->MagicMarker
= 0;
1135 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual
);
1139 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1140 BOOL
* error
, BOOL
* end
)
1146 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1149 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1151 if (*xmlbuf
->ptr
== '/')
1154 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1163 if (*xmlbuf
->ptr
== '>')
1171 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1173 if (ptr
== xmlbuf
->end
) return FALSE
;
1175 name
->ptr
= xmlbuf
->ptr
;
1176 name
->len
= ptr
-xmlbuf
->ptr
;
1179 /* skip spaces before '=' */
1180 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1181 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1183 /* skip '=' itself */
1185 if (ptr
== xmlbuf
->end
) return FALSE
;
1187 /* skip spaces after '=' */
1188 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1190 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1193 if (ptr
== xmlbuf
->end
) return FALSE
;
1195 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1198 xmlbuf
->ptr
= xmlbuf
->end
;
1202 value
->len
= ptr
- value
->ptr
;
1203 xmlbuf
->ptr
= ptr
+ 1;
1205 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1211 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1217 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1220 xmlbuf
->ptr
= xmlbuf
->end
;
1224 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1226 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1227 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1229 if (ptr
+ 3 > xmlbuf
->end
)
1231 xmlbuf
->ptr
= xmlbuf
->end
;
1234 xmlbuf
->ptr
= ptr
+ 3;
1240 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1243 elem
->ptr
= xmlbuf
->ptr
;
1244 elem
->len
= ptr
- xmlbuf
->ptr
;
1246 return xmlbuf
->ptr
!= xmlbuf
->end
;
1249 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1251 /* FIXME: parse attributes */
1254 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1256 if (ptr
[0] == '?' && ptr
[1] == '>')
1258 xmlbuf
->ptr
= ptr
+ 2;
1265 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1267 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1269 if (!ptr
) return FALSE
;
1271 content
->ptr
= xmlbuf
->ptr
;
1272 content
->len
= ptr
- xmlbuf
->ptr
;
1278 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1280 unsigned int ver
[4];
1283 UNICODE_STRING strU
;
1285 /* major.minor.build.revision */
1286 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1287 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1289 if (*curr
>= '0' && *curr
<= '9')
1291 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1292 if (ver
[pos
] >= 0x10000) goto error
;
1294 else if (*curr
== '.')
1296 if (++pos
>= 4) goto error
;
1300 version
->major
= ver
[0];
1301 version
->minor
= ver
[1];
1302 version
->build
= ver
[2];
1303 version
->revision
= ver
[3];
1307 strU
= xmlstr2unicode(str
);
1308 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU
);
1312 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1315 UNICODE_STRING elemU
;
1316 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1317 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1318 elemU
= xmlstr2unicode(&elem
);
1319 DPRINT1( "unexpected element %wZ\n", &elemU
);
1323 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1325 xmlstr_t attr_name
, attr_value
;
1326 UNICODE_STRING attr_nameU
, attr_valueU
;
1329 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1331 attr_nameU
= xmlstr2unicode(&attr_name
);
1332 attr_valueU
= xmlstr2unicode(&attr_value
);
1333 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU
,
1339 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1342 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1345 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1348 UNICODE_STRING elemU
;
1349 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1350 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1352 elemU
= xmlstr2unicode(&elem
);
1353 DPRINT1( "unexpected element %wZ\n", &elemU
);
1356 return parse_end_element(xmlbuf
);
1359 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1361 xmlstr_t attr_name
, attr_value
, elem
;
1362 BOOL end
= FALSE
, error
, ret
= TRUE
;
1364 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1365 if(error
|| end
) return end
;
1367 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1369 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1370 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1373 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1376 return ret
&& parse_end_element(xmlbuf
);
1379 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1380 struct assembly_identity
* ai
)
1382 xmlstr_t attr_name
, attr_value
;
1383 BOOL end
= FALSE
, error
;
1384 UNICODE_STRING attr_valueU
, attr_nameU
;
1386 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1388 if (xmlstr_cmp(&attr_name
, g_nameW
))
1390 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1392 else if (xmlstr_cmp(&attr_name
, typeW
))
1394 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1396 else if (xmlstr_cmp(&attr_name
, versionW
))
1398 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1400 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1402 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1404 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1406 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1408 else if (xmlstr_cmp(&attr_name
, languageW
))
1410 DPRINT1("Unsupported yet language attribute (%.*S)\n",
1411 attr_value
.len
, attr_value
.ptr
);
1412 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1416 attr_nameU
= xmlstr2unicode(&attr_name
);
1417 attr_valueU
= xmlstr2unicode(&attr_value
);
1418 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1422 if (error
|| end
) return end
;
1423 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1426 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1428 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1429 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1430 static const WCHAR freeW
[] = {'F','r','e','e',0};
1431 static const WCHAR bothW
[] = {'B','o','t','h',0};
1433 if (value
->len
== 0) return ThreadingModel_No
;
1434 if (xmlstr_cmp(value
, apartW
))
1435 return ThreadingModel_Apartment
;
1436 else if (xmlstr_cmp(value
, freeW
))
1437 return ThreadingModel_Free
;
1438 else if (xmlstr_cmp(value
, bothW
))
1439 return ThreadingModel_Both
;
1440 else if (xmlstr_cmp(value
, neutralW
))
1441 return ThreadingModel_Neutral
;
1443 return ThreadingModel_No
;
1446 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1451 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1459 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1460 if (!c
&& !olemisc_values
[n
].name
[len
])
1461 return olemisc_values
[n
].value
;
1469 DPRINT1("unknown flag %S\n", str
);
1473 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1475 const WCHAR
*str
= value
->ptr
, *start
;
1479 /* it's comma separated list of flags */
1480 while (i
< value
->len
)
1483 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1485 flags
|= get_olemisc_value(start
, str
-start
);
1487 /* skip separator */
1495 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1497 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1499 if (progids
->allocated
== 0)
1501 progids
->allocated
= 4;
1502 if (!(progids
->progids
= RtlAllocateHeap(RtlGetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1505 if (progids
->allocated
== progids
->num
)
1507 progids
->allocated
*= 2;
1508 progids
->progids
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids
->progids
, progids
->allocated
* sizeof(WCHAR
*));
1511 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1517 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1522 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1525 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1526 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1529 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1531 xmlstr_t elem
, attr_name
, attr_value
;
1532 BOOL ret
= TRUE
, end
= FALSE
, error
;
1533 struct entity
* entity
;
1534 UNICODE_STRING attr_valueU
, attr_nameU
;
1536 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1539 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1541 if (xmlstr_cmp(&attr_name
, clsidW
))
1543 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1545 else if (xmlstr_cmp(&attr_name
, progidW
))
1547 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1549 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1551 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1553 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1555 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1557 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1559 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1561 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1563 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1565 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1567 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1569 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1571 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1573 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1575 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1577 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1583 attr_nameU
= xmlstr2unicode(&attr_name
);
1584 attr_valueU
= xmlstr2unicode(&attr_value
);
1585 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1589 if (error
) return FALSE
;
1591 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1592 if (entity
->u
.comclass
.progid
)
1593 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1595 if (end
) return TRUE
;
1597 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1599 if (xmlstr_cmp_end(&elem
, comClassW
))
1601 ret
= parse_end_element(xmlbuf
);
1604 else if (xmlstr_cmp(&elem
, progidW
))
1606 ret
= parse_com_class_progid(xmlbuf
, entity
);
1610 attr_nameU
= xmlstr2unicode(&elem
);
1611 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
1612 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1616 if (entity
->u
.comclass
.progids
.num
)
1617 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1622 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1627 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1629 if (*curr
>= '0' && *curr
<= '9')
1630 num
= num
* 10 + *curr
- '0';
1633 UNICODE_STRING strU
= xmlstr2unicode(str
);
1634 DPRINT1("wrong numeric value %wZ\n", &strU
);
1638 entity
->u
.ifaceps
.nummethods
= num
;
1643 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1645 xmlstr_t attr_name
, attr_value
;
1646 BOOL end
= FALSE
, error
;
1647 struct entity
* entity
;
1648 UNICODE_STRING attr_valueU
, attr_nameU
;
1650 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1653 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1655 if (xmlstr_cmp(&attr_name
, iidW
))
1657 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1659 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1661 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1663 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1665 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1666 entity
->u
.ifaceps
.mask
|= BaseIface
;
1668 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1670 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1671 entity
->u
.ifaceps
.mask
|= NumMethods
;
1673 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1675 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1678 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1683 attr_nameU
= xmlstr2unicode(&attr_name
);
1684 attr_valueU
= xmlstr2unicode(&attr_value
);
1685 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1689 if (error
) return FALSE
;
1690 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1691 if (end
) return TRUE
;
1693 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1696 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1698 WORD
*flags
= &entity
->u
.typelib
.flags
;
1699 const WCHAR
*str
= value
->ptr
, *start
;
1704 /* it's comma separated list of flags */
1705 while (i
< value
->len
)
1708 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1710 if (!strncmpiW(start
, restrictedW
, str
-start
))
1711 *flags
|= LIBFLAG_FRESTRICTED
;
1712 else if (!strncmpiW(start
, controlW
, str
-start
))
1713 *flags
|= LIBFLAG_FCONTROL
;
1714 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1715 *flags
|= LIBFLAG_FHIDDEN
;
1716 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1717 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1720 UNICODE_STRING valueU
= xmlstr2unicode(value
);
1721 DPRINT1("unknown flags value %wZ\n", &valueU
);
1725 /* skip separator */
1733 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1735 unsigned int ver
[2];
1738 UNICODE_STRING strW
;
1741 ver
[0] = ver
[1] = pos
= 0;
1742 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1744 if (*curr
>= '0' && *curr
<= '9')
1746 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1747 if (ver
[pos
] >= 0x10000) goto error
;
1749 else if (*curr
== '.')
1751 if (++pos
>= 2) goto error
;
1755 entity
->u
.typelib
.major
= ver
[0];
1756 entity
->u
.typelib
.minor
= ver
[1];
1760 strW
= xmlstr2unicode(str
);
1761 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW
);
1765 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1767 xmlstr_t attr_name
, attr_value
;
1768 BOOL end
= FALSE
, error
;
1769 struct entity
* entity
;
1770 UNICODE_STRING attr_valueU
, attr_nameU
;
1772 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1775 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1777 if (xmlstr_cmp(&attr_name
, tlbidW
))
1779 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1781 else if (xmlstr_cmp(&attr_name
, versionW
))
1783 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1785 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1787 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1789 else if (xmlstr_cmp(&attr_name
, flagsW
))
1791 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1795 attr_nameU
= xmlstr2unicode(&attr_name
);
1796 attr_valueU
= xmlstr2unicode(&attr_value
);
1797 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1801 if (error
) return FALSE
;
1803 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1805 if (end
) return TRUE
;
1807 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1810 static inline int aligned_string_len(int len
)
1812 return (len
+ 3) & ~3;
1815 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1817 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1818 struct assembly_version
*ver
= &assembly
->id
.version
;
1821 if (!ret
) ret
= buff
;
1822 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1825 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1827 xmlstr_t elem
, content
, attr_name
, attr_value
;
1828 BOOL end
= FALSE
, ret
= TRUE
, error
;
1829 struct entity
* entity
;
1830 UNICODE_STRING elemU
, attr_nameU
, attr_valueU
;
1832 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1835 entity
->u
.class.versioned
= TRUE
;
1836 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1838 if (xmlstr_cmp(&attr_name
, versionedW
))
1840 if (xmlstr_cmpi(&attr_value
, noW
))
1841 entity
->u
.class.versioned
= FALSE
;
1842 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1847 attr_nameU
= xmlstr2unicode(&attr_name
);
1848 attr_valueU
= xmlstr2unicode(&attr_value
);
1849 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1853 if (error
|| end
) return end
;
1855 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1857 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1859 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1861 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1863 if (xmlstr_cmp_end(&elem
, windowClassW
))
1865 ret
= parse_end_element(xmlbuf
);
1870 elemU
= xmlstr2unicode(&elem
);
1871 DPRINT1("unknown elem %wZ\n", &elemU
);
1872 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1879 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1881 xmlstr_t attr_name
, attr_value
;
1882 UNICODE_STRING attr_valueU
, attr_nameU
;
1883 BOOL end
= FALSE
, error
;
1885 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1887 attr_nameU
= xmlstr2unicode(&attr_name
);
1888 attr_valueU
= xmlstr2unicode(&attr_value
);
1890 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1892 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU
);
1894 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1896 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU
);
1900 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1904 if (error
|| end
) return end
;
1905 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1908 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1910 xmlstr_t elem
, content
, attr_name
, attr_value
;
1911 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1913 UNICODE_STRING elem1U
, elem2U
;
1915 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1917 elem1U
= xmlstr2unicode(&attr_name
);
1918 elem2U
= xmlstr2unicode(&attr_value
);
1919 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
1922 if (error
) return FALSE
;
1923 if (end
) return TRUE
;
1925 if (!parse_text_content(xmlbuf
, &content
))
1928 elem1U
= xmlstr2unicode(&content
);
1929 DPRINT("Got description %wZ\n", &elem1U
);
1931 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1933 if (xmlstr_cmp_end(&elem
, descriptionW
))
1935 ret
= parse_end_element(xmlbuf
);
1940 elem1U
= xmlstr2unicode(&elem
);
1941 DPRINT1("unknown elem %wZ\n", &elem1U
);
1942 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1949 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1950 struct assembly
* assembly
,
1951 struct actctx_loader
* acl
)
1953 xmlstr_t attr_name
, attr_value
;
1954 UNICODE_STRING attr_nameU
, attr_valueU
;
1955 BOOL end
= FALSE
, error
;
1956 struct entity
* entity
;
1958 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1959 if (!entity
) return FALSE
;
1961 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1963 if (xmlstr_cmp(&attr_name
, iidW
))
1965 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1967 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1969 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1971 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1973 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1974 entity
->u
.ifaceps
.mask
|= BaseIface
;
1976 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1978 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1979 entity
->u
.ifaceps
.mask
|= NumMethods
;
1981 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1983 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1985 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1987 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1991 attr_nameU
= xmlstr2unicode(&attr_name
);
1992 attr_valueU
= xmlstr2unicode(&attr_value
);
1993 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1997 if (error
) return FALSE
;
1998 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1999 if (end
) return TRUE
;
2001 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
2004 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2006 xmlstr_t attr_name
, attr_value
, elem
;
2007 BOOL end
= FALSE
, error
, ret
= TRUE
;
2008 struct entity
* entity
;
2010 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
2011 if (!entity
) return FALSE
;
2013 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2015 if (xmlstr_cmp(&attr_name
, g_nameW
))
2017 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2019 else if (xmlstr_cmp(&attr_name
, clsidW
))
2021 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2023 else if (xmlstr_cmp(&attr_name
, progidW
))
2025 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
2027 else if (xmlstr_cmp(&attr_name
, tlbidW
))
2029 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
2031 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
2033 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
2035 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2037 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2041 UNICODE_STRING attr_nameU
, attr_valueU
;
2042 attr_nameU
= xmlstr2unicode(&attr_name
);
2043 attr_valueU
= xmlstr2unicode(&attr_value
);
2044 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2048 if (error
) return FALSE
;
2049 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2050 if (entity
->u
.comclass
.progid
)
2051 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2052 if (end
) return TRUE
;
2054 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2056 if (xmlstr_cmp_end(&elem
, clrClassW
))
2058 ret
= parse_end_element(xmlbuf
);
2061 else if (xmlstr_cmp(&elem
, progidW
))
2063 ret
= parse_com_class_progid(xmlbuf
, entity
);
2067 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2068 DPRINT1("unknown elem %wZ\n", &elemU
);
2069 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2073 if (entity
->u
.comclass
.progids
.num
)
2074 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2079 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2081 xmlstr_t attr_name
, attr_value
;
2082 UNICODE_STRING attr_nameU
, attr_valueU
;
2083 BOOL end
= FALSE
, error
;
2084 struct entity
* entity
;
2086 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
2087 if (!entity
) return FALSE
;
2089 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2091 if (xmlstr_cmp(&attr_name
, g_nameW
))
2093 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2095 else if (xmlstr_cmp(&attr_name
, clsidW
))
2097 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2099 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2101 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2105 attr_nameU
= xmlstr2unicode(&attr_name
);
2106 attr_valueU
= xmlstr2unicode(&attr_value
);
2107 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2111 if (error
) return FALSE
;
2112 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2113 if (end
) return TRUE
;
2115 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2118 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2120 struct assembly_identity ai
;
2121 xmlstr_t elem
, attr_name
, attr_value
;
2122 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2124 UNICODE_STRING elem1U
, elem2U
;
2126 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2128 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2129 static const WCHAR trueW
[] = {'t','r','u','e',0};
2131 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2132 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2135 elem1U
= xmlstr2unicode(&attr_name
);
2136 elem2U
= xmlstr2unicode(&attr_value
);
2137 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
2141 if (error
|| end
) return end
;
2143 memset(&ai
, 0, sizeof(ai
));
2144 ai
.optional
= optional
;
2145 ai
.delayed
= delayed
;
2147 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2148 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2151 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2153 /* store the newly found identity for later loading */
2154 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2156 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2158 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2160 ret
= parse_end_element(xmlbuf
);
2163 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2165 ret
= parse_binding_redirect_elem(xmlbuf
);
2169 DPRINT1("unknown elem %S\n", elem
.ptr
);
2170 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2177 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2179 xmlstr_t attr_name
, attr_value
, elem
;
2180 UNICODE_STRING attr_nameU
, attr_valueU
;
2181 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2183 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2185 attr_nameU
= xmlstr2unicode(&attr_name
);
2186 attr_valueU
= xmlstr2unicode(&attr_value
);
2188 if (xmlstr_cmp(&attr_name
, optionalW
))
2190 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2191 DPRINT1("optional=%wZ\n", &attr_valueU
);
2195 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2199 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2201 if (xmlstr_cmp_end(&elem
, dependencyW
))
2203 ret
= parse_end_element(xmlbuf
);
2206 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2208 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2212 attr_nameU
= xmlstr2unicode(&elem
);
2213 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2214 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2221 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2225 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2226 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2229 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2233 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2234 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2237 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2239 xmlstr_t attr_name
, attr_value
, elem
;
2240 UNICODE_STRING attr_nameU
, attr_valueU
;
2241 BOOL end
= FALSE
, error
, ret
= TRUE
;
2242 struct dll_redirect
* dll
;
2244 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2246 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2248 attr_nameU
= xmlstr2unicode(&attr_name
);
2249 attr_valueU
= xmlstr2unicode(&attr_value
);
2251 if (xmlstr_cmp(&attr_name
, g_nameW
))
2253 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2254 DPRINT("name=%wZ\n", &attr_valueU
);
2256 else if (xmlstr_cmp(&attr_name
, hashW
))
2258 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2260 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2262 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2263 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2264 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU
);
2268 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2272 if (error
|| !dll
->name
) return FALSE
;
2274 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2276 if (end
) return TRUE
;
2278 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2280 if (xmlstr_cmp_end(&elem
, fileW
))
2282 ret
= parse_end_element(xmlbuf
);
2285 else if (xmlstr_cmp(&elem
, comClassW
))
2287 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2289 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2291 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2293 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2295 DPRINT1("asmv2hash (undocumented) not supported\n");
2296 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2298 else if (xmlstr_cmp(&elem
, typelibW
))
2300 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2302 else if (xmlstr_cmp(&elem
, windowClassW
))
2304 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2308 attr_nameU
= xmlstr2unicode(&elem
);
2309 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
2310 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2317 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2318 struct assembly
* assembly
,
2319 struct assembly_identity
* expected_ai
)
2321 xmlstr_t attr_name
, attr_value
, elem
;
2322 UNICODE_STRING attr_nameU
, attr_valueU
;
2323 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2325 DPRINT("(%p)\n", xmlbuf
);
2327 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2329 attr_nameU
= xmlstr2unicode(&attr_name
);
2330 attr_valueU
= xmlstr2unicode(&attr_value
);
2332 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2334 static const WCHAR v10W
[] = {'1','.','0',0};
2335 if (!xmlstr_cmp(&attr_value
, v10W
))
2337 DPRINT1("wrong version %wZ\n", &attr_valueU
);
2342 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2344 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2345 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2346 !xmlstr_cmp(&attr_value
, manifestv3W
))
2348 DPRINT1("wrong namespace %wZ\n", &attr_valueU
);
2355 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2359 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2360 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2362 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2364 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2366 assembly
->no_inherit
= TRUE
;
2369 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2371 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2374 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2375 assembly
->no_inherit
)
2380 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2382 ret
= parse_end_element(xmlbuf
);
2385 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2387 ret
= parse_description_elem(xmlbuf
);
2389 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2391 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2393 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2395 ret
= parse_dependency_elem(xmlbuf
, acl
);
2397 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2399 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2401 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2403 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2405 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2407 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2409 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2411 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2415 /* FIXME: more tests */
2416 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2417 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2419 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2420 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2421 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2422 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2423 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2426 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2427 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2428 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2429 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2430 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2431 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2433 DPRINT1("wrong version for shared assembly manifest\n");
2440 attr_nameU
= xmlstr2unicode(&elem
);
2441 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2442 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2444 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2450 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2451 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2454 UNICODE_STRING elemU
;
2456 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2458 if (xmlstr_cmp(&elem
, g_xmlW
) &&
2459 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2460 return STATUS_SXS_CANT_GEN_ACTCTX
;
2462 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2464 elemU
= xmlstr2unicode(&elem
);
2465 DPRINT1("root element is %wZ, not <assembly>\n", &elemU
);
2466 return STATUS_SXS_CANT_GEN_ACTCTX
;
2469 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2471 DPRINT1("failed to parse manifest %S\n", assembly
->manifest
.info
);
2472 return STATUS_SXS_CANT_GEN_ACTCTX
;
2475 if (next_xml_elem(xmlbuf
, &elem
))
2477 elemU
= xmlstr2unicode(&elem
);
2478 DPRINT1("unexpected element %wZ\n", &elemU
);
2479 return STATUS_SXS_CANT_GEN_ACTCTX
;
2482 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2484 DPRINT1("parse error\n");
2485 return STATUS_SXS_CANT_GEN_ACTCTX
;
2487 return STATUS_SUCCESS
;
2490 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2491 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2492 const void *buffer
, SIZE_T size
)
2496 struct assembly
*assembly
;
2499 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename
, directory
);
2501 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2502 return STATUS_SXS_CANT_GEN_ACTCTX
;
2504 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2505 return STATUS_NO_MEMORY
;
2507 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2508 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2509 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2511 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2512 if (RtlIsTextUnicode((PVOID
)buffer
, (ULONG
)size
, &unicode_tests
))
2514 xmlbuf
.ptr
= buffer
;
2515 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2516 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2518 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2520 const WCHAR
*buf
= buffer
;
2524 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
2525 return STATUS_NO_MEMORY
;
2526 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2527 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2528 xmlbuf
.ptr
= new_buff
;
2529 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2530 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2531 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
2535 /* TODO: this doesn't handle arbitrary encodings */
2539 status
= RtlMultiByteToUnicodeSize(&sizeU
, buffer
, size
);
2540 if (!NT_SUCCESS(status
))
2542 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status
);
2543 return STATUS_SXS_CANT_GEN_ACTCTX
;
2546 new_buff
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU
);
2548 return STATUS_NO_MEMORY
;
2550 status
= RtlMultiByteToUnicodeN(new_buff
, sizeU
, &sizeU
, buffer
, size
);
2551 if (!NT_SUCCESS(status
))
2553 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status
);
2554 return STATUS_SXS_CANT_GEN_ACTCTX
;
2557 xmlbuf
.ptr
= new_buff
;
2558 xmlbuf
.end
= xmlbuf
.ptr
+ sizeU
/ sizeof(WCHAR
);
2559 status
= parse_manifest_buffer(acl
, assembly
, ai
, &xmlbuf
);
2560 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff
);
2565 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2567 OBJECT_ATTRIBUTES attr
;
2570 attr
.Length
= sizeof(attr
);
2571 attr
.RootDirectory
= 0;
2572 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2573 attr
.ObjectName
= name
;
2574 attr
.SecurityDescriptor
= NULL
;
2575 attr
.SecurityQualityOfService
= NULL
;
2576 return NtOpenFile(handle
,
2577 GENERIC_READ
| SYNCHRONIZE
,
2580 FILE_SYNCHRONOUS_IO_ALERT
);
2583 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2587 LDR_DATA_TABLE_ENTRY
*pldr
;
2589 LdrLockLoaderLock(0, NULL
, &magic
);
2590 status
= LdrFindEntryForAddress( module
, &pldr
);
2591 if (status
== STATUS_SUCCESS
)
2593 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2594 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2596 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2597 str
->Length
= pldr
->FullDllName
.Length
;
2598 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2600 else status
= STATUS_NO_MEMORY
;
2602 LdrUnlockLoaderLock(0, magic
);
2606 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2607 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2608 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2611 UNICODE_STRING nameW
;
2612 LDR_RESOURCE_INFO info
;
2613 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2616 //DPRINT( "looking for res %s in module %p %s\n", resname,
2617 // hModule, filename );
2618 DPRINT("get_manifest_in_module %p\n", hModule
);
2621 if (TRACE_ON(actctx
))
2623 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2625 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2626 hModule
, debugstr_w(nameW
.Buffer
) );
2627 RtlFreeUnicodeString( &nameW
);
2629 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2630 hModule
, debugstr_w(filename
) );
2634 if (!resname
) return STATUS_INVALID_PARAMETER
;
2636 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2637 info
.Language
= lang
;
2638 if (!((ULONG_PTR
)resname
>> 16))
2640 info
.Name
= (ULONG_PTR
)resname
;
2641 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2643 else if (resname
[0] == '#')
2646 RtlInitUnicodeString(&nameW
, resname
+ 1);
2647 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2648 return STATUS_INVALID_PARAMETER
;
2650 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2654 RtlCreateUnicodeString(&nameW
, resname
);
2655 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2656 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2657 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2658 RtlFreeUnicodeString(&nameW
);
2660 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2662 if (status
== STATUS_SUCCESS
)
2663 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2668 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2669 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2670 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2673 OBJECT_ATTRIBUTES attr
;
2675 LARGE_INTEGER offset
;
2680 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2682 attr
.Length
= sizeof(attr
);
2683 attr
.RootDirectory
= 0;
2684 attr
.ObjectName
= NULL
;
2685 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2686 attr
.SecurityDescriptor
= NULL
;
2687 attr
.SecurityQualityOfService
= NULL
;
2690 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2691 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2692 if (status
!= STATUS_SUCCESS
) return status
;
2694 offset
.QuadPart
= 0;
2697 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2698 &count
, ViewShare
, 0, PAGE_READONLY
);
2700 if (status
!= STATUS_SUCCESS
) return status
;
2702 if (RtlImageNtHeader(base
)) /* we got a PE file */
2704 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2705 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2707 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2709 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2713 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2714 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2716 FILE_STANDARD_INFORMATION info
;
2719 OBJECT_ATTRIBUTES attr
;
2721 LARGE_INTEGER offset
;
2726 DPRINT( "loading manifest file %S\n", filename
);
2728 attr
.Length
= sizeof(attr
);
2729 attr
.RootDirectory
= 0;
2730 attr
.ObjectName
= NULL
;
2731 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2732 attr
.SecurityDescriptor
= NULL
;
2733 attr
.SecurityQualityOfService
= NULL
;
2736 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2737 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2739 if (status
!= STATUS_SUCCESS
) return status
;
2741 offset
.QuadPart
= 0;
2744 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2745 &count
, ViewShare
, 0, PAGE_READONLY
);
2747 if (status
!= STATUS_SUCCESS
) return status
;
2749 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2750 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
2752 if (status
== STATUS_SUCCESS
)
2753 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
2755 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2759 /* try to load the .manifest file associated to the file */
2760 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2761 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2763 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2766 UNICODE_STRING nameW
;
2768 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2770 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2772 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
2774 if (module
) /* use the module filename */
2776 UNICODE_STRING name
;
2778 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2780 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2781 strcatW( name
.Buffer
, dotManifestW
);
2782 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2783 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2784 RtlFreeUnicodeString( &name
);
2786 if (status
) return status
;
2790 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2791 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2792 return STATUS_NO_MEMORY
;
2793 strcpyW( buffer
, filename
);
2794 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2795 strcatW( buffer
, dotManifestW
);
2796 RtlInitUnicodeString( &nameW
, buffer
);
2799 if (!open_nt_file( &file
, &nameW
))
2801 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2804 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2805 RtlFreeUnicodeString( &nameW
);
2809 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2811 static const WCHAR lookup_fmtW
[] =
2812 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2813 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2814 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2816 WCHAR
*lookup
, *ret
= NULL
;
2817 UNICODE_STRING lookup_us
;
2819 const WCHAR
*lang
= ai
->language
;
2820 unsigned int data_pos
= 0, data_len
;
2823 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2824 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2825 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2826 + sizeof(lookup_fmtW
) )))
2829 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2830 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2831 ai
->version
.major
, ai
->version
.minor
, lang
);
2832 RtlInitUnicodeString( &lookup_us
, lookup
);
2834 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2835 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2836 if (io
.Status
== STATUS_SUCCESS
)
2838 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2839 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2841 ULONG build
, revision
;
2843 data_len
= (ULONG
)io
.Information
;
2847 if (data_pos
>= data_len
)
2849 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2850 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2851 if (io
.Status
!= STATUS_SUCCESS
) break;
2852 data_len
= (ULONG
)io
.Information
;
2855 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2857 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2858 else data_pos
= data_len
;
2860 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2862 if (build
< min_build
) continue;
2863 tmp
= strchrW(tmp
, '.') + 1;
2864 revision
= atoiW(tmp
);
2865 if (build
== min_build
&& revision
< min_revision
) continue;
2866 tmp
= strchrW(tmp
, '_') + 1;
2867 tmp
= strchrW(tmp
, '_') + 1;
2868 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2869 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2871 /* prefer a non-Wine manifest if we already have one */
2872 /* we'll still load the builtin dll if specified through DllOverrides */
2878 min_revision
= revision
;
2880 ai
->version
.build
= build
;
2881 ai
->version
.revision
= revision
;
2882 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
2883 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2885 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2886 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2890 else DPRINT1("no matching file for %S\n", lookup
);
2891 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
2895 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2897 struct assembly_identity sxs_ai
;
2898 UNICODE_STRING path_us
;
2899 OBJECT_ATTRIBUTES attr
;
2901 WCHAR
*path
, *file
= NULL
;
2904 static const WCHAR manifest_dirW
[] =
2905 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2907 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2909 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2910 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
2911 return STATUS_NO_MEMORY
;
2913 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
2914 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
2916 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2918 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2919 return STATUS_NO_SUCH_FILE
;
2921 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2923 attr
.Length
= sizeof(attr
);
2924 attr
.RootDirectory
= 0;
2925 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2926 attr
.ObjectName
= &path_us
;
2927 attr
.SecurityDescriptor
= NULL
;
2928 attr
.SecurityQualityOfService
= NULL
;
2930 if (!NtOpenFile(&handle
,
2931 GENERIC_READ
| SYNCHRONIZE
,
2933 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2934 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2937 file
= lookup_manifest_file( handle
, &sxs_ai
);
2942 RtlFreeUnicodeString( &path_us
);
2943 return STATUS_NO_SUCH_FILE
;
2946 /* append file name to directory path */
2947 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
2948 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2950 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2951 RtlFreeUnicodeString( &path_us
);
2952 return STATUS_NO_MEMORY
;
2955 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2956 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2957 RtlInitUnicodeString( &path_us
, path
);
2958 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2960 if (!open_nt_file( &handle
, &path_us
))
2962 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2965 else io
.Status
= STATUS_NO_SUCH_FILE
;
2967 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2968 RtlFreeUnicodeString( &path_us
);
2972 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2973 struct assembly_identity
* ai
)
2975 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2977 WCHAR
*buffer
, *p
, *directory
;
2979 UNICODE_STRING nameW
;
2983 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2984 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
2986 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2988 /* FIXME: add support for language specific lookup */
2990 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2991 strlenW(acl
->actctx
->appdir
.info
));
2993 nameW
.Buffer
= NULL
;
2994 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2995 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2996 return STATUS_NO_MEMORY
;
2998 if (!(directory
= build_assembly_dir( ai
)))
3000 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3001 return STATUS_NO_MEMORY
;
3004 /* Lookup in <dir>\name.dll
3005 * <dir>\name.manifest
3006 * <dir>\name\name.dll
3007 * <dir>\name\name.manifest
3009 * First 'appdir' is used as <dir>, if that failed
3010 * it tries application manifest file path.
3012 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3013 p
= buffer
+ strlenW(buffer
);
3014 for (i
= 0; i
< 4; i
++)
3018 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3019 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3023 strcpyW( p
, ai
->name
);
3026 strcpyW( p
, dotDllW
);
3027 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3029 status
= open_nt_file( &file
, &nameW
);
3032 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3033 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3037 RtlFreeUnicodeString( &nameW
);
3040 strcpyW( p
, dotManifestW
);
3041 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3043 status
= open_nt_file( &file
, &nameW
);
3046 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3050 RtlFreeUnicodeString( &nameW
);
3052 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3054 RtlFreeUnicodeString( &nameW
);
3055 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3056 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3060 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3062 NTSTATUS status
= STATUS_SUCCESS
;
3065 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3067 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3069 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3071 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3072 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3073 acl
->dependencies
[i
].name
,
3074 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3075 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3080 /* FIXME should now iterate through all refs */
3084 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3085 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3087 NTSTATUS status
= STATUS_SUCCESS
;
3089 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3091 if (*handle
) return STATUS_INVALID_PARAMETER
;
3093 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3094 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3096 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3099 LDR_DATA_TABLE_ENTRY
*pldr
;
3101 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3103 LdrLockLoaderLock( 0, NULL
, &magic
);
3104 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3106 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3107 status
= STATUS_DLL_NOT_FOUND
;
3109 *handle
= pldr
->EntryPointActivationContext
;
3111 else status
= STATUS_DLL_NOT_FOUND
;
3112 LdrUnlockLoaderLock( 0, magic
);
3114 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3115 *handle
= process_actctx
;
3120 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3122 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3123 struct strsection_header
*header
;
3124 struct dllredirect_data
*data
;
3125 struct string_index
*index
;
3128 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3130 /* compute section length */
3131 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3133 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3134 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3136 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3138 /* each entry needs index, data and string data */
3139 total_len
+= sizeof(*index
);
3140 total_len
+= sizeof(*data
);
3141 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3143 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3146 dll_count
+= assembly
->num_dlls
;
3149 total_len
+= sizeof(*header
);
3151 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3152 if (!header
) return STATUS_NO_MEMORY
;
3154 memset(header
, 0, sizeof(*header
));
3155 header
->magic
= STRSECTION_MAGIC
;
3156 header
->size
= sizeof(*header
);
3157 header
->count
= dll_count
;
3158 header
->index_offset
= sizeof(*header
);
3159 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3160 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3162 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3164 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3166 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3168 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3170 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3174 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3175 /* setup new index entry */
3176 str
.Buffer
= dll
->name
;
3177 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3178 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3179 /* hash original class name */
3180 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3182 index
->name_offset
= name_offset
;
3183 index
->name_len
= str
.Length
;
3184 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3185 index
->data_len
= sizeof(*data
);
3186 index
->rosterindex
= i
+ 1;
3189 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3190 data
->size
= sizeof(*data
);
3191 data
->unk
= 2; /* FIXME: seems to be constant */
3192 memset(data
->res
, 0, sizeof(data
->res
));
3195 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3196 memcpy(ptrW
, dll
->name
, index
->name_len
);
3197 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3199 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3207 return STATUS_SUCCESS
;
3210 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3212 struct string_index
*iter
, *index
= NULL
;
3215 DPRINT("section %p, name %wZ\n", section
, name
);
3216 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3217 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3219 for (i
= 0; i
< section
->count
; i
++)
3221 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3222 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3223 if (iter
->hash
== hash
)
3225 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3227 if (!strcmpiW(nameW
, name
->Buffer
))
3233 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3241 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3243 struct guid_index
*iter
, *index
= NULL
;
3246 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3248 for (i
= 0; i
< section
->count
; i
++)
3250 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3261 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3263 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3266 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3267 PACTCTX_SECTION_KEYED_DATA data
)
3269 struct dllredirect_data
*dll
;
3270 struct string_index
*index
;
3272 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3273 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3275 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3276 if (!actctx
->dllredirect_section
)
3278 struct strsection_header
*section
;
3280 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3281 if (status
) return status
;
3283 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3284 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3287 index
= find_string_index(actctx
->dllredirect_section
, name
);
3288 DPRINT("index: %d\n", index
);
3289 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3293 dll
= get_dllredirect_data(actctx
, index
);
3295 data
->ulDataFormatVersion
= 1;
3297 data
->ulLength
= dll
->size
;
3298 data
->lpSectionGlobalData
= NULL
;
3299 data
->ulSectionGlobalDataLength
= 0;
3300 data
->lpSectionBase
= actctx
->dllredirect_section
;
3301 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3302 data
->hActCtx
= NULL
;
3304 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3305 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3308 return STATUS_SUCCESS
;
3311 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3313 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3316 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3318 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3321 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3323 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3324 struct wndclass_redirect_data
*data
;
3325 struct strsection_header
*header
;
3326 struct string_index
*index
;
3329 /* compute section length */
3330 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3332 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3333 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3335 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3336 for (k
= 0; k
< dll
->entities
.num
; k
++)
3338 struct entity
*entity
= &dll
->entities
.base
[k
];
3339 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3341 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3344 /* each class entry needs index, data and string data */
3345 total_len
+= sizeof(*index
);
3346 total_len
+= sizeof(*data
);
3347 /* original name is stored separately */
3348 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3349 /* versioned name and module name are stored one after another */
3350 if (entity
->u
.class.versioned
)
3351 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3354 len
+= strlenW(dll
->name
) + 1;
3355 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3363 total_len
+= sizeof(*header
);
3365 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3366 if (!header
) return STATUS_NO_MEMORY
;
3368 memset(header
, 0, sizeof(*header
));
3369 header
->magic
= STRSECTION_MAGIC
;
3370 header
->size
= sizeof(*header
);
3371 header
->count
= class_count
;
3372 header
->index_offset
= sizeof(*header
);
3373 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3374 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3376 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3378 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3379 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3381 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3382 for (k
= 0; k
< dll
->entities
.num
; k
++)
3384 struct entity
*entity
= &dll
->entities
.base
[k
];
3385 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3387 static const WCHAR exclW
[] = {'!',0};
3388 ULONG versioned_len
, module_len
;
3392 /* setup new index entry */
3393 str
.Buffer
= entity
->u
.class.name
;
3394 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3395 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3396 /* hash original class name */
3397 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3399 /* include '!' separator too */
3400 if (entity
->u
.class.versioned
)
3401 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3403 versioned_len
= str
.Length
;
3404 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3406 index
->name_offset
= name_offset
;
3407 index
->name_len
= str
.Length
;
3408 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3409 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3410 index
->rosterindex
= i
+ 1;
3413 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3414 data
->size
= sizeof(*data
);
3416 data
->name_len
= versioned_len
;
3417 data
->name_offset
= sizeof(*data
);
3418 data
->module_len
= module_len
;
3419 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3421 /* original class name */
3422 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3423 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3424 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3427 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3428 memcpy(ptrW
, dll
->name
, data
->module_len
);
3429 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3431 /* versioned name */
3432 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3433 if (entity
->u
.class.versioned
)
3435 get_assembly_version(assembly
, ptrW
);
3436 strcatW(ptrW
, exclW
);
3437 strcatW(ptrW
, entity
->u
.class.name
);
3441 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3442 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3445 name_offset
+= sizeof(*data
);
3446 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3456 return STATUS_SUCCESS
;
3459 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3460 PACTCTX_SECTION_KEYED_DATA data
)
3462 struct string_index
*iter
, *index
= NULL
;
3463 struct wndclass_redirect_data
*class;
3467 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3469 if (!actctx
->wndclass_section
)
3471 struct strsection_header
*section
;
3473 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3474 if (status
) return status
;
3476 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3477 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3481 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3482 iter
= get_wndclass_first_index(actctx
);
3484 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3486 if (iter
->hash
== hash
)
3488 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3490 if (!strcmpiW(nameW
, name
->Buffer
))
3496 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3501 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3505 class = get_wndclass_data(actctx
, index
);
3507 data
->ulDataFormatVersion
= 1;
3508 data
->lpData
= class;
3509 /* full length includes string length with nulls */
3510 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3511 data
->lpSectionGlobalData
= NULL
;
3512 data
->ulSectionGlobalDataLength
= 0;
3513 data
->lpSectionBase
= actctx
->wndclass_section
;
3514 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3515 data
->hActCtx
= NULL
;
3517 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3518 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3521 return STATUS_SUCCESS
;
3524 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3526 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3527 struct guidsection_header
*header
;
3528 ULONG module_offset
, data_offset
;
3529 struct tlibredirect_data
*data
;
3530 struct guid_index
*index
;
3532 /* compute section length */
3533 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3535 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3536 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3538 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3539 for (k
= 0; k
< dll
->entities
.num
; k
++)
3541 struct entity
*entity
= &dll
->entities
.base
[k
];
3542 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3544 /* each entry needs index, data and string data for module name and help string */
3545 total_len
+= sizeof(*index
);
3546 total_len
+= sizeof(*data
);
3547 /* help string is stored separately */
3548 if (*entity
->u
.typelib
.helpdir
)
3549 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3551 /* module names are packed one after another */
3552 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3560 total_len
+= aligned_string_len(names_len
);
3561 total_len
+= sizeof(*header
);
3563 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3564 if (!header
) return STATUS_NO_MEMORY
;
3566 memset(header
, 0, sizeof(*header
));
3567 header
->magic
= GUIDSECTION_MAGIC
;
3568 header
->size
= sizeof(*header
);
3569 header
->count
= tlib_count
;
3570 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3571 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3572 module_offset
= sizeof(*header
);
3573 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3575 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3577 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3578 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3580 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3581 for (k
= 0; k
< dll
->entities
.num
; k
++)
3583 struct entity
*entity
= &dll
->entities
.base
[k
];
3584 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3586 ULONG module_len
, help_len
;
3590 if (*entity
->u
.typelib
.helpdir
)
3591 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3595 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3597 /* setup new index entry */
3598 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3599 RtlGUIDFromString(&str
, &index
->guid
);
3600 index
->data_offset
= data_offset
;
3601 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3602 index
->rosterindex
= i
+ 1;
3605 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3606 data
->size
= sizeof(*data
);
3608 data
->name_len
= module_len
;
3609 data
->name_offset
= module_offset
;
3610 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3612 data
->flags
= entity
->u
.typelib
.flags
;
3613 data
->help_len
= help_len
;
3614 data
->help_offset
= sizeof(*data
);
3615 data
->major_version
= entity
->u
.typelib
.major
;
3616 data
->minor_version
= entity
->u
.typelib
.minor
;
3619 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3620 memcpy(ptrW
, dll
->name
, data
->name_len
);
3621 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3626 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3627 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3628 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3631 data_offset
+= sizeof(*data
);
3633 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3635 module_offset
+= module_len
+ sizeof(WCHAR
);
3645 return STATUS_SUCCESS
;
3648 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3650 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3653 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3655 struct guid_index
*index
= NULL
;
3656 struct tlibredirect_data
*tlib
;
3658 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3660 if (!actctx
->tlib_section
)
3662 struct guidsection_header
*section
;
3664 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3665 if (status
) return status
;
3667 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3668 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3671 index
= find_guid_index(actctx
->tlib_section
, guid
);
3672 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3674 tlib
= get_tlib_data(actctx
, index
);
3676 data
->ulDataFormatVersion
= 1;
3677 data
->lpData
= tlib
;
3678 /* full length includes string length with nulls */
3679 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3680 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3681 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3682 data
->lpSectionBase
= actctx
->tlib_section
;
3683 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3684 data
->hActCtx
= NULL
;
3686 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3687 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3689 return STATUS_SUCCESS
;
3692 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3694 ULONG
*ptr
= (ULONG
*)guid
;
3697 /* GUID is 16 bytes long */
3698 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3699 *ptr
= RtlUniform(seed
);
3701 guid
->Data3
&= 0x0fff;
3702 guid
->Data3
|= (4 << 12);
3703 guid
->Data4
[0] &= 0x3f;
3704 guid
->Data4
[0] |= 0x80;
3707 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3708 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3712 for (i
= 0; i
< entities
->num
; i
++)
3714 struct entity
*entity
= &entities
->base
[i
];
3715 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3717 /* each entry needs two index entries, extra one goes for alias GUID */
3718 *len
+= 2*sizeof(struct guid_index
);
3719 /* To save some memory we don't allocated two data structures,
3720 instead alias index and normal index point to the same data structure. */
3721 *len
+= sizeof(struct comclassredirect_data
);
3723 /* for clrClass store some more */
3724 if (entity
->u
.comclass
.name
)
3726 unsigned int str_len
;
3728 /* all string data is stored together in aligned block */
3729 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3730 if (entity
->u
.comclass
.progid
)
3731 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3732 if (entity
->u
.comclass
.version
)
3733 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3735 *len
+= sizeof(struct clrclass_data
);
3736 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3738 /* module name is forced to mscoree.dll, and stored two times with different case */
3739 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3743 /* progid string is stored separately */
3744 if (entity
->u
.comclass
.progid
)
3745 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3747 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3755 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3756 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3757 ULONG
*seed
, ULONG rosterindex
)
3761 for (i
= 0; i
< entities
->num
; i
++)
3763 struct entity
*entity
= &entities
->base
[i
];
3764 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3766 ULONG module_len
, progid_len
, str_len
= 0;
3767 struct comclassredirect_data
*data
;
3768 struct guid_index
*alias_index
;
3769 struct clrclass_data
*clrdata
;
3773 if (entity
->u
.comclass
.progid
)
3774 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3778 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3780 /* setup new index entry */
3781 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3782 RtlGUIDFromString(&str
, &(*index
)->guid
);
3784 (*index
)->data_offset
= *data_offset
;
3785 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3786 (*index
)->rosterindex
= rosterindex
;
3788 /* Setup new index entry for alias guid. Alias index records are placed after
3789 normal records, so normal guids are hit first on search. Note that class count
3791 alias_index
= (*index
) + section
->count
/2;
3792 generate_uuid(seed
, &alias_index
->guid
);
3793 alias_index
->data_offset
= (*index
)->data_offset
;
3794 alias_index
->data_len
= 0;
3795 alias_index
->rosterindex
= (*index
)->rosterindex
;
3798 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3799 data
->size
= sizeof(*data
);
3803 data
->model
= entity
->u
.comclass
.model
;
3804 data
->clsid
= (*index
)->guid
;
3805 data
->alias
= alias_index
->guid
;
3806 data
->clsid2
= data
->clsid
;
3807 if (entity
->u
.comclass
.tlbid
)
3809 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3810 RtlGUIDFromString(&str
, &data
->tlbid
);
3813 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3814 data
->name_len
= module_len
;
3815 data
->name_offset
= *module_offset
;
3816 data
->progid_len
= progid_len
;
3817 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3818 data
->clrdata_len
= 0; /* will be set later */
3819 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3820 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3821 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3822 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3823 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3824 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3826 /* mask describes which misc* data is available */
3828 if (data
->miscstatus
)
3829 data
->miscmask
|= MiscStatus
;
3830 if (data
->miscstatuscontent
)
3831 data
->miscmask
|= MiscStatusContent
;
3832 if (data
->miscstatusthumbnail
)
3833 data
->miscmask
|= MiscStatusThumbnail
;
3834 if (data
->miscstatusicon
)
3835 data
->miscmask
|= MiscStatusIcon
;
3836 if (data
->miscstatusdocprint
)
3837 data
->miscmask
|= MiscStatusDocPrint
;
3839 if (data
->clrdata_offset
)
3841 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3843 clrdata
->size
= sizeof(*clrdata
);
3844 clrdata
->res
[0] = 0;
3845 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3846 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3847 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3848 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3849 clrdata
->name_offset
= clrdata
->size
;
3850 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3851 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3852 clrdata
->res2
[0] = 0;
3853 clrdata
->res2
[1] = 0;
3855 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3858 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3859 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3860 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3862 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3863 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3864 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3867 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3868 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3869 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3871 /* runtime version, optional */
3872 if (clrdata
->version_len
)
3874 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3876 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3877 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3878 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3881 if (data
->progid_len
)
3882 data
->progid_offset
+= data
->clrdata_len
;
3883 (*index
)->data_len
+= sizeof(*clrdata
);
3890 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3891 memcpy(ptrW
, dll
->name
, data
->name_len
);
3892 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3896 if (data
->progid_len
)
3898 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3899 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3900 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3903 /* string block length */
3907 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3908 if (clrdata
->version_len
)
3909 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3912 str_len
+= progid_len
+ sizeof(WCHAR
);
3914 (*index
)->data_len
+= aligned_string_len(str_len
);
3915 alias_index
->data_len
= (*index
)->data_len
;
3917 /* move to next data record */
3918 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3919 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3923 (*data_offset
) += sizeof(*clrdata
);
3924 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3931 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3933 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3934 struct guidsection_header
*header
;
3935 ULONG module_offset
, data_offset
;
3936 struct guid_index
*index
;
3939 /* compute section length */
3940 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3942 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3943 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3944 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3946 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3947 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3951 total_len
+= aligned_string_len(names_len
);
3952 total_len
+= sizeof(*header
);
3954 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3955 if (!header
) return STATUS_NO_MEMORY
;
3957 memset(header
, 0, sizeof(*header
));
3958 header
->magic
= GUIDSECTION_MAGIC
;
3959 header
->size
= sizeof(*header
);
3960 header
->count
= 2*class_count
;
3961 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3962 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3963 module_offset
= sizeof(*header
);
3964 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3966 seed
= NtGetTickCount();
3967 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3969 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3970 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3971 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3973 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3974 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3980 return STATUS_SUCCESS
;
3983 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3985 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3988 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3990 struct comclassredirect_data
*comclass
;
3991 struct guid_index
*index
= NULL
;
3993 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3995 if (!actctx
->comserver_section
)
3997 struct guidsection_header
*section
;
3999 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4000 if (status
) return status
;
4002 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4003 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4006 index
= find_guid_index(actctx
->comserver_section
, guid
);
4007 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4009 comclass
= get_comclass_data(actctx
, index
);
4011 data
->ulDataFormatVersion
= 1;
4012 data
->lpData
= comclass
;
4013 /* full length includes string length with nulls */
4014 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4015 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4016 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4017 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4018 data
->lpSectionBase
= actctx
->comserver_section
;
4019 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4020 data
->hActCtx
= NULL
;
4022 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4023 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4025 return STATUS_SUCCESS
;
4028 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4032 for (i
= 0; i
< entities
->num
; i
++)
4034 struct entity
*entity
= &entities
->base
[i
];
4035 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4037 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4038 if (entity
->u
.ifaceps
.name
)
4039 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4045 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4046 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4050 for (i
= 0; i
< entities
->num
; i
++)
4052 struct entity
*entity
= &entities
->base
[i
];
4053 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4055 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4059 if (entity
->u
.ifaceps
.name
)
4060 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4065 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4066 RtlGUIDFromString(&str
, &(*index
)->guid
);
4067 (*index
)->data_offset
= *data_offset
;
4068 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4069 (*index
)->rosterindex
= rosterindex
;
4071 /* setup data record */
4072 data
->size
= sizeof(*data
);
4073 data
->mask
= entity
->u
.ifaceps
.mask
;
4075 /* proxyStubClsid32 value is only stored for external PS,
4076 if set it's used as iid, otherwise 'iid' attribute value is used */
4077 if (entity
->u
.ifaceps
.ps32
)
4079 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4080 RtlGUIDFromString(&str
, &data
->iid
);
4083 data
->iid
= (*index
)->guid
;
4085 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4087 if (entity
->u
.ifaceps
.tlib
)
4089 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4090 RtlGUIDFromString(&str
, &data
->tlbid
);
4093 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4095 if (entity
->u
.ifaceps
.base
)
4097 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4098 RtlGUIDFromString(&str
, &data
->base
);
4101 memset(&data
->base
, 0, sizeof(data
->base
));
4103 data
->name_len
= name_len
;
4104 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4109 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4110 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4111 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4114 /* move to next record */
4116 *data_offset
+= sizeof(*data
);
4118 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4123 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4125 unsigned int i
, j
, total_len
= 0, count
= 0;
4126 struct guidsection_header
*header
;
4127 struct guid_index
*index
;
4130 /* compute section length */
4131 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4133 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4135 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4136 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4138 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4139 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4143 total_len
+= sizeof(*header
);
4145 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4146 if (!header
) return STATUS_NO_MEMORY
;
4148 memset(header
, 0, sizeof(*header
));
4149 header
->magic
= GUIDSECTION_MAGIC
;
4150 header
->size
= sizeof(*header
);
4151 header
->count
= count
;
4152 header
->index_offset
= sizeof(*header
);
4153 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4154 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4156 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4158 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4160 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4161 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4163 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4164 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4170 return STATUS_SUCCESS
;
4173 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4175 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4178 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4180 struct ifacepsredirect_data
*iface
;
4181 struct guid_index
*index
= NULL
;
4183 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4185 if (!actctx
->ifaceps_section
)
4187 struct guidsection_header
*section
;
4189 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4190 if (status
) return status
;
4192 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4193 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4196 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4197 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4199 iface
= get_ifaceps_data(actctx
, index
);
4201 data
->ulDataFormatVersion
= 1;
4202 data
->lpData
= iface
;
4203 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4204 data
->lpSectionGlobalData
= NULL
;
4205 data
->ulSectionGlobalDataLength
= 0;
4206 data
->lpSectionBase
= actctx
->ifaceps_section
;
4207 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4208 data
->hActCtx
= NULL
;
4210 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4211 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4213 return STATUS_SUCCESS
;
4216 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4218 unsigned int i
, j
, total_len
= 0, count
= 0;
4219 struct guidsection_header
*header
;
4220 struct clrsurrogate_data
*data
;
4221 struct guid_index
*index
;
4224 /* compute section length */
4225 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4227 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4228 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4230 struct entity
*entity
= &assembly
->entities
.base
[j
];
4231 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4235 total_len
+= sizeof(*index
) + sizeof(*data
);
4236 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4237 if (entity
->u
.clrsurrogate
.version
)
4238 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4239 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4246 total_len
+= sizeof(*header
);
4248 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4249 if (!header
) return STATUS_NO_MEMORY
;
4251 memset(header
, 0, sizeof(*header
));
4252 header
->magic
= GUIDSECTION_MAGIC
;
4253 header
->size
= sizeof(*header
);
4254 header
->count
= count
;
4255 header
->index_offset
= sizeof(*header
);
4256 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4257 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4259 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4261 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4262 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4264 struct entity
*entity
= &assembly
->entities
.base
[j
];
4265 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4267 ULONG version_len
, name_len
;
4271 if (entity
->u
.clrsurrogate
.version
)
4272 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4275 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4277 /* setup new index entry */
4278 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4279 RtlGUIDFromString(&str
, &index
->guid
);
4281 index
->data_offset
= data_offset
;
4282 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4283 index
->rosterindex
= i
+ 1;
4286 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4287 data
->size
= sizeof(*data
);
4289 data
->clsid
= index
->guid
;
4290 data
->version_offset
= version_len
? data
->size
: 0;
4291 data
->version_len
= version_len
;
4292 data
->name_offset
= data
->size
+ version_len
;
4294 data
->name_offset
+= sizeof(WCHAR
);
4295 data
->name_len
= name_len
;
4297 /* surrogate name */
4298 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4299 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4300 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4302 /* runtime version */
4303 if (data
->version_len
)
4305 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4306 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4307 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4310 data_offset
+= index
->data_offset
;
4318 return STATUS_SUCCESS
;
4321 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4323 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4326 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4328 struct clrsurrogate_data
*surrogate
;
4329 struct guid_index
*index
= NULL
;
4331 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4333 if (!actctx
->clrsurrogate_section
)
4335 struct guidsection_header
*section
;
4337 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4338 if (status
) return status
;
4340 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4341 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4344 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4345 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4347 surrogate
= get_surrogate_data(actctx
, index
);
4349 data
->ulDataFormatVersion
= 1;
4350 data
->lpData
= surrogate
;
4351 /* full length includes string length with nulls */
4352 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4353 if (surrogate
->version_len
)
4354 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4356 data
->lpSectionGlobalData
= NULL
;
4357 data
->ulSectionGlobalDataLength
= 0;
4358 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4359 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4360 data
->hActCtx
= NULL
;
4362 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4363 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4365 return STATUS_SUCCESS
;
4368 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4370 unsigned int i
, j
, single_len
;
4372 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4373 for (i
= 0; i
< entities
->num
; i
++)
4375 struct entity
*entity
= &entities
->base
[i
];
4376 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4378 if (entity
->u
.comclass
.progid
)
4380 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4384 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4385 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4387 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4388 *count
+= entity
->u
.comclass
.progids
.num
;
4393 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4394 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4396 struct progidredirect_data
*data
;
4401 /* setup new index entry */
4403 /* hash progid name */
4404 RtlInitUnicodeString(&str
, progid
);
4405 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4407 (*index
)->name_offset
= *data_offset
;
4408 (*index
)->name_len
= str
.Length
;
4409 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4410 (*index
)->data_len
= sizeof(*data
);
4411 (*index
)->rosterindex
= rosterindex
;
4413 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4415 /* setup data structure */
4416 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4417 data
->size
= sizeof(*data
);
4419 data
->clsid_offset
= *global_offset
;
4421 /* write progid string */
4422 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4423 memcpy(ptrW
, progid
, (*index
)->name_len
);
4424 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4426 /* write guid to global area */
4427 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4431 *global_offset
+= sizeof(GUID
);
4432 *data_offset
+= data
->size
;
4436 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4437 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4441 for (i
= 0; i
< entities
->num
; i
++)
4443 struct entity
*entity
= &entities
->base
[i
];
4444 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4446 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4447 struct comclassredirect_data
*comclass
;
4448 struct guid_index
*guid_index
;
4452 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4453 RtlGUIDFromString(&str
, &clsid
);
4455 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4456 comclass
= get_comclass_data(actctx
, guid_index
);
4458 if (entity
->u
.comclass
.progid
)
4459 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4460 index
, data_offset
, global_offset
, rosterindex
);
4462 for (j
= 0; j
< progids
->num
; j
++)
4463 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4464 index
, data_offset
, global_offset
, rosterindex
);
4469 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4471 unsigned int i
, j
, total_len
= 0, count
= 0;
4472 struct strsection_header
*header
;
4473 ULONG data_offset
, global_offset
;
4474 struct string_index
*index
;
4476 /* compute section length */
4477 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4479 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4481 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4482 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4484 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4485 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4489 total_len
+= sizeof(*header
);
4491 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4492 if (!header
) return STATUS_NO_MEMORY
;
4494 memset(header
, 0, sizeof(*header
));
4495 header
->magic
= STRSECTION_MAGIC
;
4496 header
->size
= sizeof(*header
);
4497 header
->count
= count
;
4498 header
->global_offset
= header
->size
;
4499 header
->global_len
= count
*sizeof(GUID
);
4500 header
->index_offset
= header
->size
+ header
->global_len
;
4502 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4503 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4504 global_offset
= header
->global_offset
;
4506 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4508 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4510 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4511 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4513 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4514 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4520 return STATUS_SUCCESS
;
4523 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4525 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4528 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4529 PACTCTX_SECTION_KEYED_DATA data
)
4531 struct progidredirect_data
*progid
;
4532 struct string_index
*index
;
4534 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4536 if (!actctx
->comserver_section
)
4538 struct guidsection_header
*section
;
4540 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4541 if (status
) return status
;
4543 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4544 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4547 if (!actctx
->progid_section
)
4549 struct strsection_header
*section
;
4551 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4552 if (status
) return status
;
4554 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4555 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4558 index
= find_string_index(actctx
->progid_section
, name
);
4559 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4563 progid
= get_progid_data(actctx
, index
);
4565 data
->ulDataFormatVersion
= 1;
4566 data
->lpData
= progid
;
4567 data
->ulLength
= progid
->size
;
4568 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4569 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4570 data
->lpSectionBase
= actctx
->progid_section
;
4571 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4572 data
->hActCtx
= NULL
;
4574 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4575 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4578 return STATUS_SUCCESS
;
4581 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4582 const UNICODE_STRING
*section_name
,
4583 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4587 switch (section_kind
)
4589 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4590 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4591 return STATUS_SXS_KEY_NOT_FOUND
;
4592 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4593 status
= find_dll_redirection(actctx
, section_name
, data
);
4595 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4596 status
= find_window_class(actctx
, section_name
, data
);
4598 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4599 status
= find_progid_redirection(actctx
, section_name
, data
);
4601 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4602 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4603 return STATUS_SXS_SECTION_NOT_FOUND
;
4605 DPRINT1("Unknown section_kind %x\n", section_kind
);
4606 return STATUS_SXS_SECTION_NOT_FOUND
;
4609 if (status
!= STATUS_SUCCESS
) return status
;
4611 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4613 actctx_addref(actctx
);
4614 data
->hActCtx
= actctx
;
4616 return STATUS_SUCCESS
;
4619 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4620 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4624 switch (section_kind
)
4626 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4627 status
= find_tlib_redirection(actctx
, guid
, data
);
4629 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4630 status
= find_comserver_redirection(actctx
, guid
, data
);
4632 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4633 status
= find_cominterface_redirection(actctx
, guid
, data
);
4635 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4636 status
= find_clr_surrogate(actctx
, guid
, data
);
4639 DPRINT("Unknown section_kind %x\n", section_kind
);
4640 return STATUS_SXS_SECTION_NOT_FOUND
;
4643 if (status
!= STATUS_SUCCESS
) return status
;
4645 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4647 actctx_addref(actctx
);
4648 data
->hActCtx
= actctx
;
4650 return STATUS_SUCCESS
;
4653 /* initialize the activation context for the current process */
4654 void actctx_init(void)
4659 ctx
.cbSize
= sizeof(ctx
);
4660 ctx
.lpSource
= NULL
;
4661 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4662 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4663 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4665 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4667 process_actctx
= check_actctx(handle
);
4671 /* FUNCTIONS ***************************************************************/
4673 /***********************************************************************
4674 * RtlCreateActivationContext (NTDLL.@)
4676 * Create an activation context.
4680 RtlCreateActivationContext(IN ULONG Flags
,
4681 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4682 IN ULONG ExtraBytes
,
4683 IN PVOID NotificationRoutine
,
4684 IN PVOID NotificationContext
,
4685 OUT PACTIVATION_CONTEXT
*ActCtx
)
4687 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4688 const WCHAR
*directory
= NULL
;
4689 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4690 ACTIVATION_CONTEXT
*actctx
;
4691 UNICODE_STRING nameW
;
4693 NTSTATUS status
= STATUS_NO_MEMORY
;
4695 struct actctx_loader acl
;
4697 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4699 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4700 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4701 return STATUS_INVALID_PARAMETER
;
4704 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4705 return STATUS_NO_MEMORY
;
4707 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4709 actctx
= &ActualActCtx
->ActivationContext
;
4710 actctx
->RefCount
= 1;
4711 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4712 actctx
->config
.info
= NULL
;
4713 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4714 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4716 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4724 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4725 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4727 status
= get_module_filename( module
, &dir
, 0 );
4728 if (!NT_SUCCESS(status
)) goto error
;
4729 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4730 actctx
->appdir
.info
= dir
.Buffer
;
4733 nameW
.Buffer
= NULL
;
4735 /* open file only if it's going to be used */
4736 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4737 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4739 WCHAR
*source
= NULL
;
4742 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4743 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
4745 DWORD dir_len
, source_len
;
4747 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4748 source_len
= strlenW(pActCtx
->lpSource
);
4749 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4751 status
= STATUS_NO_MEMORY
;
4755 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4756 source
[dir_len
] = '\\';
4757 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4760 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4761 if (source
) RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
4764 status
= STATUS_NO_SUCH_FILE
;
4767 status
= open_nt_file( &file
, &nameW
);
4768 if (!NT_SUCCESS(status
))
4770 RtlFreeUnicodeString( &nameW
);
4775 acl
.actctx
= actctx
;
4776 acl
.dependencies
= NULL
;
4777 acl
.num_dependencies
= 0;
4778 acl
.allocated_dependencies
= 0;
4780 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4781 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4783 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4785 /* if we have a resource it's a PE file */
4786 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4788 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4789 pActCtx
->lpResourceName
, lang
);
4790 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4791 /* FIXME: what to do if pActCtx->lpSource is set */
4792 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4793 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4795 else if (pActCtx
->lpSource
)
4797 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4798 file
, pActCtx
->lpResourceName
, lang
);
4799 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4800 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4801 NULL
, pActCtx
->lpResourceName
);
4803 else status
= STATUS_INVALID_PARAMETER
;
4807 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4810 if (file
) NtClose( file
);
4811 RtlFreeUnicodeString( &nameW
);
4813 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
4814 free_depend_manifests( &acl
);
4816 if (NT_SUCCESS(status
))
4818 else actctx_release( actctx
);
4822 if (file
) NtClose( file
);
4823 actctx_release( actctx
);
4828 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4832 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
4834 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
4835 LONG OldRefCount
, NewRefCount
;
4837 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4839 RtlpValidateActCtx(ActCtx
);
4843 OldRefCount
= ActCtx
->RefCount
;
4844 ASSERT(OldRefCount
> 0);
4846 if (OldRefCount
== LONG_MAX
) break;
4848 NewRefCount
= OldRefCount
+ 1;
4849 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
4851 OldRefCount
) == OldRefCount
)
4857 NewRefCount
= LONG_MAX
;
4858 ASSERT(NewRefCount
> 0);
4864 RtlReleaseActivationContext( HANDLE handle
)
4866 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
4868 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4870 RtlpValidateActCtx(ActCtx
);
4872 actctx_release(ActCtx
);
4877 /***********************************************************************
4878 * RtlAddRefActivationContext (NTDLL.@)
4880 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
4882 ACTIVATION_CONTEXT
*actctx
;
4884 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4888 /******************************************************************
4889 * RtlReleaseActivationContext (NTDLL.@)
4891 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
4893 ACTIVATION_CONTEXT
*actctx
;
4895 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4900 /******************************************************************
4901 * RtlZombifyActivationContext (NTDLL.@)
4904 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
4908 if (Context
== ACTCTX_FAKE_HANDLE
)
4909 return STATUS_SUCCESS
;
4911 return STATUS_NOT_IMPLEMENTED
;
4915 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
4917 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4919 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
4920 return STATUS_NO_MEMORY
;
4922 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
4923 frame
->ActivationContext
= handle
;
4926 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4927 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
4930 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
4931 RtlAddRefActivationContext( handle
);
4933 *cookie
= (ULONG_PTR
)frame
;
4934 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
4935 return STATUS_SUCCESS
;
4938 /******************************************************************
4939 * RtlActivateActivationContext (NTDLL.@)
4941 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
4943 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
4946 /***********************************************************************
4947 * RtlDeactivateActivationContext (NTDLL.@)
4949 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4951 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4953 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
4955 /* find the right frame */
4956 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
4957 for (frame
= top
; frame
; frame
= frame
->Previous
)
4958 if ((ULONG_PTR
)frame
== cookie
) break;
4961 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4963 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
4964 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4966 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4967 NtCurrentTeb()->ActivationContextStackPointer
,
4968 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
4971 /* pop everything up to and including frame */
4972 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
4974 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
4976 frame
= top
->Previous
;
4977 RtlReleaseActivationContext( top
->ActivationContext
);
4978 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
4982 return STATUS_SUCCESS
;
4987 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
4989 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
4991 /* Nothing to do if there is no stack */
4994 /* Get the current active frame */
4995 ActiveFrame
= Stack
->ActiveFrame
;
4997 /* Go through them in backwards order and release */
5000 PrevFrame
= ActiveFrame
->Previous
;
5001 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5002 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5003 ActiveFrame
= PrevFrame
;
5006 /* Zero out the active frame */
5007 Stack
->ActiveFrame
= NULL
;
5009 /* TODO: Empty the Frame List Cache */
5010 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5012 /* Free activation stack memory */
5013 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5016 /******************************************************************
5017 * RtlFreeThreadActivationContextStack (NTDLL.@)
5019 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5021 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5022 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5026 /******************************************************************
5027 * RtlGetActiveActivationContext (NTDLL.@)
5029 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5031 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5033 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5034 RtlAddRefActivationContext( *handle
);
5039 return STATUS_SUCCESS
;
5043 /******************************************************************
5044 * RtlIsActivationContextActive (NTDLL.@)
5046 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5048 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5050 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5051 if (frame
->ActivationContext
== handle
) return TRUE
;
5056 /***********************************************************************
5057 * RtlQueryInformationActivationContext (NTDLL.@)
5059 * Get information about an activation context.
5060 * FIXME: function signature/prototype may be wrong
5062 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5063 ULONG
class, PVOID buffer
,
5064 SIZE_T bufsize
, SIZE_T
*retlen
)
5066 ACTIVATION_CONTEXT
*actctx
;
5069 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5070 subinst
, class, buffer
, bufsize
, retlen
);
5072 if (retlen
) *retlen
= 0;
5073 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5077 case ActivationContextBasicInformation
:
5079 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5081 if (retlen
) *retlen
= sizeof(*info
);
5082 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5084 info
->hActCtx
= handle
;
5085 info
->dwFlags
= 0; /* FIXME */
5086 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5090 case ActivationContextDetailedInformation
:
5092 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5093 struct assembly
*assembly
= NULL
;
5094 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5097 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5099 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5101 if (assembly
&& assembly
->manifest
.info
)
5102 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5103 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5104 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5105 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5107 if (retlen
) *retlen
= len
;
5108 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5111 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5112 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5113 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5114 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5115 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5116 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5117 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5118 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5119 ptr
= (LPWSTR
)(acdi
+ 1);
5122 acdi
->lpRootManifestPath
= ptr
;
5123 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5124 ptr
+= manifest_len
;
5126 else acdi
->lpRootManifestPath
= NULL
;
5129 acdi
->lpRootConfigurationPath
= ptr
;
5130 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5133 else acdi
->lpRootConfigurationPath
= NULL
;
5136 acdi
->lpAppDirPath
= ptr
;
5137 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5139 else acdi
->lpAppDirPath
= NULL
;
5143 case AssemblyDetailedInformationInActivationContext
:
5145 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5146 struct assembly
*assembly
;
5149 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5152 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5153 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5155 index
= *(DWORD
*)subinst
;
5156 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5158 assembly
= &actctx
->assemblies
[index
- 1];
5160 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5161 id_len
= strlenW(assembly_id
) + 1;
5162 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5164 if (assembly
->manifest
.info
&&
5165 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5166 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5168 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5170 if (retlen
) *retlen
= len
;
5171 if (!buffer
|| bufsize
< len
)
5173 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5174 return STATUS_BUFFER_TOO_SMALL
;
5177 afdi
->ulFlags
= 0; /* FIXME */
5178 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5179 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5180 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5181 /* FIXME afdi->liManifestLastWriteTime = 0; */
5182 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5183 afdi
->ulPolicyPathLength
= 0;
5184 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5185 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5186 afdi
->ulManifestVersionMajor
= 1;
5187 afdi
->ulManifestVersionMinor
= 0;
5188 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5189 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5190 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5191 ptr
= (LPWSTR
)(afdi
+ 1);
5192 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5193 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5197 afdi
->lpAssemblyManifestPath
= ptr
;
5198 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5200 } else afdi
->lpAssemblyManifestPath
= NULL
;
5201 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5204 afdi
->lpAssemblyDirectoryName
= ptr
;
5205 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5207 else afdi
->lpAssemblyDirectoryName
= NULL
;
5208 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5212 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5214 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5215 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5216 struct assembly
*assembly
;
5217 struct dll_redirect
*dll
;
5218 SIZE_T len
, dll_len
= 0;
5221 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5222 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5224 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5225 return STATUS_INVALID_PARAMETER
;
5226 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5228 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5229 return STATUS_INVALID_PARAMETER
;
5230 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5232 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5233 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5235 if (!buffer
|| bufsize
< len
)
5237 if (retlen
) *retlen
= len
;
5238 return STATUS_BUFFER_TOO_SMALL
;
5240 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5241 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5242 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5243 afdi
->ulPathLength
= 0; /* FIXME */
5244 ptr
= (LPWSTR
)(afdi
+ 1);
5247 afdi
->lpFileName
= ptr
;
5248 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5249 } else afdi
->lpFileName
= NULL
;
5250 afdi
->lpFilePath
= NULL
; /* FIXME */
5255 DPRINT( "class %u not implemented\n", class );
5256 return STATUS_NOT_IMPLEMENTED
;
5258 return STATUS_SUCCESS
;
5263 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5265 SIZE_T cbBuffer OPTIONAL
,
5266 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5268 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5274 pcbWrittenOrRequired
);
5277 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5278 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5279 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5283 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5284 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5286 /* Check general parameter combinations */
5287 if (!section_name
|| !section_name
->Buffer
||
5288 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5289 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5290 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5292 DPRINT1("invalid parameter\n");
5293 return STATUS_INVALID_PARAMETER
;
5297 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5298 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5300 DPRINT1("unknown flags %08x\n", flags
);
5301 return STATUS_INVALID_PARAMETER
;
5304 return STATUS_SUCCESS
;
5307 /***********************************************************************
5308 * RtlFindActivationContextSectionString (NTDLL.@)
5310 * Find information about a string in an activation context.
5311 * FIXME: function signature/prototype may be wrong
5313 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5314 const UNICODE_STRING
*section_name
, PVOID ptr
)
5316 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5319 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5320 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5321 if (!NT_SUCCESS(status
))
5323 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5327 status
= STATUS_SXS_KEY_NOT_FOUND
;
5329 /* if there is no data, but params are valid,
5330 we return that sxs key is not found to be at least somehow compatible */
5333 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5337 ASSERT(NtCurrentTeb());
5338 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5340 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5341 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5343 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5344 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5347 DPRINT("status %x\n", status
);
5348 if (status
!= STATUS_SUCCESS
)
5349 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5351 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5355 /***********************************************************************
5356 * RtlFindActivationContextSectionGuid (NTDLL.@)
5358 * Find information about a GUID in an activation context.
5359 * FIXME: function signature/prototype may be wrong
5361 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5362 const GUID
*guid
, void *ptr
)
5364 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5365 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5369 DPRINT1("expected extguid == NULL\n");
5370 return STATUS_INVALID_PARAMETER
;
5373 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5375 DPRINT1("unknown flags %08x\n", flags
);
5376 return STATUS_INVALID_PARAMETER
;
5379 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5380 return STATUS_INVALID_PARAMETER
;
5382 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5384 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5385 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5388 if (status
!= STATUS_SUCCESS
)
5389 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5398 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5400 PACTIVATION_CONTEXT_STACK ContextStack
;
5402 /* Check if it's already allocated */
5403 if (*Stack
) return STATUS_SUCCESS
;
5405 /* Allocate space for the context stack */
5406 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5409 return STATUS_NO_MEMORY
;
5412 /* Initialize the context stack */
5413 ContextStack
->Flags
= 0;
5414 ContextStack
->ActiveFrame
= NULL
;
5415 InitializeListHead(&ContextStack
->FrameListCache
);
5416 ContextStack
->NextCookieSequenceNumber
= 1;
5417 ContextStack
->StackId
= 1; //TODO: Timer-based
5419 *Stack
= ContextStack
;
5421 return STATUS_SUCCESS
;
5424 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5426 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5429 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5430 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5432 /* Get the current active frame */
5433 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5435 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5436 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5437 &Frame
->Frame
, Context
);
5439 /* Ensure it's in the right format and at least fits basic info */
5440 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5441 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5443 /* Set debug info if size allows*/
5444 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5446 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5447 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5448 //Frame->Extra3 = ...;
5453 /*ASSERT((ActiveFrame->Flags &
5454 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5455 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5456 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5458 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5460 // TODO: Perform some additional checks if it was not heap allocated
5464 /* Save pointer to the new activation frame */
5465 NewFrame
= &Frame
->Frame
;
5467 /* Actually activate it */
5468 Frame
->Frame
.Previous
= ActiveFrame
;
5469 Frame
->Frame
.ActivationContext
= Context
;
5470 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5472 /* Check if we can activate this context */
5473 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5476 /* Set new active frame */
5477 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5478 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5482 /* We can get here only one way: it was already activated */
5483 DPRINT("Trying to activate already activated activation context\n");
5485 /* Activate only if we are allowing multiple activation */
5487 if (!RtlpNotAllowingMultipleActivation
)
5489 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5490 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5493 // Activate it anyway
5494 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5497 /* Return pointer to the activation frame */
5501 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5503 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5505 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5507 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5509 /* Ensure it's in the right format and at least fits basic info */
5510 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5511 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5513 /* Make sure it is not deactivated and it is activated */
5514 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5515 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5516 ASSERT((Frame
->Frame
.Flags
& (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5518 /* Check debug info if it is present */
5519 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5521 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5522 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5523 //Frame->Extra3 = ...;
5528 // TODO: Perform some additional checks here
5531 /* Special handling for not-really-activated */
5532 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5534 DPRINT1("Deactivating not really activated activation context\n");
5535 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5536 return &Frame
->Frame
;
5539 /* find the right frame */
5540 NewFrame
= &Frame
->Frame
;
5541 if (ActiveFrame
!= NewFrame
)
5543 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5546 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5547 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5549 /* Pop everything up to and including frame */
5550 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5552 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5553 return NewFrame
->Previous
;