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 3.2-37c98396 */
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
;
453 COMPATIBILITY_CONTEXT_ELEMENT
*compat_contexts
;
454 ULONG num_compat_contexts
;
455 ACTCTX_REQUESTED_RUN_LEVEL run_level
;
459 enum context_sections
461 WINDOWCLASS_SECTION
= 1,
462 DLLREDIRECT_SECTION
= 2,
463 TLIBREDIRECT_SECTION
= 4,
464 SERVERREDIRECT_SECTION
= 8,
465 IFACEREDIRECT_SECTION
= 16,
466 CLRSURROGATES_SECTION
= 32,
467 PROGIDREDIRECT_SECTION
= 64
470 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
473 UNICODE_STRING DosPath
;
475 } ASSEMBLY_STORAGE_MAP_ENTRY
, *PASSEMBLY_STORAGE_MAP_ENTRY
;
477 typedef struct _ASSEMBLY_STORAGE_MAP
481 PASSEMBLY_STORAGE_MAP_ENTRY
*AssemblyArray
;
482 } ASSEMBLY_STORAGE_MAP
, *PASSEMBLY_STORAGE_MAP
;
484 typedef struct _ACTIVATION_CONTEXT
489 PACTIVATION_CONTEXT_DATA ActivationContextData
;
490 PVOID NotificationRoutine
;
491 PVOID NotificationContext
;
492 ULONG SentNotifications
[8];
493 ULONG DisabledNotifications
[8];
494 ASSEMBLY_STORAGE_MAP StorageMap
;
495 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries
;
496 ULONG StackTraceIndex
;
497 PVOID StackTraces
[4][4];
498 struct file_info config
;
499 struct file_info appdir
;
500 struct assembly
*assemblies
;
501 unsigned int num_assemblies
;
502 unsigned int allocated_assemblies
;
505 struct strsection_header
*wndclass_section
;
506 struct strsection_header
*dllredirect_section
;
507 struct strsection_header
*progid_section
;
508 struct guidsection_header
*tlib_section
;
509 struct guidsection_header
*comserver_section
;
510 struct guidsection_header
*ifaceps_section
;
511 struct guidsection_header
*clrsurrogate_section
;
512 } ACTIVATION_CONTEXT
, *PIACTIVATION_CONTEXT
;
516 ACTIVATION_CONTEXT
*actctx
;
517 struct assembly_identity
*dependencies
;
518 unsigned int num_dependencies
;
519 unsigned int allocated_dependencies
;
522 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
523 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
525 typedef struct _ACTIVATION_CONTEXT_WRAPPED
528 ACTIVATION_CONTEXT ActivationContext
;
529 } ACTIVATION_CONTEXT_WRAPPED
, *PACTIVATION_CONTEXT_WRAPPED
;
533 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx
,
534 IN ULONG FailureCode
)
536 EXCEPTION_RECORD ExceptionRecord
;
538 /* Fatal SxS exception header */
539 ExceptionRecord
.ExceptionRecord
= NULL
;
540 ExceptionRecord
.ExceptionCode
= STATUS_SXS_CORRUPTION
;
541 ExceptionRecord
.ExceptionFlags
= EXCEPTION_NONCONTINUABLE
;
543 /* With SxS-specific information plus the context itself */
544 ExceptionRecord
.ExceptionInformation
[0] = 1;
545 ExceptionRecord
.ExceptionInformation
[1] = FailureCode
;
546 ExceptionRecord
.ExceptionInformation
[2] = (ULONG_PTR
)ActCtx
;
547 ExceptionRecord
.NumberParameters
= 3;
550 RtlRaiseException(&ExceptionRecord
);
555 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx
)
557 PACTIVATION_CONTEXT_WRAPPED pActual
;
559 /* Get the caller-opaque header */
560 pActual
= CONTAINING_RECORD(ActCtx
,
561 ACTIVATION_CONTEXT_WRAPPED
,
564 /* Check if the header matches as expected */
565 if (pActual
->MagicMarker
!= ACTCTX_MAGIC_MARKER
)
567 /* Nope, print out a warning, assert, and then throw an exception */
568 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
569 " This means someone stepped on the allocation, or someone is using a\n"
570 " deallocated activation context\n",
572 pActual
->MagicMarker
,
574 ASSERT(pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
);
575 RtlpSxsBreakOnInvalidMarker(ActCtx
, 1);
579 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
580 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
581 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
582 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
583 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
584 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
585 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};
586 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};
587 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
588 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
589 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
590 static const WCHAR fileW
[] = {'f','i','l','e',0};
591 static const WCHAR hashW
[] = {'h','a','s','h',0};
592 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
593 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
594 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
595 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
597 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
598 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
599 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
600 static const WCHAR iidW
[] = {'i','i','d',0};
601 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
602 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
603 static const WCHAR g_nameW
[] = {'n','a','m','e',0};
604 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
605 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
606 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
607 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
608 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};
609 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
610 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
611 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
612 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
613 static const WCHAR typeW
[] = {'t','y','p','e',0};
614 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
615 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
616 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
617 static const WCHAR yesW
[] = {'y','e','s',0};
618 static const WCHAR noW
[] = {'n','o',0};
619 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
620 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
621 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
622 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
623 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
624 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
625 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
626 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
627 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
628 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
629 static const WCHAR baseInterfaceW
[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
630 static const WCHAR nummethodsW
[] = {'n','u','m','M','e','t','h','o','d','s',0};
631 static const WCHAR proxyStubClsid32W
[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
632 static const WCHAR runtimeVersionW
[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
633 static const WCHAR mscoreeW
[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
634 static const WCHAR mscoree2W
[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
636 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
637 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
638 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
639 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
640 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
641 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
642 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
643 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};
644 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
645 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
646 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
647 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
648 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
649 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
650 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
651 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
652 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};
653 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
654 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
655 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
656 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};
657 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
659 static const WCHAR compatibilityW
[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
660 static const WCHAR compatibilityNSW
[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
661 static const WCHAR applicationW
[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
662 static const WCHAR supportedOSW
[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
663 static const WCHAR IdW
[] = {'I','d',0};
664 static const WCHAR requestedExecutionLevelW
[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
665 static const WCHAR requestedPrivilegesW
[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
666 static const WCHAR securityW
[] = {'s','e','c','u','r','i','t','y',0};
667 static const WCHAR trustInfoW
[] = {'t','r','u','s','t','I','n','f','o',0};
675 static const struct olemisc_entry olemisc_values
[] =
677 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
678 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
679 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
680 { alignableW
, OLEMISC_ALIGNABLE
},
681 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
682 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
683 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
684 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
685 { imemodeW
, OLEMISC_IMEMODE
},
686 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
687 { insideoutW
, OLEMISC_INSIDEOUT
},
688 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
689 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
690 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
691 { onlyiconicW
, OLEMISC_ONLYICONIC
},
692 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
693 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
694 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
695 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
696 { staticW
, OLEMISC_STATIC
},
697 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
698 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
701 static const WCHAR g_xmlW
[] = {'?','x','m','l',0};
702 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};
703 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};
704 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};
706 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
707 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
708 static const WCHAR wildcardW
[] = {'*',0};
710 static ACTIVATION_CONTEXT_WRAPPED system_actctx
= { ACTCTX_MAGIC_MARKER
, { 1 } };
711 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
.ActivationContext
;
712 static ACTIVATION_CONTEXT
*implicit_actctx
= &system_actctx
.ActivationContext
;
714 static WCHAR
*strdupW(const WCHAR
* str
)
718 if (!(ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
720 return strcpyW(ptr
, str
);
723 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
727 if ((strW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
729 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
735 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
737 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
740 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
742 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
745 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
747 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
748 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
751 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
753 UINT len
= strlenW( namespace );
755 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
756 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
757 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
760 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
762 if (elem
->len
&& elem
->ptr
[0] == '/')
765 elem_end
.ptr
= elem
->ptr
+ 1;
766 elem_end
.len
= elem
->len
- 1;
767 return xml_elem_cmp( &elem_end
, str
, namespace );
772 static inline BOOL
isxmlspace( WCHAR ch
)
774 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
777 static UNICODE_STRING
xmlstr2unicode(const xmlstr_t
*xmlstr
)
781 res
.Buffer
= (PWSTR
)xmlstr
->ptr
;
782 res
.Length
= res
.MaximumLength
= (USHORT
)xmlstr
->len
* sizeof(WCHAR
);
787 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
789 struct assembly
*assembly
;
791 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx
);
793 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
796 unsigned int new_count
;
797 if (actctx
->assemblies
)
799 new_count
= actctx
->allocated_assemblies
* 2;
800 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
801 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
806 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
808 if (!ptr
) return NULL
;
809 actctx
->assemblies
= ptr
;
810 actctx
->allocated_assemblies
= new_count
;
813 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
818 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
820 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly
, assembly
->allocated_dlls
);
822 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
825 unsigned int new_count
;
828 new_count
= assembly
->allocated_dlls
* 2;
829 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
830 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
835 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
837 if (!ptr
) return NULL
;
838 assembly
->dlls
= ptr
;
839 assembly
->allocated_dlls
= new_count
;
841 return &assembly
->dlls
[assembly
->num_dlls
++];
844 static PCOMPATIBILITY_CONTEXT_ELEMENT
add_compat_context(struct assembly
* assembly
)
847 if (assembly
->num_compat_contexts
)
849 unsigned int new_count
= assembly
->num_compat_contexts
+ 1;
850 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
851 assembly
->compat_contexts
,
852 new_count
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
856 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(COMPATIBILITY_CONTEXT_ELEMENT
) );
858 if (!ptr
) return NULL
;
859 assembly
->compat_contexts
= ptr
;
860 return &assembly
->compat_contexts
[assembly
->num_compat_contexts
++];
863 static void free_assembly_identity(struct assembly_identity
*ai
)
865 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->name
);
866 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->arch
);
867 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->public_key
);
868 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->language
);
869 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->type
);
872 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
874 struct entity
* entity
;
876 if (array
->num
== array
->allocated
)
879 unsigned int new_count
;
882 new_count
= array
->allocated
* 2;
883 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
884 array
->base
, new_count
* sizeof(*array
->base
) );
889 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
891 if (!ptr
) return NULL
;
893 array
->allocated
= new_count
;
895 entity
= &array
->base
[array
->num
++];
900 static void free_entity_array(struct entity_array
*array
)
903 for (i
= 0; i
< array
->num
; i
++)
905 struct entity
*entity
= &array
->base
[i
];
906 switch (entity
->kind
)
908 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
909 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
910 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
911 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progid
);
912 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.name
);
913 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.version
);
914 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
915 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
[j
]);
916 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.progids
.progids
);
918 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
919 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.iid
);
920 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.base
);
921 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.ps32
);
922 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.name
);
923 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.ifaceps
.tlib
);
925 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
926 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
927 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
929 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
930 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.class.name
);
932 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
933 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
934 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
935 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.version
);
938 DPRINT1("Unknown entity kind %u\n", entity
->kind
);
941 RtlFreeHeap( RtlGetProcessHeap(), 0, array
->base
);
944 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
946 if (!str1
) return !str2
;
947 return str2
&& !strcmpiW( str1
, str2
);
950 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
951 const struct assembly_identity
*id2
)
953 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
954 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
955 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
957 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
959 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
962 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
963 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
964 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
965 if (id1
->version
.build
== id2
->version
.build
&&
966 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
970 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
971 struct assembly_identity
* ai
)
975 /* check if we already have that assembly */
977 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
978 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
980 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
981 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
982 ai
->version
.build
, ai
->version
.revision
);
986 for (i
= 0; i
< acl
->num_dependencies
; i
++)
987 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
989 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
990 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
991 ai
->version
.build
, ai
->version
.revision
);
995 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
998 unsigned int new_count
;
999 if (acl
->dependencies
)
1001 new_count
= acl
->allocated_dependencies
* 2;
1002 ptr
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl
->dependencies
,
1003 new_count
* sizeof(acl
->dependencies
[0]));
1008 ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
1010 if (!ptr
) return FALSE
;
1011 acl
->dependencies
= ptr
;
1012 acl
->allocated_dependencies
= new_count
;
1014 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
1019 static void free_depend_manifests(struct actctx_loader
* acl
)
1022 for (i
= 0; i
< acl
->num_dependencies
; i
++)
1023 free_assembly_identity(&acl
->dependencies
[i
]);
1024 RtlFreeHeap(RtlGetProcessHeap(), 0, acl
->dependencies
);
1027 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
1029 static const WCHAR undW
[] = {'_',0};
1030 static const WCHAR noneW
[] = {'n','o','n','e',0};
1031 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
1033 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
1034 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
1035 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
1036 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
1037 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
1038 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
1041 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
))) return NULL
;
1043 strcpyW( ret
, arch
);
1044 strcatW( ret
, undW
);
1045 strcatW( ret
, name
);
1046 strcatW( ret
, undW
);
1047 strcatW( ret
, key
);
1048 strcatW( ret
, undW
);
1049 sprintfW( ret
+ strlenW(ret
), version_formatW
,
1050 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1051 strcatW( ret
, undW
);
1052 strcatW( ret
, lang
);
1053 strcatW( ret
, undW
);
1054 strcatW( ret
, mskeyW
);
1058 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
1063 strcatW( buffer
, prefix
);
1072 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
1074 static const WCHAR archW
[] =
1075 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1076 static const WCHAR public_keyW
[] =
1077 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1078 static const WCHAR typeW2
[] =
1079 {',','t','y','p','e','=',0};
1080 static const WCHAR versionW2
[] =
1081 {',','v','e','r','s','i','o','n','=',0};
1083 WCHAR version
[64], *ret
;
1086 sprintfW( version
, version_formatW
,
1087 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
1088 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
1089 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
1090 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
1091 if (ai
->type
) size
+= strlenW(typeW2
) + strlenW(ai
->type
) + 2;
1092 size
+= strlenW(versionW2
) + strlenW(version
) + 2;
1094 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
1097 if (ai
->name
) strcpyW( ret
, ai
->name
);
1099 append_string( ret
, archW
, ai
->arch
);
1100 append_string( ret
, public_keyW
, ai
->public_key
);
1101 append_string( ret
, typeW2
, ai
->type
);
1102 append_string( ret
, versionW2
, version
);
1106 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
1108 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
1109 PACTIVATION_CONTEXT_WRAPPED pActual
;
1111 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
1116 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1117 if (pActual
->MagicMarker
== ACTCTX_MAGIC_MARKER
) ret
= &pActual
->ActivationContext
;
1120 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1122 DPRINT1("Invalid activation context handle!\n");
1128 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
1130 InterlockedExchangeAdd( &actctx
->RefCount
, 1 );
1133 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
1135 PACTIVATION_CONTEXT_WRAPPED pActual
;
1137 if (InterlockedExchangeAdd(&actctx
->RefCount
, -1) == 1)
1141 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
1143 struct assembly
*assembly
= &actctx
->assemblies
[i
];
1144 for (j
= 0; j
< assembly
->num_dlls
; j
++)
1146 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
1147 free_entity_array( &dll
->entities
);
1148 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->name
);
1149 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->hash
);
1151 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->dlls
);
1152 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->manifest
.info
);
1153 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->directory
);
1154 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->compat_contexts
);
1155 free_entity_array( &assembly
->entities
);
1156 free_assembly_identity(&assembly
->id
);
1158 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->config
.info
);
1159 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->appdir
.info
);
1160 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->assemblies
);
1161 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
1162 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
1163 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
1164 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
1165 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
1166 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
1167 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
1169 pActual
= CONTAINING_RECORD(actctx
, ACTIVATION_CONTEXT_WRAPPED
, ActivationContext
);
1170 pActual
->MagicMarker
= 0;
1171 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual
);
1175 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
1176 BOOL
* error
, BOOL
* end
)
1182 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
1185 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1187 if (*xmlbuf
->ptr
== '/')
1190 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
1199 if (*xmlbuf
->ptr
== '>')
1207 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
1209 if (ptr
== xmlbuf
->end
) return FALSE
;
1211 name
->ptr
= xmlbuf
->ptr
;
1212 name
->len
= ptr
-xmlbuf
->ptr
;
1215 /* skip spaces before '=' */
1216 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && isxmlspace(*ptr
)) ptr
++;
1217 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
1219 /* skip '=' itself */
1221 if (ptr
== xmlbuf
->end
) return FALSE
;
1223 /* skip spaces after '=' */
1224 while (ptr
< xmlbuf
->end
&& *ptr
!= '"' && *ptr
!= '\'' && isxmlspace(*ptr
)) ptr
++;
1226 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
1229 if (ptr
== xmlbuf
->end
) return FALSE
;
1231 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
1234 xmlbuf
->ptr
= xmlbuf
->end
;
1238 value
->len
= ptr
- value
->ptr
;
1239 xmlbuf
->ptr
= ptr
+ 1;
1241 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
1247 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
1253 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1256 xmlbuf
->ptr
= xmlbuf
->end
;
1260 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1262 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1263 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1265 if (ptr
+ 3 > xmlbuf
->end
)
1267 xmlbuf
->ptr
= xmlbuf
->end
;
1270 xmlbuf
->ptr
= ptr
+ 3;
1276 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1279 elem
->ptr
= xmlbuf
->ptr
;
1280 elem
->len
= ptr
- xmlbuf
->ptr
;
1282 return xmlbuf
->ptr
!= xmlbuf
->end
;
1285 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1287 /* FIXME: parse attributes */
1290 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1292 if (ptr
[0] == '?' && ptr
[1] == '>')
1294 xmlbuf
->ptr
= ptr
+ 2;
1301 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1303 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1305 if (!ptr
) return FALSE
;
1307 content
->ptr
= xmlbuf
->ptr
;
1308 content
->len
= ptr
- xmlbuf
->ptr
;
1314 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1316 unsigned int ver
[4];
1319 UNICODE_STRING strU
;
1321 /* major.minor.build.revision */
1322 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1323 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1325 if (*curr
>= '0' && *curr
<= '9')
1327 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1328 if (ver
[pos
] >= 0x10000) goto error
;
1330 else if (*curr
== '.')
1332 if (++pos
>= 4) goto error
;
1336 version
->major
= ver
[0];
1337 version
->minor
= ver
[1];
1338 version
->build
= ver
[2];
1339 version
->revision
= ver
[3];
1343 strU
= xmlstr2unicode(str
);
1344 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU
);
1348 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1351 UNICODE_STRING elemU
;
1352 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1353 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1354 elemU
= xmlstr2unicode(&elem
);
1355 DPRINT1( "unexpected element %wZ\n", &elemU
);
1359 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1361 xmlstr_t attr_name
, attr_value
;
1362 UNICODE_STRING attr_nameU
, attr_valueU
;
1365 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1367 attr_nameU
= xmlstr2unicode(&attr_name
);
1368 attr_valueU
= xmlstr2unicode(&attr_value
);
1369 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU
,
1375 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1378 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1381 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1384 UNICODE_STRING elemU
;
1385 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1386 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1388 elemU
= xmlstr2unicode(&elem
);
1389 DPRINT1( "unexpected element %wZ\n", &elemU
);
1392 return parse_end_element(xmlbuf
);
1395 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1397 xmlstr_t attr_name
, attr_value
, elem
;
1398 BOOL end
= FALSE
, error
, ret
= TRUE
;
1400 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1401 if(error
|| end
) return end
;
1403 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1405 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1406 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1409 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1412 return ret
&& parse_end_element(xmlbuf
);
1415 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1416 struct assembly_identity
* ai
)
1418 xmlstr_t attr_name
, attr_value
;
1419 BOOL end
= FALSE
, error
;
1420 UNICODE_STRING attr_valueU
, attr_nameU
;
1422 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1424 if (xmlstr_cmp(&attr_name
, g_nameW
))
1426 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1428 else if (xmlstr_cmp(&attr_name
, typeW
))
1430 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1432 else if (xmlstr_cmp(&attr_name
, versionW
))
1434 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1436 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1438 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1440 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1442 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1444 else if (xmlstr_cmp(&attr_name
, languageW
))
1446 DPRINT("Unsupported yet language attribute (%.*S)\n",
1447 attr_value
.len
, attr_value
.ptr
);
1448 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1452 attr_nameU
= xmlstr2unicode(&attr_name
);
1453 attr_valueU
= xmlstr2unicode(&attr_value
);
1454 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1458 if (error
|| end
) return end
;
1459 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1462 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1464 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1465 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1466 static const WCHAR freeW
[] = {'F','r','e','e',0};
1467 static const WCHAR bothW
[] = {'B','o','t','h',0};
1469 if (value
->len
== 0) return ThreadingModel_No
;
1470 if (xmlstr_cmp(value
, apartW
))
1471 return ThreadingModel_Apartment
;
1472 else if (xmlstr_cmp(value
, freeW
))
1473 return ThreadingModel_Free
;
1474 else if (xmlstr_cmp(value
, bothW
))
1475 return ThreadingModel_Both
;
1476 else if (xmlstr_cmp(value
, neutralW
))
1477 return ThreadingModel_Neutral
;
1479 return ThreadingModel_No
;
1482 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1487 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1495 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1496 if (!c
&& !olemisc_values
[n
].name
[len
])
1497 return olemisc_values
[n
].value
;
1505 DPRINT1("unknown flag %S\n", str
);
1509 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1511 const WCHAR
*str
= value
->ptr
, *start
;
1515 /* it's comma separated list of flags */
1516 while (i
< value
->len
)
1519 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1521 flags
|= get_olemisc_value(start
, str
-start
);
1523 /* skip separator */
1531 static BOOL
com_class_add_progid(const xmlstr_t
*progid
, struct entity
*entity
)
1533 struct progids
*progids
= &entity
->u
.comclass
.progids
;
1535 if (progids
->allocated
== 0)
1537 progids
->allocated
= 4;
1538 if (!(progids
->progids
= RtlAllocateHeap(RtlGetProcessHeap(), 0, progids
->allocated
* sizeof(WCHAR
*)))) return FALSE
;
1541 if (progids
->allocated
== progids
->num
)
1543 WCHAR
**new_progids
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids
->progids
,
1544 2 * progids
->allocated
* sizeof(WCHAR
*));
1545 if (!new_progids
) return FALSE
;
1546 progids
->allocated
*= 2;
1547 progids
->progids
= new_progids
;
1550 if (!(progids
->progids
[progids
->num
] = xmlstrdupW(progid
))) return FALSE
;
1556 static BOOL
parse_com_class_progid(xmlbuf_t
* xmlbuf
, struct entity
*entity
)
1561 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
|| !parse_text_content(xmlbuf
, &content
))
1564 if (!com_class_add_progid(&content
, entity
)) return FALSE
;
1565 return parse_expect_end_elem(xmlbuf
, progidW
, asmv1W
);
1568 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
*acl
)
1570 xmlstr_t elem
, attr_name
, attr_value
;
1571 BOOL ret
= TRUE
, end
= FALSE
, error
;
1572 struct entity
* entity
;
1573 UNICODE_STRING attr_valueU
, attr_nameU
;
1575 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1578 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1580 if (xmlstr_cmp(&attr_name
, clsidW
))
1582 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1584 else if (xmlstr_cmp(&attr_name
, progidW
))
1586 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1588 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1590 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1592 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1594 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1596 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1598 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1600 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1602 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1604 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1606 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1608 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1610 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1612 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1614 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1616 else if (xmlstr_cmp(&attr_name
, descriptionW
))
1622 attr_nameU
= xmlstr2unicode(&attr_name
);
1623 attr_valueU
= xmlstr2unicode(&attr_value
);
1624 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1628 if (error
) return FALSE
;
1630 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
1631 if (entity
->u
.comclass
.progid
)
1632 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1634 if (end
) return TRUE
;
1636 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1638 if (xmlstr_cmp_end(&elem
, comClassW
))
1640 ret
= parse_end_element(xmlbuf
);
1643 else if (xmlstr_cmp(&elem
, progidW
))
1645 ret
= parse_com_class_progid(xmlbuf
, entity
);
1649 attr_nameU
= xmlstr2unicode(&elem
);
1650 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
1651 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1655 if (entity
->u
.comclass
.progids
.num
)
1656 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
1661 static BOOL
parse_nummethods(const xmlstr_t
*str
, struct entity
*entity
)
1666 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1668 if (*curr
>= '0' && *curr
<= '9')
1669 num
= num
* 10 + *curr
- '0';
1672 UNICODE_STRING strU
= xmlstr2unicode(str
);
1673 DPRINT1("wrong numeric value %wZ\n", &strU
);
1677 entity
->u
.ifaceps
.nummethods
= num
;
1682 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1684 xmlstr_t attr_name
, attr_value
;
1685 BOOL end
= FALSE
, error
;
1686 struct entity
* entity
;
1687 UNICODE_STRING attr_valueU
, attr_nameU
;
1689 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1692 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1694 if (xmlstr_cmp(&attr_name
, iidW
))
1696 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1698 else if (xmlstr_cmp(&attr_name
, g_nameW
))
1700 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1702 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
1704 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
1705 entity
->u
.ifaceps
.mask
|= BaseIface
;
1707 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
1709 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
1710 entity
->u
.ifaceps
.mask
|= NumMethods
;
1712 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1714 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
1717 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
) || xmlstr_cmp(&attr_name
, threadingmodelW
))
1722 attr_nameU
= xmlstr2unicode(&attr_name
);
1723 attr_valueU
= xmlstr2unicode(&attr_value
);
1724 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1728 if (error
) return FALSE
;
1729 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
1730 if (end
) return TRUE
;
1732 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1735 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1737 WORD
*flags
= &entity
->u
.typelib
.flags
;
1738 const WCHAR
*str
= value
->ptr
, *start
;
1743 /* it's comma separated list of flags */
1744 while (i
< value
->len
)
1747 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1749 if (!strncmpiW(start
, restrictedW
, str
-start
))
1750 *flags
|= LIBFLAG_FRESTRICTED
;
1751 else if (!strncmpiW(start
, controlW
, str
-start
))
1752 *flags
|= LIBFLAG_FCONTROL
;
1753 else if (!strncmpiW(start
, hiddenW
, str
-start
))
1754 *flags
|= LIBFLAG_FHIDDEN
;
1755 else if (!strncmpiW(start
, hasdiskimageW
, str
-start
))
1756 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1759 UNICODE_STRING valueU
= xmlstr2unicode(value
);
1760 DPRINT1("unknown flags value %wZ\n", &valueU
);
1764 /* skip separator */
1772 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1774 unsigned int ver
[2];
1777 UNICODE_STRING strW
;
1780 ver
[0] = ver
[1] = pos
= 0;
1781 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1783 if (*curr
>= '0' && *curr
<= '9')
1785 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1786 if (ver
[pos
] >= 0x10000) goto error
;
1788 else if (*curr
== '.')
1790 if (++pos
>= 2) goto error
;
1794 entity
->u
.typelib
.major
= ver
[0];
1795 entity
->u
.typelib
.minor
= ver
[1];
1799 strW
= xmlstr2unicode(str
);
1800 DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW
);
1804 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1806 xmlstr_t attr_name
, attr_value
;
1807 BOOL end
= FALSE
, error
;
1808 struct entity
* entity
;
1809 UNICODE_STRING attr_valueU
, attr_nameU
;
1811 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1814 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1816 if (xmlstr_cmp(&attr_name
, tlbidW
))
1818 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1820 else if (xmlstr_cmp(&attr_name
, versionW
))
1822 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1824 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1826 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1828 else if (xmlstr_cmp(&attr_name
, flagsW
))
1830 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1834 attr_nameU
= xmlstr2unicode(&attr_name
);
1835 attr_valueU
= xmlstr2unicode(&attr_value
);
1836 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1840 if (error
) return FALSE
;
1842 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1844 if (end
) return TRUE
;
1846 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1849 static inline int aligned_string_len(int len
)
1851 return (len
+ 3) & ~3;
1854 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1856 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1857 struct assembly_version
*ver
= &assembly
->id
.version
;
1860 if (!ret
) ret
= buff
;
1861 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1864 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1866 xmlstr_t elem
, content
, attr_name
, attr_value
;
1867 BOOL end
= FALSE
, ret
= TRUE
, error
;
1868 struct entity
* entity
;
1869 UNICODE_STRING elemU
, attr_nameU
, attr_valueU
;
1871 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1874 entity
->u
.class.versioned
= TRUE
;
1875 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1877 if (xmlstr_cmp(&attr_name
, versionedW
))
1879 if (xmlstr_cmpi(&attr_value
, noW
))
1880 entity
->u
.class.versioned
= FALSE
;
1881 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1886 attr_nameU
= xmlstr2unicode(&attr_name
);
1887 attr_valueU
= xmlstr2unicode(&attr_value
);
1888 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1892 if (error
|| end
) return end
;
1894 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1896 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1898 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1900 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1902 if (xmlstr_cmp_end(&elem
, windowClassW
))
1904 ret
= parse_end_element(xmlbuf
);
1909 elemU
= xmlstr2unicode(&elem
);
1910 DPRINT1("unknown elem %wZ\n", &elemU
);
1911 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1918 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1920 xmlstr_t attr_name
, attr_value
;
1921 UNICODE_STRING attr_valueU
, attr_nameU
;
1922 BOOL end
= FALSE
, error
;
1924 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1926 attr_nameU
= xmlstr2unicode(&attr_name
);
1927 attr_valueU
= xmlstr2unicode(&attr_value
);
1929 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1931 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU
);
1933 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1935 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU
);
1939 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
1943 if (error
|| end
) return end
;
1944 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1947 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1949 xmlstr_t elem
, content
, attr_name
, attr_value
;
1950 BOOL end
= FALSE
, ret
= TRUE
, error
= FALSE
;
1952 UNICODE_STRING elem1U
, elem2U
;
1954 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1956 elem1U
= xmlstr2unicode(&attr_name
);
1957 elem2U
= xmlstr2unicode(&attr_value
);
1958 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
1961 if (error
) return FALSE
;
1962 if (end
) return TRUE
;
1964 if (!parse_text_content(xmlbuf
, &content
))
1967 elem1U
= xmlstr2unicode(&content
);
1968 DPRINT("Got description %wZ\n", &elem1U
);
1970 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1972 if (xmlstr_cmp_end(&elem
, descriptionW
))
1974 ret
= parse_end_element(xmlbuf
);
1979 elem1U
= xmlstr2unicode(&elem
);
1980 DPRINT1("unknown elem %wZ\n", &elem1U
);
1981 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1988 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1989 struct assembly
* assembly
,
1990 struct actctx_loader
* acl
)
1992 xmlstr_t attr_name
, attr_value
;
1993 UNICODE_STRING attr_nameU
, attr_valueU
;
1994 BOOL end
= FALSE
, error
;
1995 struct entity
* entity
;
1997 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1998 if (!entity
) return FALSE
;
2000 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2002 if (xmlstr_cmp(&attr_name
, iidW
))
2004 if (!(entity
->u
.ifaceps
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
2006 else if (xmlstr_cmp(&attr_name
, g_nameW
))
2008 if (!(entity
->u
.ifaceps
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2010 else if (xmlstr_cmp(&attr_name
, baseInterfaceW
))
2012 if (!(entity
->u
.ifaceps
.base
= xmlstrdupW(&attr_value
))) return FALSE
;
2013 entity
->u
.ifaceps
.mask
|= BaseIface
;
2015 else if (xmlstr_cmp(&attr_name
, nummethodsW
))
2017 if (!(parse_nummethods(&attr_value
, entity
))) return FALSE
;
2018 entity
->u
.ifaceps
.mask
|= NumMethods
;
2020 else if (xmlstr_cmp(&attr_name
, proxyStubClsid32W
))
2022 if (!(entity
->u
.ifaceps
.ps32
= xmlstrdupW(&attr_value
))) return FALSE
;
2024 else if (xmlstr_cmp(&attr_name
, tlbidW
))
2026 if (!(entity
->u
.ifaceps
.tlib
= xmlstrdupW(&attr_value
))) return FALSE
;
2030 attr_nameU
= xmlstr2unicode(&attr_name
);
2031 attr_valueU
= xmlstr2unicode(&attr_value
);
2032 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2036 if (error
) return FALSE
;
2037 acl
->actctx
->sections
|= IFACEREDIRECT_SECTION
;
2038 if (end
) return TRUE
;
2040 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
2043 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2045 xmlstr_t attr_name
, attr_value
, elem
;
2046 BOOL end
= FALSE
, error
, ret
= TRUE
;
2047 struct entity
* entity
;
2049 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
);
2050 if (!entity
) return FALSE
;
2052 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2054 if (xmlstr_cmp(&attr_name
, g_nameW
))
2056 if (!(entity
->u
.comclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2058 else if (xmlstr_cmp(&attr_name
, clsidW
))
2060 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2062 else if (xmlstr_cmp(&attr_name
, progidW
))
2064 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
2066 else if (xmlstr_cmp(&attr_name
, tlbidW
))
2068 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
2070 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
2072 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
2074 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2076 if (!(entity
->u
.comclass
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2080 UNICODE_STRING attr_nameU
, attr_valueU
;
2081 attr_nameU
= xmlstr2unicode(&attr_name
);
2082 attr_valueU
= xmlstr2unicode(&attr_value
);
2083 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2087 if (error
) return FALSE
;
2088 acl
->actctx
->sections
|= SERVERREDIRECT_SECTION
;
2089 if (entity
->u
.comclass
.progid
)
2090 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2091 if (end
) return TRUE
;
2093 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2095 if (xmlstr_cmp_end(&elem
, clrClassW
))
2097 ret
= parse_end_element(xmlbuf
);
2100 else if (xmlstr_cmp(&elem
, progidW
))
2102 ret
= parse_com_class_progid(xmlbuf
, entity
);
2106 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2107 DPRINT1("unknown elem %wZ\n", &elemU
);
2108 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2112 if (entity
->u
.comclass
.progids
.num
)
2113 acl
->actctx
->sections
|= PROGIDREDIRECT_SECTION
;
2118 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2120 xmlstr_t attr_name
, attr_value
;
2121 UNICODE_STRING attr_nameU
, attr_valueU
;
2122 BOOL end
= FALSE
, error
;
2123 struct entity
* entity
;
2125 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
2126 if (!entity
) return FALSE
;
2128 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2130 if (xmlstr_cmp(&attr_name
, g_nameW
))
2132 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
2134 else if (xmlstr_cmp(&attr_name
, clsidW
))
2136 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
2138 else if (xmlstr_cmp(&attr_name
, runtimeVersionW
))
2140 if (!(entity
->u
.clrsurrogate
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
2144 attr_nameU
= xmlstr2unicode(&attr_name
);
2145 attr_valueU
= xmlstr2unicode(&attr_value
);
2146 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2150 if (error
) return FALSE
;
2151 acl
->actctx
->sections
|= CLRSURROGATES_SECTION
;
2152 if (end
) return TRUE
;
2154 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
2157 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
2159 struct assembly_identity ai
;
2160 xmlstr_t elem
, attr_name
, attr_value
;
2161 BOOL end
= FALSE
, error
= FALSE
, ret
= TRUE
, delayed
= FALSE
;
2163 UNICODE_STRING elem1U
, elem2U
;
2165 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2167 static const WCHAR allowDelayedBindingW
[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2168 static const WCHAR trueW
[] = {'t','r','u','e',0};
2170 if (xmlstr_cmp(&attr_name
, allowDelayedBindingW
))
2171 delayed
= xmlstr_cmp(&attr_value
, trueW
);
2174 elem1U
= xmlstr2unicode(&attr_name
);
2175 elem2U
= xmlstr2unicode(&attr_value
);
2176 DPRINT1("unknown attr %s=%s\n", &elem1U
, &elem2U
);
2180 if (error
|| end
) return end
;
2182 memset(&ai
, 0, sizeof(ai
));
2183 ai
.optional
= optional
;
2184 ai
.delayed
= delayed
;
2186 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
2187 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
2190 //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2192 /* store the newly found identity for later loading */
2193 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
2195 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2197 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
2199 ret
= parse_end_element(xmlbuf
);
2202 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
2204 ret
= parse_binding_redirect_elem(xmlbuf
);
2208 DPRINT1("unknown elem %S\n", elem
.ptr
);
2209 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2216 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
2218 xmlstr_t attr_name
, attr_value
, elem
;
2219 UNICODE_STRING attr_nameU
, attr_valueU
;
2220 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
2222 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2224 attr_nameU
= xmlstr2unicode(&attr_name
);
2225 attr_valueU
= xmlstr2unicode(&attr_value
);
2227 if (xmlstr_cmp(&attr_name
, optionalW
))
2229 optional
= xmlstr_cmpi( &attr_value
, yesW
);
2230 DPRINT1("optional=%wZ\n", &attr_valueU
);
2234 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2238 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2240 if (xmlstr_cmp_end(&elem
, dependencyW
))
2242 ret
= parse_end_element(xmlbuf
);
2245 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
2247 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
2251 attr_nameU
= xmlstr2unicode(&elem
);
2252 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2253 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2260 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
2264 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2265 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
2268 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
2272 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
2273 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
2276 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
2278 xmlstr_t attr_name
, attr_value
, elem
;
2279 UNICODE_STRING attr_nameU
, attr_valueU
;
2280 BOOL end
= FALSE
, error
, ret
= TRUE
;
2281 struct dll_redirect
* dll
;
2283 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
2285 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2287 attr_nameU
= xmlstr2unicode(&attr_name
);
2288 attr_valueU
= xmlstr2unicode(&attr_value
);
2290 if (xmlstr_cmp(&attr_name
, g_nameW
))
2292 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
2293 DPRINT("name=%wZ\n", &attr_valueU
);
2295 else if (xmlstr_cmp(&attr_name
, hashW
))
2297 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
2299 else if (xmlstr_cmp(&attr_name
, hashalgW
))
2301 static const WCHAR sha1W
[] = {'S','H','A','1',0};
2302 if (!xmlstr_cmpi(&attr_value
, sha1W
))
2303 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU
);
2307 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2311 if (error
|| !dll
->name
) return FALSE
;
2313 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
2315 if (end
) return TRUE
;
2317 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2319 if (xmlstr_cmp_end(&elem
, fileW
))
2321 ret
= parse_end_element(xmlbuf
);
2324 else if (xmlstr_cmp(&elem
, comClassW
))
2326 ret
= parse_com_class_elem(xmlbuf
, dll
, acl
);
2328 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
2330 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
, acl
);
2332 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
2334 DPRINT1("asmv2hash (undocumented) not supported\n");
2335 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2337 else if (xmlstr_cmp(&elem
, typelibW
))
2339 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
2341 else if (xmlstr_cmp(&elem
, windowClassW
))
2343 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
2347 attr_nameU
= xmlstr2unicode(&elem
);
2348 DPRINT1("unknown elem %wZ\n", &attr_nameU
);
2349 ret
= parse_unknown_elem( xmlbuf
, &elem
);
2356 static BOOL
parse_compatibility_application_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2357 struct actctx_loader
* acl
)
2359 xmlstr_t attr_name
, attr_value
, elem
;
2360 BOOL end
= FALSE
, ret
= TRUE
, error
;
2362 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2364 if (xmlstr_cmp_end(&elem
, applicationW
))
2366 ret
= parse_end_element(xmlbuf
);
2369 else if (xmlstr_cmp(&elem
, supportedOSW
))
2371 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2373 if (xmlstr_cmp(&attr_name
, IdW
))
2376 COMPATIBILITY_CONTEXT_ELEMENT
* compat
;
2378 str
.Buffer
= (PWSTR
)attr_value
.ptr
;
2379 str
.Length
= str
.MaximumLength
= (USHORT
)attr_value
.len
* sizeof(WCHAR
);
2380 if (RtlGUIDFromString(&str
, &compat_id
) == STATUS_SUCCESS
)
2382 if (!(compat
= add_compat_context(assembly
))) return FALSE
;
2383 compat
->Type
= ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS
;
2384 compat
->Id
= compat_id
;
2388 UNICODE_STRING attr_valueU
= xmlstr2unicode(&attr_value
);
2389 DPRINT1("Invalid guid %wZ\n", &attr_valueU
);
2394 UNICODE_STRING attr_nameU
= xmlstr2unicode(&attr_name
);
2395 UNICODE_STRING attr_valueU
= xmlstr2unicode(&attr_value
);
2396 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2402 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2403 DPRINT1("unknown elem %wZ\n", &elemU
);
2404 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2411 static BOOL
parse_compatibility_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
,
2412 struct actctx_loader
* acl
)
2417 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2419 if (xmlstr_cmp_end(&elem
, compatibilityW
))
2421 ret
= parse_end_element(xmlbuf
);
2424 else if (xmlstr_cmp(&elem
, applicationW
))
2426 ret
= parse_compatibility_application_elem(xmlbuf
, assembly
, acl
);
2430 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2431 DPRINT1("unknown elem %wZ\n", &elemU
);
2432 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2438 static BOOL
parse_requested_execution_level_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2440 static const WCHAR levelW
[] = {'l','e','v','e','l',0};
2441 static const WCHAR asInvokerW
[] = {'a','s','I','n','v','o','k','e','r',0};
2442 static const WCHAR requireAdministratorW
[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2443 static const WCHAR highestAvailableW
[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2444 static const WCHAR uiAccessW
[] = {'u','i','A','c','c','e','s','s',0};
2445 static const WCHAR falseW
[] = {'f','a','l','s','e',0};
2446 static const WCHAR trueW
[] = {'t','r','u','e',0};
2448 xmlstr_t attr_name
, attr_value
, elem
;
2449 BOOL end
= FALSE
, ret
= TRUE
, error
;
2451 /* Multiple requestedExecutionLevel elements are not supported. */
2452 if (assembly
->run_level
!= ACTCTX_RUN_LEVEL_UNSPECIFIED
)
2455 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2457 UNICODE_STRING attr_nameU
= xmlstr2unicode(&attr_name
);
2458 UNICODE_STRING attr_valueU
= xmlstr2unicode(&attr_value
);
2459 if (xmlstr_cmp(&attr_name
, levelW
))
2461 if (xmlstr_cmpi(&attr_value
, asInvokerW
))
2462 assembly
->run_level
= ACTCTX_RUN_LEVEL_AS_INVOKER
;
2463 else if (xmlstr_cmpi(&attr_value
, highestAvailableW
))
2464 assembly
->run_level
= ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE
;
2465 else if (xmlstr_cmpi(&attr_value
, requireAdministratorW
))
2466 assembly
->run_level
= ACTCTX_RUN_LEVEL_REQUIRE_ADMIN
;
2468 DPRINT1("unknown execution level: %wZ\n", &attr_valueU
);
2470 else if (xmlstr_cmp(&attr_name
, uiAccessW
))
2472 if (xmlstr_cmpi(&attr_value
, falseW
))
2473 assembly
->ui_access
= FALSE
;
2474 else if (xmlstr_cmpi(&attr_value
, trueW
))
2475 assembly
->ui_access
= TRUE
;
2477 DPRINT1("unknown uiAccess value: %wZ\n", &attr_valueU
);
2480 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2483 if (error
) return FALSE
;
2484 if (end
) return TRUE
;
2486 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2488 if (xmlstr_cmp_end(&elem
, requestedExecutionLevelW
))
2490 ret
= parse_end_element(xmlbuf
);
2495 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2496 DPRINT1("unknown element %wZ\n", &elemU
);
2497 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2504 static BOOL
parse_requested_privileges_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
*acl
)
2509 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2511 if (xmlstr_cmp_end(&elem
, requestedPrivilegesW
))
2513 ret
= parse_end_element(xmlbuf
);
2516 else if (xmlstr_cmp(&elem
, requestedExecutionLevelW
))
2517 ret
= parse_requested_execution_level_elem(xmlbuf
, assembly
, acl
);
2520 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2521 DPRINT1("unknown elem %wZ\n", &elemU
);
2522 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2529 static BOOL
parse_security_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2534 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2536 if (xmlstr_cmp_end(&elem
, securityW
))
2538 ret
= parse_end_element(xmlbuf
);
2541 else if (xmlstr_cmp(&elem
, requestedPrivilegesW
))
2542 ret
= parse_requested_privileges_elem(xmlbuf
, assembly
, acl
);
2545 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2546 DPRINT1("unknown elem %wZ\n", &elemU
);
2547 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2554 static BOOL
parse_trust_info_elem(xmlbuf_t
*xmlbuf
, struct assembly
*assembly
, struct actctx_loader
*acl
)
2559 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
2561 if (xmlstr_cmp_end(&elem
, trustInfoW
))
2563 ret
= parse_end_element(xmlbuf
);
2566 else if (xmlstr_cmp(&elem
, securityW
))
2567 ret
= parse_security_elem(xmlbuf
, assembly
, acl
);
2570 UNICODE_STRING elemU
= xmlstr2unicode(&elem
);
2571 DPRINT1("unknown elem %wZ\n", &elemU
);
2572 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2579 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
2580 struct assembly
* assembly
,
2581 struct assembly_identity
* expected_ai
)
2583 xmlstr_t attr_name
, attr_value
, elem
;
2584 UNICODE_STRING attr_nameU
, attr_valueU
;
2585 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
2587 DPRINT("(%p)\n", xmlbuf
);
2589 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
2591 attr_nameU
= xmlstr2unicode(&attr_name
);
2592 attr_valueU
= xmlstr2unicode(&attr_value
);
2594 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
2596 static const WCHAR v10W
[] = {'1','.','0',0};
2597 if (!xmlstr_cmp(&attr_value
, v10W
))
2599 DPRINT1("wrong version %wZ\n", &attr_valueU
);
2604 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
2606 if (!xmlstr_cmp(&attr_value
, manifestv1W
) &&
2607 !xmlstr_cmp(&attr_value
, manifestv2W
) &&
2608 !xmlstr_cmp(&attr_value
, manifestv3W
))
2610 DPRINT1("wrong namespace %wZ\n", &attr_valueU
);
2617 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU
, &attr_valueU
);
2621 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
2622 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
2624 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
2626 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2628 assembly
->no_inherit
= TRUE
;
2631 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
2633 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
2636 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
2637 assembly
->no_inherit
)
2642 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
2644 ret
= parse_end_element(xmlbuf
);
2647 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
2649 ret
= parse_description_elem(xmlbuf
);
2651 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
2653 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
, acl
);
2655 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
2657 ret
= parse_dependency_elem(xmlbuf
, acl
);
2659 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
2661 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
2663 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
2665 ret
= parse_clr_class_elem(xmlbuf
, assembly
, acl
);
2667 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
2669 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
, acl
);
2671 else if (xml_elem_cmp(&elem
, trustInfoW
, asmv2W
) ||
2672 xml_elem_cmp(&elem
, trustInfoW
, asmv1W
))
2674 ret
= parse_trust_info_elem(xmlbuf
, assembly
, acl
);
2676 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
2678 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
2682 /* FIXME: more tests */
2683 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
2684 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
2686 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2687 expected_ai
->version
.major
, expected_ai
->version
.minor
,
2688 expected_ai
->version
.build
, expected_ai
->version
.revision
,
2689 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
2690 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
2693 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
2694 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
2695 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
2696 assembly
->id
.version
.build
< expected_ai
->version
.build
||
2697 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
2698 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
2700 DPRINT1("wrong version for shared assembly manifest\n");
2705 else if (xml_elem_cmp(&elem
, compatibilityW
, compatibilityNSW
))
2707 ret
= parse_compatibility_elem(xmlbuf
, assembly
, acl
);
2711 attr_nameU
= xmlstr2unicode(&elem
);
2712 DPRINT1("unknown element %wZ\n", &attr_nameU
);
2713 ret
= parse_unknown_elem(xmlbuf
, &elem
);
2715 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
2721 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
2722 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
2725 UNICODE_STRING elemU
;
2727 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
2729 if (xmlstr_cmp(&elem
, g_xmlW
) &&
2730 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
2731 return STATUS_SXS_CANT_GEN_ACTCTX
;
2733 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
2735 elemU
= xmlstr2unicode(&elem
);
2736 DPRINT1("root element is %wZ, not <assembly>\n", &elemU
);
2737 return STATUS_SXS_CANT_GEN_ACTCTX
;
2740 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
2742 DPRINT1("failed to parse manifest %S\n", assembly
->manifest
.info
);
2743 return STATUS_SXS_CANT_GEN_ACTCTX
;
2746 if (next_xml_elem(xmlbuf
, &elem
))
2748 elemU
= xmlstr2unicode(&elem
);
2749 DPRINT1("unexpected element %wZ\n", &elemU
);
2750 return STATUS_SXS_CANT_GEN_ACTCTX
;
2753 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2755 DPRINT1("parse error\n");
2756 return STATUS_SXS_CANT_GEN_ACTCTX
;
2758 return STATUS_SUCCESS
;
2761 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2762 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2763 const void *buffer
, SIZE_T size
)
2767 struct assembly
*assembly
;
2770 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename
, directory
);
2772 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2773 return STATUS_SXS_CANT_GEN_ACTCTX
;
2775 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2776 return STATUS_NO_MEMORY
;
2778 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2779 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2780 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2782 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2783 if (RtlIsTextUnicode(buffer
, size
, &unicode_tests
))
2785 xmlbuf
.ptr
= buffer
;
2786 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2787 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2789 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2791 const WCHAR
*buf
= buffer
;
2795 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
2796 return STATUS_NO_MEMORY
;
2797 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2798 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2799 xmlbuf
.ptr
= new_buff
;
2800 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2801 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2802 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
2806 /* TODO: this doesn't handle arbitrary encodings */
2810 status
= RtlMultiByteToUnicodeSize(&sizeU
, buffer
, size
);
2811 if (!NT_SUCCESS(status
))
2813 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status
);
2814 return STATUS_SXS_CANT_GEN_ACTCTX
;
2817 new_buff
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU
);
2819 return STATUS_NO_MEMORY
;
2821 status
= RtlMultiByteToUnicodeN(new_buff
, sizeU
, &sizeU
, buffer
, size
);
2822 if (!NT_SUCCESS(status
))
2824 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status
);
2825 return STATUS_SXS_CANT_GEN_ACTCTX
;
2828 xmlbuf
.ptr
= new_buff
;
2829 xmlbuf
.end
= xmlbuf
.ptr
+ sizeU
/ sizeof(WCHAR
);
2830 status
= parse_manifest_buffer(acl
, assembly
, ai
, &xmlbuf
);
2831 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff
);
2836 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2838 OBJECT_ATTRIBUTES attr
;
2841 attr
.Length
= sizeof(attr
);
2842 attr
.RootDirectory
= 0;
2843 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2844 attr
.ObjectName
= name
;
2845 attr
.SecurityDescriptor
= NULL
;
2846 attr
.SecurityQualityOfService
= NULL
;
2847 return NtOpenFile( handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2850 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, USHORT extra_len
)
2854 LDR_DATA_TABLE_ENTRY
*pldr
;
2856 LdrLockLoaderLock(0, NULL
, &magic
);
2857 status
= LdrFindEntryForAddress( module
, &pldr
);
2858 if (status
== STATUS_SUCCESS
)
2860 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
2861 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2863 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2864 str
->Length
= pldr
->FullDllName
.Length
;
2865 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2867 else status
= STATUS_NO_MEMORY
;
2869 LdrUnlockLoaderLock(0, magic
);
2873 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2874 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2875 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2878 UNICODE_STRING nameW
;
2879 LDR_RESOURCE_INFO info
;
2880 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2883 //DPRINT( "looking for res %s in module %p %s\n", resname,
2884 // hModule, filename );
2885 DPRINT("get_manifest_in_module %p\n", hModule
);
2888 if (TRACE_ON(actctx
))
2890 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2892 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2893 hModule
, debugstr_w(nameW
.Buffer
) );
2894 RtlFreeUnicodeString( &nameW
);
2896 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2897 hModule
, debugstr_w(filename
) );
2901 if (!resname
) return STATUS_INVALID_PARAMETER
;
2903 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
2904 info
.Language
= lang
;
2905 if (!((ULONG_PTR
)resname
>> 16))
2907 info
.Name
= (ULONG_PTR
)resname
;
2908 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2910 else if (resname
[0] == '#')
2913 RtlInitUnicodeString(&nameW
, resname
+ 1);
2914 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2915 return STATUS_INVALID_PARAMETER
;
2917 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2921 RtlCreateUnicodeString(&nameW
, resname
);
2922 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2923 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2924 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2925 RtlFreeUnicodeString(&nameW
);
2927 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2929 if (status
== STATUS_SUCCESS
)
2930 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2935 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2936 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2937 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2940 OBJECT_ATTRIBUTES attr
;
2942 LARGE_INTEGER offset
;
2947 DPRINT( "looking for res %S in %S\n", resname
, filename
);
2949 attr
.Length
= sizeof(attr
);
2950 attr
.RootDirectory
= 0;
2951 attr
.ObjectName
= NULL
;
2952 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2953 attr
.SecurityDescriptor
= NULL
;
2954 attr
.SecurityQualityOfService
= NULL
;
2957 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2958 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2959 if (status
!= STATUS_SUCCESS
) return status
;
2961 offset
.QuadPart
= 0;
2964 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
2965 &count
, ViewShare
, 0, PAGE_READONLY
);
2967 if (status
!= STATUS_SUCCESS
) return status
;
2969 if (RtlImageNtHeader(base
)) /* we got a PE file */
2971 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2972 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2974 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2976 NtUnmapViewOfSection( NtCurrentProcess(), base
);
2980 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2981 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2983 FILE_STANDARD_INFORMATION info
;
2986 OBJECT_ATTRIBUTES attr
;
2988 LARGE_INTEGER offset
;
2993 DPRINT( "loading manifest file %S\n", filename
);
2995 attr
.Length
= sizeof(attr
);
2996 attr
.RootDirectory
= 0;
2997 attr
.ObjectName
= NULL
;
2998 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2999 attr
.SecurityDescriptor
= NULL
;
3000 attr
.SecurityQualityOfService
= NULL
;
3003 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
3004 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
3006 if (status
!= STATUS_SUCCESS
) return status
;
3008 offset
.QuadPart
= 0;
3011 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
3012 &count
, ViewShare
, 0, PAGE_READONLY
);
3014 if (status
!= STATUS_SUCCESS
) return status
;
3016 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
3017 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
3019 if (status
== STATUS_SUCCESS
)
3020 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, (SIZE_T
)info
.EndOfFile
.QuadPart
);
3022 NtUnmapViewOfSection( NtCurrentProcess(), base
);
3026 /* try to load the .manifest file associated to the file */
3027 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
3028 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
3030 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
3033 UNICODE_STRING nameW
;
3035 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3037 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
3039 DPRINT( "looking for manifest associated with %S id %lu\n", filename
, resid
);
3041 if (module
) /* use the module filename */
3043 UNICODE_STRING name
;
3045 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
3047 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
3048 strcatW( name
.Buffer
, dotManifestW
);
3049 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
3050 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
3051 RtlFreeUnicodeString( &name
);
3053 if (status
) return status
;
3057 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
3058 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3059 return STATUS_NO_MEMORY
;
3060 strcpyW( buffer
, filename
);
3061 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
3062 strcatW( buffer
, dotManifestW
);
3063 RtlInitUnicodeString( &nameW
, buffer
);
3066 if (!open_nt_file( &file
, &nameW
))
3068 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3071 else status
= STATUS_RESOURCE_TYPE_NOT_FOUND
;
3072 RtlFreeUnicodeString( &nameW
);
3076 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
3078 static const WCHAR lookup_fmtW
[] =
3079 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3080 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3081 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3083 WCHAR
*lookup
, *ret
= NULL
;
3084 UNICODE_STRING lookup_us
;
3086 const WCHAR
*lang
= ai
->language
;
3087 unsigned int data_pos
= 0, data_len
;
3090 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
3091 (strlenW(ai
->arch
) + strlenW(ai
->name
)
3092 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
3093 + sizeof(lookup_fmtW
) )))
3096 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
3097 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
3098 ai
->version
.major
, ai
->version
.minor
, lang
);
3099 RtlInitUnicodeString( &lookup_us
, lookup
);
3101 if (!NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3102 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
))
3104 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
3105 FILE_BOTH_DIR_INFORMATION
*dir_info
;
3107 ULONG build
, revision
;
3109 data_len
= (ULONG
)io
.Information
;
3113 if (data_pos
>= data_len
)
3115 if (NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
3116 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
))
3118 data_len
= (ULONG
)io
.Information
;
3121 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
3123 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
3124 else data_pos
= data_len
;
3126 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
3128 if (build
< min_build
) continue;
3129 tmp
= strchrW(tmp
, '.') + 1;
3130 revision
= atoiW(tmp
);
3131 if (build
== min_build
&& revision
< min_revision
) continue;
3132 tmp
= strchrW(tmp
, '_') + 1;
3133 tmp
= strchrW(tmp
, '_') + 1;
3134 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
3135 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
3137 /* prefer a non-Wine manifest if we already have one */
3138 /* we'll still load the builtin dll if specified through DllOverrides */
3144 min_revision
= revision
;
3146 ai
->version
.build
= build
;
3147 ai
->version
.revision
= revision
;
3148 RtlFreeHeap( RtlGetProcessHeap(), 0, ret
);
3149 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
3151 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
3152 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
3156 else DPRINT1("no matching file for %S\n", lookup
);
3157 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
3161 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
3163 struct assembly_identity sxs_ai
;
3164 UNICODE_STRING path_us
;
3165 OBJECT_ATTRIBUTES attr
;
3167 WCHAR
*path
, *file
= NULL
;
3170 static const WCHAR manifest_dirW
[] =
3171 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3173 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
3175 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
3176 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
3177 return STATUS_NO_MEMORY
;
3179 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
3180 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
3182 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
3184 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
3185 return STATUS_NO_SUCH_FILE
;
3187 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
3189 attr
.Length
= sizeof(attr
);
3190 attr
.RootDirectory
= 0;
3191 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
3192 attr
.ObjectName
= &path_us
;
3193 attr
.SecurityDescriptor
= NULL
;
3194 attr
.SecurityQualityOfService
= NULL
;
3196 if (!NtOpenFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
3197 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
3200 file
= lookup_manifest_file( handle
, &sxs_ai
);
3205 RtlFreeUnicodeString( &path_us
);
3206 return STATUS_NO_SUCH_FILE
;
3209 /* append file name to directory path */
3210 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
3211 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
3213 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
3214 RtlFreeUnicodeString( &path_us
);
3215 return STATUS_NO_MEMORY
;
3218 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
3219 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
3220 RtlInitUnicodeString( &path_us
, path
);
3221 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
3223 if (!open_nt_file( &handle
, &path_us
))
3225 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
3228 else io
.Status
= STATUS_NO_SUCH_FILE
;
3230 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
3231 RtlFreeUnicodeString( &path_us
);
3235 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
3236 struct assembly_identity
* ai
)
3238 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
3240 WCHAR
*buffer
, *p
, *directory
;
3242 UNICODE_STRING nameW
;
3246 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
3247 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
3249 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
3251 /* FIXME: add support for language specific lookup */
3253 len
= max(RtlGetFullPathName_U(acl
->actctx
->assemblies
->manifest
.info
, 0, NULL
, NULL
) / sizeof(WCHAR
),
3254 strlenW(acl
->actctx
->appdir
.info
));
3256 nameW
.Buffer
= NULL
;
3257 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
3258 (len
+ 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
3259 return STATUS_NO_MEMORY
;
3261 if (!(directory
= build_assembly_dir( ai
)))
3263 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3264 return STATUS_NO_MEMORY
;
3267 /* Lookup in <dir>\name.dll
3268 * <dir>\name.manifest
3269 * <dir>\name\name.dll
3270 * <dir>\name\name.manifest
3272 * First 'appdir' is used as <dir>, if that failed
3273 * it tries application manifest file path.
3275 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
3276 p
= buffer
+ strlenW(buffer
);
3277 for (i
= 0; i
< 4; i
++)
3281 struct assembly
*assembly
= acl
->actctx
->assemblies
;
3282 if (!RtlGetFullPathName_U(assembly
->manifest
.info
, len
* sizeof(WCHAR
), buffer
, &p
)) break;
3286 strcpyW( p
, ai
->name
);
3289 strcpyW( p
, dotDllW
);
3290 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3292 status
= open_nt_file( &file
, &nameW
);
3295 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
3296 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
3300 RtlFreeUnicodeString( &nameW
);
3303 strcpyW( p
, dotManifestW
);
3304 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
3306 status
= open_nt_file( &file
, &nameW
);
3309 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
3313 RtlFreeUnicodeString( &nameW
);
3315 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
3317 RtlFreeUnicodeString( &nameW
);
3318 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
3319 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
3323 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
3325 NTSTATUS status
= STATUS_SUCCESS
;
3328 for (i
= 0; i
< acl
->num_dependencies
; i
++)
3330 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
3332 if (!acl
->dependencies
[i
].optional
&& !acl
->dependencies
[i
].delayed
)
3334 const struct assembly_version
*ver
= &acl
->dependencies
[i
].version
;
3335 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
3336 acl
->dependencies
[i
].name
,
3337 ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
3338 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
3343 /* FIXME should now iterate through all refs */
3347 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3348 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
3350 NTSTATUS status
= STATUS_SUCCESS
;
3352 if (flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
)
3354 if (*handle
) return STATUS_INVALID_PARAMETER
;
3356 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
3357 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
3359 else if (flags
& (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
| RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
))
3362 LDR_DATA_TABLE_ENTRY
*pldr
;
3364 if (!*handle
) return STATUS_INVALID_PARAMETER
;
3366 LdrLockLoaderLock( 0, NULL
, &magic
);
3367 if (!LdrFindEntryForAddress( *handle
, &pldr
))
3369 if ((flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
3370 status
= STATUS_DLL_NOT_FOUND
;
3372 *handle
= pldr
->EntryPointActivationContext
;
3374 else status
= STATUS_DLL_NOT_FOUND
;
3375 LdrUnlockLoaderLock( 0, magic
);
3377 else if (!*handle
&& (class != ActivationContextBasicInformation
))
3378 *handle
= process_actctx
;
3383 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3385 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
3386 struct strsection_header
*header
;
3387 struct dllredirect_data
*data
;
3388 struct string_index
*index
;
3391 DPRINT("actctx %p, num_assemblies %d\n", actctx
, actctx
->num_assemblies
);
3393 /* compute section length */
3394 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3396 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3397 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3399 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3401 /* each entry needs index, data and string data */
3402 total_len
+= sizeof(*index
);
3403 total_len
+= sizeof(*data
);
3404 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
3406 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i
, assembly
, j
, dll
->name
);
3409 dll_count
+= assembly
->num_dlls
;
3412 total_len
+= sizeof(*header
);
3414 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3415 if (!header
) return STATUS_NO_MEMORY
;
3417 memset(header
, 0, sizeof(*header
));
3418 header
->magic
= STRSECTION_MAGIC
;
3419 header
->size
= sizeof(*header
);
3420 header
->count
= dll_count
;
3421 header
->index_offset
= sizeof(*header
);
3422 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3423 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3425 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3427 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3429 DPRINT("assembly->num_dlls %d\n", assembly
->num_dlls
);
3431 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3433 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3437 DPRINT("%d: dll name %S\n", j
, dll
->name
);
3438 /* setup new index entry */
3439 str
.Buffer
= dll
->name
;
3440 str
.Length
= (USHORT
)strlenW(dll
->name
)*sizeof(WCHAR
);
3441 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3442 /* hash original class name */
3443 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3445 index
->name_offset
= name_offset
;
3446 index
->name_len
= str
.Length
;
3447 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3448 index
->data_len
= sizeof(*data
);
3449 index
->rosterindex
= i
+ 1;
3452 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3453 data
->size
= sizeof(*data
);
3454 data
->unk
= 2; /* FIXME: seems to be constant */
3455 memset(data
->res
, 0, sizeof(data
->res
));
3458 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3459 memcpy(ptrW
, dll
->name
, index
->name_len
);
3460 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3462 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
3470 return STATUS_SUCCESS
;
3473 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
3475 struct string_index
*iter
, *index
= NULL
;
3478 DPRINT("section %p, name %wZ\n", section
, name
);
3479 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3480 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
3482 for (i
= 0; i
< section
->count
; i
++)
3484 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter
->hash
, hash
);
3485 DPRINT("iter->name %S\n", (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
));
3486 if (iter
->hash
== hash
)
3488 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
3490 if (!_wcsnicmp(nameW
, name
->Buffer
, name
->Length
/ sizeof(WCHAR
)) &&
3491 wcslen(nameW
) == name
->Length
/ sizeof(WCHAR
))
3497 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3505 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
3507 struct guid_index
*iter
, *index
= NULL
;
3510 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
3512 for (i
= 0; i
< section
->count
; i
++)
3514 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
3525 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3527 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
3530 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3531 PACTCTX_SECTION_KEYED_DATA data
)
3533 struct dllredirect_data
*dll
;
3534 struct string_index
*index
;
3536 DPRINT("sections: 0x%08X\n", actctx
->sections
);
3537 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3539 DPRINT("actctx->dllredirect_section: %p\n", actctx
->dllredirect_section
);
3540 if (!actctx
->dllredirect_section
)
3542 struct strsection_header
*section
;
3544 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
3545 if (status
) return status
;
3547 if (InterlockedCompareExchangePointer((void**)&actctx
->dllredirect_section
, section
, NULL
))
3548 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3551 index
= find_string_index(actctx
->dllredirect_section
, name
);
3552 DPRINT("index: %d\n", index
);
3553 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3557 dll
= get_dllredirect_data(actctx
, index
);
3559 data
->ulDataFormatVersion
= 1;
3561 data
->ulLength
= dll
->size
;
3562 data
->lpSectionGlobalData
= NULL
;
3563 data
->ulSectionGlobalDataLength
= 0;
3564 data
->lpSectionBase
= actctx
->dllredirect_section
;
3565 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->dllredirect_section
);
3566 data
->hActCtx
= NULL
;
3568 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3569 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3572 return STATUS_SUCCESS
;
3575 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
3577 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
3580 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
3582 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
3585 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
3587 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
3588 struct wndclass_redirect_data
*data
;
3589 struct strsection_header
*header
;
3590 struct string_index
*index
;
3593 /* compute section length */
3594 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3596 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3597 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3599 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3600 for (k
= 0; k
< dll
->entities
.num
; k
++)
3602 struct entity
*entity
= &dll
->entities
.base
[k
];
3603 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3605 int class_len
= strlenW(entity
->u
.class.name
) + 1;
3608 /* each class entry needs index, data and string data */
3609 total_len
+= sizeof(*index
);
3610 total_len
+= sizeof(*data
);
3611 /* original name is stored separately */
3612 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
3613 /* versioned name and module name are stored one after another */
3614 if (entity
->u
.class.versioned
)
3615 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
3618 len
+= strlenW(dll
->name
) + 1;
3619 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
3627 total_len
+= sizeof(*header
);
3629 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3630 if (!header
) return STATUS_NO_MEMORY
;
3632 memset(header
, 0, sizeof(*header
));
3633 header
->magic
= STRSECTION_MAGIC
;
3634 header
->size
= sizeof(*header
);
3635 header
->count
= class_count
;
3636 header
->index_offset
= sizeof(*header
);
3637 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
3638 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
3640 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3642 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3643 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3645 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3646 for (k
= 0; k
< dll
->entities
.num
; k
++)
3648 struct entity
*entity
= &dll
->entities
.base
[k
];
3649 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
3651 static const WCHAR exclW
[] = {'!',0};
3652 ULONG versioned_len
, module_len
;
3656 /* setup new index entry */
3657 str
.Buffer
= entity
->u
.class.name
;
3658 str
.Length
= (USHORT
)strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
3659 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
3660 /* hash original class name */
3661 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
3663 /* include '!' separator too */
3664 if (entity
->u
.class.versioned
)
3665 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
3667 versioned_len
= str
.Length
;
3668 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3670 index
->name_offset
= name_offset
;
3671 index
->name_len
= str
.Length
;
3672 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
3673 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
3674 index
->rosterindex
= i
+ 1;
3677 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3678 data
->size
= sizeof(*data
);
3680 data
->name_len
= versioned_len
;
3681 data
->name_offset
= sizeof(*data
);
3682 data
->module_len
= module_len
;
3683 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
3685 /* original class name */
3686 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
3687 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3688 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3691 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
3692 memcpy(ptrW
, dll
->name
, data
->module_len
);
3693 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
3695 /* versioned name */
3696 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
3697 if (entity
->u
.class.versioned
)
3699 get_assembly_version(assembly
, ptrW
);
3700 strcatW(ptrW
, exclW
);
3701 strcatW(ptrW
, entity
->u
.class.name
);
3705 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
3706 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
3709 name_offset
+= sizeof(*data
);
3710 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
3720 return STATUS_SUCCESS
;
3723 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
3724 PACTCTX_SECTION_KEYED_DATA data
)
3726 struct string_index
*iter
, *index
= NULL
;
3727 struct wndclass_redirect_data
*class;
3731 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3733 if (!actctx
->wndclass_section
)
3735 struct strsection_header
*section
;
3737 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
3738 if (status
) return status
;
3740 if (InterlockedCompareExchangePointer((void**)&actctx
->wndclass_section
, section
, NULL
))
3741 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3745 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
3746 iter
= get_wndclass_first_index(actctx
);
3748 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
3750 if (iter
->hash
== hash
)
3752 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
3754 if (!strcmpiW(nameW
, name
->Buffer
))
3760 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash
, name
, nameW
);
3765 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3769 class = get_wndclass_data(actctx
, index
);
3771 data
->ulDataFormatVersion
= 1;
3772 data
->lpData
= class;
3773 /* full length includes string length with nulls */
3774 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
3775 data
->lpSectionGlobalData
= NULL
;
3776 data
->ulSectionGlobalDataLength
= 0;
3777 data
->lpSectionBase
= actctx
->wndclass_section
;
3778 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->wndclass_section
);
3779 data
->hActCtx
= NULL
;
3781 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3782 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3785 return STATUS_SUCCESS
;
3788 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
3790 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
3791 struct guidsection_header
*header
;
3792 ULONG module_offset
, data_offset
;
3793 struct tlibredirect_data
*data
;
3794 struct guid_index
*index
;
3796 /* compute section length */
3797 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3799 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3800 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3802 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3803 for (k
= 0; k
< dll
->entities
.num
; k
++)
3805 struct entity
*entity
= &dll
->entities
.base
[k
];
3806 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3808 /* each entry needs index, data and string data for module name and help string */
3809 total_len
+= sizeof(*index
);
3810 total_len
+= sizeof(*data
);
3811 /* help string is stored separately */
3812 if (*entity
->u
.typelib
.helpdir
)
3813 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3815 /* module names are packed one after another */
3816 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3824 total_len
+= aligned_string_len(names_len
);
3825 total_len
+= sizeof(*header
);
3827 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
3828 if (!header
) return STATUS_NO_MEMORY
;
3830 memset(header
, 0, sizeof(*header
));
3831 header
->magic
= GUIDSECTION_MAGIC
;
3832 header
->size
= sizeof(*header
);
3833 header
->count
= tlib_count
;
3834 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3835 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3836 module_offset
= sizeof(*header
);
3837 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3839 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3841 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3842 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3844 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3845 for (k
= 0; k
< dll
->entities
.num
; k
++)
3847 struct entity
*entity
= &dll
->entities
.base
[k
];
3848 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3850 ULONG module_len
, help_len
;
3854 if (*entity
->u
.typelib
.helpdir
)
3855 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3859 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3861 /* setup new index entry */
3862 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3863 RtlGUIDFromString(&str
, &index
->guid
);
3864 index
->data_offset
= data_offset
;
3865 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3866 index
->rosterindex
= i
+ 1;
3869 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3870 data
->size
= sizeof(*data
);
3872 data
->name_len
= module_len
;
3873 data
->name_offset
= module_offset
;
3874 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3876 data
->flags
= entity
->u
.typelib
.flags
;
3877 data
->help_len
= help_len
;
3878 data
->help_offset
= sizeof(*data
);
3879 data
->major_version
= entity
->u
.typelib
.major
;
3880 data
->minor_version
= entity
->u
.typelib
.minor
;
3883 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3884 memcpy(ptrW
, dll
->name
, data
->name_len
);
3885 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3890 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3891 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3892 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3895 data_offset
+= sizeof(*data
);
3897 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3899 module_offset
+= module_len
+ sizeof(WCHAR
);
3909 return STATUS_SUCCESS
;
3912 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3914 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3917 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3919 struct guid_index
*index
= NULL
;
3920 struct tlibredirect_data
*tlib
;
3922 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3924 if (!actctx
->tlib_section
)
3926 struct guidsection_header
*section
;
3928 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3929 if (status
) return status
;
3931 if (InterlockedCompareExchangePointer((void**)&actctx
->tlib_section
, section
, NULL
))
3932 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
3935 index
= find_guid_index(actctx
->tlib_section
, guid
);
3936 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3938 tlib
= get_tlib_data(actctx
, index
);
3940 data
->ulDataFormatVersion
= 1;
3941 data
->lpData
= tlib
;
3942 /* full length includes string length with nulls */
3943 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3944 data
->lpSectionGlobalData
= (BYTE
*)actctx
->tlib_section
+ actctx
->tlib_section
->names_offset
;
3945 data
->ulSectionGlobalDataLength
= actctx
->tlib_section
->names_len
;
3946 data
->lpSectionBase
= actctx
->tlib_section
;
3947 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->tlib_section
);
3948 data
->hActCtx
= NULL
;
3950 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3951 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3953 return STATUS_SUCCESS
;
3956 static void generate_uuid(ULONG
*seed
, GUID
*guid
)
3958 ULONG
*ptr
= (ULONG
*)guid
;
3961 /* GUID is 16 bytes long */
3962 for (i
= 0; i
< sizeof(GUID
)/sizeof(ULONG
); i
++, ptr
++)
3963 *ptr
= RtlUniform(seed
);
3965 guid
->Data3
&= 0x0fff;
3966 guid
->Data3
|= (4 << 12);
3967 guid
->Data4
[0] &= 0x3f;
3968 guid
->Data4
[0] |= 0x80;
3971 static void get_comserver_datalen(const struct entity_array
*entities
, const struct dll_redirect
*dll
,
3972 unsigned int *count
, unsigned int *len
, unsigned int *module_len
)
3976 for (i
= 0; i
< entities
->num
; i
++)
3978 struct entity
*entity
= &entities
->base
[i
];
3979 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
3981 /* each entry needs two index entries, extra one goes for alias GUID */
3982 *len
+= 2*sizeof(struct guid_index
);
3983 /* To save some memory we don't allocated two data structures,
3984 instead alias index and normal index point to the same data structure. */
3985 *len
+= sizeof(struct comclassredirect_data
);
3987 /* for clrClass store some more */
3988 if (entity
->u
.comclass
.name
)
3990 unsigned int str_len
;
3992 /* all string data is stored together in aligned block */
3993 str_len
= strlenW(entity
->u
.comclass
.name
)+1;
3994 if (entity
->u
.comclass
.progid
)
3995 str_len
+= strlenW(entity
->u
.comclass
.progid
)+1;
3996 if (entity
->u
.comclass
.version
)
3997 str_len
+= strlenW(entity
->u
.comclass
.version
)+1;
3999 *len
+= sizeof(struct clrclass_data
);
4000 *len
+= aligned_string_len(str_len
*sizeof(WCHAR
));
4002 /* module name is forced to mscoree.dll, and stored two times with different case */
4003 *module_len
+= sizeof(mscoreeW
) + sizeof(mscoree2W
);
4007 /* progid string is stored separately */
4008 if (entity
->u
.comclass
.progid
)
4009 *len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4011 *module_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
4019 static void add_comserver_record(const struct guidsection_header
*section
, const struct entity_array
*entities
,
4020 const struct dll_redirect
*dll
, struct guid_index
**index
, ULONG
*data_offset
, ULONG
*module_offset
,
4021 ULONG
*seed
, ULONG rosterindex
)
4025 for (i
= 0; i
< entities
->num
; i
++)
4027 struct entity
*entity
= &entities
->base
[i
];
4028 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4030 ULONG module_len
, progid_len
, str_len
= 0;
4031 struct comclassredirect_data
*data
;
4032 struct guid_index
*alias_index
;
4033 struct clrclass_data
*clrdata
;
4037 if (entity
->u
.comclass
.progid
)
4038 progid_len
= strlenW(entity
->u
.comclass
.progid
)*sizeof(WCHAR
);
4042 module_len
= dll
? strlenW(dll
->name
)*sizeof(WCHAR
) : strlenW(mscoreeW
)*sizeof(WCHAR
);
4044 /* setup new index entry */
4045 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4046 RtlGUIDFromString(&str
, &(*index
)->guid
);
4048 (*index
)->data_offset
= *data_offset
;
4049 (*index
)->data_len
= sizeof(*data
); /* additional length added later */
4050 (*index
)->rosterindex
= rosterindex
;
4052 /* Setup new index entry for alias guid. Alias index records are placed after
4053 normal records, so normal guids are hit first on search. Note that class count
4055 alias_index
= (*index
) + section
->count
/2;
4056 generate_uuid(seed
, &alias_index
->guid
);
4057 alias_index
->data_offset
= (*index
)->data_offset
;
4058 alias_index
->data_len
= 0;
4059 alias_index
->rosterindex
= (*index
)->rosterindex
;
4062 data
= (struct comclassredirect_data
*)((BYTE
*)section
+ (*index
)->data_offset
);
4063 data
->size
= sizeof(*data
);
4067 data
->model
= entity
->u
.comclass
.model
;
4068 data
->clsid
= (*index
)->guid
;
4069 data
->alias
= alias_index
->guid
;
4070 data
->clsid2
= data
->clsid
;
4071 if (entity
->u
.comclass
.tlbid
)
4073 RtlInitUnicodeString(&str
, entity
->u
.comclass
.tlbid
);
4074 RtlGUIDFromString(&str
, &data
->tlbid
);
4077 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4078 data
->name_len
= module_len
;
4079 data
->name_offset
= *module_offset
;
4080 data
->progid_len
= progid_len
;
4081 data
->progid_offset
= data
->progid_len
? data
->size
: 0; /* in case of clrClass additional offset is added later */
4082 data
->clrdata_len
= 0; /* will be set later */
4083 data
->clrdata_offset
= entity
->u
.comclass
.name
? sizeof(*data
) : 0;
4084 data
->miscstatus
= entity
->u
.comclass
.miscstatus
;
4085 data
->miscstatuscontent
= entity
->u
.comclass
.miscstatuscontent
;
4086 data
->miscstatusthumbnail
= entity
->u
.comclass
.miscstatusthumbnail
;
4087 data
->miscstatusicon
= entity
->u
.comclass
.miscstatusicon
;
4088 data
->miscstatusdocprint
= entity
->u
.comclass
.miscstatusdocprint
;
4090 /* mask describes which misc* data is available */
4092 if (data
->miscstatus
)
4093 data
->miscmask
|= MiscStatus
;
4094 if (data
->miscstatuscontent
)
4095 data
->miscmask
|= MiscStatusContent
;
4096 if (data
->miscstatusthumbnail
)
4097 data
->miscmask
|= MiscStatusThumbnail
;
4098 if (data
->miscstatusicon
)
4099 data
->miscmask
|= MiscStatusIcon
;
4100 if (data
->miscstatusdocprint
)
4101 data
->miscmask
|= MiscStatusDocPrint
;
4103 if (data
->clrdata_offset
)
4105 clrdata
= (struct clrclass_data
*)((BYTE
*)data
+ data
->clrdata_offset
);
4107 clrdata
->size
= sizeof(*clrdata
);
4108 clrdata
->res
[0] = 0;
4109 clrdata
->res
[1] = 2; /* FIXME: unknown field */
4110 clrdata
->module_len
= strlenW(mscoreeW
)*sizeof(WCHAR
);
4111 clrdata
->module_offset
= *module_offset
+ data
->name_len
+ sizeof(WCHAR
);
4112 clrdata
->name_len
= strlenW(entity
->u
.comclass
.name
)*sizeof(WCHAR
);
4113 clrdata
->name_offset
= clrdata
->size
;
4114 clrdata
->version_len
= entity
->u
.comclass
.version
? strlenW(entity
->u
.comclass
.version
)*sizeof(WCHAR
) : 0;
4115 clrdata
->version_offset
= clrdata
->version_len
? clrdata
->name_offset
+ clrdata
->name_len
+ sizeof(WCHAR
) : 0;
4116 clrdata
->res2
[0] = 0;
4117 clrdata
->res2
[1] = 0;
4119 data
->clrdata_len
= clrdata
->size
+ clrdata
->name_len
+ sizeof(WCHAR
);
4122 ptrW
= (WCHAR
*)((BYTE
*)section
+ clrdata
->module_offset
);
4123 memcpy(ptrW
, mscoree2W
, clrdata
->module_len
);
4124 ptrW
[clrdata
->module_len
/sizeof(WCHAR
)] = 0;
4126 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4127 memcpy(ptrW
, mscoreeW
, data
->name_len
);
4128 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4131 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->name_offset
);
4132 memcpy(ptrW
, entity
->u
.comclass
.name
, clrdata
->name_len
);
4133 ptrW
[clrdata
->name_len
/sizeof(WCHAR
)] = 0;
4135 /* runtime version, optional */
4136 if (clrdata
->version_len
)
4138 data
->clrdata_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4140 ptrW
= (WCHAR
*)((BYTE
*)clrdata
+ clrdata
->version_offset
);
4141 memcpy(ptrW
, entity
->u
.comclass
.version
, clrdata
->version_len
);
4142 ptrW
[clrdata
->version_len
/sizeof(WCHAR
)] = 0;
4145 if (data
->progid_len
)
4146 data
->progid_offset
+= data
->clrdata_len
;
4147 (*index
)->data_len
+= sizeof(*clrdata
);
4154 ptrW
= (WCHAR
*)((BYTE
*)section
+ data
->name_offset
);
4155 memcpy(ptrW
, dll
->name
, data
->name_len
);
4156 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4160 if (data
->progid_len
)
4162 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->progid_offset
);
4163 memcpy(ptrW
, entity
->u
.comclass
.progid
, data
->progid_len
);
4164 ptrW
[data
->progid_len
/sizeof(WCHAR
)] = 0;
4167 /* string block length */
4171 str_len
+= clrdata
->name_len
+ sizeof(WCHAR
);
4172 if (clrdata
->version_len
)
4173 str_len
+= clrdata
->version_len
+ sizeof(WCHAR
);
4176 str_len
+= progid_len
+ sizeof(WCHAR
);
4178 (*index
)->data_len
+= aligned_string_len(str_len
);
4179 alias_index
->data_len
= (*index
)->data_len
;
4181 /* move to next data record */
4182 (*data_offset
) += sizeof(*data
) + aligned_string_len(str_len
);
4183 (*module_offset
) += module_len
+ sizeof(WCHAR
);
4187 (*data_offset
) += sizeof(*clrdata
);
4188 (*module_offset
) += clrdata
->module_len
+ sizeof(WCHAR
);
4195 static NTSTATUS
build_comserver_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4197 unsigned int i
, j
, total_len
= 0, class_count
= 0, names_len
= 0;
4198 struct guidsection_header
*header
;
4199 ULONG module_offset
, data_offset
;
4200 struct guid_index
*index
;
4203 /* compute section length */
4204 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4206 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4207 get_comserver_datalen(&assembly
->entities
, NULL
, &class_count
, &total_len
, &names_len
);
4208 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4210 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4211 get_comserver_datalen(&dll
->entities
, dll
, &class_count
, &total_len
, &names_len
);
4215 total_len
+= aligned_string_len(names_len
);
4216 total_len
+= sizeof(*header
);
4218 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4219 if (!header
) return STATUS_NO_MEMORY
;
4221 memset(header
, 0, sizeof(*header
));
4222 header
->magic
= GUIDSECTION_MAGIC
;
4223 header
->size
= sizeof(*header
);
4224 header
->count
= 2*class_count
;
4225 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
4226 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4227 module_offset
= sizeof(*header
);
4228 data_offset
= header
->index_offset
+ 2*class_count
*sizeof(*index
);
4230 seed
= NtGetTickCount();
4231 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4233 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4234 add_comserver_record(header
, &assembly
->entities
, NULL
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4235 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4237 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4238 add_comserver_record(header
, &dll
->entities
, dll
, &index
, &data_offset
, &module_offset
, &seed
, i
+1);
4244 return STATUS_SUCCESS
;
4247 static inline struct comclassredirect_data
*get_comclass_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4249 return (struct comclassredirect_data
*)((BYTE
*)actctx
->comserver_section
+ index
->data_offset
);
4252 static NTSTATUS
find_comserver_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4254 struct comclassredirect_data
*comclass
;
4255 struct guid_index
*index
= NULL
;
4257 if (!(actctx
->sections
& SERVERREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4259 if (!actctx
->comserver_section
)
4261 struct guidsection_header
*section
;
4263 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4264 if (status
) return status
;
4266 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4267 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4270 index
= find_guid_index(actctx
->comserver_section
, guid
);
4271 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4273 comclass
= get_comclass_data(actctx
, index
);
4275 data
->ulDataFormatVersion
= 1;
4276 data
->lpData
= comclass
;
4277 /* full length includes string length with nulls */
4278 data
->ulLength
= comclass
->size
+ comclass
->clrdata_len
;
4279 if (comclass
->progid_len
) data
->ulLength
+= comclass
->progid_len
+ sizeof(WCHAR
);
4280 data
->lpSectionGlobalData
= (BYTE
*)actctx
->comserver_section
+ actctx
->comserver_section
->names_offset
;
4281 data
->ulSectionGlobalDataLength
= actctx
->comserver_section
->names_len
;
4282 data
->lpSectionBase
= actctx
->comserver_section
;
4283 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->comserver_section
);
4284 data
->hActCtx
= NULL
;
4286 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4287 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4289 return STATUS_SUCCESS
;
4292 static void get_ifaceps_datalen(const struct entity_array
*entities
, unsigned int *count
, unsigned int *len
)
4296 for (i
= 0; i
< entities
->num
; i
++)
4298 struct entity
*entity
= &entities
->base
[i
];
4299 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4301 *len
+= sizeof(struct guid_index
) + sizeof(struct ifacepsredirect_data
);
4302 if (entity
->u
.ifaceps
.name
)
4303 *len
+= aligned_string_len((strlenW(entity
->u
.ifaceps
.name
)+1)*sizeof(WCHAR
));
4309 static void add_ifaceps_record(struct guidsection_header
*section
, struct entity_array
*entities
,
4310 struct guid_index
**index
, ULONG
*data_offset
, ULONG rosterindex
)
4314 for (i
= 0; i
< entities
->num
; i
++)
4316 struct entity
*entity
= &entities
->base
[i
];
4317 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)
4319 struct ifacepsredirect_data
*data
= (struct ifacepsredirect_data
*)((BYTE
*)section
+ *data_offset
);
4323 if (entity
->u
.ifaceps
.name
)
4324 name_len
= strlenW(entity
->u
.ifaceps
.name
)*sizeof(WCHAR
);
4329 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.iid
);
4330 RtlGUIDFromString(&str
, &(*index
)->guid
);
4331 (*index
)->data_offset
= *data_offset
;
4332 (*index
)->data_len
= sizeof(*data
) + name_len
? aligned_string_len(name_len
+ sizeof(WCHAR
)) : 0;
4333 (*index
)->rosterindex
= rosterindex
;
4335 /* setup data record */
4336 data
->size
= sizeof(*data
);
4337 data
->mask
= entity
->u
.ifaceps
.mask
;
4339 /* proxyStubClsid32 value is only stored for external PS,
4340 if set it's used as iid, otherwise 'iid' attribute value is used */
4341 if (entity
->u
.ifaceps
.ps32
)
4343 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.ps32
);
4344 RtlGUIDFromString(&str
, &data
->iid
);
4347 data
->iid
= (*index
)->guid
;
4349 data
->nummethods
= entity
->u
.ifaceps
.nummethods
;
4351 if (entity
->u
.ifaceps
.tlib
)
4353 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.tlib
);
4354 RtlGUIDFromString(&str
, &data
->tlbid
);
4357 memset(&data
->tlbid
, 0, sizeof(data
->tlbid
));
4359 if (entity
->u
.ifaceps
.base
)
4361 RtlInitUnicodeString(&str
, entity
->u
.ifaceps
.base
);
4362 RtlGUIDFromString(&str
, &data
->base
);
4365 memset(&data
->base
, 0, sizeof(data
->base
));
4367 data
->name_len
= name_len
;
4368 data
->name_offset
= data
->name_len
? sizeof(*data
) : 0;
4373 WCHAR
*ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4374 memcpy(ptrW
, entity
->u
.ifaceps
.name
, data
->name_len
);
4375 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4378 /* move to next record */
4380 *data_offset
+= sizeof(*data
);
4382 *data_offset
+= aligned_string_len(data
->name_len
+ sizeof(WCHAR
));
4387 static NTSTATUS
build_ifaceps_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4389 unsigned int i
, j
, total_len
= 0, count
= 0;
4390 struct guidsection_header
*header
;
4391 struct guid_index
*index
;
4394 /* compute section length */
4395 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4397 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4399 get_ifaceps_datalen(&assembly
->entities
, &count
, &total_len
);
4400 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4402 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4403 get_ifaceps_datalen(&dll
->entities
, &count
, &total_len
);
4407 total_len
+= sizeof(*header
);
4409 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4410 if (!header
) return STATUS_NO_MEMORY
;
4412 memset(header
, 0, sizeof(*header
));
4413 header
->magic
= GUIDSECTION_MAGIC
;
4414 header
->size
= sizeof(*header
);
4415 header
->count
= count
;
4416 header
->index_offset
= sizeof(*header
);
4417 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4418 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4420 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4422 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4424 add_ifaceps_record(header
, &assembly
->entities
, &index
, &data_offset
, i
+ 1);
4425 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4427 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4428 add_ifaceps_record(header
, &dll
->entities
, &index
, &data_offset
, i
+ 1);
4434 return STATUS_SUCCESS
;
4437 static inline struct ifacepsredirect_data
*get_ifaceps_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
4439 return (struct ifacepsredirect_data
*)((BYTE
*)actctx
->ifaceps_section
+ index
->data_offset
);
4442 static NTSTATUS
find_cominterface_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4444 struct ifacepsredirect_data
*iface
;
4445 struct guid_index
*index
= NULL
;
4447 if (!(actctx
->sections
& IFACEREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4449 if (!actctx
->ifaceps_section
)
4451 struct guidsection_header
*section
;
4453 NTSTATUS status
= build_ifaceps_section(actctx
, §ion
);
4454 if (status
) return status
;
4456 if (InterlockedCompareExchangePointer((void**)&actctx
->ifaceps_section
, section
, NULL
))
4457 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4460 index
= find_guid_index(actctx
->ifaceps_section
, guid
);
4461 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4463 iface
= get_ifaceps_data(actctx
, index
);
4465 data
->ulDataFormatVersion
= 1;
4466 data
->lpData
= iface
;
4467 data
->ulLength
= iface
->size
+ (iface
->name_len
? iface
->name_len
+ sizeof(WCHAR
) : 0);
4468 data
->lpSectionGlobalData
= NULL
;
4469 data
->ulSectionGlobalDataLength
= 0;
4470 data
->lpSectionBase
= actctx
->ifaceps_section
;
4471 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->ifaceps_section
);
4472 data
->hActCtx
= NULL
;
4474 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4475 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4477 return STATUS_SUCCESS
;
4480 static NTSTATUS
build_clr_surrogate_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
4482 unsigned int i
, j
, total_len
= 0, count
= 0;
4483 struct guidsection_header
*header
;
4484 struct clrsurrogate_data
*data
;
4485 struct guid_index
*index
;
4488 /* compute section length */
4489 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4491 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4492 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4494 struct entity
*entity
= &assembly
->entities
.base
[j
];
4495 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4499 total_len
+= sizeof(*index
) + sizeof(*data
);
4500 len
= strlenW(entity
->u
.clrsurrogate
.name
) + 1;
4501 if (entity
->u
.clrsurrogate
.version
)
4502 len
+= strlenW(entity
->u
.clrsurrogate
.version
) + 1;
4503 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
4510 total_len
+= sizeof(*header
);
4512 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4513 if (!header
) return STATUS_NO_MEMORY
;
4515 memset(header
, 0, sizeof(*header
));
4516 header
->magic
= GUIDSECTION_MAGIC
;
4517 header
->size
= sizeof(*header
);
4518 header
->count
= count
;
4519 header
->index_offset
= sizeof(*header
);
4520 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
4521 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4523 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4525 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4526 for (j
= 0; j
< assembly
->entities
.num
; j
++)
4528 struct entity
*entity
= &assembly
->entities
.base
[j
];
4529 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
)
4531 ULONG version_len
, name_len
;
4535 if (entity
->u
.clrsurrogate
.version
)
4536 version_len
= strlenW(entity
->u
.clrsurrogate
.version
)*sizeof(WCHAR
);
4539 name_len
= strlenW(entity
->u
.clrsurrogate
.name
)*sizeof(WCHAR
);
4541 /* setup new index entry */
4542 RtlInitUnicodeString(&str
, entity
->u
.clrsurrogate
.clsid
);
4543 RtlGUIDFromString(&str
, &index
->guid
);
4545 index
->data_offset
= data_offset
;
4546 index
->data_len
= sizeof(*data
) + aligned_string_len(name_len
+ sizeof(WCHAR
) + (version_len
? version_len
+ sizeof(WCHAR
) : 0));
4547 index
->rosterindex
= i
+ 1;
4550 data
= (struct clrsurrogate_data
*)((BYTE
*)header
+ index
->data_offset
);
4551 data
->size
= sizeof(*data
);
4553 data
->clsid
= index
->guid
;
4554 data
->version_offset
= version_len
? data
->size
: 0;
4555 data
->version_len
= version_len
;
4556 data
->name_offset
= data
->size
+ version_len
;
4558 data
->name_offset
+= sizeof(WCHAR
);
4559 data
->name_len
= name_len
;
4561 /* surrogate name */
4562 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
4563 memcpy(ptrW
, entity
->u
.clrsurrogate
.name
, data
->name_len
);
4564 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
4566 /* runtime version */
4567 if (data
->version_len
)
4569 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->version_offset
);
4570 memcpy(ptrW
, entity
->u
.clrsurrogate
.version
, data
->version_len
);
4571 ptrW
[data
->version_len
/sizeof(WCHAR
)] = 0;
4574 data_offset
+= index
->data_offset
;
4582 return STATUS_SUCCESS
;
4585 static inline struct clrsurrogate_data
*get_surrogate_data(ACTIVATION_CONTEXT
*actctx
, const struct guid_index
*index
)
4587 return (struct clrsurrogate_data
*)((BYTE
*)actctx
->clrsurrogate_section
+ index
->data_offset
);
4590 static NTSTATUS
find_clr_surrogate(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
4592 struct clrsurrogate_data
*surrogate
;
4593 struct guid_index
*index
= NULL
;
4595 if (!(actctx
->sections
& CLRSURROGATES_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4597 if (!actctx
->clrsurrogate_section
)
4599 struct guidsection_header
*section
;
4601 NTSTATUS status
= build_clr_surrogate_section(actctx
, §ion
);
4602 if (status
) return status
;
4604 if (InterlockedCompareExchangePointer((void**)&actctx
->clrsurrogate_section
, section
, NULL
))
4605 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4608 index
= find_guid_index(actctx
->clrsurrogate_section
, guid
);
4609 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4611 surrogate
= get_surrogate_data(actctx
, index
);
4613 data
->ulDataFormatVersion
= 1;
4614 data
->lpData
= surrogate
;
4615 /* full length includes string length with nulls */
4616 data
->ulLength
= surrogate
->size
+ surrogate
->name_len
+ sizeof(WCHAR
);
4617 if (surrogate
->version_len
)
4618 data
->ulLength
+= surrogate
->version_len
+ sizeof(WCHAR
);
4620 data
->lpSectionGlobalData
= NULL
;
4621 data
->ulSectionGlobalDataLength
= 0;
4622 data
->lpSectionBase
= actctx
->clrsurrogate_section
;
4623 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->clrsurrogate_section
);
4624 data
->hActCtx
= NULL
;
4626 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4627 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4629 return STATUS_SUCCESS
;
4632 static void get_progid_datalen(struct entity_array
*entities
, unsigned int *count
, unsigned int *total_len
)
4634 unsigned int i
, j
, single_len
;
4636 single_len
= sizeof(struct progidredirect_data
) + sizeof(struct string_index
) + sizeof(GUID
);
4637 for (i
= 0; i
< entities
->num
; i
++)
4639 struct entity
*entity
= &entities
->base
[i
];
4640 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4642 if (entity
->u
.comclass
.progid
)
4644 *total_len
+= single_len
+ aligned_string_len((strlenW(entity
->u
.comclass
.progid
)+1)*sizeof(WCHAR
));
4648 for (j
= 0; j
< entity
->u
.comclass
.progids
.num
; j
++)
4649 *total_len
+= aligned_string_len((strlenW(entity
->u
.comclass
.progids
.progids
[j
])+1)*sizeof(WCHAR
));
4651 *total_len
+= single_len
*entity
->u
.comclass
.progids
.num
;
4652 *count
+= entity
->u
.comclass
.progids
.num
;
4657 static void write_progid_record(struct strsection_header
*section
, const WCHAR
*progid
, const GUID
*alias
,
4658 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4660 struct progidredirect_data
*data
;
4665 /* setup new index entry */
4667 /* hash progid name */
4668 RtlInitUnicodeString(&str
, progid
);
4669 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &(*index
)->hash
);
4671 (*index
)->name_offset
= *data_offset
;
4672 (*index
)->name_len
= str
.Length
;
4673 (*index
)->data_offset
= (*index
)->name_offset
+ aligned_string_len(str
.MaximumLength
);
4674 (*index
)->data_len
= sizeof(*data
);
4675 (*index
)->rosterindex
= rosterindex
;
4677 *data_offset
+= aligned_string_len(str
.MaximumLength
);
4679 /* setup data structure */
4680 data
= (struct progidredirect_data
*)((BYTE
*)section
+ *data_offset
);
4681 data
->size
= sizeof(*data
);
4683 data
->clsid_offset
= *global_offset
;
4685 /* write progid string */
4686 ptrW
= (WCHAR
*)((BYTE
*)section
+ (*index
)->name_offset
);
4687 memcpy(ptrW
, progid
, (*index
)->name_len
);
4688 ptrW
[(*index
)->name_len
/sizeof(WCHAR
)] = 0;
4690 /* write guid to global area */
4691 guid_ptr
= (GUID
*)((BYTE
*)section
+ data
->clsid_offset
);
4695 *global_offset
+= sizeof(GUID
);
4696 *data_offset
+= data
->size
;
4700 static void add_progid_record(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
*section
, const struct entity_array
*entities
,
4701 struct string_index
**index
, ULONG
*data_offset
, ULONG
*global_offset
, ULONG rosterindex
)
4705 for (i
= 0; i
< entities
->num
; i
++)
4707 struct entity
*entity
= &entities
->base
[i
];
4708 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)
4710 const struct progids
*progids
= &entity
->u
.comclass
.progids
;
4711 struct comclassredirect_data
*comclass
;
4712 struct guid_index
*guid_index
;
4716 RtlInitUnicodeString(&str
, entity
->u
.comclass
.clsid
);
4717 RtlGUIDFromString(&str
, &clsid
);
4719 guid_index
= find_guid_index(actctx
->comserver_section
, &clsid
);
4720 comclass
= get_comclass_data(actctx
, guid_index
);
4722 if (entity
->u
.comclass
.progid
)
4723 write_progid_record(section
, entity
->u
.comclass
.progid
, &comclass
->alias
,
4724 index
, data_offset
, global_offset
, rosterindex
);
4726 for (j
= 0; j
< progids
->num
; j
++)
4727 write_progid_record(section
, progids
->progids
[j
], &comclass
->alias
,
4728 index
, data_offset
, global_offset
, rosterindex
);
4733 static NTSTATUS
build_progid_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
4735 unsigned int i
, j
, total_len
= 0, count
= 0;
4736 struct strsection_header
*header
;
4737 ULONG data_offset
, global_offset
;
4738 struct string_index
*index
;
4740 /* compute section length */
4741 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4743 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4745 get_progid_datalen(&assembly
->entities
, &count
, &total_len
);
4746 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4748 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4749 get_progid_datalen(&dll
->entities
, &count
, &total_len
);
4753 total_len
+= sizeof(*header
);
4755 header
= RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len
);
4756 if (!header
) return STATUS_NO_MEMORY
;
4758 memset(header
, 0, sizeof(*header
));
4759 header
->magic
= STRSECTION_MAGIC
;
4760 header
->size
= sizeof(*header
);
4761 header
->count
= count
;
4762 header
->global_offset
= header
->size
;
4763 header
->global_len
= count
*sizeof(GUID
);
4764 header
->index_offset
= header
->size
+ header
->global_len
;
4766 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
4767 data_offset
= header
->index_offset
+ count
*sizeof(*index
);
4768 global_offset
= header
->global_offset
;
4770 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
4772 struct assembly
*assembly
= &actctx
->assemblies
[i
];
4774 add_progid_record(actctx
, header
, &assembly
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4775 for (j
= 0; j
< assembly
->num_dlls
; j
++)
4777 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
4778 add_progid_record(actctx
, header
, &dll
->entities
, &index
, &data_offset
, &global_offset
, i
+ 1);
4784 return STATUS_SUCCESS
;
4787 static inline struct progidredirect_data
*get_progid_data(ACTIVATION_CONTEXT
*actctx
, const struct string_index
*index
)
4789 return (struct progidredirect_data
*)((BYTE
*)actctx
->progid_section
+ index
->data_offset
);
4792 static NTSTATUS
find_progid_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
4793 PACTCTX_SECTION_KEYED_DATA data
)
4795 struct progidredirect_data
*progid
;
4796 struct string_index
*index
;
4798 if (!(actctx
->sections
& PROGIDREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
4800 if (!actctx
->comserver_section
)
4802 struct guidsection_header
*section
;
4804 NTSTATUS status
= build_comserver_section(actctx
, §ion
);
4805 if (status
) return status
;
4807 if (InterlockedCompareExchangePointer((void**)&actctx
->comserver_section
, section
, NULL
))
4808 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4811 if (!actctx
->progid_section
)
4813 struct strsection_header
*section
;
4815 NTSTATUS status
= build_progid_section(actctx
, §ion
);
4816 if (status
) return status
;
4818 if (InterlockedCompareExchangePointer((void**)&actctx
->progid_section
, section
, NULL
))
4819 RtlFreeHeap(RtlGetProcessHeap(), 0, section
);
4822 index
= find_string_index(actctx
->progid_section
, name
);
4823 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
4827 progid
= get_progid_data(actctx
, index
);
4829 data
->ulDataFormatVersion
= 1;
4830 data
->lpData
= progid
;
4831 data
->ulLength
= progid
->size
;
4832 data
->lpSectionGlobalData
= (BYTE
*)actctx
->progid_section
+ actctx
->progid_section
->global_offset
;
4833 data
->ulSectionGlobalDataLength
= actctx
->progid_section
->global_len
;
4834 data
->lpSectionBase
= actctx
->progid_section
;
4835 data
->ulSectionTotalLength
= RtlSizeHeap( RtlGetProcessHeap(), 0, actctx
->progid_section
);
4836 data
->hActCtx
= NULL
;
4838 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
4839 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
4842 return STATUS_SUCCESS
;
4845 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4846 const UNICODE_STRING
*section_name
,
4847 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4851 switch (section_kind
)
4853 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION
:
4854 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4855 return STATUS_SXS_KEY_NOT_FOUND
;
4856 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
4857 status
= find_dll_redirection(actctx
, section_name
, data
);
4859 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
4860 status
= find_window_class(actctx
, section_name
, data
);
4862 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
4863 status
= find_progid_redirection(actctx
, section_name
, data
);
4865 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
4866 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
4867 return STATUS_SXS_SECTION_NOT_FOUND
;
4869 DPRINT1("Unknown section_kind %x\n", section_kind
);
4870 return STATUS_SXS_SECTION_NOT_FOUND
;
4873 if (status
!= STATUS_SUCCESS
) return status
;
4875 if (data
&& (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
))
4877 actctx_addref(actctx
);
4878 data
->hActCtx
= actctx
;
4880 return STATUS_SUCCESS
;
4883 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
4884 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
4888 switch (section_kind
)
4890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
4891 status
= find_tlib_redirection(actctx
, guid
, data
);
4893 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
4894 status
= find_comserver_redirection(actctx
, guid
, data
);
4896 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
4897 status
= find_cominterface_redirection(actctx
, guid
, data
);
4899 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
4900 status
= find_clr_surrogate(actctx
, guid
, data
);
4903 DPRINT("Unknown section_kind %x\n", section_kind
);
4904 return STATUS_SXS_SECTION_NOT_FOUND
;
4907 if (status
!= STATUS_SUCCESS
) return status
;
4909 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
4911 actctx_addref(actctx
);
4912 data
->hActCtx
= actctx
;
4914 return STATUS_SUCCESS
;
4917 /* initialize the activation context for the current process */
4918 void actctx_init(void)
4925 ctx
.cbSize
= sizeof(ctx
);
4926 ctx
.lpSource
= NULL
;
4927 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
4928 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
4929 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
4931 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
)))
4933 process_actctx
= check_actctx(handle
);
4938 ctx
.lpResourceName
= NULL
;
4939 ctx
.lpSource
= buffer
;
4940 RtlStringCchCopyW(buffer
, 1024, SharedUserData
->NtSystemRoot
);
4941 RtlStringCchCatW(buffer
, 1024, L
"\\winsxs\\manifests\\systemcompatible.manifest");
4942 Status
= RtlCreateActivationContext(0, (PVOID
)&ctx
, 0, NULL
, NULL
, &handle
);
4943 if (NT_SUCCESS(Status
))
4945 implicit_actctx
= check_actctx(handle
);
4949 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status
);
4953 /* FUNCTIONS ***************************************************************/
4955 /***********************************************************************
4956 * RtlCreateActivationContext (NTDLL.@)
4958 * Create an activation context.
4962 RtlCreateActivationContext(IN ULONG Flags
,
4963 IN PACTIVATION_CONTEXT_DATA ActivationContextData
,
4964 IN ULONG ExtraBytes
,
4965 IN PVOID NotificationRoutine
,
4966 IN PVOID NotificationContext
,
4967 OUT PACTIVATION_CONTEXT
*ActCtx
)
4969 const ACTCTXW
*pActCtx
= (PVOID
)ActivationContextData
;
4970 const WCHAR
*directory
= NULL
;
4971 PACTIVATION_CONTEXT_WRAPPED ActualActCtx
;
4972 ACTIVATION_CONTEXT
*actctx
;
4973 UNICODE_STRING nameW
;
4975 NTSTATUS status
= STATUS_NO_MEMORY
;
4977 struct actctx_loader acl
;
4979 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0, ((ACTCTXW
*)ActivationContextData
)->hModule
);
4981 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
4982 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
4983 return STATUS_INVALID_PARAMETER
;
4986 if (!(ActualActCtx
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*ActualActCtx
))))
4987 return STATUS_NO_MEMORY
;
4989 ActualActCtx
->MagicMarker
= ACTCTX_MAGIC_MARKER
;
4991 actctx
= &ActualActCtx
->ActivationContext
;
4992 actctx
->RefCount
= 1;
4993 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
4994 actctx
->config
.info
= NULL
;
4995 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
4996 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
4998 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
5006 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
5007 else module
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
5009 status
= get_module_filename( module
, &dir
, 0 );
5010 if (!NT_SUCCESS(status
)) goto error
;
5011 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
5012 actctx
->appdir
.info
= dir
.Buffer
;
5015 nameW
.Buffer
= NULL
;
5017 /* open file only if it's going to be used */
5018 if (pActCtx
->lpSource
&& !((pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
) &&
5019 (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)))
5021 WCHAR
*source
= NULL
;
5024 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
&&
5025 RtlDetermineDosPathNameType_U(pActCtx
->lpSource
) == RtlPathTypeRelative
)
5027 DWORD dir_len
, source_len
;
5029 dir_len
= strlenW(pActCtx
->lpAssemblyDirectory
);
5030 source_len
= strlenW(pActCtx
->lpSource
);
5031 if (!(source
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len
+source_len
+2)*sizeof(WCHAR
))))
5033 status
= STATUS_NO_MEMORY
;
5037 memcpy(source
, pActCtx
->lpAssemblyDirectory
, dir_len
*sizeof(WCHAR
));
5038 source
[dir_len
] = '\\';
5039 memcpy(source
+dir_len
+1, pActCtx
->lpSource
, (source_len
+1)*sizeof(WCHAR
));
5042 ret
= RtlDosPathNameToNtPathName_U(source
? source
: pActCtx
->lpSource
, &nameW
, NULL
, NULL
);
5043 RtlFreeHeap( RtlGetProcessHeap(), 0, source
);
5046 status
= STATUS_NO_SUCH_FILE
;
5049 status
= open_nt_file( &file
, &nameW
);
5050 if (!NT_SUCCESS(status
))
5052 RtlFreeUnicodeString( &nameW
);
5057 acl
.actctx
= actctx
;
5058 acl
.dependencies
= NULL
;
5059 acl
.num_dependencies
= 0;
5060 acl
.allocated_dependencies
= 0;
5062 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
5063 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
5065 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
5067 /* if we have a resource it's a PE file */
5068 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
5070 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
5071 pActCtx
->lpResourceName
, lang
);
5072 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5073 /* FIXME: what to do if pActCtx->lpSource is set */
5074 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
5075 pActCtx
->hModule
, pActCtx
->lpResourceName
);
5077 else if (pActCtx
->lpSource
)
5079 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
5080 file
, pActCtx
->lpResourceName
, lang
);
5081 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
5082 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
5083 NULL
, pActCtx
->lpResourceName
);
5085 else status
= STATUS_INVALID_PARAMETER
;
5089 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
5092 if (file
) NtClose( file
);
5093 RtlFreeUnicodeString( &nameW
);
5095 if (NT_SUCCESS(status
)) status
= parse_depend_manifests(&acl
);
5096 free_depend_manifests( &acl
);
5098 if (NT_SUCCESS(status
))
5100 else actctx_release( actctx
);
5104 if (file
) NtClose( file
);
5105 actctx_release( actctx
);
5110 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
5114 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle
)
5116 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
)Handle
;
5117 LONG OldRefCount
, NewRefCount
;
5119 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
5121 RtlpValidateActCtx(ActCtx
);
5125 OldRefCount
= ActCtx
->RefCount
;
5126 ASSERT(OldRefCount
> 0);
5128 if (OldRefCount
== LONG_MAX
) break;
5130 NewRefCount
= OldRefCount
+ 1;
5131 if (InterlockedCompareExchange(&ActCtx
->RefCount
,
5133 OldRefCount
) == OldRefCount
)
5139 NewRefCount
= LONG_MAX
;
5140 ASSERT(NewRefCount
> 0);
5146 RtlReleaseActivationContext( HANDLE handle
)
5148 PIACTIVATION_CONTEXT ActCtx
= (PIACTIVATION_CONTEXT
) Handle
;
5150 if ((ActCtx
) && (ACT_CTX_VALID(ActCtx
)) && (ActCtx
->RefCount
!= LONG_MAX
))
5152 RtlpValidateActCtx(ActCtx
);
5154 actctx_release(ActCtx
);
5159 /***********************************************************************
5160 * RtlAddRefActivationContext (NTDLL.@)
5162 VOID NTAPI
RtlAddRefActivationContext( HANDLE handle
)
5164 ACTIVATION_CONTEXT
*actctx
;
5166 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
5170 /******************************************************************
5171 * RtlReleaseActivationContext (NTDLL.@)
5173 VOID NTAPI
RtlReleaseActivationContext( HANDLE handle
)
5175 ACTIVATION_CONTEXT
*actctx
;
5177 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
5182 /******************************************************************
5183 * RtlZombifyActivationContext (NTDLL.@)
5186 NTSTATUS NTAPI
RtlZombifyActivationContext(PVOID Context
)
5190 if (Context
== ACTCTX_FAKE_HANDLE
)
5191 return STATUS_SUCCESS
;
5193 return STATUS_NOT_IMPLEMENTED
;
5197 NTAPI
RtlActivateActivationContextEx( ULONG flags
, PTEB tebAddress
, HANDLE handle
, PULONG_PTR cookie
)
5199 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5201 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
5202 return STATUS_NO_MEMORY
;
5204 frame
->Previous
= tebAddress
->ActivationContextStackPointer
->ActiveFrame
;
5205 frame
->ActivationContext
= handle
;
5208 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5209 tebAddress
->ActivationContextStackPointer
, tebAddress
->ActivationContextStackPointer
->ActiveFrame
,
5212 tebAddress
->ActivationContextStackPointer
->ActiveFrame
= frame
;
5213 RtlAddRefActivationContext( handle
);
5215 *cookie
= (ULONG_PTR
)frame
;
5216 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
5217 return STATUS_SUCCESS
;
5220 /******************************************************************
5221 * RtlActivateActivationContext (NTDLL.@)
5223 NTSTATUS NTAPI
RtlActivateActivationContext( ULONG flags
, HANDLE handle
, PULONG_PTR cookie
)
5225 return RtlActivateActivationContextEx(flags
, NtCurrentTeb(), handle
, cookie
);
5228 /***********************************************************************
5229 * RtlDeactivateActivationContext (NTDLL.@)
5231 NTSTATUS NTAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
5233 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
5235 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
5237 /* find the right frame */
5238 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5239 for (frame
= top
; frame
; frame
= frame
->Previous
)
5240 if ((ULONG_PTR
)frame
== cookie
) break;
5243 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
5245 if (frame
!= top
&& !(flags
& RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
))
5246 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
5248 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5249 NtCurrentTeb()->ActivationContextStackPointer
,
5250 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
,
5253 /* pop everything up to and including frame */
5254 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
5256 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5258 frame
= top
->Previous
;
5259 RtlReleaseActivationContext( top
->ActivationContext
);
5260 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
5264 return STATUS_SUCCESS
;
5269 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack
)
5271 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, PrevFrame
;
5273 /* Nothing to do if there is no stack */
5276 /* Get the current active frame */
5277 ActiveFrame
= Stack
->ActiveFrame
;
5279 /* Go through them in backwards order and release */
5282 PrevFrame
= ActiveFrame
->Previous
;
5283 RtlReleaseActivationContext(ActiveFrame
->ActivationContext
);
5284 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame
);
5285 ActiveFrame
= PrevFrame
;
5288 /* Zero out the active frame */
5289 Stack
->ActiveFrame
= NULL
;
5291 /* TODO: Empty the Frame List Cache */
5292 ASSERT(IsListEmpty(&Stack
->FrameListCache
));
5294 /* Free activation stack memory */
5295 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack
);
5298 /******************************************************************
5299 * RtlFreeThreadActivationContextStack (NTDLL.@)
5301 VOID NTAPI
RtlFreeThreadActivationContextStack(VOID
)
5303 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer
);
5304 NtCurrentTeb()->ActivationContextStackPointer
= NULL
;
5308 /******************************************************************
5309 * RtlGetActiveActivationContext (NTDLL.@)
5311 NTSTATUS NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
5313 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5315 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
5316 RtlAddRefActivationContext( *handle
);
5321 return STATUS_SUCCESS
;
5325 /******************************************************************
5326 * RtlIsActivationContextActive (NTDLL.@)
5328 BOOLEAN NTAPI
RtlIsActivationContextActive( HANDLE handle
)
5330 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
5332 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
5333 if (frame
->ActivationContext
== handle
) return TRUE
;
5338 /***********************************************************************
5339 * RtlQueryInformationActivationContext (NTDLL.@)
5341 * Get information about an activation context.
5342 * FIXME: function signature/prototype may be wrong
5344 NTSTATUS NTAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
5345 ULONG
class, PVOID buffer
,
5346 SIZE_T bufsize
, SIZE_T
*retlen
)
5348 ACTIVATION_CONTEXT
*actctx
;
5351 DPRINT("%08x %p %p %u %p %Iu %p\n", flags
, handle
,
5352 subinst
, class, buffer
, bufsize
, retlen
);
5354 if (retlen
) *retlen
= 0;
5355 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
5359 case ActivationContextBasicInformation
:
5361 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
5363 if (retlen
) *retlen
= sizeof(*info
);
5364 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
5366 info
->hActCtx
= handle
;
5367 info
->dwFlags
= 0; /* FIXME */
5368 if (!(flags
& RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
)) RtlAddRefActivationContext(handle
);
5372 case ActivationContextDetailedInformation
:
5374 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
5375 struct assembly
*assembly
= NULL
;
5376 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
5379 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5381 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5383 if (assembly
&& assembly
->manifest
.info
)
5384 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
5385 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
5386 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
5387 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
5389 if (retlen
) *retlen
= len
;
5390 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5393 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
5394 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
5395 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
5396 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? (DWORD
)manifest_len
- 1 : 0;
5397 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
5398 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? (DWORD
)config_len
- 1 : 0;
5399 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
5400 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? (DWORD
)appdir_len
- 1 : 0;
5401 ptr
= (LPWSTR
)(acdi
+ 1);
5404 acdi
->lpRootManifestPath
= ptr
;
5405 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
5406 ptr
+= manifest_len
;
5408 else acdi
->lpRootManifestPath
= NULL
;
5411 acdi
->lpRootConfigurationPath
= ptr
;
5412 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
5415 else acdi
->lpRootConfigurationPath
= NULL
;
5418 acdi
->lpAppDirPath
= ptr
;
5419 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
5421 else acdi
->lpAppDirPath
= NULL
;
5425 case AssemblyDetailedInformationInActivationContext
:
5427 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
5428 struct assembly
*assembly
;
5431 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
5434 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5435 if (!subinst
) return STATUS_INVALID_PARAMETER
;
5437 index
= *(DWORD
*)subinst
;
5438 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
5440 assembly
= &actctx
->assemblies
[index
- 1];
5442 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
5443 id_len
= strlenW(assembly_id
) + 1;
5444 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
5446 if (assembly
->manifest
.info
&&
5447 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
5448 path_len
= strlenW(assembly
->manifest
.info
) + 1;
5450 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
5452 if (retlen
) *retlen
= len
;
5453 if (!buffer
|| bufsize
< len
)
5455 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5456 return STATUS_BUFFER_TOO_SMALL
;
5459 afdi
->ulFlags
= 0; /* FIXME */
5460 afdi
->ulEncodedAssemblyIdentityLength
= (DWORD
)(id_len
- 1) * sizeof(WCHAR
);
5461 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
5462 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (DWORD
)(path_len
- 1) * sizeof(WCHAR
) : 0;
5463 /* FIXME afdi->liManifestLastWriteTime = 0; */
5464 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
5465 afdi
->ulPolicyPathLength
= 0;
5466 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5467 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
5468 afdi
->ulManifestVersionMajor
= 1;
5469 afdi
->ulManifestVersionMinor
= 0;
5470 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
5471 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
5472 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (DWORD
)(ad_len
- 1) * sizeof(WCHAR
) : 0;
5473 ptr
= (LPWSTR
)(afdi
+ 1);
5474 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
5475 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
5479 afdi
->lpAssemblyManifestPath
= ptr
;
5480 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
5482 } else afdi
->lpAssemblyManifestPath
= NULL
;
5483 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
5486 afdi
->lpAssemblyDirectoryName
= ptr
;
5487 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
5489 else afdi
->lpAssemblyDirectoryName
= NULL
;
5490 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
5494 case FileInformationInAssemblyOfAssemblyInActivationContext
:
5496 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
5497 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
5498 struct assembly
*assembly
;
5499 struct dll_redirect
*dll
;
5500 SIZE_T len
, dll_len
= 0;
5503 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5504 if (!acqi
) return STATUS_INVALID_PARAMETER
;
5506 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
5507 return STATUS_INVALID_PARAMETER
;
5508 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
5510 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
5511 return STATUS_INVALID_PARAMETER
;
5512 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
5514 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
5515 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
5517 if (!buffer
|| bufsize
< len
)
5519 if (retlen
) *retlen
= len
;
5520 return STATUS_BUFFER_TOO_SMALL
;
5522 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
5523 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
5524 afdi
->ulFilenameLength
= dll_len
? (DWORD
)(dll_len
- 1) * sizeof(WCHAR
) : 0;
5525 afdi
->ulPathLength
= 0; /* FIXME */
5526 ptr
= (LPWSTR
)(afdi
+ 1);
5529 afdi
->lpFileName
= ptr
;
5530 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
5531 } else afdi
->lpFileName
= NULL
;
5532 afdi
->lpFilePath
= NULL
; /* FIXME */
5536 case CompatibilityInformationInActivationContext
:
5538 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD
*acci
= buffer
;
5539 COMPATIBILITY_CONTEXT_ELEMENT
*elements
;
5540 struct assembly
*assembly
= NULL
;
5541 ULONG num_compat_contexts
= 0, n
;
5544 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5546 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
5549 num_compat_contexts
= assembly
->num_compat_contexts
;
5550 len
= sizeof(*acci
) + num_compat_contexts
* sizeof(COMPATIBILITY_CONTEXT_ELEMENT
);
5552 if (retlen
) *retlen
= len
;
5553 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
5555 *acci
= num_compat_contexts
;
5556 elements
= (COMPATIBILITY_CONTEXT_ELEMENT
*)(acci
+ 1);
5557 for (n
= 0; n
< num_compat_contexts
; ++n
)
5559 elements
[n
] = assembly
->compat_contexts
[n
];
5564 case RunlevelInformationInActivationContext
:
5566 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION
*acrli
= buffer
;
5567 struct assembly
*assembly
;
5570 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
5572 len
= sizeof(*acrli
);
5573 if (retlen
) *retlen
= len
;
5574 if (!buffer
|| bufsize
< len
)
5575 return STATUS_BUFFER_TOO_SMALL
;
5577 assembly
= actctx
->assemblies
;
5580 acrli
->RunLevel
= assembly
? assembly
->run_level
: ACTCTX_RUN_LEVEL_UNSPECIFIED
;
5581 acrli
->UiAccess
= assembly
? assembly
->ui_access
: 0;
5586 DPRINT( "class %u not implemented\n", class );
5587 return STATUS_NOT_IMPLEMENTED
;
5589 return STATUS_SUCCESS
;
5594 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass
,
5596 SIZE_T cbBuffer OPTIONAL
,
5597 SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
5599 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
5605 pcbWrittenOrRequired
);
5608 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
5609 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
5610 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
5614 RtlpFindActivationContextSection_CheckParameters( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5615 const UNICODE_STRING
*section_name
, PACTCTX_SECTION_KEYED_DATA data
)
5617 /* Check general parameter combinations */
5618 if (!section_name
|| !section_name
->Buffer
||
5619 (flags
& ~FIND_ACTCTX_VALID_MASK
) ||
5620 ((flags
& FIND_ACTCTX_VALID_MASK
) && !data
) ||
5621 (data
&& data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
)))
5623 DPRINT1("invalid parameter\n");
5624 return STATUS_INVALID_PARAMETER
;
5628 if (flags
& FIND_ACTCTX_RETURN_FLAGS
||
5629 flags
& FIND_ACTCTX_RETURN_ASSEMBLY_METADATA
)
5631 DPRINT1("unknown flags %08x\n", flags
);
5632 return STATUS_INVALID_PARAMETER
;
5635 return STATUS_SUCCESS
;
5638 /***********************************************************************
5639 * RtlFindActivationContextSectionString (NTDLL.@)
5641 * Find information about a string in an activation context.
5642 * FIXME: function signature/prototype may be wrong
5644 NTSTATUS NTAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
5645 const UNICODE_STRING
*section_name
, PVOID ptr
)
5647 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
5650 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags
, guid
, section_kind
, section_name
, ptr
);
5651 status
= RtlpFindActivationContextSection_CheckParameters(flags
, guid
, section_kind
, section_name
, data
);
5652 if (!NT_SUCCESS(status
))
5654 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5658 status
= STATUS_SXS_KEY_NOT_FOUND
;
5660 /* if there is no data, but params are valid,
5661 we return that sxs key is not found to be at least somehow compatible */
5664 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status
);
5668 ASSERT(NtCurrentTeb());
5669 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
5671 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
);
5672 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5674 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5675 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
5678 DPRINT("status %x\n", status
);
5679 if (status
!= STATUS_SUCCESS
)
5680 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
5682 if (status
!= STATUS_SUCCESS
)
5683 status
= find_string( implicit_actctx
, section_kind
, section_name
, flags
, data
);
5685 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status
);
5689 /***********************************************************************
5690 * RtlFindActivationContextSectionGuid (NTDLL.@)
5692 * Find information about a GUID in an activation context.
5693 * FIXME: function signature/prototype may be wrong
5695 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
5696 const GUID
*guid
, void *ptr
)
5698 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
5699 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
5703 DPRINT1("expected extguid == NULL\n");
5704 return STATUS_INVALID_PARAMETER
;
5707 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
5709 DPRINT1("unknown flags %08x\n", flags
);
5710 return STATUS_INVALID_PARAMETER
;
5713 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
5714 return STATUS_INVALID_PARAMETER
;
5716 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
5718 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
5719 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
5722 if (status
!= STATUS_SUCCESS
)
5723 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);
5725 if (status
!= STATUS_SUCCESS
)
5726 status
= find_guid( implicit_actctx
, section_kind
, guid
, flags
, data
);
5735 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK
*Stack
)
5737 PACTIVATION_CONTEXT_STACK ContextStack
;
5739 /* Check if it's already allocated */
5740 if (*Stack
) return STATUS_SUCCESS
;
5742 /* Allocate space for the context stack */
5743 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACTIVATION_CONTEXT_STACK
));
5746 return STATUS_NO_MEMORY
;
5749 /* Initialize the context stack */
5750 ContextStack
->Flags
= 0;
5751 ContextStack
->ActiveFrame
= NULL
;
5752 InitializeListHead(&ContextStack
->FrameListCache
);
5753 ContextStack
->NextCookieSequenceNumber
= 1;
5754 ContextStack
->StackId
= 1; //TODO: Timer-based
5756 *Stack
= ContextStack
;
5758 return STATUS_SUCCESS
;
5761 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5763 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
5766 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*NewFrame
;
5767 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*ActiveFrame
;
5769 /* Get the current active frame */
5770 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5772 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n",
5773 NtCurrentTeb()->ActivationContextStackPointer
, ActiveFrame
,
5774 &Frame
->Frame
, Context
);
5776 /* Ensure it's in the right format and at least fits basic info */
5777 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5778 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5780 /* Set debug info if size allows*/
5781 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5783 Frame
->Extra1
= (PVOID
)(~(ULONG_PTR
)ActiveFrame
);
5784 Frame
->Extra2
= (PVOID
)(~(ULONG_PTR
)Context
);
5785 //Frame->Extra3 = ...;
5790 /*ASSERT((ActiveFrame->Flags &
5791 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED |
5792 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED |
5793 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/
5795 if (!(ActiveFrame
->Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED
))
5797 // TODO: Perform some additional checks if it was not heap allocated
5801 /* Save pointer to the new activation frame */
5802 NewFrame
= &Frame
->Frame
;
5804 /* Actually activate it */
5805 Frame
->Frame
.Previous
= ActiveFrame
;
5806 Frame
->Frame
.ActivationContext
= Context
;
5807 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
;
5809 /* Check if we can activate this context */
5810 if ((ActiveFrame
&& (ActiveFrame
->ActivationContext
!= Context
)) ||
5813 /* Set new active frame */
5814 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame
, ActiveFrame
);
5815 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5819 /* We can get here only one way: it was already activated */
5820 DPRINT("Trying to activate already activated activation context\n");
5822 /* Activate only if we are allowing multiple activation */
5824 if (!RtlpNotAllowingMultipleActivation
)
5826 Frame
->Frame
.Flags
= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
| RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
;
5827 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5830 // Activate it anyway
5831 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
;
5834 /* Return pointer to the activation frame */
5838 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
5840 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
5842 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame
, NewFrame
;
5844 ActiveFrame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
5846 /* Ensure it's in the right format and at least fits basic info */
5847 ASSERT(Frame
->Format
== RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER
);
5848 ASSERT(Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC
));
5850 /* Make sure it is not deactivated and it is activated */
5851 ASSERT((Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
) == 0);
5852 ASSERT(Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED
);
5853 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
);
5855 /* Check debug info if it is present */
5856 if (Frame
->Size
>= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED
))
5858 ASSERT(Frame
->Extra1
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.Previous
));
5859 ASSERT(Frame
->Extra2
== (PVOID
)(~(ULONG_PTR
)Frame
->Frame
.ActivationContext
));
5860 //Frame->Extra3 = ...;
5865 // TODO: Perform some additional checks here
5868 /* Special handling for not-really-activated */
5869 if (Frame
->Frame
.Flags
& RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED
)
5871 DPRINT1("Deactivating not really activated activation context\n");
5872 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5873 return &Frame
->Frame
;
5876 /* find the right frame */
5877 NewFrame
= &Frame
->Frame
;
5878 if (ActiveFrame
!= NewFrame
)
5880 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame
, NewFrame
);
5883 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n",
5884 NtCurrentTeb()->ActivationContextStackPointer
, NewFrame
, NewFrame
->Previous
);
5886 /* Pop everything up to and including frame */
5887 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NewFrame
->Previous
;
5889 Frame
->Frame
.Flags
|= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED
;
5890 return NewFrame
->Previous
;