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;
140 unsigned int allocated;
147 struct entity_array entities;
152 APPLICATION_MANIFEST,
158 enum assembly_type type;
159 struct assembly_identity id;
160 struct file_info manifest;
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
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;
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)
235 if (!str) return NULL;
236 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
238 return strcpyW(ptr, str);
241 static WCHAR *xmlstrdupW(const xmlstr_t* str)
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 );
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)
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) );
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++];
299 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
301 if (assembly->num_dlls == assembly->allocated_dlls)
304 unsigned int new_count;
307 new_count = assembly->allocated_dlls * 2;
308 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
309 assembly->dlls, new_count * sizeof(*assembly->dlls) );
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)
338 unsigned int new_count;
341 new_count = array->allocated * 2;
342 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
343 array->base, new_count * sizeof(*array->base) );
348 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
350 if (!ptr) return NULL;
352 array->allocated = new_count;
354 entity = &array->base[array->num++];
359 static void free_entity_array(struct entity_array *array)
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);
370 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
371 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
372 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.name);
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);
379 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
380 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
382 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
383 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.name);
384 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.clsid);
386 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
387 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
388 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
391 FIXME("Unknown entity kind %d\n", entity->kind);
394 RtlFreeHeap( GetProcessHeap(), 0, array->base );
397 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
398 struct assembly_identity* ai)
400 /* FIXME: should check that the passed ai isn't already in the list */
401 if (acl->num_dependencies == acl->allocated_dependencies)
404 unsigned int new_count;
405 if (acl->dependencies)
407 new_count = acl->allocated_dependencies * 2;
408 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
409 new_count * sizeof(acl->dependencies[0]));
414 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
416 if (!ptr) return FALSE;
417 acl->dependencies = ptr;
418 acl->allocated_dependencies = new_count;
420 acl->dependencies[acl->num_dependencies++] = *ai;
425 static void free_depend_manifests(struct actctx_loader* acl)
428 for (i = 0; i < acl->num_dependencies; i++)
429 free_assembly_identity(&acl->dependencies[i]);
430 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
433 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
435 ACTIVATION_CONTEXT *actctx = h;
437 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
438 switch (actctx->magic)
447 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
449 interlocked_xchg_add( &actctx->ref_count, 1 );
452 static void actctx_release( ACTIVATION_CONTEXT *actctx )
454 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
458 for (i = 0; i < actctx->num_assemblies; i++)
460 struct assembly *assembly = &actctx->assemblies[i];
461 for (j = 0; j < assembly->num_dlls; j++)
463 struct dll_redirect *dll = &assembly->dlls[j];
464 free_entity_array( &dll->entities );
465 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
466 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
468 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
469 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
470 free_entity_array( &assembly->entities );
471 free_assembly_identity(&assembly->id);
473 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
474 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
475 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
477 RtlFreeHeap( GetProcessHeap(), 0, actctx );
481 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
482 BOOL* error, BOOL* end)
488 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
491 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
493 if (*xmlbuf->ptr == '/')
496 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
505 if (*xmlbuf->ptr == '>')
513 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
515 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
517 name->ptr = xmlbuf->ptr;
518 name->len = ptr-xmlbuf->ptr;
522 if (ptr == xmlbuf->end || *ptr != '\"') return FALSE;
525 if (ptr == xmlbuf->end) return FALSE;
527 ptr = memchr(ptr, '\"', xmlbuf->end - ptr);
530 xmlbuf->ptr = xmlbuf->end;
534 value->len = ptr - value->ptr;
535 xmlbuf->ptr = ptr + 1;
537 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
543 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
549 ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
552 xmlbuf->ptr = xmlbuf->end;
556 if (ptr + 3 < xmlbuf->end && !strncmp( ptr, "!--", 3 )) /* skip comment */
558 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
559 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
561 if (ptr + 3 > xmlbuf->end)
563 xmlbuf->ptr = xmlbuf->end;
566 xmlbuf->ptr = ptr + 3;
572 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
575 elem->ptr = xmlbuf->ptr;
576 elem->len = ptr - xmlbuf->ptr;
578 return xmlbuf->ptr != xmlbuf->end;
581 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
583 /* FIXME: parse attributes */
586 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
588 if (ptr[0] == '?' && ptr[1] == '>')
590 xmlbuf->ptr = ptr + 2;
597 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
599 const char *ptr = memchr(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
601 if (!ptr) return FALSE;
603 content->ptr = xmlbuf->ptr;
604 content->len = ptr - xmlbuf->ptr;
610 static BOOL parse_version(const xmlstr_t *str, struct version *version)
616 /* major.minor.build.revision */
617 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
618 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
620 if (*curr >= '0' && *curr <= '9')
622 ver[pos] = ver[pos] * 10 + *curr - '0';
623 if (ver[pos] >= 0x10000) goto error;
625 else if (*curr == '.')
627 if (++pos >= 4) goto error;
631 version->major = ver[0];
632 version->minor = ver[1];
633 version->build = ver[2];
634 version->revision = ver[3];
638 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
642 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const char* name)
645 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
646 if (xmlstr_cmp(&elem, name)) return TRUE;
647 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
651 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
653 xmlstr_t attr_name, attr_value;
656 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
658 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
659 debugstr_xmlstr(&attr_value));
664 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
667 return parse_expect_no_attr(xmlbuf, &end) && !end;
670 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
672 xmlstr_t attr_name, attr_value, elem;
673 BOOL end = FALSE, error, ret = TRUE;
675 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
676 if(error || end) return end;
678 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
680 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
681 !strncmp(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
684 ret = parse_unknown_elem(xmlbuf, &elem);
687 return ret && parse_end_element(xmlbuf);
690 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
691 struct assembly_identity* ai)
693 xmlstr_t attr_name, attr_value;
694 BOOL end = FALSE, error;
698 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
700 if (xmlstr_cmp(&attr_name, NAME_ATTR))
702 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
704 else if (xmlstr_cmp(&attr_name, TYPE_ATTR))
706 if (!xmlstr_cmp(&attr_value, "win32"))
708 FIXME("wrong type attr %s\n", debugstr_xmlstr(&attr_value));
711 ai->type = TYPE_WIN32;
713 else if (xmlstr_cmp(&attr_name, VERSION_ATTR))
715 if (!parse_version(&attr_value, &ai->version)) return FALSE;
717 else if (xmlstr_cmp(&attr_name, PROCESSORARCHITECTURE_ATTR))
719 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
721 else if (xmlstr_cmp(&attr_name, PUBLICKEYTOKEN_ATTR))
723 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
725 else if (xmlstr_cmp(&attr_name, LANGUAGE_ATTR))
727 WARN("Unsupported yet language attribute (%s)\n",
728 debugstr_xmlstr(&attr_value));
729 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
733 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
734 debugstr_xmlstr(&attr_value));
738 if (error || end) return end;
739 return parse_expect_elem(xmlbuf, ELEM_END(ASSEMBLYIDENTITY_ELEM)) && parse_end_element(xmlbuf);
742 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
744 xmlstr_t attr_name, attr_value;
745 BOOL end = FALSE, error;
746 struct entity* entity;
748 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
751 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
753 if (xmlstr_cmp(&attr_name, CLSID_ATTR))
755 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
759 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
763 if (error || end) return end;
764 return parse_expect_elem(xmlbuf, ELEM_END(COMCLASS_ELEM)) && parse_end_element(xmlbuf);
767 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
769 xmlstr_t attr_name, attr_value;
770 BOOL end = FALSE, error;
771 struct entity* entity;
773 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
776 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
778 if (xmlstr_cmp(&attr_name, IID_ATTR))
780 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
782 if (xmlstr_cmp(&attr_name, NAME_ATTR))
784 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
788 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
792 if (error || end) return end;
793 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEPROXYSTUB_ELEM)) && parse_end_element(xmlbuf);
796 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
798 xmlstr_t attr_name, attr_value;
799 BOOL end = FALSE, error;
800 struct entity* entity;
802 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
805 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
807 if (xmlstr_cmp(&attr_name, TLBID_ATTR))
809 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
811 if (xmlstr_cmp(&attr_name, VERSION_ATTR))
813 if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
815 if (xmlstr_cmp(&attr_name, HELPDIR_ATTR))
817 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
821 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
825 if (error || end) return end;
826 return parse_expect_elem(xmlbuf, ELEM_END(TYPELIB_ELEM)) && parse_end_element(xmlbuf);
829 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
831 xmlstr_t elem, content;
832 BOOL end = FALSE, ret = TRUE;
833 struct entity* entity;
835 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
838 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
839 if (end) return FALSE;
841 if (!parse_text_content(xmlbuf, &content)) return FALSE;
843 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
845 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
847 if (xmlstr_cmp(&elem, ELEM_END(WINDOWCLASS_ELEM)))
849 ret = parse_end_element(xmlbuf);
854 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
855 ret = parse_unknown_elem(xmlbuf, &elem);
862 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
864 xmlstr_t attr_name, attr_value;
865 BOOL end = FALSE, error;
867 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
869 if (xmlstr_cmp(&attr_name, OLDVERSION_ATTR))
871 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
873 else if (xmlstr_cmp(&attr_name, NEWVERSION_ATTR))
875 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
879 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
883 if (error || end) return end;
884 return parse_expect_elem(xmlbuf, ELEM_END(BINDINGREDIRECT_ELEM)) && parse_end_element(xmlbuf);
887 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
889 xmlstr_t elem, content;
890 BOOL end = FALSE, ret = TRUE;
892 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
893 !parse_text_content(xmlbuf, &content))
896 TRACE("Got description %s\n", debugstr_xmlstr(&content));
898 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
900 if (xmlstr_cmp(&elem, ELEM_END(DESCRIPTION_ELEM)))
902 ret = parse_end_element(xmlbuf);
907 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
908 ret = parse_unknown_elem(xmlbuf, &elem);
915 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
916 struct assembly* assembly)
918 xmlstr_t attr_name, attr_value;
919 BOOL end = FALSE, error;
920 struct entity* entity;
922 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
923 if (!entity) return FALSE;
925 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
927 if (xmlstr_cmp(&attr_name, IID_ATTR))
929 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
931 if (xmlstr_cmp(&attr_name, NAME_ATTR))
933 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
937 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
941 if (error || end) return end;
942 return parse_expect_elem(xmlbuf, ELEM_END(COMINTERFACEEXTERNALPROXYSTUB_ELEM)) &&
943 parse_end_element(xmlbuf);
946 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
948 xmlstr_t attr_name, attr_value;
949 BOOL end = FALSE, error;
950 struct entity* entity;
952 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
953 if (!entity) return FALSE;
955 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
957 if (xmlstr_cmp(&attr_name, NAME_ATTR))
959 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
961 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
963 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
967 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
971 if (error || end) return end;
972 return parse_expect_elem(xmlbuf, ELEM_END(CLRCLASS_ELEM)) && parse_end_element(xmlbuf);
975 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
977 xmlstr_t attr_name, attr_value;
978 BOOL end = FALSE, error;
979 struct entity* entity;
981 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
982 if (!entity) return FALSE;
984 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
986 if (xmlstr_cmp(&attr_name, NAME_ATTR))
988 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
990 else if (xmlstr_cmp(&attr_name, CLSID_ATTR))
992 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
996 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1000 if (error || end) return end;
1001 return parse_expect_elem(xmlbuf, ELEM_END(CLRSURROGATE_ELEM)) && parse_end_element(xmlbuf);
1004 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1006 struct assembly_identity ai;
1008 BOOL end = FALSE, ret = TRUE;
1010 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1012 memset(&ai, 0, sizeof(ai));
1013 ai.optional = optional;
1015 if (!parse_expect_elem(xmlbuf, ASSEMBLYIDENTITY_ELEM) ||
1016 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1019 TRACE( "adding %s\n", debugstr_w(ai.name) );
1021 /* store the newly found identity for later loading */
1022 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1024 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1026 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENTASSEMBLY_ELEM)))
1028 ret = parse_end_element(xmlbuf);
1031 else if (xmlstr_cmp(&elem, BINDINGREDIRECT_ELEM))
1033 ret = parse_binding_redirect_elem(xmlbuf);
1037 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1038 ret = parse_unknown_elem(xmlbuf, &elem);
1045 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1047 xmlstr_t attr_name, attr_value, elem;
1048 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1052 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1054 if (xmlstr_cmp(&attr_name, OPTIONAL_ATTR))
1056 optional = xmlstr_cmp( &attr_value, "yes" );
1057 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
1061 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1065 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1067 if (xmlstr_cmp(&elem, ELEM_END(DEPENDENCY_ELEM)))
1069 ret = parse_end_element(xmlbuf);
1072 else if (xmlstr_cmp(&elem, DEPENDENTASSEMBLY_ELEM))
1074 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1078 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1079 ret = parse_unknown_elem(xmlbuf, &elem);
1086 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1090 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1092 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERIT_ELEM)) && parse_end_element(xmlbuf));
1095 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1099 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1101 (parse_expect_elem(xmlbuf, ELEM_END(NOINHERITABLE_ELEM)) && parse_end_element(xmlbuf));
1104 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1106 xmlstr_t attr_name, attr_value, elem;
1107 BOOL end = FALSE, error, ret = TRUE;
1108 struct dll_redirect* dll;
1110 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1112 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1114 if (xmlstr_cmp(&attr_name, NAME_ATTR))
1116 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1117 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1119 else if (xmlstr_cmp(&attr_name, HASH_ATTR))
1121 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1123 else if (xmlstr_cmp(&attr_name, HASHALG_ATTR))
1125 if (!xmlstr_cmp(&attr_value, "SHA1"))
1126 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
1130 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1134 if (error || !dll->name) return FALSE;
1135 if (end) return TRUE;
1137 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1139 if (xmlstr_cmp(&elem, ELEM_END(FILE_ELEM)))
1141 ret = parse_end_element(xmlbuf);
1144 else if (xmlstr_cmp(&elem, COMCLASS_ELEM))
1146 ret = parse_com_class_elem(xmlbuf, dll);
1148 else if (xmlstr_cmp(&elem, COMINTERFACEPROXYSTUB_ELEM))
1150 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1152 else if (xmlstr_cmp(&elem, HASH_ELEM))
1154 WARN(HASH_ELEM " (undocumented) not supported\n");
1155 ret = parse_unknown_elem(xmlbuf, &elem);
1157 else if (xmlstr_cmp(&elem, TYPELIB_ELEM))
1159 ret = parse_typelib_elem(xmlbuf, dll);
1161 else if (xmlstr_cmp(&elem, WINDOWCLASS_ELEM))
1163 ret = parse_window_class_elem(xmlbuf, dll);
1167 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1168 ret = parse_unknown_elem( xmlbuf, &elem );
1175 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1176 struct assembly* assembly,
1177 struct assembly_identity* expected_ai)
1179 xmlstr_t attr_name, attr_value, elem;
1180 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1182 TRACE("(%p)\n", xmlbuf);
1184 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1186 if (xmlstr_cmp(&attr_name, MANIFESTVERSION_ATTR))
1188 if (!xmlstr_cmp(&attr_value, "1.0"))
1190 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
1195 else if (xmlstr_cmp(&attr_name, XMLNS_ATTR))
1197 if (!xmlstr_cmp(&attr_value, MANIFESTV1_NAMESPACE) &&
1198 !xmlstr_cmp(&attr_value, MANIFESTV3_NAMESPACE))
1200 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
1207 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1211 if (error || end || !xmlns || !version) return FALSE;
1212 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1214 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, NOINHERIT_ELEM))
1216 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1218 assembly->no_inherit = TRUE;
1221 if (xmlstr_cmp(&elem, NOINHERITABLE_ELEM))
1223 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1226 else if (assembly->type == ASSEMBLY_MANIFEST && assembly->no_inherit)
1229 if (xmlstr_cmp(&elem, ASSEMBLYIDENTITY_ELEM))
1231 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
1232 ret = next_xml_elem(xmlbuf, &elem);
1236 /* FIXME: more tests */
1237 if (assembly->type == ASSEMBLY_MANIFEST &&
1238 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
1240 FIXME("wrong version\n");
1248 if (xmlstr_cmp(&elem, ELEM_END(ASSEMBLY_ELEM)))
1250 ret = parse_end_element(xmlbuf);
1253 else if (xmlstr_cmp(&elem, DESCRIPTION_ELEM))
1255 ret = parse_description_elem(xmlbuf);
1257 else if (xmlstr_cmp(&elem, COMINTERFACEEXTERNALPROXYSTUB_ELEM))
1259 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1261 else if (xmlstr_cmp(&elem, DEPENDENCY_ELEM))
1263 ret = parse_dependency_elem(xmlbuf, acl);
1265 else if (xmlstr_cmp(&elem, FILE_ELEM))
1267 ret = parse_file_elem(xmlbuf, assembly);
1269 else if (xmlstr_cmp(&elem, CLRCLASS_ELEM))
1271 ret = parse_clr_class_elem(xmlbuf, assembly);
1273 else if (xmlstr_cmp(&elem, CLRSURROGATE_ELEM))
1275 ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1279 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1280 ret = parse_unknown_elem(xmlbuf, &elem);
1282 if (ret) ret = next_xml_elem(xmlbuf, &elem);
1288 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1289 LPCWSTR filename, xmlbuf_t* xmlbuf )
1292 struct assembly* assembly;
1294 TRACE( "parsing manifest loaded from %s\n", debugstr_w(filename) );
1296 if (!(assembly = add_assembly(acl->actctx, ASSEMBLY_MANIFEST)))
1297 return STATUS_SXS_CANT_GEN_ACTCTX;
1299 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
1300 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1301 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1303 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1305 if (xmlstr_cmp(&elem, "?xml") &&
1306 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1307 return STATUS_SXS_CANT_GEN_ACTCTX;
1309 if (!xmlstr_cmp(&elem, ASSEMBLY_ELEM))
1311 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
1312 return STATUS_SXS_CANT_GEN_ACTCTX;
1315 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1317 FIXME("failed to parse manifest %s\n", debugstr_w(filename) );
1318 return STATUS_SXS_CANT_GEN_ACTCTX;
1321 if (next_xml_elem(xmlbuf, &elem))
1323 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
1324 return STATUS_SXS_CANT_GEN_ACTCTX;
1327 if (xmlbuf->ptr != xmlbuf->end)
1329 FIXME("parse error\n");
1330 return STATUS_SXS_CANT_GEN_ACTCTX;
1332 return STATUS_SUCCESS;
1335 static NTSTATUS open_nt_file( HANDLE handle, UNICODE_STRING *name )
1337 OBJECT_ATTRIBUTES attr;
1340 attr.Length = sizeof(attr);
1341 attr.RootDirectory = 0;
1342 attr.Attributes = OBJ_CASE_INSENSITIVE;
1343 attr.ObjectName = name;
1344 attr.SecurityDescriptor = NULL;
1345 attr.SecurityQualityOfService = NULL;
1346 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
1349 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
1355 LdrLockLoaderLock(0, NULL, &magic);
1356 status = LdrFindEntryForAddress( module, &pldr );
1357 if (status == STATUS_SUCCESS)
1359 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1360 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1362 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1363 str->Length = pldr->FullDllName.Length;
1364 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1366 else status = STATUS_NO_MEMORY;
1368 LdrUnlockLoaderLock(0, magic);
1372 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1373 LPCWSTR filename, HANDLE hModule, LPCWSTR resname, ULONG lang )
1376 UNICODE_STRING nameW;
1377 LDR_RESOURCE_INFO info;
1378 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1381 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), hModule, debugstr_w(filename) );
1383 if (!resname) return STATUS_INVALID_PARAMETER;
1385 info.Type = RT_MANIFEST;
1386 info.Language = lang;
1387 if (!((ULONG_PTR)resname >> 16))
1389 info.Name = (ULONG_PTR)resname;
1390 status = LdrFindResource_U(hModule, &info, 3, &entry);
1392 else if (resname[0] == '#')
1395 RtlInitUnicodeString(&nameW, resname + 1);
1396 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1397 return STATUS_INVALID_PARAMETER;
1399 status = LdrFindResource_U(hModule, &info, 3, &entry);
1403 RtlCreateUnicodeString(&nameW, resname);
1404 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1405 info.Name = (ULONG_PTR)nameW.Buffer;
1406 status = LdrFindResource_U(hModule, &info, 3, &entry);
1407 RtlFreeUnicodeString(&nameW);
1409 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1411 if (status == STATUS_SUCCESS)
1415 buf.end = buf.ptr + entry->Size;
1416 status = parse_manifest(acl, ai, filename, &buf);
1421 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1422 LPCWSTR filename, HANDLE file, LPCWSTR resname, ULONG lang )
1425 OBJECT_ATTRIBUTES attr;
1427 LARGE_INTEGER offset;
1432 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
1434 attr.Length = sizeof(attr);
1435 attr.RootDirectory = 0;
1436 attr.ObjectName = NULL;
1437 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1438 attr.SecurityDescriptor = NULL;
1439 attr.SecurityQualityOfService = NULL;
1442 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1443 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1444 if (status != STATUS_SUCCESS) return status;
1446 offset.QuadPart = 0;
1449 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1450 &count, ViewShare, 0, PAGE_READONLY );
1452 if (status != STATUS_SUCCESS) return status;
1454 if (RtlImageNtHeader(base)) /* we got a PE file */
1456 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1457 status = get_manifest_in_module( acl, ai, filename, module, resname, lang );
1459 else status = STATUS_INVALID_IMAGE_FORMAT;
1461 NtUnmapViewOfSection( GetCurrentProcess(), base );
1465 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1466 LPCWSTR filename, HANDLE file )
1469 OBJECT_ATTRIBUTES attr;
1471 LARGE_INTEGER offset;
1477 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
1479 attr.Length = sizeof(attr);
1480 attr.RootDirectory = 0;
1481 attr.ObjectName = NULL;
1482 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1483 attr.SecurityDescriptor = NULL;
1484 attr.SecurityQualityOfService = NULL;
1487 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1488 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1489 if (status != STATUS_SUCCESS) return status;
1491 offset.QuadPart = 0;
1494 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
1495 &count, ViewShare, 0, PAGE_READONLY );
1497 if (status != STATUS_SUCCESS) return status;
1500 buf.end = buf.ptr + count;
1501 status = parse_manifest(acl, ai, filename, &buf);
1503 NtUnmapViewOfSection( GetCurrentProcess(), base );
1507 /* try to load the .manifest file associated to the file */
1508 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1509 LPCWSTR filename, HMODULE module, LPCWSTR resname )
1511 static const WCHAR fmtW[] = { '.','%','l','u',0 };
1514 UNICODE_STRING nameW;
1516 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
1518 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1520 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
1522 if (module) /* use the module filename */
1524 UNICODE_STRING name;
1526 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1528 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1529 strcatW( name.Buffer, dotManifestW );
1530 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1531 status = STATUS_NO_SUCH_FILE;
1532 RtlFreeUnicodeString( &name );
1534 if (status) return status;
1538 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1539 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1540 return STATUS_NO_MEMORY;
1541 strcpyW( buffer, filename );
1542 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1543 strcatW( buffer, dotManifestW );
1544 RtlInitUnicodeString( &nameW, buffer );
1547 status = open_nt_file( &file, &nameW );
1548 if (status == STATUS_SUCCESS)
1550 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1553 RtlFreeUnicodeString( &nameW );
1557 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
1559 static const WCHAR lookup_fmtW[] =
1560 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1562 '.','m','a','n','i','f','e','s','t',0};
1564 WCHAR *lookup, *ret = NULL;
1565 UNICODE_STRING lookup_us;
1567 unsigned int data_pos = 0, data_len;
1570 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
1571 (strlenW(ai->arch) + strlenW(ai->name)
1572 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
1573 + sizeof(lookup_fmtW) )))
1576 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
1577 RtlInitUnicodeString( &lookup_us, lookup );
1579 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1580 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
1581 if (io.u.Status == STATUS_SUCCESS)
1583 FILE_BOTH_DIR_INFORMATION *dir_info;
1585 ULONG build, revision;
1587 data_len = io.Information;
1591 if (data_pos >= data_len)
1593 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1594 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
1595 if (io.u.Status != STATUS_SUCCESS) break;
1596 data_len = io.Information;
1599 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
1601 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
1602 else data_pos = data_len;
1604 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
1606 if (build < ai->version.build) continue;
1607 tmp = strchrW(tmp, '.') + 1;
1608 revision = atoiW(tmp);
1609 if (build == ai->version.build && revision < ai->version.revision)
1611 ai->version.build = build;
1612 ai->version.revision = revision;
1613 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
1615 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
1616 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
1621 else WARN("no matching file for %s\n", debugstr_w(lookup));
1622 RtlFreeHeap( GetProcessHeap(), 0, lookup );
1626 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
1628 struct assembly_identity sxs_ai;
1629 UNICODE_STRING path_us;
1630 OBJECT_ATTRIBUTES attr;
1632 WCHAR *path, *file = NULL;
1635 static const WCHAR manifest_dirW[] =
1636 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
1638 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
1640 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, windows_dir.Length + sizeof(manifest_dirW) )))
1641 return STATUS_NO_MEMORY;
1643 memcpy( path, windows_dir.Buffer, windows_dir.Length );
1644 memcpy( path + windows_dir.Length/sizeof(WCHAR), manifest_dirW, sizeof(manifest_dirW) );
1646 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
1648 RtlFreeHeap( GetProcessHeap(), 0, path );
1649 return STATUS_NO_SUCH_FILE;
1651 RtlFreeHeap( GetProcessHeap(), 0, path );
1653 attr.Length = sizeof(attr);
1654 attr.RootDirectory = 0;
1655 attr.Attributes = OBJ_CASE_INSENSITIVE;
1656 attr.ObjectName = &path_us;
1657 attr.SecurityDescriptor = NULL;
1658 attr.SecurityQualityOfService = NULL;
1660 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1661 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
1664 file = lookup_manifest_file( handle, &sxs_ai );
1669 RtlFreeUnicodeString( &path_us );
1670 return STATUS_NO_SUCH_FILE;
1673 /* append file name to directory path */
1674 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
1675 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
1677 RtlFreeHeap( GetProcessHeap(), 0, file );
1678 RtlFreeUnicodeString( &path_us );
1679 return STATUS_NO_MEMORY;
1682 path[path_us.Length/sizeof(WCHAR)] = '\\';
1683 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
1684 RtlFreeHeap( GetProcessHeap(), 0, file );
1685 RtlInitUnicodeString( &path_us, path );
1687 if (!open_nt_file( &handle, &path_us ))
1689 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, handle);
1692 else io.u.Status = STATUS_NO_SUCH_FILE;
1694 RtlFreeUnicodeString( &path_us );
1698 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
1699 struct assembly_identity* ai)
1701 static const WCHAR dotDllW[] = {'.','d','l','l',0};
1705 UNICODE_STRING nameW;
1708 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
1710 /* FIXME: add support for language specific lookup */
1712 nameW.Buffer = NULL;
1713 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
1714 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1715 return STATUS_NO_MEMORY;
1717 /* lookup in appdir\name.dll
1718 * appdir\name.manifest
1719 * appdir\name\name.dll
1720 * appdir\name\name.manifest
1722 strcpyW( buffer, acl->actctx->appdir.info );
1723 p = buffer + strlenW(buffer);
1724 for (i = 0; i < 2; i++)
1727 strcpyW( p, ai->name );
1730 strcpyW( p, dotDllW );
1731 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1733 status = open_nt_file( &file, &nameW );
1736 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, file,
1737 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
1741 RtlFreeUnicodeString( &nameW );
1744 strcpyW( p, dotManifestW );
1745 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
1747 status = open_nt_file( &file, &nameW );
1750 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, file );
1754 RtlFreeUnicodeString( &nameW );
1757 RtlFreeUnicodeString( &nameW );
1758 return STATUS_SXS_ASSEMBLY_NOT_FOUND;
1761 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
1763 NTSTATUS status = STATUS_SUCCESS;
1766 for (i = 0; i < acl->num_dependencies; i++)
1768 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
1770 if (!acl->dependencies[i].optional)
1772 FIXME( "Could not find dependent assembly %s\n", debugstr_w(acl->dependencies[i].name) );
1773 status = STATUS_SXS_CANT_GEN_ACTCTX;
1778 /* FIXME should now iterate through all refs */
1783 /***********************************************************************
1784 * RtlCreateActivationContext (NTDLL.@)
1786 * Create an activation context.
1788 * FIXME: function signature/prototype is wrong
1790 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
1792 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
1793 ACTIVATION_CONTEXT *actctx;
1794 UNICODE_STRING nameW;
1795 struct assembly *assembly;
1797 NTSTATUS status = STATUS_NO_MEMORY;
1799 struct actctx_loader acl;
1801 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
1803 if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx) ||
1804 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
1805 return STATUS_INVALID_PARAMETER;
1807 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
1808 return STATUS_NO_MEMORY;
1810 actctx->magic = ACTCTX_MAGIC;
1811 actctx->ref_count = 1;
1813 if (!(assembly = add_assembly( actctx, APPLICATION_MANIFEST ))) goto error;
1814 if (!(assembly->id.name = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) )))
1816 assembly->id.version.major = 1;
1817 assembly->id.version.minor = 0;
1818 assembly->id.version.build = 0;
1819 assembly->id.version.revision = 0;
1820 assembly->manifest.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1821 assembly->manifest.info = NULL;
1823 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1824 actctx->config.info = NULL;
1825 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
1826 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
1828 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
1835 if ((status = get_module_filename( NtCurrentTeb()->Peb->ImageBaseAddress, &dir, 0 )))
1837 if ((p = strrchrW( dir.Buffer, '\\' ))) *p = 0;
1838 actctx->appdir.info = dir.Buffer;
1841 nameW.Buffer = NULL;
1842 if (pActCtx->lpSource)
1844 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
1846 status = STATUS_NO_SUCH_FILE;
1849 status = open_nt_file( &file, &nameW );
1852 RtlFreeUnicodeString( &nameW );
1857 acl.actctx = actctx;
1858 acl.dependencies = NULL;
1859 acl.num_dependencies = 0;
1860 acl.allocated_dependencies = 0;
1862 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
1864 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
1866 /* if we have a resource it's a PE file */
1867 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
1869 status = get_manifest_in_module( &acl, NULL, NULL, pActCtx->hModule,
1870 pActCtx->lpResourceName, lang );
1872 /* FIXME: what to do if pActCtx->lpSource is set */
1873 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, pActCtx->hModule,
1874 pActCtx->lpResourceName );
1876 else if (pActCtx->lpSource)
1878 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, file,
1879 pActCtx->lpResourceName, lang );
1881 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, NULL,
1882 pActCtx->lpResourceName );
1884 else status = STATUS_INVALID_PARAMETER;
1888 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, file );
1891 if (file) NtClose( file );
1892 RtlFreeUnicodeString( &nameW );
1894 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
1895 free_depend_manifests( &acl );
1897 if (status == STATUS_SUCCESS) *handle = actctx;
1898 else actctx_release( actctx );
1902 if (file) NtClose( file );
1903 actctx_release( actctx );
1908 /***********************************************************************
1909 * RtlAddRefActivationContext (NTDLL.@)
1911 void WINAPI RtlAddRefActivationContext( HANDLE handle )
1913 ACTIVATION_CONTEXT *actctx;
1915 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
1919 /******************************************************************
1920 * RtlReleaseActivationContext (NTDLL.@)
1922 void WINAPI RtlReleaseActivationContext( HANDLE handle )
1924 ACTIVATION_CONTEXT *actctx;
1926 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
1930 /******************************************************************
1931 * RtlActivateActivationContext (NTDLL.@)
1933 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, ULONG_PTR *cookie )
1935 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1937 TRACE( "%p %p\n", handle, cookie );
1939 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
1940 return STATUS_NO_MEMORY;
1942 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1943 frame->ActivationContext = handle;
1945 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
1946 RtlAddRefActivationContext( handle );
1948 *cookie = (ULONG_PTR)frame;
1949 return STATUS_SUCCESS;
1953 /***********************************************************************
1954 * RtlDeactivateActivationContext (NTDLL.@)
1956 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
1958 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
1960 TRACE( "%x %lx\n", flags, cookie );
1962 /* find the right frame */
1963 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1964 for (frame = top; frame; frame = frame->Previous)
1965 if ((ULONG_PTR)frame == cookie) break;
1968 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
1970 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
1971 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
1973 /* pop everything up to and including frame */
1974 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
1976 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
1978 frame = top->Previous;
1979 RtlReleaseActivationContext( top->ActivationContext );
1980 RtlFreeHeap( GetProcessHeap(), 0, top );
1986 /******************************************************************
1987 * RtlFreeThreadActivationContextStack (NTDLL.@)
1989 void WINAPI RtlFreeThreadActivationContextStack(void)
1991 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
1993 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
1996 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
1997 RtlReleaseActivationContext( frame->ActivationContext );
1998 RtlFreeHeap( GetProcessHeap(), 0, frame );
2001 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
2005 /******************************************************************
2006 * RtlGetActiveActivationContext (NTDLL.@)
2008 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
2010 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2012 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2013 RtlAddRefActivationContext( *handle );
2018 return STATUS_SUCCESS;
2022 /******************************************************************
2023 * RtlIsActivationContextActive (NTDLL.@)
2025 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
2027 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2029 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
2030 if (frame->ActivationContext == handle) return TRUE;