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 DPRINT("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");
2439 else if (xml_elem_cmp(&elem
, L
"trustInfo", asmv1W
))
2441 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2446 attr_nameU
= xmlstr2unicode(&elem
);
2447 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2448 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2450 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2456 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2457 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2460 UNICODE_STRING elemU
;
2462 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2464 if (xmlstr_cmp(&elem
, g_xmlW
) &&
2465 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2466 return STATUS_SXS_CANT_GEN_ACTCTX
;
2468 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2470 elemU
= xmlstr2unicode(&elem
);
2471 DPRINT1("root element is %wZ, not <assembly>\n", &elemU
);
2472 return STATUS_SXS_CANT_GEN_ACTCTX
;
2475 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2477 DPRINT1("failed to parse manifest %S\n", assembly
->manifest
.info
);
2478 return STATUS_SXS_CANT_GEN_ACTCTX
;
2481 if (next_xml_elem(xmlbuf
, &elem
))
2483 elemU
= xmlstr2unicode(&elem
);
2484 DPRINT1("unexpected element %wZ\n", &elemU
);
2485 return STATUS_SXS_CANT_GEN_ACTCTX
;
2488 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2490 DPRINT1("parse error\n");
2491 return STATUS_SXS_CANT_GEN_ACTCTX
;
2493 return STATUS_SUCCESS
;
2496 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2497 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2498 const void *buffer
, SIZE_T size
)
2502 struct assembly
*assembly
;
2505 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename
, directory
);
2507 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2508 return STATUS_SXS_CANT_GEN_ACTCTX
;
2510 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2511 return STATUS_NO_MEMORY
;
2513 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2514 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2515 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2517 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2518 if (RtlIsTextUnicode(buffer
, size
, &unicode_tests
))
2520 xmlbuf
.ptr
= buffer
;
2521 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2522 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2524 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2526 const WCHAR
*buf
= buffer
;
2530 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
2531 return STATUS_NO_MEMORY
;
2532 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2533 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2534 xmlbuf
.ptr
= new_buff
;
2535 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2536 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2537 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
2541 /* TODO: this doesn't handle arbitrary encodings */
2545 status
= RtlMultiByteToUnicodeSize(&sizeU
, buffer
, size
);
2546 if (!NT_SUCCESS(status
))
2548 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status
);
2549 return STATUS_SXS_CANT_GEN_ACTCTX
;
2552 new_buff
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU
);
2554 return STATUS_NO_MEMORY
;
2556 status
= RtlMultiByteToUnicodeN(new_buff
, sizeU
, &sizeU
, buffer
, size
);
2557 if (!NT_SUCCESS(status
))
2559 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status
);
2560 return STATUS_SXS_CANT_GEN_ACTCTX
;
2563 xmlbuf
.ptr
= new_buff
;
2564 xmlbuf
.end
= xmlbuf
.ptr
+ sizeU
/ sizeof(WCHAR
);
2565 status
= parse_manifest_buffer(acl
, assembly
, ai
, &xmlbuf
);
2566 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff
);
2571 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2573 OBJECT_ATTRIBUTES attr
;
2576 attr
.Length
= sizeof(attr
);
2577 attr
.RootDirectory
= 0;
2578 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2579 attr
.ObjectName
= name
;
2580 attr
.SecurityDescriptor
= NULL
;
2581 attr
.SecurityQualityOfService
= NULL
;
2582 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2585 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2589 LDR_DATA_TABLE_ENTRY
*pldr
;
2591 LdrLockLoaderLock(0, NULL
, &magic
);
2592 status
= LdrFindEntryForAddress( module
, &pldr
);
2593 if (status
== STATUS_SUCCESS
)
2595 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2596 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2598 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2599 str
->Length
= pldr
->FullDllName
.Length
;
2600 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2602 else status
= STATUS_NO_MEMORY
;
2604 LdrUnlockLoaderLock(0, magic
);
2608 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2609 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2610 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2613 UNICODE_STRING nameW
;
2614 LDR_RESOURCE_INFO info
;
2615 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2618 //DPRINT( "looking for res %s in module %p %s\n", resname,
2619 // hModule, filename );
2620 DPRINT("get_manifest_in_module %p\n", hModule
);
2623 if (TRACE_ON(actctx
))
2625 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2627 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2628 hModule
, debugstr_w(nameW
.Buffer
) );
2629 RtlFreeUnicodeString( &nameW
);
2631 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2632 hModule
, debugstr_w(filename
) );
2636 if (!resname
) return STATUS_INVALID_PARAMETER
;
2638 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2639 info
.Language
= lang
;
2640 if (!((ULONG_PTR
)resname
>> 16))
2642 info
.Name
= (ULONG_PTR
)resname
;
2643 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2645 else if (resname
[0] == '#')
2648 RtlInitUnicodeString(&nameW
, resname
+ 1);
2649 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2650 return STATUS_INVALID_PARAMETER
;
2652 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2656 RtlCreateUnicodeString(&nameW
, resname
);
2657 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2658 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2659 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2660 RtlFreeUnicodeString(&nameW
);
2662 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2664 if (status
== STATUS_SUCCESS
)
2665 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2670 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2671 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2672 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2675 OBJECT_ATTRIBUTES attr
;
2677 LARGE_INTEGER offset
;
2682 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2684 attr
.Length
= sizeof(attr
);
2685 attr
.RootDirectory
= 0;
2686 attr
.ObjectName
= NULL
;
2687 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2688 attr
.SecurityDescriptor
= NULL
;
2689 attr
.SecurityQualityOfService
= NULL
;
2692 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2693 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2694 if (status
!= STATUS_SUCCESS
) return status
;
2696 offset
.QuadPart
= 0;
2699 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2700 &count
, ViewShare
, 0, PAGE_READONLY
);
2702 if (status
!= STATUS_SUCCESS
) return status
;
2704 if (RtlImageNtHeader(base
)) /* we got a PE file */
2706 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2707 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2709 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2711 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2715 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2716 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2718 FILE_STANDARD_INFORMATION info
;
2721 OBJECT_ATTRIBUTES attr
;
2723 LARGE_INTEGER offset
;
2728 DPRINT( "loading manifest file %S\n", filename
);
2730 attr
.Length
= sizeof(attr
);
2731 attr
.RootDirectory
= 0;
2732 attr
.ObjectName
= NULL
;
2733 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2734 attr
.SecurityDescriptor
= NULL
;
2735 attr
.SecurityQualityOfService
= NULL
;
2738 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2739 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2741 if (status
!= STATUS_SUCCESS
) return status
;
2743 offset
.QuadPart
= 0;
2746 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2747 &count
, ViewShare
, 0, PAGE_READONLY
);
2749 if (status
!= STATUS_SUCCESS
) return status
;
2751 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2752 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
2754 if (status
== STATUS_SUCCESS
)
2755 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
2757 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2761 /* try to load the .manifest file associated to the file */
2762 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2763 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2765 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2768 UNICODE_STRING nameW
;
2770 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2772 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2774 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
2776 if (module
) /* use the module filename */
2778 UNICODE_STRING name
;
2780 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2782 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2783 strcatW( name
.Buffer
, dotManifestW
);
2784 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2785 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2786 RtlFreeUnicodeString( &name
);
2788 if (status
) return status
;
2792 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2793 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2794 return STATUS_NO_MEMORY
;
2795 strcpyW( buffer
, filename
);
2796 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2797 strcatW( buffer
, dotManifestW
);
2798 RtlInitUnicodeString( &nameW
, buffer
);
2801 if (!open_nt_file( &file
, &nameW
))
2803 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2806 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2807 RtlFreeUnicodeString( &nameW
);
2811 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2813 static const WCHAR lookup_fmtW
[] =
2814 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2815 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2816 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2818 WCHAR
*lookup
, *ret
= NULL
;
2819 UNICODE_STRING lookup_us
;
2821 const WCHAR
*lang
= ai
->language
;
2822 unsigned int data_pos
= 0, data_len
;
2825 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2826 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2827 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2828 + sizeof(lookup_fmtW
) )))
2831 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2832 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2833 ai
->version
.major
, ai
->version
.minor
, lang
);
2834 RtlInitUnicodeString( &lookup_us
, lookup
);
2836 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2837 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
2839 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2840 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2842 ULONG build
, revision
;
2844 data_len
= (ULONG
)io
.Information
;
2848 if (data_pos
>= data_len
)
2850 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2851 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
2853 data_len
= (ULONG
)io
.Information
;
2856 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2858 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2859 else data_pos
= data_len
;
2861 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2863 if (build
< min_build
) continue;
2864 tmp
= strchrW(tmp
, '.') + 1;
2865 revision
= atoiW(tmp
);
2866 if (build
== min_build
&& revision
< min_revision
) continue;
2867 tmp
= strchrW(tmp
, '_') + 1;
2868 tmp
= strchrW(tmp
, '_') + 1;
2869 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2870 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2872 /* prefer a non-Wine manifest if we already have one */
2873 /* we'll still load the builtin dll if specified through DllOverrides */
2879 min_revision
= revision
;
2881 ai
->version
.build
= build
;
2882 ai
->version
.revision
= revision
;
2883 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
2884 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2886 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2887 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2891 else DPRINT1("no matching file for %S\n", lookup
);
2892 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
2896 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2898 struct assembly_identity sxs_ai
;
2899 UNICODE_STRING path_us
;
2900 OBJECT_ATTRIBUTES attr
;
2902 WCHAR
*path
, *file
= NULL
;
2905 static const WCHAR manifest_dirW
[] =
2906 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2908 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2910 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2911 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
2912 return STATUS_NO_MEMORY
;
2914 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
2915 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
2917 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2919 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2920 return STATUS_NO_SUCH_FILE
;
2922 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2924 attr
.Length
= sizeof(attr
);
2925 attr
.RootDirectory
= 0;
2926 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2927 attr
.ObjectName
= &path_us
;
2928 attr
.SecurityDescriptor
= NULL
;
2929 attr
.SecurityQualityOfService
= NULL
;
2931 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2932 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2935 file
= lookup_manifest_file( handle
, &sxs_ai
);
2940 RtlFreeUnicodeString( &path_us
);
2941 return STATUS_NO_SUCH_FILE
;
2944 /* append file name to directory path */
2945 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
2946 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2948 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2949 RtlFreeUnicodeString( &path_us
);
2950 return STATUS_NO_MEMORY
;
2953 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2954 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2955 RtlInitUnicodeString( &path_us
, path
);
2956 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2958 if (!open_nt_file( &handle
, &path_us
))
2960 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2963 else io
.Status
= STATUS_NO_SUCH_FILE
;
2965 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2966 RtlFreeUnicodeString( &path_us
);
2970 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2971 struct assembly_identity
* ai
)
2973 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2975 WCHAR
*buffer
, *p
, *directory
;
2977 UNICODE_STRING nameW
;
2981 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2982 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
2984 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2986 /* FIXME: add support for language specific lookup */
2988 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2989 strlenW(acl
->actctx
->appdir
.info
));
2991 nameW
.Buffer
= NULL
;
2992 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2993 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2994 return STATUS_NO_MEMORY
;
2996 if (!(directory
= build_assembly_dir( ai
)))
2998 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
2999 return STATUS_NO_MEMORY
;
3002 /* Lookup in <dir>\name.dll
3003 * <dir>\name.manifest
3004 * <dir>\name\name.dll
3005 * <dir>\name\name.manifest
3007 * First 'appdir' is used as <dir>, if that failed
3008 * it tries application manifest file path.
3010 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3011 p
= buffer
+ strlenW(buffer
);
3012 for (i
= 0; i
< 4; i
++)
3016 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3017 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3021 strcpyW( p
, ai
->name
);
3024 strcpyW( p
, dotDllW
);
3025 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3027 status
= open_nt_file( &file
, &nameW
);
3030 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3031 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3035 RtlFreeUnicodeString( &nameW
);
3038 strcpyW( p
, dotManifestW
);
3039 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3041 status
= open_nt_file( &file
, &nameW
);
3044 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3048 RtlFreeUnicodeString( &nameW
);
3050 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3052 RtlFreeUnicodeString( &nameW
);
3053 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3054 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3058 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3060 NTSTATUS status
= STATUS_SUCCESS
;
3063 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3065 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3067 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3069 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3070 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3071 acl
->dependencies
[i
].name
,
3072 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3073 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3078 /* FIXME should now iterate through all refs */
3082 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3083 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3085 NTSTATUS status
= STATUS_SUCCESS
;
3087 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3089 if (*handle
) return STATUS_INVALID_PARAMETER
;
3091 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3092 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3094 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3097 LDR_DATA_TABLE_ENTRY
*pldr
;
3099 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3101 LdrLockLoaderLock( 0, NULL
, &magic
);
3102 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3104 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3105 status
= STATUS_DLL_NOT_FOUND
;
3107 *handle
= pldr
->EntryPointActivationContext
;
3109 else status
= STATUS_DLL_NOT_FOUND
;
3110 LdrUnlockLoaderLock( 0, magic
);
3112 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3113 *handle
= process_actctx
;
3118 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3120 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3121 struct strsection_header
*header
;
3122 struct dllredirect_data
*data
;
3123 struct string_index
*index
;
3126 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3128 /* compute section length */
3129 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3131 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3132 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3134 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3136 /* each entry needs index, data and string data */
3137 total_len
+= sizeof(*index
);
3138 total_len
+= sizeof(*data
);
3139 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3141 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3144 dll_count
+= assembly
->num_dlls
;
3147 total_len
+= sizeof(*header
);
3149 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3150 if (!header
) return STATUS_NO_MEMORY
;
3152 memset(header
, 0, sizeof(*header
));
3153 header
->magic
= STRSECTION_MAGIC
;
3154 header
->size
= sizeof(*header
);
3155 header
->count
= dll_count
;
3156 header
->index_offset
= sizeof(*header
);
3157 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3158 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3160 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3162 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3164 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3166 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3168 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3172 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3173 /* setup new index entry */
3174 str
.Buffer
= dll
->name
;
3175 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3176 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3177 /* hash original class name */
3178 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3180 index
->name_offset
= name_offset
;
3181 index
->name_len
= str
.Length
;
3182 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3183 index
->data_len
= sizeof(*data
);
3184 index
->rosterindex
= i
+ 1;
3187 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3188 data
->size
= sizeof(*data
);
3189 data
->unk
= 2; /* FIXME: seems to be constant */
3190 memset(data
->res
, 0, sizeof(data
->res
));
3193 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3194 memcpy(ptrW
, dll
->name
, index
->name_len
);
3195 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3197 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3205 return STATUS_SUCCESS
;
3208 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3210 struct string_index
*iter
, *index
= NULL
;
3213 DPRINT("section %p, name %wZ\n", section
, name
);
3214 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3215 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3217 for (i
= 0; i
< section
->count
; i
++)
3219 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3220 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3221 if (iter
->hash
== hash
)
3223 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3225 if (!strcmpiW(nameW
, name
->Buffer
))
3231 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3239 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3241 struct guid_index
*iter
, *index
= NULL
;
3244 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3246 for (i
= 0; i
< section
->count
; i
++)
3248 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3259 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3261 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3264 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3265 PACTCTX_SECTION_KEYED_DATA data
)
3267 struct dllredirect_data
*dll
;
3268 struct string_index
*index
;
3270 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3271 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3273 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3274 if (!actctx
->dllredirect_section
)
3276 struct strsection_header
*section
;
3278 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3279 if (status
) return status
;
3281 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3282 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3285 index
= find_string_index(actctx
->dllredirect_section
, name
);
3286 DPRINT("index: %d\n", index
);
3287 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3291 dll
= get_dllredirect_data(actctx
, index
);
3293 data
->ulDataFormatVersion
= 1;
3295 data
->ulLength
= dll
->size
;
3296 data
->lpSectionGlobalData
= NULL
;
3297 data
->ulSectionGlobalDataLength
= 0;
3298 data
->lpSectionBase
= actctx
->dllredirect_section
;
3299 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3300 data
->hActCtx
= NULL
;
3302 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3303 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3306 return STATUS_SUCCESS
;
3309 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3311 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3314 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3316 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3319 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3321 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3322 struct wndclass_redirect_data
*data
;
3323 struct strsection_header
*header
;
3324 struct string_index
*index
;
3327 /* compute section length */
3328 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3330 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3331 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3333 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3334 for (k
= 0; k
< dll
->entities
.num
; k
++)
3336 struct entity
*entity
= &dll
->entities
.base
[k
];
3337 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3339 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3342 /* each class entry needs index, data and string data */
3343 total_len
+= sizeof(*index
);
3344 total_len
+= sizeof(*data
);
3345 /* original name is stored separately */
3346 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3347 /* versioned name and module name are stored one after another */
3348 if (entity
->u
.class.versioned
)
3349 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3352 len
+= strlenW(dll
->name
) + 1;
3353 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3361 total_len
+= sizeof(*header
);
3363 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3364 if (!header
) return STATUS_NO_MEMORY
;
3366 memset(header
, 0, sizeof(*header
));
3367 header
->magic
= STRSECTION_MAGIC
;
3368 header
->size
= sizeof(*header
);
3369 header
->count
= class_count
;
3370 header
->index_offset
= sizeof(*header
);
3371 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3372 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3374 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3376 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3377 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3379 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3380 for (k
= 0; k
< dll
->entities
.num
; k
++)
3382 struct entity
*entity
= &dll
->entities
.base
[k
];
3383 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3385 static const WCHAR exclW
[] = {'!',0};
3386 ULONG versioned_len
, module_len
;
3390 /* setup new index entry */
3391 str
.Buffer
= entity
->u
.class.name
;
3392 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3393 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3394 /* hash original class name */
3395 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3397 /* include '!' separator too */
3398 if (entity
->u
.class.versioned
)
3399 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3401 versioned_len
= str
.Length
;
3402 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3404 index
->name_offset
= name_offset
;
3405 index
->name_len
= str
.Length
;
3406 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3407 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3408 index
->rosterindex
= i
+ 1;
3411 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3412 data
->size
= sizeof(*data
);
3414 data
->name_len
= versioned_len
;
3415 data
->name_offset
= sizeof(*data
);
3416 data
->module_len
= module_len
;
3417 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3419 /* original class name */
3420 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3421 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3422 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3425 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3426 memcpy(ptrW
, dll
->name
, data
->module_len
);
3427 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3429 /* versioned name */
3430 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3431 if (entity
->u
.class.versioned
)
3433 get_assembly_version(assembly
, ptrW
);
3434 strcatW(ptrW
, exclW
);
3435 strcatW(ptrW
, entity
->u
.class.name
);
3439 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3440 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3443 name_offset
+= sizeof(*data
);
3444 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3454 return STATUS_SUCCESS
;
3457 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3458 PACTCTX_SECTION_KEYED_DATA data
)
3460 struct string_index
*iter
, *index
= NULL
;
3461 struct wndclass_redirect_data
*class;
3465 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3467 if (!actctx
->wndclass_section
)
3469 struct strsection_header
*section
;
3471 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3472 if (status
) return status
;
3474 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3475 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3479 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3480 iter
= get_wndclass_first_index(actctx
);
3482 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3484 if (iter
->hash
== hash
)
3486 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3488 if (!strcmpiW(nameW
, name
->Buffer
))
3494 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3499 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3503 class = get_wndclass_data(actctx
, index
);
3505 data
->ulDataFormatVersion
= 1;
3506 data
->lpData
= class;
3507 /* full length includes string length with nulls */
3508 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3509 data
->lpSectionGlobalData
= NULL
;
3510 data
->ulSectionGlobalDataLength
= 0;
3511 data
->lpSectionBase
= actctx
->wndclass_section
;
3512 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3513 data
->hActCtx
= NULL
;
3515 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3516 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3519 return STATUS_SUCCESS
;
3522 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3524 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3525 struct guidsection_header
*header
;
3526 ULONG module_offset
, data_offset
;
3527 struct tlibredirect_data
*data
;
3528 struct guid_index
*index
;
3530 /* compute section length */
3531 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3533 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3534 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3536 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3537 for (k
= 0; k
< dll
->entities
.num
; k
++)
3539 struct entity
*entity
= &dll
->entities
.base
[k
];
3540 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3542 /* each entry needs index, data and string data for module name and help string */
3543 total_len
+= sizeof(*index
);
3544 total_len
+= sizeof(*data
);
3545 /* help string is stored separately */
3546 if (*entity
->u
.typelib
.helpdir
)
3547 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3549 /* module names are packed one after another */
3550 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3558 total_len
+= aligned_string_len(names_len
);
3559 total_len
+= sizeof(*header
);
3561 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3562 if (!header
) return STATUS_NO_MEMORY
;
3564 memset(header
, 0, sizeof(*header
));
3565 header
->magic
= GUIDSECTION_MAGIC
;
3566 header
->size
= sizeof(*header
);
3567 header
->count
= tlib_count
;
3568 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3569 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3570 module_offset
= sizeof(*header
);
3571 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3573 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3575 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3576 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3578 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3579 for (k
= 0; k
< dll
->entities
.num
; k
++)
3581 struct entity
*entity
= &dll
->entities
.base
[k
];
3582 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3584 ULONG module_len
, help_len
;
3588 if (*entity
->u
.typelib
.helpdir
)
3589 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3593 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3595 /* setup new index entry */
3596 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3597 RtlGUIDFromString(&str
, &index
->guid
);
3598 index
->data_offset
= data_offset
;
3599 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3600 index
->rosterindex
= i
+ 1;
3603 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3604 data
->size
= sizeof(*data
);
3606 data
->name_len
= module_len
;
3607 data
->name_offset
= module_offset
;
3608 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3610 data
->flags
= entity
->u
.typelib
.flags
;
3611 data
->help_len
= help_len
;
3612 data
->help_offset
= sizeof(*data
);
3613 data
->major_version
= entity
->u
.typelib
.major
;
3614 data
->minor_version
= entity
->u
.typelib
.minor
;
3617 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3618 memcpy(ptrW
, dll
->name
, data
->name_len
);
3619 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3624 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3625 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3626 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3629 data_offset
+= sizeof(*data
);
3631 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3633 module_offset
+= module_len
+ sizeof(WCHAR
);
3643 return STATUS_SUCCESS
;
3646 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3648 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3651 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3653 struct guid_index
*index
= NULL
;
3654 struct tlibredirect_data
*tlib
;
3656 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3658 if (!actctx
->tlib_section
)
3660 struct guidsection_header
*section
;
3662 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3663 if (status
) return status
;
3665 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3666 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3669 index
= find_guid_index(actctx
->tlib_section
, guid
);
3670 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3672 tlib
= get_tlib_data(actctx
, index
);
3674 data
->ulDataFormatVersion
= 1;
3675 data
->lpData
= tlib
;
3676 /* full length includes string length with nulls */
3677 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3678 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3679 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3680 data
->lpSectionBase
= actctx
->tlib_section
;
3681 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3682 data
->hActCtx
= NULL
;
3684 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3685 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3687 return STATUS_SUCCESS
;
3690 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3692 ULONG
*ptr
= (ULONG
*)guid
;
3695 /* GUID is 16 bytes long */
3696 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3697 *ptr
= RtlUniform(seed
);
3699 guid
->Data3
&= 0x0fff;
3700 guid
->Data3
|= (4 << 12);
3701 guid
->Data4
[0] &= 0x3f;
3702 guid
->Data4
[0] |= 0x80;
3705 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3706 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3710 for (i
= 0; i
< entities
->num
; i
++)
3712 struct entity
*entity
= &entities
->base
[i
];
3713 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3715 /* each entry needs two index entries, extra one goes for alias GUID */
3716 *len
+= 2*sizeof(struct guid_index
);
3717 /* To save some memory we don't allocated two data structures,
3718 instead alias index and normal index point to the same data structure. */
3719 *len
+= sizeof(struct comclassredirect_data
);
3721 /* for clrClass store some more */
3722 if (entity
->u
.comclass
.name
)
3724 unsigned int str_len
;
3726 /* all string data is stored together in aligned block */
3727 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3728 if (entity
->u
.comclass
.progid
)
3729 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3730 if (entity
->u
.comclass
.version
)
3731 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3733 *len
+= sizeof(struct clrclass_data
);
3734 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3736 /* module name is forced to mscoree.dll, and stored two times with different case */
3737 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3741 /* progid string is stored separately */
3742 if (entity
->u
.comclass
.progid
)
3743 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3745 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3753 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3754 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3755 ULONG
*seed
, ULONG rosterindex
)
3759 for (i
= 0; i
< entities
->num
; i
++)
3761 struct entity
*entity
= &entities
->base
[i
];
3762 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3764 ULONG module_len
, progid_len
, str_len
= 0;
3765 struct comclassredirect_data
*data
;
3766 struct guid_index
*alias_index
;
3767 struct clrclass_data
*clrdata
;
3771 if (entity
->u
.comclass
.progid
)
3772 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3776 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3778 /* setup new index entry */
3779 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3780 RtlGUIDFromString(&str
, &(*index
)->guid
);
3782 (*index
)->data_offset
= *data_offset
;
3783 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3784 (*index
)->rosterindex
= rosterindex
;
3786 /* Setup new index entry for alias guid. Alias index records are placed after
3787 normal records, so normal guids are hit first on search. Note that class count
3789 alias_index
= (*index
) + section
->count
/2;
3790 generate_uuid(seed
, &alias_index
->guid
);
3791 alias_index
->data_offset
= (*index
)->data_offset
;
3792 alias_index
->data_len
= 0;
3793 alias_index
->rosterindex
= (*index
)->rosterindex
;
3796 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3797 data
->size
= sizeof(*data
);
3801 data
->model
= entity
->u
.comclass
.model
;
3802 data
->clsid
= (*index
)->guid
;
3803 data
->alias
= alias_index
->guid
;
3804 data
->clsid2
= data
->clsid
;
3805 if (entity
->u
.comclass
.tlbid
)
3807 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3808 RtlGUIDFromString(&str
, &data
->tlbid
);
3811 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3812 data
->name_len
= module_len
;
3813 data
->name_offset
= *module_offset
;
3814 data
->progid_len
= progid_len
;
3815 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3816 data
->clrdata_len
= 0; /* will be set later */
3817 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3818 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3819 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3820 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3821 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3822 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3824 /* mask describes which misc* data is available */
3826 if (data
->miscstatus
)
3827 data
->miscmask
|= MiscStatus
;
3828 if (data
->miscstatuscontent
)
3829 data
->miscmask
|= MiscStatusContent
;
3830 if (data
->miscstatusthumbnail
)
3831 data
->miscmask
|= MiscStatusThumbnail
;
3832 if (data
->miscstatusicon
)
3833 data
->miscmask
|= MiscStatusIcon
;
3834 if (data
->miscstatusdocprint
)
3835 data
->miscmask
|= MiscStatusDocPrint
;
3837 if (data
->clrdata_offset
)
3839 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3841 clrdata
->size
= sizeof(*clrdata
);
3842 clrdata
->res
[0] = 0;
3843 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3844 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3845 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3846 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3847 clrdata
->name_offset
= clrdata
->size
;
3848 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3849 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3850 clrdata
->res2
[0] = 0;
3851 clrdata
->res2
[1] = 0;
3853 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3856 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3857 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3858 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3860 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3861 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3862 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3865 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3866 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3867 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3869 /* runtime version, optional */
3870 if (clrdata
->version_len
)
3872 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3874 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3875 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3876 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3879 if (data
->progid_len
)
3880 data
->progid_offset
+= data
->clrdata_len
;
3881 (*index
)->data_len
+= sizeof(*clrdata
);
3888 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3889 memcpy(ptrW
, dll
->name
, data
->name_len
);
3890 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3894 if (data
->progid_len
)
3896 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3897 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3898 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3901 /* string block length */
3905 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3906 if (clrdata
->version_len
)
3907 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3910 str_len
+= progid_len
+ sizeof(WCHAR
);
3912 (*index
)->data_len
+= aligned_string_len(str_len
);
3913 alias_index
->data_len
= (*index
)->data_len
;
3915 /* move to next data record */
3916 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3917 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3921 (*data_offset
) += sizeof(*clrdata
);
3922 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3929 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3931 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3932 struct guidsection_header
*header
;
3933 ULONG module_offset
, data_offset
;
3934 struct guid_index
*index
;
3937 /* compute section length */
3938 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3940 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3941 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3942 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3944 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3945 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3949 total_len
+= aligned_string_len(names_len
);
3950 total_len
+= sizeof(*header
);
3952 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3953 if (!header
) return STATUS_NO_MEMORY
;
3955 memset(header
, 0, sizeof(*header
));
3956 header
->magic
= GUIDSECTION_MAGIC
;
3957 header
->size
= sizeof(*header
);
3958 header
->count
= 2*class_count
;
3959 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3960 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3961 module_offset
= sizeof(*header
);
3962 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3964 seed
= NtGetTickCount();
3965 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3967 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3968 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3969 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3971 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3972 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3978 return STATUS_SUCCESS
;
3981 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3983 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3986 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3988 struct comclassredirect_data
*comclass
;
3989 struct guid_index
*index
= NULL
;
3991 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3993 if (!actctx
->comserver_section
)
3995 struct guidsection_header
*section
;
3997 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
3998 if (status
) return status
;
4000 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4001 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4004 index
= find_guid_index(actctx
->comserver_section
, guid
);
4005 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4007 comclass
= get_comclass_data(actctx
, index
);
4009 data
->ulDataFormatVersion
= 1;
4010 data
->lpData
= comclass
;
4011 /* full length includes string length with nulls */
4012 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4013 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4014 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4015 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4016 data
->lpSectionBase
= actctx
->comserver_section
;
4017 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4018 data
->hActCtx
= NULL
;
4020 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4021 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4023 return STATUS_SUCCESS
;
4026 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4030 for (i
= 0; i
< entities
->num
; i
++)
4032 struct entity
*entity
= &entities
->base
[i
];
4033 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4035 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4036 if (entity
->u
.ifaceps
.name
)
4037 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4043 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4044 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4048 for (i
= 0; i
< entities
->num
; i
++)
4050 struct entity
*entity
= &entities
->base
[i
];
4051 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4053 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4057 if (entity
->u
.ifaceps
.name
)
4058 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4063 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4064 RtlGUIDFromString(&str
, &(*index
)->guid
);
4065 (*index
)->data_offset
= *data_offset
;
4066 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4067 (*index
)->rosterindex
= rosterindex
;
4069 /* setup data record */
4070 data
->size
= sizeof(*data
);
4071 data
->mask
= entity
->u
.ifaceps
.mask
;
4073 /* proxyStubClsid32 value is only stored for external PS,
4074 if set it's used as iid, otherwise 'iid' attribute value is used */
4075 if (entity
->u
.ifaceps
.ps32
)
4077 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4078 RtlGUIDFromString(&str
, &data
->iid
);
4081 data
->iid
= (*index
)->guid
;
4083 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4085 if (entity
->u
.ifaceps
.tlib
)
4087 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4088 RtlGUIDFromString(&str
, &data
->tlbid
);
4091 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4093 if (entity
->u
.ifaceps
.base
)
4095 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4096 RtlGUIDFromString(&str
, &data
->base
);
4099 memset(&data
->base
, 0, sizeof(data
->base
));
4101 data
->name_len
= name_len
;
4102 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4107 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4108 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4109 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4112 /* move to next record */
4114 *data_offset
+= sizeof(*data
);
4116 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4121 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4123 unsigned int i
, j
, total_len
= 0, count
= 0;
4124 struct guidsection_header
*header
;
4125 struct guid_index
*index
;
4128 /* compute section length */
4129 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4131 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4133 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4134 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4136 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4137 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4141 total_len
+= sizeof(*header
);
4143 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4144 if (!header
) return STATUS_NO_MEMORY
;
4146 memset(header
, 0, sizeof(*header
));
4147 header
->magic
= GUIDSECTION_MAGIC
;
4148 header
->size
= sizeof(*header
);
4149 header
->count
= count
;
4150 header
->index_offset
= sizeof(*header
);
4151 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4152 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4154 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4156 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4158 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4159 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4161 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4162 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4168 return STATUS_SUCCESS
;
4171 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4173 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4176 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4178 struct ifacepsredirect_data
*iface
;
4179 struct guid_index
*index
= NULL
;
4181 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4183 if (!actctx
->ifaceps_section
)
4185 struct guidsection_header
*section
;
4187 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4188 if (status
) return status
;
4190 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4191 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4194 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4195 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4197 iface
= get_ifaceps_data(actctx
, index
);
4199 data
->ulDataFormatVersion
= 1;
4200 data
->lpData
= iface
;
4201 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4202 data
->lpSectionGlobalData
= NULL
;
4203 data
->ulSectionGlobalDataLength
= 0;
4204 data
->lpSectionBase
= actctx
->ifaceps_section
;
4205 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4206 data
->hActCtx
= NULL
;
4208 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4209 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4211 return STATUS_SUCCESS
;
4214 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4216 unsigned int i
, j
, total_len
= 0, count
= 0;
4217 struct guidsection_header
*header
;
4218 struct clrsurrogate_data
*data
;
4219 struct guid_index
*index
;
4222 /* compute section length */
4223 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4225 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4226 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4228 struct entity
*entity
= &assembly
->entities
.base
[j
];
4229 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4233 total_len
+= sizeof(*index
) + sizeof(*data
);
4234 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4235 if (entity
->u
.clrsurrogate
.version
)
4236 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4237 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4244 total_len
+= sizeof(*header
);
4246 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4247 if (!header
) return STATUS_NO_MEMORY
;
4249 memset(header
, 0, sizeof(*header
));
4250 header
->magic
= GUIDSECTION_MAGIC
;
4251 header
->size
= sizeof(*header
);
4252 header
->count
= count
;
4253 header
->index_offset
= sizeof(*header
);
4254 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4255 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4257 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4259 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4260 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4262 struct entity
*entity
= &assembly
->entities
.base
[j
];
4263 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4265 ULONG version_len
, name_len
;
4269 if (entity
->u
.clrsurrogate
.version
)
4270 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4273 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4275 /* setup new index entry */
4276 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4277 RtlGUIDFromString(&str
, &index
->guid
);
4279 index
->data_offset
= data_offset
;
4280 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4281 index
->rosterindex
= i
+ 1;
4284 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4285 data
->size
= sizeof(*data
);
4287 data
->clsid
= index
->guid
;
4288 data
->version_offset
= version_len
? data
->size
: 0;
4289 data
->version_len
= version_len
;
4290 data
->name_offset
= data
->size
+ version_len
;
4292 data
->name_offset
+= sizeof(WCHAR
);
4293 data
->name_len
= name_len
;
4295 /* surrogate name */
4296 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4297 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4298 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4300 /* runtime version */
4301 if (data
->version_len
)
4303 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4304 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4305 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4308 data_offset
+= index
->data_offset
;
4316 return STATUS_SUCCESS
;
4319 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4321 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4324 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4326 struct clrsurrogate_data
*surrogate
;
4327 struct guid_index
*index
= NULL
;
4329 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4331 if (!actctx
->clrsurrogate_section
)
4333 struct guidsection_header
*section
;
4335 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4336 if (status
) return status
;
4338 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4339 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4342 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4343 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4345 surrogate
= get_surrogate_data(actctx
, index
);
4347 data
->ulDataFormatVersion
= 1;
4348 data
->lpData
= surrogate
;
4349 /* full length includes string length with nulls */
4350 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4351 if (surrogate
->version_len
)
4352 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4354 data
->lpSectionGlobalData
= NULL
;
4355 data
->ulSectionGlobalDataLength
= 0;
4356 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4357 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4358 data
->hActCtx
= NULL
;
4360 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4361 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4363 return STATUS_SUCCESS
;
4366 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4368 unsigned int i
, j
, single_len
;
4370 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4371 for (i
= 0; i
< entities
->num
; i
++)
4373 struct entity
*entity
= &entities
->base
[i
];
4374 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4376 if (entity
->u
.comclass
.progid
)
4378 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4382 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4383 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4385 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4386 *count
+= entity
->u
.comclass
.progids
.num
;
4391 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4392 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4394 struct progidredirect_data
*data
;
4399 /* setup new index entry */
4401 /* hash progid name */
4402 RtlInitUnicodeString(&str
, progid
);
4403 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4405 (*index
)->name_offset
= *data_offset
;
4406 (*index
)->name_len
= str
.Length
;
4407 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4408 (*index
)->data_len
= sizeof(*data
);
4409 (*index
)->rosterindex
= rosterindex
;
4411 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4413 /* setup data structure */
4414 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4415 data
->size
= sizeof(*data
);
4417 data
->clsid_offset
= *global_offset
;
4419 /* write progid string */
4420 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4421 memcpy(ptrW
, progid
, (*index
)->name_len
);
4422 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4424 /* write guid to global area */
4425 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4429 *global_offset
+= sizeof(GUID
);
4430 *data_offset
+= data
->size
;
4434 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4435 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4439 for (i
= 0; i
< entities
->num
; i
++)
4441 struct entity
*entity
= &entities
->base
[i
];
4442 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4444 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4445 struct comclassredirect_data
*comclass
;
4446 struct guid_index
*guid_index
;
4450 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4451 RtlGUIDFromString(&str
, &clsid
);
4453 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4454 comclass
= get_comclass_data(actctx
, guid_index
);
4456 if (entity
->u
.comclass
.progid
)
4457 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4458 index
, data_offset
, global_offset
, rosterindex
);
4460 for (j
= 0; j
< progids
->num
; j
++)
4461 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4462 index
, data_offset
, global_offset
, rosterindex
);
4467 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4469 unsigned int i
, j
, total_len
= 0, count
= 0;
4470 struct strsection_header
*header
;
4471 ULONG data_offset
, global_offset
;
4472 struct string_index
*index
;
4474 /* compute section length */
4475 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4477 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4479 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4480 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4482 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4483 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4487 total_len
+= sizeof(*header
);
4489 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4490 if (!header
) return STATUS_NO_MEMORY
;
4492 memset(header
, 0, sizeof(*header
));
4493 header
->magic
= STRSECTION_MAGIC
;
4494 header
->size
= sizeof(*header
);
4495 header
->count
= count
;
4496 header
->global_offset
= header
->size
;
4497 header
->global_len
= count
*sizeof(GUID
);
4498 header
->index_offset
= header
->size
+ header
->global_len
;
4500 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4501 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4502 global_offset
= header
->global_offset
;
4504 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4506 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4508 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4509 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4511 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4512 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4518 return STATUS_SUCCESS
;
4521 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4523 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4526 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4527 PACTCTX_SECTION_KEYED_DATA data
)
4529 struct progidredirect_data
*progid
;
4530 struct string_index
*index
;
4532 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4534 if (!actctx
->comserver_section
)
4536 struct guidsection_header
*section
;
4538 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4539 if (status
) return status
;
4541 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4542 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4545 if (!actctx
->progid_section
)
4547 struct strsection_header
*section
;
4549 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4550 if (status
) return status
;
4552 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4553 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4556 index
= find_string_index(actctx
->progid_section
, name
);
4557 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4561 progid
= get_progid_data(actctx
, index
);
4563 data
->ulDataFormatVersion
= 1;
4564 data
->lpData
= progid
;
4565 data
->ulLength
= progid
->size
;
4566 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4567 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4568 data
->lpSectionBase
= actctx
->progid_section
;
4569 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4570 data
->hActCtx
= NULL
;
4572 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4573 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4576 return STATUS_SUCCESS
;
4579 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4580 const UNICODE_STRING
*section_name
,
4581 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4585 switch (section_kind
)
4587 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4588 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4589 return STATUS_SXS_KEY_NOT_FOUND
;
4590 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4591 status
= find_dll_redirection(actctx
, section_name
, data
);
4593 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4594 status
= find_window_class(actctx
, section_name
, data
);
4596 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4597 status
= find_progid_redirection(actctx
, section_name
, data
);
4599 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4600 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4601 return STATUS_SXS_SECTION_NOT_FOUND
;
4603 DPRINT1("Unknown section_kind %x\n", section_kind
);
4604 return STATUS_SXS_SECTION_NOT_FOUND
;
4607 if (status
!= STATUS_SUCCESS
) return status
;
4609 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4611 actctx_addref(actctx
);
4612 data
->hActCtx
= actctx
;
4614 return STATUS_SUCCESS
;
4617 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4618 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4622 switch (section_kind
)
4624 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4625 status
= find_tlib_redirection(actctx
, guid
, data
);
4627 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4628 status
= find_comserver_redirection(actctx
, guid
, data
);
4630 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4631 status
= find_cominterface_redirection(actctx
, guid
, data
);
4633 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4634 status
= find_clr_surrogate(actctx
, guid
, data
);
4637 DPRINT("Unknown section_kind %x\n", section_kind
);
4638 return STATUS_SXS_SECTION_NOT_FOUND
;
4641 if (status
!= STATUS_SUCCESS
) return status
;
4643 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4645 actctx_addref(actctx
);
4646 data
->hActCtx
= actctx
;
4648 return STATUS_SUCCESS
;
4651 /* initialize the activation context for the current process */
4652 void actctx_init(void)
4657 ctx
.cbSize
= sizeof(ctx
);
4658 ctx
.lpSource
= NULL
;
4659 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4660 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4661 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4663 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4665 process_actctx
= check_actctx(handle
);
4669 /* FUNCTIONS ***************************************************************/
4671 /***********************************************************************
4672 * RtlCreateActivationContext (NTDLL.@)
4674 * Create an activation context.
4678 RtlCreateActivationContext(IN ULONG Flags
,
4679 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4680 IN ULONG ExtraBytes
,
4681 IN PVOID NotificationRoutine
,
4682 IN PVOID NotificationContext
,
4683 OUT PACTIVATION_CONTEXT
*ActCtx
)
4685 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4686 const WCHAR
*directory
= NULL
;
4687 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4688 ACTIVATION_CONTEXT
*actctx
;
4689 UNICODE_STRING nameW
;
4691 NTSTATUS status
= STATUS_NO_MEMORY
;
4693 struct actctx_loader acl
;
4695 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4697 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4698 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4699 return STATUS_INVALID_PARAMETER
;
4702 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4703 return STATUS_NO_MEMORY
;
4705 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4707 actctx
= &ActualActCtx
->ActivationContext
;
4708 actctx
->RefCount
= 1;
4709 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4710 actctx
->config
.info
= NULL
;
4711 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4712 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4714 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4722 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4723 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4725 status
= get_module_filename( module
, &dir
, 0 );
4726 if (!NT_SUCCESS(status
)) goto error
;
4727 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4728 actctx
->appdir
.info
= dir
.Buffer
;
4731 nameW
.Buffer
= NULL
;
4733 /* open file only if it's going to be used */
4734 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4735 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4737 WCHAR
*source
= NULL
;
4740 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4741 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
4743 DWORD dir_len
, source_len
;
4745 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4746 source_len
= strlenW(pActCtx
->lpSource
);
4747 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4749 status
= STATUS_NO_MEMORY
;
4753 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4754 source
[dir_len
] = '\\';
4755 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4758 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4759 RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
4762 status
= STATUS_NO_SUCH_FILE
;
4765 status
= open_nt_file( &file
, &nameW
);
4766 if (!NT_SUCCESS(status
))
4768 RtlFreeUnicodeString( &nameW
);
4773 acl
.actctx
= actctx
;
4774 acl
.dependencies
= NULL
;
4775 acl
.num_dependencies
= 0;
4776 acl
.allocated_dependencies
= 0;
4778 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4779 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4781 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4783 /* if we have a resource it's a PE file */
4784 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4786 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4787 pActCtx
->lpResourceName
, lang
);
4788 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4789 /* FIXME: what to do if pActCtx->lpSource is set */
4790 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4791 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4793 else if (pActCtx
->lpSource
)
4795 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4796 file
, pActCtx
->lpResourceName
, lang
);
4797 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4798 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4799 NULL
, pActCtx
->lpResourceName
);
4801 else status
= STATUS_INVALID_PARAMETER
;
4805 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4808 if (file
) NtClose( file
);
4809 RtlFreeUnicodeString( &nameW
);
4811 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
4812 free_depend_manifests( &acl
);
4814 if (NT_SUCCESS(status
))
4816 else actctx_release( actctx
);
4820 if (file
) NtClose( file
);
4821 actctx_release( actctx
);
4826 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4830 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
4832 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
4833 LONG OldRefCount
, NewRefCount
;
4835 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4837 RtlpValidateActCtx(ActCtx
);
4841 OldRefCount
= ActCtx
->RefCount
;
4842 ASSERT(OldRefCount
> 0);
4844 if (OldRefCount
== LONG_MAX
) break;
4846 NewRefCount
= OldRefCount
+ 1;
4847 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
4849 OldRefCount
) == OldRefCount
)
4855 NewRefCount
= LONG_MAX
;
4856 ASSERT(NewRefCount
> 0);
4862 RtlReleaseActivationContext( HANDLE handle
)
4864 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
4866 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4868 RtlpValidateActCtx(ActCtx
);
4870 actctx_release(ActCtx
);
4875 /***********************************************************************
4876 * RtlAddRefActivationContext (NTDLL.@)
4878 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
4880 ACTIVATION_CONTEXT
*actctx
;
4882 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4886 /******************************************************************
4887 * RtlReleaseActivationContext (NTDLL.@)
4889 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
4891 ACTIVATION_CONTEXT
*actctx
;
4893 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4898 /******************************************************************
4899 * RtlZombifyActivationContext (NTDLL.@)
4902 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
4906 if (Context
== ACTCTX_FAKE_HANDLE
)
4907 return STATUS_SUCCESS
;
4909 return STATUS_NOT_IMPLEMENTED
;
4913 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
4915 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4917 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
4918 return STATUS_NO_MEMORY
;
4920 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
4921 frame
->ActivationContext
= handle
;
4924 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4925 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
4928 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
4929 RtlAddRefActivationContext( handle
);
4931 *cookie
= (ULONG_PTR
)frame
;
4932 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
4933 return STATUS_SUCCESS
;
4936 /******************************************************************
4937 * RtlActivateActivationContext (NTDLL.@)
4939 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
4941 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
4944 /***********************************************************************
4945 * RtlDeactivateActivationContext (NTDLL.@)
4947 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4949 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4951 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
4953 /* find the right frame */
4954 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
4955 for (frame
= top
; frame
; frame
= frame
->Previous
)
4956 if ((ULONG_PTR
)frame
== cookie
) break;
4959 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4961 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
4962 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4964 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4965 NtCurrentTeb()->ActivationContextStackPointer
,
4966 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
4969 /* pop everything up to and including frame */
4970 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
4972 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
4974 frame
= top
->Previous
;
4975 RtlReleaseActivationContext( top
->ActivationContext
);
4976 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
4980 return STATUS_SUCCESS
;
4985 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
4987 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
4989 /* Nothing to do if there is no stack */
4992 /* Get the current active frame */
4993 ActiveFrame
= Stack
->ActiveFrame
;
4995 /* Go through them in backwards order and release */
4998 PrevFrame
= ActiveFrame
->Previous
;
4999 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5000 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5001 ActiveFrame
= PrevFrame
;
5004 /* Zero out the active frame */
5005 Stack
->ActiveFrame
= NULL
;
5007 /* TODO: Empty the Frame List Cache */
5008 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5010 /* Free activation stack memory */
5011 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5014 /******************************************************************
5015 * RtlFreeThreadActivationContextStack (NTDLL.@)
5017 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5019 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5020 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5024 /******************************************************************
5025 * RtlGetActiveActivationContext (NTDLL.@)
5027 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5029 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5031 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5032 RtlAddRefActivationContext( *handle
);
5037 return STATUS_SUCCESS
;
5041 /******************************************************************
5042 * RtlIsActivationContextActive (NTDLL.@)
5044 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5046 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5048 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5049 if (frame
->ActivationContext
== handle
) return TRUE
;
5054 /***********************************************************************
5055 * RtlQueryInformationActivationContext (NTDLL.@)
5057 * Get information about an activation context.
5058 * FIXME: function signature/prototype may be wrong
5060 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5061 ULONG
class, PVOID buffer
,
5062 SIZE_T bufsize
, SIZE_T
*retlen
)
5064 ACTIVATION_CONTEXT
*actctx
;
5067 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5068 subinst
, class, buffer
, bufsize
, retlen
);
5070 if (retlen
) *retlen
= 0;
5071 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5075 case ActivationContextBasicInformation
:
5077 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5079 if (retlen
) *retlen
= sizeof(*info
);
5080 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5082 info
->hActCtx
= handle
;
5083 info
->dwFlags
= 0; /* FIXME */
5084 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5088 case ActivationContextDetailedInformation
:
5090 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5091 struct assembly
*assembly
= NULL
;
5092 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5095 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5097 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5099 if (assembly
&& assembly
->manifest
.info
)
5100 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5101 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5102 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5103 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5105 if (retlen
) *retlen
= len
;
5106 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5109 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5110 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5111 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5112 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5113 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5114 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5115 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5116 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5117 ptr
= (LPWSTR
)(acdi
+ 1);
5120 acdi
->lpRootManifestPath
= ptr
;
5121 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5122 ptr
+= manifest_len
;
5124 else acdi
->lpRootManifestPath
= NULL
;
5127 acdi
->lpRootConfigurationPath
= ptr
;
5128 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5131 else acdi
->lpRootConfigurationPath
= NULL
;
5134 acdi
->lpAppDirPath
= ptr
;
5135 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5137 else acdi
->lpAppDirPath
= NULL
;
5141 case AssemblyDetailedInformationInActivationContext
:
5143 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5144 struct assembly
*assembly
;
5147 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5150 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5151 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5153 index
= *(DWORD
*)subinst
;
5154 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5156 assembly
= &actctx
->assemblies
[index
- 1];
5158 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5159 id_len
= strlenW(assembly_id
) + 1;
5160 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5162 if (assembly
->manifest
.info
&&
5163 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5164 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5166 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5168 if (retlen
) *retlen
= len
;
5169 if (!buffer
|| bufsize
< len
)
5171 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5172 return STATUS_BUFFER_TOO_SMALL
;
5175 afdi
->ulFlags
= 0; /* FIXME */
5176 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5177 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5178 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5179 /* FIXME afdi->liManifestLastWriteTime = 0; */
5180 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5181 afdi
->ulPolicyPathLength
= 0;
5182 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5183 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5184 afdi
->ulManifestVersionMajor
= 1;
5185 afdi
->ulManifestVersionMinor
= 0;
5186 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5187 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5188 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5189 ptr
= (LPWSTR
)(afdi
+ 1);
5190 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5191 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5195 afdi
->lpAssemblyManifestPath
= ptr
;
5196 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5198 } else afdi
->lpAssemblyManifestPath
= NULL
;
5199 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5202 afdi
->lpAssemblyDirectoryName
= ptr
;
5203 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5205 else afdi
->lpAssemblyDirectoryName
= NULL
;
5206 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5210 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5212 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5213 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5214 struct assembly
*assembly
;
5215 struct dll_redirect
*dll
;
5216 SIZE_T len
, dll_len
= 0;
5219 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5220 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5222 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5223 return STATUS_INVALID_PARAMETER
;
5224 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5226 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5227 return STATUS_INVALID_PARAMETER
;
5228 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5230 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5231 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5233 if (!buffer
|| bufsize
< len
)
5235 if (retlen
) *retlen
= len
;
5236 return STATUS_BUFFER_TOO_SMALL
;
5238 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5239 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5240 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5241 afdi
->ulPathLength
= 0; /* FIXME */
5242 ptr
= (LPWSTR
)(afdi
+ 1);
5245 afdi
->lpFileName
= ptr
;
5246 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5247 } else afdi
->lpFileName
= NULL
;
5248 afdi
->lpFilePath
= NULL
; /* FIXME */
5253 DPRINT( "class %u not implemented\n", class );
5254 return STATUS_NOT_IMPLEMENTED
;
5256 return STATUS_SUCCESS
;
5261 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5263 SIZE_T cbBuffer OPTIONAL
,
5264 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5266 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5272 pcbWrittenOrRequired
);
5275 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5276 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5277 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5281 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5282 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5284 /* Check general parameter combinations */
5285 if (!section_name
|| !section_name
->Buffer
||
5286 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5287 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5288 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5290 DPRINT1("invalid parameter\n");
5291 return STATUS_INVALID_PARAMETER
;
5295 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5296 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5298 DPRINT1("unknown flags %08x\n", flags
);
5299 return STATUS_INVALID_PARAMETER
;
5302 return STATUS_SUCCESS
;
5305 /***********************************************************************
5306 * RtlFindActivationContextSectionString (NTDLL.@)
5308 * Find information about a string in an activation context.
5309 * FIXME: function signature/prototype may be wrong
5311 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5312 const UNICODE_STRING
*section_name
, PVOID ptr
)
5314 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5317 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5318 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5319 if (!NT_SUCCESS(status
))
5321 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5325 status
= STATUS_SXS_KEY_NOT_FOUND
;
5327 /* if there is no data, but params are valid,
5328 we return that sxs key is not found to be at least somehow compatible */
5331 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5335 ASSERT(NtCurrentTeb());
5336 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5338 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5339 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5341 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5342 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5345 DPRINT("status %x\n", status
);
5346 if (status
!= STATUS_SUCCESS
)
5347 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5349 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5353 /***********************************************************************
5354 * RtlFindActivationContextSectionGuid (NTDLL.@)
5356 * Find information about a GUID in an activation context.
5357 * FIXME: function signature/prototype may be wrong
5359 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5360 const GUID
*guid
, void *ptr
)
5362 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5363 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5367 DPRINT1("expected extguid == NULL\n");
5368 return STATUS_INVALID_PARAMETER
;
5371 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5373 DPRINT1("unknown flags %08x\n", flags
);
5374 return STATUS_INVALID_PARAMETER
;
5377 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5378 return STATUS_INVALID_PARAMETER
;
5380 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5382 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5383 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5386 if (status
!= STATUS_SUCCESS
)
5387 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5396 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5398 PACTIVATION_CONTEXT_STACK ContextStack
;
5400 /* Check if it's already allocated */
5401 if (*Stack
) return STATUS_SUCCESS
;
5403 /* Allocate space for the context stack */
5404 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5407 return STATUS_NO_MEMORY
;
5410 /* Initialize the context stack */
5411 ContextStack
->Flags
= 0;
5412 ContextStack
->ActiveFrame
= NULL
;
5413 InitializeListHead(&ContextStack
->FrameListCache
);
5414 ContextStack
->NextCookieSequenceNumber
= 1;
5415 ContextStack
->StackId
= 1; //TODO: Timer-based
5417 *Stack
= ContextStack
;
5419 return STATUS_SUCCESS
;
5422 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5424 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5427 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5428 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5430 /* Get the current active frame */
5431 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5433 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5434 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5435 &Frame
->Frame
, Context
);
5437 /* Ensure it's in the right format and at least fits basic info */
5438 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5439 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5441 /* Set debug info if size allows*/
5442 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5444 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5445 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5446 //Frame->Extra3 = ...;
5451 /*ASSERT((ActiveFrame->Flags &
5452 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5453 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5454 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5456 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5458 // TODO: Perform some additional checks if it was not heap allocated
5462 /* Save pointer to the new activation frame */
5463 NewFrame
= &Frame
->Frame
;
5465 /* Actually activate it */
5466 Frame
->Frame
.Previous
= ActiveFrame
;
5467 Frame
->Frame
.ActivationContext
= Context
;
5468 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5470 /* Check if we can activate this context */
5471 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5474 /* Set new active frame */
5475 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5476 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5480 /* We can get here only one way: it was already activated */
5481 DPRINT("Trying to activate already activated activation context\n");
5483 /* Activate only if we are allowing multiple activation */
5485 if (!RtlpNotAllowingMultipleActivation
)
5487 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5488 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5491 // Activate it anyway
5492 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5495 /* Return pointer to the activation frame */
5499 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5501 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5503 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5505 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5507 /* Ensure it's in the right format and at least fits basic info */
5508 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5509 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5511 /* Make sure it is not deactivated and it is activated */
5512 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5513 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5514 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
);
5516 /* Check debug info if it is present */
5517 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5519 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5520 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5521 //Frame->Extra3 = ...;
5526 // TODO: Perform some additional checks here
5529 /* Special handling for not-really-activated */
5530 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5532 DPRINT1("Deactivating not really activated activation context\n");
5533 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5534 return &Frame
->Frame
;
5537 /* find the right frame */
5538 NewFrame
= &Frame
->Frame
;
5539 if (ActiveFrame
!= NewFrame
)
5541 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5544 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5545 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5547 /* Pop everything up to and including frame */
5548 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5550 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5551 return NewFrame
->Previous
;