4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
33 #define WIN32_NO_STATUS
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx
);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
62 typedef enum tagLIBFLAGS
{
63 LIBFLAG_FRESTRICTED
= 0x1,
64 LIBFLAG_FCONTROL
= 0x2,
65 LIBFLAG_FHIDDEN
= 0x4,
66 LIBFLAG_FHASDISKIMAGE
= 0x8
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE
= 0x1,
73 OLEMISC_ONLYICONIC
= 0x2,
74 OLEMISC_INSERTNOTREPLACE
= 0x4,
76 OLEMISC_CANTLINKINSIDE
= 0x10,
77 OLEMISC_CANLINKBYOLE1
= 0x20,
78 OLEMISC_ISLINKOBJECT
= 0x40,
79 OLEMISC_INSIDEOUT
= 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE
= 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT
= 0x200,
82 OLEMISC_INVISIBLEATRUNTIME
= 0x400,
83 OLEMISC_ALWAYSRUN
= 0x800,
84 OLEMISC_ACTSLIKEBUTTON
= 0x1000,
85 OLEMISC_ACTSLIKELABEL
= 0x2000,
86 OLEMISC_NOUIACTIVATE
= 0x4000,
87 OLEMISC_ALIGNABLE
= 0x8000,
88 OLEMISC_SIMPLEFRAME
= 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST
= 0x20000,
90 OLEMISC_IMEMODE
= 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE
= 0x80000,
92 OLEMISC_WANTSTOMENUMERGE
= 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO
= 0x200000
114 struct assembly_version
122 struct assembly_identity
129 struct assembly_version version
;
133 struct strsection_header
145 ULONG hash
; /* key string hash */
148 ULONG data_offset
; /* redirect data offset */
153 struct guidsection_header
173 struct wndclass_redirect_data
178 ULONG name_offset
; /* versioned name offset */
180 ULONG module_offset
;/* container name offset */
183 struct dllredirect_data
190 struct tlibredirect_data
204 enum comclass_threadingmodel
206 ThreadingModel_Apartment
= 1,
207 ThreadingModel_Free
= 2,
208 ThreadingModel_No
= 3,
209 ThreadingModel_Both
= 4,
210 ThreadingModel_Neutral
= 5
213 enum comclass_miscfields
217 MiscStatusContent
= 4,
218 MiscStatusThumbnail
= 8,
219 MiscStatusDocPrint
= 16
226 Sections are accessible by string or guid key, that defines two types of sections.
227 All sections of each type have same magic value and header structure, index
228 data could be of two possible types too. So every string based section uses
229 the same index format, same applies to guid sections - they share same guid index
232 - window class redirection section is a plain buffer with following format:
236 <data[]> --- <original name>
241 Header is fixed length structure - struct strsection_header,
242 contains redirected classes count;
244 Index is an array of fixed length index records, each record is
247 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
249 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
250 others are relative to section itself.
252 - dll redirect section format:
256 <data[]> --- <dll name>
259 This section doesn't seem to carry any payload data except dll names.
261 - typelib section format:
269 Header is fixed length, index is an array of fixed length 'struct guid_index'.
270 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
271 4-bytes aligned as a whole.
273 Module name offsets are relative to section, helpstring offset is relative to data
297 DWORD miscstatuscontent
;
298 DWORD miscstatusthumbnail
;
299 DWORD miscstatusicon
;
300 DWORD miscstatusdocprint
;
328 unsigned int allocated
;
335 struct entity_array entities
;
340 APPLICATION_MANIFEST
,
342 ASSEMBLY_SHARED_MANIFEST
,
347 enum assembly_type type
;
348 struct assembly_identity id
;
349 struct file_info manifest
;
352 struct dll_redirect
*dlls
;
353 unsigned int num_dlls
;
354 unsigned int allocated_dlls
;
355 struct entity_array entities
;
358 enum context_sections
360 WINDOWCLASS_SECTION
= 1,
361 DLLREDIRECT_SECTION
= 2,
362 TLIBREDIRECT_SECTION
= 4
365 typedef struct _ACTIVATION_CONTEXT
369 struct file_info config
;
370 struct file_info appdir
;
371 struct assembly
*assemblies
;
372 unsigned int num_assemblies
;
373 unsigned int allocated_assemblies
;
376 struct strsection_header
*wndclass_section
;
377 struct strsection_header
*dllredirect_section
;
378 struct guidsection_header
*tlib_section
;
379 } ACTIVATION_CONTEXT
;
383 ACTIVATION_CONTEXT
*actctx
;
384 struct assembly_identity
*dependencies
;
385 unsigned int num_dependencies
;
386 unsigned int allocated_dependencies
;
389 static const WCHAR asmv1W
[] = {'a','s','m','v','1',':',0};
390 static const WCHAR asmv2W
[] = {'a','s','m','v','2',':',0};
391 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
392 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
393 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
394 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
395 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
396 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
397 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};
398 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};
399 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
400 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
401 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
402 static const WCHAR fileW
[] = {'f','i','l','e',0};
403 static const WCHAR hashW
[] = {'h','a','s','h',0};
404 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
405 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
406 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
407 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
409 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
410 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
411 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
412 static const WCHAR iidW
[] = {'i','i','d',0};
413 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
414 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
415 static const WCHAR nameW
[] = {'n','a','m','e',0};
416 static const WCHAR neutralW
[] = {'n','e','u','t','r','a','l',0};
417 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
418 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
419 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
420 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};
421 static const WCHAR progidW
[] = {'p','r','o','g','i','d',0};
422 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
423 static const WCHAR threadingmodelW
[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
424 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
425 static const WCHAR typeW
[] = {'t','y','p','e',0};
426 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
427 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
428 static const WCHAR versionedW
[] = {'v','e','r','s','i','o','n','e','d',0};
429 static const WCHAR yesW
[] = {'y','e','s',0};
430 static const WCHAR noW
[] = {'n','o',0};
431 static const WCHAR restrictedW
[] = {'R','E','S','T','R','I','C','T','E','D',0};
432 static const WCHAR controlW
[] = {'C','O','N','T','R','O','L',0};
433 static const WCHAR hiddenW
[] = {'H','I','D','D','E','N',0};
434 static const WCHAR hasdiskimageW
[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
435 static const WCHAR flagsW
[] = {'f','l','a','g','s',0};
436 static const WCHAR miscstatusW
[] = {'m','i','s','c','S','t','a','t','u','s',0};
437 static const WCHAR miscstatusiconW
[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
438 static const WCHAR miscstatuscontentW
[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
439 static const WCHAR miscstatusthumbnailW
[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
440 static const WCHAR miscstatusdocprintW
[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
442 static const WCHAR activatewhenvisibleW
[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
443 static const WCHAR actslikebuttonW
[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
444 static const WCHAR actslikelabelW
[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
445 static const WCHAR alignableW
[] = {'a','l','i','g','n','a','b','l','e',0};
446 static const WCHAR alwaysrunW
[] = {'a','l','w','a','y','s','r','u','n',0};
447 static const WCHAR canlinkbyole1W
[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
448 static const WCHAR cantlinkinsideW
[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
449 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};
450 static const WCHAR imemodeW
[] = {'i','m','e','m','o','d','e',0};
451 static const WCHAR insertnotreplaceW
[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
452 static const WCHAR insideoutW
[] = {'i','n','s','i','d','e','o','u','t',0};
453 static const WCHAR invisibleatruntimeW
[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
454 static const WCHAR islinkobjectW
[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
455 static const WCHAR nouiactivateW
[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
456 static const WCHAR onlyiconicW
[] = {'o','n','l','y','i','c','o','n','i','c',0};
457 static const WCHAR recomposeonresizeW
[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
458 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};
459 static const WCHAR setclientsitefirstW
[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
460 static const WCHAR simpleframeW
[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
461 static const WCHAR staticW
[] = {'s','t','a','t','i','c',0};
462 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};
463 static const WCHAR wantstomenumergeW
[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
471 static const struct olemisc_entry olemisc_values
[] =
473 { activatewhenvisibleW
, OLEMISC_ACTIVATEWHENVISIBLE
},
474 { actslikebuttonW
, OLEMISC_ACTSLIKEBUTTON
},
475 { actslikelabelW
, OLEMISC_ACTSLIKELABEL
},
476 { alignableW
, OLEMISC_ALIGNABLE
},
477 { alwaysrunW
, OLEMISC_ALWAYSRUN
},
478 { canlinkbyole1W
, OLEMISC_CANLINKBYOLE1
},
479 { cantlinkinsideW
, OLEMISC_CANTLINKINSIDE
},
480 { ignoreactivatewhenvisibleW
, OLEMISC_IGNOREACTIVATEWHENVISIBLE
},
481 { imemodeW
, OLEMISC_IMEMODE
},
482 { insertnotreplaceW
, OLEMISC_INSERTNOTREPLACE
},
483 { insideoutW
, OLEMISC_INSIDEOUT
},
484 { invisibleatruntimeW
, OLEMISC_INVISIBLEATRUNTIME
},
485 { islinkobjectW
, OLEMISC_ISLINKOBJECT
},
486 { nouiactivateW
, OLEMISC_NOUIACTIVATE
},
487 { onlyiconicW
, OLEMISC_ONLYICONIC
},
488 { recomposeonresizeW
, OLEMISC_RECOMPOSEONRESIZE
},
489 { renderingisdeviceindependentW
, OLEMISC_RENDERINGISDEVICEINDEPENDENT
},
490 { setclientsitefirstW
, OLEMISC_SETCLIENTSITEFIRST
},
491 { simpleframeW
, OLEMISC_SIMPLEFRAME
},
492 { staticW
, OLEMISC_STATIC
},
493 { supportsmultilevelundoW
, OLEMISC_SUPPORTSMULTILEVELUNDO
},
494 { wantstomenumergeW
, OLEMISC_WANTSTOMENUMERGE
}
497 static const WCHAR xmlW
[] = {'?','x','m','l',0};
498 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};
499 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};
501 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
502 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
503 static const WCHAR wildcardW
[] = {'*',0};
505 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
506 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
508 static WCHAR
*strdupW(const WCHAR
* str
)
512 if (!(ptr
= RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
514 return strcpyW(ptr
, str
);
517 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
521 if ((strW
= RtlAllocateHeap(GetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
523 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
529 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
531 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
534 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
536 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
539 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
541 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
542 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
545 static inline BOOL
xml_elem_cmp(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
547 UINT len
= strlenW( namespace );
549 if (!strncmpW(elem
->ptr
, str
, elem
->len
) && !str
[elem
->len
]) return TRUE
;
550 return (elem
->len
> len
&& !strncmpW(elem
->ptr
, namespace, len
) &&
551 !strncmpW(elem
->ptr
+ len
, str
, elem
->len
- len
) && !str
[elem
->len
- len
]);
554 static inline BOOL
xml_elem_cmp_end(const xmlstr_t
*elem
, const WCHAR
*str
, const WCHAR
*namespace)
556 if (elem
->len
&& elem
->ptr
[0] == '/')
559 elem_end
.ptr
= elem
->ptr
+ 1;
560 elem_end
.len
= elem
->len
- 1;
561 return xml_elem_cmp( &elem_end
, str
, namespace );
566 static inline BOOL
isxmlspace( WCHAR ch
)
568 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
571 static inline const char* debugstr_xmlstr(const xmlstr_t
* str
)
573 return debugstr_wn(str
->ptr
, str
->len
);
576 static inline const char* debugstr_version(const struct assembly_version
*ver
)
578 return wine_dbg_sprintf("%u.%u.%u.%u", ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
581 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
583 struct assembly
*assembly
;
585 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
588 unsigned int new_count
;
589 if (actctx
->assemblies
)
591 new_count
= actctx
->allocated_assemblies
* 2;
592 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
593 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
598 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
600 if (!ptr
) return NULL
;
601 actctx
->assemblies
= ptr
;
602 actctx
->allocated_assemblies
= new_count
;
605 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
610 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
612 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
615 unsigned int new_count
;
618 new_count
= assembly
->allocated_dlls
* 2;
619 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
620 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
625 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
627 if (!ptr
) return NULL
;
628 assembly
->dlls
= ptr
;
629 assembly
->allocated_dlls
= new_count
;
631 return &assembly
->dlls
[assembly
->num_dlls
++];
634 static void free_assembly_identity(struct assembly_identity
*ai
)
636 RtlFreeHeap( GetProcessHeap(), 0, ai
->name
);
637 RtlFreeHeap( GetProcessHeap(), 0, ai
->arch
);
638 RtlFreeHeap( GetProcessHeap(), 0, ai
->public_key
);
639 RtlFreeHeap( GetProcessHeap(), 0, ai
->language
);
640 RtlFreeHeap( GetProcessHeap(), 0, ai
->type
);
643 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
645 struct entity
* entity
;
647 if (array
->num
== array
->allocated
)
650 unsigned int new_count
;
653 new_count
= array
->allocated
* 2;
654 ptr
= RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
,
655 array
->base
, new_count
* sizeof(*array
->base
) );
660 ptr
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
662 if (!ptr
) return NULL
;
664 array
->allocated
= new_count
;
666 entity
= &array
->base
[array
->num
++];
671 static void free_entity_array(struct entity_array
*array
)
674 for (i
= 0; i
< array
->num
; i
++)
676 struct entity
*entity
= &array
->base
[i
];
677 switch (entity
->kind
)
679 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
680 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
681 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.tlbid
);
682 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.comclass
.progid
);
684 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
685 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.proxy
.iid
);
686 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.proxy
.name
);
688 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
689 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
690 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
692 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
693 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.class.name
);
695 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
696 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrclass
.name
);
697 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrclass
.clsid
);
699 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
700 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
701 RtlFreeHeap(GetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
704 FIXME("Unknown entity kind %d\n", entity
->kind
);
707 RtlFreeHeap( GetProcessHeap(), 0, array
->base
);
710 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
712 if (!str1
) return !str2
;
713 return str2
&& !strcmpiW( str1
, str2
);
716 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
717 const struct assembly_identity
*id2
)
719 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
720 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
721 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
723 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
725 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
728 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
729 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
730 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
731 if (id1
->version
.build
== id2
->version
.build
&&
732 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
736 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
737 struct assembly_identity
* ai
)
741 /* check if we already have that assembly */
743 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
744 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
746 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
747 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
748 ai
->version
.build
, ai
->version
.revision
);
752 for (i
= 0; i
< acl
->num_dependencies
; i
++)
753 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
755 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
756 debugstr_w(ai
->name
), debugstr_w(ai
->arch
), ai
->version
.major
, ai
->version
.minor
,
757 ai
->version
.build
, ai
->version
.revision
);
761 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
764 unsigned int new_count
;
765 if (acl
->dependencies
)
767 new_count
= acl
->allocated_dependencies
* 2;
768 ptr
= RtlReAllocateHeap(GetProcessHeap(), 0, acl
->dependencies
,
769 new_count
* sizeof(acl
->dependencies
[0]));
774 ptr
= RtlAllocateHeap(GetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
776 if (!ptr
) return FALSE
;
777 acl
->dependencies
= ptr
;
778 acl
->allocated_dependencies
= new_count
;
780 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
785 static void free_depend_manifests(struct actctx_loader
* acl
)
788 for (i
= 0; i
< acl
->num_dependencies
; i
++)
789 free_assembly_identity(&acl
->dependencies
[i
]);
790 RtlFreeHeap(GetProcessHeap(), 0, acl
->dependencies
);
793 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
795 static const WCHAR undW
[] = {'_',0};
796 static const WCHAR noneW
[] = {'n','o','n','e',0};
797 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
799 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
800 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
801 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
802 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
803 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
804 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
807 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, size
))) return NULL
;
809 strcpyW( ret
, arch
);
810 strcatW( ret
, undW
);
811 strcatW( ret
, name
);
812 strcatW( ret
, undW
);
814 strcatW( ret
, undW
);
815 sprintfW( ret
+ strlenW(ret
), version_formatW
,
816 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
817 strcatW( ret
, undW
);
818 strcatW( ret
, lang
);
819 strcatW( ret
, undW
);
820 strcatW( ret
, mskeyW
);
824 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
829 strcatW( buffer
, prefix
);
838 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
840 static const WCHAR archW
[] =
841 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
842 static const WCHAR public_keyW
[] =
843 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
844 static const WCHAR typeW
[] =
845 {',','t','y','p','e','=',0};
846 static const WCHAR versionW
[] =
847 {',','v','e','r','s','i','o','n','=',0};
849 WCHAR version
[64], *ret
;
852 sprintfW( version
, version_formatW
,
853 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
854 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
855 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
856 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
857 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
858 size
+= strlenW(versionW
) + strlenW(version
) + 2;
860 if (!(ret
= RtlAllocateHeap( GetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
863 if (ai
->name
) strcpyW( ret
, ai
->name
);
865 append_string( ret
, archW
, ai
->arch
);
866 append_string( ret
, public_keyW
, ai
->public_key
);
867 append_string( ret
, typeW
, ai
->type
);
868 append_string( ret
, versionW
, version
);
872 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
874 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
876 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
879 if (actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
888 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
890 interlocked_xchg_add( &actctx
->ref_count
, 1 );
893 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
895 if (interlocked_xchg_add( &actctx
->ref_count
, -1 ) == 1)
899 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
901 struct assembly
*assembly
= &actctx
->assemblies
[i
];
902 for (j
= 0; j
< assembly
->num_dlls
; j
++)
904 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
905 free_entity_array( &dll
->entities
);
906 RtlFreeHeap( GetProcessHeap(), 0, dll
->name
);
907 RtlFreeHeap( GetProcessHeap(), 0, dll
->hash
);
909 RtlFreeHeap( GetProcessHeap(), 0, assembly
->dlls
);
910 RtlFreeHeap( GetProcessHeap(), 0, assembly
->manifest
.info
);
911 RtlFreeHeap( GetProcessHeap(), 0, assembly
->directory
);
912 free_entity_array( &assembly
->entities
);
913 free_assembly_identity(&assembly
->id
);
915 RtlFreeHeap( GetProcessHeap(), 0, actctx
->config
.info
);
916 RtlFreeHeap( GetProcessHeap(), 0, actctx
->appdir
.info
);
917 RtlFreeHeap( GetProcessHeap(), 0, actctx
->assemblies
);
918 RtlFreeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
919 RtlFreeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
921 RtlFreeHeap( GetProcessHeap(), 0, actctx
);
925 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
926 BOOL
* error
, BOOL
* end
)
932 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
935 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
937 if (*xmlbuf
->ptr
== '/')
940 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
949 if (*xmlbuf
->ptr
== '>')
957 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
959 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
961 name
->ptr
= xmlbuf
->ptr
;
962 name
->len
= ptr
-xmlbuf
->ptr
;
966 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
969 if (ptr
== xmlbuf
->end
) return FALSE
;
971 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
974 xmlbuf
->ptr
= xmlbuf
->end
;
978 value
->len
= ptr
- value
->ptr
;
979 xmlbuf
->ptr
= ptr
+ 1;
981 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
987 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
993 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
996 xmlbuf
->ptr
= xmlbuf
->end
;
1000 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
1002 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
1003 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
1005 if (ptr
+ 3 > xmlbuf
->end
)
1007 xmlbuf
->ptr
= xmlbuf
->end
;
1010 xmlbuf
->ptr
= ptr
+ 3;
1016 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
1019 elem
->ptr
= xmlbuf
->ptr
;
1020 elem
->len
= ptr
- xmlbuf
->ptr
;
1022 return xmlbuf
->ptr
!= xmlbuf
->end
;
1025 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
1027 /* FIXME: parse attributes */
1030 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
1032 if (ptr
[0] == '?' && ptr
[1] == '>')
1034 xmlbuf
->ptr
= ptr
+ 2;
1041 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
1043 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
1045 if (!ptr
) return FALSE
;
1047 content
->ptr
= xmlbuf
->ptr
;
1048 content
->len
= ptr
- xmlbuf
->ptr
;
1054 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
1056 unsigned int ver
[4];
1060 /* major.minor.build.revision */
1061 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
1062 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1064 if (*curr
>= '0' && *curr
<= '9')
1066 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1067 if (ver
[pos
] >= 0x10000) goto error
;
1069 else if (*curr
== '.')
1071 if (++pos
>= 4) goto error
;
1075 version
->major
= ver
[0];
1076 version
->minor
= ver
[1];
1077 version
->build
= ver
[2];
1078 version
->revision
= ver
[3];
1082 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str
) );
1086 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
, const WCHAR
*namespace)
1089 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1090 if (xml_elem_cmp(&elem
, name
, namespace)) return TRUE
;
1091 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1095 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
1097 xmlstr_t attr_name
, attr_value
;
1100 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
1102 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1103 debugstr_xmlstr(&attr_value
));
1108 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
1111 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
1114 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
, const WCHAR
*namespace)
1117 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1118 if (!xml_elem_cmp_end(&elem
, name
, namespace))
1120 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem
) );
1123 return parse_end_element(xmlbuf
);
1126 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
1128 xmlstr_t attr_name
, attr_value
, elem
;
1129 BOOL end
= FALSE
, error
, ret
= TRUE
;
1131 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
1132 if(error
|| end
) return end
;
1134 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1136 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
1137 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
1140 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1143 return ret
&& parse_end_element(xmlbuf
);
1146 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
1147 struct assembly_identity
* ai
)
1149 xmlstr_t attr_name
, attr_value
;
1150 BOOL end
= FALSE
, error
;
1152 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1154 if (xmlstr_cmp(&attr_name
, nameW
))
1156 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1158 else if (xmlstr_cmp(&attr_name
, typeW
))
1160 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
1162 else if (xmlstr_cmp(&attr_name
, versionW
))
1164 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
1166 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
1168 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
1170 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
1172 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
1174 else if (xmlstr_cmp(&attr_name
, languageW
))
1176 WARN("Unsupported yet language attribute (%s)\n",
1177 debugstr_xmlstr(&attr_value
));
1178 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
1182 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
),
1183 debugstr_xmlstr(&attr_value
));
1187 TRACE( "name=%s version=%s arch=%s\n",
1188 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
1190 if (error
|| end
) return end
;
1191 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
, asmv1W
);
1194 static enum comclass_threadingmodel
parse_com_class_threadingmodel(xmlstr_t
*value
)
1196 static const WCHAR apartW
[] = {'A','p','a','r','t','m','e','n','t',0};
1197 static const WCHAR neutralW
[] = {'N','e','u','t','r','a','l',0};
1198 static const WCHAR freeW
[] = {'F','r','e','e',0};
1199 static const WCHAR bothW
[] = {'B','o','t','h',0};
1201 if (value
->len
== 0) return ThreadingModel_No
;
1202 if (xmlstr_cmp(value
, apartW
))
1203 return ThreadingModel_Apartment
;
1204 else if (xmlstr_cmp(value
, freeW
))
1205 return ThreadingModel_Free
;
1206 else if (xmlstr_cmp(value
, bothW
))
1207 return ThreadingModel_Both
;
1208 else if (xmlstr_cmp(value
, neutralW
))
1209 return ThreadingModel_Neutral
;
1211 return ThreadingModel_No
;
1214 static OLEMISC
get_olemisc_value(const WCHAR
*str
, int len
)
1219 max
= sizeof(olemisc_values
)/sizeof(struct olemisc_entry
) - 1;
1227 c
= strncmpW(olemisc_values
[n
].name
, str
, len
);
1228 if (!c
&& !olemisc_values
[n
].name
[len
])
1229 return olemisc_values
[n
].value
;
1237 WARN("unknown flag %s\n", debugstr_wn(str
, len
));
1241 static DWORD
parse_com_class_misc(const xmlstr_t
*value
)
1243 const WCHAR
*str
= value
->ptr
, *start
;
1247 /* it's comma separated list of flags */
1248 while (i
< value
->len
)
1251 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1253 flags
|= get_olemisc_value(start
, str
-start
);
1255 /* skip separator */
1263 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
1265 xmlstr_t elem
, attr_name
, attr_value
;
1266 BOOL ret
, end
= FALSE
, error
;
1267 struct entity
* entity
;
1269 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
1272 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1274 if (xmlstr_cmp(&attr_name
, clsidW
))
1276 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1278 else if (xmlstr_cmp(&attr_name
, progidW
))
1280 if (!(entity
->u
.comclass
.progid
= xmlstrdupW(&attr_value
))) return FALSE
;
1282 else if (xmlstr_cmp(&attr_name
, tlbidW
))
1284 if (!(entity
->u
.comclass
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1286 else if (xmlstr_cmp(&attr_name
, threadingmodelW
))
1288 entity
->u
.comclass
.model
= parse_com_class_threadingmodel(&attr_value
);
1290 else if (xmlstr_cmp(&attr_name
, miscstatusW
))
1292 entity
->u
.comclass
.miscstatus
= parse_com_class_misc(&attr_value
);
1294 else if (xmlstr_cmp(&attr_name
, miscstatuscontentW
))
1296 entity
->u
.comclass
.miscstatuscontent
= parse_com_class_misc(&attr_value
);
1298 else if (xmlstr_cmp(&attr_name
, miscstatusthumbnailW
))
1300 entity
->u
.comclass
.miscstatusthumbnail
= parse_com_class_misc(&attr_value
);
1302 else if (xmlstr_cmp(&attr_name
, miscstatusiconW
))
1304 entity
->u
.comclass
.miscstatusicon
= parse_com_class_misc(&attr_value
);
1306 else if (xmlstr_cmp(&attr_name
, miscstatusdocprintW
))
1308 entity
->u
.comclass
.miscstatusdocprint
= parse_com_class_misc(&attr_value
);
1312 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1316 if (error
|| end
) return end
;
1318 while ((ret
= next_xml_elem(xmlbuf
, &elem
)))
1320 if (xmlstr_cmp_end(&elem
, comClassW
))
1322 ret
= parse_end_element(xmlbuf
);
1327 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1328 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1334 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
1336 xmlstr_t attr_name
, attr_value
;
1337 BOOL end
= FALSE
, error
;
1338 struct entity
* entity
;
1340 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
1343 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1345 if (xmlstr_cmp(&attr_name
, iidW
))
1347 if (!(entity
->u
.proxy
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1349 if (xmlstr_cmp(&attr_name
, nameW
))
1351 if (!(entity
->u
.proxy
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1355 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1359 if (error
|| end
) return end
;
1360 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
, asmv1W
);
1363 static BOOL
parse_typelib_flags(const xmlstr_t
*value
, struct entity
*entity
)
1365 WORD
*flags
= &entity
->u
.typelib
.flags
;
1366 const WCHAR
*str
= value
->ptr
, *start
;
1371 /* it's comma separated list of flags */
1372 while (i
< value
->len
)
1375 while (*str
!= ',' && (i
++ < value
->len
)) str
++;
1377 if (!strncmpW(start
, restrictedW
, str
-start
))
1378 *flags
|= LIBFLAG_FRESTRICTED
;
1379 else if (!strncmpW(start
, controlW
, str
-start
))
1380 *flags
|= LIBFLAG_FCONTROL
;
1381 else if (!strncmpW(start
, hiddenW
, str
-start
))
1382 *flags
|= LIBFLAG_FHIDDEN
;
1383 else if (!strncmpW(start
, hasdiskimageW
, str
-start
))
1384 *flags
|= LIBFLAG_FHASDISKIMAGE
;
1387 WARN("unknown flags value %s\n", debugstr_xmlstr(value
));
1391 /* skip separator */
1399 static BOOL
parse_typelib_version(const xmlstr_t
*str
, struct entity
*entity
)
1401 unsigned int ver
[2];
1406 ver
[0] = ver
[1] = pos
= 0;
1407 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
1409 if (*curr
>= '0' && *curr
<= '9')
1411 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
1412 if (ver
[pos
] >= 0x10000) goto error
;
1414 else if (*curr
== '.')
1416 if (++pos
>= 2) goto error
;
1420 entity
->u
.typelib
.major
= ver
[0];
1421 entity
->u
.typelib
.minor
= ver
[1];
1425 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str
));
1429 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1431 xmlstr_t attr_name
, attr_value
;
1432 BOOL end
= FALSE
, error
;
1433 struct entity
* entity
;
1435 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
1438 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1440 if (xmlstr_cmp(&attr_name
, tlbidW
))
1442 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
1444 else if (xmlstr_cmp(&attr_name
, versionW
))
1446 if (!parse_typelib_version(&attr_value
, entity
)) return FALSE
;
1448 else if (xmlstr_cmp(&attr_name
, helpdirW
))
1450 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
1452 else if (xmlstr_cmp(&attr_name
, flagsW
))
1454 if (!parse_typelib_flags(&attr_value
, entity
)) return FALSE
;
1458 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1462 if (error
) return FALSE
;
1464 acl
->actctx
->sections
|= TLIBREDIRECT_SECTION
;
1466 if (end
) return TRUE
;
1468 return parse_expect_end_elem(xmlbuf
, typelibW
, asmv1W
);
1471 static inline int aligned_string_len(int len
)
1473 return (len
+ 3) & ~3;
1476 static int get_assembly_version(struct assembly
*assembly
, WCHAR
*ret
)
1478 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1479 struct assembly_version
*ver
= &assembly
->id
.version
;
1482 if (!ret
) ret
= buff
;
1483 return sprintfW(ret
, fmtW
, ver
->major
, ver
->minor
, ver
->build
, ver
->revision
);
1486 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
, struct actctx_loader
* acl
)
1488 xmlstr_t elem
, content
, attr_name
, attr_value
;
1489 BOOL end
= FALSE
, ret
= TRUE
, error
;
1490 struct entity
* entity
;
1492 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
1495 entity
->u
.class.versioned
= TRUE
;
1496 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1498 if (xmlstr_cmp(&attr_name
, versionedW
))
1500 if (xmlstr_cmpi(&attr_value
, noW
))
1501 entity
->u
.class.versioned
= FALSE
;
1502 else if (!xmlstr_cmpi(&attr_value
, yesW
))
1507 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1511 if (error
|| end
) return end
;
1513 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
1515 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
1517 acl
->actctx
->sections
|= WINDOWCLASS_SECTION
;
1519 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1521 if (xmlstr_cmp_end(&elem
, windowClassW
))
1523 ret
= parse_end_element(xmlbuf
);
1528 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1529 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1536 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1538 xmlstr_t attr_name
, attr_value
;
1539 BOOL end
= FALSE
, error
;
1541 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1543 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1545 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value
));
1547 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1549 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value
));
1553 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1557 if (error
|| end
) return end
;
1558 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
, asmv1W
);
1561 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1563 xmlstr_t elem
, content
;
1564 BOOL end
= FALSE
, ret
= TRUE
;
1566 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
||
1567 !parse_text_content(xmlbuf
, &content
))
1570 TRACE("Got description %s\n", debugstr_xmlstr(&content
));
1572 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1574 if (xmlstr_cmp_end(&elem
, descriptionW
))
1576 ret
= parse_end_element(xmlbuf
);
1581 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1582 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1589 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1590 struct assembly
* assembly
)
1592 xmlstr_t attr_name
, attr_value
;
1593 BOOL end
= FALSE
, error
;
1594 struct entity
* entity
;
1596 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1597 if (!entity
) return FALSE
;
1599 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1601 if (xmlstr_cmp(&attr_name
, iidW
))
1603 if (!(entity
->u
.proxy
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1605 if (xmlstr_cmp(&attr_name
, nameW
))
1607 if (!(entity
->u
.proxy
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1611 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1615 if (error
|| end
) return end
;
1616 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
, asmv1W
);
1619 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
)
1621 xmlstr_t attr_name
, attr_value
;
1622 BOOL end
= FALSE
, error
;
1623 struct entity
* entity
;
1625 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
);
1626 if (!entity
) return FALSE
;
1628 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1630 if (xmlstr_cmp(&attr_name
, nameW
))
1632 if (!(entity
->u
.clrclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1634 else if (xmlstr_cmp(&attr_name
, clsidW
))
1636 if (!(entity
->u
.clrclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1640 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1644 if (error
|| end
) return end
;
1645 return parse_expect_end_elem(xmlbuf
, clrClassW
, asmv1W
);
1648 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
)
1650 xmlstr_t attr_name
, attr_value
;
1651 BOOL end
= FALSE
, error
;
1652 struct entity
* entity
;
1654 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
1655 if (!entity
) return FALSE
;
1657 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1659 if (xmlstr_cmp(&attr_name
, nameW
))
1661 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1663 else if (xmlstr_cmp(&attr_name
, clsidW
))
1665 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1669 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1673 if (error
|| end
) return end
;
1674 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
, asmv1W
);
1677 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
1679 struct assembly_identity ai
;
1681 BOOL end
= FALSE
, ret
= TRUE
;
1683 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
) return end
;
1685 memset(&ai
, 0, sizeof(ai
));
1686 ai
.optional
= optional
;
1688 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
, asmv1W
) ||
1689 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
1692 TRACE( "adding name=%s version=%s arch=%s\n",
1693 debugstr_w(ai
.name
), debugstr_version(&ai
.version
), debugstr_w(ai
.arch
) );
1695 /* store the newly found identity for later loading */
1696 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
1698 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1700 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
1702 ret
= parse_end_element(xmlbuf
);
1705 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
1707 ret
= parse_binding_redirect_elem(xmlbuf
);
1711 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1712 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1719 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
1721 xmlstr_t attr_name
, attr_value
, elem
;
1722 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
1724 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1726 if (xmlstr_cmp(&attr_name
, optionalW
))
1728 optional
= xmlstr_cmpi( &attr_value
, yesW
);
1729 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value
));
1733 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1737 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1739 if (xmlstr_cmp_end(&elem
, dependencyW
))
1741 ret
= parse_end_element(xmlbuf
);
1744 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
1746 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
1750 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
1751 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1758 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
1762 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
1763 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
, asmv1W
);
1766 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
1770 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
1771 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
, asmv1W
);
1774 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
, struct actctx_loader
* acl
)
1776 xmlstr_t attr_name
, attr_value
, elem
;
1777 BOOL end
= FALSE
, error
, ret
= TRUE
;
1778 struct dll_redirect
* dll
;
1780 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
1782 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1784 if (xmlstr_cmp(&attr_name
, nameW
))
1786 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1787 TRACE("name=%s\n", debugstr_xmlstr(&attr_value
));
1789 else if (xmlstr_cmp(&attr_name
, hashW
))
1791 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
1793 else if (xmlstr_cmp(&attr_name
, hashalgW
))
1795 static const WCHAR sha1W
[] = {'S','H','A','1',0};
1796 if (!xmlstr_cmpi(&attr_value
, sha1W
))
1797 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value
));
1801 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1805 if (error
|| !dll
->name
) return FALSE
;
1807 acl
->actctx
->sections
|= DLLREDIRECT_SECTION
;
1809 if (end
) return TRUE
;
1811 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1813 if (xmlstr_cmp_end(&elem
, fileW
))
1815 ret
= parse_end_element(xmlbuf
);
1818 else if (xmlstr_cmp(&elem
, comClassW
))
1820 ret
= parse_com_class_elem(xmlbuf
, dll
);
1822 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
1824 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
);
1826 else if (xml_elem_cmp(&elem
, hashW
, asmv2W
))
1828 WARN("asmv2:hash (undocumented) not supported\n");
1829 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1831 else if (xmlstr_cmp(&elem
, typelibW
))
1833 ret
= parse_typelib_elem(xmlbuf
, dll
, acl
);
1835 else if (xmlstr_cmp(&elem
, windowClassW
))
1837 ret
= parse_window_class_elem(xmlbuf
, dll
, acl
);
1841 WARN("unknown elem %s\n", debugstr_xmlstr(&elem
));
1842 ret
= parse_unknown_elem( xmlbuf
, &elem
);
1849 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
1850 struct assembly
* assembly
,
1851 struct assembly_identity
* expected_ai
)
1853 xmlstr_t attr_name
, attr_value
, elem
;
1854 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
1856 TRACE("(%p)\n", xmlbuf
);
1858 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1860 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
1862 static const WCHAR v10W
[] = {'1','.','0',0};
1863 if (!xmlstr_cmp(&attr_value
, v10W
))
1865 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value
));
1870 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
1872 if (!xmlstr_cmp(&attr_value
, manifestv1W
) && !xmlstr_cmp(&attr_value
, manifestv3W
))
1874 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value
));
1881 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name
), debugstr_xmlstr(&attr_value
));
1885 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
1886 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1888 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
1890 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
1892 assembly
->no_inherit
= TRUE
;
1895 if (xml_elem_cmp(&elem
, noInheritableW
, asmv1W
))
1897 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
1900 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
1901 assembly
->no_inherit
)
1906 if (xml_elem_cmp_end(&elem
, assemblyW
, asmv1W
))
1908 ret
= parse_end_element(xmlbuf
);
1911 else if (xml_elem_cmp(&elem
, descriptionW
, asmv1W
))
1913 ret
= parse_description_elem(xmlbuf
);
1915 else if (xml_elem_cmp(&elem
, comInterfaceExternalProxyStubW
, asmv1W
))
1917 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
);
1919 else if (xml_elem_cmp(&elem
, dependencyW
, asmv1W
))
1921 ret
= parse_dependency_elem(xmlbuf
, acl
);
1923 else if (xml_elem_cmp(&elem
, fileW
, asmv1W
))
1925 ret
= parse_file_elem(xmlbuf
, assembly
, acl
);
1927 else if (xml_elem_cmp(&elem
, clrClassW
, asmv1W
))
1929 ret
= parse_clr_class_elem(xmlbuf
, assembly
);
1931 else if (xml_elem_cmp(&elem
, clrSurrogateW
, asmv1W
))
1933 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
);
1935 else if (xml_elem_cmp(&elem
, assemblyIdentityW
, asmv1W
))
1937 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
1941 /* FIXME: more tests */
1942 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
1943 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
1945 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
1946 expected_ai
->version
.major
, expected_ai
->version
.minor
,
1947 expected_ai
->version
.build
, expected_ai
->version
.revision
,
1948 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
1949 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
1952 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
1953 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
1954 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
1955 assembly
->id
.version
.build
< expected_ai
->version
.build
||
1956 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
1957 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
1959 FIXME("wrong version for shared assembly manifest\n");
1966 WARN("unknown element %s\n", debugstr_xmlstr(&elem
));
1967 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1969 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
1975 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
1976 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
1980 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
1982 if (xmlstr_cmp(&elem
, xmlW
) &&
1983 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
1984 return STATUS_SXS_CANT_GEN_ACTCTX
;
1986 if (!xml_elem_cmp(&elem
, assemblyW
, asmv1W
))
1988 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem
));
1989 return STATUS_SXS_CANT_GEN_ACTCTX
;
1992 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
1994 FIXME("failed to parse manifest %s\n", debugstr_w(assembly
->manifest
.info
) );
1995 return STATUS_SXS_CANT_GEN_ACTCTX
;
1998 if (next_xml_elem(xmlbuf
, &elem
))
2000 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem
));
2001 return STATUS_SXS_CANT_GEN_ACTCTX
;
2004 if (xmlbuf
->ptr
!= xmlbuf
->end
)
2006 FIXME("parse error\n");
2007 return STATUS_SXS_CANT_GEN_ACTCTX
;
2009 return STATUS_SUCCESS
;
2012 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2013 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2014 const void *buffer
, SIZE_T size
)
2018 struct assembly
*assembly
;
2021 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename
), debugstr_w(directory
) );
2023 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
2024 return STATUS_SXS_CANT_GEN_ACTCTX
;
2026 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
2027 return STATUS_NO_MEMORY
;
2029 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
2030 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2031 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2033 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
2034 if (RtlIsTextUnicode( buffer
, size
, &unicode_tests
))
2036 xmlbuf
.ptr
= buffer
;
2037 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2038 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2040 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
2042 const WCHAR
*buf
= buffer
;
2046 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
2047 return STATUS_NO_MEMORY
;
2048 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
2049 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
2050 xmlbuf
.ptr
= new_buff
;
2051 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
2052 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2053 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2057 /* let's assume utf-8 for now */
2058 int len
= wine_utf8_mbstowcs( 0, buffer
, size
, NULL
, 0 );
2063 FIXME( "utf-8 conversion failed\n" );
2064 return STATUS_SXS_CANT_GEN_ACTCTX
;
2066 if (!(new_buff
= RtlAllocateHeap( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
2067 return STATUS_NO_MEMORY
;
2068 wine_utf8_mbstowcs( 0, buffer
, size
, new_buff
, len
);
2069 xmlbuf
.ptr
= new_buff
;
2070 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
2071 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
2072 RtlFreeHeap( GetProcessHeap(), 0, new_buff
);
2077 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
2079 OBJECT_ATTRIBUTES attr
;
2082 attr
.Length
= sizeof(attr
);
2083 attr
.RootDirectory
= 0;
2084 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2085 attr
.ObjectName
= name
;
2086 attr
.SecurityDescriptor
= NULL
;
2087 attr
.SecurityQualityOfService
= NULL
;
2088 return NtOpenFile( handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
2091 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
2097 LdrLockLoaderLock(0, NULL
, &magic
);
2098 status
= LdrFindEntryForAddress( module
, &pldr
);
2099 if (status
== STATUS_SUCCESS
)
2101 if ((str
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2102 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
2104 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
2105 str
->Length
= pldr
->FullDllName
.Length
;
2106 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
2108 else status
= STATUS_NO_MEMORY
;
2110 LdrUnlockLoaderLock(0, magic
);
2114 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2115 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2116 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
2119 UNICODE_STRING nameW
;
2120 LDR_RESOURCE_INFO info
;
2121 const IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
2124 if (TRACE_ON(actctx
))
2126 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
2128 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2129 hModule
, debugstr_w(nameW
.Buffer
) );
2130 RtlFreeUnicodeString( &nameW
);
2132 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname
),
2133 hModule
, debugstr_w(filename
) );
2136 if (!resname
) return STATUS_INVALID_PARAMETER
;
2138 info
.Type
= RT_MANIFEST
;
2139 info
.Language
= lang
;
2140 if (!((ULONG_PTR
)resname
>> 16))
2142 info
.Name
= (ULONG_PTR
)resname
;
2143 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2145 else if (resname
[0] == '#')
2148 RtlInitUnicodeString(&nameW
, resname
+ 1);
2149 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
2150 return STATUS_INVALID_PARAMETER
;
2152 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2156 RtlCreateUnicodeString(&nameW
, resname
);
2157 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
2158 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
2159 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
2160 RtlFreeUnicodeString(&nameW
);
2162 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
2164 if (status
== STATUS_SUCCESS
)
2165 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
2170 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2171 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
2172 HANDLE file
, LPCWSTR resname
, ULONG lang
)
2175 OBJECT_ATTRIBUTES attr
;
2177 LARGE_INTEGER offset
;
2182 TRACE( "looking for res %s in %s\n", debugstr_w(resname
), debugstr_w(filename
) );
2184 attr
.Length
= sizeof(attr
);
2185 attr
.RootDirectory
= 0;
2186 attr
.ObjectName
= NULL
;
2187 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2188 attr
.SecurityDescriptor
= NULL
;
2189 attr
.SecurityQualityOfService
= NULL
;
2192 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2193 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2194 if (status
!= STATUS_SUCCESS
) return status
;
2196 offset
.QuadPart
= 0;
2199 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2200 &count
, ViewShare
, 0, PAGE_READONLY
);
2202 if (status
!= STATUS_SUCCESS
) return status
;
2204 if (RtlImageNtHeader(base
)) /* we got a PE file */
2206 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2207 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
2209 else status
= STATUS_INVALID_IMAGE_FORMAT
;
2211 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2215 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2216 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
2218 FILE_END_OF_FILE_INFORMATION info
;
2221 OBJECT_ATTRIBUTES attr
;
2223 LARGE_INTEGER offset
;
2228 TRACE( "loading manifest file %s\n", debugstr_w(filename
) );
2230 attr
.Length
= sizeof(attr
);
2231 attr
.RootDirectory
= 0;
2232 attr
.ObjectName
= NULL
;
2233 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
2234 attr
.SecurityDescriptor
= NULL
;
2235 attr
.SecurityQualityOfService
= NULL
;
2238 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
2239 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
2240 if (status
!= STATUS_SUCCESS
) return status
;
2242 offset
.QuadPart
= 0;
2245 status
= NtMapViewOfSection( mapping
, GetCurrentProcess(), &base
, 0, 0, &offset
,
2246 &count
, ViewShare
, 0, PAGE_READONLY
);
2248 if (status
!= STATUS_SUCCESS
) return status
;
2250 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileEndOfFileInformation
);
2251 if (status
== STATUS_SUCCESS
)
2252 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
2254 NtUnmapViewOfSection( GetCurrentProcess(), base
);
2258 /* try to load the .manifest file associated to the file */
2259 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
2260 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
2262 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
2265 UNICODE_STRING nameW
;
2267 ULONG_PTR resid
= CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2269 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
2271 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename
), resid
);
2273 if (module
) /* use the module filename */
2275 UNICODE_STRING name
;
2277 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
2279 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
2280 strcatW( name
.Buffer
, dotManifestW
);
2281 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
2282 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2283 RtlFreeUnicodeString( &name
);
2285 if (status
) return status
;
2289 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2290 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2291 return STATUS_NO_MEMORY
;
2292 strcpyW( buffer
, filename
);
2293 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
2294 strcatW( buffer
, dotManifestW
);
2295 RtlInitUnicodeString( &nameW
, buffer
);
2298 if (!open_nt_file( &file
, &nameW
))
2300 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2303 else status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
2304 RtlFreeUnicodeString( &nameW
);
2308 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
2310 static const WCHAR lookup_fmtW
[] =
2311 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2312 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2313 static const WCHAR wine_trailerW
[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2315 WCHAR
*lookup
, *ret
= NULL
;
2316 UNICODE_STRING lookup_us
;
2318 const WCHAR
*lang
= ai
->language
;
2319 unsigned int data_pos
= 0, data_len
;
2322 if (!(lookup
= RtlAllocateHeap( GetProcessHeap(), 0,
2323 (strlenW(ai
->arch
) + strlenW(ai
->name
)
2324 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
2325 + sizeof(lookup_fmtW
) )))
2328 if (!lang
|| !strcmpiW( lang
, neutralW
)) lang
= wildcardW
;
2329 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
,
2330 ai
->version
.major
, ai
->version
.minor
, lang
);
2331 RtlInitUnicodeString( &lookup_us
, lookup
);
2333 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2334 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
2335 if (io
.u
.Status
== STATUS_SUCCESS
)
2337 ULONG min_build
= ai
->version
.build
, min_revision
= ai
->version
.revision
;
2338 FILE_BOTH_DIR_INFORMATION
*dir_info
;
2340 ULONG build
, revision
;
2342 data_len
= io
.Information
;
2346 if (data_pos
>= data_len
)
2348 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
2349 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
2350 if (io
.u
.Status
!= STATUS_SUCCESS
) break;
2351 data_len
= io
.Information
;
2354 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
2356 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
2357 else data_pos
= data_len
;
2359 tmp
= dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
2361 if (build
< min_build
) continue;
2362 tmp
= strchrW(tmp
, '.') + 1;
2363 revision
= atoiW(tmp
);
2364 if (build
== min_build
&& revision
< min_revision
) continue;
2365 tmp
= strchrW(tmp
, '_') + 1;
2366 tmp
= strchrW(tmp
, '_') + 1;
2367 if (dir_info
->FileNameLength
- (tmp
- dir_info
->FileName
) * sizeof(WCHAR
) == sizeof(wine_trailerW
) &&
2368 !memicmpW( tmp
, wine_trailerW
, sizeof(wine_trailerW
) / sizeof(WCHAR
) ))
2370 /* prefer a non-Wine manifest if we already have one */
2371 /* we'll still load the builtin dll if specified through DllOverrides */
2377 min_revision
= revision
;
2379 ai
->version
.build
= build
;
2380 ai
->version
.revision
= revision
;
2381 RtlFreeHeap( GetProcessHeap(), 0, ret
);
2382 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, dir_info
->FileNameLength
+ sizeof(WCHAR
) )))
2384 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
2385 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
2389 else WARN("no matching file for %s\n", debugstr_w(lookup
));
2390 RtlFreeHeap( GetProcessHeap(), 0, lookup
);
2394 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
2396 struct assembly_identity sxs_ai
;
2397 UNICODE_STRING path_us
;
2398 OBJECT_ATTRIBUTES attr
;
2400 WCHAR
*path
, *file
= NULL
;
2403 static const WCHAR manifest_dirW
[] =
2404 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2406 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
2408 if (!(path
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW
) +
2409 strlenW(user_shared_data
->NtSystemRoot
) * sizeof(WCHAR
) )))
2410 return STATUS_NO_MEMORY
;
2412 strcpyW( path
, user_shared_data
->NtSystemRoot
);
2413 memcpy( path
+ strlenW(path
), manifest_dirW
, sizeof(manifest_dirW
) );
2415 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
2417 RtlFreeHeap( GetProcessHeap(), 0, path
);
2418 return STATUS_NO_SUCH_FILE
;
2420 RtlFreeHeap( GetProcessHeap(), 0, path
);
2422 attr
.Length
= sizeof(attr
);
2423 attr
.RootDirectory
= 0;
2424 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2425 attr
.ObjectName
= &path_us
;
2426 attr
.SecurityDescriptor
= NULL
;
2427 attr
.SecurityQualityOfService
= NULL
;
2429 if (!NtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2430 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
2433 file
= lookup_manifest_file( handle
, &sxs_ai
);
2438 RtlFreeUnicodeString( &path_us
);
2439 return STATUS_NO_SUCH_FILE
;
2442 /* append file name to directory path */
2443 if (!(path
= RtlReAllocateHeap( GetProcessHeap(), 0, path_us
.Buffer
,
2444 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
2446 RtlFreeHeap( GetProcessHeap(), 0, file
);
2447 RtlFreeUnicodeString( &path_us
);
2448 return STATUS_NO_MEMORY
;
2451 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
2452 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
2453 RtlInitUnicodeString( &path_us
, path
);
2454 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
2456 if (!open_nt_file( &handle
, &path_us
))
2458 io
.u
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
2461 else io
.u
.Status
= STATUS_NO_SUCH_FILE
;
2463 RtlFreeHeap( GetProcessHeap(), 0, file
);
2464 RtlFreeUnicodeString( &path_us
);
2468 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
2469 struct assembly_identity
* ai
)
2471 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
2473 WCHAR
*buffer
, *p
, *directory
;
2475 UNICODE_STRING nameW
;
2478 TRACE( "looking for name=%s version=%s arch=%s\n",
2479 debugstr_w(ai
->name
), debugstr_version(&ai
->version
), debugstr_w(ai
->arch
) );
2481 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
2483 /* FIXME: add support for language specific lookup */
2485 nameW
.Buffer
= NULL
;
2486 if (!(buffer
= RtlAllocateHeap( GetProcessHeap(), 0,
2487 (strlenW(acl
->actctx
->appdir
.info
) + 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
2488 return STATUS_NO_MEMORY
;
2490 if (!(directory
= build_assembly_dir( ai
)))
2492 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2493 return STATUS_NO_MEMORY
;
2496 /* lookup in appdir\name.dll
2497 * appdir\name.manifest
2498 * appdir\name\name.dll
2499 * appdir\name\name.manifest
2501 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
2502 p
= buffer
+ strlenW(buffer
);
2503 for (i
= 0; i
< 2; i
++)
2506 strcpyW( p
, ai
->name
);
2509 strcpyW( p
, dotDllW
);
2510 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2512 status
= open_nt_file( &file
, &nameW
);
2515 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
2516 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
2520 RtlFreeUnicodeString( &nameW
);
2523 strcpyW( p
, dotManifestW
);
2524 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
2526 status
= open_nt_file( &file
, &nameW
);
2529 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
2533 RtlFreeUnicodeString( &nameW
);
2535 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
2537 RtlFreeUnicodeString( &nameW
);
2538 RtlFreeHeap( GetProcessHeap(), 0, directory
);
2539 RtlFreeHeap( GetProcessHeap(), 0, buffer
);
2543 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
2545 NTSTATUS status
= STATUS_SUCCESS
;
2548 for (i
= 0; i
< acl
->num_dependencies
; i
++)
2550 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
2552 if (!acl
->dependencies
[i
].optional
)
2554 FIXME( "Could not find dependent assembly %s (%s)\n",
2555 debugstr_w(acl
->dependencies
[i
].name
),
2556 debugstr_version(&acl
->dependencies
[i
].version
) );
2557 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
2562 /* FIXME should now iterate through all refs */
2566 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2567 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
2569 NTSTATUS status
= STATUS_SUCCESS
;
2571 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
2573 if (*handle
) return STATUS_INVALID_PARAMETER
;
2575 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
2576 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
2578 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
2583 if (!*handle
) return STATUS_INVALID_PARAMETER
;
2585 LdrLockLoaderLock( 0, NULL
, &magic
);
2586 if (!LdrFindEntryForAddress( *handle
, &pldr
))
2588 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->BaseAddress
)
2589 status
= STATUS_DLL_NOT_FOUND
;
2591 *handle
= pldr
->ActivationContext
;
2593 else status
= STATUS_DLL_NOT_FOUND
;
2594 LdrUnlockLoaderLock( 0, magic
);
2596 else if (!*handle
&& (class != ActivationContextBasicInformation
))
2597 *handle
= process_actctx
;
2602 static NTSTATUS
build_dllredirect_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
2604 unsigned int i
, j
, total_len
= 0, dll_count
= 0;
2605 struct strsection_header
*header
;
2606 struct dllredirect_data
*data
;
2607 struct string_index
*index
;
2610 /* compute section length */
2611 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2613 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2614 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2616 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2618 /* each entry needs index, data and string data */
2619 total_len
+= sizeof(*index
);
2620 total_len
+= sizeof(*data
);
2621 total_len
+= aligned_string_len((strlenW(dll
->name
)+1)*sizeof(WCHAR
));
2624 dll_count
+= assembly
->num_dlls
;
2627 total_len
+= sizeof(*header
);
2629 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
2630 if (!header
) return STATUS_NO_MEMORY
;
2632 memset(header
, 0, sizeof(*header
));
2633 header
->magic
= STRSECTION_MAGIC
;
2634 header
->size
= sizeof(*header
);
2635 header
->count
= dll_count
;
2636 header
->index_offset
= sizeof(*header
);
2637 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
2638 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
2640 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2642 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2643 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2645 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2649 /* setup new index entry */
2650 str
.Buffer
= dll
->name
;
2651 str
.Length
= strlenW(dll
->name
)*sizeof(WCHAR
);
2652 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
2653 /* hash original class name */
2654 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
2656 index
->name_offset
= name_offset
;
2657 index
->name_len
= str
.Length
;
2658 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
2659 index
->data_len
= sizeof(*data
);
2660 index
->rosterindex
= i
+ 1;
2663 data
= (struct dllredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
2664 data
->size
= sizeof(*data
);
2665 data
->unk
= 2; /* FIXME: seems to be constant */
2666 memset(data
->res
, 0, sizeof(data
->res
));
2669 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
2670 memcpy(ptrW
, dll
->name
, index
->name_len
);
2671 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
2673 name_offset
+= sizeof(*data
) + aligned_string_len(str
.MaximumLength
);
2681 return STATUS_SUCCESS
;
2684 static struct string_index
*find_string_index(const struct strsection_header
*section
, const UNICODE_STRING
*name
)
2686 struct string_index
*iter
, *index
= NULL
;
2689 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
2690 iter
= (struct string_index
*)((BYTE
*)section
+ section
->index_offset
);
2692 for (i
= 0; i
< section
->count
; i
++)
2694 if (iter
->hash
== hash
)
2696 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)section
+ iter
->name_offset
);
2698 if (!strcmpiW(nameW
, name
->Buffer
))
2704 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
2712 static struct guid_index
*find_guid_index(const struct guidsection_header
*section
, const GUID
*guid
)
2714 struct guid_index
*iter
, *index
= NULL
;
2717 iter
= (struct guid_index
*)((BYTE
*)section
+ section
->index_offset
);
2719 for (i
= 0; i
< section
->count
; i
++)
2721 if (!memcmp(guid
, &iter
->guid
, sizeof(*guid
)))
2732 static inline struct dllredirect_data
*get_dllredirect_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
2734 return (struct dllredirect_data
*)((BYTE
*)ctxt
->dllredirect_section
+ index
->data_offset
);
2737 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
2738 PACTCTX_SECTION_KEYED_DATA data
)
2740 struct dllredirect_data
*dll
;
2741 struct string_index
*index
;
2743 if (!(actctx
->sections
& DLLREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
2745 if (!actctx
->dllredirect_section
)
2747 struct strsection_header
*section
;
2749 NTSTATUS status
= build_dllredirect_section(actctx
, §ion
);
2750 if (status
) return status
;
2752 if (interlocked_cmpxchg_ptr((void**)&actctx
->dllredirect_section
, section
, NULL
))
2753 RtlFreeHeap(GetProcessHeap(), 0, section
);
2756 index
= find_string_index(actctx
->dllredirect_section
, name
);
2757 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
2759 dll
= get_dllredirect_data(actctx
, index
);
2761 data
->ulDataFormatVersion
= 1;
2763 data
->ulLength
= dll
->size
;
2764 data
->lpSectionGlobalData
= NULL
;
2765 data
->ulSectionGlobalDataLength
= 0;
2766 data
->lpSectionBase
= actctx
->dllredirect_section
;
2767 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->dllredirect_section
);
2768 data
->hActCtx
= NULL
;
2770 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
2771 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
2773 return STATUS_SUCCESS
;
2776 static inline struct string_index
*get_wndclass_first_index(ACTIVATION_CONTEXT
*actctx
)
2778 return (struct string_index
*)((BYTE
*)actctx
->wndclass_section
+ actctx
->wndclass_section
->index_offset
);
2781 static inline struct wndclass_redirect_data
*get_wndclass_data(ACTIVATION_CONTEXT
*ctxt
, struct string_index
*index
)
2783 return (struct wndclass_redirect_data
*)((BYTE
*)ctxt
->wndclass_section
+ index
->data_offset
);
2786 static NTSTATUS
build_wndclass_section(ACTIVATION_CONTEXT
* actctx
, struct strsection_header
**section
)
2788 unsigned int i
, j
, k
, total_len
= 0, class_count
= 0;
2789 struct wndclass_redirect_data
*data
;
2790 struct strsection_header
*header
;
2791 struct string_index
*index
;
2794 /* compute section length */
2795 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2797 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2798 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2800 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2801 for (k
= 0; k
< dll
->entities
.num
; k
++)
2803 struct entity
*entity
= &dll
->entities
.base
[k
];
2804 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
2806 int class_len
= strlenW(entity
->u
.class.name
) + 1;
2809 /* each class entry needs index, data and string data */
2810 total_len
+= sizeof(*index
);
2811 total_len
+= sizeof(*data
);
2812 /* original name is stored separately */
2813 total_len
+= aligned_string_len(class_len
*sizeof(WCHAR
));
2814 /* versioned name and module name are stored one after another */
2815 if (entity
->u
.class.versioned
)
2816 len
= get_assembly_version(assembly
, NULL
) + class_len
+ 1 /* '!' separator */;
2819 len
+= strlenW(dll
->name
) + 1;
2820 total_len
+= aligned_string_len(len
*sizeof(WCHAR
));
2828 total_len
+= sizeof(*header
);
2830 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
2831 if (!header
) return STATUS_NO_MEMORY
;
2833 memset(header
, 0, sizeof(*header
));
2834 header
->magic
= STRSECTION_MAGIC
;
2835 header
->size
= sizeof(*header
);
2836 header
->count
= class_count
;
2837 header
->index_offset
= sizeof(*header
);
2838 index
= (struct string_index
*)((BYTE
*)header
+ header
->index_offset
);
2839 name_offset
= header
->index_offset
+ header
->count
*sizeof(*index
);
2841 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2843 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2844 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2846 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2847 for (k
= 0; k
< dll
->entities
.num
; k
++)
2849 struct entity
*entity
= &dll
->entities
.base
[k
];
2850 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
2852 static const WCHAR exclW
[] = {'!',0};
2853 ULONG versioned_len
, module_len
;
2857 /* setup new index entry */
2858 str
.Buffer
= entity
->u
.class.name
;
2859 str
.Length
= strlenW(entity
->u
.class.name
)*sizeof(WCHAR
);
2860 str
.MaximumLength
= str
.Length
+ sizeof(WCHAR
);
2861 /* hash original class name */
2862 RtlHashUnicodeString(&str
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &index
->hash
);
2864 /* include '!' separator too */
2865 if (entity
->u
.class.versioned
)
2866 versioned_len
= (get_assembly_version(assembly
, NULL
) + 1)*sizeof(WCHAR
) + str
.Length
;
2868 versioned_len
= str
.Length
;
2869 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
2871 index
->name_offset
= name_offset
;
2872 index
->name_len
= str
.Length
;
2873 index
->data_offset
= index
->name_offset
+ aligned_string_len(str
.MaximumLength
);
2874 index
->data_len
= sizeof(*data
) + versioned_len
+ module_len
+ 2*sizeof(WCHAR
) /* two nulls */;
2875 index
->rosterindex
= i
+ 1;
2878 data
= (struct wndclass_redirect_data
*)((BYTE
*)header
+ index
->data_offset
);
2879 data
->size
= sizeof(*data
);
2881 data
->name_len
= versioned_len
;
2882 data
->name_offset
= sizeof(*data
);
2883 data
->module_len
= module_len
;
2884 data
->module_offset
= index
->data_offset
+ data
->name_offset
+ data
->name_len
+ sizeof(WCHAR
);
2886 /* original class name */
2887 ptrW
= (WCHAR
*)((BYTE
*)header
+ index
->name_offset
);
2888 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
2889 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
2892 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->module_offset
);
2893 memcpy(ptrW
, dll
->name
, data
->module_len
);
2894 ptrW
[data
->module_len
/sizeof(WCHAR
)] = 0;
2896 /* versioned name */
2897 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->name_offset
);
2898 if (entity
->u
.class.versioned
)
2900 get_assembly_version(assembly
, ptrW
);
2901 strcatW(ptrW
, exclW
);
2902 strcatW(ptrW
, entity
->u
.class.name
);
2906 memcpy(ptrW
, entity
->u
.class.name
, index
->name_len
);
2907 ptrW
[index
->name_len
/sizeof(WCHAR
)] = 0;
2910 name_offset
+= sizeof(*data
);
2911 name_offset
+= aligned_string_len(str
.MaximumLength
) + aligned_string_len(versioned_len
+ module_len
+ 2*sizeof(WCHAR
));
2921 return STATUS_SUCCESS
;
2924 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*name
,
2925 PACTCTX_SECTION_KEYED_DATA data
)
2927 struct string_index
*iter
, *index
= NULL
;
2928 struct wndclass_redirect_data
*class;
2932 if (!(actctx
->sections
& WINDOWCLASS_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
2934 if (!actctx
->wndclass_section
)
2936 struct strsection_header
*section
;
2938 NTSTATUS status
= build_wndclass_section(actctx
, §ion
);
2939 if (status
) return status
;
2941 if (interlocked_cmpxchg_ptr((void**)&actctx
->wndclass_section
, section
, NULL
))
2942 RtlFreeHeap(GetProcessHeap(), 0, section
);
2946 RtlHashUnicodeString(name
, TRUE
, HASH_STRING_ALGORITHM_X65599
, &hash
);
2947 iter
= get_wndclass_first_index(actctx
);
2949 for (i
= 0; i
< actctx
->wndclass_section
->count
; i
++)
2951 if (iter
->hash
== hash
)
2953 const WCHAR
*nameW
= (WCHAR
*)((BYTE
*)actctx
->wndclass_section
+ iter
->name_offset
);
2955 if (!strcmpW(nameW
, name
->Buffer
))
2961 WARN("hash collision 0x%08x, %s, %s\n", hash
, debugstr_us(name
), debugstr_w(nameW
));
2966 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
2968 class = get_wndclass_data(actctx
, index
);
2970 data
->ulDataFormatVersion
= 1;
2971 data
->lpData
= class;
2972 /* full length includes string length with nulls */
2973 data
->ulLength
= class->size
+ class->name_len
+ class->module_len
+ 2*sizeof(WCHAR
);
2974 data
->lpSectionGlobalData
= NULL
;
2975 data
->ulSectionGlobalDataLength
= 0;
2976 data
->lpSectionBase
= actctx
->wndclass_section
;
2977 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->wndclass_section
);
2978 data
->hActCtx
= NULL
;
2980 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
2981 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
2983 return STATUS_SUCCESS
;
2986 static NTSTATUS
build_tlib_section(ACTIVATION_CONTEXT
* actctx
, struct guidsection_header
**section
)
2988 unsigned int i
, j
, k
, total_len
= 0, tlib_count
= 0, names_len
= 0;
2989 struct guidsection_header
*header
;
2990 ULONG module_offset
, data_offset
;
2991 struct tlibredirect_data
*data
;
2992 struct guid_index
*index
;
2994 /* compute section length */
2995 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2997 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2998 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3000 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3001 for (k
= 0; k
< dll
->entities
.num
; k
++)
3003 struct entity
*entity
= &dll
->entities
.base
[k
];
3004 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3006 /* each entry needs index, data and string data for module name and help string */
3007 total_len
+= sizeof(*index
);
3008 total_len
+= sizeof(*data
);
3009 /* help string is stored separately */
3010 if (*entity
->u
.typelib
.helpdir
)
3011 total_len
+= aligned_string_len((strlenW(entity
->u
.typelib
.helpdir
)+1)*sizeof(WCHAR
));
3013 /* module names are packed one after another */
3014 names_len
+= (strlenW(dll
->name
)+1)*sizeof(WCHAR
);
3022 total_len
+= aligned_string_len(names_len
);
3023 total_len
+= sizeof(*header
);
3025 header
= RtlAllocateHeap(GetProcessHeap(), 0, total_len
);
3026 if (!header
) return STATUS_NO_MEMORY
;
3028 memset(header
, 0, sizeof(*header
));
3029 header
->magic
= GUIDSECTION_MAGIC
;
3030 header
->size
= sizeof(*header
);
3031 header
->count
= tlib_count
;
3032 header
->index_offset
= sizeof(*header
) + aligned_string_len(names_len
);
3033 index
= (struct guid_index
*)((BYTE
*)header
+ header
->index_offset
);
3034 module_offset
= sizeof(*header
);
3035 data_offset
= header
->index_offset
+ tlib_count
*sizeof(*index
);
3037 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
3039 struct assembly
*assembly
= &actctx
->assemblies
[i
];
3040 for (j
= 0; j
< assembly
->num_dlls
; j
++)
3042 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
3043 for (k
= 0; k
< dll
->entities
.num
; k
++)
3045 struct entity
*entity
= &dll
->entities
.base
[k
];
3046 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)
3048 ULONG module_len
, help_len
;
3052 if (*entity
->u
.typelib
.helpdir
)
3053 help_len
= strlenW(entity
->u
.typelib
.helpdir
)*sizeof(WCHAR
);
3057 module_len
= strlenW(dll
->name
)*sizeof(WCHAR
);
3059 /* setup new index entry */
3060 RtlInitUnicodeString(&str
, entity
->u
.typelib
.tlbid
);
3061 RtlGUIDFromString(&str
, &index
->guid
);
3062 index
->data_offset
= data_offset
;
3063 index
->data_len
= sizeof(*data
) + aligned_string_len(help_len
);
3064 index
->rosterindex
= i
+ 1;
3067 data
= (struct tlibredirect_data
*)((BYTE
*)header
+ index
->data_offset
);
3068 data
->size
= sizeof(*data
);
3070 data
->name_len
= module_len
;
3071 data
->name_offset
= module_offset
;
3072 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3074 data
->flags
= entity
->u
.typelib
.flags
;
3075 data
->help_len
= help_len
;
3076 data
->help_offset
= sizeof(*data
);
3077 data
->major_version
= entity
->u
.typelib
.major
;
3078 data
->minor_version
= entity
->u
.typelib
.minor
;
3081 ptrW
= (WCHAR
*)((BYTE
*)header
+ data
->name_offset
);
3082 memcpy(ptrW
, dll
->name
, data
->name_len
);
3083 ptrW
[data
->name_len
/sizeof(WCHAR
)] = 0;
3088 ptrW
= (WCHAR
*)((BYTE
*)data
+ data
->help_offset
);
3089 memcpy(ptrW
, entity
->u
.typelib
.helpdir
, data
->help_len
);
3090 ptrW
[data
->help_len
/sizeof(WCHAR
)] = 0;
3093 data_offset
+= sizeof(*data
);
3095 data_offset
+= aligned_string_len(help_len
+ sizeof(WCHAR
));
3097 module_offset
+= module_len
+ sizeof(WCHAR
);
3107 return STATUS_SUCCESS
;
3110 static inline struct tlibredirect_data
*get_tlib_data(ACTIVATION_CONTEXT
*actctx
, struct guid_index
*index
)
3112 return (struct tlibredirect_data
*)((BYTE
*)actctx
->tlib_section
+ index
->data_offset
);
3115 static NTSTATUS
find_tlib_redirection(ACTIVATION_CONTEXT
* actctx
, const GUID
*guid
, ACTCTX_SECTION_KEYED_DATA
* data
)
3117 struct guid_index
*index
= NULL
;
3118 struct tlibredirect_data
*tlib
;
3120 if (!(actctx
->sections
& TLIBREDIRECT_SECTION
)) return STATUS_SXS_KEY_NOT_FOUND
;
3122 if (!actctx
->tlib_section
)
3124 struct guidsection_header
*section
;
3126 NTSTATUS status
= build_tlib_section(actctx
, §ion
);
3127 if (status
) return status
;
3129 if (interlocked_cmpxchg_ptr((void**)&actctx
->tlib_section
, section
, NULL
))
3130 RtlFreeHeap(GetProcessHeap(), 0, section
);
3133 index
= find_guid_index(actctx
->tlib_section
, guid
);
3134 if (!index
) return STATUS_SXS_KEY_NOT_FOUND
;
3136 tlib
= get_tlib_data(actctx
, index
);
3138 data
->ulDataFormatVersion
= 1;
3139 data
->lpData
= tlib
;
3140 /* full length includes string length with nulls */
3141 data
->ulLength
= tlib
->size
+ tlib
->help_len
+ sizeof(WCHAR
);
3142 data
->lpSectionGlobalData
= NULL
;
3143 data
->ulSectionGlobalDataLength
= 0;
3144 data
->lpSectionBase
= actctx
->tlib_section
;
3145 data
->ulSectionTotalLength
= RtlSizeHeap( GetProcessHeap(), 0, actctx
->tlib_section
);
3146 data
->hActCtx
= NULL
;
3148 if (data
->cbSize
>= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
3149 data
->ulAssemblyRosterIndex
= index
->rosterindex
;
3151 return STATUS_SUCCESS
;
3154 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
3155 const UNICODE_STRING
*section_name
,
3156 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
3160 switch (section_kind
)
3162 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
3163 status
= find_dll_redirection(actctx
, section_name
, data
);
3165 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
3166 status
= find_window_class(actctx
, section_name
, data
);
3168 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
3169 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
3170 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
3171 FIXME("Unsupported yet section_kind %x\n", section_kind
);
3172 return STATUS_SXS_SECTION_NOT_FOUND
;
3174 WARN("Unknown section_kind %x\n", section_kind
);
3175 return STATUS_SXS_SECTION_NOT_FOUND
;
3178 if (status
!= STATUS_SUCCESS
) return status
;
3180 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
3182 actctx_addref(actctx
);
3183 data
->hActCtx
= actctx
;
3185 return STATUS_SUCCESS
;
3188 static NTSTATUS
find_guid(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
3189 const GUID
*guid
, DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
3193 switch (section_kind
)
3195 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
3196 status
= find_tlib_redirection(actctx
, guid
, data
);
3198 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
3199 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
3200 FIXME("Unsupported yet section_kind %x\n", section_kind
);
3201 return STATUS_SXS_SECTION_NOT_FOUND
;
3203 WARN("Unknown section_kind %x\n", section_kind
);
3204 return STATUS_SXS_SECTION_NOT_FOUND
;
3207 if (status
!= STATUS_SUCCESS
) return status
;
3209 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
3211 actctx_addref(actctx
);
3212 data
->hActCtx
= actctx
;
3214 return STATUS_SUCCESS
;
3217 /* initialize the activation context for the current process */
3218 void actctx_init(void)
3223 ctx
.cbSize
= sizeof(ctx
);
3224 ctx
.lpSource
= NULL
;
3225 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
3226 ctx
.hModule
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
3227 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
3229 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
3233 /***********************************************************************
3234 * RtlCreateActivationContext (NTDLL.@)
3236 * Create an activation context.
3238 * FIXME: function signature/prototype is wrong
3240 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, const void *ptr
)
3242 const ACTCTXW
*pActCtx
= ptr
; /* FIXME: not the right structure */
3243 const WCHAR
*directory
= NULL
;
3244 ACTIVATION_CONTEXT
*actctx
;
3245 UNICODE_STRING nameW
;
3247 NTSTATUS status
= STATUS_NO_MEMORY
;
3249 struct actctx_loader acl
;
3251 TRACE("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
3253 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
3254 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
3255 return STATUS_INVALID_PARAMETER
;
3257 if (!(actctx
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
3258 return STATUS_NO_MEMORY
;
3260 actctx
->magic
= ACTCTX_MAGIC
;
3261 actctx
->ref_count
= 1;
3262 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
3263 actctx
->config
.info
= NULL
;
3264 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
3265 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
3267 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
3275 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
) module
= pActCtx
->hModule
;
3276 else module
= NtCurrentTeb()->Peb
->ImageBaseAddress
;
3278 if ((status
= get_module_filename( module
, &dir
, 0 ))) goto error
;
3279 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
3280 actctx
->appdir
.info
= dir
.Buffer
;
3283 nameW
.Buffer
= NULL
;
3284 if (pActCtx
->lpSource
)
3286 if (!RtlDosPathNameToNtPathName_U(pActCtx
->lpSource
, &nameW
, NULL
, NULL
))
3288 status
= STATUS_NO_SUCH_FILE
;
3291 status
= open_nt_file( &file
, &nameW
);
3294 RtlFreeUnicodeString( &nameW
);
3299 acl
.actctx
= actctx
;
3300 acl
.dependencies
= NULL
;
3301 acl
.num_dependencies
= 0;
3302 acl
.allocated_dependencies
= 0;
3304 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
3305 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
3307 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
3309 /* if we have a resource it's a PE file */
3310 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
3312 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
3313 pActCtx
->lpResourceName
, lang
);
3314 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
3315 /* FIXME: what to do if pActCtx->lpSource is set */
3316 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
3317 pActCtx
->hModule
, pActCtx
->lpResourceName
);
3319 else if (pActCtx
->lpSource
)
3321 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
3322 file
, pActCtx
->lpResourceName
, lang
);
3323 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
3324 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
3325 NULL
, pActCtx
->lpResourceName
);
3327 else status
= STATUS_INVALID_PARAMETER
;
3331 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
3334 if (file
) NtClose( file
);
3335 RtlFreeUnicodeString( &nameW
);
3337 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
3338 free_depend_manifests( &acl
);
3340 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
3341 else actctx_release( actctx
);
3345 if (file
) NtClose( file
);
3346 actctx_release( actctx
);
3351 /***********************************************************************
3352 * RtlAddRefActivationContext (NTDLL.@)
3354 void WINAPI
RtlAddRefActivationContext( HANDLE handle
)
3356 ACTIVATION_CONTEXT
*actctx
;
3358 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
3362 /******************************************************************
3363 * RtlReleaseActivationContext (NTDLL.@)
3365 void WINAPI
RtlReleaseActivationContext( HANDLE handle
)
3367 ACTIVATION_CONTEXT
*actctx
;
3369 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
3373 /******************************************************************
3374 * RtlActivateActivationContext (NTDLL.@)
3376 NTSTATUS WINAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
3378 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
3380 if (!(frame
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame
) )))
3381 return STATUS_NO_MEMORY
;
3383 frame
->Previous
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
3384 frame
->ActivationContext
= handle
;
3386 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
;
3387 RtlAddRefActivationContext( handle
);
3389 *cookie
= (ULONG_PTR
)frame
;
3390 TRACE( "%p cookie=%lx\n", handle
, *cookie
);
3391 return STATUS_SUCCESS
;
3395 /***********************************************************************
3396 * RtlDeactivateActivationContext (NTDLL.@)
3398 void WINAPI
RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
3400 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
3402 TRACE( "%x cookie=%lx\n", flags
, cookie
);
3404 /* find the right frame */
3405 top
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
3406 for (frame
= top
; frame
; frame
= frame
->Previous
)
3407 if ((ULONG_PTR
)frame
== cookie
) break;
3410 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
3412 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
3413 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
3415 /* pop everything up to and including frame */
3416 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= frame
->Previous
;
3418 while (top
!= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3420 frame
= top
->Previous
;
3421 RtlReleaseActivationContext( top
->ActivationContext
);
3422 RtlFreeHeap( GetProcessHeap(), 0, top
);
3428 /******************************************************************
3429 * RtlFreeThreadActivationContextStack (NTDLL.@)
3431 void WINAPI
RtlFreeThreadActivationContextStack(void)
3433 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
3435 frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
;
3438 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
3439 RtlReleaseActivationContext( frame
->ActivationContext
);
3440 RtlFreeHeap( GetProcessHeap(), 0, frame
);
3443 NtCurrentTeb()->ActivationContextStack
.ActiveFrame
= NULL
;
3447 /******************************************************************
3448 * RtlGetActiveActivationContext (NTDLL.@)
3450 NTSTATUS WINAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
3452 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3454 *handle
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
;
3455 RtlAddRefActivationContext( *handle
);
3460 return STATUS_SUCCESS
;
3464 /******************************************************************
3465 * RtlIsActivationContextActive (NTDLL.@)
3467 BOOLEAN WINAPI
RtlIsActivationContextActive( HANDLE handle
)
3469 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
3471 for (frame
= NtCurrentTeb()->ActivationContextStack
.ActiveFrame
; frame
; frame
= frame
->Previous
)
3472 if (frame
->ActivationContext
== handle
) return TRUE
;
3477 /***********************************************************************
3478 * RtlQueryInformationActivationContext (NTDLL.@)
3480 * Get information about an activation context.
3481 * FIXME: function signature/prototype may be wrong
3483 NTSTATUS WINAPI
RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
3484 ULONG
class, PVOID buffer
,
3485 SIZE_T bufsize
, SIZE_T
*retlen
)
3487 ACTIVATION_CONTEXT
*actctx
;
3490 TRACE("%08x %p %p %u %p %ld %p\n", flags
, handle
,
3491 subinst
, class, buffer
, bufsize
, retlen
);
3493 if (retlen
) *retlen
= 0;
3494 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
3498 case ActivationContextBasicInformation
:
3500 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
3502 if (retlen
) *retlen
= sizeof(*info
);
3503 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
3505 info
->hActCtx
= handle
;
3506 info
->dwFlags
= 0; /* FIXME */
3507 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
3511 case ActivationContextDetailedInformation
:
3513 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
3514 struct assembly
*assembly
= NULL
;
3515 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
3518 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
3520 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
3522 if (assembly
&& assembly
->manifest
.info
)
3523 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
3524 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
3525 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
3526 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
3528 if (retlen
) *retlen
= len
;
3529 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
3532 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
3533 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
3534 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
3535 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
3536 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
3537 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
3538 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
3539 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
3540 ptr
= (LPWSTR
)(acdi
+ 1);
3543 acdi
->lpRootManifestPath
= ptr
;
3544 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
3545 ptr
+= manifest_len
;
3547 else acdi
->lpRootManifestPath
= NULL
;
3550 acdi
->lpRootConfigurationPath
= ptr
;
3551 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
3554 else acdi
->lpRootConfigurationPath
= NULL
;
3557 acdi
->lpAppDirPath
= ptr
;
3558 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
3560 else acdi
->lpAppDirPath
= NULL
;
3564 case AssemblyDetailedInformationInActivationContext
:
3566 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
3567 struct assembly
*assembly
;
3570 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
3573 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
3574 if (!subinst
) return STATUS_INVALID_PARAMETER
;
3576 index
= *(DWORD
*)subinst
;
3577 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
3579 assembly
= &actctx
->assemblies
[index
- 1];
3581 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
3582 id_len
= strlenW(assembly_id
) + 1;
3583 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
3585 if (assembly
->manifest
.info
&&
3586 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
3587 path_len
= strlenW(assembly
->manifest
.info
) + 1;
3589 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
3591 if (retlen
) *retlen
= len
;
3592 if (!buffer
|| bufsize
< len
)
3594 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
3595 return STATUS_BUFFER_TOO_SMALL
;
3598 afdi
->ulFlags
= 0; /* FIXME */
3599 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
3600 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
3601 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
3602 /* FIXME afdi->liManifestLastWriteTime = 0; */
3603 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
3604 afdi
->ulPolicyPathLength
= 0;
3605 /* FIXME afdi->liPolicyLastWriteTime = 0; */
3606 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
3607 afdi
->ulManifestVersionMajor
= 1;
3608 afdi
->ulManifestVersionMinor
= 0;
3609 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
3610 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
3611 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
3612 ptr
= (LPWSTR
)(afdi
+ 1);
3613 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
3614 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
3618 afdi
->lpAssemblyManifestPath
= ptr
;
3619 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
3621 } else afdi
->lpAssemblyManifestPath
= NULL
;
3622 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
3625 afdi
->lpAssemblyDirectoryName
= ptr
;
3626 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
3628 else afdi
->lpAssemblyDirectoryName
= NULL
;
3629 RtlFreeHeap( GetProcessHeap(), 0, assembly_id
);
3633 case FileInformationInAssemblyOfAssemblyInActivationContext
:
3635 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
3636 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
3637 struct assembly
*assembly
;
3638 struct dll_redirect
*dll
;
3639 SIZE_T len
, dll_len
= 0;
3642 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
3643 if (!acqi
) return STATUS_INVALID_PARAMETER
;
3645 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
3646 return STATUS_INVALID_PARAMETER
;
3647 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
3649 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
3650 return STATUS_INVALID_PARAMETER
;
3651 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
3653 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
3654 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
3656 if (!buffer
|| bufsize
< len
)
3658 if (retlen
) *retlen
= len
;
3659 return STATUS_BUFFER_TOO_SMALL
;
3661 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
3662 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
3663 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
3664 afdi
->ulPathLength
= 0; /* FIXME */
3665 ptr
= (LPWSTR
)(afdi
+ 1);
3668 afdi
->lpFileName
= ptr
;
3669 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
3670 } else afdi
->lpFileName
= NULL
;
3671 afdi
->lpFilePath
= NULL
; /* FIXME */
3676 FIXME( "class %u not implemented\n", class );
3677 return STATUS_NOT_IMPLEMENTED
;
3679 return STATUS_SUCCESS
;
3682 /***********************************************************************
3683 * RtlFindActivationContextSectionString (NTDLL.@)
3685 * Find information about a string in an activation context.
3686 * FIXME: function signature/prototype may be wrong
3688 NTSTATUS WINAPI
RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
3689 const UNICODE_STRING
*section_name
, PVOID ptr
)
3691 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
3692 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
3694 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(guid
), section_kind
,
3695 debugstr_us(section_name
), data
);
3699 FIXME("expected guid == NULL\n");
3700 return STATUS_INVALID_PARAMETER
;
3702 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
3704 FIXME("unknown flags %08x\n", flags
);
3705 return STATUS_INVALID_PARAMETER
;
3707 if (!data
|| data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) ||
3708 !section_name
|| !section_name
->Buffer
)
3710 WARN("invalid parameter\n");
3711 return STATUS_INVALID_PARAMETER
;
3714 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3716 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
3717 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
3720 if (status
!= STATUS_SUCCESS
)
3721 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
3726 /***********************************************************************
3727 * RtlFindActivationContextSectionGuid (NTDLL.@)
3729 * Find information about a GUID in an activation context.
3730 * FIXME: function signature/prototype may be wrong
3732 NTSTATUS WINAPI
RtlFindActivationContextSectionGuid( ULONG flags
, const GUID
*extguid
, ULONG section_kind
,
3733 const GUID
*guid
, void *ptr
)
3735 ACTCTX_SECTION_KEYED_DATA
*data
= ptr
;
3736 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
3738 TRACE("%08x %s %u %s %p\n", flags
, debugstr_guid(extguid
), section_kind
, debugstr_guid(guid
), data
);
3742 FIXME("expected extguid == NULL\n");
3743 return STATUS_INVALID_PARAMETER
;
3746 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
3748 FIXME("unknown flags %08x\n", flags
);
3749 return STATUS_INVALID_PARAMETER
;
3752 if (!data
|| data
->cbSize
< FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) || !guid
)
3753 return STATUS_INVALID_PARAMETER
;
3755 if (NtCurrentTeb()->ActivationContextStack
.ActiveFrame
)
3757 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStack
.ActiveFrame
->ActivationContext
);
3758 if (actctx
) status
= find_guid( actctx
, section_kind
, guid
, flags
, data
);
3761 if (status
!= STATUS_SUCCESS
)
3762 status
= find_guid( process_actctx
, section_kind
, guid
, flags
, data
);