ntdll: Don't add an empty assembly when creating an activation context.
[wine.git] / dlls / ntdll / actctx.c
blob1e2e101cf8d54381fe0718a9488dc0a7a9b0f8b6
1 /*
2 * Activation contexts
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
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdio.h>
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "winternl.h"
35 #include "ntdll_misc.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
41 #define ACTCTX_FLAGS_ALL (\
42 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
43 ACTCTX_FLAG_LANGID_VALID |\
44 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
45 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
46 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
47 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
48 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
49 ACTCTX_FLAG_HMODULE_VALID )
51 #define ACTCTX_MAGIC 0xC07E3E11
53 /* we don't want to include winuser.h */
54 #define RT_MANIFEST ((ULONG_PTR)24)
55 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
57 typedef struct
59 const char* ptr;
60 unsigned int len;
61 } xmlstr_t;
63 typedef struct
65 const char* ptr;
66 const char* end;
67 } xmlbuf_t;
69 struct file_info
71 ULONG type;
72 WCHAR *info;
75 struct version
77 USHORT major;
78 USHORT minor;
79 USHORT build;
80 USHORT revision;
83 enum assembly_id_type
85 TYPE_NONE,
86 TYPE_WIN32
89 struct assembly_identity
91 WCHAR *name;
92 WCHAR *arch;
93 WCHAR *public_key;
94 WCHAR *language;
95 struct version version;
96 enum assembly_id_type type;
97 BOOL optional;
100 struct entity
102 DWORD kind;
103 union
105 struct
107 WCHAR *tlbid;
108 WCHAR *version;
109 WCHAR *helpdir;
110 } typelib;
111 struct
113 WCHAR *clsid;
114 } comclass;
115 struct {
116 WCHAR *iid;
117 WCHAR *name;
118 } proxy;
119 struct
121 WCHAR *name;
122 } class;
123 struct
125 WCHAR *name;
126 WCHAR *clsid;
127 } clrclass;
128 struct
130 WCHAR *name;
131 WCHAR *clsid;
132 } clrsurrogate;
133 } u;
136 struct entity_array
138 struct entity *base;
139 unsigned int num;
140 unsigned int allocated;
143 struct dll_redirect
145 WCHAR *name;
146 WCHAR *hash;
147 struct entity_array entities;
150 enum assembly_type
152 APPLICATION_MANIFEST,
153 ASSEMBLY_MANIFEST
156 struct assembly
158 enum assembly_type type;
159 struct assembly_identity id;
160 struct file_info manifest;
161 BOOL no_inherit;
162 struct dll_redirect *dlls;
163 unsigned int num_dlls;
164 unsigned int allocated_dlls;
165 struct entity_array entities;
168 typedef struct _ACTIVATION_CONTEXT
170 ULONG magic;
171 int ref_count;
172 struct file_info config;
173 struct file_info appdir;
174 struct assembly *assemblies;
175 unsigned int num_assemblies;
176 unsigned int allocated_assemblies;
177 } ACTIVATION_CONTEXT;
179 struct actctx_loader
181 ACTIVATION_CONTEXT *actctx;
182 struct assembly_identity *dependencies;
183 unsigned int num_dependencies;
184 unsigned int allocated_dependencies;
187 #define ASSEMBLY_ELEM "assembly"
188 #define ASSEMBLYIDENTITY_ELEM "assemblyIdentity"
189 #define BINDINGREDIRECT_ELEM "bindingRedirect"
190 #define CLRCLASS_ELEM "clrClass"
191 #define CLRSURROGATE_ELEM "clrSurrogate"
192 #define COMCLASS_ELEM "comClass"
193 #define COMINTERFACEEXTERNALPROXYSTUB_ELEM "comInterfaceExternalProxyStub"
194 #define COMINTERFACEPROXYSTUB_ELEM "comInterfaceProxyStub"
195 #define DEPENDENCY_ELEM "dependency"
196 #define DEPENDENTASSEMBLY_ELEM "dependentAssembly"
197 #define DESCRIPTION_ELEM "description"
198 #define FILE_ELEM "file"
199 #define HASH_ELEM "asmv2:hash"
200 #define NOINHERIT_ELEM "noInherit"
201 #define NOINHERITABLE_ELEM "noInheritable"
202 #define TYPELIB_ELEM "typelib"
203 #define WINDOWCLASS_ELEM "windowClass"
205 #define ELEM_END(elem) "/" elem
207 #define CLSID_ATTR "clsid"
208 #define HASH_ATTR "hash"
209 #define HASHALG_ATTR "hashalg"
210 #define HELPDIR_ATTR "helpdir"
211 #define IID_ATTR "iid"
212 #define LANGUAGE_ATTR "language"
213 #define MANIFESTVERSION_ATTR "manifestVersion"
214 #define NAME_ATTR "name"
215 #define NEWVERSION_ATTR "newVersion"
216 #define OLDVERSION_ATTR "oldVersion"
217 #define OPTIONAL_ATTR "optional"
218 #define PROCESSORARCHITECTURE_ATTR "processorArchitecture"
219 #define PUBLICKEYTOKEN_ATTR "publicKeyToken"
220 #define TLBID_ATTR "tlbid"
221 #define TYPE_ATTR "type"
222 #define VERSION_ATTR "version"
223 #define XMLNS_ATTR "xmlns"
225 #define MANIFESTV1_NAMESPACE "urn:schemas-microsoft-com:asm.v1"
226 #define MANIFESTV3_NAMESPACE "urn:schemas-microsoft-com:asm.v3"
228 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
231 static WCHAR *strdupW(const WCHAR* str)
233 WCHAR* ptr;
235 if (!str) return NULL;
236 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
237 return NULL;
238 return strcpyW(ptr, str);
241 static WCHAR *xmlstrdupW(const xmlstr_t* str)
243 WCHAR *strW;
244 int len = wine_utf8_mbstowcs( 0, str->ptr, str->len, NULL, 0 );
246 if (len == -1) return NULL;
247 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
249 wine_utf8_mbstowcs( 0, str->ptr, str->len, strW, len );
250 strW[len] = 0;
252 return strW;
255 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const char* str)
257 return !strncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
260 static inline BOOL isxmlspace( char ch )
262 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
265 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
267 return debugstr_an(str->ptr, str->len);
270 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
272 struct assembly *assembly;
274 if (actctx->num_assemblies == actctx->allocated_assemblies)
276 void *ptr;
277 unsigned int new_count;
278 if (actctx->assemblies)
280 new_count = actctx->allocated_assemblies * 2;
281 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
282 actctx->assemblies, new_count * sizeof(*assembly) );
284 else
286 new_count = 4;
287 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
289 if (!ptr) return NULL;
290 actctx->assemblies = ptr;
291 actctx->allocated_assemblies = new_count;
294 assembly = &actctx->assemblies[actctx->num_assemblies++];
295 assembly->type = at;
296 return assembly;
299 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
301 if (assembly->num_dlls == assembly->allocated_dlls)
303 void *ptr;
304 unsigned int new_count;
305 if (assembly->dlls)
307 new_count = assembly->allocated_dlls * 2;
308 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
309 assembly->dlls, new_count * sizeof(*assembly->dlls) );
311 else
313 new_count = 4;
314 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
316 if (!ptr) return NULL;
317 assembly->dlls = ptr;
318 assembly->allocated_dlls = new_count;
320 return &assembly->dlls[assembly->num_dlls++];
323 static void free_assembly_identity(struct assembly_identity *ai)
325 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
326 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
327 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
328 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
331 static struct entity* add_entity(struct entity_array *array, DWORD kind)
333 struct entity* entity;
335 if (array->num == array->allocated)
337 void *ptr;
338 unsigned int new_count;
339 if (array->base)
341 new_count = array->allocated * 2;
342 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
343 array->base, new_count * sizeof(*array->base) );
345 else
347 new_count = 4;
348 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
350 if (!ptr) return NULL;
351 array->base = ptr;
352 array->allocated = new_count;
354 entity = &array->base[array->num++];
355 entity->kind = kind;
356 return entity;
359 static void free_entity_array(struct entity_array *array)
361 unsigned int i;
362 for (i = 0; i < array->num; i++)
364 struct entity *entity = &array->base[i];
365 switch (entity->kind)
367 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
368 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
369 break;
370 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
371 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
372 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.name);
373 break;
374 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
375 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
376 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.version);
377 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
378 break;
379 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
380 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
381 break;
382 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
383 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.name);
384 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.clsid);
385 break;
386 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
387 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
388 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
389 break;
390 default:
391 FIXME("Unknown entity kind %d\n", entity->kind);
394 RtlFreeHeap( GetProcessHeap(), 0, array->base );
397 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
399 if (!str1) return !str2;
400 return str2 && !strcmpiW( str1, str2 );
403 static BOOL is_matching_identity( const struct assembly_identity *id1,
404 const struct assembly_identity *id2 )
406 if (!is_matching_string( id1->name, id2->name )) return FALSE;
407 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
408 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
410 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
412 static const WCHAR wildcardW[] = {'*',0};
413 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
414 return FALSE;
416 if (id1->version.major != id2->version.major) return FALSE;
417 if (id1->version.minor != id2->version.minor) return FALSE;
418 if (id1->version.build > id2->version.build) return FALSE;
419 if (id1->version.build == id2->version.build &&
420 id1->version.revision > id2->version.revision) return FALSE;
421 return TRUE;
424 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
425 struct assembly_identity* ai)
427 unsigned int i;
429 /* check if we already have that assembly */
431 for (i = 0; i < acl->actctx->num_assemblies; i++)
432 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
434 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
435 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
436 ai->version.build, ai->version.revision );
437 return TRUE;
440 for (i = 0; i < acl->num_dependencies; i++)
441 if (is_matching_identity( ai, &acl->dependencies[i] ))
443 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
444 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
445 ai->version.build, ai->version.revision );
446 return TRUE;
449 if (acl->num_dependencies == acl->allocated_dependencies)
451 void *ptr;
452 unsigned int new_count;
453 if (acl->dependencies)
455 new_count = acl->allocated_dependencies * 2;
456 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
457 new_count * sizeof(acl->dependencies[0]));
459 else
461 new_count = 4;
462 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
464 if (!ptr) return FALSE;
465 acl->dependencies = ptr;
466 acl->allocated_dependencies = new_count;
468 acl->dependencies[acl->num_dependencies++] = *ai;
470 return TRUE;
473 static void free_depend_manifests(struct actctx_loader* acl)
475 unsigned int i;
476 for (i = 0; i < acl->num_dependencies; i++)
477 free_assembly_identity(&acl->dependencies[i]);
478 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
481 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
483 ACTIVATION_CONTEXT *actctx = h;
485 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
486 switch (actctx->magic)
488 case ACTCTX_MAGIC:
489 return actctx;
490 default:
491 return NULL;
495 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
497 interlocked_xchg_add( &actctx->ref_count, 1 );
500 static void actctx_release( ACTIVATION_CONTEXT *actctx )
502 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
504 unsigned int i, j;
506 for (i = 0; i < actctx->num_assemblies; i++)
508 struct assembly *assembly = &actctx->assemblies[i];
509 for (j = 0; j < assembly->num_dlls; j++)
511 struct dll_redirect *dll = &assembly->dlls[j];
512 free_entity_array( &dll->entities );
513 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
514 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
516 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
517 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
518 free_entity_array( &assembly->entities );
519 free_assembly_identity(&assembly->id);
521 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
522 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
523 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
524 actctx->magic = 0;
525 RtlFreeHeap( GetProcessHeap(), 0, actctx );
529 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
530 BOOL* error, BOOL* end)
532 const char* ptr;
534 *error = TRUE;
536 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
537 xmlbuf->ptr++;
539 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
541 if (*xmlbuf->ptr == '/')
543 xmlbuf->ptr++;
544 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
545 return FALSE;
547 xmlbuf->ptr++;
548 *end = TRUE;
549 *error = FALSE;
550 return FALSE;
553 if (*xmlbuf->ptr == '>')
555 xmlbuf->ptr++;
556 *error = FALSE;
557 return FALSE;
560 ptr = xmlbuf->ptr;
561 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
563 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
565 name->ptr = xmlbuf->ptr;
566 name->len = ptr-xmlbuf->ptr;
567 xmlbuf->ptr = ptr;
569 ptr++;
570 if (ptr == xmlbuf->end || *ptr != '\"') return FALSE;
572 value->ptr = ++ptr;
573 if (ptr == xmlbuf->end) return FALSE;
575 ptr = memchr(ptr, '\"', xmlbuf->end - ptr);
576 if (!ptr)
578 xmlbuf->ptr = xmlbuf->end;
579 return FALSE;
582 value->len = ptr - value->ptr;
583 xmlbuf->ptr = ptr + 1;
585 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
587 *error = FALSE;
588 return TRUE;
591 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
593 const char* ptr;
595 for (;;)
597 ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
598 if (!ptr)
600 xmlbuf->ptr = xmlbuf->end;
601 return FALSE;
603 ptr++;
604 if (ptr + 3 < xmlbuf->end && !strncmp( ptr, "!--", 3 )) /* skip comment */
606 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
607 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
609 if (ptr + 3 > xmlbuf->end)
611 xmlbuf->ptr = xmlbuf->end;
612 return FALSE;
614 xmlbuf->ptr = ptr + 3;
616 else break;
619 xmlbuf->ptr = ptr;
620 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
621 ptr++;
623 elem->ptr = xmlbuf->ptr;
624 elem->len = ptr - xmlbuf->ptr;
625 xmlbuf->ptr = ptr;
626 return xmlbuf->ptr != xmlbuf->end;
629 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
631 /* FIXME: parse attributes */
632 const char *ptr;
634 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
636 if (ptr[0] == '?' && ptr[1] == '>')
638 xmlbuf->ptr = ptr + 2;
639 return TRUE;
642 return FALSE;
645 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
647 const char *ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
649 if (!ptr) return FALSE;
651 content->ptr = xmlbuf->ptr;
652 content->len = ptr - xmlbuf->ptr;
653 xmlbuf->ptr = ptr;
655 return TRUE;
658 static BOOL parse_version(const xmlstr_t *str, struct version *version)
660 unsigned int ver[4];
661 unsigned int pos;
662 const char *curr;
664 /* major.minor.build.revision */
665 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
666 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
668 if (*curr >= '0' && *curr <= '9')
670 ver[pos] = ver[pos] * 10 + *curr - '0';
671 if (ver[pos] >= 0x10000) goto error;
673 else if (*curr == '.')
675 if (++pos >= 4) goto error;
677 else goto error;
679 version->major = ver[0];
680 version->minor = ver[1];
681 version->build = ver[2];
682 version->revision = ver[3];
683 return TRUE;
685 error:
686 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
687 return FALSE;
690 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const char* name)
692 xmlstr_t elem;
693 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
694 if (xmlstr_cmp(&elem, name)) return TRUE;
695 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
696 return FALSE;
699 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
701 xmlstr_t attr_name, attr_value;
702 BOOL error;
704 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
706 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
707 debugstr_xmlstr(&attr_value));
709 return !error;
712 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
714 BOOL end = FALSE;
715 return parse_expect_no_attr(xmlbuf, &end) && !end;
718 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
720 xmlstr_t attr_name, attr_value, elem;
721 BOOL end = FALSE, error, ret = TRUE;
723 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
724 if(error || end) return end;
726 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
728 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
729 !strncmp(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
730 break;
731 else
732 ret = parse_unknown_elem(xmlbuf, &elem);
735 return ret && parse_end_element(xmlbuf);
738 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
739 struct assembly_identity* ai)
741 xmlstr_t attr_name, attr_value;
742 BOOL end = FALSE, error;
744 TRACE("\n");
746 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
748 if (xmlstr_cmp(&attr_name, NAME_ATTR))
750 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
752 else if (xmlstr_cmp(&attr_name, TYPE_ATTR))
754 if (!xmlstr_cmp(&attr_value, "win32"))
756 FIXME("wrong type attr %s\n", debugstr_xmlstr(&attr_value));
757 return FALSE;
759 ai->type = TYPE_WIN32;
761 else if (xmlstr_cmp(&attr_name, VERSION_ATTR))
763 if (!parse_version(&attr_value, &ai->version)) return FALSE;
765 else if (xmlstr_cmp(&attr_name, PROCESSORARCHITECTURE_ATTR))
767 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
769 else if (xmlstr_cmp(&attr_name, PUBLICKEYTOKEN_ATTR))
771 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
773 else if (xmlstr_cmp(&attr_name, LANGUAGE_ATTR))
775 WARN("Unsupported yet language attribute (%s)\n",
776 debugstr_xmlstr(&attr_value));
777 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
779 else
781 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
782 debugstr_xmlstr(&attr_value));
786 if (error || end) return end;
787 return parse_expect_elem(xmlbuf, ELEM_END(ASSEMBLYIDENTITY_ELEM)) && parse_end_element(xmlbuf);
790 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
792 xmlstr_t attr_name, attr_value;
793 BOOL end = FALSE, error;
794 struct entity* entity;
796 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
797 return FALSE;
799 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
801 if (xmlstr_cmp(&attr_name, CLSID_ATTR))
803 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
805 else
807 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
811 if (error || end) return end;
812 return parse_expect_elem(xmlbuf, ELEM_END(COMCLASS_ELEM)) && parse_end_element(xmlbuf);
815 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
817 xmlstr_t attr_name, attr_value;
818 BOOL end = FALSE, error;
819 struct entity* entity;
821 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
822 return FALSE;
824 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
826 if (xmlstr_cmp(&attr_name, IID_ATTR))
828 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
830 if (xmlstr_cmp(&attr_name, NAME_ATTR))
832 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
834 else
836 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
840 if (error || end) return end;
841 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEPROXYSTUB_ELEM)) && parse_end_element(xmlbuf);
844 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
846 xmlstr_t attr_name, attr_value;
847 BOOL end = FALSE, error;
848 struct entity* entity;
850 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
851 return FALSE;
853 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
855 if (xmlstr_cmp(&attr_name, TLBID_ATTR))
857 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
859 if (xmlstr_cmp(&attr_name, VERSION_ATTR))
861 if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
863 if (xmlstr_cmp(&attr_name, HELPDIR_ATTR))
865 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
867 else
869 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
873 if (error || end) return end;
874 return parse_expect_elem(xmlbuf, ELEM_END(TYPELIB_ELEM)) && parse_end_element(xmlbuf);
877 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
879 xmlstr_t elem, content;
880 BOOL end = FALSE, ret = TRUE;
881 struct entity* entity;
883 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
884 return FALSE;
886 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
887 if (end) return FALSE;
889 if (!parse_text_content(xmlbuf, &content)) return FALSE;
891 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
893 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
895 if (xmlstr_cmp(&elem, ELEM_END(WINDOWCLASS_ELEM)))
897 ret = parse_end_element(xmlbuf);
898 break;
900 else
902 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
903 ret = parse_unknown_elem(xmlbuf, &elem);
907 return ret;
910 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
912 xmlstr_t attr_name, attr_value;
913 BOOL end = FALSE, error;
915 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
917 if (xmlstr_cmp(&attr_name, OLDVERSION_ATTR))
919 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
921 else if (xmlstr_cmp(&attr_name, NEWVERSION_ATTR))
923 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
925 else
927 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
931 if (error || end) return end;
932 return parse_expect_elem(xmlbuf, ELEM_END(BINDINGREDIRECT_ELEM)) && parse_end_element(xmlbuf);
935 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
937 xmlstr_t elem, content;
938 BOOL end = FALSE, ret = TRUE;
940 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
941 !parse_text_content(xmlbuf, &content))
942 return FALSE;
944 TRACE("Got description %s\n", debugstr_xmlstr(&content));
946 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
948 if (xmlstr_cmp(&elem, ELEM_END(DESCRIPTION_ELEM)))
950 ret = parse_end_element(xmlbuf);
951 break;
953 else
955 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
956 ret = parse_unknown_elem(xmlbuf, &elem);
960 return ret;
963 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
964 struct assembly* assembly)
966 xmlstr_t attr_name, attr_value;
967 BOOL end = FALSE, error;
968 struct entity* entity;
970 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
971 if (!entity) return FALSE;
973 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
975 if (xmlstr_cmp(&attr_name, IID_ATTR))
977 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
979 if (xmlstr_cmp(&attr_name, NAME_ATTR))
981 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
983 else
985 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
989 if (error || end) return end;
990 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEEXTERNALPROXYSTUB_ELEM)) &&
991 parse_end_element(xmlbuf);
994 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
996 xmlstr_t attr_name, attr_value;
997 BOOL end = FALSE, error;
998 struct entity* entity;
1000 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
1001 if (!entity) return FALSE;
1003 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1005 if (xmlstr_cmp(&attr_name, NAME_ATTR))
1007 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
1009 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
1011 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1013 else
1015 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1019 if (error || end) return end;
1020 return parse_expect_elem(xmlbuf, ELEM_END(CLRCLASS_ELEM)) && parse_end_element(xmlbuf);
1023 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1025 xmlstr_t attr_name, attr_value;
1026 BOOL end = FALSE, error;
1027 struct entity* entity;
1029 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1030 if (!entity) return FALSE;
1032 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1034 if (xmlstr_cmp(&attr_name, NAME_ATTR))
1036 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
1038 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
1040 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
1042 else
1044 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1048 if (error || end) return end;
1049 return parse_expect_elem(xmlbuf, ELEM_END(CLRSURROGATE_ELEM)) && parse_end_element(xmlbuf);
1052 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1054 struct assembly_identity ai;
1055 xmlstr_t elem;
1056 BOOL end = FALSE, ret = TRUE;
1058 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1060 memset(&ai, 0, sizeof(ai));
1061 ai.optional = optional;
1063 if (!parse_expect_elem(xmlbuf, ASSEMBLYIDENTITY_ELEM) ||
1064 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1065 return FALSE;
1067 TRACE( "adding %s\n", debugstr_w(ai.name) );
1069 /* store the newly found identity for later loading */
1070 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1072 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1074 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENTASSEMBLY_ELEM)))
1076 ret = parse_end_element(xmlbuf);
1077 break;
1079 else if (xmlstr_cmp(&elem, BINDINGREDIRECT_ELEM))
1081 ret = parse_binding_redirect_elem(xmlbuf);
1083 else
1085 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1086 ret = parse_unknown_elem(xmlbuf, &elem);
1090 return ret;
1093 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1095 xmlstr_t attr_name, attr_value, elem;
1096 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1098 TRACE("\n");
1100 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1102 if (xmlstr_cmp(&attr_name, OPTIONAL_ATTR))
1104 optional = xmlstr_cmp( &attr_value, "yes" );
1105 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
1107 else
1109 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1113 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1115 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENCY_ELEM)))
1117 ret = parse_end_element(xmlbuf);
1118 break;
1120 else if (xmlstr_cmp(&elem, DEPENDENTASSEMBLY_ELEM))
1122 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1124 else
1126 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1127 ret = parse_unknown_elem(xmlbuf, &elem);
1131 return ret;
1134 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1136 BOOL end = FALSE;
1138 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1139 return end ||
1140 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERIT_ELEM)) && parse_end_element(xmlbuf));
1143 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1145 BOOL end = FALSE;
1147 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1148 return end ||
1149 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERITABLE_ELEM)) && parse_end_element(xmlbuf));
1152 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1154 xmlstr_t attr_name, attr_value, elem;
1155 BOOL end = FALSE, error, ret = TRUE;
1156 struct dll_redirect* dll;
1158 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1160 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1162 if (xmlstr_cmp(&attr_name, NAME_ATTR))
1164 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1165 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1167 else if (xmlstr_cmp(&attr_name, HASH_ATTR))
1169 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1171 else if (xmlstr_cmp(&attr_name, HASHALG_ATTR))
1173 if (!xmlstr_cmp(&attr_value, "SHA1"))
1174 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
1176 else
1178 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1182 if (error || !dll->name) return FALSE;
1183 if (end) return TRUE;
1185 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1187 if (xmlstr_cmp(&elem, ELEM_END(FILE_ELEM)))
1189 ret = parse_end_element(xmlbuf);
1190 break;
1192 else if (xmlstr_cmp(&elem, COMCLASS_ELEM))
1194 ret = parse_com_class_elem(xmlbuf, dll);
1196 else if (xmlstr_cmp(&elem, COMINTERFACEPROXYSTUB_ELEM))
1198 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1200 else if (xmlstr_cmp(&elem, HASH_ELEM))
1202 WARN(HASH_ELEM " (undocumented) not supported\n");
1203 ret = parse_unknown_elem(xmlbuf, &elem);
1205 else if (xmlstr_cmp(&elem, TYPELIB_ELEM))
1207 ret = parse_typelib_elem(xmlbuf, dll);
1209 else if (xmlstr_cmp(&elem, WINDOWCLASS_ELEM))
1211 ret = parse_window_class_elem(xmlbuf, dll);
1213 else
1215 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1216 ret = parse_unknown_elem( xmlbuf, &elem );
1220 return ret;
1223 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1224 struct assembly* assembly,
1225 struct assembly_identity* expected_ai)
1227 xmlstr_t attr_name, attr_value, elem;
1228 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1230 TRACE("(%p)\n", xmlbuf);
1232 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1234 if (xmlstr_cmp(&attr_name, MANIFESTVERSION_ATTR))
1236 if (!xmlstr_cmp(&attr_value, "1.0"))
1238 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
1239 return FALSE;
1241 version = TRUE;
1243 else if (xmlstr_cmp(&attr_name, XMLNS_ATTR))
1245 if (!xmlstr_cmp(&attr_value, MANIFESTV1_NAMESPACE) &&
1246 !xmlstr_cmp(&attr_value, MANIFESTV3_NAMESPACE))
1248 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
1249 return FALSE;
1251 xmlns = TRUE;
1253 else
1255 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1259 if (error || end || !xmlns || !version) return FALSE;
1260 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1262 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, NOINHERIT_ELEM))
1264 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1265 return FALSE;
1266 assembly->no_inherit = TRUE;
1269 if (xmlstr_cmp(&elem, NOINHERITABLE_ELEM))
1271 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1272 return FALSE;
1274 else if (assembly->type == ASSEMBLY_MANIFEST && assembly->no_inherit)
1275 return FALSE;
1277 if (xmlstr_cmp(&elem, ASSEMBLYIDENTITY_ELEM))
1279 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
1280 ret = next_xml_elem(xmlbuf, &elem);
1282 if (expected_ai)
1284 /* FIXME: more tests */
1285 if (assembly->type == ASSEMBLY_MANIFEST &&
1286 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
1288 FIXME("wrong version\n");
1289 return FALSE;
1294 while (ret)
1296 if (xmlstr_cmp(&elem, ELEM_END(ASSEMBLY_ELEM)))
1298 ret = parse_end_element(xmlbuf);
1299 break;
1301 else if (xmlstr_cmp(&elem, DESCRIPTION_ELEM))
1303 ret = parse_description_elem(xmlbuf);
1305 else if (xmlstr_cmp(&elem, COMINTERFACEEXTERNALPROXYSTUB_ELEM))
1307 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1309 else if (xmlstr_cmp(&elem, DEPENDENCY_ELEM))
1311 ret = parse_dependency_elem(xmlbuf, acl);
1313 else if (xmlstr_cmp(&elem, FILE_ELEM))
1315 ret = parse_file_elem(xmlbuf, assembly);
1317 else if (xmlstr_cmp(&elem, CLRCLASS_ELEM))
1319 ret = parse_clr_class_elem(xmlbuf, assembly);
1321 else if (xmlstr_cmp(&elem, CLRSURROGATE_ELEM))
1323 ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1325 else
1327 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1328 ret = parse_unknown_elem(xmlbuf, &elem);
1330 if (ret) ret = next_xml_elem(xmlbuf, &elem);
1333 return ret;
1336 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1337 LPCWSTR filename, xmlbuf_t* xmlbuf )
1339 xmlstr_t elem;
1340 struct assembly* assembly;
1342 TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) );
1344 if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
1345 return STATUS_SXS_CANT_GEN_ACTCTX;
1347 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
1348 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1349 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1351 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1353 if (xmlstr_cmp(&elem, "?xml") &&
1354 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1355 return STATUS_SXS_CANT_GEN_ACTCTX;
1357 if (!xmlstr_cmp(&elem, ASSEMBLY_ELEM))
1359 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
1360 return STATUS_SXS_CANT_GEN_ACTCTX;
1363 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1365 FIXME("failed to parse manifest %s\n", debugstr_w(filename) );
1366 return STATUS_SXS_CANT_GEN_ACTCTX;
1369 if (next_xml_elem(xmlbuf, &elem))
1371 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
1372 return STATUS_SXS_CANT_GEN_ACTCTX;
1375 if (xmlbuf->ptr != xmlbuf->end)
1377 FIXME("parse error\n");
1378 return STATUS_SXS_CANT_GEN_ACTCTX;
1380 return STATUS_SUCCESS;
1383 static NTSTATUS open_nt_file( HANDLE handle, UNICODE_STRING *name )
1385 OBJECT_ATTRIBUTES attr;
1386 IO_STATUS_BLOCK io;
1388 attr.Length = sizeof(attr);
1389 attr.RootDirectory = 0;
1390 attr.Attributes = OBJ_CASE_INSENSITIVE;
1391 attr.ObjectName = name;
1392 attr.SecurityDescriptor = NULL;
1393 attr.SecurityQualityOfService = NULL;
1394 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
1397 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
1399 NTSTATUS status;
1400 ULONG magic;
1401 LDR_MODULE *pldr;
1403 LdrLockLoaderLock(0, NULL, &magic);
1404 status = LdrFindEntryForAddress( module, &pldr );
1405 if (status == STATUS_SUCCESS)
1407 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1408 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1410 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1411 str->Length = pldr->FullDllName.Length;
1412 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1414 else status = STATUS_NO_MEMORY;
1416 LdrUnlockLoaderLock(0, magic);
1417 return status;
1420 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1421 LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang )
1423 NTSTATUS status;
1424 UNICODE_STRING nameW;
1425 LDR_RESOURCE_INFO info;
1426 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1427 void *ptr;
1429 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), hModule, debugstr_w(filename) );
1431 if (!resname) return STATUS_INVALID_PARAMETER;
1433 info.Type = RT_MANIFEST;
1434 info.Language = lang;
1435 if (!((ULONG_PTR)resname >> 16))
1437 info.Name = (ULONG_PTR)resname;
1438 status = LdrFindResource_U(hModule, &info, 3, &entry);
1440 else if (resname[0] == '#')
1442 ULONG value;
1443 RtlInitUnicodeString(&nameW, resname + 1);
1444 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1445 return STATUS_INVALID_PARAMETER;
1446 info.Name = value;
1447 status = LdrFindResource_U(hModule, &info, 3, &entry);
1449 else
1451 RtlCreateUnicodeString(&nameW, resname);
1452 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1453 info.Name = (ULONG_PTR)nameW.Buffer;
1454 status = LdrFindResource_U(hModule, &info, 3, &entry);
1455 RtlFreeUnicodeString(&nameW);
1457 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1459 if (status == STATUS_SUCCESS)
1461 xmlbuf_t buf;
1462 buf.ptr = ptr;
1463 buf.end = buf.ptr + entry->Size;
1464 status = parse_manifest(acl, ai, filename, &buf);
1466 return status;
1469 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1470 LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang )
1472 HANDLE mapping;
1473 OBJECT_ATTRIBUTES attr;
1474 LARGE_INTEGER size;
1475 LARGE_INTEGER offset;
1476 NTSTATUS status;
1477 SIZE_T count;
1478 void *base;
1480 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
1482 attr.Length = sizeof(attr);
1483 attr.RootDirectory = 0;
1484 attr.ObjectName = NULL;
1485 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1486 attr.SecurityDescriptor = NULL;
1487 attr.SecurityQualityOfService = NULL;
1489 size.QuadPart = 0;
1490 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1491 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1492 if (status != STATUS_SUCCESS) return status;
1494 offset.QuadPart = 0;
1495 count = 0;
1496 base = NULL;
1497 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1498 &count, ViewShare, 0, PAGE_READONLY );
1499 NtClose( mapping );
1500 if (status != STATUS_SUCCESS) return status;
1502 if (RtlImageNtHeader(base)) /* we got a PE file */
1504 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1505 status = get_manifest_in_module( acl, ai, filename, module, resname, lang );
1507 else status = STATUS_INVALID_IMAGE_FORMAT;
1509 NtUnmapViewOfSection( GetCurrentProcess(), base );
1510 return status;
1513 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1514 LPCWSTR filename, HANDLE file )
1516 HANDLE mapping;
1517 OBJECT_ATTRIBUTES attr;
1518 LARGE_INTEGER size;
1519 LARGE_INTEGER offset;
1520 NTSTATUS status;
1521 SIZE_T count;
1522 void *base;
1523 xmlbuf_t buf;
1525 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
1527 attr.Length = sizeof(attr);
1528 attr.RootDirectory = 0;
1529 attr.ObjectName = NULL;
1530 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1531 attr.SecurityDescriptor = NULL;
1532 attr.SecurityQualityOfService = NULL;
1534 size.QuadPart = 0;
1535 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1536 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1537 if (status != STATUS_SUCCESS) return status;
1539 offset.QuadPart = 0;
1540 count = 0;
1541 base = NULL;
1542 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1543 &count, ViewShare, 0, PAGE_READONLY );
1544 NtClose( mapping );
1545 if (status != STATUS_SUCCESS) return status;
1547 buf.ptr = base;
1548 buf.end = buf.ptr + count;
1549 status = parse_manifest(acl, ai, filename, &buf);
1551 NtUnmapViewOfSection( GetCurrentProcess(), base );
1552 return status;
1555 /* try to load the .manifest file associated to the file */
1556 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1557 LPCWSTR filename, HMODULE module, LPCWSTR resname )
1559 static const WCHAR fmtW[] = { '.','%','l','u',0 };
1560 WCHAR *buffer;
1561 NTSTATUS status;
1562 UNICODE_STRING nameW;
1563 HANDLE file;
1564 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
1566 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1568 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
1570 if (module) /* use the module filename */
1572 UNICODE_STRING name;
1574 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1576 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1577 strcatW( name.Buffer, dotManifestW );
1578 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1579 status = STATUS_NO_SUCH_FILE;
1580 RtlFreeUnicodeString( &name );
1582 if (status) return status;
1584 else
1586 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1587 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1588 return STATUS_NO_MEMORY;
1589 strcpyW( buffer, filename );
1590 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1591 strcatW( buffer, dotManifestW );
1592 RtlInitUnicodeString( &nameW, buffer );
1595 status = open_nt_file( &file, &nameW );
1596 if (status == STATUS_SUCCESS)
1598 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1599 NtClose( file );
1601 RtlFreeUnicodeString( &nameW );
1602 return status;
1605 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
1607 static const WCHAR lookup_fmtW[] =
1608 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1609 '*', /* FIXME */
1610 '.','m','a','n','i','f','e','s','t',0};
1612 WCHAR *lookup, *ret = NULL;
1613 UNICODE_STRING lookup_us;
1614 IO_STATUS_BLOCK io;
1615 unsigned int data_pos = 0, data_len;
1616 char buffer[8192];
1618 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
1619 (strlenW(ai->arch) + strlenW(ai->name)
1620 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
1621 + sizeof(lookup_fmtW) )))
1622 return NULL;
1624 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
1625 RtlInitUnicodeString( &lookup_us, lookup );
1627 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1628 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
1629 if (io.u.Status == STATUS_SUCCESS)
1631 FILE_BOTH_DIR_INFORMATION *dir_info;
1632 WCHAR *tmp;
1633 ULONG build, revision;
1635 data_len = io.Information;
1637 for (;;)
1639 if (data_pos >= data_len)
1641 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1642 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
1643 if (io.u.Status != STATUS_SUCCESS) break;
1644 data_len = io.Information;
1645 data_pos = 0;
1647 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
1649 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
1650 else data_pos = data_len;
1652 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
1653 build = atoiW(tmp);
1654 if (build < ai->version.build) continue;
1655 tmp = strchrW(tmp, '.') + 1;
1656 revision = atoiW(tmp);
1657 if (build == ai->version.build && revision < ai->version.revision)
1658 continue;
1659 ai->version.build = build;
1660 ai->version.revision = revision;
1661 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
1663 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
1664 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
1666 break;
1669 else WARN("no matching file for %s\n", debugstr_w(lookup));
1670 RtlFreeHeap( GetProcessHeap(), 0, lookup );
1671 return ret;
1674 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
1676 struct assembly_identity sxs_ai;
1677 UNICODE_STRING path_us;
1678 OBJECT_ATTRIBUTES attr;
1679 IO_STATUS_BLOCK io;
1680 WCHAR *path, *file = NULL;
1681 HANDLE handle;
1683 static const WCHAR manifest_dirW[] =
1684 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
1686 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
1688 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, windows_dir.Length + sizeof(manifest_dirW) )))
1689 return STATUS_NO_MEMORY;
1691 memcpy( path, windows_dir.Buffer, windows_dir.Length );
1692 memcpy( path + windows_dir.Length/sizeof(WCHAR), manifest_dirW, sizeof(manifest_dirW) );
1694 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
1696 RtlFreeHeap( GetProcessHeap(), 0, path );
1697 return STATUS_NO_SUCH_FILE;
1699 RtlFreeHeap( GetProcessHeap(), 0, path );
1701 attr.Length = sizeof(attr);
1702 attr.RootDirectory = 0;
1703 attr.Attributes = OBJ_CASE_INSENSITIVE;
1704 attr.ObjectName = &path_us;
1705 attr.SecurityDescriptor = NULL;
1706 attr.SecurityQualityOfService = NULL;
1708 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1709 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
1711 sxs_ai = *ai;
1712 file = lookup_manifest_file( handle, &sxs_ai );
1713 NtClose( handle );
1715 if (!file)
1717 RtlFreeUnicodeString( &path_us );
1718 return STATUS_NO_SUCH_FILE;
1721 /* append file name to directory path */
1722 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
1723 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
1725 RtlFreeHeap( GetProcessHeap(), 0, file );
1726 RtlFreeUnicodeString( &path_us );
1727 return STATUS_NO_MEMORY;
1730 path[path_us.Length/sizeof(WCHAR)] = '\\';
1731 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
1732 RtlFreeHeap( GetProcessHeap(), 0, file );
1733 RtlInitUnicodeString( &path_us, path );
1735 if (!open_nt_file( &handle, &path_us ))
1737 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, handle);
1738 NtClose( handle );
1740 else io.u.Status = STATUS_NO_SUCH_FILE;
1742 RtlFreeUnicodeString( &path_us );
1743 return io.u.Status;
1746 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
1747 struct assembly_identity* ai)
1749 static const WCHAR dotDllW[] = {'.','d','l','l',0};
1750 unsigned int i;
1751 WCHAR *buffer, *p;
1752 NTSTATUS status;
1753 UNICODE_STRING nameW;
1754 HANDLE file;
1756 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
1758 /* FIXME: add support for language specific lookup */
1760 nameW.Buffer = NULL;
1761 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1762 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1763 return STATUS_NO_MEMORY;
1765 /* lookup in appdir\name.dll
1766 * appdir\name.manifest
1767 * appdir\name\name.dll
1768 * appdir\name\name.manifest
1770 strcpyW( buffer, acl->actctx->appdir.info );
1771 p = buffer + strlenW(buffer);
1772 for (i = 0; i < 2; i++)
1774 *p++ = '\\';
1775 strcpyW( p, ai->name );
1776 p += strlenW(p);
1778 strcpyW( p, dotDllW );
1779 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1781 status = open_nt_file( &file, &nameW );
1782 if (!status)
1784 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file,
1785 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
1786 NtClose( file );
1787 break;
1789 RtlFreeUnicodeString( &nameW );
1792 strcpyW( p, dotManifestW );
1793 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1795 status = open_nt_file( &file, &nameW );
1796 if (!status)
1798 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1799 NtClose( file );
1800 break;
1802 RtlFreeUnicodeString( &nameW );
1805 RtlFreeUnicodeString( &nameW );
1806 return STATUS_SXS_ASSEMBLY_NOT_FOUND;
1809 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
1811 NTSTATUS status = STATUS_SUCCESS;
1812 unsigned int i;
1814 for (i = 0; i < acl->num_dependencies; i++)
1816 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
1818 if (!acl->dependencies[i].optional)
1820 FIXME( "Could not find dependent assembly %s\n", debugstr_w(acl->dependencies[i].name) );
1821 status = STATUS_SXS_CANT_GEN_ACTCTX;
1822 break;
1826 /* FIXME should now iterate through all refs */
1827 return status;
1831 /***********************************************************************
1832 * RtlCreateActivationContext (NTDLL.@)
1834 * Create an activation context.
1836 * FIXME: function signature/prototype is wrong
1838 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
1840 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
1841 ACTIVATION_CONTEXT *actctx;
1842 UNICODE_STRING nameW;
1843 ULONG lang = 0;
1844 NTSTATUS status = STATUS_NO_MEMORY;
1845 HANDLE file = 0;
1846 struct actctx_loader acl;
1848 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
1850 if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx) ||
1851 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
1852 return STATUS_INVALID_PARAMETER;
1854 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
1855 return STATUS_NO_MEMORY;
1857 actctx->magic = ACTCTX_MAGIC;
1858 actctx->ref_count = 1;
1859 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1860 actctx->config.info = NULL;
1861 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1862 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
1864 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
1866 else
1868 UNICODE_STRING dir;
1869 WCHAR *p;
1871 if ((status = get_module_filename( NtCurrentTeb()->Peb->ImageBaseAddress, &dir, 0 )))
1872 goto error;
1873 if ((p = strrchrW( dir.Buffer, '\\' ))) *p = 0;
1874 actctx->appdir.info = dir.Buffer;
1877 nameW.Buffer = NULL;
1878 if (pActCtx->lpSource)
1880 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
1882 status = STATUS_NO_SUCH_FILE;
1883 goto error;
1885 status = open_nt_file( &file, &nameW );
1886 if (status)
1888 RtlFreeUnicodeString( &nameW );
1889 goto error;
1893 acl.actctx = actctx;
1894 acl.dependencies = NULL;
1895 acl.num_dependencies = 0;
1896 acl.allocated_dependencies = 0;
1898 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
1900 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
1902 /* if we have a resource it's a PE file */
1903 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
1905 status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule,
1906 pActCtx->lpResourceName, lang );
1907 if (status)
1908 /* FIXME: what to do if pActCtx->lpSource is set */
1909 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule,
1910 pActCtx->lpResourceName );
1912 else if (pActCtx->lpSource)
1914 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file,
1915 pActCtx->lpResourceName, lang );
1916 if (status)
1917 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL,
1918 pActCtx->lpResourceName );
1920 else status = STATUS_INVALID_PARAMETER;
1922 else
1924 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file );
1927 if (file) NtClose( file );
1928 RtlFreeUnicodeString( &nameW );
1930 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
1931 free_depend_manifests( &acl );
1933 if (status == STATUS_SUCCESS) *handle = actctx;
1934 else actctx_release( actctx );
1935 return status;
1937 error:
1938 if (file) NtClose( file );
1939 actctx_release( actctx );
1940 return status;
1944 /***********************************************************************
1945 * RtlAddRefActivationContext (NTDLL.@)
1947 void WINAPI RtlAddRefActivationContext( HANDLE handle )
1949 ACTIVATION_CONTEXT *actctx;
1951 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
1955 /******************************************************************
1956 * RtlReleaseActivationContext (NTDLL.@)
1958 void WINAPI RtlReleaseActivationContext( HANDLE handle )
1960 ACTIVATION_CONTEXT *actctx;
1962 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
1966 /******************************************************************
1967 * RtlActivateActivationContext (NTDLL.@)
1969 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, ULONG_PTR *cookie )
1971 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1973 TRACE( "%p %p\n", handle, cookie );
1975 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
1976 return STATUS_NO_MEMORY;
1978 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1979 frame->ActivationContext = handle;
1980 frame->Flags = 0;
1981 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
1982 RtlAddRefActivationContext( handle );
1984 *cookie = (ULONG_PTR)frame;
1985 return STATUS_SUCCESS;
1989 /***********************************************************************
1990 * RtlDeactivateActivationContext (NTDLL.@)
1992 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
1994 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
1996 TRACE( "%x %lx\n", flags, cookie );
1998 /* find the right frame */
1999 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
2000 for (frame = top; frame; frame = frame->Previous)
2001 if ((ULONG_PTR)frame == cookie) break;
2003 if (!frame)
2004 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
2006 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
2007 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
2009 /* pop everything up to and including frame */
2010 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
2012 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2014 frame = top->Previous;
2015 RtlReleaseActivationContext( top->ActivationContext );
2016 RtlFreeHeap( GetProcessHeap(), 0, top );
2017 top = frame;
2022 /******************************************************************
2023 * RtlFreeThreadActivationContextStack (NTDLL.@)
2025 void WINAPI RtlFreeThreadActivationContextStack(void)
2027 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2029 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
2030 while (frame)
2032 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
2033 RtlReleaseActivationContext( frame->ActivationContext );
2034 RtlFreeHeap( GetProcessHeap(), 0, frame );
2035 frame = prev;
2037 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
2041 /******************************************************************
2042 * RtlGetActiveActivationContext (NTDLL.@)
2044 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
2046 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2048 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2049 RtlAddRefActivationContext( *handle );
2051 else
2052 *handle = 0;
2054 return STATUS_SUCCESS;
2058 /******************************************************************
2059 * RtlIsActivationContextActive (NTDLL.@)
2061 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
2063 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2065 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
2066 if (frame->ActivationContext == handle) return TRUE;
2067 return FALSE;