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 */
18 #include <ntstrsafe.h>
23 #include <wine/unicode.h>
25 BOOLEAN RtlpNotAllowingMultipleActivation
;
27 #define ACTCTX_FLAGS_ALL (\
28 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
29 ACTCTX_FLAG_LANGID_VALID |\
30 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
31 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
32 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
33 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
34 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
35 ACTCTX_FLAG_HMODULE_VALID )
37 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
38 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
40 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
42 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
43 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
65 struct assembly_version
73 struct assembly_identity
80 struct assembly_version version
;
85 struct strsection_header
99 ULONG hash
; /* key string hash */
102 ULONG data_offset
; /* redirect data offset */
107 struct guidsection_header
127 struct wndclass_redirect_data
132 ULONG name_offset
; /* versioned name offset */
134 ULONG module_offset
;/* container name offset */
137 struct dllredirect_data
144 struct tlibredirect_data
158 enum comclass_threadingmodel
160 ThreadingModel_Apartment
= 1,
161 ThreadingModel_Free
= 2,
162 ThreadingModel_No
= 3,
163 ThreadingModel_Both
= 4,
164 ThreadingModel_Neutral
= 5
167 enum comclass_miscfields
171 MiscStatusContent
= 4,
172 MiscStatusThumbnail
= 8,
173 MiscStatusDocPrint
= 16
176 struct comclassredirect_data
192 ULONG clrdata_offset
;
194 DWORD miscstatuscontent
;
195 DWORD miscstatusthumbnail
;
196 DWORD miscstatusicon
;
197 DWORD miscstatusdocprint
;
206 struct ifacepsredirect_data
218 struct clrsurrogate_data
223 ULONG version_offset
;
238 ULONG version_offset
;
242 struct progidredirect_data
253 Sections are accessible by string or guid key, that defines two types of sections.
254 All sections of each type have same magic value and header structure, index
255 data could be of two possible types too. So every string based section uses
256 the same index format, same applies to guid sections - they share same guid index
259 - window class redirection section is a plain buffer with following format:
263 <data[]> --- <original name>
268 Header is fixed length structure - struct strsection_header,
269 contains redirected classes count;
271 Index is an array of fixed length index records, each record is
274 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
276 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
277 others are relative to section itself.
279 - dll redirect section format:
283 <data[]> --- <dll name>
286 This section doesn't seem to carry any payload data except dll names.
288 - typelib section format:
296 Header is fixed length, index is an array of fixed length 'struct guid_index'.
297 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
298 4-bytes aligned as a whole.
300 Module name offsets are relative to section, helpstring offset is relative to data
303 - comclass section format:
308 <data[]> --- <data> --- <data>
314 This section uses two index records per comclass, one entry contains original guid
315 as specified by context, another one has a generated guid. Index and strings handling
316 is similar to typelib sections.
318 For CLR classes additional data is stored after main COM class data, it contains
319 class name and runtime version string, see 'struct clrclass_data'.
321 Module name offsets are relative to section, progid offset is relative to data
324 - COM interface section format:
331 Interface section contains data for proxy/stubs and external proxy/stubs. External
332 ones are defined at assembly level, so this section has no module information.
333 All records are indexed with 'iid' value from manifest. There an exception for
334 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
335 redirect data, but index is still 'iid' from manifest.
337 Interface name offset is relative to data structure itself.
339 - CLR surrogates section format:
347 There's nothing special about this section, same way to store strings is used,
348 no modules part as it belongs to assembly level, not a file.
350 - ProgID section format:
355 <data[]> --- <progid>
358 This sections uses generated alias guids from COM server section. This way
359 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
360 is stored too, aligned.
367 unsigned int allocated
;
388 WCHAR
*name
; /* clrClass: class name */
389 WCHAR
*version
; /* clrClass: CLR runtime version */
392 DWORD miscstatuscontent
;
393 DWORD miscstatusthumbnail
;
394 DWORD miscstatusicon
;
395 DWORD miscstatusdocprint
;
396 struct progids progids
;
403 WCHAR
*ps32
; /* only stored for 'comInterfaceExternalProxyStub' */
425 unsigned int allocated
;
432 struct entity_array entities
;
437 APPLICATION_MANIFEST
,
439 ASSEMBLY_SHARED_MANIFEST
,
444 enum assembly_type type
;
445 struct assembly_identity id
;
446 struct file_info manifest
;
449 struct dll_redirect
*dlls
;
450 unsigned int num_dlls
;
451 unsigned int allocated_dlls
;
452 struct entity_array entities
;
455 enum context_sections
457 WINDOWCLASS_SECTION
= 1,
458 DLLREDIRECT_SECTION
= 2,
459 TLIBREDIRECT_SECTION
= 4,
460 SERVERREDIRECT_SECTION
= 8,
461 IFACEREDIRECT_SECTION
= 16,
462 CLRSURROGATES_SECTION
= 32,
463 PROGIDREDIRECT_SECTION
= 64
466 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
469 UNICODE_STRING DosPath
;
471 } ASSEMBLY_STORAGE_MAP_ENTRY
, *PASSEMBLY_STORAGE_MAP_ENTRY
;
473 typedef struct _ASSEMBLY_STORAGE_MAP
477 PASSEMBLY_STORAGE_MAP_ENTRY
*AssemblyArray
;
478 } ASSEMBLY_STORAGE_MAP
, *PASSEMBLY_STORAGE_MAP
;
480 typedef struct _ACTIVATION_CONTEXT
485 PACTIVATION_CONTEXT_DATA ActivationContextData
;
486 PVOID NotificationRoutine
;
487 PVOID NotificationContext
;
488 ULONG SentNotifications
[8];
489 ULONG DisabledNotifications
[8];
490 ASSEMBLY_STORAGE_MAP StorageMap
;
491 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries
;
492 ULONG StackTraceIndex
;
493 PVOID StackTraces
[4][4];
494 struct file_info config
;
495 struct file_info appdir
;
496 struct assembly
*assemblies
;
497 unsigned int num_assemblies
;
498 unsigned int allocated_assemblies
;
501 struct strsection_header
*wndclass_section
;
502 struct strsection_header
*dllredirect_section
;
503 struct strsection_header
*progid_section
;
504 struct guidsection_header
*tlib_section
;
505 struct guidsection_header
*comserver_section
;
506 struct guidsection_header
*ifaceps_section
;
507 struct guidsection_header
*clrsurrogate_section
;
508 } ACTIVATION_CONTEXT
, *PIACTIVATION_CONTEXT
;
512 ACTIVATION_CONTEXT
*actctx
;
513 struct assembly_identity
*dependencies
;
514 unsigned int num_dependencies
;
515 unsigned int allocated_dependencies
;
518 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
519 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
521 typedef struct _ACTIVATION_CONTEXT_WRAPPED
524 ACTIVATION_CONTEXT ActivationContext
;
525 } ACTIVATION_CONTEXT_WRAPPED
, *PACTIVATION_CONTEXT_WRAPPED
;
529 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx
,
530 IN ULONG FailureCode
)
532 EXCEPTION_RECORD ExceptionRecord
;
534 /* Fatal SxS exception header */
535 ExceptionRecord
.ExceptionRecord
= NULL
;
536 ExceptionRecord
.ExceptionCode
= STATUS_SXS_CORRUPTION
;
537 ExceptionRecord
.ExceptionFlags
= EXCEPTION_NONCONTINUABLE
;
539 /* With SxS-specific information plus the context itself */
540 ExceptionRecord
.ExceptionInformation
[0] = 1;
541 ExceptionRecord
.ExceptionInformation
[1] = FailureCode
;
542 ExceptionRecord
.ExceptionInformation
[2] = (ULONG_PTR
)ActCtx
;
543 ExceptionRecord
.NumberParameters
= 3;
546 RtlRaiseException(&ExceptionRecord
);
551 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx
)
553 PACTIVATION_CONTEXT_WRAPPED pActual
;
555 /* Get the caller-opaque header */
556 pActual
= CONTAINING_RECORD(ActCtx
,
557 ACTIVATION_CONTEXT_WRAPPED
,
560 /* Check if the header matches as expected */
561 if (pActual
->MagicMarker
!= ACTCTX_MAGIC_MARKER
)
563 /* Nope, print out a warning, assert, and then throw an exception */
564 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
565 " This means someone stepped on the allocation, or someone is using a\n"
566 " deallocated activation context\n",
568 pActual
->MagicMarker
,
570 ASSERT(pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
);
571 RtlpSxsBreakOnInvalidMarker(ActCtx
, 1);
575 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
576 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
577 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
578 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
579 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
580 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
581 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};
582 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};
583 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
584 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
585 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
586 static const WCHAR fileW
[] = {'f','i','l','e',0};
587 static const WCHAR hashW
[] = {'h','a','s','h',0};
588 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
589 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
590 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
591 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
593 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
594 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
595 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
596 static const WCHAR iidW
[] = {'i','i','d',0};
597 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
598 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
599 static const WCHAR g_nameW
[] = {'n','a','m','e',0};
600 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
601 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
602 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
603 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
604 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};
605 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
606 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
607 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
608 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
609 static const WCHAR typeW
[] = {'t','y','p','e',0};
610 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
611 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
612 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
613 static const WCHAR yesW
[] = {'y','e','s',0};
614 static const WCHAR noW
[] = {'n','o',0};
615 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
616 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
617 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
618 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
619 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
620 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
621 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
622 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
623 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
624 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
625 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
626 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
627 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
628 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
629 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
630 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
632 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
633 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
634 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
635 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
636 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
637 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
638 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
639 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};
640 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
641 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
642 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
643 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
644 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
645 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
646 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
647 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
648 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};
649 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
650 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
651 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
652 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};
653 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
661 static const struct olemisc_entry olemisc_values
[] =
663 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
664 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
665 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
666 { alignableW
, OLEMISC_ALIGNABLE
},
667 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
668 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
669 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
670 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
671 { imemodeW
, OLEMISC_IMEMODE
},
672 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
673 { insideoutW
, OLEMISC_INSIDEOUT
},
674 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
675 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
676 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
677 { onlyiconicW
, OLEMISC_ONLYICONIC
},
678 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
679 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
680 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
681 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
682 { staticW
, OLEMISC_STATIC
},
683 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
684 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
687 static const WCHAR g_xmlW
[] = {'?','x','m','l',0};
688 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};
689 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};
690 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};
692 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
693 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
694 static const WCHAR wildcardW
[] = {'*',0};
696 static ACTIVATION_CONTEXT_WRAPPED system_actctx
= { ACTCTX_MAGIC_MARKER
, { 1 } };
697 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
.ActivationContext
;
698 static ACTIVATION_CONTEXT
*implicit_actctx
= &system_actctx
.ActivationContext
;
700 static WCHAR
*strdupW(const WCHAR
* str
)
704 if (!(ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
706 return strcpyW(ptr
, str
);
709 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
713 if ((strW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
715 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
721 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
723 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
726 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
728 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
731 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
733 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
734 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
737 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
739 UINT len
= strlenW( namespace );
741 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
742 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
743 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
746 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
748 if (elem
->len
&& elem
->ptr
[0] == '/')
751 elem_end
.ptr
= elem
->ptr
+ 1;
752 elem_end
.len
= elem
->len
- 1;
753 return xml_elem_cmp( &elem_end
, str
, namespace );
758 static inline BOOL
isxmlspace( WCHAR ch
)
760 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
763 static UNICODE_STRING
xmlstr2unicode(const xmlstr_t
*xmlstr
)
767 res
.Buffer
= (PWSTR
)xmlstr
->ptr
;
768 res
.Length
= res
.MaximumLength
= (USHORT
)xmlstr
->len
* sizeof(WCHAR
);
773 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
775 struct assembly
*assembly
;
777 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx
);
779 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
782 unsigned int new_count
;
783 if (actctx
->assemblies
)
785 new_count
= actctx
->allocated_assemblies
* 2;
786 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
787 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
792 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
794 if (!ptr
) return NULL
;
795 actctx
->assemblies
= ptr
;
796 actctx
->allocated_assemblies
= new_count
;
799 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
804 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
806 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly
, assembly
->allocated_dlls
);
808 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
811 unsigned int new_count
;
814 new_count
= assembly
->allocated_dlls
* 2;
815 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
816 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
821 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
823 if (!ptr
) return NULL
;
824 assembly
->dlls
= ptr
;
825 assembly
->allocated_dlls
= new_count
;
827 return &assembly
->dlls
[assembly
->num_dlls
++];
830 static void free_assembly_identity(struct assembly_identity
*ai
)
832 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->name
);
833 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->arch
);
834 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->public_key
);
835 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->language
);
836 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->type
);
839 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
841 struct entity
* entity
;
843 if (array
->num
== array
->allocated
)
846 unsigned int new_count
;
849 new_count
= array
->allocated
* 2;
850 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
851 array
->base
, new_count
* sizeof(*array
->base
) );
856 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
858 if (!ptr
) return NULL
;
860 array
->allocated
= new_count
;
862 entity
= &array
->base
[array
->num
++];
867 static void free_entity_array(struct entity_array
*array
)
870 for (i
= 0; i
< array
->num
; i
++)
872 struct entity
*entity
= &array
->base
[i
];
873 switch (entity
->kind
)
875 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
876 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
877 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progid
);
879 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.name
);
880 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.version
);
881 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
882 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
883 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
885 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
886 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
887 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
888 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
889 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
890 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
892 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
893 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
894 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
896 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
897 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.class.name
);
899 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
900 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
901 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
902 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
905 DPRINT1("Unknown entity kind %u\n", entity
->kind
);
908 RtlFreeHeap( RtlGetProcessHeap(), 0, array
->base
);
911 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
913 if (!str1
) return !str2
;
914 return str2
&& !strcmpiW( str1
, str2
);
917 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
918 const struct assembly_identity
*id2
)
920 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
921 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
922 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
924 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
926 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
929 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
930 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
931 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
932 if (id1
->version
.build
== id2
->version
.build
&&
933 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
937 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
938 struct assembly_identity
* ai
)
942 /* check if we already have that assembly */
944 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
945 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
947 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
948 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
949 ai
->version
.build
, ai
->version
.revision
);
953 for (i
= 0; i
< acl
->num_dependencies
; i
++)
954 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
956 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
957 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
958 ai
->version
.build
, ai
->version
.revision
);
962 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
965 unsigned int new_count
;
966 if (acl
->dependencies
)
968 new_count
= acl
->allocated_dependencies
* 2;
969 ptr
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl
->dependencies
,
970 new_count
* sizeof(acl
->dependencies
[0]));
975 ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
977 if (!ptr
) return FALSE
;
978 acl
->dependencies
= ptr
;
979 acl
->allocated_dependencies
= new_count
;
981 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
986 static void free_depend_manifests(struct actctx_loader
* acl
)
989 for (i
= 0; i
< acl
->num_dependencies
; i
++)
990 free_assembly_identity(&acl
->dependencies
[i
]);
991 RtlFreeHeap(RtlGetProcessHeap(), 0, acl
->dependencies
);
994 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
996 static const WCHAR undW
[] = {'_',0};
997 static const WCHAR noneW
[] = {'n','o','n','e',0};
998 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
1000 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
1001 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1002 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1003 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1004 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
1005 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1008 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
))) return NULL
;
1010 strcpyW( ret
, arch
);
1011 strcatW( ret
, undW
);
1012 strcatW( ret
, name
);
1013 strcatW( ret
, undW
);
1014 strcatW( ret
, key
);
1015 strcatW( ret
, undW
);
1016 sprintfW( ret
+ strlenW(ret
), version_formatW
,
1017 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1018 strcatW( ret
, undW
);
1019 strcatW( ret
, lang
);
1020 strcatW( ret
, undW
);
1021 strcatW( ret
, mskeyW
);
1025 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1030 strcatW( buffer
, prefix
);
1039 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1041 static const WCHAR archW
[] =
1042 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1043 static const WCHAR public_keyW
[] =
1044 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1045 static const WCHAR typeW2
[] =
1046 {',','t','y','p','e','=',0};
1047 static const WCHAR versionW2
[] =
1048 {',','v','e','r','s','i','o','n','=',0};
1050 WCHAR version
[64], *ret
;
1053 sprintfW( version
, version_formatW
,
1054 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1055 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1056 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1057 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1058 if (ai
->type
) size
+= strlenW(typeW2
) + strlenW(ai
->type
) + 2;
1059 size
+= strlenW(versionW2
) + strlenW(version
) + 2;
1061 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1064 if (ai
->name
) strcpyW( ret
, ai
->name
);
1066 append_string( ret
, archW
, ai
->arch
);
1067 append_string( ret
, public_keyW
, ai
->public_key
);
1068 append_string( ret
, typeW2
, ai
->type
);
1069 append_string( ret
, versionW2
, version
);
1073 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1075 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1076 PACTIVATION_CONTEXT_WRAPPED pActual
;
1078 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1083 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1084 if (pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
) ret
= &pActual
->ActivationContext
;
1087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1089 DPRINT1("Invalid activation context handle!\n");
1095 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1097 InterlockedExchangeAdd( &actctx
->RefCount
, 1 );
1100 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1102 PACTIVATION_CONTEXT_WRAPPED pActual
;
1104 if (InterlockedExchangeAdd(&actctx
->RefCount
, -1) == 1)
1108 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1110 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1111 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1113 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1114 free_entity_array( &dll
->entities
);
1115 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->name
);
1116 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->hash
);
1118 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->dlls
);
1119 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->manifest
.info
);
1120 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->directory
);
1121 free_entity_array( &assembly
->entities
);
1122 free_assembly_identity(&assembly
->id
);
1124 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->config
.info
);
1125 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->appdir
.info
);
1126 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->assemblies
);
1127 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
1128 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
1129 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
1130 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
1131 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
1132 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1133 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
1135 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1136 pActual
->MagicMarker
= 0;
1137 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual
);
1141 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1142 BOOL
* error
, BOOL
* end
)
1148 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1151 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1153 if (*xmlbuf
->ptr
== '/')
1156 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1165 if (*xmlbuf
->ptr
== '>')
1173 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1175 if (ptr
== xmlbuf
->end
) return FALSE
;
1177 name
->ptr
= xmlbuf
->ptr
;
1178 name
->len
= ptr
-xmlbuf
->ptr
;
1181 /* skip spaces before '=' */
1182 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1183 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1185 /* skip '=' itself */
1187 if (ptr
== xmlbuf
->end
) return FALSE
;
1189 /* skip spaces after '=' */
1190 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1192 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1195 if (ptr
== xmlbuf
->end
) return FALSE
;
1197 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1200 xmlbuf
->ptr
= xmlbuf
->end
;
1204 value
->len
= ptr
- value
->ptr
;
1205 xmlbuf
->ptr
= ptr
+ 1;
1207 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1213 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1219 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1222 xmlbuf
->ptr
= xmlbuf
->end
;
1226 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1228 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1229 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1231 if (ptr
+ 3 > xmlbuf
->end
)
1233 xmlbuf
->ptr
= xmlbuf
->end
;
1236 xmlbuf
->ptr
= ptr
+ 3;
1242 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1245 elem
->ptr
= xmlbuf
->ptr
;
1246 elem
->len
= ptr
- xmlbuf
->ptr
;
1248 return xmlbuf
->ptr
!= xmlbuf
->end
;
1251 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1253 /* FIXME: parse attributes */
1256 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1258 if (ptr
[0] == '?' && ptr
[1] == '>')
1260 xmlbuf
->ptr
= ptr
+ 2;
1267 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1269 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1271 if (!ptr
) return FALSE
;
1273 content
->ptr
= xmlbuf
->ptr
;
1274 content
->len
= ptr
- xmlbuf
->ptr
;
1280 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1282 unsigned int ver
[4];
1285 UNICODE_STRING strU
;
1287 /* major.minor.build.revision */
1288 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1289 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1291 if (*curr
>= '0' && *curr
<= '9')
1293 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1294 if (ver
[pos
] >= 0x10000) goto error
;
1296 else if (*curr
== '.')
1298 if (++pos
>= 4) goto error
;
1302 version
->major
= ver
[0];
1303 version
->minor
= ver
[1];
1304 version
->build
= ver
[2];
1305 version
->revision
= ver
[3];
1309 strU
= xmlstr2unicode(str
);
1310 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU
);
1314 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1317 UNICODE_STRING elemU
;
1318 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1319 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1320 elemU
= xmlstr2unicode(&elem
);
1321 DPRINT1( "unexpected element %wZ\n", &elemU
);
1325 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1327 xmlstr_t attr_name
, attr_value
;
1328 UNICODE_STRING attr_nameU
, attr_valueU
;
1331 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1333 attr_nameU
= xmlstr2unicode(&attr_name
);
1334 attr_valueU
= xmlstr2unicode(&attr_value
);
1335 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU
,
1341 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1344 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1347 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1350 UNICODE_STRING elemU
;
1351 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1352 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1354 elemU
= xmlstr2unicode(&elem
);
1355 DPRINT1( "unexpected element %wZ\n", &elemU
);
1358 return parse_end_element(xmlbuf
);
1361 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1363 xmlstr_t attr_name
, attr_value
, elem
;
1364 BOOL end
= FALSE
, error
, ret
= TRUE
;
1366 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1367 if(error
|| end
) return end
;
1369 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1371 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1372 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1375 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1378 return ret
&& parse_end_element(xmlbuf
);
1381 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1382 struct assembly_identity
* ai
)
1384 xmlstr_t attr_name
, attr_value
;
1385 BOOL end
= FALSE
, error
;
1386 UNICODE_STRING attr_valueU
, attr_nameU
;
1388 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1390 if (xmlstr_cmp(&attr_name
, g_nameW
))
1392 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1394 else if (xmlstr_cmp(&attr_name
, typeW
))
1396 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1398 else if (xmlstr_cmp(&attr_name
, versionW
))
1400 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1402 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1404 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1406 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1408 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1410 else if (xmlstr_cmp(&attr_name
, languageW
))
1412 DPRINT("Unsupported yet language attribute (%.*S)\n",
1413 attr_value
.len
, attr_value
.ptr
);
1414 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1418 attr_nameU
= xmlstr2unicode(&attr_name
);
1419 attr_valueU
= xmlstr2unicode(&attr_value
);
1420 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1424 if (error
|| end
) return end
;
1425 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1428 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1430 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1431 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1432 static const WCHAR freeW
[] = {'F','r','e','e',0};
1433 static const WCHAR bothW
[] = {'B','o','t','h',0};
1435 if (value
->len
== 0) return ThreadingModel_No
;
1436 if (xmlstr_cmp(value
, apartW
))
1437 return ThreadingModel_Apartment
;
1438 else if (xmlstr_cmp(value
, freeW
))
1439 return ThreadingModel_Free
;
1440 else if (xmlstr_cmp(value
, bothW
))
1441 return ThreadingModel_Both
;
1442 else if (xmlstr_cmp(value
, neutralW
))
1443 return ThreadingModel_Neutral
;
1445 return ThreadingModel_No
;
1448 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1453 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1461 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1462 if (!c
&& !olemisc_values
[n
].name
[len
])
1463 return olemisc_values
[n
].value
;
1471 DPRINT1("unknown flag %S\n", str
);
1475 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1477 const WCHAR
*str
= value
->ptr
, *start
;
1481 /* it's comma separated list of flags */
1482 while (i
< value
->len
)
1485 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1487 flags
|= get_olemisc_value(start
, str
-start
);
1489 /* skip separator */
1497 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1499 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1501 if (progids
->allocated
== 0)
1503 progids
->allocated
= 4;
1504 if (!(progids
->progids
= RtlAllocateHeap(RtlGetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1507 if (progids
->allocated
== progids
->num
)
1509 WCHAR
**new_progids
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids
->progids
,
1510 2 * progids
->allocated
* sizeof(WCHAR
*));
1511 if (!new_progids
) return FALSE
;
1512 progids
->allocated
*= 2;
1513 progids
->progids
= new_progids
;
1516 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1522 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1527 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1530 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1531 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1534 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1536 xmlstr_t elem
, attr_name
, attr_value
;
1537 BOOL ret
= TRUE
, end
= FALSE
, error
;
1538 struct entity
* entity
;
1539 UNICODE_STRING attr_valueU
, attr_nameU
;
1541 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1544 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1546 if (xmlstr_cmp(&attr_name
, clsidW
))
1548 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1550 else if (xmlstr_cmp(&attr_name
, progidW
))
1552 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1554 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1556 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1558 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1560 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1562 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1564 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1566 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1568 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1570 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1572 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1574 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1576 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1578 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1580 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1582 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1588 attr_nameU
= xmlstr2unicode(&attr_name
);
1589 attr_valueU
= xmlstr2unicode(&attr_value
);
1590 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1594 if (error
) return FALSE
;
1596 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1597 if (entity
->u
.comclass
.progid
)
1598 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1600 if (end
) return TRUE
;
1602 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1604 if (xmlstr_cmp_end(&elem
, comClassW
))
1606 ret
= parse_end_element(xmlbuf
);
1609 else if (xmlstr_cmp(&elem
, progidW
))
1611 ret
= parse_com_class_progid(xmlbuf
, entity
);
1615 attr_nameU
= xmlstr2unicode(&elem
);
1616 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
1617 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1621 if (entity
->u
.comclass
.progids
.num
)
1622 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1627 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1632 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1634 if (*curr
>= '0' && *curr
<= '9')
1635 num
= num
* 10 + *curr
- '0';
1638 UNICODE_STRING strU
= xmlstr2unicode(str
);
1639 DPRINT1("wrong numeric value %wZ\n", &strU
);
1643 entity
->u
.ifaceps
.nummethods
= num
;
1648 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1650 xmlstr_t attr_name
, attr_value
;
1651 BOOL end
= FALSE
, error
;
1652 struct entity
* entity
;
1653 UNICODE_STRING attr_valueU
, attr_nameU
;
1655 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1658 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1660 if (xmlstr_cmp(&attr_name
, iidW
))
1662 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1664 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1666 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1668 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1670 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1671 entity
->u
.ifaceps
.mask
|= BaseIface
;
1673 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1675 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1676 entity
->u
.ifaceps
.mask
|= NumMethods
;
1678 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1680 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1683 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1688 attr_nameU
= xmlstr2unicode(&attr_name
);
1689 attr_valueU
= xmlstr2unicode(&attr_value
);
1690 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1694 if (error
) return FALSE
;
1695 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1696 if (end
) return TRUE
;
1698 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1701 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1703 WORD
*flags
= &entity
->u
.typelib
.flags
;
1704 const WCHAR
*str
= value
->ptr
, *start
;
1709 /* it's comma separated list of flags */
1710 while (i
< value
->len
)
1713 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1715 if (!strncmpiW(start
, restrictedW
, str
-start
))
1716 *flags
|= LIBFLAG_FRESTRICTED
;
1717 else if (!strncmpiW(start
, controlW
, str
-start
))
1718 *flags
|= LIBFLAG_FCONTROL
;
1719 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1720 *flags
|= LIBFLAG_FHIDDEN
;
1721 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1722 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1725 UNICODE_STRING valueU
= xmlstr2unicode(value
);
1726 DPRINT1("unknown flags value %wZ\n", &valueU
);
1730 /* skip separator */
1738 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1740 unsigned int ver
[2];
1743 UNICODE_STRING strW
;
1746 ver
[0] = ver
[1] = pos
= 0;
1747 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1749 if (*curr
>= '0' && *curr
<= '9')
1751 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1752 if (ver
[pos
] >= 0x10000) goto error
;
1754 else if (*curr
== '.')
1756 if (++pos
>= 2) goto error
;
1760 entity
->u
.typelib
.major
= ver
[0];
1761 entity
->u
.typelib
.minor
= ver
[1];
1765 strW
= xmlstr2unicode(str
);
1766 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW
);
1770 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1772 xmlstr_t attr_name
, attr_value
;
1773 BOOL end
= FALSE
, error
;
1774 struct entity
* entity
;
1775 UNICODE_STRING attr_valueU
, attr_nameU
;
1777 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1780 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1782 if (xmlstr_cmp(&attr_name
, tlbidW
))
1784 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1786 else if (xmlstr_cmp(&attr_name
, versionW
))
1788 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1790 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1792 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1794 else if (xmlstr_cmp(&attr_name
, flagsW
))
1796 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1800 attr_nameU
= xmlstr2unicode(&attr_name
);
1801 attr_valueU
= xmlstr2unicode(&attr_value
);
1802 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1806 if (error
) return FALSE
;
1808 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1810 if (end
) return TRUE
;
1812 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1815 static inline int aligned_string_len(int len
)
1817 return (len
+ 3) & ~3;
1820 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1822 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1823 struct assembly_version
*ver
= &assembly
->id
.version
;
1826 if (!ret
) ret
= buff
;
1827 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1830 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1832 xmlstr_t elem
, content
, attr_name
, attr_value
;
1833 BOOL end
= FALSE
, ret
= TRUE
, error
;
1834 struct entity
* entity
;
1835 UNICODE_STRING elemU
, attr_nameU
, attr_valueU
;
1837 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1840 entity
->u
.class.versioned
= TRUE
;
1841 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1843 if (xmlstr_cmp(&attr_name
, versionedW
))
1845 if (xmlstr_cmpi(&attr_value
, noW
))
1846 entity
->u
.class.versioned
= FALSE
;
1847 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1852 attr_nameU
= xmlstr2unicode(&attr_name
);
1853 attr_valueU
= xmlstr2unicode(&attr_value
);
1854 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1858 if (error
|| end
) return end
;
1860 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1862 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1864 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1866 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1868 if (xmlstr_cmp_end(&elem
, windowClassW
))
1870 ret
= parse_end_element(xmlbuf
);
1875 elemU
= xmlstr2unicode(&elem
);
1876 DPRINT1("unknown elem %wZ\n", &elemU
);
1877 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1884 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1886 xmlstr_t attr_name
, attr_value
;
1887 UNICODE_STRING attr_valueU
, attr_nameU
;
1888 BOOL end
= FALSE
, error
;
1890 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1892 attr_nameU
= xmlstr2unicode(&attr_name
);
1893 attr_valueU
= xmlstr2unicode(&attr_value
);
1895 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1897 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU
);
1899 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1901 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU
);
1905 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1909 if (error
|| end
) return end
;
1910 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1913 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1915 xmlstr_t elem
, content
, attr_name
, attr_value
;
1916 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1918 UNICODE_STRING elem1U
, elem2U
;
1920 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1922 elem1U
= xmlstr2unicode(&attr_name
);
1923 elem2U
= xmlstr2unicode(&attr_value
);
1924 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
1927 if (error
) return FALSE
;
1928 if (end
) return TRUE
;
1930 if (!parse_text_content(xmlbuf
, &content
))
1933 elem1U
= xmlstr2unicode(&content
);
1934 DPRINT("Got description %wZ\n", &elem1U
);
1936 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1938 if (xmlstr_cmp_end(&elem
, descriptionW
))
1940 ret
= parse_end_element(xmlbuf
);
1945 elem1U
= xmlstr2unicode(&elem
);
1946 DPRINT1("unknown elem %wZ\n", &elem1U
);
1947 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1954 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1955 struct assembly
* assembly
,
1956 struct actctx_loader
* acl
)
1958 xmlstr_t attr_name
, attr_value
;
1959 UNICODE_STRING attr_nameU
, attr_valueU
;
1960 BOOL end
= FALSE
, error
;
1961 struct entity
* entity
;
1963 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1964 if (!entity
) return FALSE
;
1966 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1968 if (xmlstr_cmp(&attr_name
, iidW
))
1970 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1972 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1974 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1976 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1978 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1979 entity
->u
.ifaceps
.mask
|= BaseIface
;
1981 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1983 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1984 entity
->u
.ifaceps
.mask
|= NumMethods
;
1986 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
1988 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
1990 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1992 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1996 attr_nameU
= xmlstr2unicode(&attr_name
);
1997 attr_valueU
= xmlstr2unicode(&attr_value
);
1998 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2002 if (error
) return FALSE
;
2003 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2004 if (end
) return TRUE
;
2006 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
2009 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2011 xmlstr_t attr_name
, attr_value
, elem
;
2012 BOOL end
= FALSE
, error
, ret
= TRUE
;
2013 struct entity
* entity
;
2015 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
2016 if (!entity
) return FALSE
;
2018 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2020 if (xmlstr_cmp(&attr_name
, g_nameW
))
2022 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2024 else if (xmlstr_cmp(&attr_name
, clsidW
))
2026 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2028 else if (xmlstr_cmp(&attr_name
, progidW
))
2030 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
2032 else if (xmlstr_cmp(&attr_name
, tlbidW
))
2034 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
2036 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
2038 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
2040 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2042 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2046 UNICODE_STRING attr_nameU
, attr_valueU
;
2047 attr_nameU
= xmlstr2unicode(&attr_name
);
2048 attr_valueU
= xmlstr2unicode(&attr_value
);
2049 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2053 if (error
) return FALSE
;
2054 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2055 if (entity
->u
.comclass
.progid
)
2056 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2057 if (end
) return TRUE
;
2059 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2061 if (xmlstr_cmp_end(&elem
, clrClassW
))
2063 ret
= parse_end_element(xmlbuf
);
2066 else if (xmlstr_cmp(&elem
, progidW
))
2068 ret
= parse_com_class_progid(xmlbuf
, entity
);
2072 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2073 DPRINT1("unknown elem %wZ\n", &elemU
);
2074 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2078 if (entity
->u
.comclass
.progids
.num
)
2079 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2084 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2086 xmlstr_t attr_name
, attr_value
;
2087 UNICODE_STRING attr_nameU
, attr_valueU
;
2088 BOOL end
= FALSE
, error
;
2089 struct entity
* entity
;
2091 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
2092 if (!entity
) return FALSE
;
2094 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2096 if (xmlstr_cmp(&attr_name
, g_nameW
))
2098 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2100 else if (xmlstr_cmp(&attr_name
, clsidW
))
2102 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2104 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2106 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2110 attr_nameU
= xmlstr2unicode(&attr_name
);
2111 attr_valueU
= xmlstr2unicode(&attr_value
);
2112 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2116 if (error
) return FALSE
;
2117 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2118 if (end
) return TRUE
;
2120 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2123 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2125 struct assembly_identity ai
;
2126 xmlstr_t elem
, attr_name
, attr_value
;
2127 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2129 UNICODE_STRING elem1U
, elem2U
;
2131 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2133 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2134 static const WCHAR trueW
[] = {'t','r','u','e',0};
2136 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2137 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2140 elem1U
= xmlstr2unicode(&attr_name
);
2141 elem2U
= xmlstr2unicode(&attr_value
);
2142 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
2146 if (error
|| end
) return end
;
2148 memset(&ai
, 0, sizeof(ai
));
2149 ai
.optional
= optional
;
2150 ai
.delayed
= delayed
;
2152 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2153 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2156 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2158 /* store the newly found identity for later loading */
2159 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2161 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2163 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2165 ret
= parse_end_element(xmlbuf
);
2168 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2170 ret
= parse_binding_redirect_elem(xmlbuf
);
2174 DPRINT1("unknown elem %S\n", elem
.ptr
);
2175 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2182 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2184 xmlstr_t attr_name
, attr_value
, elem
;
2185 UNICODE_STRING attr_nameU
, attr_valueU
;
2186 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2188 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2190 attr_nameU
= xmlstr2unicode(&attr_name
);
2191 attr_valueU
= xmlstr2unicode(&attr_value
);
2193 if (xmlstr_cmp(&attr_name
, optionalW
))
2195 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2196 DPRINT1("optional=%wZ\n", &attr_valueU
);
2200 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2204 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2206 if (xmlstr_cmp_end(&elem
, dependencyW
))
2208 ret
= parse_end_element(xmlbuf
);
2211 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2213 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2217 attr_nameU
= xmlstr2unicode(&elem
);
2218 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2219 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2226 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2230 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2231 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2234 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2238 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2239 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2242 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2244 xmlstr_t attr_name
, attr_value
, elem
;
2245 UNICODE_STRING attr_nameU
, attr_valueU
;
2246 BOOL end
= FALSE
, error
, ret
= TRUE
;
2247 struct dll_redirect
* dll
;
2249 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2251 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2253 attr_nameU
= xmlstr2unicode(&attr_name
);
2254 attr_valueU
= xmlstr2unicode(&attr_value
);
2256 if (xmlstr_cmp(&attr_name
, g_nameW
))
2258 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2259 DPRINT("name=%wZ\n", &attr_valueU
);
2261 else if (xmlstr_cmp(&attr_name
, hashW
))
2263 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2265 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2267 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2268 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2269 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU
);
2273 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2277 if (error
|| !dll
->name
) return FALSE
;
2279 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2281 if (end
) return TRUE
;
2283 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2285 if (xmlstr_cmp_end(&elem
, fileW
))
2287 ret
= parse_end_element(xmlbuf
);
2290 else if (xmlstr_cmp(&elem
, comClassW
))
2292 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2294 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2296 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2298 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2300 DPRINT1("asmv2hash (undocumented) not supported\n");
2301 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2303 else if (xmlstr_cmp(&elem
, typelibW
))
2305 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2307 else if (xmlstr_cmp(&elem
, windowClassW
))
2309 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2313 attr_nameU
= xmlstr2unicode(&elem
);
2314 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
2315 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2322 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2323 struct assembly
* assembly
,
2324 struct assembly_identity
* expected_ai
)
2326 xmlstr_t attr_name
, attr_value
, elem
;
2327 UNICODE_STRING attr_nameU
, attr_valueU
;
2328 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2330 DPRINT("(%p)\n", xmlbuf
);
2332 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2334 attr_nameU
= xmlstr2unicode(&attr_name
);
2335 attr_valueU
= xmlstr2unicode(&attr_value
);
2337 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2339 static const WCHAR v10W
[] = {'1','.','0',0};
2340 if (!xmlstr_cmp(&attr_value
, v10W
))
2342 DPRINT1("wrong version %wZ\n", &attr_valueU
);
2347 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2349 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2350 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2351 !xmlstr_cmp(&attr_value
, manifestv3W
))
2353 DPRINT1("wrong namespace %wZ\n", &attr_valueU
);
2360 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2364 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2365 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2367 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2369 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2371 assembly
->no_inherit
= TRUE
;
2374 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2376 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2379 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2380 assembly
->no_inherit
)
2385 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2387 ret
= parse_end_element(xmlbuf
);
2390 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2392 ret
= parse_description_elem(xmlbuf
);
2394 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2396 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2398 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2400 ret
= parse_dependency_elem(xmlbuf
, acl
);
2402 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2404 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2406 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2408 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2410 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2412 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2414 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2416 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2420 /* FIXME: more tests */
2421 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2422 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2424 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2425 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2426 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2427 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2428 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2431 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2432 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2433 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2434 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2435 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2436 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2438 DPRINT1("wrong version for shared assembly manifest\n");
2444 else if (xml_elem_cmp(&elem
, L
"trustInfo", asmv1W
))
2446 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2451 attr_nameU
= xmlstr2unicode(&elem
);
2452 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2453 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2455 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2461 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2462 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2465 UNICODE_STRING elemU
;
2467 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2469 if (xmlstr_cmp(&elem
, g_xmlW
) &&
2470 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2471 return STATUS_SXS_CANT_GEN_ACTCTX
;
2473 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2475 elemU
= xmlstr2unicode(&elem
);
2476 DPRINT1("root element is %wZ, not <assembly>\n", &elemU
);
2477 return STATUS_SXS_CANT_GEN_ACTCTX
;
2480 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2482 DPRINT1("failed to parse manifest %S\n", assembly
->manifest
.info
);
2483 return STATUS_SXS_CANT_GEN_ACTCTX
;
2486 if (next_xml_elem(xmlbuf
, &elem
))
2488 elemU
= xmlstr2unicode(&elem
);
2489 DPRINT1("unexpected element %wZ\n", &elemU
);
2490 return STATUS_SXS_CANT_GEN_ACTCTX
;
2493 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2495 DPRINT1("parse error\n");
2496 return STATUS_SXS_CANT_GEN_ACTCTX
;
2498 return STATUS_SUCCESS
;
2501 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2502 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2503 const void *buffer
, SIZE_T size
)
2507 struct assembly
*assembly
;
2510 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename
, directory
);
2512 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2513 return STATUS_SXS_CANT_GEN_ACTCTX
;
2515 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2516 return STATUS_NO_MEMORY
;
2518 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2519 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2520 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2522 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2523 if (RtlIsTextUnicode(buffer
, size
, &unicode_tests
))
2525 xmlbuf
.ptr
= buffer
;
2526 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2527 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2529 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2531 const WCHAR
*buf
= buffer
;
2535 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
2536 return STATUS_NO_MEMORY
;
2537 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2538 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2539 xmlbuf
.ptr
= new_buff
;
2540 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2541 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2542 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
2546 /* TODO: this doesn't handle arbitrary encodings */
2550 status
= RtlMultiByteToUnicodeSize(&sizeU
, buffer
, size
);
2551 if (!NT_SUCCESS(status
))
2553 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status
);
2554 return STATUS_SXS_CANT_GEN_ACTCTX
;
2557 new_buff
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU
);
2559 return STATUS_NO_MEMORY
;
2561 status
= RtlMultiByteToUnicodeN(new_buff
, sizeU
, &sizeU
, buffer
, size
);
2562 if (!NT_SUCCESS(status
))
2564 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status
);
2565 return STATUS_SXS_CANT_GEN_ACTCTX
;
2568 xmlbuf
.ptr
= new_buff
;
2569 xmlbuf
.end
= xmlbuf
.ptr
+ sizeU
/ sizeof(WCHAR
);
2570 status
= parse_manifest_buffer(acl
, assembly
, ai
, &xmlbuf
);
2571 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff
);
2576 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2578 OBJECT_ATTRIBUTES attr
;
2581 attr
.Length
= sizeof(attr
);
2582 attr
.RootDirectory
= 0;
2583 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2584 attr
.ObjectName
= name
;
2585 attr
.SecurityDescriptor
= NULL
;
2586 attr
.SecurityQualityOfService
= NULL
;
2587 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2590 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2594 LDR_DATA_TABLE_ENTRY
*pldr
;
2596 LdrLockLoaderLock(0, NULL
, &magic
);
2597 status
= LdrFindEntryForAddress( module
, &pldr
);
2598 if (status
== STATUS_SUCCESS
)
2600 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2601 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2603 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2604 str
->Length
= pldr
->FullDllName
.Length
;
2605 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2607 else status
= STATUS_NO_MEMORY
;
2609 LdrUnlockLoaderLock(0, magic
);
2613 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2614 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2615 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2618 UNICODE_STRING nameW
;
2619 LDR_RESOURCE_INFO info
;
2620 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2623 //DPRINT( "looking for res %s in module %p %s\n", resname,
2624 // hModule, filename );
2625 DPRINT("get_manifest_in_module %p\n", hModule
);
2628 if (TRACE_ON(actctx
))
2630 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2632 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2633 hModule
, debugstr_w(nameW
.Buffer
) );
2634 RtlFreeUnicodeString( &nameW
);
2636 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2637 hModule
, debugstr_w(filename
) );
2641 if (!resname
) return STATUS_INVALID_PARAMETER
;
2643 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2644 info
.Language
= lang
;
2645 if (!((ULONG_PTR
)resname
>> 16))
2647 info
.Name
= (ULONG_PTR
)resname
;
2648 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2650 else if (resname
[0] == '#')
2653 RtlInitUnicodeString(&nameW
, resname
+ 1);
2654 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2655 return STATUS_INVALID_PARAMETER
;
2657 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2661 RtlCreateUnicodeString(&nameW
, resname
);
2662 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2663 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2664 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2665 RtlFreeUnicodeString(&nameW
);
2667 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2669 if (status
== STATUS_SUCCESS
)
2670 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2675 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2676 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2677 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2680 OBJECT_ATTRIBUTES attr
;
2682 LARGE_INTEGER offset
;
2687 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2689 attr
.Length
= sizeof(attr
);
2690 attr
.RootDirectory
= 0;
2691 attr
.ObjectName
= NULL
;
2692 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2693 attr
.SecurityDescriptor
= NULL
;
2694 attr
.SecurityQualityOfService
= NULL
;
2697 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2698 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2699 if (status
!= STATUS_SUCCESS
) return status
;
2701 offset
.QuadPart
= 0;
2704 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2705 &count
, ViewShare
, 0, PAGE_READONLY
);
2707 if (status
!= STATUS_SUCCESS
) return status
;
2709 if (RtlImageNtHeader(base
)) /* we got a PE file */
2711 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2712 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2714 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2716 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2720 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2721 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2723 FILE_STANDARD_INFORMATION info
;
2726 OBJECT_ATTRIBUTES attr
;
2728 LARGE_INTEGER offset
;
2733 DPRINT( "loading manifest file %S\n", filename
);
2735 attr
.Length
= sizeof(attr
);
2736 attr
.RootDirectory
= 0;
2737 attr
.ObjectName
= NULL
;
2738 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2739 attr
.SecurityDescriptor
= NULL
;
2740 attr
.SecurityQualityOfService
= NULL
;
2743 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2744 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2746 if (status
!= STATUS_SUCCESS
) return status
;
2748 offset
.QuadPart
= 0;
2751 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2752 &count
, ViewShare
, 0, PAGE_READONLY
);
2754 if (status
!= STATUS_SUCCESS
) return status
;
2756 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
2757 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
2759 if (status
== STATUS_SUCCESS
)
2760 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
2762 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2766 /* try to load the .manifest file associated to the file */
2767 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2768 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2770 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2773 UNICODE_STRING nameW
;
2775 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2777 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2779 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
2781 if (module
) /* use the module filename */
2783 UNICODE_STRING name
;
2785 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2787 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2788 strcatW( name
.Buffer
, dotManifestW
);
2789 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2790 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2791 RtlFreeUnicodeString( &name
);
2793 if (status
) return status
;
2797 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2798 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2799 return STATUS_NO_MEMORY
;
2800 strcpyW( buffer
, filename
);
2801 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2802 strcatW( buffer
, dotManifestW
);
2803 RtlInitUnicodeString( &nameW
, buffer
);
2806 if (!open_nt_file( &file
, &nameW
))
2808 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2811 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
2812 RtlFreeUnicodeString( &nameW
);
2816 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2818 static const WCHAR lookup_fmtW
[] =
2819 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2820 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2821 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2823 WCHAR
*lookup
, *ret
= NULL
;
2824 UNICODE_STRING lookup_us
;
2826 const WCHAR
*lang
= ai
->language
;
2827 unsigned int data_pos
= 0, data_len
;
2830 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2831 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2832 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2833 + sizeof(lookup_fmtW
) )))
2836 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2837 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2838 ai
->version
.major
, ai
->version
.minor
, lang
);
2839 RtlInitUnicodeString( &lookup_us
, lookup
);
2841 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2842 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
2844 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2845 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2847 ULONG build
, revision
;
2849 data_len
= (ULONG
)io
.Information
;
2853 if (data_pos
>= data_len
)
2855 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2856 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
2858 data_len
= (ULONG
)io
.Information
;
2861 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2863 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2864 else data_pos
= data_len
;
2866 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2868 if (build
< min_build
) continue;
2869 tmp
= strchrW(tmp
, '.') + 1;
2870 revision
= atoiW(tmp
);
2871 if (build
== min_build
&& revision
< min_revision
) continue;
2872 tmp
= strchrW(tmp
, '_') + 1;
2873 tmp
= strchrW(tmp
, '_') + 1;
2874 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2875 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2877 /* prefer a non-Wine manifest if we already have one */
2878 /* we'll still load the builtin dll if specified through DllOverrides */
2884 min_revision
= revision
;
2886 ai
->version
.build
= build
;
2887 ai
->version
.revision
= revision
;
2888 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
2889 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2891 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2892 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2896 else DPRINT1("no matching file for %S\n", lookup
);
2897 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
2901 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2903 struct assembly_identity sxs_ai
;
2904 UNICODE_STRING path_us
;
2905 OBJECT_ATTRIBUTES attr
;
2907 WCHAR
*path
, *file
= NULL
;
2910 static const WCHAR manifest_dirW
[] =
2911 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2913 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2915 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2916 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
2917 return STATUS_NO_MEMORY
;
2919 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
2920 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
2922 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2924 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2925 return STATUS_NO_SUCH_FILE
;
2927 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
2929 attr
.Length
= sizeof(attr
);
2930 attr
.RootDirectory
= 0;
2931 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2932 attr
.ObjectName
= &path_us
;
2933 attr
.SecurityDescriptor
= NULL
;
2934 attr
.SecurityQualityOfService
= NULL
;
2936 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2937 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2940 file
= lookup_manifest_file( handle
, &sxs_ai
);
2945 RtlFreeUnicodeString( &path_us
);
2946 return STATUS_NO_SUCH_FILE
;
2949 /* append file name to directory path */
2950 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
2951 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2953 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2954 RtlFreeUnicodeString( &path_us
);
2955 return STATUS_NO_MEMORY
;
2958 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2959 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2960 RtlInitUnicodeString( &path_us
, path
);
2961 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2963 if (!open_nt_file( &handle
, &path_us
))
2965 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2968 else io
.Status
= STATUS_NO_SUCH_FILE
;
2970 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
2971 RtlFreeUnicodeString( &path_us
);
2975 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2976 struct assembly_identity
* ai
)
2978 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2980 WCHAR
*buffer
, *p
, *directory
;
2982 UNICODE_STRING nameW
;
2986 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2987 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
2989 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2991 /* FIXME: add support for language specific lookup */
2993 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
2994 strlenW(acl
->actctx
->appdir
.info
));
2996 nameW
.Buffer
= NULL
;
2997 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2998 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2999 return STATUS_NO_MEMORY
;
3001 if (!(directory
= build_assembly_dir( ai
)))
3003 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3004 return STATUS_NO_MEMORY
;
3007 /* Lookup in <dir>\name.dll
3008 * <dir>\name.manifest
3009 * <dir>\name\name.dll
3010 * <dir>\name\name.manifest
3012 * First 'appdir' is used as <dir>, if that failed
3013 * it tries application manifest file path.
3015 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3016 p
= buffer
+ strlenW(buffer
);
3017 for (i
= 0; i
< 4; i
++)
3021 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3022 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3026 strcpyW( p
, ai
->name
);
3029 strcpyW( p
, dotDllW
);
3030 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3032 status
= open_nt_file( &file
, &nameW
);
3035 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3036 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3040 RtlFreeUnicodeString( &nameW
);
3043 strcpyW( p
, dotManifestW
);
3044 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3046 status
= open_nt_file( &file
, &nameW
);
3049 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3053 RtlFreeUnicodeString( &nameW
);
3055 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3057 RtlFreeUnicodeString( &nameW
);
3058 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3059 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3063 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3065 NTSTATUS status
= STATUS_SUCCESS
;
3068 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3070 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3072 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3074 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3075 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3076 acl
->dependencies
[i
].name
,
3077 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3078 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3083 /* FIXME should now iterate through all refs */
3087 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3088 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3090 NTSTATUS status
= STATUS_SUCCESS
;
3092 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3094 if (*handle
) return STATUS_INVALID_PARAMETER
;
3096 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3097 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3099 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3102 LDR_DATA_TABLE_ENTRY
*pldr
;
3104 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3106 LdrLockLoaderLock( 0, NULL
, &magic
);
3107 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3109 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3110 status
= STATUS_DLL_NOT_FOUND
;
3112 *handle
= pldr
->EntryPointActivationContext
;
3114 else status
= STATUS_DLL_NOT_FOUND
;
3115 LdrUnlockLoaderLock( 0, magic
);
3117 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3118 *handle
= process_actctx
;
3123 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3125 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3126 struct strsection_header
*header
;
3127 struct dllredirect_data
*data
;
3128 struct string_index
*index
;
3131 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3133 /* compute section length */
3134 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3136 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3137 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3139 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3141 /* each entry needs index, data and string data */
3142 total_len
+= sizeof(*index
);
3143 total_len
+= sizeof(*data
);
3144 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3146 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3149 dll_count
+= assembly
->num_dlls
;
3152 total_len
+= sizeof(*header
);
3154 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3155 if (!header
) return STATUS_NO_MEMORY
;
3157 memset(header
, 0, sizeof(*header
));
3158 header
->magic
= STRSECTION_MAGIC
;
3159 header
->size
= sizeof(*header
);
3160 header
->count
= dll_count
;
3161 header
->index_offset
= sizeof(*header
);
3162 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3163 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3165 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3167 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3169 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3171 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3173 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3177 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3178 /* setup new index entry */
3179 str
.Buffer
= dll
->name
;
3180 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3181 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3182 /* hash original class name */
3183 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3185 index
->name_offset
= name_offset
;
3186 index
->name_len
= str
.Length
;
3187 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3188 index
->data_len
= sizeof(*data
);
3189 index
->rosterindex
= i
+ 1;
3192 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3193 data
->size
= sizeof(*data
);
3194 data
->unk
= 2; /* FIXME: seems to be constant */
3195 memset(data
->res
, 0, sizeof(data
->res
));
3198 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3199 memcpy(ptrW
, dll
->name
, index
->name_len
);
3200 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3202 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3210 return STATUS_SUCCESS
;
3213 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3215 struct string_index
*iter
, *index
= NULL
;
3218 DPRINT("section %p, name %wZ\n", section
, name
);
3219 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3220 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3222 for (i
= 0; i
< section
->count
; i
++)
3224 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3225 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3226 if (iter
->hash
== hash
)
3228 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3230 if (!_wcsnicmp(nameW
, name
->Buffer
, name
->Length
/ sizeof(WCHAR
)) &&
3231 wcslen(nameW
) == name
->Length
/ sizeof(WCHAR
))
3237 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3245 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3247 struct guid_index
*iter
, *index
= NULL
;
3250 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3252 for (i
= 0; i
< section
->count
; i
++)
3254 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3265 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3267 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3270 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3271 PACTCTX_SECTION_KEYED_DATA data
)
3273 struct dllredirect_data
*dll
;
3274 struct string_index
*index
;
3276 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3277 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3279 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3280 if (!actctx
->dllredirect_section
)
3282 struct strsection_header
*section
;
3284 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3285 if (status
) return status
;
3287 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3288 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3291 index
= find_string_index(actctx
->dllredirect_section
, name
);
3292 DPRINT("index: %d\n", index
);
3293 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3297 dll
= get_dllredirect_data(actctx
, index
);
3299 data
->ulDataFormatVersion
= 1;
3301 data
->ulLength
= dll
->size
;
3302 data
->lpSectionGlobalData
= NULL
;
3303 data
->ulSectionGlobalDataLength
= 0;
3304 data
->lpSectionBase
= actctx
->dllredirect_section
;
3305 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3306 data
->hActCtx
= NULL
;
3308 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3309 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3312 return STATUS_SUCCESS
;
3315 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3317 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3320 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3322 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3325 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3327 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3328 struct wndclass_redirect_data
*data
;
3329 struct strsection_header
*header
;
3330 struct string_index
*index
;
3333 /* compute section length */
3334 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3336 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3337 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3339 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3340 for (k
= 0; k
< dll
->entities
.num
; k
++)
3342 struct entity
*entity
= &dll
->entities
.base
[k
];
3343 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3345 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3348 /* each class entry needs index, data and string data */
3349 total_len
+= sizeof(*index
);
3350 total_len
+= sizeof(*data
);
3351 /* original name is stored separately */
3352 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3353 /* versioned name and module name are stored one after another */
3354 if (entity
->u
.class.versioned
)
3355 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3358 len
+= strlenW(dll
->name
) + 1;
3359 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3367 total_len
+= sizeof(*header
);
3369 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3370 if (!header
) return STATUS_NO_MEMORY
;
3372 memset(header
, 0, sizeof(*header
));
3373 header
->magic
= STRSECTION_MAGIC
;
3374 header
->size
= sizeof(*header
);
3375 header
->count
= class_count
;
3376 header
->index_offset
= sizeof(*header
);
3377 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3378 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3380 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3382 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3383 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3385 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3386 for (k
= 0; k
< dll
->entities
.num
; k
++)
3388 struct entity
*entity
= &dll
->entities
.base
[k
];
3389 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3391 static const WCHAR exclW
[] = {'!',0};
3392 ULONG versioned_len
, module_len
;
3396 /* setup new index entry */
3397 str
.Buffer
= entity
->u
.class.name
;
3398 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3399 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3400 /* hash original class name */
3401 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3403 /* include '!' separator too */
3404 if (entity
->u
.class.versioned
)
3405 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3407 versioned_len
= str
.Length
;
3408 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3410 index
->name_offset
= name_offset
;
3411 index
->name_len
= str
.Length
;
3412 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3413 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3414 index
->rosterindex
= i
+ 1;
3417 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3418 data
->size
= sizeof(*data
);
3420 data
->name_len
= versioned_len
;
3421 data
->name_offset
= sizeof(*data
);
3422 data
->module_len
= module_len
;
3423 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3425 /* original class name */
3426 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3427 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3428 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3431 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3432 memcpy(ptrW
, dll
->name
, data
->module_len
);
3433 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3435 /* versioned name */
3436 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3437 if (entity
->u
.class.versioned
)
3439 get_assembly_version(assembly
, ptrW
);
3440 strcatW(ptrW
, exclW
);
3441 strcatW(ptrW
, entity
->u
.class.name
);
3445 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3446 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3449 name_offset
+= sizeof(*data
);
3450 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3460 return STATUS_SUCCESS
;
3463 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3464 PACTCTX_SECTION_KEYED_DATA data
)
3466 struct string_index
*iter
, *index
= NULL
;
3467 struct wndclass_redirect_data
*class;
3471 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3473 if (!actctx
->wndclass_section
)
3475 struct strsection_header
*section
;
3477 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3478 if (status
) return status
;
3480 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3481 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3485 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3486 iter
= get_wndclass_first_index(actctx
);
3488 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3490 if (iter
->hash
== hash
)
3492 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3494 if (!strcmpiW(nameW
, name
->Buffer
))
3500 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3505 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3509 class = get_wndclass_data(actctx
, index
);
3511 data
->ulDataFormatVersion
= 1;
3512 data
->lpData
= class;
3513 /* full length includes string length with nulls */
3514 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3515 data
->lpSectionGlobalData
= NULL
;
3516 data
->ulSectionGlobalDataLength
= 0;
3517 data
->lpSectionBase
= actctx
->wndclass_section
;
3518 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3519 data
->hActCtx
= NULL
;
3521 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3522 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3525 return STATUS_SUCCESS
;
3528 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3530 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3531 struct guidsection_header
*header
;
3532 ULONG module_offset
, data_offset
;
3533 struct tlibredirect_data
*data
;
3534 struct guid_index
*index
;
3536 /* compute section length */
3537 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3539 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3540 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3542 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3543 for (k
= 0; k
< dll
->entities
.num
; k
++)
3545 struct entity
*entity
= &dll
->entities
.base
[k
];
3546 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3548 /* each entry needs index, data and string data for module name and help string */
3549 total_len
+= sizeof(*index
);
3550 total_len
+= sizeof(*data
);
3551 /* help string is stored separately */
3552 if (*entity
->u
.typelib
.helpdir
)
3553 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3555 /* module names are packed one after another */
3556 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3564 total_len
+= aligned_string_len(names_len
);
3565 total_len
+= sizeof(*header
);
3567 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3568 if (!header
) return STATUS_NO_MEMORY
;
3570 memset(header
, 0, sizeof(*header
));
3571 header
->magic
= GUIDSECTION_MAGIC
;
3572 header
->size
= sizeof(*header
);
3573 header
->count
= tlib_count
;
3574 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3575 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3576 module_offset
= sizeof(*header
);
3577 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3579 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3581 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3582 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3584 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3585 for (k
= 0; k
< dll
->entities
.num
; k
++)
3587 struct entity
*entity
= &dll
->entities
.base
[k
];
3588 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3590 ULONG module_len
, help_len
;
3594 if (*entity
->u
.typelib
.helpdir
)
3595 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3599 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3601 /* setup new index entry */
3602 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3603 RtlGUIDFromString(&str
, &index
->guid
);
3604 index
->data_offset
= data_offset
;
3605 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3606 index
->rosterindex
= i
+ 1;
3609 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3610 data
->size
= sizeof(*data
);
3612 data
->name_len
= module_len
;
3613 data
->name_offset
= module_offset
;
3614 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3616 data
->flags
= entity
->u
.typelib
.flags
;
3617 data
->help_len
= help_len
;
3618 data
->help_offset
= sizeof(*data
);
3619 data
->major_version
= entity
->u
.typelib
.major
;
3620 data
->minor_version
= entity
->u
.typelib
.minor
;
3623 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3624 memcpy(ptrW
, dll
->name
, data
->name_len
);
3625 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3630 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3631 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3632 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3635 data_offset
+= sizeof(*data
);
3637 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3639 module_offset
+= module_len
+ sizeof(WCHAR
);
3649 return STATUS_SUCCESS
;
3652 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3654 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3657 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3659 struct guid_index
*index
= NULL
;
3660 struct tlibredirect_data
*tlib
;
3662 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3664 if (!actctx
->tlib_section
)
3666 struct guidsection_header
*section
;
3668 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3669 if (status
) return status
;
3671 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3672 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3675 index
= find_guid_index(actctx
->tlib_section
, guid
);
3676 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3678 tlib
= get_tlib_data(actctx
, index
);
3680 data
->ulDataFormatVersion
= 1;
3681 data
->lpData
= tlib
;
3682 /* full length includes string length with nulls */
3683 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3684 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3685 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3686 data
->lpSectionBase
= actctx
->tlib_section
;
3687 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3688 data
->hActCtx
= NULL
;
3690 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3691 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3693 return STATUS_SUCCESS
;
3696 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3698 ULONG
*ptr
= (ULONG
*)guid
;
3701 /* GUID is 16 bytes long */
3702 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3703 *ptr
= RtlUniform(seed
);
3705 guid
->Data3
&= 0x0fff;
3706 guid
->Data3
|= (4 << 12);
3707 guid
->Data4
[0] &= 0x3f;
3708 guid
->Data4
[0] |= 0x80;
3711 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3712 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3716 for (i
= 0; i
< entities
->num
; i
++)
3718 struct entity
*entity
= &entities
->base
[i
];
3719 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3721 /* each entry needs two index entries, extra one goes for alias GUID */
3722 *len
+= 2*sizeof(struct guid_index
);
3723 /* To save some memory we don't allocated two data structures,
3724 instead alias index and normal index point to the same data structure. */
3725 *len
+= sizeof(struct comclassredirect_data
);
3727 /* for clrClass store some more */
3728 if (entity
->u
.comclass
.name
)
3730 unsigned int str_len
;
3732 /* all string data is stored together in aligned block */
3733 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3734 if (entity
->u
.comclass
.progid
)
3735 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3736 if (entity
->u
.comclass
.version
)
3737 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3739 *len
+= sizeof(struct clrclass_data
);
3740 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
3742 /* module name is forced to mscoree.dll, and stored two times with different case */
3743 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
3747 /* progid string is stored separately */
3748 if (entity
->u
.comclass
.progid
)
3749 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
3751 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3759 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
3760 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
3761 ULONG
*seed
, ULONG rosterindex
)
3765 for (i
= 0; i
< entities
->num
; i
++)
3767 struct entity
*entity
= &entities
->base
[i
];
3768 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3770 ULONG module_len
, progid_len
, str_len
= 0;
3771 struct comclassredirect_data
*data
;
3772 struct guid_index
*alias_index
;
3773 struct clrclass_data
*clrdata
;
3777 if (entity
->u
.comclass
.progid
)
3778 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
3782 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
3784 /* setup new index entry */
3785 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
3786 RtlGUIDFromString(&str
, &(*index
)->guid
);
3788 (*index
)->data_offset
= *data_offset
;
3789 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
3790 (*index
)->rosterindex
= rosterindex
;
3792 /* Setup new index entry for alias guid. Alias index records are placed after
3793 normal records, so normal guids are hit first on search. Note that class count
3795 alias_index
= (*index
) + section
->count
/2;
3796 generate_uuid(seed
, &alias_index
->guid
);
3797 alias_index
->data_offset
= (*index
)->data_offset
;
3798 alias_index
->data_len
= 0;
3799 alias_index
->rosterindex
= (*index
)->rosterindex
;
3802 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
3803 data
->size
= sizeof(*data
);
3807 data
->model
= entity
->u
.comclass
.model
;
3808 data
->clsid
= (*index
)->guid
;
3809 data
->alias
= alias_index
->guid
;
3810 data
->clsid2
= data
->clsid
;
3811 if (entity
->u
.comclass
.tlbid
)
3813 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
3814 RtlGUIDFromString(&str
, &data
->tlbid
);
3817 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
3818 data
->name_len
= module_len
;
3819 data
->name_offset
= *module_offset
;
3820 data
->progid_len
= progid_len
;
3821 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
3822 data
->clrdata_len
= 0; /* will be set later */
3823 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
3824 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
3825 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
3826 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
3827 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
3828 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
3830 /* mask describes which misc* data is available */
3832 if (data
->miscstatus
)
3833 data
->miscmask
|= MiscStatus
;
3834 if (data
->miscstatuscontent
)
3835 data
->miscmask
|= MiscStatusContent
;
3836 if (data
->miscstatusthumbnail
)
3837 data
->miscmask
|= MiscStatusThumbnail
;
3838 if (data
->miscstatusicon
)
3839 data
->miscmask
|= MiscStatusIcon
;
3840 if (data
->miscstatusdocprint
)
3841 data
->miscmask
|= MiscStatusDocPrint
;
3843 if (data
->clrdata_offset
)
3845 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
3847 clrdata
->size
= sizeof(*clrdata
);
3848 clrdata
->res
[0] = 0;
3849 clrdata
->res
[1] = 2; /* FIXME: unknown field */
3850 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
3851 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
3852 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
3853 clrdata
->name_offset
= clrdata
->size
;
3854 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
3855 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
3856 clrdata
->res2
[0] = 0;
3857 clrdata
->res2
[1] = 0;
3859 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
3862 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
3863 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
3864 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
3866 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3867 memcpy(ptrW
, mscoreeW
, data
->name_len
);
3868 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3871 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
3872 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
3873 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
3875 /* runtime version, optional */
3876 if (clrdata
->version_len
)
3878 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3880 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
3881 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
3882 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
3885 if (data
->progid_len
)
3886 data
->progid_offset
+= data
->clrdata_len
;
3887 (*index
)->data_len
+= sizeof(*clrdata
);
3894 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
3895 memcpy(ptrW
, dll
->name
, data
->name_len
);
3896 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3900 if (data
->progid_len
)
3902 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
3903 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
3904 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
3907 /* string block length */
3911 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
3912 if (clrdata
->version_len
)
3913 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
3916 str_len
+= progid_len
+ sizeof(WCHAR
);
3918 (*index
)->data_len
+= aligned_string_len(str_len
);
3919 alias_index
->data_len
= (*index
)->data_len
;
3921 /* move to next data record */
3922 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
3923 (*module_offset
) += module_len
+ sizeof(WCHAR
);
3927 (*data_offset
) += sizeof(*clrdata
);
3928 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
3935 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3937 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
3938 struct guidsection_header
*header
;
3939 ULONG module_offset
, data_offset
;
3940 struct guid_index
*index
;
3943 /* compute section length */
3944 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3946 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3947 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
3948 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3950 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3951 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
3955 total_len
+= aligned_string_len(names_len
);
3956 total_len
+= sizeof(*header
);
3958 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3959 if (!header
) return STATUS_NO_MEMORY
;
3961 memset(header
, 0, sizeof(*header
));
3962 header
->magic
= GUIDSECTION_MAGIC
;
3963 header
->size
= sizeof(*header
);
3964 header
->count
= 2*class_count
;
3965 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3966 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3967 module_offset
= sizeof(*header
);
3968 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
3970 seed
= NtGetTickCount();
3971 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3973 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3974 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3975 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3977 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3978 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
3984 return STATUS_SUCCESS
;
3987 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3989 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
3992 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3994 struct comclassredirect_data
*comclass
;
3995 struct guid_index
*index
= NULL
;
3997 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3999 if (!actctx
->comserver_section
)
4001 struct guidsection_header
*section
;
4003 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4004 if (status
) return status
;
4006 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4007 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4010 index
= find_guid_index(actctx
->comserver_section
, guid
);
4011 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4013 comclass
= get_comclass_data(actctx
, index
);
4015 data
->ulDataFormatVersion
= 1;
4016 data
->lpData
= comclass
;
4017 /* full length includes string length with nulls */
4018 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4019 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4020 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4021 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4022 data
->lpSectionBase
= actctx
->comserver_section
;
4023 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4024 data
->hActCtx
= NULL
;
4026 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4027 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4029 return STATUS_SUCCESS
;
4032 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4036 for (i
= 0; i
< entities
->num
; i
++)
4038 struct entity
*entity
= &entities
->base
[i
];
4039 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4041 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4042 if (entity
->u
.ifaceps
.name
)
4043 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4049 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4050 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4054 for (i
= 0; i
< entities
->num
; i
++)
4056 struct entity
*entity
= &entities
->base
[i
];
4057 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4059 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4063 if (entity
->u
.ifaceps
.name
)
4064 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4069 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4070 RtlGUIDFromString(&str
, &(*index
)->guid
);
4071 (*index
)->data_offset
= *data_offset
;
4072 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4073 (*index
)->rosterindex
= rosterindex
;
4075 /* setup data record */
4076 data
->size
= sizeof(*data
);
4077 data
->mask
= entity
->u
.ifaceps
.mask
;
4079 /* proxyStubClsid32 value is only stored for external PS,
4080 if set it's used as iid, otherwise 'iid' attribute value is used */
4081 if (entity
->u
.ifaceps
.ps32
)
4083 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4084 RtlGUIDFromString(&str
, &data
->iid
);
4087 data
->iid
= (*index
)->guid
;
4089 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4091 if (entity
->u
.ifaceps
.tlib
)
4093 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4094 RtlGUIDFromString(&str
, &data
->tlbid
);
4097 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4099 if (entity
->u
.ifaceps
.base
)
4101 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4102 RtlGUIDFromString(&str
, &data
->base
);
4105 memset(&data
->base
, 0, sizeof(data
->base
));
4107 data
->name_len
= name_len
;
4108 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4113 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4114 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4115 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4118 /* move to next record */
4120 *data_offset
+= sizeof(*data
);
4122 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4127 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4129 unsigned int i
, j
, total_len
= 0, count
= 0;
4130 struct guidsection_header
*header
;
4131 struct guid_index
*index
;
4134 /* compute section length */
4135 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4137 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4139 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4140 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4142 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4143 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4147 total_len
+= sizeof(*header
);
4149 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4150 if (!header
) return STATUS_NO_MEMORY
;
4152 memset(header
, 0, sizeof(*header
));
4153 header
->magic
= GUIDSECTION_MAGIC
;
4154 header
->size
= sizeof(*header
);
4155 header
->count
= count
;
4156 header
->index_offset
= sizeof(*header
);
4157 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4158 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4160 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4162 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4164 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4165 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4167 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4168 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4174 return STATUS_SUCCESS
;
4177 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4179 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4182 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4184 struct ifacepsredirect_data
*iface
;
4185 struct guid_index
*index
= NULL
;
4187 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4189 if (!actctx
->ifaceps_section
)
4191 struct guidsection_header
*section
;
4193 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4194 if (status
) return status
;
4196 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4197 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4200 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4201 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4203 iface
= get_ifaceps_data(actctx
, index
);
4205 data
->ulDataFormatVersion
= 1;
4206 data
->lpData
= iface
;
4207 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4208 data
->lpSectionGlobalData
= NULL
;
4209 data
->ulSectionGlobalDataLength
= 0;
4210 data
->lpSectionBase
= actctx
->ifaceps_section
;
4211 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4212 data
->hActCtx
= NULL
;
4214 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4215 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4217 return STATUS_SUCCESS
;
4220 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4222 unsigned int i
, j
, total_len
= 0, count
= 0;
4223 struct guidsection_header
*header
;
4224 struct clrsurrogate_data
*data
;
4225 struct guid_index
*index
;
4228 /* compute section length */
4229 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4231 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4232 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4234 struct entity
*entity
= &assembly
->entities
.base
[j
];
4235 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4239 total_len
+= sizeof(*index
) + sizeof(*data
);
4240 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4241 if (entity
->u
.clrsurrogate
.version
)
4242 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4243 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4250 total_len
+= sizeof(*header
);
4252 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4253 if (!header
) return STATUS_NO_MEMORY
;
4255 memset(header
, 0, sizeof(*header
));
4256 header
->magic
= GUIDSECTION_MAGIC
;
4257 header
->size
= sizeof(*header
);
4258 header
->count
= count
;
4259 header
->index_offset
= sizeof(*header
);
4260 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4261 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4263 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4265 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4266 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4268 struct entity
*entity
= &assembly
->entities
.base
[j
];
4269 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4271 ULONG version_len
, name_len
;
4275 if (entity
->u
.clrsurrogate
.version
)
4276 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4279 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4281 /* setup new index entry */
4282 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4283 RtlGUIDFromString(&str
, &index
->guid
);
4285 index
->data_offset
= data_offset
;
4286 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4287 index
->rosterindex
= i
+ 1;
4290 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4291 data
->size
= sizeof(*data
);
4293 data
->clsid
= index
->guid
;
4294 data
->version_offset
= version_len
? data
->size
: 0;
4295 data
->version_len
= version_len
;
4296 data
->name_offset
= data
->size
+ version_len
;
4298 data
->name_offset
+= sizeof(WCHAR
);
4299 data
->name_len
= name_len
;
4301 /* surrogate name */
4302 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4303 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4304 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4306 /* runtime version */
4307 if (data
->version_len
)
4309 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4310 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4311 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4314 data_offset
+= index
->data_offset
;
4322 return STATUS_SUCCESS
;
4325 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4327 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4330 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4332 struct clrsurrogate_data
*surrogate
;
4333 struct guid_index
*index
= NULL
;
4335 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4337 if (!actctx
->clrsurrogate_section
)
4339 struct guidsection_header
*section
;
4341 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4342 if (status
) return status
;
4344 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4345 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4348 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4349 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4351 surrogate
= get_surrogate_data(actctx
, index
);
4353 data
->ulDataFormatVersion
= 1;
4354 data
->lpData
= surrogate
;
4355 /* full length includes string length with nulls */
4356 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4357 if (surrogate
->version_len
)
4358 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4360 data
->lpSectionGlobalData
= NULL
;
4361 data
->ulSectionGlobalDataLength
= 0;
4362 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4363 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4364 data
->hActCtx
= NULL
;
4366 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4367 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4369 return STATUS_SUCCESS
;
4372 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4374 unsigned int i
, j
, single_len
;
4376 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4377 for (i
= 0; i
< entities
->num
; i
++)
4379 struct entity
*entity
= &entities
->base
[i
];
4380 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4382 if (entity
->u
.comclass
.progid
)
4384 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4388 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4389 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4391 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4392 *count
+= entity
->u
.comclass
.progids
.num
;
4397 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4398 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4400 struct progidredirect_data
*data
;
4405 /* setup new index entry */
4407 /* hash progid name */
4408 RtlInitUnicodeString(&str
, progid
);
4409 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4411 (*index
)->name_offset
= *data_offset
;
4412 (*index
)->name_len
= str
.Length
;
4413 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4414 (*index
)->data_len
= sizeof(*data
);
4415 (*index
)->rosterindex
= rosterindex
;
4417 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4419 /* setup data structure */
4420 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4421 data
->size
= sizeof(*data
);
4423 data
->clsid_offset
= *global_offset
;
4425 /* write progid string */
4426 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4427 memcpy(ptrW
, progid
, (*index
)->name_len
);
4428 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4430 /* write guid to global area */
4431 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4435 *global_offset
+= sizeof(GUID
);
4436 *data_offset
+= data
->size
;
4440 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4441 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4445 for (i
= 0; i
< entities
->num
; i
++)
4447 struct entity
*entity
= &entities
->base
[i
];
4448 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4450 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4451 struct comclassredirect_data
*comclass
;
4452 struct guid_index
*guid_index
;
4456 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4457 RtlGUIDFromString(&str
, &clsid
);
4459 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4460 comclass
= get_comclass_data(actctx
, guid_index
);
4462 if (entity
->u
.comclass
.progid
)
4463 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4464 index
, data_offset
, global_offset
, rosterindex
);
4466 for (j
= 0; j
< progids
->num
; j
++)
4467 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4468 index
, data_offset
, global_offset
, rosterindex
);
4473 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4475 unsigned int i
, j
, total_len
= 0, count
= 0;
4476 struct strsection_header
*header
;
4477 ULONG data_offset
, global_offset
;
4478 struct string_index
*index
;
4480 /* compute section length */
4481 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4483 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4485 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4486 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4488 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4489 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4493 total_len
+= sizeof(*header
);
4495 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4496 if (!header
) return STATUS_NO_MEMORY
;
4498 memset(header
, 0, sizeof(*header
));
4499 header
->magic
= STRSECTION_MAGIC
;
4500 header
->size
= sizeof(*header
);
4501 header
->count
= count
;
4502 header
->global_offset
= header
->size
;
4503 header
->global_len
= count
*sizeof(GUID
);
4504 header
->index_offset
= header
->size
+ header
->global_len
;
4506 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4507 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4508 global_offset
= header
->global_offset
;
4510 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4512 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4514 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4515 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4517 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4518 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4524 return STATUS_SUCCESS
;
4527 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4529 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4532 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4533 PACTCTX_SECTION_KEYED_DATA data
)
4535 struct progidredirect_data
*progid
;
4536 struct string_index
*index
;
4538 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4540 if (!actctx
->comserver_section
)
4542 struct guidsection_header
*section
;
4544 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4545 if (status
) return status
;
4547 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4548 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4551 if (!actctx
->progid_section
)
4553 struct strsection_header
*section
;
4555 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4556 if (status
) return status
;
4558 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4559 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4562 index
= find_string_index(actctx
->progid_section
, name
);
4563 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4567 progid
= get_progid_data(actctx
, index
);
4569 data
->ulDataFormatVersion
= 1;
4570 data
->lpData
= progid
;
4571 data
->ulLength
= progid
->size
;
4572 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4573 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4574 data
->lpSectionBase
= actctx
->progid_section
;
4575 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4576 data
->hActCtx
= NULL
;
4578 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4579 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4582 return STATUS_SUCCESS
;
4585 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4586 const UNICODE_STRING
*section_name
,
4587 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4591 switch (section_kind
)
4593 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4594 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4595 return STATUS_SXS_KEY_NOT_FOUND
;
4596 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4597 status
= find_dll_redirection(actctx
, section_name
, data
);
4599 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4600 status
= find_window_class(actctx
, section_name
, data
);
4602 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4603 status
= find_progid_redirection(actctx
, section_name
, data
);
4605 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4606 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4607 return STATUS_SXS_SECTION_NOT_FOUND
;
4609 DPRINT1("Unknown section_kind %x\n", section_kind
);
4610 return STATUS_SXS_SECTION_NOT_FOUND
;
4613 if (status
!= STATUS_SUCCESS
) return status
;
4615 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4617 actctx_addref(actctx
);
4618 data
->hActCtx
= actctx
;
4620 return STATUS_SUCCESS
;
4623 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4624 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4628 switch (section_kind
)
4630 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4631 status
= find_tlib_redirection(actctx
, guid
, data
);
4633 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4634 status
= find_comserver_redirection(actctx
, guid
, data
);
4636 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4637 status
= find_cominterface_redirection(actctx
, guid
, data
);
4639 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4640 status
= find_clr_surrogate(actctx
, guid
, data
);
4643 DPRINT("Unknown section_kind %x\n", section_kind
);
4644 return STATUS_SXS_SECTION_NOT_FOUND
;
4647 if (status
!= STATUS_SUCCESS
) return status
;
4649 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4651 actctx_addref(actctx
);
4652 data
->hActCtx
= actctx
;
4654 return STATUS_SUCCESS
;
4657 /* initialize the activation context for the current process */
4658 void actctx_init(void)
4665 ctx
.cbSize
= sizeof(ctx
);
4666 ctx
.lpSource
= NULL
;
4667 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4668 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4669 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4671 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4673 process_actctx
= check_actctx(handle
);
4678 ctx
.lpResourceName
= NULL
;
4679 ctx
.lpSource
= buffer
;
4680 RtlStringCchCopyW(buffer
, 1024, SharedUserData
->NtSystemRoot
);
4681 RtlStringCchCatW(buffer
, 1024, L
"\\winsxs\\manifests\\systemcompatible.manifest");
4682 Status
= RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
);
4683 if (NT_SUCCESS(Status
))
4685 implicit_actctx
= check_actctx(handle
);
4689 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status
);
4693 /* FUNCTIONS ***************************************************************/
4695 /***********************************************************************
4696 * RtlCreateActivationContext (NTDLL.@)
4698 * Create an activation context.
4702 RtlCreateActivationContext(IN ULONG Flags
,
4703 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4704 IN ULONG ExtraBytes
,
4705 IN PVOID NotificationRoutine
,
4706 IN PVOID NotificationContext
,
4707 OUT PACTIVATION_CONTEXT
*ActCtx
)
4709 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4710 const WCHAR
*directory
= NULL
;
4711 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4712 ACTIVATION_CONTEXT
*actctx
;
4713 UNICODE_STRING nameW
;
4715 NTSTATUS status
= STATUS_NO_MEMORY
;
4717 struct actctx_loader acl
;
4719 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4721 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4722 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4723 return STATUS_INVALID_PARAMETER
;
4726 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4727 return STATUS_NO_MEMORY
;
4729 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4731 actctx
= &ActualActCtx
->ActivationContext
;
4732 actctx
->RefCount
= 1;
4733 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4734 actctx
->config
.info
= NULL
;
4735 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4736 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4738 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
4746 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
4747 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4749 status
= get_module_filename( module
, &dir
, 0 );
4750 if (!NT_SUCCESS(status
)) goto error
;
4751 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
4752 actctx
->appdir
.info
= dir
.Buffer
;
4755 nameW
.Buffer
= NULL
;
4757 /* open file only if it's going to be used */
4758 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
4759 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
4761 WCHAR
*source
= NULL
;
4764 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
4765 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
4767 DWORD dir_len
, source_len
;
4769 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
4770 source_len
= strlenW(pActCtx
->lpSource
);
4771 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
4773 status
= STATUS_NO_MEMORY
;
4777 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
4778 source
[dir_len
] = '\\';
4779 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
4782 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
4783 RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
4786 status
= STATUS_NO_SUCH_FILE
;
4789 status
= open_nt_file( &file
, &nameW
);
4790 if (!NT_SUCCESS(status
))
4792 RtlFreeUnicodeString( &nameW
);
4797 acl
.actctx
= actctx
;
4798 acl
.dependencies
= NULL
;
4799 acl
.num_dependencies
= 0;
4800 acl
.allocated_dependencies
= 0;
4802 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
4803 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
4805 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
4807 /* if we have a resource it's a PE file */
4808 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
4810 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
4811 pActCtx
->lpResourceName
, lang
);
4812 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4813 /* FIXME: what to do if pActCtx->lpSource is set */
4814 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
4815 pActCtx
->hModule
, pActCtx
->lpResourceName
);
4817 else if (pActCtx
->lpSource
)
4819 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
4820 file
, pActCtx
->lpResourceName
, lang
);
4821 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
4822 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
4823 NULL
, pActCtx
->lpResourceName
);
4825 else status
= STATUS_INVALID_PARAMETER
;
4829 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
4832 if (file
) NtClose( file
);
4833 RtlFreeUnicodeString( &nameW
);
4835 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
4836 free_depend_manifests( &acl
);
4838 if (NT_SUCCESS(status
))
4840 else actctx_release( actctx
);
4844 if (file
) NtClose( file
);
4845 actctx_release( actctx
);
4850 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
4854 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
4856 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
4857 LONG OldRefCount
, NewRefCount
;
4859 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4861 RtlpValidateActCtx(ActCtx
);
4865 OldRefCount
= ActCtx
->RefCount
;
4866 ASSERT(OldRefCount
> 0);
4868 if (OldRefCount
== LONG_MAX
) break;
4870 NewRefCount
= OldRefCount
+ 1;
4871 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
4873 OldRefCount
) == OldRefCount
)
4879 NewRefCount
= LONG_MAX
;
4880 ASSERT(NewRefCount
> 0);
4886 RtlReleaseActivationContext( HANDLE handle
)
4888 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
4890 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
4892 RtlpValidateActCtx(ActCtx
);
4894 actctx_release(ActCtx
);
4899 /***********************************************************************
4900 * RtlAddRefActivationContext (NTDLL.@)
4902 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
4904 ACTIVATION_CONTEXT
*actctx
;
4906 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
4910 /******************************************************************
4911 * RtlReleaseActivationContext (NTDLL.@)
4913 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
4915 ACTIVATION_CONTEXT
*actctx
;
4917 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
4922 /******************************************************************
4923 * RtlZombifyActivationContext (NTDLL.@)
4926 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
4930 if (Context
== ACTCTX_FAKE_HANDLE
)
4931 return STATUS_SUCCESS
;
4933 return STATUS_NOT_IMPLEMENTED
;
4937 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
4939 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
4941 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
4942 return STATUS_NO_MEMORY
;
4944 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
4945 frame
->ActivationContext
= handle
;
4948 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
4949 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
4952 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
4953 RtlAddRefActivationContext( handle
);
4955 *cookie
= (ULONG_PTR
)frame
;
4956 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
4957 return STATUS_SUCCESS
;
4960 /******************************************************************
4961 * RtlActivateActivationContext (NTDLL.@)
4963 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
4965 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
4968 /***********************************************************************
4969 * RtlDeactivateActivationContext (NTDLL.@)
4971 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
4973 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
4975 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
4977 /* find the right frame */
4978 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
4979 for (frame
= top
; frame
; frame
= frame
->Previous
)
4980 if ((ULONG_PTR
)frame
== cookie
) break;
4983 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
4985 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
4986 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
4988 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
4989 NtCurrentTeb()->ActivationContextStackPointer
,
4990 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
4993 /* pop everything up to and including frame */
4994 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
4996 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
4998 frame
= top
->Previous
;
4999 RtlReleaseActivationContext( top
->ActivationContext
);
5000 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
5004 return STATUS_SUCCESS
;
5009 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
5011 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
5013 /* Nothing to do if there is no stack */
5016 /* Get the current active frame */
5017 ActiveFrame
= Stack
->ActiveFrame
;
5019 /* Go through them in backwards order and release */
5022 PrevFrame
= ActiveFrame
->Previous
;
5023 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5024 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5025 ActiveFrame
= PrevFrame
;
5028 /* Zero out the active frame */
5029 Stack
->ActiveFrame
= NULL
;
5031 /* TODO: Empty the Frame List Cache */
5032 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5034 /* Free activation stack memory */
5035 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5038 /******************************************************************
5039 * RtlFreeThreadActivationContextStack (NTDLL.@)
5041 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5043 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5044 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5048 /******************************************************************
5049 * RtlGetActiveActivationContext (NTDLL.@)
5051 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5053 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5055 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5056 RtlAddRefActivationContext( *handle
);
5061 return STATUS_SUCCESS
;
5065 /******************************************************************
5066 * RtlIsActivationContextActive (NTDLL.@)
5068 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5070 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5072 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5073 if (frame
->ActivationContext
== handle
) return TRUE
;
5078 /***********************************************************************
5079 * RtlQueryInformationActivationContext (NTDLL.@)
5081 * Get information about an activation context.
5082 * FIXME: function signature/prototype may be wrong
5084 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5085 ULONG
class, PVOID buffer
,
5086 SIZE_T bufsize
, SIZE_T
*retlen
)
5088 ACTIVATION_CONTEXT
*actctx
;
5091 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5092 subinst
, class, buffer
, bufsize
, retlen
);
5094 if (retlen
) *retlen
= 0;
5095 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5099 case ActivationContextBasicInformation
:
5101 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5103 if (retlen
) *retlen
= sizeof(*info
);
5104 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5106 info
->hActCtx
= handle
;
5107 info
->dwFlags
= 0; /* FIXME */
5108 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5112 case ActivationContextDetailedInformation
:
5114 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5115 struct assembly
*assembly
= NULL
;
5116 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5119 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5121 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5123 if (assembly
&& assembly
->manifest
.info
)
5124 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5125 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5126 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5127 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5129 if (retlen
) *retlen
= len
;
5130 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5133 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5134 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5135 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5136 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5137 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5138 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5139 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5140 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5141 ptr
= (LPWSTR
)(acdi
+ 1);
5144 acdi
->lpRootManifestPath
= ptr
;
5145 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5146 ptr
+= manifest_len
;
5148 else acdi
->lpRootManifestPath
= NULL
;
5151 acdi
->lpRootConfigurationPath
= ptr
;
5152 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5155 else acdi
->lpRootConfigurationPath
= NULL
;
5158 acdi
->lpAppDirPath
= ptr
;
5159 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5161 else acdi
->lpAppDirPath
= NULL
;
5165 case AssemblyDetailedInformationInActivationContext
:
5167 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5168 struct assembly
*assembly
;
5171 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5174 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5175 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5177 index
= *(DWORD
*)subinst
;
5178 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5180 assembly
= &actctx
->assemblies
[index
- 1];
5182 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5183 id_len
= strlenW(assembly_id
) + 1;
5184 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5186 if (assembly
->manifest
.info
&&
5187 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5188 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5190 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5192 if (retlen
) *retlen
= len
;
5193 if (!buffer
|| bufsize
< len
)
5195 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5196 return STATUS_BUFFER_TOO_SMALL
;
5199 afdi
->ulFlags
= 0; /* FIXME */
5200 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5201 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5202 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5203 /* FIXME afdi->liManifestLastWriteTime = 0; */
5204 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5205 afdi
->ulPolicyPathLength
= 0;
5206 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5207 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5208 afdi
->ulManifestVersionMajor
= 1;
5209 afdi
->ulManifestVersionMinor
= 0;
5210 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5211 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5212 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5213 ptr
= (LPWSTR
)(afdi
+ 1);
5214 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5215 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5219 afdi
->lpAssemblyManifestPath
= ptr
;
5220 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5222 } else afdi
->lpAssemblyManifestPath
= NULL
;
5223 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5226 afdi
->lpAssemblyDirectoryName
= ptr
;
5227 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5229 else afdi
->lpAssemblyDirectoryName
= NULL
;
5230 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5234 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5236 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5237 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5238 struct assembly
*assembly
;
5239 struct dll_redirect
*dll
;
5240 SIZE_T len
, dll_len
= 0;
5243 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5244 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5246 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5247 return STATUS_INVALID_PARAMETER
;
5248 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5250 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5251 return STATUS_INVALID_PARAMETER
;
5252 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5254 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5255 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5257 if (!buffer
|| bufsize
< len
)
5259 if (retlen
) *retlen
= len
;
5260 return STATUS_BUFFER_TOO_SMALL
;
5262 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5263 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5264 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5265 afdi
->ulPathLength
= 0; /* FIXME */
5266 ptr
= (LPWSTR
)(afdi
+ 1);
5269 afdi
->lpFileName
= ptr
;
5270 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5271 } else afdi
->lpFileName
= NULL
;
5272 afdi
->lpFilePath
= NULL
; /* FIXME */
5277 DPRINT( "class %u not implemented\n", class );
5278 return STATUS_NOT_IMPLEMENTED
;
5280 return STATUS_SUCCESS
;
5285 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5287 SIZE_T cbBuffer OPTIONAL
,
5288 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5290 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5296 pcbWrittenOrRequired
);
5299 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5300 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5301 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5305 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5306 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5308 /* Check general parameter combinations */
5309 if (!section_name
|| !section_name
->Buffer
||
5310 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5311 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5312 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5314 DPRINT1("invalid parameter\n");
5315 return STATUS_INVALID_PARAMETER
;
5319 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5320 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5322 DPRINT1("unknown flags %08x\n", flags
);
5323 return STATUS_INVALID_PARAMETER
;
5326 return STATUS_SUCCESS
;
5329 /***********************************************************************
5330 * RtlFindActivationContextSectionString (NTDLL.@)
5332 * Find information about a string in an activation context.
5333 * FIXME: function signature/prototype may be wrong
5335 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5336 const UNICODE_STRING
*section_name
, PVOID ptr
)
5338 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5341 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5342 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5343 if (!NT_SUCCESS(status
))
5345 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5349 status
= STATUS_SXS_KEY_NOT_FOUND
;
5351 /* if there is no data, but params are valid,
5352 we return that sxs key is not found to be at least somehow compatible */
5355 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5359 ASSERT(NtCurrentTeb());
5360 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5362 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5363 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5365 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5366 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5369 DPRINT("status %x\n", status
);
5370 if (status
!= STATUS_SUCCESS
)
5371 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5373 if (status
!= STATUS_SUCCESS
)
5374 status
= find_string( implicit_actctx
, section_kind
, section_name
, flags
, data
);
5376 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5380 /***********************************************************************
5381 * RtlFindActivationContextSectionGuid (NTDLL.@)
5383 * Find information about a GUID in an activation context.
5384 * FIXME: function signature/prototype may be wrong
5386 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5387 const GUID
*guid
, void *ptr
)
5389 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5390 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5394 DPRINT1("expected extguid == NULL\n");
5395 return STATUS_INVALID_PARAMETER
;
5398 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5400 DPRINT1("unknown flags %08x\n", flags
);
5401 return STATUS_INVALID_PARAMETER
;
5404 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5405 return STATUS_INVALID_PARAMETER
;
5407 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5409 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5410 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5413 if (status
!= STATUS_SUCCESS
)
5414 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5416 if (status
!= STATUS_SUCCESS
)
5417 status
= find_guid( implicit_actctx
, section_kind
, guid
, flags
, data
);
5426 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5428 PACTIVATION_CONTEXT_STACK ContextStack
;
5430 /* Check if it's already allocated */
5431 if (*Stack
) return STATUS_SUCCESS
;
5433 /* Allocate space for the context stack */
5434 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5437 return STATUS_NO_MEMORY
;
5440 /* Initialize the context stack */
5441 ContextStack
->Flags
= 0;
5442 ContextStack
->ActiveFrame
= NULL
;
5443 InitializeListHead(&ContextStack
->FrameListCache
);
5444 ContextStack
->NextCookieSequenceNumber
= 1;
5445 ContextStack
->StackId
= 1; //TODO: Timer-based
5447 *Stack
= ContextStack
;
5449 return STATUS_SUCCESS
;
5452 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5454 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5457 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5458 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5460 /* Get the current active frame */
5461 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5463 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5464 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5465 &Frame
->Frame
, Context
);
5467 /* Ensure it's in the right format and at least fits basic info */
5468 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5469 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5471 /* Set debug info if size allows*/
5472 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5474 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5475 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5476 //Frame->Extra3 = ...;
5481 /*ASSERT((ActiveFrame->Flags &
5482 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5483 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5484 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5486 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5488 // TODO: Perform some additional checks if it was not heap allocated
5492 /* Save pointer to the new activation frame */
5493 NewFrame
= &Frame
->Frame
;
5495 /* Actually activate it */
5496 Frame
->Frame
.Previous
= ActiveFrame
;
5497 Frame
->Frame
.ActivationContext
= Context
;
5498 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5500 /* Check if we can activate this context */
5501 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5504 /* Set new active frame */
5505 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5506 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5510 /* We can get here only one way: it was already activated */
5511 DPRINT("Trying to activate already activated activation context\n");
5513 /* Activate only if we are allowing multiple activation */
5515 if (!RtlpNotAllowingMultipleActivation
)
5517 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5518 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5521 // Activate it anyway
5522 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5525 /* Return pointer to the activation frame */
5529 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5531 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5533 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5535 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5537 /* Ensure it's in the right format and at least fits basic info */
5538 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5539 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5541 /* Make sure it is not deactivated and it is activated */
5542 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5543 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5544 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
);
5546 /* Check debug info if it is present */
5547 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5549 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5550 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5551 //Frame->Extra3 = ...;
5556 // TODO: Perform some additional checks here
5559 /* Special handling for not-really-activated */
5560 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5562 DPRINT1("Deactivating not really activated activation context\n");
5563 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5564 return &Frame
->Frame
;
5567 /* find the right frame */
5568 NewFrame
= &Frame
->Frame
;
5569 if (ActiveFrame
!= NewFrame
)
5571 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5574 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5575 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5577 /* Pop everything up to and including frame */
5578 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5580 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5581 return NewFrame
->Previous
;