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 WCHAR
**new_progids
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids
->progids
,
1508 2 * progids
->allocated
* sizeof(WCHAR
*));
1509 if (!new_progids
) return FALSE
;
1510 progids
->allocated
*= 2;
1511 progids
->progids
= new_progids
;
1514 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1520 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1525 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1528 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1529 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1532 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1534 xmlstr_t elem
, attr_name
, attr_value
;
1535 BOOL ret
= TRUE
, end
= FALSE
, error
;
1536 struct entity
* entity
;
1537 UNICODE_STRING attr_valueU
, attr_nameU
;
1539 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1542 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1544 if (xmlstr_cmp(&attr_name
, clsidW
))
1546 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1548 else if (xmlstr_cmp(&attr_name
, progidW
))
1550 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1552 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1554 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1556 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1558 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1560 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1562 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1564 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1566 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1568 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1570 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1572 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1574 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1576 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1578 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1580 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1586 attr_nameU
= xmlstr2unicode(&attr_name
);
1587 attr_valueU
= xmlstr2unicode(&attr_value
);
1588 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1592 if (error
) return FALSE
;
1594 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1595 if (entity
->u
.comclass
.progid
)
1596 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1598 if (end
) return TRUE
;
1600 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1602 if (xmlstr_cmp_end(&elem
, comClassW
))
1604 ret
= parse_end_element(xmlbuf
);
1607 else if (xmlstr_cmp(&elem
, progidW
))
1609 ret
= parse_com_class_progid(xmlbuf
, entity
);
1613 attr_nameU
= xmlstr2unicode(&elem
);
1614 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
1615 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1619 if (entity
->u
.comclass
.progids
.num
)
1620 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1625 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1630 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1632 if (*curr
>= '0' && *curr
<= '9')
1633 num
= num
* 10 + *curr
- '0';
1636 UNICODE_STRING strU
= xmlstr2unicode(str
);
1637 DPRINT1("wrong numeric value %wZ\n", &strU
);
1641 entity
->u
.ifaceps
.nummethods
= num
;
1646 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1648 xmlstr_t attr_name
, attr_value
;
1649 BOOL end
= FALSE
, error
;
1650 struct entity
* entity
;
1651 UNICODE_STRING attr_valueU
, attr_nameU
;
1653 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1656 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1658 if (xmlstr_cmp(&attr_name
, iidW
))
1660 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1662 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1664 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1666 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1668 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1669 entity
->u
.ifaceps
.mask
|= BaseIface
;
1671 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1673 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1674 entity
->u
.ifaceps
.mask
|= NumMethods
;
1676 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1678 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1681 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1686 attr_nameU
= xmlstr2unicode(&attr_name
);
1687 attr_valueU
= xmlstr2unicode(&attr_value
);
1688 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1692 if (error
) return FALSE
;
1693 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1694 if (end
) return TRUE
;
1696 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1699 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1701 WORD
*flags
= &entity
->u
.typelib
.flags
;
1702 const WCHAR
*str
= value
->ptr
, *start
;
1707 /* it's comma separated list of flags */
1708 while (i
< value
->len
)
1711 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1713 if (!strncmpiW(start
, restrictedW
, str
-start
))
1714 *flags
|= LIBFLAG_FRESTRICTED
;
1715 else if (!strncmpiW(start
, controlW
, str
-start
))
1716 *flags
|= LIBFLAG_FCONTROL
;
1717 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1718 *flags
|= LIBFLAG_FHIDDEN
;
1719 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1720 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1723 UNICODE_STRING valueU
= xmlstr2unicode(value
);
1724 DPRINT1("unknown flags value %wZ\n", &valueU
);
1728 /* skip separator */
1736 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1738 unsigned int ver
[2];
1741 UNICODE_STRING strW
;
1744 ver
[0] = ver
[1] = pos
= 0;
1745 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1747 if (*curr
>= '0' && *curr
<= '9')
1749 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1750 if (ver
[pos
] >= 0x10000) goto error
;
1752 else if (*curr
== '.')
1754 if (++pos
>= 2) goto error
;
1758 entity
->u
.typelib
.major
= ver
[0];
1759 entity
->u
.typelib
.minor
= ver
[1];
1763 strW
= xmlstr2unicode(str
);
1764 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW
);
1768 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1770 xmlstr_t attr_name
, attr_value
;
1771 BOOL end
= FALSE
, error
;
1772 struct entity
* entity
;
1773 UNICODE_STRING attr_valueU
, attr_nameU
;
1775 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1778 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1780 if (xmlstr_cmp(&attr_name
, tlbidW
))
1782 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1784 else if (xmlstr_cmp(&attr_name
, versionW
))
1786 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1788 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1790 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1792 else if (xmlstr_cmp(&attr_name
, flagsW
))
1794 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1798 attr_nameU
= xmlstr2unicode(&attr_name
);
1799 attr_valueU
= xmlstr2unicode(&attr_value
);
1800 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1804 if (error
) return FALSE
;
1806 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1808 if (end
) return TRUE
;
1810 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1813 static inline int aligned_string_len(int len
)
1815 return (len
+ 3) & ~3;
1818 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1820 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1821 struct assembly_version
*ver
= &assembly
->id
.version
;
1824 if (!ret
) ret
= buff
;
1825 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1828 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1830 xmlstr_t elem
, content
, attr_name
, attr_value
;
1831 BOOL end
= FALSE
, ret
= TRUE
, error
;
1832 struct entity
* entity
;
1833 UNICODE_STRING elemU
, attr_nameU
, attr_valueU
;
1835 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1838 entity
->u
.class.versioned
= TRUE
;
1839 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1841 if (xmlstr_cmp(&attr_name
, versionedW
))
1843 if (xmlstr_cmpi(&attr_value
, noW
))
1844 entity
->u
.class.versioned
= FALSE
;
1845 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1850 attr_nameU
= xmlstr2unicode(&attr_name
);
1851 attr_valueU
= xmlstr2unicode(&attr_value
);
1852 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1856 if (error
|| end
) return end
;
1858 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1860 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1862 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1864 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1866 if (xmlstr_cmp_end(&elem
, windowClassW
))
1868 ret
= parse_end_element(xmlbuf
);
1873 elemU
= xmlstr2unicode(&elem
);
1874 DPRINT1("unknown elem %wZ\n", &elemU
);
1875 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1882 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1884 xmlstr_t attr_name
, attr_value
;
1885 UNICODE_STRING attr_valueU
, attr_nameU
;
1886 BOOL end
= FALSE
, error
;
1888 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1890 attr_nameU
= xmlstr2unicode(&attr_name
);
1891 attr_valueU
= xmlstr2unicode(&attr_value
);
1893 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1895 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU
);
1897 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1899 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU
);
1903 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1907 if (error
|| end
) return end
;
1908 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1911 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1913 xmlstr_t elem
, content
, attr_name
, attr_value
;
1914 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1916 UNICODE_STRING elem1U
, elem2U
;
1918 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1920 elem1U
= xmlstr2unicode(&attr_name
);
1921 elem2U
= xmlstr2unicode(&attr_value
);
1922 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
1925 if (error
) return FALSE
;
1926 if (end
) return TRUE
;
1928 if (!parse_text_content(xmlbuf
, &content
))
1931 elem1U
= xmlstr2unicode(&content
);
1932 DPRINT("Got description %wZ\n", &elem1U
);
1934 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1936 if (xmlstr_cmp_end(&elem
, descriptionW
))
1938 ret
= parse_end_element(xmlbuf
);
1943 elem1U
= xmlstr2unicode(&elem
);
1944 DPRINT1("unknown elem %wZ\n", &elem1U
);
1945 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1952 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1953 struct assembly
* assembly
,
1954 struct actctx_loader
* acl
)
1956 xmlstr_t attr_name
, attr_value
;
1957 UNICODE_STRING attr_nameU
, attr_valueU
;
1958 BOOL end
= FALSE
, error
;
1959 struct entity
* entity
;
1961 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1962 if (!entity
) return FALSE
;
1964 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1966 if (xmlstr_cmp(&attr_name
, iidW
))
1968 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1970 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1972 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1974 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1976 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1977 entity
->u
.ifaceps
.mask
|= BaseIface
;
1979 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1981 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1982 entity
->u
.ifaceps
.mask
|= NumMethods
;
1984 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1986 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1988 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1990 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1994 attr_nameU
= xmlstr2unicode(&attr_name
);
1995 attr_valueU
= xmlstr2unicode(&attr_value
);
1996 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2000 if (error
) return FALSE
;
2001 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2002 if (end
) return TRUE
;
2004 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
2007 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2009 xmlstr_t attr_name
, attr_value
, elem
;
2010 BOOL end
= FALSE
, error
, ret
= TRUE
;
2011 struct entity
* entity
;
2013 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
2014 if (!entity
) return FALSE
;
2016 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2018 if (xmlstr_cmp(&attr_name
, g_nameW
))
2020 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2022 else if (xmlstr_cmp(&attr_name
, clsidW
))
2024 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2026 else if (xmlstr_cmp(&attr_name
, progidW
))
2028 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
2030 else if (xmlstr_cmp(&attr_name
, tlbidW
))
2032 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
2034 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
2036 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
2038 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2040 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2044 UNICODE_STRING attr_nameU
, attr_valueU
;
2045 attr_nameU
= xmlstr2unicode(&attr_name
);
2046 attr_valueU
= xmlstr2unicode(&attr_value
);
2047 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2051 if (error
) return FALSE
;
2052 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2053 if (entity
->u
.comclass
.progid
)
2054 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2055 if (end
) return TRUE
;
2057 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2059 if (xmlstr_cmp_end(&elem
, clrClassW
))
2061 ret
= parse_end_element(xmlbuf
);
2064 else if (xmlstr_cmp(&elem
, progidW
))
2066 ret
= parse_com_class_progid(xmlbuf
, entity
);
2070 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2071 DPRINT1("unknown elem %wZ\n", &elemU
);
2072 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2076 if (entity
->u
.comclass
.progids
.num
)
2077 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2082 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2084 xmlstr_t attr_name
, attr_value
;
2085 UNICODE_STRING attr_nameU
, attr_valueU
;
2086 BOOL end
= FALSE
, error
;
2087 struct entity
* entity
;
2089 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
2090 if (!entity
) return FALSE
;
2092 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2094 if (xmlstr_cmp(&attr_name
, g_nameW
))
2096 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2098 else if (xmlstr_cmp(&attr_name
, clsidW
))
2100 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2102 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2104 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2108 attr_nameU
= xmlstr2unicode(&attr_name
);
2109 attr_valueU
= xmlstr2unicode(&attr_value
);
2110 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2114 if (error
) return FALSE
;
2115 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2116 if (end
) return TRUE
;
2118 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2121 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2123 struct assembly_identity ai
;
2124 xmlstr_t elem
, attr_name
, attr_value
;
2125 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2127 UNICODE_STRING elem1U
, elem2U
;
2129 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2131 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2132 static const WCHAR trueW
[] = {'t','r','u','e',0};
2134 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2135 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2138 elem1U
= xmlstr2unicode(&attr_name
);
2139 elem2U
= xmlstr2unicode(&attr_value
);
2140 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
2144 if (error
|| end
) return end
;
2146 memset(&ai
, 0, sizeof(ai
));
2147 ai
.optional
= optional
;
2148 ai
.delayed
= delayed
;
2150 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2151 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2154 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2156 /* store the newly found identity for later loading */
2157 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2159 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2161 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2163 ret
= parse_end_element(xmlbuf
);
2166 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2168 ret
= parse_binding_redirect_elem(xmlbuf
);
2172 DPRINT1("unknown elem %S\n", elem
.ptr
);
2173 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2180 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2182 xmlstr_t attr_name
, attr_value
, elem
;
2183 UNICODE_STRING attr_nameU
, attr_valueU
;
2184 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2186 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2188 attr_nameU
= xmlstr2unicode(&attr_name
);
2189 attr_valueU
= xmlstr2unicode(&attr_value
);
2191 if (xmlstr_cmp(&attr_name
, optionalW
))
2193 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2194 DPRINT1("optional=%wZ\n", &attr_valueU
);
2198 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2202 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2204 if (xmlstr_cmp_end(&elem
, dependencyW
))
2206 ret
= parse_end_element(xmlbuf
);
2209 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2211 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2215 attr_nameU
= xmlstr2unicode(&elem
);
2216 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2217 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2224 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2228 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2229 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2232 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2236 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2237 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2240 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2242 xmlstr_t attr_name
, attr_value
, elem
;
2243 UNICODE_STRING attr_nameU
, attr_valueU
;
2244 BOOL end
= FALSE
, error
, ret
= TRUE
;
2245 struct dll_redirect
* dll
;
2247 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2249 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2251 attr_nameU
= xmlstr2unicode(&attr_name
);
2252 attr_valueU
= xmlstr2unicode(&attr_value
);
2254 if (xmlstr_cmp(&attr_name
, g_nameW
))
2256 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2257 DPRINT("name=%wZ\n", &attr_valueU
);
2259 else if (xmlstr_cmp(&attr_name
, hashW
))
2261 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2263 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2265 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2266 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2267 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU
);
2271 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2275 if (error
|| !dll
->name
) return FALSE
;
2277 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2279 if (end
) return TRUE
;
2281 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2283 if (xmlstr_cmp_end(&elem
, fileW
))
2285 ret
= parse_end_element(xmlbuf
);
2288 else if (xmlstr_cmp(&elem
, comClassW
))
2290 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2292 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2294 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2296 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2298 DPRINT1("asmv2hash (undocumented) not supported\n");
2299 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2301 else if (xmlstr_cmp(&elem
, typelibW
))
2303 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2305 else if (xmlstr_cmp(&elem
, windowClassW
))
2307 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2311 attr_nameU
= xmlstr2unicode(&elem
);
2312 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
2313 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2320 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2321 struct assembly
* assembly
,
2322 struct assembly_identity
* expected_ai
)
2324 xmlstr_t attr_name
, attr_value
, elem
;
2325 UNICODE_STRING attr_nameU
, attr_valueU
;
2326 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2328 DPRINT("(%p)\n", xmlbuf
);
2330 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2332 attr_nameU
= xmlstr2unicode(&attr_name
);
2333 attr_valueU
= xmlstr2unicode(&attr_value
);
2335 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2337 static const WCHAR v10W
[] = {'1','.','0',0};
2338 if (!xmlstr_cmp(&attr_value
, v10W
))
2340 DPRINT1("wrong version %wZ\n", &attr_valueU
);
2345 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2347 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2348 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2349 !xmlstr_cmp(&attr_value
, manifestv3W
))
2351 DPRINT1("wrong namespace %wZ\n", &attr_valueU
);
2358 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2362 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2363 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2365 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2367 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2369 assembly
->no_inherit
= TRUE
;
2372 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2374 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2377 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2378 assembly
->no_inherit
)
2383 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2385 ret
= parse_end_element(xmlbuf
);
2388 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2390 ret
= parse_description_elem(xmlbuf
);
2392 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2394 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2396 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2398 ret
= parse_dependency_elem(xmlbuf
, acl
);
2400 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2402 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2404 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2406 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2408 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2410 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2412 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2414 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2418 /* FIXME: more tests */
2419 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2420 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2422 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2423 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2424 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2425 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2426 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2429 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2430 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2431 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2432 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2433 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2434 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2436 DPRINT1("wrong version for shared assembly manifest\n");
2442 else if (xml_elem_cmp(&elem
, L
"trustInfo", asmv1W
))
2444 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2449 attr_nameU
= xmlstr2unicode(&elem
);
2450 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2451 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2453 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2459 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2460 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2463 UNICODE_STRING elemU
;
2465 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2467 if (xmlstr_cmp(&elem
, g_xmlW
) &&
2468 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2469 return STATUS_SXS_CANT_GEN_ACTCTX
;
2471 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2473 elemU
= xmlstr2unicode(&elem
);
2474 DPRINT1("root element is %wZ, not <assembly>\n", &elemU
);
2475 return STATUS_SXS_CANT_GEN_ACTCTX
;
2478 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2480 DPRINT1("failed to parse manifest %S\n", assembly
->manifest
.info
);
2481 return STATUS_SXS_CANT_GEN_ACTCTX
;
2484 if (next_xml_elem(xmlbuf
, &elem
))
2486 elemU
= xmlstr2unicode(&elem
);
2487 DPRINT1("unexpected element %wZ\n", &elemU
);
2488 return STATUS_SXS_CANT_GEN_ACTCTX
;
2491 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2493 DPRINT1("parse error\n");
2494 return STATUS_SXS_CANT_GEN_ACTCTX
;
2496 return STATUS_SUCCESS
;
2499 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2500 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2501 const void *buffer
, SIZE_T size
)
2505 struct assembly
*assembly
;
2508 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename
, directory
);
2510 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2511 return STATUS_SXS_CANT_GEN_ACTCTX
;
2513 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2514 return STATUS_NO_MEMORY
;
2516 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2517 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2518 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2520 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2521 if (RtlIsTextUnicode(buffer
, size
, &unicode_tests
))
2523 xmlbuf
.ptr
= buffer
;
2524 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2525 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2527 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2529 const WCHAR
*buf
= buffer
;
2533 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
2534 return STATUS_NO_MEMORY
;
2535 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2536 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2537 xmlbuf
.ptr
= new_buff
;
2538 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2539 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2540 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
2544 /* TODO: this doesn't handle arbitrary encodings */
2548 status
= RtlMultiByteToUnicodeSize(&sizeU
, buffer
, size
);
2549 if (!NT_SUCCESS(status
))
2551 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status
);
2552 return STATUS_SXS_CANT_GEN_ACTCTX
;
2555 new_buff
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU
);
2557 return STATUS_NO_MEMORY
;
2559 status
= RtlMultiByteToUnicodeN(new_buff
, sizeU
, &sizeU
, buffer
, size
);
2560 if (!NT_SUCCESS(status
))
2562 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status
);
2563 return STATUS_SXS_CANT_GEN_ACTCTX
;
2566 xmlbuf
.ptr
= new_buff
;
2567 xmlbuf
.end
= xmlbuf
.ptr
+ sizeU
/ sizeof(WCHAR
);
2568 status
= parse_manifest_buffer(acl
, assembly
, ai
, &xmlbuf
);
2569 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff
);
2574 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2576 OBJECT_ATTRIBUTES attr
;
2579 attr
.Length
= sizeof(attr
);
2580 attr
.RootDirectory
= 0;
2581 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2582 attr
.ObjectName
= name
;
2583 attr
.SecurityDescriptor
= NULL
;
2584 attr
.SecurityQualityOfService
= NULL
;
2585 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2588 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2592 LDR_DATA_TABLE_ENTRY
*pldr
;
2594 LdrLockLoaderLock(0, NULL
, &magic
);
2595 status
= LdrFindEntryForAddress( module
, &pldr
);
2596 if (status
== STATUS_SUCCESS
)
2598 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2599 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2601 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2602 str
->Length
= pldr
->FullDllName
.Length
;
2603 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2605 else status
= STATUS_NO_MEMORY
;
2607 LdrUnlockLoaderLock(0, magic
);
2611 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2612 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2613 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2616 UNICODE_STRING nameW
;
2617 LDR_RESOURCE_INFO info
;
2618 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2621 //DPRINT( "looking for res %s in module %p %s\n", resname,
2622 // hModule, filename );
2623 DPRINT("get_manifest_in_module %p\n", hModule
);
2626 if (TRACE_ON(actctx
))
2628 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2630 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2631 hModule
, debugstr_w(nameW
.Buffer
) );
2632 RtlFreeUnicodeString( &nameW
);
2634 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2635 hModule
, debugstr_w(filename
) );
2639 if (!resname
) return STATUS_INVALID_PARAMETER
;
2641 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2642 info
.Language
= lang
;
2643 if (!((ULONG_PTR
)resname
>> 16))
2645 info
.Name
= (ULONG_PTR
)resname
;
2646 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2648 else if (resname
[0] == '#')
2651 RtlInitUnicodeString(&nameW
, resname
+ 1);
2652 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2653 return STATUS_INVALID_PARAMETER
;
2655 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2659 RtlCreateUnicodeString(&nameW
, resname
);
2660 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2661 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2662 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2663 RtlFreeUnicodeString(&nameW
);
2665 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2667 if (status
== STATUS_SUCCESS
)
2668 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2673 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2674 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2675 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2678 OBJECT_ATTRIBUTES attr
;
2680 LARGE_INTEGER offset
;
2685 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2687 attr
.Length
= sizeof(attr
);
2688 attr
.RootDirectory
= 0;
2689 attr
.ObjectName
= NULL
;
2690 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2691 attr
.SecurityDescriptor
= NULL
;
2692 attr
.SecurityQualityOfService
= NULL
;
2695 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2696 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2697 if (status
!= STATUS_SUCCESS
) return status
;
2699 offset
.QuadPart
= 0;
2702 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2703 &count
, ViewShare
, 0, PAGE_READONLY
);
2705 if (status
!= STATUS_SUCCESS
) return status
;
2707 if (RtlImageNtHeader(base
)) /* we got a PE file */
2709 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2710 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2712 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2714 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2718 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2719 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2721 FILE_STANDARD_INFORMATION info
;
2724 OBJECT_ATTRIBUTES attr
;
2726 LARGE_INTEGER offset
;
2731 DPRINT( "loading manifest file %S\n", filename
);
2733 attr
.Length
= sizeof(attr
);
2734 attr
.RootDirectory
= 0;
2735 attr
.ObjectName
= NULL
;
2736 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2737 attr
.SecurityDescriptor
= NULL
;
2738 attr
.SecurityQualityOfService
= NULL
;
2741 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2742 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2744 if (status
!= STATUS_SUCCESS
) return status
;
2746 offset
.QuadPart
= 0;
2749 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2750 &count
, ViewShare
, 0, PAGE_READONLY
);
2752 if (status
!= STATUS_SUCCESS
) return status
;
2754 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2755 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
2757 if (status
== STATUS_SUCCESS
)
2758 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
2760 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2764 /* try to load the .manifest file associated to the file */
2765 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2766 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2768 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2771 UNICODE_STRING nameW
;
2773 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2775 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2777 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
2779 if (module
) /* use the module filename */
2781 UNICODE_STRING name
;
2783 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2785 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2786 strcatW( name
.Buffer
, dotManifestW
);
2787 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2788 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2789 RtlFreeUnicodeString( &name
);
2791 if (status
) return status
;
2795 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2796 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2797 return STATUS_NO_MEMORY
;
2798 strcpyW( buffer
, filename
);
2799 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2800 strcatW( buffer
, dotManifestW
);
2801 RtlInitUnicodeString( &nameW
, buffer
);
2804 if (!open_nt_file( &file
, &nameW
))
2806 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2809 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2810 RtlFreeUnicodeString( &nameW
);
2814 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2816 static const WCHAR lookup_fmtW
[] =
2817 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2818 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2819 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2821 WCHAR
*lookup
, *ret
= NULL
;
2822 UNICODE_STRING lookup_us
;
2824 const WCHAR
*lang
= ai
->language
;
2825 unsigned int data_pos
= 0, data_len
;
2828 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2829 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2830 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2831 + sizeof(lookup_fmtW
) )))
2834 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2835 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2836 ai
->version
.major
, ai
->version
.minor
, lang
);
2837 RtlInitUnicodeString( &lookup_us
, lookup
);
2839 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2840 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
2842 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2843 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2845 ULONG build
, revision
;
2847 data_len
= (ULONG
)io
.Information
;
2851 if (data_pos
>= data_len
)
2853 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2854 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
2856 data_len
= (ULONG
)io
.Information
;
2859 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2861 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2862 else data_pos
= data_len
;
2864 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2866 if (build
< min_build
) continue;
2867 tmp
= strchrW(tmp
, '.') + 1;
2868 revision
= atoiW(tmp
);
2869 if (build
== min_build
&& revision
< min_revision
) continue;
2870 tmp
= strchrW(tmp
, '_') + 1;
2871 tmp
= strchrW(tmp
, '_') + 1;
2872 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2873 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2875 /* prefer a non-Wine manifest if we already have one */
2876 /* we'll still load the builtin dll if specified through DllOverrides */
2882 min_revision
= revision
;
2884 ai
->version
.build
= build
;
2885 ai
->version
.revision
= revision
;
2886 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
2887 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2889 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2890 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2894 else DPRINT1("no matching file for %S\n", lookup
);
2895 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
2899 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2901 struct assembly_identity sxs_ai
;
2902 UNICODE_STRING path_us
;
2903 OBJECT_ATTRIBUTES attr
;
2905 WCHAR
*path
, *file
= NULL
;
2908 static const WCHAR manifest_dirW
[] =
2909 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2911 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2913 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2914 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
2915 return STATUS_NO_MEMORY
;
2917 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
2918 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
2920 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2922 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2923 return STATUS_NO_SUCH_FILE
;
2925 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2927 attr
.Length
= sizeof(attr
);
2928 attr
.RootDirectory
= 0;
2929 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2930 attr
.ObjectName
= &path_us
;
2931 attr
.SecurityDescriptor
= NULL
;
2932 attr
.SecurityQualityOfService
= NULL
;
2934 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2935 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2938 file
= lookup_manifest_file( handle
, &sxs_ai
);
2943 RtlFreeUnicodeString( &path_us
);
2944 return STATUS_NO_SUCH_FILE
;
2947 /* append file name to directory path */
2948 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
2949 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2951 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2952 RtlFreeUnicodeString( &path_us
);
2953 return STATUS_NO_MEMORY
;
2956 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2957 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2958 RtlInitUnicodeString( &path_us
, path
);
2959 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2961 if (!open_nt_file( &handle
, &path_us
))
2963 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2966 else io
.Status
= STATUS_NO_SUCH_FILE
;
2968 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2969 RtlFreeUnicodeString( &path_us
);
2973 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2974 struct assembly_identity
* ai
)
2976 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2978 WCHAR
*buffer
, *p
, *directory
;
2980 UNICODE_STRING nameW
;
2984 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2985 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
2987 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2989 /* FIXME: add support for language specific lookup */
2991 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2992 strlenW(acl
->actctx
->appdir
.info
));
2994 nameW
.Buffer
= NULL
;
2995 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2996 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2997 return STATUS_NO_MEMORY
;
2999 if (!(directory
= build_assembly_dir( ai
)))
3001 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3002 return STATUS_NO_MEMORY
;
3005 /* Lookup in <dir>\name.dll
3006 * <dir>\name.manifest
3007 * <dir>\name\name.dll
3008 * <dir>\name\name.manifest
3010 * First 'appdir' is used as <dir>, if that failed
3011 * it tries application manifest file path.
3013 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3014 p
= buffer
+ strlenW(buffer
);
3015 for (i
= 0; i
< 4; i
++)
3019 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3020 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3024 strcpyW( p
, ai
->name
);
3027 strcpyW( p
, dotDllW
);
3028 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3030 status
= open_nt_file( &file
, &nameW
);
3033 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3034 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3038 RtlFreeUnicodeString( &nameW
);
3041 strcpyW( p
, dotManifestW
);
3042 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3044 status
= open_nt_file( &file
, &nameW
);
3047 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3051 RtlFreeUnicodeString( &nameW
);
3053 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3055 RtlFreeUnicodeString( &nameW
);
3056 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3057 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3061 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3063 NTSTATUS status
= STATUS_SUCCESS
;
3066 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3068 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3070 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3072 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3073 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3074 acl
->dependencies
[i
].name
,
3075 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3076 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3081 /* FIXME should now iterate through all refs */
3085 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3086 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3088 NTSTATUS status
= STATUS_SUCCESS
;
3090 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3092 if (*handle
) return STATUS_INVALID_PARAMETER
;
3094 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3095 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3097 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3100 LDR_DATA_TABLE_ENTRY
*pldr
;
3102 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3104 LdrLockLoaderLock( 0, NULL
, &magic
);
3105 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3107 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3108 status
= STATUS_DLL_NOT_FOUND
;
3110 *handle
= pldr
->EntryPointActivationContext
;
3112 else status
= STATUS_DLL_NOT_FOUND
;
3113 LdrUnlockLoaderLock( 0, magic
);
3115 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3116 *handle
= process_actctx
;
3121 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3123 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3124 struct strsection_header
*header
;
3125 struct dllredirect_data
*data
;
3126 struct string_index
*index
;
3129 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3131 /* compute section length */
3132 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3134 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3135 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3137 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3139 /* each entry needs index, data and string data */
3140 total_len
+= sizeof(*index
);
3141 total_len
+= sizeof(*data
);
3142 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3144 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3147 dll_count
+= assembly
->num_dlls
;
3150 total_len
+= sizeof(*header
);
3152 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3153 if (!header
) return STATUS_NO_MEMORY
;
3155 memset(header
, 0, sizeof(*header
));
3156 header
->magic
= STRSECTION_MAGIC
;
3157 header
->size
= sizeof(*header
);
3158 header
->count
= dll_count
;
3159 header
->index_offset
= sizeof(*header
);
3160 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3161 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3163 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3165 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3167 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3169 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3171 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3175 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3176 /* setup new index entry */
3177 str
.Buffer
= dll
->name
;
3178 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3179 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3180 /* hash original class name */
3181 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3183 index
->name_offset
= name_offset
;
3184 index
->name_len
= str
.Length
;
3185 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3186 index
->data_len
= sizeof(*data
);
3187 index
->rosterindex
= i
+ 1;
3190 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3191 data
->size
= sizeof(*data
);
3192 data
->unk
= 2; /* FIXME: seems to be constant */
3193 memset(data
->res
, 0, sizeof(data
->res
));
3196 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3197 memcpy(ptrW
, dll
->name
, index
->name_len
);
3198 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3200 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3208 return STATUS_SUCCESS
;
3211 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3213 struct string_index
*iter
, *index
= NULL
;
3216 DPRINT("section %p, name %wZ\n", section
, name
);
3217 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3218 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3220 for (i
= 0; i
< section
->count
; i
++)
3222 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3223 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3224 if (iter
->hash
== hash
)
3226 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3228 if (!_wcsnicmp(nameW
, name
->Buffer
, name
->Length
/ sizeof(WCHAR
)) &&
3229 wcslen(nameW
) == name
->Length
/ sizeof(WCHAR
))
3235 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3243 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3245 struct guid_index
*iter
, *index
= NULL
;
3248 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3250 for (i
= 0; i
< section
->count
; i
++)
3252 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3263 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3265 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3268 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3269 PACTCTX_SECTION_KEYED_DATA data
)
3271 struct dllredirect_data
*dll
;
3272 struct string_index
*index
;
3274 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3275 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3277 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3278 if (!actctx
->dllredirect_section
)
3280 struct strsection_header
*section
;
3282 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3283 if (status
) return status
;
3285 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3286 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3289 index
= find_string_index(actctx
->dllredirect_section
, name
);
3290 DPRINT("index: %d\n", index
);
3291 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3295 dll
= get_dllredirect_data(actctx
, index
);
3297 data
->ulDataFormatVersion
= 1;
3299 data
->ulLength
= dll
->size
;
3300 data
->lpSectionGlobalData
= NULL
;
3301 data
->ulSectionGlobalDataLength
= 0;
3302 data
->lpSectionBase
= actctx
->dllredirect_section
;
3303 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3304 data
->hActCtx
= NULL
;
3306 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3307 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3310 return STATUS_SUCCESS
;
3313 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3315 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3318 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3320 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3323 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3325 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3326 struct wndclass_redirect_data
*data
;
3327 struct strsection_header
*header
;
3328 struct string_index
*index
;
3331 /* compute section length */
3332 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3334 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3335 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3337 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3338 for (k
= 0; k
< dll
->entities
.num
; k
++)
3340 struct entity
*entity
= &dll
->entities
.base
[k
];
3341 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3343 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3346 /* each class entry needs index, data and string data */
3347 total_len
+= sizeof(*index
);
3348 total_len
+= sizeof(*data
);
3349 /* original name is stored separately */
3350 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3351 /* versioned name and module name are stored one after another */
3352 if (entity
->u
.class.versioned
)
3353 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3356 len
+= strlenW(dll
->name
) + 1;
3357 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3365 total_len
+= sizeof(*header
);
3367 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3368 if (!header
) return STATUS_NO_MEMORY
;
3370 memset(header
, 0, sizeof(*header
));
3371 header
->magic
= STRSECTION_MAGIC
;
3372 header
->size
= sizeof(*header
);
3373 header
->count
= class_count
;
3374 header
->index_offset
= sizeof(*header
);
3375 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3376 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3378 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3380 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3381 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3383 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3384 for (k
= 0; k
< dll
->entities
.num
; k
++)
3386 struct entity
*entity
= &dll
->entities
.base
[k
];
3387 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3389 static const WCHAR exclW
[] = {'!',0};
3390 ULONG versioned_len
, module_len
;
3394 /* setup new index entry */
3395 str
.Buffer
= entity
->u
.class.name
;
3396 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3397 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3398 /* hash original class name */
3399 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3401 /* include '!' separator too */
3402 if (entity
->u
.class.versioned
)
3403 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3405 versioned_len
= str
.Length
;
3406 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3408 index
->name_offset
= name_offset
;
3409 index
->name_len
= str
.Length
;
3410 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3411 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3412 index
->rosterindex
= i
+ 1;
3415 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3416 data
->size
= sizeof(*data
);
3418 data
->name_len
= versioned_len
;
3419 data
->name_offset
= sizeof(*data
);
3420 data
->module_len
= module_len
;
3421 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3423 /* original class name */
3424 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3425 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3426 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3429 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3430 memcpy(ptrW
, dll
->name
, data
->module_len
);
3431 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3433 /* versioned name */
3434 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3435 if (entity
->u
.class.versioned
)
3437 get_assembly_version(assembly
, ptrW
);
3438 strcatW(ptrW
, exclW
);
3439 strcatW(ptrW
, entity
->u
.class.name
);
3443 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3444 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3447 name_offset
+= sizeof(*data
);
3448 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3458 return STATUS_SUCCESS
;
3461 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3462 PACTCTX_SECTION_KEYED_DATA data
)
3464 struct string_index
*iter
, *index
= NULL
;
3465 struct wndclass_redirect_data
*class;
3469 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3471 if (!actctx
->wndclass_section
)
3473 struct strsection_header
*section
;
3475 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3476 if (status
) return status
;
3478 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3479 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3483 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3484 iter
= get_wndclass_first_index(actctx
);
3486 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3488 if (iter
->hash
== hash
)
3490 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3492 if (!strcmpiW(nameW
, name
->Buffer
))
3498 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3503 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3507 class = get_wndclass_data(actctx
, index
);
3509 data
->ulDataFormatVersion
= 1;
3510 data
->lpData
= class;
3511 /* full length includes string length with nulls */
3512 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3513 data
->lpSectionGlobalData
= NULL
;
3514 data
->ulSectionGlobalDataLength
= 0;
3515 data
->lpSectionBase
= actctx
->wndclass_section
;
3516 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3517 data
->hActCtx
= NULL
;
3519 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3520 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3523 return STATUS_SUCCESS
;
3526 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3528 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3529 struct guidsection_header
*header
;
3530 ULONG module_offset
, data_offset
;
3531 struct tlibredirect_data
*data
;
3532 struct guid_index
*index
;
3534 /* compute section length */
3535 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3537 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3538 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3540 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3541 for (k
= 0; k
< dll
->entities
.num
; k
++)
3543 struct entity
*entity
= &dll
->entities
.base
[k
];
3544 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3546 /* each entry needs index, data and string data for module name and help string */
3547 total_len
+= sizeof(*index
);
3548 total_len
+= sizeof(*data
);
3549 /* help string is stored separately */
3550 if (*entity
->u
.typelib
.helpdir
)
3551 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3553 /* module names are packed one after another */
3554 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3562 total_len
+= aligned_string_len(names_len
);
3563 total_len
+= sizeof(*header
);
3565 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3566 if (!header
) return STATUS_NO_MEMORY
;
3568 memset(header
, 0, sizeof(*header
));
3569 header
->magic
= GUIDSECTION_MAGIC
;
3570 header
->size
= sizeof(*header
);
3571 header
->count
= tlib_count
;
3572 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3573 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3574 module_offset
= sizeof(*header
);
3575 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3577 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3579 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3580 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3582 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3583 for (k
= 0; k
< dll
->entities
.num
; k
++)
3585 struct entity
*entity
= &dll
->entities
.base
[k
];
3586 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3588 ULONG module_len
, help_len
;
3592 if (*entity
->u
.typelib
.helpdir
)
3593 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3597 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3599 /* setup new index entry */
3600 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3601 RtlGUIDFromString(&str
, &index
->guid
);
3602 index
->data_offset
= data_offset
;
3603 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3604 index
->rosterindex
= i
+ 1;
3607 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3608 data
->size
= sizeof(*data
);
3610 data
->name_len
= module_len
;
3611 data
->name_offset
= module_offset
;
3612 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3614 data
->flags
= entity
->u
.typelib
.flags
;
3615 data
->help_len
= help_len
;
3616 data
->help_offset
= sizeof(*data
);
3617 data
->major_version
= entity
->u
.typelib
.major
;
3618 data
->minor_version
= entity
->u
.typelib
.minor
;
3621 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3622 memcpy(ptrW
, dll
->name
, data
->name_len
);
3623 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3628 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3629 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3630 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3633 data_offset
+= sizeof(*data
);
3635 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3637 module_offset
+= module_len
+ sizeof(WCHAR
);
3647 return STATUS_SUCCESS
;
3650 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3652 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3655 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3657 struct guid_index
*index
= NULL
;
3658 struct tlibredirect_data
*tlib
;
3660 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3662 if (!actctx
->tlib_section
)
3664 struct guidsection_header
*section
;
3666 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3667 if (status
) return status
;
3669 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3670 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3673 index
= find_guid_index(actctx
->tlib_section
, guid
);
3674 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3676 tlib
= get_tlib_data(actctx
, index
);
3678 data
->ulDataFormatVersion
= 1;
3679 data
->lpData
= tlib
;
3680 /* full length includes string length with nulls */
3681 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3682 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3683 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3684 data
->lpSectionBase
= actctx
->tlib_section
;
3685 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3686 data
->hActCtx
= NULL
;
3688 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3689 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3691 return STATUS_SUCCESS
;
3694 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3696 ULONG
*ptr
= (ULONG
*)guid
;
3699 /* GUID is 16 bytes long */
3700 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3701 *ptr
= RtlUniform(seed
);
3703 guid
->Data3
&= 0x0fff;
3704 guid
->Data3
|= (4 << 12);
3705 guid
->Data4
[0] &= 0x3f;
3706 guid
->Data4
[0] |= 0x80;
3709 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3710 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3714 for (i
= 0; i
< entities
->num
; i
++)
3716 struct entity
*entity
= &entities
->base
[i
];
3717 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3719 /* each entry needs two index entries, extra one goes for alias GUID */
3720 *len
+= 2*sizeof(struct guid_index
);
3721 /* To save some memory we don't allocated two data structures,
3722 instead alias index and normal index point to the same data structure. */
3723 *len
+= sizeof(struct comclassredirect_data
);
3725 /* for clrClass store some more */
3726 if (entity
->u
.comclass
.name
)
3728 unsigned int str_len
;
3730 /* all string data is stored together in aligned block */
3731 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3732 if (entity
->u
.comclass
.progid
)
3733 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3734 if (entity
->u
.comclass
.version
)
3735 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3737 *len
+= sizeof(struct clrclass_data
);
3738 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3740 /* module name is forced to mscoree.dll, and stored two times with different case */
3741 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3745 /* progid string is stored separately */
3746 if (entity
->u
.comclass
.progid
)
3747 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3749 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3757 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3758 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3759 ULONG
*seed
, ULONG rosterindex
)
3763 for (i
= 0; i
< entities
->num
; i
++)
3765 struct entity
*entity
= &entities
->base
[i
];
3766 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3768 ULONG module_len
, progid_len
, str_len
= 0;
3769 struct comclassredirect_data
*data
;
3770 struct guid_index
*alias_index
;
3771 struct clrclass_data
*clrdata
;
3775 if (entity
->u
.comclass
.progid
)
3776 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3780 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3782 /* setup new index entry */
3783 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3784 RtlGUIDFromString(&str
, &(*index
)->guid
);
3786 (*index
)->data_offset
= *data_offset
;
3787 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3788 (*index
)->rosterindex
= rosterindex
;
3790 /* Setup new index entry for alias guid. Alias index records are placed after
3791 normal records, so normal guids are hit first on search. Note that class count
3793 alias_index
= (*index
) + section
->count
/2;
3794 generate_uuid(seed
, &alias_index
->guid
);
3795 alias_index
->data_offset
= (*index
)->data_offset
;
3796 alias_index
->data_len
= 0;
3797 alias_index
->rosterindex
= (*index
)->rosterindex
;
3800 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3801 data
->size
= sizeof(*data
);
3805 data
->model
= entity
->u
.comclass
.model
;
3806 data
->clsid
= (*index
)->guid
;
3807 data
->alias
= alias_index
->guid
;
3808 data
->clsid2
= data
->clsid
;
3809 if (entity
->u
.comclass
.tlbid
)
3811 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3812 RtlGUIDFromString(&str
, &data
->tlbid
);
3815 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3816 data
->name_len
= module_len
;
3817 data
->name_offset
= *module_offset
;
3818 data
->progid_len
= progid_len
;
3819 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3820 data
->clrdata_len
= 0; /* will be set later */
3821 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3822 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3823 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3824 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3825 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3826 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3828 /* mask describes which misc* data is available */
3830 if (data
->miscstatus
)
3831 data
->miscmask
|= MiscStatus
;
3832 if (data
->miscstatuscontent
)
3833 data
->miscmask
|= MiscStatusContent
;
3834 if (data
->miscstatusthumbnail
)
3835 data
->miscmask
|= MiscStatusThumbnail
;
3836 if (data
->miscstatusicon
)
3837 data
->miscmask
|= MiscStatusIcon
;
3838 if (data
->miscstatusdocprint
)
3839 data
->miscmask
|= MiscStatusDocPrint
;
3841 if (data
->clrdata_offset
)
3843 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3845 clrdata
->size
= sizeof(*clrdata
);
3846 clrdata
->res
[0] = 0;
3847 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3848 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3849 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3850 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3851 clrdata
->name_offset
= clrdata
->size
;
3852 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3853 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3854 clrdata
->res2
[0] = 0;
3855 clrdata
->res2
[1] = 0;
3857 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3860 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3861 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3862 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3864 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3865 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3866 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3869 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3870 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3871 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3873 /* runtime version, optional */
3874 if (clrdata
->version_len
)
3876 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3878 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3879 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3880 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3883 if (data
->progid_len
)
3884 data
->progid_offset
+= data
->clrdata_len
;
3885 (*index
)->data_len
+= sizeof(*clrdata
);
3892 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3893 memcpy(ptrW
, dll
->name
, data
->name_len
);
3894 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3898 if (data
->progid_len
)
3900 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3901 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3902 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3905 /* string block length */
3909 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3910 if (clrdata
->version_len
)
3911 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3914 str_len
+= progid_len
+ sizeof(WCHAR
);
3916 (*index
)->data_len
+= aligned_string_len(str_len
);
3917 alias_index
->data_len
= (*index
)->data_len
;
3919 /* move to next data record */
3920 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3921 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3925 (*data_offset
) += sizeof(*clrdata
);
3926 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3933 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3935 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3936 struct guidsection_header
*header
;
3937 ULONG module_offset
, data_offset
;
3938 struct guid_index
*index
;
3941 /* compute section length */
3942 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3944 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3945 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3946 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3948 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3949 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3953 total_len
+= aligned_string_len(names_len
);
3954 total_len
+= sizeof(*header
);
3956 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3957 if (!header
) return STATUS_NO_MEMORY
;
3959 memset(header
, 0, sizeof(*header
));
3960 header
->magic
= GUIDSECTION_MAGIC
;
3961 header
->size
= sizeof(*header
);
3962 header
->count
= 2*class_count
;
3963 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3964 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3965 module_offset
= sizeof(*header
);
3966 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3968 seed
= NtGetTickCount();
3969 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3971 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3972 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3973 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3975 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3976 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3982 return STATUS_SUCCESS
;
3985 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3987 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3990 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3992 struct comclassredirect_data
*comclass
;
3993 struct guid_index
*index
= NULL
;
3995 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3997 if (!actctx
->comserver_section
)
3999 struct guidsection_header
*section
;
4001 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4002 if (status
) return status
;
4004 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4005 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4008 index
= find_guid_index(actctx
->comserver_section
, guid
);
4009 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4011 comclass
= get_comclass_data(actctx
, index
);
4013 data
->ulDataFormatVersion
= 1;
4014 data
->lpData
= comclass
;
4015 /* full length includes string length with nulls */
4016 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4017 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4018 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4019 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4020 data
->lpSectionBase
= actctx
->comserver_section
;
4021 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4022 data
->hActCtx
= NULL
;
4024 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4025 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4027 return STATUS_SUCCESS
;
4030 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4034 for (i
= 0; i
< entities
->num
; i
++)
4036 struct entity
*entity
= &entities
->base
[i
];
4037 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4039 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4040 if (entity
->u
.ifaceps
.name
)
4041 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4047 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4048 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4052 for (i
= 0; i
< entities
->num
; i
++)
4054 struct entity
*entity
= &entities
->base
[i
];
4055 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4057 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4061 if (entity
->u
.ifaceps
.name
)
4062 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4067 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4068 RtlGUIDFromString(&str
, &(*index
)->guid
);
4069 (*index
)->data_offset
= *data_offset
;
4070 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4071 (*index
)->rosterindex
= rosterindex
;
4073 /* setup data record */
4074 data
->size
= sizeof(*data
);
4075 data
->mask
= entity
->u
.ifaceps
.mask
;
4077 /* proxyStubClsid32 value is only stored for external PS,
4078 if set it's used as iid, otherwise 'iid' attribute value is used */
4079 if (entity
->u
.ifaceps
.ps32
)
4081 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4082 RtlGUIDFromString(&str
, &data
->iid
);
4085 data
->iid
= (*index
)->guid
;
4087 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4089 if (entity
->u
.ifaceps
.tlib
)
4091 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4092 RtlGUIDFromString(&str
, &data
->tlbid
);
4095 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4097 if (entity
->u
.ifaceps
.base
)
4099 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4100 RtlGUIDFromString(&str
, &data
->base
);
4103 memset(&data
->base
, 0, sizeof(data
->base
));
4105 data
->name_len
= name_len
;
4106 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4111 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4112 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4113 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4116 /* move to next record */
4118 *data_offset
+= sizeof(*data
);
4120 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4125 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4127 unsigned int i
, j
, total_len
= 0, count
= 0;
4128 struct guidsection_header
*header
;
4129 struct guid_index
*index
;
4132 /* compute section length */
4133 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4135 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4137 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4138 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4140 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4141 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4145 total_len
+= sizeof(*header
);
4147 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4148 if (!header
) return STATUS_NO_MEMORY
;
4150 memset(header
, 0, sizeof(*header
));
4151 header
->magic
= GUIDSECTION_MAGIC
;
4152 header
->size
= sizeof(*header
);
4153 header
->count
= count
;
4154 header
->index_offset
= sizeof(*header
);
4155 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4156 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4158 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4160 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4162 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4163 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4165 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4166 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4172 return STATUS_SUCCESS
;
4175 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4177 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4180 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4182 struct ifacepsredirect_data
*iface
;
4183 struct guid_index
*index
= NULL
;
4185 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4187 if (!actctx
->ifaceps_section
)
4189 struct guidsection_header
*section
;
4191 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4192 if (status
) return status
;
4194 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4195 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4198 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4199 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4201 iface
= get_ifaceps_data(actctx
, index
);
4203 data
->ulDataFormatVersion
= 1;
4204 data
->lpData
= iface
;
4205 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4206 data
->lpSectionGlobalData
= NULL
;
4207 data
->ulSectionGlobalDataLength
= 0;
4208 data
->lpSectionBase
= actctx
->ifaceps_section
;
4209 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4210 data
->hActCtx
= NULL
;
4212 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4213 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4215 return STATUS_SUCCESS
;
4218 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4220 unsigned int i
, j
, total_len
= 0, count
= 0;
4221 struct guidsection_header
*header
;
4222 struct clrsurrogate_data
*data
;
4223 struct guid_index
*index
;
4226 /* compute section length */
4227 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4229 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4230 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4232 struct entity
*entity
= &assembly
->entities
.base
[j
];
4233 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4237 total_len
+= sizeof(*index
) + sizeof(*data
);
4238 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4239 if (entity
->u
.clrsurrogate
.version
)
4240 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4241 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4248 total_len
+= sizeof(*header
);
4250 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4251 if (!header
) return STATUS_NO_MEMORY
;
4253 memset(header
, 0, sizeof(*header
));
4254 header
->magic
= GUIDSECTION_MAGIC
;
4255 header
->size
= sizeof(*header
);
4256 header
->count
= count
;
4257 header
->index_offset
= sizeof(*header
);
4258 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4259 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4261 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4263 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4264 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4266 struct entity
*entity
= &assembly
->entities
.base
[j
];
4267 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4269 ULONG version_len
, name_len
;
4273 if (entity
->u
.clrsurrogate
.version
)
4274 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4277 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4279 /* setup new index entry */
4280 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4281 RtlGUIDFromString(&str
, &index
->guid
);
4283 index
->data_offset
= data_offset
;
4284 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4285 index
->rosterindex
= i
+ 1;
4288 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4289 data
->size
= sizeof(*data
);
4291 data
->clsid
= index
->guid
;
4292 data
->version_offset
= version_len
? data
->size
: 0;
4293 data
->version_len
= version_len
;
4294 data
->name_offset
= data
->size
+ version_len
;
4296 data
->name_offset
+= sizeof(WCHAR
);
4297 data
->name_len
= name_len
;
4299 /* surrogate name */
4300 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4301 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4302 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4304 /* runtime version */
4305 if (data
->version_len
)
4307 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4308 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4309 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4312 data_offset
+= index
->data_offset
;
4320 return STATUS_SUCCESS
;
4323 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4325 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4328 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4330 struct clrsurrogate_data
*surrogate
;
4331 struct guid_index
*index
= NULL
;
4333 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4335 if (!actctx
->clrsurrogate_section
)
4337 struct guidsection_header
*section
;
4339 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4340 if (status
) return status
;
4342 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4343 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4346 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4347 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4349 surrogate
= get_surrogate_data(actctx
, index
);
4351 data
->ulDataFormatVersion
= 1;
4352 data
->lpData
= surrogate
;
4353 /* full length includes string length with nulls */
4354 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4355 if (surrogate
->version_len
)
4356 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4358 data
->lpSectionGlobalData
= NULL
;
4359 data
->ulSectionGlobalDataLength
= 0;
4360 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4361 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4362 data
->hActCtx
= NULL
;
4364 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4365 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4367 return STATUS_SUCCESS
;
4370 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4372 unsigned int i
, j
, single_len
;
4374 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4375 for (i
= 0; i
< entities
->num
; i
++)
4377 struct entity
*entity
= &entities
->base
[i
];
4378 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4380 if (entity
->u
.comclass
.progid
)
4382 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4386 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4387 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4389 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4390 *count
+= entity
->u
.comclass
.progids
.num
;
4395 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4396 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4398 struct progidredirect_data
*data
;
4403 /* setup new index entry */
4405 /* hash progid name */
4406 RtlInitUnicodeString(&str
, progid
);
4407 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4409 (*index
)->name_offset
= *data_offset
;
4410 (*index
)->name_len
= str
.Length
;
4411 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4412 (*index
)->data_len
= sizeof(*data
);
4413 (*index
)->rosterindex
= rosterindex
;
4415 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4417 /* setup data structure */
4418 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4419 data
->size
= sizeof(*data
);
4421 data
->clsid_offset
= *global_offset
;
4423 /* write progid string */
4424 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4425 memcpy(ptrW
, progid
, (*index
)->name_len
);
4426 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4428 /* write guid to global area */
4429 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4433 *global_offset
+= sizeof(GUID
);
4434 *data_offset
+= data
->size
;
4438 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4439 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4443 for (i
= 0; i
< entities
->num
; i
++)
4445 struct entity
*entity
= &entities
->base
[i
];
4446 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4448 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4449 struct comclassredirect_data
*comclass
;
4450 struct guid_index
*guid_index
;
4454 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4455 RtlGUIDFromString(&str
, &clsid
);
4457 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4458 comclass
= get_comclass_data(actctx
, guid_index
);
4460 if (entity
->u
.comclass
.progid
)
4461 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4462 index
, data_offset
, global_offset
, rosterindex
);
4464 for (j
= 0; j
< progids
->num
; j
++)
4465 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4466 index
, data_offset
, global_offset
, rosterindex
);
4471 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4473 unsigned int i
, j
, total_len
= 0, count
= 0;
4474 struct strsection_header
*header
;
4475 ULONG data_offset
, global_offset
;
4476 struct string_index
*index
;
4478 /* compute section length */
4479 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4481 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4483 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4484 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4486 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4487 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4491 total_len
+= sizeof(*header
);
4493 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4494 if (!header
) return STATUS_NO_MEMORY
;
4496 memset(header
, 0, sizeof(*header
));
4497 header
->magic
= STRSECTION_MAGIC
;
4498 header
->size
= sizeof(*header
);
4499 header
->count
= count
;
4500 header
->global_offset
= header
->size
;
4501 header
->global_len
= count
*sizeof(GUID
);
4502 header
->index_offset
= header
->size
+ header
->global_len
;
4504 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4505 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4506 global_offset
= header
->global_offset
;
4508 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4510 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4512 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4513 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4515 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4516 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4522 return STATUS_SUCCESS
;
4525 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4527 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4530 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4531 PACTCTX_SECTION_KEYED_DATA data
)
4533 struct progidredirect_data
*progid
;
4534 struct string_index
*index
;
4536 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4538 if (!actctx
->comserver_section
)
4540 struct guidsection_header
*section
;
4542 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4543 if (status
) return status
;
4545 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4546 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4549 if (!actctx
->progid_section
)
4551 struct strsection_header
*section
;
4553 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4554 if (status
) return status
;
4556 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4557 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4560 index
= find_string_index(actctx
->progid_section
, name
);
4561 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4565 progid
= get_progid_data(actctx
, index
);
4567 data
->ulDataFormatVersion
= 1;
4568 data
->lpData
= progid
;
4569 data
->ulLength
= progid
->size
;
4570 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4571 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4572 data
->lpSectionBase
= actctx
->progid_section
;
4573 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4574 data
->hActCtx
= NULL
;
4576 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4577 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4580 return STATUS_SUCCESS
;
4583 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4584 const UNICODE_STRING
*section_name
,
4585 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4589 switch (section_kind
)
4591 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4592 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4593 return STATUS_SXS_KEY_NOT_FOUND
;
4594 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4595 status
= find_dll_redirection(actctx
, section_name
, data
);
4597 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4598 status
= find_window_class(actctx
, section_name
, data
);
4600 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4601 status
= find_progid_redirection(actctx
, section_name
, data
);
4603 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4604 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4605 return STATUS_SXS_SECTION_NOT_FOUND
;
4607 DPRINT1("Unknown section_kind %x\n", section_kind
);
4608 return STATUS_SXS_SECTION_NOT_FOUND
;
4611 if (status
!= STATUS_SUCCESS
) return status
;
4613 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4615 actctx_addref(actctx
);
4616 data
->hActCtx
= actctx
;
4618 return STATUS_SUCCESS
;
4621 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4622 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4626 switch (section_kind
)
4628 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4629 status
= find_tlib_redirection(actctx
, guid
, data
);
4631 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4632 status
= find_comserver_redirection(actctx
, guid
, data
);
4634 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4635 status
= find_cominterface_redirection(actctx
, guid
, data
);
4637 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4638 status
= find_clr_surrogate(actctx
, guid
, data
);
4641 DPRINT("Unknown section_kind %x\n", section_kind
);
4642 return STATUS_SXS_SECTION_NOT_FOUND
;
4645 if (status
!= STATUS_SUCCESS
) return status
;
4647 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4649 actctx_addref(actctx
);
4650 data
->hActCtx
= actctx
;
4652 return STATUS_SUCCESS
;
4655 /* initialize the activation context for the current process */
4656 void actctx_init(void)
4661 ctx
.cbSize
= sizeof(ctx
);
4662 ctx
.lpSource
= NULL
;
4663 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4664 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4665 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4667 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4669 process_actctx
= check_actctx(handle
);
4673 /* FUNCTIONS ***************************************************************/
4675 /***********************************************************************
4676 * RtlCreateActivationContext (NTDLL.@)
4678 * Create an activation context.
4682 RtlCreateActivationContext(IN ULONG Flags
,
4683 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4684 IN ULONG ExtraBytes
,
4685 IN PVOID NotificationRoutine
,
4686 IN PVOID NotificationContext
,
4687 OUT PACTIVATION_CONTEXT
*ActCtx
)
4689 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4690 const WCHAR
*directory
= NULL
;
4691 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4692 ACTIVATION_CONTEXT
*actctx
;
4693 UNICODE_STRING nameW
;
4695 NTSTATUS status
= STATUS_NO_MEMORY
;
4697 struct actctx_loader acl
;
4699 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4701 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4702 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4703 return STATUS_INVALID_PARAMETER
;
4706 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4707 return STATUS_NO_MEMORY
;
4709 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4711 actctx
= &ActualActCtx
->ActivationContext
;
4712 actctx
->RefCount
= 1;
4713 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4714 actctx
->config
.info
= NULL
;
4715 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4716 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4718 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4726 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4727 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4729 status
= get_module_filename( module
, &dir
, 0 );
4730 if (!NT_SUCCESS(status
)) goto error
;
4731 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4732 actctx
->appdir
.info
= dir
.Buffer
;
4735 nameW
.Buffer
= NULL
;
4737 /* open file only if it's going to be used */
4738 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4739 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4741 WCHAR
*source
= NULL
;
4744 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4745 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
4747 DWORD dir_len
, source_len
;
4749 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4750 source_len
= strlenW(pActCtx
->lpSource
);
4751 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4753 status
= STATUS_NO_MEMORY
;
4757 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4758 source
[dir_len
] = '\\';
4759 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4762 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4763 RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
4766 status
= STATUS_NO_SUCH_FILE
;
4769 status
= open_nt_file( &file
, &nameW
);
4770 if (!NT_SUCCESS(status
))
4772 RtlFreeUnicodeString( &nameW
);
4777 acl
.actctx
= actctx
;
4778 acl
.dependencies
= NULL
;
4779 acl
.num_dependencies
= 0;
4780 acl
.allocated_dependencies
= 0;
4782 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4783 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4785 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4787 /* if we have a resource it's a PE file */
4788 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4790 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4791 pActCtx
->lpResourceName
, lang
);
4792 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4793 /* FIXME: what to do if pActCtx->lpSource is set */
4794 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4795 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4797 else if (pActCtx
->lpSource
)
4799 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4800 file
, pActCtx
->lpResourceName
, lang
);
4801 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4802 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4803 NULL
, pActCtx
->lpResourceName
);
4805 else status
= STATUS_INVALID_PARAMETER
;
4809 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4812 if (file
) NtClose( file
);
4813 RtlFreeUnicodeString( &nameW
);
4815 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
4816 free_depend_manifests( &acl
);
4818 if (NT_SUCCESS(status
))
4820 else actctx_release( actctx
);
4824 if (file
) NtClose( file
);
4825 actctx_release( actctx
);
4830 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4834 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
4836 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
4837 LONG OldRefCount
, NewRefCount
;
4839 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4841 RtlpValidateActCtx(ActCtx
);
4845 OldRefCount
= ActCtx
->RefCount
;
4846 ASSERT(OldRefCount
> 0);
4848 if (OldRefCount
== LONG_MAX
) break;
4850 NewRefCount
= OldRefCount
+ 1;
4851 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
4853 OldRefCount
) == OldRefCount
)
4859 NewRefCount
= LONG_MAX
;
4860 ASSERT(NewRefCount
> 0);
4866 RtlReleaseActivationContext( HANDLE handle
)
4868 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
4870 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4872 RtlpValidateActCtx(ActCtx
);
4874 actctx_release(ActCtx
);
4879 /***********************************************************************
4880 * RtlAddRefActivationContext (NTDLL.@)
4882 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
4884 ACTIVATION_CONTEXT
*actctx
;
4886 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4890 /******************************************************************
4891 * RtlReleaseActivationContext (NTDLL.@)
4893 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
4895 ACTIVATION_CONTEXT
*actctx
;
4897 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4902 /******************************************************************
4903 * RtlZombifyActivationContext (NTDLL.@)
4906 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
4910 if (Context
== ACTCTX_FAKE_HANDLE
)
4911 return STATUS_SUCCESS
;
4913 return STATUS_NOT_IMPLEMENTED
;
4917 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
4919 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4921 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
4922 return STATUS_NO_MEMORY
;
4924 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
4925 frame
->ActivationContext
= handle
;
4928 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4929 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
4932 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
4933 RtlAddRefActivationContext( handle
);
4935 *cookie
= (ULONG_PTR
)frame
;
4936 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
4937 return STATUS_SUCCESS
;
4940 /******************************************************************
4941 * RtlActivateActivationContext (NTDLL.@)
4943 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
4945 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
4948 /***********************************************************************
4949 * RtlDeactivateActivationContext (NTDLL.@)
4951 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4953 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4955 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
4957 /* find the right frame */
4958 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
4959 for (frame
= top
; frame
; frame
= frame
->Previous
)
4960 if ((ULONG_PTR
)frame
== cookie
) break;
4963 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4965 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
4966 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4968 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4969 NtCurrentTeb()->ActivationContextStackPointer
,
4970 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
4973 /* pop everything up to and including frame */
4974 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
4976 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
4978 frame
= top
->Previous
;
4979 RtlReleaseActivationContext( top
->ActivationContext
);
4980 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
4984 return STATUS_SUCCESS
;
4989 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
4991 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
4993 /* Nothing to do if there is no stack */
4996 /* Get the current active frame */
4997 ActiveFrame
= Stack
->ActiveFrame
;
4999 /* Go through them in backwards order and release */
5002 PrevFrame
= ActiveFrame
->Previous
;
5003 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5004 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5005 ActiveFrame
= PrevFrame
;
5008 /* Zero out the active frame */
5009 Stack
->ActiveFrame
= NULL
;
5011 /* TODO: Empty the Frame List Cache */
5012 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5014 /* Free activation stack memory */
5015 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5018 /******************************************************************
5019 * RtlFreeThreadActivationContextStack (NTDLL.@)
5021 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5023 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5024 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5028 /******************************************************************
5029 * RtlGetActiveActivationContext (NTDLL.@)
5031 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5033 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5035 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5036 RtlAddRefActivationContext( *handle
);
5041 return STATUS_SUCCESS
;
5045 /******************************************************************
5046 * RtlIsActivationContextActive (NTDLL.@)
5048 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5050 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5052 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5053 if (frame
->ActivationContext
== handle
) return TRUE
;
5058 /***********************************************************************
5059 * RtlQueryInformationActivationContext (NTDLL.@)
5061 * Get information about an activation context.
5062 * FIXME: function signature/prototype may be wrong
5064 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5065 ULONG
class, PVOID buffer
,
5066 SIZE_T bufsize
, SIZE_T
*retlen
)
5068 ACTIVATION_CONTEXT
*actctx
;
5071 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5072 subinst
, class, buffer
, bufsize
, retlen
);
5074 if (retlen
) *retlen
= 0;
5075 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5079 case ActivationContextBasicInformation
:
5081 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5083 if (retlen
) *retlen
= sizeof(*info
);
5084 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5086 info
->hActCtx
= handle
;
5087 info
->dwFlags
= 0; /* FIXME */
5088 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5092 case ActivationContextDetailedInformation
:
5094 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5095 struct assembly
*assembly
= NULL
;
5096 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5099 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5101 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5103 if (assembly
&& assembly
->manifest
.info
)
5104 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5105 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5106 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5107 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5109 if (retlen
) *retlen
= len
;
5110 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5113 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5114 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5115 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5116 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5117 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5118 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5119 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5120 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5121 ptr
= (LPWSTR
)(acdi
+ 1);
5124 acdi
->lpRootManifestPath
= ptr
;
5125 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5126 ptr
+= manifest_len
;
5128 else acdi
->lpRootManifestPath
= NULL
;
5131 acdi
->lpRootConfigurationPath
= ptr
;
5132 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5135 else acdi
->lpRootConfigurationPath
= NULL
;
5138 acdi
->lpAppDirPath
= ptr
;
5139 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5141 else acdi
->lpAppDirPath
= NULL
;
5145 case AssemblyDetailedInformationInActivationContext
:
5147 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5148 struct assembly
*assembly
;
5151 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5154 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5155 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5157 index
= *(DWORD
*)subinst
;
5158 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5160 assembly
= &actctx
->assemblies
[index
- 1];
5162 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5163 id_len
= strlenW(assembly_id
) + 1;
5164 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5166 if (assembly
->manifest
.info
&&
5167 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5168 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5170 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5172 if (retlen
) *retlen
= len
;
5173 if (!buffer
|| bufsize
< len
)
5175 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5176 return STATUS_BUFFER_TOO_SMALL
;
5179 afdi
->ulFlags
= 0; /* FIXME */
5180 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5181 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5182 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5183 /* FIXME afdi->liManifestLastWriteTime = 0; */
5184 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5185 afdi
->ulPolicyPathLength
= 0;
5186 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5187 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5188 afdi
->ulManifestVersionMajor
= 1;
5189 afdi
->ulManifestVersionMinor
= 0;
5190 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5191 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5192 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5193 ptr
= (LPWSTR
)(afdi
+ 1);
5194 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5195 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5199 afdi
->lpAssemblyManifestPath
= ptr
;
5200 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5202 } else afdi
->lpAssemblyManifestPath
= NULL
;
5203 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5206 afdi
->lpAssemblyDirectoryName
= ptr
;
5207 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5209 else afdi
->lpAssemblyDirectoryName
= NULL
;
5210 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5214 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5216 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5217 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5218 struct assembly
*assembly
;
5219 struct dll_redirect
*dll
;
5220 SIZE_T len
, dll_len
= 0;
5223 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5224 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5226 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5227 return STATUS_INVALID_PARAMETER
;
5228 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5230 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5231 return STATUS_INVALID_PARAMETER
;
5232 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5234 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5235 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5237 if (!buffer
|| bufsize
< len
)
5239 if (retlen
) *retlen
= len
;
5240 return STATUS_BUFFER_TOO_SMALL
;
5242 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5243 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5244 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5245 afdi
->ulPathLength
= 0; /* FIXME */
5246 ptr
= (LPWSTR
)(afdi
+ 1);
5249 afdi
->lpFileName
= ptr
;
5250 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5251 } else afdi
->lpFileName
= NULL
;
5252 afdi
->lpFilePath
= NULL
; /* FIXME */
5257 DPRINT( "class %u not implemented\n", class );
5258 return STATUS_NOT_IMPLEMENTED
;
5260 return STATUS_SUCCESS
;
5265 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5267 SIZE_T cbBuffer OPTIONAL
,
5268 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5270 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5276 pcbWrittenOrRequired
);
5279 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5280 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5281 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5285 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5286 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5288 /* Check general parameter combinations */
5289 if (!section_name
|| !section_name
->Buffer
||
5290 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5291 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5292 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5294 DPRINT1("invalid parameter\n");
5295 return STATUS_INVALID_PARAMETER
;
5299 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5300 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5302 DPRINT1("unknown flags %08x\n", flags
);
5303 return STATUS_INVALID_PARAMETER
;
5306 return STATUS_SUCCESS
;
5309 /***********************************************************************
5310 * RtlFindActivationContextSectionString (NTDLL.@)
5312 * Find information about a string in an activation context.
5313 * FIXME: function signature/prototype may be wrong
5315 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5316 const UNICODE_STRING
*section_name
, PVOID ptr
)
5318 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5321 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5322 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5323 if (!NT_SUCCESS(status
))
5325 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5329 status
= STATUS_SXS_KEY_NOT_FOUND
;
5331 /* if there is no data, but params are valid,
5332 we return that sxs key is not found to be at least somehow compatible */
5335 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5339 ASSERT(NtCurrentTeb());
5340 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5342 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5343 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5345 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5346 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5349 DPRINT("status %x\n", status
);
5350 if (status
!= STATUS_SUCCESS
)
5351 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5353 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5357 /***********************************************************************
5358 * RtlFindActivationContextSectionGuid (NTDLL.@)
5360 * Find information about a GUID in an activation context.
5361 * FIXME: function signature/prototype may be wrong
5363 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5364 const GUID
*guid
, void *ptr
)
5366 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5367 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5371 DPRINT1("expected extguid == NULL\n");
5372 return STATUS_INVALID_PARAMETER
;
5375 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5377 DPRINT1("unknown flags %08x\n", flags
);
5378 return STATUS_INVALID_PARAMETER
;
5381 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5382 return STATUS_INVALID_PARAMETER
;
5384 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5386 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5387 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5390 if (status
!= STATUS_SUCCESS
)
5391 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5400 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5402 PACTIVATION_CONTEXT_STACK ContextStack
;
5404 /* Check if it's already allocated */
5405 if (*Stack
) return STATUS_SUCCESS
;
5407 /* Allocate space for the context stack */
5408 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5411 return STATUS_NO_MEMORY
;
5414 /* Initialize the context stack */
5415 ContextStack
->Flags
= 0;
5416 ContextStack
->ActiveFrame
= NULL
;
5417 InitializeListHead(&ContextStack
->FrameListCache
);
5418 ContextStack
->NextCookieSequenceNumber
= 1;
5419 ContextStack
->StackId
= 1; //TODO: Timer-based
5421 *Stack
= ContextStack
;
5423 return STATUS_SUCCESS
;
5426 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5428 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5431 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5432 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5434 /* Get the current active frame */
5435 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5437 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5438 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5439 &Frame
->Frame
, Context
);
5441 /* Ensure it's in the right format and at least fits basic info */
5442 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5443 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5445 /* Set debug info if size allows*/
5446 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5448 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5449 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5450 //Frame->Extra3 = ...;
5455 /*ASSERT((ActiveFrame->Flags &
5456 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5457 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5458 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5460 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5462 // TODO: Perform some additional checks if it was not heap allocated
5466 /* Save pointer to the new activation frame */
5467 NewFrame
= &Frame
->Frame
;
5469 /* Actually activate it */
5470 Frame
->Frame
.Previous
= ActiveFrame
;
5471 Frame
->Frame
.ActivationContext
= Context
;
5472 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5474 /* Check if we can activate this context */
5475 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5478 /* Set new active frame */
5479 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5480 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5484 /* We can get here only one way: it was already activated */
5485 DPRINT("Trying to activate already activated activation context\n");
5487 /* Activate only if we are allowing multiple activation */
5489 if (!RtlpNotAllowingMultipleActivation
)
5491 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5492 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5495 // Activate it anyway
5496 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5499 /* Return pointer to the activation frame */
5503 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5505 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5507 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5509 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5511 /* Ensure it's in the right format and at least fits basic info */
5512 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5513 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5515 /* Make sure it is not deactivated and it is activated */
5516 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5517 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5518 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
);
5520 /* Check debug info if it is present */
5521 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5523 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5524 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5525 //Frame->Extra3 = ...;
5530 // TODO: Perform some additional checks here
5533 /* Special handling for not-really-activated */
5534 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5536 DPRINT1("Deactivating not really activated activation context\n");
5537 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5538 return &Frame
->Frame
;
5541 /* find the right frame */
5542 NewFrame
= &Frame
->Frame
;
5543 if (ActiveFrame
!= NewFrame
)
5545 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5548 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5549 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5551 /* Pop everything up to and including frame */
5552 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5554 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5555 return NewFrame
->Previous
;