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((PVOID
)buffer
, (ULONG
)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
,
2583 GENERIC_READ
| SYNCHRONIZE
,
2586 FILE_SYNCHRONOUS_IO_ALERT
);
2589 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2593 LDR_DATA_TABLE_ENTRY
*pldr
;
2595 LdrLockLoaderLock(0, NULL
, &magic
);
2596 status
= LdrFindEntryForAddress( module
, &pldr
);
2597 if (status
== STATUS_SUCCESS
)
2599 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2600 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2602 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2603 str
->Length
= pldr
->FullDllName
.Length
;
2604 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2606 else status
= STATUS_NO_MEMORY
;
2608 LdrUnlockLoaderLock(0, magic
);
2612 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2613 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2614 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2617 UNICODE_STRING nameW
;
2618 LDR_RESOURCE_INFO info
;
2619 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2622 //DPRINT( "looking for res %s in module %p %s\n", resname,
2623 // hModule, filename );
2624 DPRINT("get_manifest_in_module %p\n", hModule
);
2627 if (TRACE_ON(actctx
))
2629 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2631 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2632 hModule
, debugstr_w(nameW
.Buffer
) );
2633 RtlFreeUnicodeString( &nameW
);
2635 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2636 hModule
, debugstr_w(filename
) );
2640 if (!resname
) return STATUS_INVALID_PARAMETER
;
2642 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2643 info
.Language
= lang
;
2644 if (!((ULONG_PTR
)resname
>> 16))
2646 info
.Name
= (ULONG_PTR
)resname
;
2647 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2649 else if (resname
[0] == '#')
2652 RtlInitUnicodeString(&nameW
, resname
+ 1);
2653 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2654 return STATUS_INVALID_PARAMETER
;
2656 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2660 RtlCreateUnicodeString(&nameW
, resname
);
2661 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2662 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2663 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2664 RtlFreeUnicodeString(&nameW
);
2666 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2668 if (status
== STATUS_SUCCESS
)
2669 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2674 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2675 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2676 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2679 OBJECT_ATTRIBUTES attr
;
2681 LARGE_INTEGER offset
;
2686 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2688 attr
.Length
= sizeof(attr
);
2689 attr
.RootDirectory
= 0;
2690 attr
.ObjectName
= NULL
;
2691 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2692 attr
.SecurityDescriptor
= NULL
;
2693 attr
.SecurityQualityOfService
= NULL
;
2696 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2697 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2698 if (status
!= STATUS_SUCCESS
) return status
;
2700 offset
.QuadPart
= 0;
2703 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2704 &count
, ViewShare
, 0, PAGE_READONLY
);
2706 if (status
!= STATUS_SUCCESS
) return status
;
2708 if (RtlImageNtHeader(base
)) /* we got a PE file */
2710 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2711 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2713 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2715 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2719 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2720 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2722 FILE_STANDARD_INFORMATION info
;
2725 OBJECT_ATTRIBUTES attr
;
2727 LARGE_INTEGER offset
;
2732 DPRINT( "loading manifest file %S\n", filename
);
2734 attr
.Length
= sizeof(attr
);
2735 attr
.RootDirectory
= 0;
2736 attr
.ObjectName
= NULL
;
2737 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2738 attr
.SecurityDescriptor
= NULL
;
2739 attr
.SecurityQualityOfService
= NULL
;
2742 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2743 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2745 if (status
!= STATUS_SUCCESS
) return status
;
2747 offset
.QuadPart
= 0;
2750 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2751 &count
, ViewShare
, 0, PAGE_READONLY
);
2753 if (status
!= STATUS_SUCCESS
) return status
;
2755 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2756 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
2758 if (status
== STATUS_SUCCESS
)
2759 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
2761 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2765 /* try to load the .manifest file associated to the file */
2766 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2767 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2769 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2772 UNICODE_STRING nameW
;
2774 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2776 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2778 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
2780 if (module
) /* use the module filename */
2782 UNICODE_STRING name
;
2784 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2786 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2787 strcatW( name
.Buffer
, dotManifestW
);
2788 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2789 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2790 RtlFreeUnicodeString( &name
);
2792 if (status
) return status
;
2796 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2797 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2798 return STATUS_NO_MEMORY
;
2799 strcpyW( buffer
, filename
);
2800 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2801 strcatW( buffer
, dotManifestW
);
2802 RtlInitUnicodeString( &nameW
, buffer
);
2805 if (!open_nt_file( &file
, &nameW
))
2807 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2810 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2811 RtlFreeUnicodeString( &nameW
);
2815 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2817 static const WCHAR lookup_fmtW
[] =
2818 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2819 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2820 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2822 WCHAR
*lookup
, *ret
= NULL
;
2823 UNICODE_STRING lookup_us
;
2825 const WCHAR
*lang
= ai
->language
;
2826 unsigned int data_pos
= 0, data_len
;
2829 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2830 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2831 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2832 + sizeof(lookup_fmtW
) )))
2835 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2836 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2837 ai
->version
.major
, ai
->version
.minor
, lang
);
2838 RtlInitUnicodeString( &lookup_us
, lookup
);
2840 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2841 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2842 if (io
.Status
== STATUS_SUCCESS
)
2844 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2845 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2847 ULONG build
, revision
;
2849 data_len
= (ULONG
)io
.Information
;
2853 if (data_pos
>= data_len
)
2855 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2856 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2857 if (io
.Status
!= STATUS_SUCCESS
) break;
2858 data_len
= (ULONG
)io
.Information
;
2861 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2863 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2864 else data_pos
= data_len
;
2866 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2868 if (build
< min_build
) continue;
2869 tmp
= strchrW(tmp
, '.') + 1;
2870 revision
= atoiW(tmp
);
2871 if (build
== min_build
&& revision
< min_revision
) continue;
2872 tmp
= strchrW(tmp
, '_') + 1;
2873 tmp
= strchrW(tmp
, '_') + 1;
2874 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2875 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2877 /* prefer a non-Wine manifest if we already have one */
2878 /* we'll still load the builtin dll if specified through DllOverrides */
2884 min_revision
= revision
;
2886 ai
->version
.build
= build
;
2887 ai
->version
.revision
= revision
;
2888 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
2889 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2891 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2892 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2896 else DPRINT1("no matching file for %S\n", lookup
);
2897 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
2901 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2903 struct assembly_identity sxs_ai
;
2904 UNICODE_STRING path_us
;
2905 OBJECT_ATTRIBUTES attr
;
2907 WCHAR
*path
, *file
= NULL
;
2910 static const WCHAR manifest_dirW
[] =
2911 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2913 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2915 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2916 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
2917 return STATUS_NO_MEMORY
;
2919 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
2920 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
2922 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2924 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2925 return STATUS_NO_SUCH_FILE
;
2927 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2929 attr
.Length
= sizeof(attr
);
2930 attr
.RootDirectory
= 0;
2931 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2932 attr
.ObjectName
= &path_us
;
2933 attr
.SecurityDescriptor
= NULL
;
2934 attr
.SecurityQualityOfService
= NULL
;
2936 if (!NtOpenFile(&handle
,
2937 GENERIC_READ
| SYNCHRONIZE
,
2939 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2940 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2943 file
= lookup_manifest_file( handle
, &sxs_ai
);
2948 RtlFreeUnicodeString( &path_us
);
2949 return STATUS_NO_SUCH_FILE
;
2952 /* append file name to directory path */
2953 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
2954 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2956 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2957 RtlFreeUnicodeString( &path_us
);
2958 return STATUS_NO_MEMORY
;
2961 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2962 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2963 RtlInitUnicodeString( &path_us
, path
);
2964 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2966 if (!open_nt_file( &handle
, &path_us
))
2968 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2971 else io
.Status
= STATUS_NO_SUCH_FILE
;
2973 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2974 RtlFreeUnicodeString( &path_us
);
2978 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2979 struct assembly_identity
* ai
)
2981 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2983 WCHAR
*buffer
, *p
, *directory
;
2985 UNICODE_STRING nameW
;
2989 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2990 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
2992 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2994 /* FIXME: add support for language specific lookup */
2996 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2997 strlenW(acl
->actctx
->appdir
.info
));
2999 nameW
.Buffer
= NULL
;
3000 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
3001 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3002 return STATUS_NO_MEMORY
;
3004 if (!(directory
= build_assembly_dir( ai
)))
3006 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3007 return STATUS_NO_MEMORY
;
3010 /* Lookup in <dir>\name.dll
3011 * <dir>\name.manifest
3012 * <dir>\name\name.dll
3013 * <dir>\name\name.manifest
3015 * First 'appdir' is used as <dir>, if that failed
3016 * it tries application manifest file path.
3018 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3019 p
= buffer
+ strlenW(buffer
);
3020 for (i
= 0; i
< 4; i
++)
3024 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3025 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3029 strcpyW( p
, ai
->name
);
3032 strcpyW( p
, dotDllW
);
3033 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3035 status
= open_nt_file( &file
, &nameW
);
3038 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3039 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3043 RtlFreeUnicodeString( &nameW
);
3046 strcpyW( p
, dotManifestW
);
3047 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3049 status
= open_nt_file( &file
, &nameW
);
3052 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3056 RtlFreeUnicodeString( &nameW
);
3058 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3060 RtlFreeUnicodeString( &nameW
);
3061 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3062 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3066 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3068 NTSTATUS status
= STATUS_SUCCESS
;
3071 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3073 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3075 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3077 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3078 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3079 acl
->dependencies
[i
].name
,
3080 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3081 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3086 /* FIXME should now iterate through all refs */
3090 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3091 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3093 NTSTATUS status
= STATUS_SUCCESS
;
3095 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3097 if (*handle
) return STATUS_INVALID_PARAMETER
;
3099 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3100 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3102 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3105 LDR_DATA_TABLE_ENTRY
*pldr
;
3107 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3109 LdrLockLoaderLock( 0, NULL
, &magic
);
3110 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3112 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3113 status
= STATUS_DLL_NOT_FOUND
;
3115 *handle
= pldr
->EntryPointActivationContext
;
3117 else status
= STATUS_DLL_NOT_FOUND
;
3118 LdrUnlockLoaderLock( 0, magic
);
3120 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3121 *handle
= process_actctx
;
3126 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3128 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3129 struct strsection_header
*header
;
3130 struct dllredirect_data
*data
;
3131 struct string_index
*index
;
3134 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3136 /* compute section length */
3137 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3139 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3140 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3142 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3144 /* each entry needs index, data and string data */
3145 total_len
+= sizeof(*index
);
3146 total_len
+= sizeof(*data
);
3147 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3149 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3152 dll_count
+= assembly
->num_dlls
;
3155 total_len
+= sizeof(*header
);
3157 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3158 if (!header
) return STATUS_NO_MEMORY
;
3160 memset(header
, 0, sizeof(*header
));
3161 header
->magic
= STRSECTION_MAGIC
;
3162 header
->size
= sizeof(*header
);
3163 header
->count
= dll_count
;
3164 header
->index_offset
= sizeof(*header
);
3165 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3166 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3168 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3170 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3172 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3174 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3176 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3180 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3181 /* setup new index entry */
3182 str
.Buffer
= dll
->name
;
3183 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3184 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3185 /* hash original class name */
3186 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3188 index
->name_offset
= name_offset
;
3189 index
->name_len
= str
.Length
;
3190 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3191 index
->data_len
= sizeof(*data
);
3192 index
->rosterindex
= i
+ 1;
3195 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3196 data
->size
= sizeof(*data
);
3197 data
->unk
= 2; /* FIXME: seems to be constant */
3198 memset(data
->res
, 0, sizeof(data
->res
));
3201 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3202 memcpy(ptrW
, dll
->name
, index
->name_len
);
3203 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3205 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3213 return STATUS_SUCCESS
;
3216 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3218 struct string_index
*iter
, *index
= NULL
;
3221 DPRINT("section %p, name %wZ\n", section
, name
);
3222 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3223 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3225 for (i
= 0; i
< section
->count
; i
++)
3227 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3228 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3229 if (iter
->hash
== hash
)
3231 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3233 if (!strcmpiW(nameW
, name
->Buffer
))
3239 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3247 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3249 struct guid_index
*iter
, *index
= NULL
;
3252 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3254 for (i
= 0; i
< section
->count
; i
++)
3256 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3267 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3269 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3272 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3273 PACTCTX_SECTION_KEYED_DATA data
)
3275 struct dllredirect_data
*dll
;
3276 struct string_index
*index
;
3278 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3279 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3281 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3282 if (!actctx
->dllredirect_section
)
3284 struct strsection_header
*section
;
3286 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3287 if (status
) return status
;
3289 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3290 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3293 index
= find_string_index(actctx
->dllredirect_section
, name
);
3294 DPRINT("index: %d\n", index
);
3295 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3299 dll
= get_dllredirect_data(actctx
, index
);
3301 data
->ulDataFormatVersion
= 1;
3303 data
->ulLength
= dll
->size
;
3304 data
->lpSectionGlobalData
= NULL
;
3305 data
->ulSectionGlobalDataLength
= 0;
3306 data
->lpSectionBase
= actctx
->dllredirect_section
;
3307 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3308 data
->hActCtx
= NULL
;
3310 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3311 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3314 return STATUS_SUCCESS
;
3317 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3319 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3322 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3324 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3327 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3329 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3330 struct wndclass_redirect_data
*data
;
3331 struct strsection_header
*header
;
3332 struct string_index
*index
;
3335 /* compute section length */
3336 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3338 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3339 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3341 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3342 for (k
= 0; k
< dll
->entities
.num
; k
++)
3344 struct entity
*entity
= &dll
->entities
.base
[k
];
3345 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3347 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3350 /* each class entry needs index, data and string data */
3351 total_len
+= sizeof(*index
);
3352 total_len
+= sizeof(*data
);
3353 /* original name is stored separately */
3354 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3355 /* versioned name and module name are stored one after another */
3356 if (entity
->u
.class.versioned
)
3357 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3360 len
+= strlenW(dll
->name
) + 1;
3361 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3369 total_len
+= sizeof(*header
);
3371 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3372 if (!header
) return STATUS_NO_MEMORY
;
3374 memset(header
, 0, sizeof(*header
));
3375 header
->magic
= STRSECTION_MAGIC
;
3376 header
->size
= sizeof(*header
);
3377 header
->count
= class_count
;
3378 header
->index_offset
= sizeof(*header
);
3379 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3380 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3382 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3384 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3385 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3387 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3388 for (k
= 0; k
< dll
->entities
.num
; k
++)
3390 struct entity
*entity
= &dll
->entities
.base
[k
];
3391 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3393 static const WCHAR exclW
[] = {'!',0};
3394 ULONG versioned_len
, module_len
;
3398 /* setup new index entry */
3399 str
.Buffer
= entity
->u
.class.name
;
3400 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3401 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3402 /* hash original class name */
3403 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3405 /* include '!' separator too */
3406 if (entity
->u
.class.versioned
)
3407 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3409 versioned_len
= str
.Length
;
3410 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3412 index
->name_offset
= name_offset
;
3413 index
->name_len
= str
.Length
;
3414 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3415 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3416 index
->rosterindex
= i
+ 1;
3419 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3420 data
->size
= sizeof(*data
);
3422 data
->name_len
= versioned_len
;
3423 data
->name_offset
= sizeof(*data
);
3424 data
->module_len
= module_len
;
3425 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3427 /* original class name */
3428 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3429 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3430 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3433 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3434 memcpy(ptrW
, dll
->name
, data
->module_len
);
3435 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3437 /* versioned name */
3438 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3439 if (entity
->u
.class.versioned
)
3441 get_assembly_version(assembly
, ptrW
);
3442 strcatW(ptrW
, exclW
);
3443 strcatW(ptrW
, entity
->u
.class.name
);
3447 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3448 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3451 name_offset
+= sizeof(*data
);
3452 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3462 return STATUS_SUCCESS
;
3465 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3466 PACTCTX_SECTION_KEYED_DATA data
)
3468 struct string_index
*iter
, *index
= NULL
;
3469 struct wndclass_redirect_data
*class;
3473 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3475 if (!actctx
->wndclass_section
)
3477 struct strsection_header
*section
;
3479 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3480 if (status
) return status
;
3482 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3483 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3487 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3488 iter
= get_wndclass_first_index(actctx
);
3490 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3492 if (iter
->hash
== hash
)
3494 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3496 if (!strcmpiW(nameW
, name
->Buffer
))
3502 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3507 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3511 class = get_wndclass_data(actctx
, index
);
3513 data
->ulDataFormatVersion
= 1;
3514 data
->lpData
= class;
3515 /* full length includes string length with nulls */
3516 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3517 data
->lpSectionGlobalData
= NULL
;
3518 data
->ulSectionGlobalDataLength
= 0;
3519 data
->lpSectionBase
= actctx
->wndclass_section
;
3520 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3521 data
->hActCtx
= NULL
;
3523 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3524 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3527 return STATUS_SUCCESS
;
3530 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3532 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3533 struct guidsection_header
*header
;
3534 ULONG module_offset
, data_offset
;
3535 struct tlibredirect_data
*data
;
3536 struct guid_index
*index
;
3538 /* compute section length */
3539 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3541 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3542 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3544 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3545 for (k
= 0; k
< dll
->entities
.num
; k
++)
3547 struct entity
*entity
= &dll
->entities
.base
[k
];
3548 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3550 /* each entry needs index, data and string data for module name and help string */
3551 total_len
+= sizeof(*index
);
3552 total_len
+= sizeof(*data
);
3553 /* help string is stored separately */
3554 if (*entity
->u
.typelib
.helpdir
)
3555 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3557 /* module names are packed one after another */
3558 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3566 total_len
+= aligned_string_len(names_len
);
3567 total_len
+= sizeof(*header
);
3569 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3570 if (!header
) return STATUS_NO_MEMORY
;
3572 memset(header
, 0, sizeof(*header
));
3573 header
->magic
= GUIDSECTION_MAGIC
;
3574 header
->size
= sizeof(*header
);
3575 header
->count
= tlib_count
;
3576 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3577 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3578 module_offset
= sizeof(*header
);
3579 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3581 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3583 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3584 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3586 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3587 for (k
= 0; k
< dll
->entities
.num
; k
++)
3589 struct entity
*entity
= &dll
->entities
.base
[k
];
3590 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3592 ULONG module_len
, help_len
;
3596 if (*entity
->u
.typelib
.helpdir
)
3597 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3601 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3603 /* setup new index entry */
3604 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3605 RtlGUIDFromString(&str
, &index
->guid
);
3606 index
->data_offset
= data_offset
;
3607 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3608 index
->rosterindex
= i
+ 1;
3611 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3612 data
->size
= sizeof(*data
);
3614 data
->name_len
= module_len
;
3615 data
->name_offset
= module_offset
;
3616 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3618 data
->flags
= entity
->u
.typelib
.flags
;
3619 data
->help_len
= help_len
;
3620 data
->help_offset
= sizeof(*data
);
3621 data
->major_version
= entity
->u
.typelib
.major
;
3622 data
->minor_version
= entity
->u
.typelib
.minor
;
3625 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3626 memcpy(ptrW
, dll
->name
, data
->name_len
);
3627 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3632 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3633 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3634 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3637 data_offset
+= sizeof(*data
);
3639 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3641 module_offset
+= module_len
+ sizeof(WCHAR
);
3651 return STATUS_SUCCESS
;
3654 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3656 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3659 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3661 struct guid_index
*index
= NULL
;
3662 struct tlibredirect_data
*tlib
;
3664 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3666 if (!actctx
->tlib_section
)
3668 struct guidsection_header
*section
;
3670 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3671 if (status
) return status
;
3673 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3674 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3677 index
= find_guid_index(actctx
->tlib_section
, guid
);
3678 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3680 tlib
= get_tlib_data(actctx
, index
);
3682 data
->ulDataFormatVersion
= 1;
3683 data
->lpData
= tlib
;
3684 /* full length includes string length with nulls */
3685 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3686 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3687 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3688 data
->lpSectionBase
= actctx
->tlib_section
;
3689 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3690 data
->hActCtx
= NULL
;
3692 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3693 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3695 return STATUS_SUCCESS
;
3698 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3700 ULONG
*ptr
= (ULONG
*)guid
;
3703 /* GUID is 16 bytes long */
3704 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3705 *ptr
= RtlUniform(seed
);
3707 guid
->Data3
&= 0x0fff;
3708 guid
->Data3
|= (4 << 12);
3709 guid
->Data4
[0] &= 0x3f;
3710 guid
->Data4
[0] |= 0x80;
3713 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3714 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3718 for (i
= 0; i
< entities
->num
; i
++)
3720 struct entity
*entity
= &entities
->base
[i
];
3721 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3723 /* each entry needs two index entries, extra one goes for alias GUID */
3724 *len
+= 2*sizeof(struct guid_index
);
3725 /* To save some memory we don't allocated two data structures,
3726 instead alias index and normal index point to the same data structure. */
3727 *len
+= sizeof(struct comclassredirect_data
);
3729 /* for clrClass store some more */
3730 if (entity
->u
.comclass
.name
)
3732 unsigned int str_len
;
3734 /* all string data is stored together in aligned block */
3735 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3736 if (entity
->u
.comclass
.progid
)
3737 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3738 if (entity
->u
.comclass
.version
)
3739 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3741 *len
+= sizeof(struct clrclass_data
);
3742 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3744 /* module name is forced to mscoree.dll, and stored two times with different case */
3745 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3749 /* progid string is stored separately */
3750 if (entity
->u
.comclass
.progid
)
3751 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3753 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3761 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3762 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3763 ULONG
*seed
, ULONG rosterindex
)
3767 for (i
= 0; i
< entities
->num
; i
++)
3769 struct entity
*entity
= &entities
->base
[i
];
3770 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3772 ULONG module_len
, progid_len
, str_len
= 0;
3773 struct comclassredirect_data
*data
;
3774 struct guid_index
*alias_index
;
3775 struct clrclass_data
*clrdata
;
3779 if (entity
->u
.comclass
.progid
)
3780 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3784 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3786 /* setup new index entry */
3787 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3788 RtlGUIDFromString(&str
, &(*index
)->guid
);
3790 (*index
)->data_offset
= *data_offset
;
3791 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3792 (*index
)->rosterindex
= rosterindex
;
3794 /* Setup new index entry for alias guid. Alias index records are placed after
3795 normal records, so normal guids are hit first on search. Note that class count
3797 alias_index
= (*index
) + section
->count
/2;
3798 generate_uuid(seed
, &alias_index
->guid
);
3799 alias_index
->data_offset
= (*index
)->data_offset
;
3800 alias_index
->data_len
= 0;
3801 alias_index
->rosterindex
= (*index
)->rosterindex
;
3804 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3805 data
->size
= sizeof(*data
);
3809 data
->model
= entity
->u
.comclass
.model
;
3810 data
->clsid
= (*index
)->guid
;
3811 data
->alias
= alias_index
->guid
;
3812 data
->clsid2
= data
->clsid
;
3813 if (entity
->u
.comclass
.tlbid
)
3815 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3816 RtlGUIDFromString(&str
, &data
->tlbid
);
3819 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3820 data
->name_len
= module_len
;
3821 data
->name_offset
= *module_offset
;
3822 data
->progid_len
= progid_len
;
3823 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3824 data
->clrdata_len
= 0; /* will be set later */
3825 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3826 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3827 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3828 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3829 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3830 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3832 /* mask describes which misc* data is available */
3834 if (data
->miscstatus
)
3835 data
->miscmask
|= MiscStatus
;
3836 if (data
->miscstatuscontent
)
3837 data
->miscmask
|= MiscStatusContent
;
3838 if (data
->miscstatusthumbnail
)
3839 data
->miscmask
|= MiscStatusThumbnail
;
3840 if (data
->miscstatusicon
)
3841 data
->miscmask
|= MiscStatusIcon
;
3842 if (data
->miscstatusdocprint
)
3843 data
->miscmask
|= MiscStatusDocPrint
;
3845 if (data
->clrdata_offset
)
3847 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3849 clrdata
->size
= sizeof(*clrdata
);
3850 clrdata
->res
[0] = 0;
3851 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3852 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3853 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3854 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3855 clrdata
->name_offset
= clrdata
->size
;
3856 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3857 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3858 clrdata
->res2
[0] = 0;
3859 clrdata
->res2
[1] = 0;
3861 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3864 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3865 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3866 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3868 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3869 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3870 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3873 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3874 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3875 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3877 /* runtime version, optional */
3878 if (clrdata
->version_len
)
3880 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3882 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3883 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3884 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3887 if (data
->progid_len
)
3888 data
->progid_offset
+= data
->clrdata_len
;
3889 (*index
)->data_len
+= sizeof(*clrdata
);
3896 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3897 memcpy(ptrW
, dll
->name
, data
->name_len
);
3898 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3902 if (data
->progid_len
)
3904 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3905 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3906 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3909 /* string block length */
3913 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3914 if (clrdata
->version_len
)
3915 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3918 str_len
+= progid_len
+ sizeof(WCHAR
);
3920 (*index
)->data_len
+= aligned_string_len(str_len
);
3921 alias_index
->data_len
= (*index
)->data_len
;
3923 /* move to next data record */
3924 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3925 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3929 (*data_offset
) += sizeof(*clrdata
);
3930 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3937 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3939 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3940 struct guidsection_header
*header
;
3941 ULONG module_offset
, data_offset
;
3942 struct guid_index
*index
;
3945 /* compute section length */
3946 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3948 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3949 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3950 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3952 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3953 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3957 total_len
+= aligned_string_len(names_len
);
3958 total_len
+= sizeof(*header
);
3960 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3961 if (!header
) return STATUS_NO_MEMORY
;
3963 memset(header
, 0, sizeof(*header
));
3964 header
->magic
= GUIDSECTION_MAGIC
;
3965 header
->size
= sizeof(*header
);
3966 header
->count
= 2*class_count
;
3967 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3968 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3969 module_offset
= sizeof(*header
);
3970 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3972 seed
= NtGetTickCount();
3973 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3975 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3976 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3977 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3979 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3980 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3986 return STATUS_SUCCESS
;
3989 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3991 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3994 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3996 struct comclassredirect_data
*comclass
;
3997 struct guid_index
*index
= NULL
;
3999 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4001 if (!actctx
->comserver_section
)
4003 struct guidsection_header
*section
;
4005 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4006 if (status
) return status
;
4008 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4009 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4012 index
= find_guid_index(actctx
->comserver_section
, guid
);
4013 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4015 comclass
= get_comclass_data(actctx
, index
);
4017 data
->ulDataFormatVersion
= 1;
4018 data
->lpData
= comclass
;
4019 /* full length includes string length with nulls */
4020 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4021 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4022 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4023 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4024 data
->lpSectionBase
= actctx
->comserver_section
;
4025 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4026 data
->hActCtx
= NULL
;
4028 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4029 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4031 return STATUS_SUCCESS
;
4034 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4038 for (i
= 0; i
< entities
->num
; i
++)
4040 struct entity
*entity
= &entities
->base
[i
];
4041 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4043 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4044 if (entity
->u
.ifaceps
.name
)
4045 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4051 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4052 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4056 for (i
= 0; i
< entities
->num
; i
++)
4058 struct entity
*entity
= &entities
->base
[i
];
4059 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4061 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4065 if (entity
->u
.ifaceps
.name
)
4066 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4071 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4072 RtlGUIDFromString(&str
, &(*index
)->guid
);
4073 (*index
)->data_offset
= *data_offset
;
4074 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4075 (*index
)->rosterindex
= rosterindex
;
4077 /* setup data record */
4078 data
->size
= sizeof(*data
);
4079 data
->mask
= entity
->u
.ifaceps
.mask
;
4081 /* proxyStubClsid32 value is only stored for external PS,
4082 if set it's used as iid, otherwise 'iid' attribute value is used */
4083 if (entity
->u
.ifaceps
.ps32
)
4085 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4086 RtlGUIDFromString(&str
, &data
->iid
);
4089 data
->iid
= (*index
)->guid
;
4091 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4093 if (entity
->u
.ifaceps
.tlib
)
4095 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4096 RtlGUIDFromString(&str
, &data
->tlbid
);
4099 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4101 if (entity
->u
.ifaceps
.base
)
4103 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4104 RtlGUIDFromString(&str
, &data
->base
);
4107 memset(&data
->base
, 0, sizeof(data
->base
));
4109 data
->name_len
= name_len
;
4110 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4115 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4116 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4117 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4120 /* move to next record */
4122 *data_offset
+= sizeof(*data
);
4124 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4129 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4131 unsigned int i
, j
, total_len
= 0, count
= 0;
4132 struct guidsection_header
*header
;
4133 struct guid_index
*index
;
4136 /* compute section length */
4137 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4139 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4141 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4142 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4144 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4145 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4149 total_len
+= sizeof(*header
);
4151 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4152 if (!header
) return STATUS_NO_MEMORY
;
4154 memset(header
, 0, sizeof(*header
));
4155 header
->magic
= GUIDSECTION_MAGIC
;
4156 header
->size
= sizeof(*header
);
4157 header
->count
= count
;
4158 header
->index_offset
= sizeof(*header
);
4159 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4160 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4162 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4164 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4166 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4167 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4169 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4170 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4176 return STATUS_SUCCESS
;
4179 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4181 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4184 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4186 struct ifacepsredirect_data
*iface
;
4187 struct guid_index
*index
= NULL
;
4189 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4191 if (!actctx
->ifaceps_section
)
4193 struct guidsection_header
*section
;
4195 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4196 if (status
) return status
;
4198 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4199 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4202 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4203 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4205 iface
= get_ifaceps_data(actctx
, index
);
4207 data
->ulDataFormatVersion
= 1;
4208 data
->lpData
= iface
;
4209 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4210 data
->lpSectionGlobalData
= NULL
;
4211 data
->ulSectionGlobalDataLength
= 0;
4212 data
->lpSectionBase
= actctx
->ifaceps_section
;
4213 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4214 data
->hActCtx
= NULL
;
4216 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4217 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4219 return STATUS_SUCCESS
;
4222 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4224 unsigned int i
, j
, total_len
= 0, count
= 0;
4225 struct guidsection_header
*header
;
4226 struct clrsurrogate_data
*data
;
4227 struct guid_index
*index
;
4230 /* compute section length */
4231 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4233 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4234 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4236 struct entity
*entity
= &assembly
->entities
.base
[j
];
4237 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4241 total_len
+= sizeof(*index
) + sizeof(*data
);
4242 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4243 if (entity
->u
.clrsurrogate
.version
)
4244 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4245 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4252 total_len
+= sizeof(*header
);
4254 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4255 if (!header
) return STATUS_NO_MEMORY
;
4257 memset(header
, 0, sizeof(*header
));
4258 header
->magic
= GUIDSECTION_MAGIC
;
4259 header
->size
= sizeof(*header
);
4260 header
->count
= count
;
4261 header
->index_offset
= sizeof(*header
);
4262 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4263 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4265 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4267 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4268 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4270 struct entity
*entity
= &assembly
->entities
.base
[j
];
4271 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4273 ULONG version_len
, name_len
;
4277 if (entity
->u
.clrsurrogate
.version
)
4278 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4281 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4283 /* setup new index entry */
4284 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4285 RtlGUIDFromString(&str
, &index
->guid
);
4287 index
->data_offset
= data_offset
;
4288 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4289 index
->rosterindex
= i
+ 1;
4292 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4293 data
->size
= sizeof(*data
);
4295 data
->clsid
= index
->guid
;
4296 data
->version_offset
= version_len
? data
->size
: 0;
4297 data
->version_len
= version_len
;
4298 data
->name_offset
= data
->size
+ version_len
;
4300 data
->name_offset
+= sizeof(WCHAR
);
4301 data
->name_len
= name_len
;
4303 /* surrogate name */
4304 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4305 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4306 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4308 /* runtime version */
4309 if (data
->version_len
)
4311 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4312 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4313 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4316 data_offset
+= index
->data_offset
;
4324 return STATUS_SUCCESS
;
4327 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4329 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4332 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4334 struct clrsurrogate_data
*surrogate
;
4335 struct guid_index
*index
= NULL
;
4337 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4339 if (!actctx
->clrsurrogate_section
)
4341 struct guidsection_header
*section
;
4343 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4344 if (status
) return status
;
4346 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4347 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4350 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4351 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4353 surrogate
= get_surrogate_data(actctx
, index
);
4355 data
->ulDataFormatVersion
= 1;
4356 data
->lpData
= surrogate
;
4357 /* full length includes string length with nulls */
4358 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4359 if (surrogate
->version_len
)
4360 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4362 data
->lpSectionGlobalData
= NULL
;
4363 data
->ulSectionGlobalDataLength
= 0;
4364 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4365 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4366 data
->hActCtx
= NULL
;
4368 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4369 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4371 return STATUS_SUCCESS
;
4374 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4376 unsigned int i
, j
, single_len
;
4378 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4379 for (i
= 0; i
< entities
->num
; i
++)
4381 struct entity
*entity
= &entities
->base
[i
];
4382 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4384 if (entity
->u
.comclass
.progid
)
4386 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4390 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4391 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4393 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4394 *count
+= entity
->u
.comclass
.progids
.num
;
4399 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4400 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4402 struct progidredirect_data
*data
;
4407 /* setup new index entry */
4409 /* hash progid name */
4410 RtlInitUnicodeString(&str
, progid
);
4411 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4413 (*index
)->name_offset
= *data_offset
;
4414 (*index
)->name_len
= str
.Length
;
4415 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4416 (*index
)->data_len
= sizeof(*data
);
4417 (*index
)->rosterindex
= rosterindex
;
4419 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4421 /* setup data structure */
4422 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4423 data
->size
= sizeof(*data
);
4425 data
->clsid_offset
= *global_offset
;
4427 /* write progid string */
4428 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4429 memcpy(ptrW
, progid
, (*index
)->name_len
);
4430 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4432 /* write guid to global area */
4433 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4437 *global_offset
+= sizeof(GUID
);
4438 *data_offset
+= data
->size
;
4442 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4443 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4447 for (i
= 0; i
< entities
->num
; i
++)
4449 struct entity
*entity
= &entities
->base
[i
];
4450 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4452 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4453 struct comclassredirect_data
*comclass
;
4454 struct guid_index
*guid_index
;
4458 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4459 RtlGUIDFromString(&str
, &clsid
);
4461 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4462 comclass
= get_comclass_data(actctx
, guid_index
);
4464 if (entity
->u
.comclass
.progid
)
4465 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4466 index
, data_offset
, global_offset
, rosterindex
);
4468 for (j
= 0; j
< progids
->num
; j
++)
4469 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4470 index
, data_offset
, global_offset
, rosterindex
);
4475 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4477 unsigned int i
, j
, total_len
= 0, count
= 0;
4478 struct strsection_header
*header
;
4479 ULONG data_offset
, global_offset
;
4480 struct string_index
*index
;
4482 /* compute section length */
4483 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4485 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4487 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4488 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4490 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4491 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4495 total_len
+= sizeof(*header
);
4497 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4498 if (!header
) return STATUS_NO_MEMORY
;
4500 memset(header
, 0, sizeof(*header
));
4501 header
->magic
= STRSECTION_MAGIC
;
4502 header
->size
= sizeof(*header
);
4503 header
->count
= count
;
4504 header
->global_offset
= header
->size
;
4505 header
->global_len
= count
*sizeof(GUID
);
4506 header
->index_offset
= header
->size
+ header
->global_len
;
4508 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4509 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4510 global_offset
= header
->global_offset
;
4512 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4514 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4516 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4517 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4519 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4520 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4526 return STATUS_SUCCESS
;
4529 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4531 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4534 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4535 PACTCTX_SECTION_KEYED_DATA data
)
4537 struct progidredirect_data
*progid
;
4538 struct string_index
*index
;
4540 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4542 if (!actctx
->comserver_section
)
4544 struct guidsection_header
*section
;
4546 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4547 if (status
) return status
;
4549 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4550 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4553 if (!actctx
->progid_section
)
4555 struct strsection_header
*section
;
4557 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4558 if (status
) return status
;
4560 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4561 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4564 index
= find_string_index(actctx
->progid_section
, name
);
4565 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4569 progid
= get_progid_data(actctx
, index
);
4571 data
->ulDataFormatVersion
= 1;
4572 data
->lpData
= progid
;
4573 data
->ulLength
= progid
->size
;
4574 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4575 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4576 data
->lpSectionBase
= actctx
->progid_section
;
4577 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4578 data
->hActCtx
= NULL
;
4580 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4581 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4584 return STATUS_SUCCESS
;
4587 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4588 const UNICODE_STRING
*section_name
,
4589 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4593 switch (section_kind
)
4595 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4596 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4597 return STATUS_SXS_KEY_NOT_FOUND
;
4598 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4599 status
= find_dll_redirection(actctx
, section_name
, data
);
4601 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4602 status
= find_window_class(actctx
, section_name
, data
);
4604 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4605 status
= find_progid_redirection(actctx
, section_name
, data
);
4607 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4608 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4609 return STATUS_SXS_SECTION_NOT_FOUND
;
4611 DPRINT1("Unknown section_kind %x\n", section_kind
);
4612 return STATUS_SXS_SECTION_NOT_FOUND
;
4615 if (status
!= STATUS_SUCCESS
) return status
;
4617 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4619 actctx_addref(actctx
);
4620 data
->hActCtx
= actctx
;
4622 return STATUS_SUCCESS
;
4625 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4626 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4630 switch (section_kind
)
4632 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4633 status
= find_tlib_redirection(actctx
, guid
, data
);
4635 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4636 status
= find_comserver_redirection(actctx
, guid
, data
);
4638 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4639 status
= find_cominterface_redirection(actctx
, guid
, data
);
4641 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4642 status
= find_clr_surrogate(actctx
, guid
, data
);
4645 DPRINT("Unknown section_kind %x\n", section_kind
);
4646 return STATUS_SXS_SECTION_NOT_FOUND
;
4649 if (status
!= STATUS_SUCCESS
) return status
;
4651 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4653 actctx_addref(actctx
);
4654 data
->hActCtx
= actctx
;
4656 return STATUS_SUCCESS
;
4659 /* initialize the activation context for the current process */
4660 void actctx_init(void)
4665 ctx
.cbSize
= sizeof(ctx
);
4666 ctx
.lpSource
= NULL
;
4667 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4668 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4669 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4671 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4673 process_actctx
= check_actctx(handle
);
4677 /* FUNCTIONS ***************************************************************/
4679 /***********************************************************************
4680 * RtlCreateActivationContext (NTDLL.@)
4682 * Create an activation context.
4686 RtlCreateActivationContext(IN ULONG Flags
,
4687 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4688 IN ULONG ExtraBytes
,
4689 IN PVOID NotificationRoutine
,
4690 IN PVOID NotificationContext
,
4691 OUT PACTIVATION_CONTEXT
*ActCtx
)
4693 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4694 const WCHAR
*directory
= NULL
;
4695 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4696 ACTIVATION_CONTEXT
*actctx
;
4697 UNICODE_STRING nameW
;
4699 NTSTATUS status
= STATUS_NO_MEMORY
;
4701 struct actctx_loader acl
;
4703 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4705 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4706 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4707 return STATUS_INVALID_PARAMETER
;
4710 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4711 return STATUS_NO_MEMORY
;
4713 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4715 actctx
= &ActualActCtx
->ActivationContext
;
4716 actctx
->RefCount
= 1;
4717 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4718 actctx
->config
.info
= NULL
;
4719 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4720 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4722 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4730 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4731 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4733 status
= get_module_filename( module
, &dir
, 0 );
4734 if (!NT_SUCCESS(status
)) goto error
;
4735 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4736 actctx
->appdir
.info
= dir
.Buffer
;
4739 nameW
.Buffer
= NULL
;
4741 /* open file only if it's going to be used */
4742 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4743 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4745 WCHAR
*source
= NULL
;
4748 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4749 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
4751 DWORD dir_len
, source_len
;
4753 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4754 source_len
= strlenW(pActCtx
->lpSource
);
4755 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4757 status
= STATUS_NO_MEMORY
;
4761 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4762 source
[dir_len
] = '\\';
4763 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4766 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4767 if (source
) RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
4770 status
= STATUS_NO_SUCH_FILE
;
4773 status
= open_nt_file( &file
, &nameW
);
4774 if (!NT_SUCCESS(status
))
4776 RtlFreeUnicodeString( &nameW
);
4781 acl
.actctx
= actctx
;
4782 acl
.dependencies
= NULL
;
4783 acl
.num_dependencies
= 0;
4784 acl
.allocated_dependencies
= 0;
4786 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4787 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4789 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4791 /* if we have a resource it's a PE file */
4792 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4794 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4795 pActCtx
->lpResourceName
, lang
);
4796 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4797 /* FIXME: what to do if pActCtx->lpSource is set */
4798 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4799 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4801 else if (pActCtx
->lpSource
)
4803 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4804 file
, pActCtx
->lpResourceName
, lang
);
4805 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4806 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4807 NULL
, pActCtx
->lpResourceName
);
4809 else status
= STATUS_INVALID_PARAMETER
;
4813 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4816 if (file
) NtClose( file
);
4817 RtlFreeUnicodeString( &nameW
);
4819 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
4820 free_depend_manifests( &acl
);
4822 if (NT_SUCCESS(status
))
4824 else actctx_release( actctx
);
4828 if (file
) NtClose( file
);
4829 actctx_release( actctx
);
4834 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4838 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
4840 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
4841 LONG OldRefCount
, NewRefCount
;
4843 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4845 RtlpValidateActCtx(ActCtx
);
4849 OldRefCount
= ActCtx
->RefCount
;
4850 ASSERT(OldRefCount
> 0);
4852 if (OldRefCount
== LONG_MAX
) break;
4854 NewRefCount
= OldRefCount
+ 1;
4855 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
4857 OldRefCount
) == OldRefCount
)
4863 NewRefCount
= LONG_MAX
;
4864 ASSERT(NewRefCount
> 0);
4870 RtlReleaseActivationContext( HANDLE handle
)
4872 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
4874 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4876 RtlpValidateActCtx(ActCtx
);
4878 actctx_release(ActCtx
);
4883 /***********************************************************************
4884 * RtlAddRefActivationContext (NTDLL.@)
4886 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
4888 ACTIVATION_CONTEXT
*actctx
;
4890 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4894 /******************************************************************
4895 * RtlReleaseActivationContext (NTDLL.@)
4897 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
4899 ACTIVATION_CONTEXT
*actctx
;
4901 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4906 /******************************************************************
4907 * RtlZombifyActivationContext (NTDLL.@)
4910 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
4914 if (Context
== ACTCTX_FAKE_HANDLE
)
4915 return STATUS_SUCCESS
;
4917 return STATUS_NOT_IMPLEMENTED
;
4921 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
4923 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4925 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
4926 return STATUS_NO_MEMORY
;
4928 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
4929 frame
->ActivationContext
= handle
;
4932 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4933 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
4936 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
4937 RtlAddRefActivationContext( handle
);
4939 *cookie
= (ULONG_PTR
)frame
;
4940 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
4941 return STATUS_SUCCESS
;
4944 /******************************************************************
4945 * RtlActivateActivationContext (NTDLL.@)
4947 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
4949 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
4952 /***********************************************************************
4953 * RtlDeactivateActivationContext (NTDLL.@)
4955 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4957 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4959 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
4961 /* find the right frame */
4962 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
4963 for (frame
= top
; frame
; frame
= frame
->Previous
)
4964 if ((ULONG_PTR
)frame
== cookie
) break;
4967 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4969 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
4970 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4972 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4973 NtCurrentTeb()->ActivationContextStackPointer
,
4974 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
4977 /* pop everything up to and including frame */
4978 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
4980 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
4982 frame
= top
->Previous
;
4983 RtlReleaseActivationContext( top
->ActivationContext
);
4984 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
4988 return STATUS_SUCCESS
;
4993 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
4995 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
4997 /* Nothing to do if there is no stack */
5000 /* Get the current active frame */
5001 ActiveFrame
= Stack
->ActiveFrame
;
5003 /* Go through them in backwards order and release */
5006 PrevFrame
= ActiveFrame
->Previous
;
5007 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5008 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5009 ActiveFrame
= PrevFrame
;
5012 /* Zero out the active frame */
5013 Stack
->ActiveFrame
= NULL
;
5015 /* TODO: Empty the Frame List Cache */
5016 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5018 /* Free activation stack memory */
5019 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5022 /******************************************************************
5023 * RtlFreeThreadActivationContextStack (NTDLL.@)
5025 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5027 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5028 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5032 /******************************************************************
5033 * RtlGetActiveActivationContext (NTDLL.@)
5035 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5037 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5039 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5040 RtlAddRefActivationContext( *handle
);
5045 return STATUS_SUCCESS
;
5049 /******************************************************************
5050 * RtlIsActivationContextActive (NTDLL.@)
5052 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5054 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5056 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5057 if (frame
->ActivationContext
== handle
) return TRUE
;
5062 /***********************************************************************
5063 * RtlQueryInformationActivationContext (NTDLL.@)
5065 * Get information about an activation context.
5066 * FIXME: function signature/prototype may be wrong
5068 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5069 ULONG
class, PVOID buffer
,
5070 SIZE_T bufsize
, SIZE_T
*retlen
)
5072 ACTIVATION_CONTEXT
*actctx
;
5075 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5076 subinst
, class, buffer
, bufsize
, retlen
);
5078 if (retlen
) *retlen
= 0;
5079 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5083 case ActivationContextBasicInformation
:
5085 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5087 if (retlen
) *retlen
= sizeof(*info
);
5088 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5090 info
->hActCtx
= handle
;
5091 info
->dwFlags
= 0; /* FIXME */
5092 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5096 case ActivationContextDetailedInformation
:
5098 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5099 struct assembly
*assembly
= NULL
;
5100 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5103 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5105 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5107 if (assembly
&& assembly
->manifest
.info
)
5108 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5109 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5110 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5111 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5113 if (retlen
) *retlen
= len
;
5114 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5117 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5118 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5119 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5120 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5121 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5122 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5123 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5124 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5125 ptr
= (LPWSTR
)(acdi
+ 1);
5128 acdi
->lpRootManifestPath
= ptr
;
5129 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5130 ptr
+= manifest_len
;
5132 else acdi
->lpRootManifestPath
= NULL
;
5135 acdi
->lpRootConfigurationPath
= ptr
;
5136 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5139 else acdi
->lpRootConfigurationPath
= NULL
;
5142 acdi
->lpAppDirPath
= ptr
;
5143 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5145 else acdi
->lpAppDirPath
= NULL
;
5149 case AssemblyDetailedInformationInActivationContext
:
5151 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5152 struct assembly
*assembly
;
5155 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5158 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5159 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5161 index
= *(DWORD
*)subinst
;
5162 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5164 assembly
= &actctx
->assemblies
[index
- 1];
5166 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5167 id_len
= strlenW(assembly_id
) + 1;
5168 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5170 if (assembly
->manifest
.info
&&
5171 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5172 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5174 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5176 if (retlen
) *retlen
= len
;
5177 if (!buffer
|| bufsize
< len
)
5179 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5180 return STATUS_BUFFER_TOO_SMALL
;
5183 afdi
->ulFlags
= 0; /* FIXME */
5184 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5185 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5186 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5187 /* FIXME afdi->liManifestLastWriteTime = 0; */
5188 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5189 afdi
->ulPolicyPathLength
= 0;
5190 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5191 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5192 afdi
->ulManifestVersionMajor
= 1;
5193 afdi
->ulManifestVersionMinor
= 0;
5194 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5195 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5196 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5197 ptr
= (LPWSTR
)(afdi
+ 1);
5198 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5199 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5203 afdi
->lpAssemblyManifestPath
= ptr
;
5204 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5206 } else afdi
->lpAssemblyManifestPath
= NULL
;
5207 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5210 afdi
->lpAssemblyDirectoryName
= ptr
;
5211 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5213 else afdi
->lpAssemblyDirectoryName
= NULL
;
5214 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5218 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5220 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5221 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5222 struct assembly
*assembly
;
5223 struct dll_redirect
*dll
;
5224 SIZE_T len
, dll_len
= 0;
5227 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5228 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5230 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5231 return STATUS_INVALID_PARAMETER
;
5232 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5234 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5235 return STATUS_INVALID_PARAMETER
;
5236 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5238 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5239 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5241 if (!buffer
|| bufsize
< len
)
5243 if (retlen
) *retlen
= len
;
5244 return STATUS_BUFFER_TOO_SMALL
;
5246 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5247 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5248 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5249 afdi
->ulPathLength
= 0; /* FIXME */
5250 ptr
= (LPWSTR
)(afdi
+ 1);
5253 afdi
->lpFileName
= ptr
;
5254 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5255 } else afdi
->lpFileName
= NULL
;
5256 afdi
->lpFilePath
= NULL
; /* FIXME */
5261 DPRINT( "class %u not implemented\n", class );
5262 return STATUS_NOT_IMPLEMENTED
;
5264 return STATUS_SUCCESS
;
5269 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5271 SIZE_T cbBuffer OPTIONAL
,
5272 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5274 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5280 pcbWrittenOrRequired
);
5283 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5284 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5285 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5289 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5290 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5292 /* Check general parameter combinations */
5293 if (!section_name
|| !section_name
->Buffer
||
5294 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5295 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5296 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5298 DPRINT1("invalid parameter\n");
5299 return STATUS_INVALID_PARAMETER
;
5303 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5304 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5306 DPRINT1("unknown flags %08x\n", flags
);
5307 return STATUS_INVALID_PARAMETER
;
5310 return STATUS_SUCCESS
;
5313 /***********************************************************************
5314 * RtlFindActivationContextSectionString (NTDLL.@)
5316 * Find information about a string in an activation context.
5317 * FIXME: function signature/prototype may be wrong
5319 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5320 const UNICODE_STRING
*section_name
, PVOID ptr
)
5322 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5325 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5326 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5327 if (!NT_SUCCESS(status
))
5329 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5333 status
= STATUS_SXS_KEY_NOT_FOUND
;
5335 /* if there is no data, but params are valid,
5336 we return that sxs key is not found to be at least somehow compatible */
5339 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5343 ASSERT(NtCurrentTeb());
5344 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5346 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5347 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5349 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5350 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5353 DPRINT("status %x\n", status
);
5354 if (status
!= STATUS_SUCCESS
)
5355 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5357 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5361 /***********************************************************************
5362 * RtlFindActivationContextSectionGuid (NTDLL.@)
5364 * Find information about a GUID in an activation context.
5365 * FIXME: function signature/prototype may be wrong
5367 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5368 const GUID
*guid
, void *ptr
)
5370 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5371 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5375 DPRINT1("expected extguid == NULL\n");
5376 return STATUS_INVALID_PARAMETER
;
5379 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5381 DPRINT1("unknown flags %08x\n", flags
);
5382 return STATUS_INVALID_PARAMETER
;
5385 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5386 return STATUS_INVALID_PARAMETER
;
5388 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5390 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5391 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5394 if (status
!= STATUS_SUCCESS
)
5395 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5404 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5406 PACTIVATION_CONTEXT_STACK ContextStack
;
5408 /* Check if it's already allocated */
5409 if (*Stack
) return STATUS_SUCCESS
;
5411 /* Allocate space for the context stack */
5412 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5415 return STATUS_NO_MEMORY
;
5418 /* Initialize the context stack */
5419 ContextStack
->Flags
= 0;
5420 ContextStack
->ActiveFrame
= NULL
;
5421 InitializeListHead(&ContextStack
->FrameListCache
);
5422 ContextStack
->NextCookieSequenceNumber
= 1;
5423 ContextStack
->StackId
= 1; //TODO: Timer-based
5425 *Stack
= ContextStack
;
5427 return STATUS_SUCCESS
;
5430 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5432 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5435 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5436 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5438 /* Get the current active frame */
5439 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5441 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5442 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5443 &Frame
->Frame
, Context
);
5445 /* Ensure it's in the right format and at least fits basic info */
5446 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5447 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5449 /* Set debug info if size allows*/
5450 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5452 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5453 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5454 //Frame->Extra3 = ...;
5459 /*ASSERT((ActiveFrame->Flags &
5460 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5461 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5462 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5464 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5466 // TODO: Perform some additional checks if it was not heap allocated
5470 /* Save pointer to the new activation frame */
5471 NewFrame
= &Frame
->Frame
;
5473 /* Actually activate it */
5474 Frame
->Frame
.Previous
= ActiveFrame
;
5475 Frame
->Frame
.ActivationContext
= Context
;
5476 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5478 /* Check if we can activate this context */
5479 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5482 /* Set new active frame */
5483 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5484 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5488 /* We can get here only one way: it was already activated */
5489 DPRINT("Trying to activate already activated activation context\n");
5491 /* Activate only if we are allowing multiple activation */
5493 if (!RtlpNotAllowingMultipleActivation
)
5495 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5496 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5499 // Activate it anyway
5500 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5503 /* Return pointer to the activation frame */
5507 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5509 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5511 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5513 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5515 /* Ensure it's in the right format and at least fits basic info */
5516 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5517 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5519 /* Make sure it is not deactivated and it is activated */
5520 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5521 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5522 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
);
5524 /* Check debug info if it is present */
5525 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5527 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5528 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5529 //Frame->Extra3 = ...;
5534 // TODO: Perform some additional checks here
5537 /* Special handling for not-really-activated */
5538 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5540 DPRINT1("Deactivating not really activated activation context\n");
5541 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5542 return &Frame
->Frame
;
5545 /* find the right frame */
5546 NewFrame
= &Frame
->Frame
;
5547 if (ActiveFrame
!= NewFrame
)
5549 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5552 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5553 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5555 /* Pop everything up to and including frame */
5556 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5558 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5559 return NewFrame
->Previous
;