2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Runtime Library
4 * PURPOSE: Activation Context Support
5 * FILE: lib/rtl/actctx.c
9 * Jacek Caban for CodeWeavers
11 * Stefan Ginsberg (stefan__100__@hotmail.com)
15 /* Based on Wine 1.1.26 */
17 /* INCLUDES *****************************************************************/
23 #include <wine/unicode.h>
25 #define QUERY_ACTCTX_FLAG_ACTIVE (0x00000001)
27 #define ACTCTX_FLAGS_ALL (\
28 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
29 ACTCTX_FLAG_LANGID_VALID |\
30 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
31 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
32 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
33 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
34 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
35 ACTCTX_FLAG_HMODULE_VALID )
37 #define ACTCTX_MAGIC 0xC07E3E11
39 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
40 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
62 struct assembly_version
70 struct assembly_identity
77 struct assembly_version version
;
121 unsigned int allocated
;
128 struct entity_array entities
;
133 APPLICATION_MANIFEST
,
135 ASSEMBLY_SHARED_MANIFEST
,
140 enum assembly_type type
;
141 struct assembly_identity id
;
142 struct file_info manifest
;
145 struct dll_redirect
*dlls
;
146 unsigned int num_dlls
;
147 unsigned int allocated_dlls
;
148 struct entity_array entities
;
151 typedef struct _ACTIVATION_CONTEXT
155 struct file_info config
;
156 struct file_info appdir
;
157 struct assembly
*assemblies
;
158 unsigned int num_assemblies
;
159 unsigned int allocated_assemblies
;
160 } ACTIVATION_CONTEXT
;
164 ACTIVATION_CONTEXT
*actctx
;
165 struct assembly_identity
*dependencies
;
166 unsigned int num_dependencies
;
167 unsigned int allocated_dependencies
;
170 static const WCHAR assemblyW
[] = {'a','s','s','e','m','b','l','y',0};
171 static const WCHAR assemblyIdentityW
[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
172 static const WCHAR bindingRedirectW
[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
173 static const WCHAR clrClassW
[] = {'c','l','r','C','l','a','s','s',0};
174 static const WCHAR clrSurrogateW
[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
175 static const WCHAR comClassW
[] = {'c','o','m','C','l','a','s','s',0};
176 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};
177 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};
178 static const WCHAR dependencyW
[] = {'d','e','p','e','n','d','e','n','c','y',0};
179 static const WCHAR dependentAssemblyW
[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
180 static const WCHAR descriptionW
[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
181 static const WCHAR fileW
[] = {'f','i','l','e',0};
182 static const WCHAR asmv2hashW
[] = {'a','s','m','v','2',':','h','a','s','h',0};
183 static const WCHAR noInheritW
[] = {'n','o','I','n','h','e','r','i','t',0};
184 static const WCHAR noInheritableW
[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
185 static const WCHAR typelibW
[] = {'t','y','p','e','l','i','b',0};
186 static const WCHAR windowClassW
[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
188 static const WCHAR clsidW
[] = {'c','l','s','i','d',0};
189 static const WCHAR hashW
[] = {'h','a','s','h',0};
190 static const WCHAR hashalgW
[] = {'h','a','s','h','a','l','g',0};
191 static const WCHAR helpdirW
[] = {'h','e','l','p','d','i','r',0};
192 static const WCHAR iidW
[] = {'i','i','d',0};
193 static const WCHAR languageW
[] = {'l','a','n','g','u','a','g','e',0};
194 static const WCHAR manifestVersionW
[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
195 static const WCHAR nameW
[] = {'n','a','m','e',0};
196 static const WCHAR newVersionW
[] = {'n','e','w','V','e','r','s','i','o','n',0};
197 static const WCHAR oldVersionW
[] = {'o','l','d','V','e','r','s','i','o','n',0};
198 static const WCHAR optionalW
[] = {'o','p','t','i','o','n','a','l',0};
199 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};
200 static const WCHAR publicKeyTokenW
[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
201 static const WCHAR tlbidW
[] = {'t','l','b','i','d',0};
202 static const WCHAR typeW
[] = {'t','y','p','e',0};
203 static const WCHAR versionW
[] = {'v','e','r','s','i','o','n',0};
204 static const WCHAR xmlnsW
[] = {'x','m','l','n','s',0};
206 static const WCHAR xmlW
[] = {'?','x','m','l',0};
207 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};
208 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};
210 static const WCHAR dotManifestW
[] = {'.','m','a','n','i','f','e','s','t',0};
211 static const WCHAR version_formatW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
213 static ACTIVATION_CONTEXT system_actctx
= { ACTCTX_MAGIC
, 1 };
214 static ACTIVATION_CONTEXT
*process_actctx
= &system_actctx
;
216 static WCHAR
*strdupW(const WCHAR
* str
)
220 if (!(ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str
) + 1) * sizeof(WCHAR
))))
222 return strcpyW(ptr
, str
);
225 static WCHAR
*xmlstrdupW(const xmlstr_t
* str
)
229 if ((strW
= RtlAllocateHeap(RtlGetProcessHeap(), 0, (str
->len
+ 1) * sizeof(WCHAR
))))
231 memcpy( strW
, str
->ptr
, str
->len
* sizeof(WCHAR
) );
237 static inline BOOL
xmlstr_cmp(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
239 return !strncmpW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
242 static inline BOOL
xmlstr_cmpi(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
244 return !strncmpiW(xmlstr
->ptr
, str
, xmlstr
->len
) && !str
[xmlstr
->len
];
247 static inline BOOL
xmlstr_cmp_end(const xmlstr_t
* xmlstr
, const WCHAR
*str
)
249 return (xmlstr
->len
&& xmlstr
->ptr
[0] == '/' &&
250 !strncmpW(xmlstr
->ptr
+ 1, str
, xmlstr
->len
- 1) && !str
[xmlstr
->len
- 1]);
253 static inline BOOL
isxmlspace( WCHAR ch
)
255 return (ch
== ' ' || ch
== '\r' || ch
== '\n' || ch
== '\t');
258 static struct assembly
*add_assembly(ACTIVATION_CONTEXT
*actctx
, enum assembly_type at
)
260 struct assembly
*assembly
;
262 if (actctx
->num_assemblies
== actctx
->allocated_assemblies
)
265 unsigned int new_count
;
266 if (actctx
->assemblies
)
268 new_count
= actctx
->allocated_assemblies
* 2;
269 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
270 actctx
->assemblies
, new_count
* sizeof(*assembly
) );
275 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
) );
277 if (!ptr
) return NULL
;
278 actctx
->assemblies
= ptr
;
279 actctx
->allocated_assemblies
= new_count
;
282 assembly
= &actctx
->assemblies
[actctx
->num_assemblies
++];
287 static struct dll_redirect
* add_dll_redirect(struct assembly
* assembly
)
289 if (assembly
->num_dlls
== assembly
->allocated_dlls
)
292 unsigned int new_count
;
295 new_count
= assembly
->allocated_dlls
* 2;
296 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
297 assembly
->dlls
, new_count
* sizeof(*assembly
->dlls
) );
302 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*assembly
->dlls
) );
304 if (!ptr
) return NULL
;
305 assembly
->dlls
= ptr
;
306 assembly
->allocated_dlls
= new_count
;
308 return &assembly
->dlls
[assembly
->num_dlls
++];
311 static void free_assembly_identity(struct assembly_identity
*ai
)
313 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->name
);
314 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->arch
);
315 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->public_key
);
316 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->language
);
317 RtlFreeHeap( RtlGetProcessHeap(), 0, ai
->type
);
320 static struct entity
* add_entity(struct entity_array
*array
, DWORD kind
)
322 struct entity
* entity
;
324 if (array
->num
== array
->allocated
)
327 unsigned int new_count
;
330 new_count
= array
->allocated
* 2;
331 ptr
= RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
,
332 array
->base
, new_count
* sizeof(*array
->base
) );
337 ptr
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, new_count
* sizeof(*array
->base
) );
339 if (!ptr
) return NULL
;
341 array
->allocated
= new_count
;
343 entity
= &array
->base
[array
->num
++];
348 static void free_entity_array(struct entity_array
*array
)
351 for (i
= 0; i
< array
->num
; i
++)
353 struct entity
*entity
= &array
->base
[i
];
354 switch (entity
->kind
)
356 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
357 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.comclass
.clsid
);
359 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
360 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.proxy
.iid
);
361 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.proxy
.name
);
363 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
364 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.tlbid
);
365 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.version
);
366 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.typelib
.helpdir
);
368 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
369 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.class.name
);
371 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
372 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrclass
.name
);
373 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrclass
.clsid
);
375 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
376 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.name
);
377 RtlFreeHeap(RtlGetProcessHeap(), 0, entity
->u
.clrsurrogate
.clsid
);
380 DPRINT1("Unknown entity kind %d\n", entity
->kind
);
383 RtlFreeHeap( RtlGetProcessHeap(), 0, array
->base
);
386 static BOOL
is_matching_string( const WCHAR
*str1
, const WCHAR
*str2
)
388 if (!str1
) return !str2
;
389 return str2
&& !strcmpiW( str1
, str2
);
392 static BOOL
is_matching_identity( const struct assembly_identity
*id1
,
393 const struct assembly_identity
*id2
)
395 if (!is_matching_string( id1
->name
, id2
->name
)) return FALSE
;
396 if (!is_matching_string( id1
->arch
, id2
->arch
)) return FALSE
;
397 if (!is_matching_string( id1
->public_key
, id2
->public_key
)) return FALSE
;
399 if (id1
->language
&& id2
->language
&& strcmpiW( id1
->language
, id2
->language
))
401 static const WCHAR wildcardW
[] = {'*',0};
402 if (strcmpW( wildcardW
, id1
->language
) && strcmpW( wildcardW
, id2
->language
))
405 if (id1
->version
.major
!= id2
->version
.major
) return FALSE
;
406 if (id1
->version
.minor
!= id2
->version
.minor
) return FALSE
;
407 if (id1
->version
.build
> id2
->version
.build
) return FALSE
;
408 if (id1
->version
.build
== id2
->version
.build
&&
409 id1
->version
.revision
> id2
->version
.revision
) return FALSE
;
413 static BOOL
add_dependent_assembly_id(struct actctx_loader
* acl
,
414 struct assembly_identity
* ai
)
418 /* check if we already have that assembly */
420 for (i
= 0; i
< acl
->actctx
->num_assemblies
; i
++)
421 if (is_matching_identity( ai
, &acl
->actctx
->assemblies
[i
].id
))
423 DPRINT( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
424 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
425 ai
->version
.build
, ai
->version
.revision
);
429 for (i
= 0; i
< acl
->num_dependencies
; i
++)
430 if (is_matching_identity( ai
, &acl
->dependencies
[i
] ))
432 DPRINT( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
433 ai
->name
, ai
->arch
, ai
->version
.major
, ai
->version
.minor
,
434 ai
->version
.build
, ai
->version
.revision
);
438 if (acl
->num_dependencies
== acl
->allocated_dependencies
)
441 unsigned int new_count
;
442 if (acl
->dependencies
)
444 new_count
= acl
->allocated_dependencies
* 2;
445 ptr
= RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl
->dependencies
,
446 new_count
* sizeof(acl
->dependencies
[0]));
451 ptr
= RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count
* sizeof(acl
->dependencies
[0]));
453 if (!ptr
) return FALSE
;
454 acl
->dependencies
= ptr
;
455 acl
->allocated_dependencies
= new_count
;
457 acl
->dependencies
[acl
->num_dependencies
++] = *ai
;
462 static void free_depend_manifests(struct actctx_loader
* acl
)
465 for (i
= 0; i
< acl
->num_dependencies
; i
++)
466 free_assembly_identity(&acl
->dependencies
[i
]);
467 RtlFreeHeap(RtlGetProcessHeap(), 0, acl
->dependencies
);
470 static WCHAR
*build_assembly_dir(struct assembly_identity
* ai
)
472 static const WCHAR undW
[] = {'_',0};
473 static const WCHAR noneW
[] = {'n','o','n','e',0};
474 static const WCHAR mskeyW
[] = {'d','e','a','d','b','e','e','f',0};
476 const WCHAR
*arch
= ai
->arch
? ai
->arch
: noneW
;
477 const WCHAR
*key
= ai
->public_key
? ai
->public_key
: noneW
;
478 const WCHAR
*lang
= ai
->language
? ai
->language
: noneW
;
479 const WCHAR
*name
= ai
->name
? ai
->name
: noneW
;
480 SIZE_T size
= (strlenW(arch
) + 1 + strlenW(name
) + 1 + strlenW(key
) + 24 + 1 +
481 strlenW(lang
) + 1) * sizeof(WCHAR
) + sizeof(mskeyW
);
484 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
))) return NULL
;
486 strcpyW( ret
, arch
);
487 strcatW( ret
, undW
);
488 strcatW( ret
, name
);
489 strcatW( ret
, undW
);
491 strcatW( ret
, undW
);
492 sprintfW( ret
+ strlenW(ret
), version_formatW
,
493 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
494 strcatW( ret
, undW
);
495 strcatW( ret
, lang
);
496 strcatW( ret
, undW
);
497 strcatW( ret
, mskeyW
);
501 static inline void append_string( WCHAR
*buffer
, const WCHAR
*prefix
, const WCHAR
*str
)
506 strcatW( buffer
, prefix
);
515 static WCHAR
*build_assembly_id( const struct assembly_identity
*ai
)
517 static const WCHAR archW
[] =
518 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
519 static const WCHAR public_keyW
[] =
520 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
521 static const WCHAR typeW
[] =
522 {',','t','y','p','e','=',0};
523 static const WCHAR versionW
[] =
524 {',','v','e','r','s','i','o','n','=',0};
526 WCHAR version
[64], *ret
;
529 sprintfW( version
, version_formatW
,
530 ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
);
531 if (ai
->name
) size
+= strlenW(ai
->name
) * sizeof(WCHAR
);
532 if (ai
->arch
) size
+= strlenW(archW
) + strlenW(ai
->arch
) + 2;
533 if (ai
->public_key
) size
+= strlenW(public_keyW
) + strlenW(ai
->public_key
) + 2;
534 if (ai
->type
) size
+= strlenW(typeW
) + strlenW(ai
->type
) + 2;
535 size
+= strlenW(versionW
) + strlenW(version
) + 2;
537 if (!(ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, (size
+ 1) * sizeof(WCHAR
) )))
540 if (ai
->name
) strcpyW( ret
, ai
->name
);
542 append_string( ret
, archW
, ai
->arch
);
543 append_string( ret
, public_keyW
, ai
->public_key
);
544 append_string( ret
, typeW
, ai
->type
);
545 append_string( ret
, versionW
, version
);
549 static ACTIVATION_CONTEXT
*check_actctx( HANDLE h
)
551 ACTIVATION_CONTEXT
*ret
= NULL
, *actctx
= h
;
553 if (!h
|| h
== INVALID_HANDLE_VALUE
) return NULL
;
556 if (actctx
&& actctx
->magic
== ACTCTX_MAGIC
) ret
= actctx
;
558 //__EXCEPT_PAGE_FAULT
565 static inline void actctx_addref( ACTIVATION_CONTEXT
*actctx
)
567 _InterlockedExchangeAdd( &actctx
->ref_count
, 1 );
570 static void actctx_release( ACTIVATION_CONTEXT
*actctx
)
572 if (_InterlockedExchangeAdd( &actctx
->ref_count
, -1 ) == 1)
576 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
578 struct assembly
*assembly
= &actctx
->assemblies
[i
];
579 for (j
= 0; j
< assembly
->num_dlls
; j
++)
581 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
582 free_entity_array( &dll
->entities
);
583 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->name
);
584 RtlFreeHeap( RtlGetProcessHeap(), 0, dll
->hash
);
586 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->dlls
);
587 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->manifest
.info
);
588 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly
->directory
);
589 free_entity_array( &assembly
->entities
);
590 free_assembly_identity(&assembly
->id
);
592 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->config
.info
);
593 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->appdir
.info
);
594 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
->assemblies
);
596 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx
);
600 static BOOL
next_xml_attr(xmlbuf_t
* xmlbuf
, xmlstr_t
* name
, xmlstr_t
* value
,
601 BOOL
* error
, BOOL
* end
)
607 while (xmlbuf
->ptr
< xmlbuf
->end
&& isxmlspace(*xmlbuf
->ptr
))
610 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
612 if (*xmlbuf
->ptr
== '/')
615 if (xmlbuf
->ptr
== xmlbuf
->end
|| *xmlbuf
->ptr
!= '>')
624 if (*xmlbuf
->ptr
== '>')
632 while (ptr
< xmlbuf
->end
&& *ptr
!= '=' && *ptr
!= '>' && !isxmlspace(*ptr
)) ptr
++;
634 if (ptr
== xmlbuf
->end
|| *ptr
!= '=') return FALSE
;
636 name
->ptr
= xmlbuf
->ptr
;
637 name
->len
= ptr
-xmlbuf
->ptr
;
641 if (ptr
== xmlbuf
->end
|| (*ptr
!= '"' && *ptr
!= '\'')) return FALSE
;
644 if (ptr
== xmlbuf
->end
) return FALSE
;
646 ptr
= memchrW(ptr
, ptr
[-1], xmlbuf
->end
- ptr
);
649 xmlbuf
->ptr
= xmlbuf
->end
;
653 value
->len
= ptr
- value
->ptr
;
654 xmlbuf
->ptr
= ptr
+ 1;
656 if (xmlbuf
->ptr
== xmlbuf
->end
) return FALSE
;
662 static BOOL
next_xml_elem(xmlbuf_t
* xmlbuf
, xmlstr_t
* elem
)
668 ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
671 xmlbuf
->ptr
= xmlbuf
->end
;
675 if (ptr
+ 3 < xmlbuf
->end
&& ptr
[0] == '!' && ptr
[1] == '-' && ptr
[2] == '-') /* skip comment */
677 for (ptr
+= 3; ptr
+ 3 <= xmlbuf
->end
; ptr
++)
678 if (ptr
[0] == '-' && ptr
[1] == '-' && ptr
[2] == '>') break;
680 if (ptr
+ 3 > xmlbuf
->end
)
682 xmlbuf
->ptr
= xmlbuf
->end
;
685 xmlbuf
->ptr
= ptr
+ 3;
691 while (ptr
< xmlbuf
->end
&& !isxmlspace(*ptr
) && *ptr
!= '>' && (*ptr
!= '/' || ptr
== xmlbuf
->ptr
))
694 elem
->ptr
= xmlbuf
->ptr
;
695 elem
->len
= ptr
- xmlbuf
->ptr
;
697 return xmlbuf
->ptr
!= xmlbuf
->end
;
700 static BOOL
parse_xml_header(xmlbuf_t
* xmlbuf
)
702 /* FIXME: parse attributes */
705 for (ptr
= xmlbuf
->ptr
; ptr
< xmlbuf
->end
- 1; ptr
++)
707 if (ptr
[0] == '?' && ptr
[1] == '>')
709 xmlbuf
->ptr
= ptr
+ 2;
716 static BOOL
parse_text_content(xmlbuf_t
* xmlbuf
, xmlstr_t
* content
)
718 const WCHAR
*ptr
= memchrW(xmlbuf
->ptr
, '<', xmlbuf
->end
- xmlbuf
->ptr
);
720 if (!ptr
) return FALSE
;
722 content
->ptr
= xmlbuf
->ptr
;
723 content
->len
= ptr
- xmlbuf
->ptr
;
729 static BOOL
parse_version(const xmlstr_t
*str
, struct assembly_version
*version
)
735 /* major.minor.build.revision */
736 ver
[0] = ver
[1] = ver
[2] = ver
[3] = pos
= 0;
737 for (curr
= str
->ptr
; curr
< str
->ptr
+ str
->len
; curr
++)
739 if (*curr
>= '0' && *curr
<= '9')
741 ver
[pos
] = ver
[pos
] * 10 + *curr
- '0';
742 if (ver
[pos
] >= 0x10000) goto error
;
744 else if (*curr
== '.')
746 if (++pos
>= 4) goto error
;
750 version
->major
= ver
[0];
751 version
->minor
= ver
[1];
752 version
->build
= ver
[2];
753 version
->revision
= ver
[3];
757 DPRINT1( "Wrong version definition in manifest file (%s)\n", str
->ptr
);
761 static BOOL
parse_expect_elem(xmlbuf_t
* xmlbuf
, const WCHAR
* name
)
764 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
765 if (xmlstr_cmp(&elem
, name
)) return TRUE
;
766 DPRINT1( "unexpected element %s\n", elem
.ptr
);
770 static BOOL
parse_expect_no_attr(xmlbuf_t
* xmlbuf
, BOOL
* end
)
772 xmlstr_t attr_name
, attr_value
;
775 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, end
))
777 DPRINT1( "unexpected attr %s=%s\n", attr_name
.ptr
,
783 static BOOL
parse_end_element(xmlbuf_t
*xmlbuf
)
786 return parse_expect_no_attr(xmlbuf
, &end
) && !end
;
789 static BOOL
parse_expect_end_elem(xmlbuf_t
*xmlbuf
, const WCHAR
*name
)
792 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
793 if (!xmlstr_cmp_end(&elem
, name
))
795 DPRINT1( "unexpected element %s\n", elem
.ptr
);
798 return parse_end_element(xmlbuf
);
801 static BOOL
parse_unknown_elem(xmlbuf_t
*xmlbuf
, const xmlstr_t
*unknown_elem
)
803 xmlstr_t attr_name
, attr_value
, elem
;
804 BOOL end
= FALSE
, error
, ret
= TRUE
;
806 while(next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
));
807 if(error
|| end
) return end
;
809 while(ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
811 if(*elem
.ptr
== '/' && elem
.len
- 1 == unknown_elem
->len
&&
812 !strncmpW(elem
.ptr
+1, unknown_elem
->ptr
, unknown_elem
->len
))
815 ret
= parse_unknown_elem(xmlbuf
, &elem
);
818 return ret
&& parse_end_element(xmlbuf
);
821 static BOOL
parse_assembly_identity_elem(xmlbuf_t
* xmlbuf
, ACTIVATION_CONTEXT
* actctx
,
822 struct assembly_identity
* ai
)
824 xmlstr_t attr_name
, attr_value
;
825 BOOL end
= FALSE
, error
;
827 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
829 if (xmlstr_cmp(&attr_name
, nameW
))
831 if (!(ai
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
833 else if (xmlstr_cmp(&attr_name
, typeW
))
835 if (!(ai
->type
= xmlstrdupW(&attr_value
))) return FALSE
;
837 else if (xmlstr_cmp(&attr_name
, versionW
))
839 if (!parse_version(&attr_value
, &ai
->version
)) return FALSE
;
841 else if (xmlstr_cmp(&attr_name
, processorArchitectureW
))
843 if (!(ai
->arch
= xmlstrdupW(&attr_value
))) return FALSE
;
845 else if (xmlstr_cmp(&attr_name
, publicKeyTokenW
))
847 if (!(ai
->public_key
= xmlstrdupW(&attr_value
))) return FALSE
;
849 else if (xmlstr_cmp(&attr_name
, languageW
))
851 DPRINT1("Unsupported yet language attribute (%s)\n",
853 if (!(ai
->language
= xmlstrdupW(&attr_value
))) return FALSE
;
857 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
,
862 if (error
|| end
) return end
;
863 return parse_expect_end_elem(xmlbuf
, assemblyIdentityW
);
866 static BOOL
parse_com_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
868 xmlstr_t elem
, attr_name
, attr_value
;
869 BOOL ret
, end
= FALSE
, error
;
870 struct entity
* entity
;
872 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
)))
875 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
877 if (xmlstr_cmp(&attr_name
, clsidW
))
879 if (!(entity
->u
.comclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
883 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
887 if (error
|| end
) return end
;
889 while ((ret
= next_xml_elem(xmlbuf
, &elem
)))
891 if (xmlstr_cmp_end(&elem
, comClassW
))
893 ret
= parse_end_element(xmlbuf
);
898 DPRINT1("unknown elem %s\n", elem
.ptr
);
899 ret
= parse_unknown_elem(xmlbuf
, &elem
);
905 static BOOL
parse_cominterface_proxy_stub_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
907 xmlstr_t attr_name
, attr_value
;
908 BOOL end
= FALSE
, error
;
909 struct entity
* entity
;
911 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
)))
914 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
916 if (xmlstr_cmp(&attr_name
, iidW
))
918 if (!(entity
->u
.proxy
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
920 if (xmlstr_cmp(&attr_name
, nameW
))
922 if (!(entity
->u
.proxy
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
926 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
930 if (error
|| end
) return end
;
931 return parse_expect_end_elem(xmlbuf
, comInterfaceProxyStubW
);
934 static BOOL
parse_typelib_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
936 xmlstr_t attr_name
, attr_value
;
937 BOOL end
= FALSE
, error
;
938 struct entity
* entity
;
940 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
)))
943 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
945 if (xmlstr_cmp(&attr_name
, tlbidW
))
947 if (!(entity
->u
.typelib
.tlbid
= xmlstrdupW(&attr_value
))) return FALSE
;
949 if (xmlstr_cmp(&attr_name
, versionW
))
951 if (!(entity
->u
.typelib
.version
= xmlstrdupW(&attr_value
))) return FALSE
;
953 if (xmlstr_cmp(&attr_name
, helpdirW
))
955 if (!(entity
->u
.typelib
.helpdir
= xmlstrdupW(&attr_value
))) return FALSE
;
959 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
963 if (error
|| end
) return end
;
964 return parse_expect_end_elem(xmlbuf
, typelibW
);
967 static BOOL
parse_window_class_elem(xmlbuf_t
* xmlbuf
, struct dll_redirect
* dll
)
969 xmlstr_t elem
, content
;
970 BOOL end
= FALSE
, ret
= TRUE
;
971 struct entity
* entity
;
973 if (!(entity
= add_entity(&dll
->entities
, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)))
976 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
977 if (end
) return FALSE
;
979 if (!parse_text_content(xmlbuf
, &content
)) return FALSE
;
981 if (!(entity
->u
.class.name
= xmlstrdupW(&content
))) return FALSE
;
983 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
985 if (xmlstr_cmp_end(&elem
, windowClassW
))
987 ret
= parse_end_element(xmlbuf
);
992 DPRINT1("unknown elem %s\n", elem
.ptr
);
993 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1000 static BOOL
parse_binding_redirect_elem(xmlbuf_t
* xmlbuf
)
1002 xmlstr_t attr_name
, attr_value
;
1003 BOOL end
= FALSE
, error
;
1005 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1007 if (xmlstr_cmp(&attr_name
, oldVersionW
))
1009 DPRINT1("Not stored yet oldVersion=%s\n", attr_value
.ptr
);
1011 else if (xmlstr_cmp(&attr_name
, newVersionW
))
1013 DPRINT1("Not stored yet newVersion=%s\n", attr_value
.ptr
);
1017 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1021 if (error
|| end
) return end
;
1022 return parse_expect_end_elem(xmlbuf
, bindingRedirectW
);
1025 static BOOL
parse_description_elem(xmlbuf_t
* xmlbuf
)
1027 xmlstr_t elem
, content
;
1028 BOOL end
= FALSE
, ret
= TRUE
;
1030 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
||
1031 !parse_text_content(xmlbuf
, &content
))
1034 DPRINT("Got description %s\n", content
.ptr
);
1036 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1038 if (xmlstr_cmp_end(&elem
, descriptionW
))
1040 ret
= parse_end_element(xmlbuf
);
1045 DPRINT1("unknown elem %s\n", elem
.ptr
);
1046 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1053 static BOOL
parse_com_interface_external_proxy_stub_elem(xmlbuf_t
* xmlbuf
,
1054 struct assembly
* assembly
)
1056 xmlstr_t attr_name
, attr_value
;
1057 BOOL end
= FALSE
, error
;
1058 struct entity
* entity
;
1060 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
);
1061 if (!entity
) return FALSE
;
1063 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1065 if (xmlstr_cmp(&attr_name
, iidW
))
1067 if (!(entity
->u
.proxy
.iid
= xmlstrdupW(&attr_value
))) return FALSE
;
1069 if (xmlstr_cmp(&attr_name
, nameW
))
1071 if (!(entity
->u
.proxy
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1075 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1079 if (error
|| end
) return end
;
1080 return parse_expect_end_elem(xmlbuf
, comInterfaceExternalProxyStubW
);
1083 static BOOL
parse_clr_class_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
)
1085 xmlstr_t attr_name
, attr_value
;
1086 BOOL end
= FALSE
, error
;
1087 struct entity
* entity
;
1089 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
);
1090 if (!entity
) return FALSE
;
1092 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1094 if (xmlstr_cmp(&attr_name
, nameW
))
1096 if (!(entity
->u
.clrclass
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1098 else if (xmlstr_cmp(&attr_name
, clsidW
))
1100 if (!(entity
->u
.clrclass
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1104 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1108 if (error
|| end
) return end
;
1109 return parse_expect_end_elem(xmlbuf
, clrClassW
);
1112 static BOOL
parse_clr_surrogate_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
)
1114 xmlstr_t attr_name
, attr_value
;
1115 BOOL end
= FALSE
, error
;
1116 struct entity
* entity
;
1118 entity
= add_entity(&assembly
->entities
, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
);
1119 if (!entity
) return FALSE
;
1121 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1123 if (xmlstr_cmp(&attr_name
, nameW
))
1125 if (!(entity
->u
.clrsurrogate
.name
= xmlstrdupW(&attr_value
))) return FALSE
;
1127 else if (xmlstr_cmp(&attr_name
, clsidW
))
1129 if (!(entity
->u
.clrsurrogate
.clsid
= xmlstrdupW(&attr_value
))) return FALSE
;
1133 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1137 if (error
|| end
) return end
;
1138 return parse_expect_end_elem(xmlbuf
, clrSurrogateW
);
1141 static BOOL
parse_dependent_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
, BOOL optional
)
1143 struct assembly_identity ai
;
1145 BOOL end
= FALSE
, ret
= TRUE
;
1147 if (!parse_expect_no_attr(xmlbuf
, &end
) || end
) return end
;
1149 memset(&ai
, 0, sizeof(ai
));
1150 ai
.optional
= optional
;
1152 if (!parse_expect_elem(xmlbuf
, assemblyIdentityW
) ||
1153 !parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &ai
))
1156 /* store the newly found identity for later loading */
1157 if (!add_dependent_assembly_id(acl
, &ai
)) return FALSE
;
1159 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1161 if (xmlstr_cmp_end(&elem
, dependentAssemblyW
))
1163 ret
= parse_end_element(xmlbuf
);
1166 else if (xmlstr_cmp(&elem
, bindingRedirectW
))
1168 ret
= parse_binding_redirect_elem(xmlbuf
);
1172 DPRINT1("unknown elem %s\n", elem
.ptr
);
1173 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1180 static BOOL
parse_dependency_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
)
1182 xmlstr_t attr_name
, attr_value
, elem
;
1183 BOOL end
= FALSE
, ret
= TRUE
, error
, optional
= FALSE
;
1185 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1187 if (xmlstr_cmp(&attr_name
, optionalW
))
1189 static const WCHAR yesW
[] = {'y','e','s',0};
1190 optional
= xmlstr_cmpi( &attr_value
, yesW
);
1191 DPRINT1("optional=%s\n", attr_value
.ptr
);
1195 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1199 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1201 if (xmlstr_cmp_end(&elem
, dependencyW
))
1203 ret
= parse_end_element(xmlbuf
);
1206 else if (xmlstr_cmp(&elem
, dependentAssemblyW
))
1208 ret
= parse_dependent_assembly_elem(xmlbuf
, acl
, optional
);
1212 DPRINT1("unknown element %s\n", elem
.ptr
);
1213 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1220 static BOOL
parse_noinherit_elem(xmlbuf_t
* xmlbuf
)
1224 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
1225 return end
|| parse_expect_end_elem(xmlbuf
, noInheritW
);
1228 static BOOL
parse_noinheritable_elem(xmlbuf_t
* xmlbuf
)
1232 if (!parse_expect_no_attr(xmlbuf
, &end
)) return FALSE
;
1233 return end
|| parse_expect_end_elem(xmlbuf
, noInheritableW
);
1236 static BOOL
parse_file_elem(xmlbuf_t
* xmlbuf
, struct assembly
* assembly
)
1238 xmlstr_t attr_name
, attr_value
, elem
;
1239 BOOL end
= FALSE
, error
, ret
= TRUE
;
1240 struct dll_redirect
* dll
;
1242 if (!(dll
= add_dll_redirect(assembly
))) return FALSE
;
1244 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1246 if (xmlstr_cmp(&attr_name
, nameW
))
1248 if (!(dll
->name
= xmlstrdupW(&attr_value
))) return FALSE
;
1249 DPRINT("name=%s\n", attr_value
.ptr
);
1251 else if (xmlstr_cmp(&attr_name
, hashW
))
1253 if (!(dll
->hash
= xmlstrdupW(&attr_value
))) return FALSE
;
1255 else if (xmlstr_cmp(&attr_name
, hashalgW
))
1257 static const WCHAR sha1W
[] = {'S','H','A','1',0};
1258 if (!xmlstr_cmpi(&attr_value
, sha1W
))
1259 DPRINT1("hashalg should be SHA1, got %s\n", attr_value
.ptr
);
1263 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1267 if (error
|| !dll
->name
) return FALSE
;
1268 if (end
) return TRUE
;
1270 while (ret
&& (ret
= next_xml_elem(xmlbuf
, &elem
)))
1272 if (xmlstr_cmp_end(&elem
, fileW
))
1274 ret
= parse_end_element(xmlbuf
);
1277 else if (xmlstr_cmp(&elem
, comClassW
))
1279 ret
= parse_com_class_elem(xmlbuf
, dll
);
1281 else if (xmlstr_cmp(&elem
, comInterfaceProxyStubW
))
1283 ret
= parse_cominterface_proxy_stub_elem(xmlbuf
, dll
);
1285 else if (xmlstr_cmp(&elem
, asmv2hashW
))
1287 DPRINT1("asmv2hash (undocumented) not supported\n");
1288 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1290 else if (xmlstr_cmp(&elem
, typelibW
))
1292 ret
= parse_typelib_elem(xmlbuf
, dll
);
1294 else if (xmlstr_cmp(&elem
, windowClassW
))
1296 ret
= parse_window_class_elem(xmlbuf
, dll
);
1300 DPRINT1("unknown elem %s\n", elem
.ptr
);
1301 ret
= parse_unknown_elem( xmlbuf
, &elem
);
1308 static BOOL
parse_assembly_elem(xmlbuf_t
* xmlbuf
, struct actctx_loader
* acl
,
1309 struct assembly
* assembly
,
1310 struct assembly_identity
* expected_ai
)
1312 xmlstr_t attr_name
, attr_value
, elem
;
1313 BOOL end
= FALSE
, error
, version
= FALSE
, xmlns
= FALSE
, ret
= TRUE
;
1315 while (next_xml_attr(xmlbuf
, &attr_name
, &attr_value
, &error
, &end
))
1317 if (xmlstr_cmp(&attr_name
, manifestVersionW
))
1319 static const WCHAR v10W
[] = {'1','.','0',0};
1320 if (!xmlstr_cmp(&attr_value
, v10W
))
1322 DPRINT1("wrong version %s\n", attr_value
.ptr
);
1327 else if (xmlstr_cmp(&attr_name
, xmlnsW
))
1329 if (!xmlstr_cmp(&attr_value
, manifestv1W
) && !xmlstr_cmp(&attr_value
, manifestv3W
))
1331 DPRINT1("wrong namespace %s\n", attr_value
.ptr
);
1338 DPRINT1("unknown attr %s=%s\n", attr_name
.ptr
, attr_value
.ptr
);
1342 if (error
|| end
|| !xmlns
|| !version
) return FALSE
;
1343 if (!next_xml_elem(xmlbuf
, &elem
)) return FALSE
;
1345 if (assembly
->type
== APPLICATION_MANIFEST
&& xmlstr_cmp(&elem
, noInheritW
))
1347 if (!parse_noinherit_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
1349 assembly
->no_inherit
= TRUE
;
1352 if (xmlstr_cmp(&elem
, noInheritableW
))
1354 if (!parse_noinheritable_elem(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
))
1357 else if ((assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
) &&
1358 assembly
->no_inherit
)
1363 if (xmlstr_cmp_end(&elem
, assemblyW
))
1365 ret
= parse_end_element(xmlbuf
);
1368 else if (xmlstr_cmp(&elem
, descriptionW
))
1370 ret
= parse_description_elem(xmlbuf
);
1372 else if (xmlstr_cmp(&elem
, comInterfaceExternalProxyStubW
))
1374 ret
= parse_com_interface_external_proxy_stub_elem(xmlbuf
, assembly
);
1376 else if (xmlstr_cmp(&elem
, dependencyW
))
1378 ret
= parse_dependency_elem(xmlbuf
, acl
);
1380 else if (xmlstr_cmp(&elem
, fileW
))
1382 ret
= parse_file_elem(xmlbuf
, assembly
);
1384 else if (xmlstr_cmp(&elem
, clrClassW
))
1386 ret
= parse_clr_class_elem(xmlbuf
, assembly
);
1388 else if (xmlstr_cmp(&elem
, clrSurrogateW
))
1390 ret
= parse_clr_surrogate_elem(xmlbuf
, assembly
);
1392 else if (xmlstr_cmp(&elem
, assemblyIdentityW
))
1394 if (!parse_assembly_identity_elem(xmlbuf
, acl
->actctx
, &assembly
->id
)) return FALSE
;
1398 /* FIXME: more tests */
1399 if (assembly
->type
== ASSEMBLY_MANIFEST
&&
1400 memcmp(&assembly
->id
.version
, &expected_ai
->version
, sizeof(assembly
->id
.version
)))
1402 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
1403 expected_ai
->version
.major
, expected_ai
->version
.minor
,
1404 expected_ai
->version
.build
, expected_ai
->version
.revision
,
1405 assembly
->id
.version
.major
, assembly
->id
.version
.minor
,
1406 assembly
->id
.version
.build
, assembly
->id
.version
.revision
);
1409 else if (assembly
->type
== ASSEMBLY_SHARED_MANIFEST
&&
1410 (assembly
->id
.version
.major
!= expected_ai
->version
.major
||
1411 assembly
->id
.version
.minor
!= expected_ai
->version
.minor
||
1412 assembly
->id
.version
.build
< expected_ai
->version
.build
||
1413 (assembly
->id
.version
.build
== expected_ai
->version
.build
&&
1414 assembly
->id
.version
.revision
< expected_ai
->version
.revision
)))
1416 DPRINT1("wrong version for shared assembly manifest\n");
1423 DPRINT1("unknown element %s\n", elem
.ptr
);
1424 ret
= parse_unknown_elem(xmlbuf
, &elem
);
1426 if (ret
) ret
= next_xml_elem(xmlbuf
, &elem
);
1432 static NTSTATUS
parse_manifest_buffer( struct actctx_loader
* acl
, struct assembly
*assembly
,
1433 struct assembly_identity
* ai
, xmlbuf_t
*xmlbuf
)
1437 if (!next_xml_elem(xmlbuf
, &elem
)) return STATUS_SXS_CANT_GEN_ACTCTX
;
1439 if (xmlstr_cmp(&elem
, xmlW
) &&
1440 (!parse_xml_header(xmlbuf
) || !next_xml_elem(xmlbuf
, &elem
)))
1441 return STATUS_SXS_CANT_GEN_ACTCTX
;
1443 if (!xmlstr_cmp(&elem
, assemblyW
))
1445 DPRINT1("root element is %s, not <assembly>\n", elem
.ptr
);
1446 return STATUS_SXS_CANT_GEN_ACTCTX
;
1449 if (!parse_assembly_elem(xmlbuf
, acl
, assembly
, ai
))
1451 DPRINT1("failed to parse manifest %s\n", assembly
->manifest
.info
);
1452 return STATUS_SXS_CANT_GEN_ACTCTX
;
1455 if (next_xml_elem(xmlbuf
, &elem
))
1457 DPRINT1("unexpected element %s\n", elem
.ptr
);
1458 return STATUS_SXS_CANT_GEN_ACTCTX
;
1461 if (xmlbuf
->ptr
!= xmlbuf
->end
)
1463 DPRINT1("parse error\n");
1464 return STATUS_SXS_CANT_GEN_ACTCTX
;
1466 return STATUS_SUCCESS
;
1469 static NTSTATUS
parse_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
1470 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
1471 const void *buffer
, SIZE_T size
)
1475 struct assembly
*assembly
;
1478 DPRINT( "parsing manifest loaded from %s base dir %s\n", filename
, directory
);
1480 if (!(assembly
= add_assembly(acl
->actctx
, shared
? ASSEMBLY_SHARED_MANIFEST
: ASSEMBLY_MANIFEST
)))
1481 return STATUS_SXS_CANT_GEN_ACTCTX
;
1483 if (directory
&& !(assembly
->directory
= strdupW(directory
)))
1484 return STATUS_NO_MEMORY
;
1486 if (filename
) assembly
->manifest
.info
= strdupW( filename
+ 4 /* skip \??\ prefix */ );
1487 assembly
->manifest
.type
= assembly
->manifest
.info
? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1488 : ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
1490 unicode_tests
= IS_TEXT_UNICODE_SIGNATURE
| IS_TEXT_UNICODE_REVERSE_SIGNATURE
;
1491 if (RtlIsTextUnicode( (PVOID
) buffer
, size
, &unicode_tests
))
1493 xmlbuf
.ptr
= buffer
;
1494 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
1495 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
1497 else if (unicode_tests
& IS_TEXT_UNICODE_REVERSE_SIGNATURE
)
1499 const WCHAR
*buf
= buffer
;
1503 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), 0, size
)))
1504 return STATUS_NO_MEMORY
;
1505 for (i
= 0; i
< size
/ sizeof(WCHAR
); i
++)
1506 new_buff
[i
] = RtlUshortByteSwap( buf
[i
] );
1507 xmlbuf
.ptr
= new_buff
;
1508 xmlbuf
.end
= xmlbuf
.ptr
+ size
/ sizeof(WCHAR
);
1509 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
1510 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
1514 /* let's assume utf-8 for now */
1519 len
= mbstowcs( NULL
, buffer
, size
);
1521 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1523 DPRINT1("Exception accessing buffer\n");
1524 return STATUS_SXS_CANT_GEN_ACTCTX
;
1528 DPRINT("len = %x\n", len
);
1533 DPRINT1( "utf-8 conversion failed\n" );
1534 return STATUS_SXS_CANT_GEN_ACTCTX
;
1536 if (!(new_buff
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
) )))
1537 return STATUS_NO_MEMORY
;
1539 mbstowcs( new_buff
, buffer
, len
);
1540 xmlbuf
.ptr
= new_buff
;
1541 DPRINT("Buffer %S\n", new_buff
);
1542 xmlbuf
.end
= xmlbuf
.ptr
+ len
;
1543 status
= parse_manifest_buffer( acl
, assembly
, ai
, &xmlbuf
);
1545 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff
);
1550 static NTSTATUS
open_nt_file( HANDLE
*handle
, UNICODE_STRING
*name
)
1552 OBJECT_ATTRIBUTES attr
;
1555 attr
.Length
= sizeof(attr
);
1556 attr
.RootDirectory
= 0;
1557 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1558 attr
.ObjectName
= name
;
1559 attr
.SecurityDescriptor
= NULL
;
1560 attr
.SecurityQualityOfService
= NULL
;
1561 return NtOpenFile( handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
, FILE_SYNCHRONOUS_IO_ALERT
);
1564 static NTSTATUS
get_module_filename( HMODULE module
, UNICODE_STRING
*str
, unsigned int extra_len
)
1568 LDR_DATA_TABLE_ENTRY
*pldr
;
1570 LdrLockLoaderLock(0, NULL
, &magic
);
1571 status
= LdrFindEntryForAddress( module
, &pldr
);
1572 if (status
== STATUS_SUCCESS
)
1574 if ((str
->Buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
1575 pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
) )))
1577 memcpy( str
->Buffer
, pldr
->FullDllName
.Buffer
, pldr
->FullDllName
.Length
+ sizeof(WCHAR
) );
1578 str
->Length
= pldr
->FullDllName
.Length
;
1579 str
->MaximumLength
= pldr
->FullDllName
.Length
+ extra_len
+ sizeof(WCHAR
);
1581 else status
= STATUS_NO_MEMORY
;
1583 LdrUnlockLoaderLock(0, magic
);
1587 static NTSTATUS
get_manifest_in_module( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
1588 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
1589 HANDLE hModule
, LPCWSTR resname
, ULONG lang
)
1592 UNICODE_STRING nameW
;
1593 LDR_RESOURCE_INFO info
;
1594 IMAGE_RESOURCE_DATA_ENTRY
* entry
= NULL
;
1598 if (TRACE_ON(actctx
))
1600 if (!filename
&& !get_module_filename( hModule
, &nameW
, 0 ))
1602 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
1603 hModule
, debugstr_w(nameW
.Buffer
) );
1604 RtlFreeUnicodeString( &nameW
);
1606 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname
),
1607 hModule
, debugstr_w(filename
) );
1611 if (!resname
) return STATUS_INVALID_PARAMETER
;
1613 info
.Type
= (ULONG_PTR
)RT_MANIFEST
;
1614 info
.Language
= lang
;
1615 if (!((ULONG_PTR
)resname
>> 16))
1617 info
.Name
= (ULONG_PTR
)resname
;
1618 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
1620 else if (resname
[0] == '#')
1623 RtlInitUnicodeString(&nameW
, resname
+ 1);
1624 if (RtlUnicodeStringToInteger(&nameW
, 10, &value
) != STATUS_SUCCESS
|| HIWORD(value
))
1625 return STATUS_INVALID_PARAMETER
;
1627 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
1631 RtlCreateUnicodeString(&nameW
, resname
);
1632 RtlUpcaseUnicodeString(&nameW
, &nameW
, FALSE
);
1633 info
.Name
= (ULONG_PTR
)nameW
.Buffer
;
1634 status
= LdrFindResource_U(hModule
, &info
, 3, &entry
);
1635 RtlFreeUnicodeString(&nameW
);
1637 if (status
== STATUS_SUCCESS
) status
= LdrAccessResource(hModule
, entry
, &ptr
, NULL
);
1639 if (status
== STATUS_SUCCESS
)
1640 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, ptr
, entry
->Size
);
1645 static NTSTATUS
get_manifest_in_pe_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
1646 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
,
1647 HANDLE file
, LPCWSTR resname
, ULONG lang
)
1650 OBJECT_ATTRIBUTES attr
;
1652 LARGE_INTEGER offset
;
1657 DPRINT( "looking for res %s in %s\n", resname
, filename
);
1659 attr
.Length
= sizeof(attr
);
1660 attr
.RootDirectory
= 0;
1661 attr
.ObjectName
= NULL
;
1662 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
1663 attr
.SecurityDescriptor
= NULL
;
1664 attr
.SecurityQualityOfService
= NULL
;
1667 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
1668 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1669 if (status
!= STATUS_SUCCESS
) return status
;
1671 offset
.QuadPart
= 0;
1674 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
1675 &count
, ViewShare
, 0, PAGE_READONLY
);
1677 if (status
!= STATUS_SUCCESS
) return status
;
1679 if (RtlImageNtHeader(base
)) /* we got a PE file */
1681 HANDLE module
= (HMODULE
)((ULONG_PTR
)base
| 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1682 status
= get_manifest_in_module( acl
, ai
, filename
, directory
, shared
, module
, resname
, lang
);
1684 else status
= STATUS_INVALID_IMAGE_FORMAT
;
1686 NtUnmapViewOfSection( NtCurrentProcess(), base
);
1690 static NTSTATUS
get_manifest_in_manifest_file( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
1691 LPCWSTR filename
, LPCWSTR directory
, BOOL shared
, HANDLE file
)
1693 FILE_STANDARD_INFORMATION info
;
1696 OBJECT_ATTRIBUTES attr
;
1698 LARGE_INTEGER offset
;
1703 DPRINT( "loading manifest file %S\n", filename
);
1705 attr
.Length
= sizeof(attr
);
1706 attr
.RootDirectory
= 0;
1707 attr
.ObjectName
= NULL
;
1708 attr
.Attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
;
1709 attr
.SecurityDescriptor
= NULL
;
1710 attr
.SecurityQualityOfService
= NULL
;
1713 status
= NtCreateSection( &mapping
, STANDARD_RIGHTS_REQUIRED
| SECTION_QUERY
| SECTION_MAP_READ
,
1714 &attr
, &size
, PAGE_READONLY
, SEC_COMMIT
, file
);
1716 if (status
!= STATUS_SUCCESS
) return status
;
1718 offset
.QuadPart
= 0;
1721 status
= NtMapViewOfSection( mapping
, NtCurrentProcess(), &base
, 0, 0, &offset
,
1722 &count
, ViewShare
, 0, PAGE_READONLY
);
1724 if (status
!= STATUS_SUCCESS
) return status
;
1726 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
1727 status
= NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
);
1729 if (status
== STATUS_SUCCESS
)
1730 status
= parse_manifest(acl
, ai
, filename
, directory
, shared
, base
, info
.EndOfFile
.QuadPart
);
1732 NtUnmapViewOfSection( NtCurrentProcess(), base
);
1737 /* try to load the .manifest file associated to the file */
1738 static NTSTATUS
get_manifest_in_associated_manifest( struct actctx_loader
* acl
, struct assembly_identity
* ai
,
1739 LPCWSTR filename
, LPCWSTR directory
, HMODULE module
, LPCWSTR resname
)
1741 static const WCHAR fmtW
[] = { '.','%','l','u',0 };
1744 UNICODE_STRING nameW
;
1746 ULONG_PTR resid
= (ULONG_PTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
1748 if (!((ULONG_PTR
)resname
>> 16)) resid
= (ULONG_PTR
)resname
& 0xffff;
1750 DPRINT( "looking for manifest associated with %s id %lu\n", filename
, resid
);
1752 if (module
) /* use the module filename */
1754 UNICODE_STRING name
;
1756 if (!(status
= get_module_filename( module
, &name
, sizeof(dotManifestW
) + 10*sizeof(WCHAR
) )))
1758 if (resid
!= 1) sprintfW( name
.Buffer
+ strlenW(name
.Buffer
), fmtW
, resid
);
1759 strcatW( name
.Buffer
, dotManifestW
);
1760 if (!RtlDosPathNameToNtPathName_U( name
.Buffer
, &nameW
, NULL
, NULL
))
1761 status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
1762 RtlFreeUnicodeString( &name
);
1764 if (status
) return status
;
1768 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
1769 (strlenW(filename
) + 10) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
1770 return STATUS_NO_MEMORY
;
1771 strcpyW( buffer
, filename
);
1772 if (resid
!= 1) sprintfW( buffer
+ strlenW(buffer
), fmtW
, resid
);
1773 strcatW( buffer
, dotManifestW
);
1774 RtlInitUnicodeString( &nameW
, buffer
);
1777 if (!open_nt_file( &file
, &nameW
))
1779 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
1782 else status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
1783 RtlFreeUnicodeString( &nameW
);
1787 static WCHAR
*lookup_manifest_file( HANDLE dir
, struct assembly_identity
*ai
)
1789 static const WCHAR lookup_fmtW
[] =
1790 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1792 '.','m','a','n','i','f','e','s','t',0};
1794 WCHAR
*lookup
, *ret
= NULL
;
1795 UNICODE_STRING lookup_us
;
1797 unsigned int data_pos
= 0, data_len
;
1800 if (!(lookup
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
1801 (strlenW(ai
->arch
) + strlenW(ai
->name
)
1802 + strlenW(ai
->public_key
) + 20) * sizeof(WCHAR
)
1803 + sizeof(lookup_fmtW
) )))
1806 sprintfW( lookup
, lookup_fmtW
, ai
->arch
, ai
->name
, ai
->public_key
, ai
->version
.major
, ai
->version
.minor
);
1807 RtlInitUnicodeString( &lookup_us
, lookup
);
1809 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
1810 FileBothDirectoryInformation
, FALSE
, &lookup_us
, TRUE
);
1811 if (io
.Status
== STATUS_SUCCESS
)
1813 FILE_BOTH_DIR_INFORMATION
*dir_info
;
1815 ULONG build
, revision
;
1817 data_len
= io
.Information
;
1821 if (data_pos
>= data_len
)
1823 NtQueryDirectoryFile( dir
, 0, NULL
, NULL
, &io
, buffer
, sizeof(buffer
),
1824 FileBothDirectoryInformation
, FALSE
, &lookup_us
, FALSE
);
1825 if (io
.Status
!= STATUS_SUCCESS
) break;
1826 data_len
= io
.Information
;
1829 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(buffer
+ data_pos
);
1831 if (dir_info
->NextEntryOffset
) data_pos
+= dir_info
->NextEntryOffset
;
1832 else data_pos
= data_len
;
1834 tmp
= (WCHAR
*)dir_info
->FileName
+ (strchrW(lookup
, '*') - lookup
);
1836 if (build
< ai
->version
.build
) continue;
1837 tmp
= strchrW(tmp
, '.') + 1;
1838 revision
= atoiW(tmp
);
1839 if (build
== ai
->version
.build
&& revision
< ai
->version
.revision
)
1841 ai
->version
.build
= build
;
1842 ai
->version
.revision
= revision
;
1844 if ((ret
= RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info
->FileNameLength
* sizeof(WCHAR
) )))
1846 memcpy( ret
, dir_info
->FileName
, dir_info
->FileNameLength
);
1847 ret
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
1852 else DPRINT1("no matching file for %s\n", lookup
);
1853 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup
);
1857 static NTSTATUS
lookup_winsxs(struct actctx_loader
* acl
, struct assembly_identity
* ai
)
1859 struct assembly_identity sxs_ai
;
1860 UNICODE_STRING path_us
;
1861 OBJECT_ATTRIBUTES attr
;
1863 WCHAR
*path
, *file
= NULL
;
1866 static const WCHAR manifest_dirW
[] =
1867 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
1869 if (!ai
->arch
|| !ai
->name
|| !ai
->public_key
) return STATUS_NO_SUCH_FILE
;
1871 if (!(path
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
1872 ((strlenW(SharedUserData
->NtSystemRoot
) + 1) *sizeof(WCHAR
)) + sizeof(manifest_dirW
) )))
1873 return STATUS_NO_MEMORY
;
1875 memcpy( path
, SharedUserData
->NtSystemRoot
, strlenW(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
) );
1876 memcpy( path
+ strlenW(SharedUserData
->NtSystemRoot
), manifest_dirW
, sizeof(manifest_dirW
) );
1878 if (!RtlDosPathNameToNtPathName_U( path
, &path_us
, NULL
, NULL
))
1880 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
1881 return STATUS_NO_SUCH_FILE
;
1883 RtlFreeHeap( RtlGetProcessHeap(), 0, path
);
1885 attr
.Length
= sizeof(attr
);
1886 attr
.RootDirectory
= 0;
1887 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1888 attr
.ObjectName
= &path_us
;
1889 attr
.SecurityDescriptor
= NULL
;
1890 attr
.SecurityQualityOfService
= NULL
;
1892 if (!NtOpenFile( &handle
, GENERIC_READ
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1893 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
))
1896 file
= lookup_manifest_file( handle
, &sxs_ai
);
1901 RtlFreeUnicodeString( &path_us
);
1902 return STATUS_NO_SUCH_FILE
;
1905 /* append file name to directory path */
1906 if (!(path
= RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us
.Buffer
,
1907 path_us
.Length
+ (strlenW(file
) + 2) * sizeof(WCHAR
) )))
1909 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
1910 RtlFreeUnicodeString( &path_us
);
1911 return STATUS_NO_MEMORY
;
1914 path
[path_us
.Length
/sizeof(WCHAR
)] = '\\';
1915 strcpyW( path
+ path_us
.Length
/sizeof(WCHAR
) + 1, file
);
1916 RtlInitUnicodeString( &path_us
, path
);
1917 *strrchrW(file
, '.') = 0; /* remove .manifest extension */
1919 if (!open_nt_file( &handle
, &path_us
))
1921 io
.Status
= get_manifest_in_manifest_file(acl
, &sxs_ai
, path_us
.Buffer
, file
, TRUE
, handle
);
1924 else io
.Status
= STATUS_NO_SUCH_FILE
;
1926 RtlFreeHeap( RtlGetProcessHeap(), 0, file
);
1927 RtlFreeUnicodeString( &path_us
);
1931 static NTSTATUS
lookup_assembly(struct actctx_loader
* acl
,
1932 struct assembly_identity
* ai
)
1934 static const WCHAR dotDllW
[] = {'.','d','l','l',0};
1936 WCHAR
*buffer
, *p
, *directory
;
1938 UNICODE_STRING nameW
;
1941 DPRINT1( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
1942 ai
->name
, ai
->version
.major
, ai
->version
.minor
, ai
->version
.build
, ai
->version
.revision
, ai
->arch
);
1944 if ((status
= lookup_winsxs(acl
, ai
)) != STATUS_NO_SUCH_FILE
) return status
;
1946 /* FIXME: add support for language specific lookup */
1948 nameW
.Buffer
= NULL
;
1949 if (!(buffer
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
1950 (strlenW(acl
->actctx
->appdir
.info
) + 2 * strlenW(ai
->name
) + 2) * sizeof(WCHAR
) + sizeof(dotManifestW
) )))
1951 return STATUS_NO_MEMORY
;
1953 if (!(directory
= build_assembly_dir( ai
)))
1955 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
1956 return STATUS_NO_MEMORY
;
1959 /* lookup in appdir\name.dll
1960 * appdir\name.manifest
1961 * appdir\name\name.dll
1962 * appdir\name\name.manifest
1964 strcpyW( buffer
, acl
->actctx
->appdir
.info
);
1965 p
= buffer
+ strlenW(buffer
);
1966 for (i
= 0; i
< 2; i
++)
1969 strcpyW( p
, ai
->name
);
1972 strcpyW( p
, dotDllW
);
1973 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
1975 status
= open_nt_file( &file
, &nameW
);
1978 status
= get_manifest_in_pe_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
,
1979 (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
, 0 );
1983 RtlFreeUnicodeString( &nameW
);
1986 strcpyW( p
, dotManifestW
);
1987 if (RtlDosPathNameToNtPathName_U( buffer
, &nameW
, NULL
, NULL
))
1989 status
= open_nt_file( &file
, &nameW
);
1992 status
= get_manifest_in_manifest_file( acl
, ai
, nameW
.Buffer
, directory
, FALSE
, file
);
1996 RtlFreeUnicodeString( &nameW
);
1998 status
= STATUS_SXS_ASSEMBLY_NOT_FOUND
;
2000 RtlFreeUnicodeString( &nameW
);
2001 RtlFreeHeap( RtlGetProcessHeap(), 0, directory
);
2002 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer
);
2006 static NTSTATUS
parse_depend_manifests(struct actctx_loader
* acl
)
2008 NTSTATUS status
= STATUS_SUCCESS
;
2011 for (i
= 0; i
< acl
->num_dependencies
; i
++)
2013 if (lookup_assembly(acl
, &acl
->dependencies
[i
]) != STATUS_SUCCESS
)
2015 if (!acl
->dependencies
[i
].optional
)
2017 DPRINT1( "Could not find dependent assembly %S\n", acl
->dependencies
[i
].name
);
2018 status
= STATUS_SXS_CANT_GEN_ACTCTX
;
2023 /* FIXME should now iterate through all refs */
2027 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2028 static NTSTATUS
find_query_actctx( HANDLE
*handle
, DWORD flags
, ULONG
class )
2030 NTSTATUS status
= STATUS_SUCCESS
;
2032 if (flags
& QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
)
2034 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
2035 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
2037 else if (flags
& (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
))
2040 LDR_DATA_TABLE_ENTRY
*pldr
;
2042 LdrLockLoaderLock( 0, NULL
, &magic
);
2043 if (!LdrFindEntryForAddress( *handle
, &pldr
))
2045 if ((flags
& QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
) && *handle
!= pldr
->DllBase
)
2046 status
= STATUS_DLL_NOT_FOUND
;
2048 *handle
= pldr
->EntryPointActivationContext
;
2050 else status
= STATUS_DLL_NOT_FOUND
;
2051 LdrUnlockLoaderLock( 0, magic
);
2053 else if (!*handle
&& (class != ActivationContextBasicInformation
))
2054 *handle
= process_actctx
;
2059 static NTSTATUS
fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data
, PVOID v1
, PVOID v2
, unsigned int i
)
2061 data
->ulDataFormatVersion
= 1;
2063 data
->ulLength
= 20; /* FIXME */
2064 data
->lpSectionGlobalData
= NULL
; /* FIXME */
2065 data
->ulSectionGlobalDataLength
= 0; /* FIXME */
2066 data
->lpSectionBase
= v2
;
2067 data
->ulSectionTotalLength
= 0; /* FIXME */
2068 data
->hActCtx
= NULL
;
2069 if (data
->cbSize
>= offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) + sizeof(ULONG
))
2070 data
->ulAssemblyRosterIndex
= i
+ 1;
2072 return STATUS_SUCCESS
;
2075 static NTSTATUS
find_dll_redirection(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*section_name
,
2076 PACTCTX_SECTION_KEYED_DATA data
)
2078 unsigned int i
, j
, snlen
= section_name
->Length
/ sizeof(WCHAR
);
2080 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2082 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2083 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2085 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2086 if (!strncmpiW(section_name
->Buffer
, dll
->name
, snlen
) && !dll
->name
[snlen
])
2087 return fill_keyed_data(data
, dll
, assembly
, i
);
2090 return STATUS_SXS_KEY_NOT_FOUND
;
2093 static NTSTATUS
find_window_class(ACTIVATION_CONTEXT
* actctx
, const UNICODE_STRING
*section_name
,
2094 PACTCTX_SECTION_KEYED_DATA data
)
2096 unsigned int i
, j
, k
, snlen
= section_name
->Length
/ sizeof(WCHAR
);
2098 for (i
= 0; i
< actctx
->num_assemblies
; i
++)
2100 struct assembly
*assembly
= &actctx
->assemblies
[i
];
2101 for (j
= 0; j
< assembly
->num_dlls
; j
++)
2103 struct dll_redirect
*dll
= &assembly
->dlls
[j
];
2104 for (k
= 0; k
< dll
->entities
.num
; k
++)
2106 struct entity
*entity
= &dll
->entities
.base
[k
];
2107 if (entity
->kind
== ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
)
2109 if (!strncmpiW(section_name
->Buffer
, entity
->u
.class.name
, snlen
) && !entity
->u
.class.name
[snlen
])
2110 return fill_keyed_data(data
, entity
, dll
, i
);
2115 return STATUS_SXS_KEY_NOT_FOUND
;
2118 static NTSTATUS
find_string(ACTIVATION_CONTEXT
* actctx
, ULONG section_kind
,
2119 const UNICODE_STRING
*section_name
,
2120 DWORD flags
, PACTCTX_SECTION_KEYED_DATA data
)
2124 switch (section_kind
)
2126 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
:
2127 status
= find_dll_redirection(actctx
, section_name
, data
);
2129 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
:
2130 status
= find_window_class(actctx
, section_name
, data
);
2132 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
:
2133 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
:
2134 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
:
2135 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
:
2136 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE
:
2137 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES
:
2138 DPRINT1("Unsupported yet section_kind %x\n", section_kind
);
2139 return STATUS_SXS_SECTION_NOT_FOUND
;
2141 DPRINT1("Unknown section_kind %x\n", section_kind
);
2142 return STATUS_SXS_SECTION_NOT_FOUND
;
2145 if (status
!= STATUS_SUCCESS
) return status
;
2147 if (flags
& FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
2149 actctx_addref(actctx
);
2150 data
->hActCtx
= actctx
;
2152 return STATUS_SUCCESS
;
2155 /* initialize the activation context for the current process */
2156 void actctx_init(void)
2161 ctx
.cbSize
= sizeof(ctx
);
2162 ctx
.lpSource
= NULL
;
2163 ctx
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
2164 ctx
.hModule
= NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
;
2165 ctx
.lpResourceName
= (LPCWSTR
)CREATEPROCESS_MANIFEST_RESOURCE_ID
;
2167 if (!RtlCreateActivationContext( &handle
, &ctx
)) process_actctx
= check_actctx(handle
);
2170 /* FUNCTIONS ***************************************************************/
2172 NTSTATUS WINAPI
RtlCreateActivationContext( HANDLE
*handle
, void *ptr
)
2174 const ACTCTXW
*pActCtx
= ptr
;
2175 const WCHAR
*directory
= NULL
;
2176 ACTIVATION_CONTEXT
*actctx
;
2177 UNICODE_STRING nameW
;
2179 NTSTATUS status
= STATUS_NO_MEMORY
;
2181 struct actctx_loader acl
;
2183 DPRINT("%p %08x\n", pActCtx
, pActCtx
? pActCtx
->dwFlags
: 0);
2185 if (!pActCtx
|| pActCtx
->cbSize
< sizeof(*pActCtx
) ||
2186 (pActCtx
->dwFlags
& ~ACTCTX_FLAGS_ALL
))
2187 return STATUS_INVALID_PARAMETER
;
2190 if (!(actctx
= RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*actctx
) )))
2191 return STATUS_NO_MEMORY
;
2193 actctx
->magic
= ACTCTX_MAGIC
;
2194 actctx
->ref_count
= 1;
2195 actctx
->config
.type
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
;
2196 actctx
->config
.info
= NULL
;
2197 actctx
->appdir
.type
= ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
;
2198 if (pActCtx
->dwFlags
& ACTCTX_FLAG_APPLICATION_NAME_VALID
)
2200 if (!(actctx
->appdir
.info
= strdupW( pActCtx
->lpApplicationName
))) goto error
;
2207 if ((status
= get_module_filename( NtCurrentTeb()->ProcessEnvironmentBlock
->ImageBaseAddress
, &dir
, 0 )))
2210 if ((p
= strrchrW( dir
.Buffer
, '\\' ))) p
[1] = 0;
2211 actctx
->appdir
.info
= dir
.Buffer
;
2214 nameW
.Buffer
= NULL
;
2215 if (pActCtx
->lpSource
)
2217 if (!RtlDosPathNameToNtPathName_U(pActCtx
->lpSource
, &nameW
, NULL
, NULL
))
2219 status
= STATUS_NO_SUCH_FILE
;
2222 status
= open_nt_file( &file
, &nameW
);
2225 RtlFreeUnicodeString( &nameW
);
2230 acl
.actctx
= actctx
;
2231 acl
.dependencies
= NULL
;
2232 acl
.num_dependencies
= 0;
2233 acl
.allocated_dependencies
= 0;
2235 if (pActCtx
->dwFlags
& ACTCTX_FLAG_LANGID_VALID
) lang
= pActCtx
->wLangId
;
2236 if (pActCtx
->dwFlags
& ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID
) directory
= pActCtx
->lpAssemblyDirectory
;
2238 if (pActCtx
->dwFlags
& ACTCTX_FLAG_RESOURCE_NAME_VALID
)
2240 /* if we have a resource it's a PE file */
2241 if (pActCtx
->dwFlags
& ACTCTX_FLAG_HMODULE_VALID
)
2243 status
= get_manifest_in_module( &acl
, NULL
, NULL
, directory
, FALSE
, pActCtx
->hModule
,
2244 pActCtx
->lpResourceName
, lang
);
2245 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
2246 /* FIXME: what to do if pActCtx->lpSource is set */
2247 status
= get_manifest_in_associated_manifest( &acl
, NULL
, NULL
, directory
,
2248 pActCtx
->hModule
, pActCtx
->lpResourceName
);
2250 else if (pActCtx
->lpSource
)
2252 status
= get_manifest_in_pe_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
,
2253 file
, pActCtx
->lpResourceName
, lang
);
2254 if (status
&& status
!= STATUS_SXS_CANT_GEN_ACTCTX
)
2255 status
= get_manifest_in_associated_manifest( &acl
, NULL
, nameW
.Buffer
, directory
,
2256 NULL
, pActCtx
->lpResourceName
);
2258 else status
= STATUS_INVALID_PARAMETER
;
2262 status
= get_manifest_in_manifest_file( &acl
, NULL
, nameW
.Buffer
, directory
, FALSE
, file
);
2265 if (file
) NtClose( file
);
2266 RtlFreeUnicodeString( &nameW
);
2268 if (status
== STATUS_SUCCESS
) status
= parse_depend_manifests(&acl
);
2269 free_depend_manifests( &acl
);
2271 if (status
== STATUS_SUCCESS
) *handle
= actctx
;
2272 else actctx_release( actctx
);
2277 if (file
) NtClose( file
);
2278 actctx_release( actctx
);
2284 RtlAddRefActivationContext(HANDLE handle
)
2286 ACTIVATION_CONTEXT
*actctx
;
2288 if ((actctx
= check_actctx( handle
))) actctx_addref( actctx
);
2293 RtlReleaseActivationContext( HANDLE handle
)
2295 ACTIVATION_CONTEXT
*actctx
;
2297 if ((actctx
= check_actctx( handle
))) actctx_release( actctx
);
2301 NTAPI
RtlActivateActivationContext( ULONG unknown
, HANDLE handle
, PULONG_PTR cookie
)
2303 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
2305 if (!(frame
= RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame
) )))
2306 return STATUS_NO_MEMORY
;
2308 frame
->Previous
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
2309 frame
->ActivationContext
= handle
;
2312 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
;
2313 RtlAddRefActivationContext( handle
);
2315 *cookie
= (ULONG_PTR
)frame
;
2316 DPRINT( "%p cookie=%lx\n", handle
, *cookie
);
2317 return STATUS_SUCCESS
;
2323 RtlDeactivateActivationContext( ULONG flags
, ULONG_PTR cookie
)
2325 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
, *top
;
2327 DPRINT( "%x cookie=%lx\n", flags
, cookie
);
2329 /* find the right frame */
2330 top
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
2331 for (frame
= top
; frame
; frame
= frame
->Previous
)
2332 if ((ULONG_PTR
)frame
== cookie
) break;
2335 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION
);
2337 if (frame
!= top
&& !(flags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
))
2338 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION
);
2340 /* pop everything up to and including frame */
2341 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= frame
->Previous
;
2343 while (top
!= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
2345 frame
= top
->Previous
;
2346 RtlReleaseActivationContext( top
->ActivationContext
);
2347 RtlFreeHeap( RtlGetProcessHeap(), 0, top
);
2351 return STATUS_SUCCESS
;
2355 NTAPI
RtlFreeThreadActivationContextStack(void)
2357 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
2359 frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
;
2362 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*prev
= frame
->Previous
;
2363 RtlReleaseActivationContext( frame
->ActivationContext
);
2364 RtlFreeHeap( RtlGetProcessHeap(), 0, frame
);
2367 NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
= NULL
;
2372 NTAPI
RtlGetActiveActivationContext( HANDLE
*handle
)
2374 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
2376 *handle
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
;
2377 RtlAddRefActivationContext( *handle
);
2382 return STATUS_SUCCESS
;
2387 NTAPI
RtlIsActivationContextActive( HANDLE handle
)
2389 RTL_ACTIVATION_CONTEXT_STACK_FRAME
*frame
;
2391 for (frame
= NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
; frame
; frame
= frame
->Previous
)
2392 if (frame
->ActivationContext
== handle
) return TRUE
;
2398 RtlQueryInformationActivationContext( ULONG flags
, HANDLE handle
, PVOID subinst
,
2399 ULONG
class, PVOID buffer
,
2400 SIZE_T bufsize
, SIZE_T
*retlen
)
2402 ACTIVATION_CONTEXT
*actctx
;
2405 DPRINT("%08x %p %p %u %p %ld %p\n", flags
, handle
,
2406 subinst
, class, buffer
, bufsize
, retlen
);
2408 if (retlen
) *retlen
= 0;
2409 if ((status
= find_query_actctx( &handle
, flags
, class ))) return status
;
2413 case ActivationContextBasicInformation
:
2415 ACTIVATION_CONTEXT_BASIC_INFORMATION
*info
= buffer
;
2417 if (retlen
) *retlen
= sizeof(*info
);
2418 if (!info
|| bufsize
< sizeof(*info
)) return STATUS_BUFFER_TOO_SMALL
;
2420 info
->hActCtx
= handle
;
2421 info
->dwFlags
= 0; /* FIXME */
2422 if (!(flags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)) RtlAddRefActivationContext( handle
);
2426 case ActivationContextDetailedInformation
:
2428 ACTIVATION_CONTEXT_DETAILED_INFORMATION
*acdi
= buffer
;
2429 struct assembly
*assembly
= NULL
;
2430 SIZE_T len
, manifest_len
= 0, config_len
= 0, appdir_len
= 0;
2433 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
2435 if (actctx
->num_assemblies
) assembly
= actctx
->assemblies
;
2437 if (assembly
&& assembly
->manifest
.info
)
2438 manifest_len
= strlenW(assembly
->manifest
.info
) + 1;
2439 if (actctx
->config
.info
) config_len
= strlenW(actctx
->config
.info
) + 1;
2440 if (actctx
->appdir
.info
) appdir_len
= strlenW(actctx
->appdir
.info
) + 1;
2441 len
= sizeof(*acdi
) + (manifest_len
+ config_len
+ appdir_len
) * sizeof(WCHAR
);
2443 if (retlen
) *retlen
= len
;
2444 if (!buffer
|| bufsize
< len
) return STATUS_BUFFER_TOO_SMALL
;
2447 acdi
->ulFormatVersion
= assembly
? 1 : 0; /* FIXME */
2448 acdi
->ulAssemblyCount
= actctx
->num_assemblies
;
2449 acdi
->ulRootManifestPathType
= assembly
? assembly
->manifest
.type
: 0 /* FIXME */;
2450 acdi
->ulRootManifestPathChars
= assembly
&& assembly
->manifest
.info
? manifest_len
- 1 : 0;
2451 acdi
->ulRootConfigurationPathType
= actctx
->config
.type
;
2452 acdi
->ulRootConfigurationPathChars
= actctx
->config
.info
? config_len
- 1 : 0;
2453 acdi
->ulAppDirPathType
= actctx
->appdir
.type
;
2454 acdi
->ulAppDirPathChars
= actctx
->appdir
.info
? appdir_len
- 1 : 0;
2455 ptr
= (LPWSTR
)(acdi
+ 1);
2458 acdi
->lpRootManifestPath
= ptr
;
2459 memcpy(ptr
, assembly
->manifest
.info
, manifest_len
* sizeof(WCHAR
));
2460 ptr
+= manifest_len
;
2462 else acdi
->lpRootManifestPath
= NULL
;
2465 acdi
->lpRootConfigurationPath
= ptr
;
2466 memcpy(ptr
, actctx
->config
.info
, config_len
* sizeof(WCHAR
));
2469 else acdi
->lpRootConfigurationPath
= NULL
;
2472 acdi
->lpAppDirPath
= ptr
;
2473 memcpy(ptr
, actctx
->appdir
.info
, appdir_len
* sizeof(WCHAR
));
2475 else acdi
->lpAppDirPath
= NULL
;
2479 case AssemblyDetailedInformationInActivationContext
:
2481 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*afdi
= buffer
;
2482 struct assembly
*assembly
;
2485 SIZE_T len
, id_len
= 0, ad_len
= 0, path_len
= 0;
2488 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
2489 if (!subinst
) return STATUS_INVALID_PARAMETER
;
2491 index
= *(DWORD
*)subinst
;
2492 if (!index
|| index
> actctx
->num_assemblies
) return STATUS_INVALID_PARAMETER
;
2494 assembly
= &actctx
->assemblies
[index
- 1];
2496 if (!(assembly_id
= build_assembly_id( &assembly
->id
))) return STATUS_NO_MEMORY
;
2497 id_len
= strlenW(assembly_id
) + 1;
2498 if (assembly
->directory
) ad_len
= strlenW(assembly
->directory
) + 1;
2500 if (assembly
->manifest
.info
&&
2501 (assembly
->type
== ASSEMBLY_MANIFEST
|| assembly
->type
== ASSEMBLY_SHARED_MANIFEST
))
2502 path_len
= strlenW(assembly
->manifest
.info
) + 1;
2504 len
= sizeof(*afdi
) + (id_len
+ ad_len
+ path_len
) * sizeof(WCHAR
);
2506 if (retlen
) *retlen
= len
;
2507 if (!buffer
|| bufsize
< len
)
2509 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
2510 return STATUS_BUFFER_TOO_SMALL
;
2513 afdi
->ulFlags
= 0; /* FIXME */
2514 afdi
->ulEncodedAssemblyIdentityLength
= (id_len
- 1) * sizeof(WCHAR
);
2515 afdi
->ulManifestPathType
= assembly
->manifest
.type
;
2516 afdi
->ulManifestPathLength
= assembly
->manifest
.info
? (path_len
- 1) * sizeof(WCHAR
) : 0;
2517 /* FIXME afdi->liManifestLastWriteTime = 0; */
2518 afdi
->ulPolicyPathType
= ACTIVATION_CONTEXT_PATH_TYPE_NONE
; /* FIXME */
2519 afdi
->ulPolicyPathLength
= 0;
2520 /* FIXME afdi->liPolicyLastWriteTime = 0; */
2521 afdi
->ulMetadataSatelliteRosterIndex
= 0; /* FIXME */
2522 afdi
->ulManifestVersionMajor
= 1;
2523 afdi
->ulManifestVersionMinor
= 0;
2524 afdi
->ulPolicyVersionMajor
= 0; /* FIXME */
2525 afdi
->ulPolicyVersionMinor
= 0; /* FIXME */
2526 afdi
->ulAssemblyDirectoryNameLength
= ad_len
? (ad_len
- 1) * sizeof(WCHAR
) : 0;
2527 ptr
= (LPWSTR
)(afdi
+ 1);
2528 afdi
->lpAssemblyEncodedAssemblyIdentity
= ptr
;
2529 memcpy( ptr
, assembly_id
, id_len
* sizeof(WCHAR
) );
2533 afdi
->lpAssemblyManifestPath
= ptr
;
2534 memcpy(ptr
, assembly
->manifest
.info
, path_len
* sizeof(WCHAR
));
2536 } else afdi
->lpAssemblyManifestPath
= NULL
;
2537 afdi
->lpAssemblyPolicyPath
= NULL
; /* FIXME */
2540 afdi
->lpAssemblyDirectoryName
= ptr
;
2541 memcpy(ptr
, assembly
->directory
, ad_len
* sizeof(WCHAR
));
2544 else afdi
->lpAssemblyDirectoryName
= NULL
;
2545 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id
);
2549 case FileInformationInAssemblyOfAssemblyInActivationContext
:
2551 const ACTIVATION_CONTEXT_QUERY_INDEX
*acqi
= subinst
;
2552 ASSEMBLY_FILE_DETAILED_INFORMATION
*afdi
= buffer
;
2553 struct assembly
*assembly
;
2554 struct dll_redirect
*dll
;
2555 SIZE_T len
, dll_len
= 0;
2558 if (!(actctx
= check_actctx(handle
))) return STATUS_INVALID_PARAMETER
;
2559 if (!acqi
) return STATUS_INVALID_PARAMETER
;
2561 if (acqi
->ulAssemblyIndex
>= actctx
->num_assemblies
)
2562 return STATUS_INVALID_PARAMETER
;
2563 assembly
= &actctx
->assemblies
[acqi
->ulAssemblyIndex
];
2565 if (acqi
->ulFileIndexInAssembly
>= assembly
->num_dlls
)
2566 return STATUS_INVALID_PARAMETER
;
2567 dll
= &assembly
->dlls
[acqi
->ulFileIndexInAssembly
];
2569 if (dll
->name
) dll_len
= strlenW(dll
->name
) + 1;
2570 len
= sizeof(*afdi
) + dll_len
* sizeof(WCHAR
);
2572 if (!buffer
|| bufsize
< len
)
2574 if (retlen
) *retlen
= len
;
2575 return STATUS_BUFFER_TOO_SMALL
;
2577 if (retlen
) *retlen
= 0; /* yes that's what native does !! */
2578 afdi
->ulFlags
= ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
;
2579 afdi
->ulFilenameLength
= dll_len
? (dll_len
- 1) * sizeof(WCHAR
) : 0;
2580 afdi
->ulPathLength
= 0; /* FIXME */
2581 ptr
= (LPWSTR
)(afdi
+ 1);
2584 afdi
->lpFileName
= ptr
;
2585 memcpy( ptr
, dll
->name
, dll_len
* sizeof(WCHAR
) );
2586 } else afdi
->lpFileName
= NULL
;
2587 afdi
->lpFilePath
= NULL
; /* FIXME */
2592 DPRINT( "class %u not implemented\n", class );
2593 return STATUS_NOT_IMPLEMENTED
;
2595 return STATUS_SUCCESS
;
2600 RtlFindActivationContextSectionString( ULONG flags
, const GUID
*guid
, ULONG section_kind
,
2601 UNICODE_STRING
*section_name
, PVOID ptr
)
2603 PACTCTX_SECTION_KEYED_DATA data
= ptr
;
2604 NTSTATUS status
= STATUS_SXS_KEY_NOT_FOUND
;
2608 DPRINT1("expected guid == NULL\n");
2609 return STATUS_INVALID_PARAMETER
;
2611 if (flags
& ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
)
2613 DPRINT1("unknown flags %08x\n", flags
);
2614 return STATUS_INVALID_PARAMETER
;
2616 if (!data
|| data
->cbSize
< offsetof(ACTCTX_SECTION_KEYED_DATA
, ulAssemblyRosterIndex
) ||
2617 !section_name
|| !section_name
->Buffer
)
2619 DPRINT1("invalid parameter\n");
2620 return STATUS_INVALID_PARAMETER
;
2623 ASSERT(NtCurrentTeb());
2624 ASSERT(NtCurrentTeb()->ActivationContextStackPointer
);
2626 if (NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
)
2628 ACTIVATION_CONTEXT
*actctx
= check_actctx(NtCurrentTeb()->ActivationContextStackPointer
->ActiveFrame
->ActivationContext
);
2629 if (actctx
) status
= find_string( actctx
, section_kind
, section_name
, flags
, data
);
2632 if (status
!= STATUS_SUCCESS
)
2633 status
= find_string( process_actctx
, section_kind
, section_name
, flags
, data
);
2642 RtlAllocateActivationContextStack(IN PVOID
*Context
)
2644 PACTIVATION_CONTEXT_STACK ContextStack
;
2645 ContextStack
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof (ACTIVATION_CONTEXT_STACK
) );
2648 return STATUS_NO_MEMORY
;
2651 ContextStack
->ActiveFrame
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME
));
2652 if (!ContextStack
->ActiveFrame
) return STATUS_NO_MEMORY
;
2654 *Context
= ContextStack
;
2656 /* FIXME: Documentation on MSDN reads that activation contexts are only created
2657 for modules that have a valid manifest file or resource */
2660 return STATUS_SUCCESS
;
2665 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
,
2669 return STATUS_NOT_IMPLEMENTED
;
2674 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame
)
2677 return STATUS_NOT_IMPLEMENTED
;
2683 RtlZombifyActivationContext(PVOID Context
)
2687 if (Context
== ACTCTX_FAKE_HANDLE
)
2688 return STATUS_SUCCESS
;
2690 return STATUS_NOT_IMPLEMENTED
;