4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
33 #define WIN32_NO_STATUS
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)
89 struct assembly_identity
95 struct version version;
96 enum assembly_id_type type;
139 unsigned int allocated;
146 struct entity_array entities;
151 APPLICATION_MANIFEST,
157 enum assembly_type type;
158 struct assembly_identity id;
159 struct file_info manifest;
161 struct dll_redirect *dlls;
162 unsigned int num_dlls;
163 unsigned int allocated_dlls;
164 struct entity_array entities;
167 typedef struct _ACTIVATION_CONTEXT
171 struct file_info config;
172 struct file_info appdir;
173 struct assembly *assemblies;
174 unsigned int num_assemblies;
175 unsigned int allocated_assemblies;
176 } ACTIVATION_CONTEXT;
180 ACTIVATION_CONTEXT *actctx;
181 struct assembly_identity *dependencies;
182 unsigned int num_dependencies;
183 unsigned int allocated_dependencies;
186 #define ASSEMBLY_ELEM "assembly"
187 #define ASSEMBLYIDENTITY_ELEM "assemblyIdentity"
188 #define CLRCLASS_ELEM "clrClass"
189 #define CLRSURROGATE_ELEM "clrSurrogate"
190 #define COMCLASS_ELEM "comClass"
191 #define COMINTERFACEEXTERNALPROXYSTUB_ELEM "comInterfaceExternalProxyStub"
192 #define COMINTERFACEPROXYSTUB_ELEM "comInterfaceProxyStub"
193 #define DEPENDENCY_ELEM "dependency"
194 #define DEPENDENTASSEMBLY_ELEM "dependentAssembly"
195 #define DESCRIPTION_ELEM "description"
196 #define FILE_ELEM "file"
197 #define NOINHERIT_ELEM "noInherit"
198 #define NOINHERITABLE_ELEM "noInheritable"
199 #define TYPELIB_ELEM "typelib"
200 #define WINDOWCLASS_ELEM "windowClass"
202 #define ELEM_END(elem) "/" elem
204 #define CLSID_ATTR "clsid"
205 #define HASH_ATTR "hash"
206 #define HASHALG_ATTR "hashalg"
207 #define HELPDIR_ATTR "helpdir"
208 #define IID_ATTR "iid"
209 #define LANGUAGE_ATTR "language"
210 #define MANIFESTVERSION_ATTR "manifestVersion"
211 #define NAME_ATTR "name"
212 #define PROCESSORARCHITECTURE_ATTR "processorArchitecture"
213 #define PUBLICKEYTOKEN_ATTR "publicKeyToken"
214 #define TLBID_ATTR "tlbid"
215 #define TYPE_ATTR "type"
216 #define VERSION_ATTR "version"
217 #define XMLNS_ATTR "xmlns"
219 #define MANIFEST_NAMESPACE "urn:schemas-microsoft-com:asm.v1"
221 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
224 static WCHAR *strdupW(const WCHAR* str)
228 if (!str) return NULL;
229 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
231 return strcpyW(ptr, str);
234 static WCHAR *xmlstrdupW(const xmlstr_t* str)
237 int len = wine_utf8_mbstowcs( 0, str->ptr, str->len, NULL, 0 );
239 if (len == -1) return NULL;
240 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR))))
242 wine_utf8_mbstowcs( 0, str->ptr, str->len, strW, len );
248 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const char* str)
250 return !strncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
253 static inline BOOL isxmlspace( char ch )
255 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
258 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
260 return debugstr_an(str->ptr, str->len);
263 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
265 struct assembly *assembly;
267 if (actctx->num_assemblies == actctx->allocated_assemblies)
270 unsigned int new_count;
271 if (actctx->assemblies)
273 new_count = actctx->allocated_assemblies * 2;
274 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
275 actctx->assemblies, new_count * sizeof(*assembly) );
280 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
282 if (!ptr) return NULL;
283 actctx->assemblies = ptr;
284 actctx->allocated_assemblies = new_count;
287 assembly = &actctx->assemblies[actctx->num_assemblies++];
292 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
294 if (assembly->num_dlls == assembly->allocated_dlls)
297 unsigned int new_count;
300 new_count = assembly->allocated_dlls * 2;
301 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
302 assembly->dlls, new_count * sizeof(*assembly->dlls) );
307 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
309 if (!ptr) return NULL;
310 assembly->dlls = ptr;
311 assembly->allocated_dlls = new_count;
313 return &assembly->dlls[assembly->num_dlls++];
316 static void free_assembly_identity(struct assembly_identity *ai)
318 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
319 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
320 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
321 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
324 static struct entity* add_entity(struct entity_array *array, DWORD kind)
326 struct entity* entity;
328 if (array->num == array->allocated)
331 unsigned int new_count;
334 new_count = array->allocated * 2;
335 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
336 array->base, new_count * sizeof(*array->base) );
341 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
343 if (!ptr) return NULL;
345 array->allocated = new_count;
347 entity = &array->base[array->num++];
352 static void free_entity_array(struct entity_array *array)
355 for (i = 0; i < array->num; i++)
357 struct entity *entity = &array->base[i];
358 switch (entity->kind)
360 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
361 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
363 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
364 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
365 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.name);
367 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
368 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
369 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.version);
370 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
372 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
373 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
375 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
376 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.name);
377 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.clsid);
379 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
380 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
381 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
384 FIXME("Unknown entity kind %d\n", entity->kind);
387 RtlFreeHeap( GetProcessHeap(), 0, array->base );
390 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
391 struct assembly_identity* ai)
393 /* FIXME: should check that the passed ai isn't already in the list */
394 if (acl->num_dependencies == acl->allocated_dependencies)
397 unsigned int new_count;
398 if (acl->dependencies)
400 new_count = acl->allocated_dependencies * 2;
401 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
402 new_count * sizeof(acl->dependencies[0]));
407 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
409 if (!ptr) return FALSE;
410 acl->dependencies = ptr;
411 acl->allocated_dependencies = new_count;
413 acl->dependencies[acl->num_dependencies++] = *ai;
418 static void free_depend_manifests(struct actctx_loader* acl)
421 for (i = 0; i < acl->num_dependencies; i++)
422 free_assembly_identity(&acl->dependencies[i]);
423 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
426 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
428 ACTIVATION_CONTEXT *actctx = h;
430 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
431 switch (actctx->magic)
440 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
442 interlocked_xchg_add( &actctx->ref_count, 1 );
445 static void actctx_release( ACTIVATION_CONTEXT *actctx )
447 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
451 for (i = 0; i < actctx->num_assemblies; i++)
453 struct assembly *assembly = &actctx->assemblies[i];
454 for (j = 0; j < assembly->num_dlls; j++)
456 struct dll_redirect *dll = &assembly->dlls[j];
457 free_entity_array( &dll->entities );
458 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
459 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
461 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
462 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
463 free_entity_array( &assembly->entities );
464 free_assembly_identity(&assembly->id);
466 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
467 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
468 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
470 RtlFreeHeap( GetProcessHeap(), 0, actctx );
474 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
475 BOOL* error, BOOL* end)
481 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
484 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
486 if (*xmlbuf->ptr == '/')
489 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
498 if (*xmlbuf->ptr == '>')
506 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
508 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
510 name->ptr = xmlbuf->ptr;
511 name->len = ptr-xmlbuf->ptr;
515 if (ptr == xmlbuf->end || *ptr != '\"') return FALSE;
518 if (ptr == xmlbuf->end) return FALSE;
520 ptr = memchr(ptr, '\"', xmlbuf->end - ptr);
523 xmlbuf->ptr = xmlbuf->end;
527 value->len = ptr - value->ptr;
528 xmlbuf->ptr = ptr + 1;
530 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
536 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
540 ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
543 xmlbuf->ptr = xmlbuf->end;
548 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>')
551 elem->ptr = xmlbuf->ptr;
552 elem->len = ptr - xmlbuf->ptr;
554 return xmlbuf->ptr != xmlbuf->end;
557 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
559 /* FIXME: parse attributes */
562 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
564 if (ptr[0] == '?' && ptr[1] == '>')
566 xmlbuf->ptr = ptr + 2;
573 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
575 const char *ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
577 if (!ptr) return FALSE;
579 content->ptr = xmlbuf->ptr;
580 content->len = ptr - xmlbuf->ptr;
586 static BOOL parse_version(const xmlstr_t *str, struct version *version)
592 /* major.minor.build.revision */
593 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
594 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
596 if (*curr >= '0' && *curr <= '9')
598 ver[pos] = ver[pos] * 10 + *curr - '0';
599 if (ver[pos] >= 0x10000) goto error;
601 else if (*curr == '.')
603 if (++pos >= 4) goto error;
607 version->major = ver[0];
608 version->minor = ver[1];
609 version->build = ver[2];
610 version->revision = ver[3];
614 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
618 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const char* name)
621 return next_xml_elem(xmlbuf, &elem) && xmlstr_cmp(&elem, name);
624 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
626 xmlstr_t attr_name, attr_value;
629 if (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
631 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
632 debugstr_xmlstr(&attr_value));
639 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
642 return parse_expect_no_attr(xmlbuf, &end) && !end;
645 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
646 struct assembly_identity* ai)
648 xmlstr_t attr_name, attr_value;
649 BOOL end = FALSE, error;
653 memset(ai, 0, sizeof(*ai));
654 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
656 if (xmlstr_cmp(&attr_name, NAME_ATTR))
658 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
660 else if (xmlstr_cmp(&attr_name, TYPE_ATTR))
662 if (!xmlstr_cmp(&attr_value, "win32"))
664 WARN("wrong type attr %s\n", debugstr_xmlstr(&attr_value));
667 ai->type = TYPE_WIN32;
669 else if (xmlstr_cmp(&attr_name, VERSION_ATTR))
671 if (!parse_version(&attr_value, &ai->version)) return FALSE;
673 else if (xmlstr_cmp(&attr_name, PROCESSORARCHITECTURE_ATTR))
675 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
677 else if (xmlstr_cmp(&attr_name, PUBLICKEYTOKEN_ATTR))
679 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
681 else if (xmlstr_cmp(&attr_name, LANGUAGE_ATTR))
683 WARN("Unsupported yet language attribute (%s)\n",
684 debugstr_xmlstr(&attr_value));
685 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
689 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
690 debugstr_xmlstr(&attr_value));
695 if (error || end) return end;
696 return parse_expect_elem(xmlbuf, ELEM_END(ASSEMBLYIDENTITY_ELEM)) && parse_end_element(xmlbuf);
699 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
701 xmlstr_t attr_name, attr_value;
702 BOOL end = FALSE, error;
703 struct entity* entity;
705 entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
707 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
709 if (xmlstr_cmp(&attr_name, CLSID_ATTR))
711 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
715 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
716 debugstr_xmlstr(&attr_value));
721 if (error || end) return end;
722 return parse_expect_elem(xmlbuf, ELEM_END(COMCLASS_ELEM)) && parse_end_element(xmlbuf);
725 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
727 xmlstr_t attr_name, attr_value;
728 BOOL end = FALSE, error;
729 struct entity* entity;
731 entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
733 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
735 if (xmlstr_cmp(&attr_name, IID_ATTR))
737 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
739 if (xmlstr_cmp(&attr_name, NAME_ATTR))
741 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
745 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
746 debugstr_xmlstr(&attr_value));
751 if (error || end) return end;
752 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEPROXYSTUB_ELEM)) && parse_end_element(xmlbuf);
755 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
757 xmlstr_t attr_name, attr_value;
758 BOOL end = FALSE, error;
759 struct entity* entity;
761 entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION);
763 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
765 if (xmlstr_cmp(&attr_name, TLBID_ATTR))
767 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
769 if (xmlstr_cmp(&attr_name, VERSION_ATTR))
771 if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
773 if (xmlstr_cmp(&attr_name, HELPDIR_ATTR))
775 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
779 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
780 debugstr_xmlstr(&attr_value));
785 if (error || end) return end;
786 return parse_expect_elem(xmlbuf, ELEM_END(TYPELIB_ELEM)) && parse_end_element(xmlbuf);
789 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
791 xmlstr_t elem, content;
792 BOOL end = FALSE, ret = TRUE;
793 struct entity* entity;
795 entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION);
797 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
798 if (end) return FALSE;
800 if (!parse_text_content(xmlbuf, &content)) return FALSE;
802 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
804 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
806 if (xmlstr_cmp(&elem, ELEM_END(WINDOWCLASS_ELEM)))
808 ret = parse_end_element(xmlbuf);
813 WARN("wrong elem %s\n", debugstr_xmlstr(&elem));
821 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
823 xmlstr_t elem, content;
824 BOOL end = FALSE, ret = TRUE;
826 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
827 !parse_text_content(xmlbuf, &content))
830 TRACE("Got description %s\n", debugstr_xmlstr(&content));
832 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
834 if (xmlstr_cmp(&elem, ELEM_END(DESCRIPTION_ELEM)))
836 ret = parse_end_element(xmlbuf);
841 WARN("wrong elem %s\n", debugstr_xmlstr(&elem));
849 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
850 struct assembly* assembly)
852 xmlstr_t attr_name, attr_value;
853 BOOL end = FALSE, error;
854 struct entity* entity;
856 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
857 if (!entity) return FALSE;
859 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
861 if (xmlstr_cmp(&attr_name, IID_ATTR))
863 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
865 if (xmlstr_cmp(&attr_name, NAME_ATTR))
867 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
871 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
872 debugstr_xmlstr(&attr_value));
877 if (error || end) return end;
878 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEEXTERNALPROXYSTUB_ELEM)) &&
879 parse_end_element(xmlbuf);
882 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
884 xmlstr_t attr_name, attr_value;
885 BOOL end = FALSE, error;
886 struct entity* entity;
888 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
889 if (!entity) return FALSE;
891 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
893 if (xmlstr_cmp(&attr_name, NAME_ATTR))
895 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
897 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
899 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
903 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
904 debugstr_xmlstr(&attr_value));
909 if (error || end) return end;
910 return parse_expect_elem(xmlbuf, ELEM_END(CLRCLASS_ELEM)) && parse_end_element(xmlbuf);
913 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
915 xmlstr_t attr_name, attr_value;
916 BOOL end = FALSE, error;
917 struct entity* entity;
919 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
920 if (!entity) return FALSE;
922 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
924 if (xmlstr_cmp(&attr_name, NAME_ATTR))
926 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
928 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
930 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
934 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
935 debugstr_xmlstr(&attr_value));
940 if (error || end) return end;
941 return parse_expect_elem(xmlbuf, ELEM_END(CLRSURROGATE_ELEM)) && parse_end_element(xmlbuf);
944 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf,
945 struct actctx_loader* acl)
947 struct assembly_identity ai;
949 BOOL end = FALSE, ret = TRUE;
953 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
955 if (!parse_expect_elem(xmlbuf, ASSEMBLYIDENTITY_ELEM) ||
956 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
959 /* store the newly found identity for later loading */
960 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
962 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
964 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENTASSEMBLY_ELEM)))
966 ret = parse_end_element(xmlbuf);
971 WARN("wrong elem %s\n", debugstr_xmlstr(&elem));
979 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
982 BOOL end = FALSE, ret = TRUE;
986 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
988 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
990 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENCY_ELEM)))
992 ret = parse_end_element(xmlbuf);
995 else if (xmlstr_cmp(&elem, DEPENDENTASSEMBLY_ELEM))
997 ret = parse_dependent_assembly_elem(xmlbuf, acl);
1001 WARN("wrong element %s\n", debugstr_xmlstr(&elem));
1009 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1013 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1015 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERIT_ELEM)) && parse_end_element(xmlbuf));
1018 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1022 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1024 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERITABLE_ELEM)) && parse_end_element(xmlbuf));
1027 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1029 xmlstr_t attr_name, attr_value, elem;
1030 BOOL end = FALSE, error, ret = TRUE;
1031 struct dll_redirect* dll;
1033 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1035 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1037 if (xmlstr_cmp(&attr_name, NAME_ATTR))
1039 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1040 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1042 else if (xmlstr_cmp(&attr_name, HASH_ATTR))
1044 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1046 else if (xmlstr_cmp(&attr_name, HASHALG_ATTR))
1048 if (!xmlstr_cmp(&attr_value, "SHA1"))
1049 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
1053 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
1054 debugstr_xmlstr(&attr_value));
1059 if (error || !dll->name) return FALSE;
1060 if (end) return TRUE;
1062 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1064 if (xmlstr_cmp(&elem, ELEM_END(FILE_ELEM)))
1066 ret = parse_end_element(xmlbuf);
1069 else if (xmlstr_cmp(&elem, COMCLASS_ELEM))
1071 ret = parse_com_class_elem(xmlbuf, dll);
1073 else if (xmlstr_cmp(&elem, COMINTERFACEPROXYSTUB_ELEM))
1075 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1077 else if (xmlstr_cmp(&elem, TYPELIB_ELEM))
1079 ret = parse_typelib_elem(xmlbuf, dll);
1081 else if (xmlstr_cmp(&elem, WINDOWCLASS_ELEM))
1083 ret = parse_window_class_elem(xmlbuf, dll);
1087 WARN("wrong elem %s\n", debugstr_xmlstr(&elem));
1095 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1096 struct assembly* assembly,
1097 struct assembly_identity* expected_ai)
1099 xmlstr_t attr_name, attr_value, elem;
1100 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1101 struct assembly_identity ai;
1103 TRACE("(%p)\n", xmlbuf);
1105 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1107 if (xmlstr_cmp(&attr_name, MANIFESTVERSION_ATTR))
1109 if (!xmlstr_cmp(&attr_value, "1.0"))
1111 WARN("wrong version %s\n", debugstr_xmlstr(&attr_value));
1116 else if (xmlstr_cmp(&attr_name, XMLNS_ATTR))
1118 if (!xmlstr_cmp(&attr_value, MANIFEST_NAMESPACE))
1120 WARN("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
1127 WARN("wrong attr %s=%s\n", debugstr_xmlstr(&attr_name),
1128 debugstr_xmlstr(&attr_value));
1133 if (error || end || !xmlns || !version) return FALSE;
1134 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1136 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, NOINHERIT_ELEM))
1138 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1140 assembly->no_inherit = TRUE;
1143 if (xmlstr_cmp(&elem, NOINHERITABLE_ELEM))
1145 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1148 else if (assembly->type == ASSEMBLY_MANIFEST && assembly->no_inherit)
1151 if (!xmlstr_cmp(&elem, ASSEMBLYIDENTITY_ELEM))
1153 WARN("expected assemblyIdentity element, got %s\n", debugstr_xmlstr(&elem));
1157 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai)) return FALSE;
1161 /* FIXME: more tests */
1162 if (assembly->type == ASSEMBLY_MANIFEST &&
1163 memcmp(&ai.version, &expected_ai->version, sizeof(ai.version)))
1165 WARN("wrong version\n");
1172 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1174 if (xmlstr_cmp(&elem, ELEM_END(ASSEMBLY_ELEM)))
1176 ret = parse_end_element(xmlbuf);
1179 else if (xmlstr_cmp(&elem, DESCRIPTION_ELEM))
1181 ret = parse_description_elem(xmlbuf);
1183 else if (xmlstr_cmp(&elem, COMINTERFACEEXTERNALPROXYSTUB_ELEM))
1185 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1187 else if (xmlstr_cmp(&elem, DEPENDENCY_ELEM))
1189 ret = parse_dependency_elem(xmlbuf, acl);
1191 else if (xmlstr_cmp(&elem, FILE_ELEM))
1193 ret = parse_file_elem(xmlbuf, assembly);
1195 else if (xmlstr_cmp(&elem, CLRCLASS_ELEM))
1197 ret = parse_clr_class_elem(xmlbuf, assembly);
1199 else if (xmlstr_cmp(&elem, CLRSURROGATE_ELEM))
1201 ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1205 WARN("wrong element %s\n", debugstr_xmlstr(&elem));
1213 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1214 LPCWSTR filename, xmlbuf_t* xmlbuf )
1217 struct assembly* assembly;
1219 TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) );
1221 if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
1222 return STATUS_SXS_CANT_GEN_ACTCTX;
1224 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
1225 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1226 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1228 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1230 if (xmlstr_cmp(&elem, "?xml") &&
1231 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1232 return STATUS_SXS_CANT_GEN_ACTCTX;
1234 if (!xmlstr_cmp(&elem, ASSEMBLY_ELEM))
1236 WARN("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
1237 return STATUS_SXS_CANT_GEN_ACTCTX;
1240 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1241 return STATUS_SXS_CANT_GEN_ACTCTX;
1243 if (next_xml_elem(xmlbuf, &elem))
1245 WARN("unexpected element %s\n", debugstr_xmlstr(&elem));
1246 return STATUS_SXS_CANT_GEN_ACTCTX;
1249 if (xmlbuf->ptr != xmlbuf->end)
1251 WARN("parse error\n");
1252 return STATUS_SXS_CANT_GEN_ACTCTX;
1254 return STATUS_SUCCESS;
1257 static NTSTATUS open_nt_file( HANDLE handle, UNICODE_STRING *name )
1259 OBJECT_ATTRIBUTES attr;
1262 attr.Length = sizeof(attr);
1263 attr.RootDirectory = 0;
1264 attr.Attributes = OBJ_CASE_INSENSITIVE;
1265 attr.ObjectName = name;
1266 attr.SecurityDescriptor = NULL;
1267 attr.SecurityQualityOfService = NULL;
1268 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
1271 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
1277 LdrLockLoaderLock(0, NULL, &magic);
1278 status = LdrFindEntryForAddress( module, &pldr );
1279 if (status == STATUS_SUCCESS)
1281 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1282 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1284 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1285 str->Length = pldr->FullDllName.Length;
1286 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1288 else status = STATUS_NO_MEMORY;
1290 LdrUnlockLoaderLock(0, magic);
1294 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1295 LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang )
1298 UNICODE_STRING nameW;
1299 LDR_RESOURCE_INFO info;
1300 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1303 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), hModule, debugstr_w(filename) );
1305 if (!resname) return STATUS_INVALID_PARAMETER;
1307 info.Type = RT_MANIFEST;
1308 info.Language = lang;
1309 if (!((ULONG_PTR)resname >> 16))
1311 info.Name = (ULONG_PTR)resname;
1312 status = LdrFindResource_U(hModule, &info, 3, &entry);
1314 else if (resname[0] == '#')
1317 RtlInitUnicodeString(&nameW, resname + 1);
1318 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1319 return STATUS_INVALID_PARAMETER;
1321 status = LdrFindResource_U(hModule, &info, 3, &entry);
1325 RtlCreateUnicodeString(&nameW, resname);
1326 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1327 info.Name = (ULONG_PTR)nameW.Buffer;
1328 status = LdrFindResource_U(hModule, &info, 3, &entry);
1329 RtlFreeUnicodeString(&nameW);
1331 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1333 if (status == STATUS_SUCCESS)
1337 buf.end = buf.ptr + entry->Size;
1338 status = parse_manifest(acl, ai, filename, &buf);
1343 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1344 LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang )
1347 OBJECT_ATTRIBUTES attr;
1349 LARGE_INTEGER offset;
1354 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
1356 attr.Length = sizeof(attr);
1357 attr.RootDirectory = 0;
1358 attr.ObjectName = NULL;
1359 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1360 attr.SecurityDescriptor = NULL;
1361 attr.SecurityQualityOfService = NULL;
1364 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1365 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1366 if (status != STATUS_SUCCESS) return status;
1368 offset.QuadPart = 0;
1371 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1372 &count, ViewShare, 0, PAGE_READONLY );
1374 if (status != STATUS_SUCCESS) return status;
1376 if (RtlImageNtHeader(base)) /* we got a PE file */
1378 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1379 status = get_manifest_in_module( acl, ai, filename, module, resname, lang );
1381 else status = STATUS_INVALID_IMAGE_FORMAT;
1383 NtUnmapViewOfSection( GetCurrentProcess(), base );
1387 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1388 LPCWSTR filename, HANDLE file )
1391 OBJECT_ATTRIBUTES attr;
1393 LARGE_INTEGER offset;
1399 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
1401 attr.Length = sizeof(attr);
1402 attr.RootDirectory = 0;
1403 attr.ObjectName = NULL;
1404 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1405 attr.SecurityDescriptor = NULL;
1406 attr.SecurityQualityOfService = NULL;
1409 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1410 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1411 if (status != STATUS_SUCCESS) return status;
1413 offset.QuadPart = 0;
1416 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1417 &count, ViewShare, 0, PAGE_READONLY );
1419 if (status != STATUS_SUCCESS) return status;
1422 buf.end = buf.ptr + count;
1423 status = parse_manifest(acl, ai, filename, &buf);
1425 NtUnmapViewOfSection( GetCurrentProcess(), base );
1429 /* try to load the .manifest file associated to the file */
1430 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1431 LPCWSTR filename, HMODULE module, LPCWSTR resname )
1433 static const WCHAR fmtW[] = { '.','%','l','u',0 };
1436 UNICODE_STRING nameW;
1438 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
1440 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1442 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
1444 if (module) /* use the module filename */
1446 UNICODE_STRING name;
1448 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1450 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1451 strcatW( name.Buffer, dotManifestW );
1452 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1453 status = STATUS_NO_SUCH_FILE;
1454 RtlFreeUnicodeString( &name );
1456 if (status) return status;
1460 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1461 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1462 return STATUS_NO_MEMORY;
1463 strcpyW( buffer, filename );
1464 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1465 strcatW( buffer, dotManifestW );
1466 RtlInitUnicodeString( &nameW, buffer );
1469 status = open_nt_file( &file, &nameW );
1470 if (status == STATUS_SUCCESS)
1472 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1475 RtlFreeUnicodeString( &nameW );
1479 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
1480 struct assembly_identity* ai)
1482 static const WCHAR dotDllW[] = {'.','d','l','l',0};
1486 UNICODE_STRING nameW;
1489 /* FIXME: add support for language specific lookup */
1491 nameW.Buffer = NULL;
1492 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1493 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1494 return STATUS_NO_MEMORY;
1496 /* lookup in appdir\name.dll
1497 * appdir\name.manifest
1498 * appdir\name\name.dll
1499 * appdir\name\name.manifest
1501 strcpyW( buffer, acl->actctx->appdir.info );
1502 p = buffer + strlenW(buffer);
1503 for (i = 0; i < 2; i++)
1506 strcpyW( p, ai->name );
1509 strcpyW( p, dotDllW );
1510 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1512 status = open_nt_file( &file, &nameW );
1515 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file,
1516 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
1520 RtlFreeUnicodeString( &nameW );
1523 strcpyW( p, dotManifestW );
1524 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1526 status = open_nt_file( &file, &nameW );
1529 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1533 RtlFreeUnicodeString( &nameW );
1536 RtlFreeUnicodeString( &nameW );
1537 return STATUS_SXS_ASSEMBLY_NOT_FOUND;
1540 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
1542 NTSTATUS status = STATUS_SUCCESS;
1545 for (i = 0; i < acl->num_dependencies; i++)
1547 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
1549 FIXME( "Could not find assembly %s\n", debugstr_w(acl->dependencies[i].name) );
1550 status = STATUS_SXS_CANT_GEN_ACTCTX;
1554 /* FIXME should now iterate through all refs */
1559 /***********************************************************************
1560 * RtlCreateActivationContext (NTDLL.@)
1562 * Create an activation context.
1564 * FIXME: function signature/prototype is wrong
1566 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
1568 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
1569 ACTIVATION_CONTEXT *actctx;
1570 UNICODE_STRING nameW;
1571 struct assembly *assembly;
1573 NTSTATUS status = STATUS_NO_MEMORY;
1575 struct actctx_loader acl;
1577 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
1579 if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx) ||
1580 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
1581 return STATUS_INVALID_PARAMETER;
1583 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
1584 return STATUS_NO_MEMORY;
1586 actctx->magic = ACTCTX_MAGIC;
1587 actctx->ref_count = 1;
1589 if (!(assembly = add_assembly( actctx, APPLICATION_MANIFEST ))) goto error;
1590 if (!(assembly->id.name = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) )))
1592 assembly->id.version.major = 1;
1593 assembly->id.version.minor = 0;
1594 assembly->id.version.build = 0;
1595 assembly->id.version.revision = 0;
1596 assembly->manifest.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1597 assembly->manifest.info = NULL;
1599 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1600 actctx->config.info = NULL;
1601 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1602 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
1604 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
1611 if ((status = get_module_filename( NtCurrentTeb()->Peb->ImageBaseAddress, &dir, 0 )))
1613 if ((p = strrchrW( dir.Buffer, '\\' ))) *p = 0;
1614 actctx->appdir.info = dir.Buffer;
1617 nameW.Buffer = NULL;
1618 if (pActCtx->lpSource)
1620 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
1622 status = STATUS_NO_SUCH_FILE;
1625 status = open_nt_file( &file, &nameW );
1628 RtlFreeUnicodeString( &nameW );
1633 acl.actctx = actctx;
1634 acl.dependencies = NULL;
1635 acl.num_dependencies = 0;
1636 acl.allocated_dependencies = 0;
1638 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
1640 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
1642 /* if we have a resource it's a PE file */
1643 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
1645 status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule,
1646 pActCtx->lpResourceName, lang );
1648 /* FIXME: what to do if pActCtx->lpSource is set */
1649 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule,
1650 pActCtx->lpResourceName );
1652 else if (pActCtx->lpSource)
1654 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file,
1655 pActCtx->lpResourceName, lang );
1657 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL,
1658 pActCtx->lpResourceName );
1660 else status = STATUS_INVALID_PARAMETER;
1664 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file );
1667 if (file) NtClose( file );
1668 RtlFreeUnicodeString( &nameW );
1670 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
1671 free_depend_manifests( &acl );
1673 if (status == STATUS_SUCCESS) *handle = actctx;
1674 else actctx_release( actctx );
1678 if (file) NtClose( file );
1679 actctx_release( actctx );
1684 /***********************************************************************
1685 * RtlAddRefActivationContext (NTDLL.@)
1687 void WINAPI RtlAddRefActivationContext( HANDLE handle )
1689 ACTIVATION_CONTEXT *actctx;
1691 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
1695 /******************************************************************
1696 * RtlReleaseActivationContext (NTDLL.@)
1698 void WINAPI RtlReleaseActivationContext( HANDLE handle )
1700 ACTIVATION_CONTEXT *actctx;
1702 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
1706 /******************************************************************
1707 * RtlActivateActivationContext (NTDLL.@)
1709 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, ULONG_PTR *cookie )
1711 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1713 TRACE( "%p %p\n", handle, cookie );
1715 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
1716 return STATUS_NO_MEMORY;
1718 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1719 frame->ActivationContext = handle;
1721 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
1722 RtlAddRefActivationContext( handle );
1724 *cookie = (ULONG_PTR)frame;
1725 return STATUS_SUCCESS;
1729 /***********************************************************************
1730 * RtlDeactivateActivationContext (NTDLL.@)
1732 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
1734 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
1736 TRACE( "%x %lx\n", flags, cookie );
1738 /* find the right frame */
1739 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1740 for (frame = top; frame; frame = frame->Previous)
1741 if ((ULONG_PTR)frame == cookie) break;
1744 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
1746 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
1747 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
1749 /* pop everything up to and including frame */
1750 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
1752 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
1754 frame = top->Previous;
1755 RtlReleaseActivationContext( top->ActivationContext );
1756 RtlFreeHeap( GetProcessHeap(), 0, top );
1762 /******************************************************************
1763 * RtlFreeThreadActivationContextStack (NTDLL.@)
1765 void WINAPI RtlFreeThreadActivationContextStack(void)
1767 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1769 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1772 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
1773 RtlReleaseActivationContext( frame->ActivationContext );
1774 RtlFreeHeap( GetProcessHeap(), 0, frame );
1777 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
1781 /******************************************************************
1782 * RtlGetActiveActivationContext (NTDLL.@)
1784 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
1786 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
1788 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
1789 RtlAddRefActivationContext( *handle );
1794 return STATUS_SUCCESS;
1798 /******************************************************************
1799 * RtlIsActivationContextActive (NTDLL.@)
1801 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
1803 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1805 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
1806 if (frame->ActivationContext == handle) return TRUE;