include: Move ddk/imm.h to immdev.h.
[wine.git] / dlls / ntdll / actctx.c
blob721a2f339a5aa435a0eadce34cefbf85c770364b
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #define NONAMELESSUNION
32 #include "winternl.h"
33 #include "ddk/wdm.h"
34 #include "ntdll_misc.h"
35 #include "wine/exception.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
40 #define ACTCTX_FLAGS_ALL (\
41 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
42 ACTCTX_FLAG_LANGID_VALID |\
43 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
44 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
45 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
46 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
47 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
48 ACTCTX_FLAG_HMODULE_VALID )
50 #define ACTCTX_MAGIC 0xC07E3E11
51 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
52 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
54 /* we don't want to include winuser.h */
55 #define RT_MANIFEST ((ULONG_PTR)24)
56 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
58 /* from oaidl.h */
59 typedef enum tagLIBFLAGS {
60 LIBFLAG_FRESTRICTED = 0x1,
61 LIBFLAG_FCONTROL = 0x2,
62 LIBFLAG_FHIDDEN = 0x4,
63 LIBFLAG_FHASDISKIMAGE = 0x8
64 } LIBFLAGS;
66 /* from oleidl.idl */
67 typedef enum tagOLEMISC
69 OLEMISC_RECOMPOSEONRESIZE = 0x1,
70 OLEMISC_ONLYICONIC = 0x2,
71 OLEMISC_INSERTNOTREPLACE = 0x4,
72 OLEMISC_STATIC = 0x8,
73 OLEMISC_CANTLINKINSIDE = 0x10,
74 OLEMISC_CANLINKBYOLE1 = 0x20,
75 OLEMISC_ISLINKOBJECT = 0x40,
76 OLEMISC_INSIDEOUT = 0x80,
77 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
78 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
79 OLEMISC_INVISIBLEATRUNTIME = 0x400,
80 OLEMISC_ALWAYSRUN = 0x800,
81 OLEMISC_ACTSLIKEBUTTON = 0x1000,
82 OLEMISC_ACTSLIKELABEL = 0x2000,
83 OLEMISC_NOUIACTIVATE = 0x4000,
84 OLEMISC_ALIGNABLE = 0x8000,
85 OLEMISC_SIMPLEFRAME = 0x10000,
86 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
87 OLEMISC_IMEMODE = 0x40000,
88 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
89 OLEMISC_WANTSTOMENUMERGE = 0x100000,
90 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
91 } OLEMISC;
93 #define MAX_NAMESPACES 64
95 typedef struct
97 const WCHAR *ptr;
98 unsigned int len;
99 } xmlstr_t;
101 struct xml_elem
103 xmlstr_t name;
104 xmlstr_t ns;
105 int ns_pos;
108 struct xml_attr
110 xmlstr_t name;
111 xmlstr_t value;
114 typedef struct
116 const WCHAR *ptr;
117 const WCHAR *end;
118 struct xml_attr namespaces[MAX_NAMESPACES];
119 int ns_pos;
120 BOOL error;
121 } xmlbuf_t;
123 struct file_info
125 ULONG type;
126 WCHAR *info;
129 struct assembly_version
131 USHORT major;
132 USHORT minor;
133 USHORT build;
134 USHORT revision;
137 struct assembly_identity
139 WCHAR *name;
140 WCHAR *arch;
141 WCHAR *public_key;
142 WCHAR *language;
143 WCHAR *type;
144 struct assembly_version version;
145 BOOL optional;
146 BOOL delayed;
149 struct strsection_header
151 DWORD magic;
152 ULONG size;
153 DWORD unk1[3];
154 ULONG count;
155 ULONG index_offset;
156 DWORD unk2[2];
157 ULONG global_offset;
158 ULONG global_len;
161 struct string_index
163 ULONG hash; /* key string hash */
164 ULONG name_offset;
165 ULONG name_len;
166 ULONG data_offset; /* redirect data offset */
167 ULONG data_len;
168 ULONG rosterindex;
171 struct guidsection_header
173 DWORD magic;
174 ULONG size;
175 DWORD unk[3];
176 ULONG count;
177 ULONG index_offset;
178 DWORD unk2;
179 ULONG names_offset;
180 ULONG names_len;
183 struct guid_index
185 GUID guid;
186 ULONG data_offset;
187 ULONG data_len;
188 ULONG rosterindex;
191 struct wndclass_redirect_data
193 ULONG size;
194 DWORD res;
195 ULONG name_len;
196 ULONG name_offset; /* versioned name offset */
197 ULONG module_len;
198 ULONG module_offset;/* container name offset */
201 struct tlibredirect_data
203 ULONG size;
204 DWORD res;
205 ULONG name_len;
206 ULONG name_offset;
207 LANGID langid;
208 WORD flags;
209 ULONG help_len;
210 ULONG help_offset;
211 WORD major_version;
212 WORD minor_version;
215 enum comclass_threadingmodel
217 ThreadingModel_Apartment = 1,
218 ThreadingModel_Free = 2,
219 ThreadingModel_No = 3,
220 ThreadingModel_Both = 4,
221 ThreadingModel_Neutral = 5
224 enum comclass_miscfields
226 MiscStatus = 1,
227 MiscStatusIcon = 2,
228 MiscStatusContent = 4,
229 MiscStatusThumbnail = 8,
230 MiscStatusDocPrint = 16
233 struct comclassredirect_data
235 ULONG size;
236 ULONG flags;
237 DWORD model;
238 GUID clsid;
239 GUID alias;
240 GUID clsid2;
241 GUID tlbid;
242 ULONG name_len;
243 ULONG name_offset;
244 ULONG progid_len;
245 ULONG progid_offset;
246 ULONG clrdata_len;
247 ULONG clrdata_offset;
248 DWORD miscstatus;
249 DWORD miscstatuscontent;
250 DWORD miscstatusthumbnail;
251 DWORD miscstatusicon;
252 DWORD miscstatusdocprint;
255 enum ifaceps_mask
257 NumMethods = 1,
258 BaseIface = 2
261 struct ifacepsredirect_data
263 ULONG size;
264 DWORD mask;
265 GUID iid;
266 ULONG nummethods;
267 GUID tlbid;
268 GUID base;
269 ULONG name_len;
270 ULONG name_offset;
273 struct clrsurrogate_data
275 ULONG size;
276 DWORD res;
277 GUID clsid;
278 ULONG version_offset;
279 ULONG version_len;
280 ULONG name_offset;
281 ULONG name_len;
284 struct clrclass_data
286 ULONG size;
287 DWORD res[2];
288 ULONG module_len;
289 ULONG module_offset;
290 ULONG name_len;
291 ULONG name_offset;
292 ULONG version_len;
293 ULONG version_offset;
294 DWORD res2[2];
297 struct progidredirect_data
299 ULONG size;
300 DWORD reserved;
301 ULONG clsid_offset;
304 struct activatable_class_data
306 ULONG size;
307 DWORD unk;
308 DWORD module_len;
309 DWORD module_offset;
310 DWORD threading_model;
315 Sections structure.
317 Sections are accessible by string or guid key, that defines two types of sections.
318 All sections of each type have same magic value and header structure, index
319 data could be of two possible types too. So every string based section uses
320 the same index format, same applies to guid sections - they share same guid index
321 format.
323 - window class redirection section is a plain buffer with following format:
325 <section header>
326 <index[]>
327 <data[]> --- <original name>
328 <redirect data>
329 <versioned name>
330 <module name>
332 Header is fixed length structure - struct strsection_header,
333 contains redirected classes count;
335 Index is an array of fixed length index records, each record is
336 struct string_index.
338 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
340 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
341 others are relative to section itself.
343 - dll redirect section format:
345 <section header>
346 <index[]>
347 <data[]> --- <dll name>
348 <data>
350 This section doesn't seem to carry any payload data except dll names.
352 - typelib section format:
354 <section header>
355 <module names[]>
356 <index[]>
357 <data[]> --- <data>
358 <helpstring>
360 Header is fixed length, index is an array of fixed length 'struct guid_index'.
361 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
362 4-bytes aligned as a whole.
364 Module name offsets are relative to section, helpstring offset is relative to data
365 structure itself.
367 - comclass section format:
369 <section header>
370 <module names[]>
371 <index[]>
372 <data[]> --- <data> --- <data>
373 <progid> <clrdata>
374 <name>
375 <version>
376 <progid>
378 This section uses two index records per comclass, one entry contains original guid
379 as specified by context, another one has a generated guid. Index and strings handling
380 is similar to typelib sections.
382 For CLR classes additional data is stored after main COM class data, it contains
383 class name and runtime version string, see 'struct clrclass_data'.
385 Module name offsets are relative to section, progid offset is relative to data
386 structure itself.
388 - COM interface section format:
390 <section header>
391 <index[]>
392 <data[]> --- <data>
393 <name>
395 Interface section contains data for proxy/stubs and external proxy/stubs. External
396 ones are defined at assembly level, so this section has no module information.
397 All records are indexed with 'iid' value from manifest. There an exception for
398 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
399 redirect data, but index is still 'iid' from manifest.
401 Interface name offset is relative to data structure itself.
403 - CLR surrogates section format:
405 <section header>
406 <index[]>
407 <data[]> --- <data>
408 <name>
409 <version>
411 There's nothing special about this section, same way to store strings is used,
412 no modules part as it belongs to assembly level, not a file.
414 - ProgID section format:
416 <section header>
417 <guids[]>
418 <index[]>
419 <data[]> --- <progid>
420 <data>
422 This sections uses generated alias guids from COM server section. This way
423 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
424 is stored too, aligned.
426 - WinRT activatable class section is a plain buffer with following format:
428 <section header>
429 <module names[]>
430 <index[]>
431 <data[]> --- <class name>
432 <data>
434 Header is fixed length structure - struct strsection_header,
435 contains classes count;
437 Index is an array of fixed length index records, each record is
438 struct string_index.
440 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
442 All offsets are relative to section itself.
446 struct progids
448 WCHAR **progids;
449 unsigned int num;
450 unsigned int allocated;
453 struct entity
455 DWORD kind;
456 union
458 struct
460 WCHAR *tlbid;
461 WCHAR *helpdir;
462 WORD flags;
463 WORD major;
464 WORD minor;
465 } typelib;
466 struct
468 WCHAR *clsid;
469 WCHAR *tlbid;
470 WCHAR *progid;
471 WCHAR *name; /* clrClass: class name */
472 WCHAR *version; /* clrClass: CLR runtime version */
473 DWORD model;
474 DWORD miscstatus;
475 DWORD miscstatuscontent;
476 DWORD miscstatusthumbnail;
477 DWORD miscstatusicon;
478 DWORD miscstatusdocprint;
479 struct progids progids;
480 } comclass;
481 struct {
482 WCHAR *iid;
483 WCHAR *base;
484 WCHAR *tlib;
485 WCHAR *name;
486 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
487 DWORD mask;
488 ULONG nummethods;
489 } ifaceps;
490 struct
492 WCHAR *name;
493 BOOL versioned;
494 } class;
495 struct
497 WCHAR *name;
498 WCHAR *clsid;
499 WCHAR *version;
500 } clrsurrogate;
501 struct
503 WCHAR *name;
504 WCHAR *value;
505 WCHAR *ns;
506 } settings;
507 struct
509 WCHAR *name;
510 DWORD threading_model;
511 } activatable_class;
512 } u;
515 struct entity_array
517 struct entity *base;
518 unsigned int num;
519 unsigned int allocated;
522 struct dll_redirect
524 WCHAR *name;
525 WCHAR *load_from;
526 WCHAR *hash;
527 struct entity_array entities;
530 enum assembly_type
532 APPLICATION_MANIFEST,
533 ASSEMBLY_MANIFEST,
534 ASSEMBLY_SHARED_MANIFEST,
537 struct assembly
539 enum assembly_type type;
540 struct assembly_identity id;
541 struct file_info manifest;
542 WCHAR *directory;
543 BOOL no_inherit;
544 struct dll_redirect *dlls;
545 unsigned int num_dlls;
546 unsigned int allocated_dlls;
547 struct entity_array entities;
548 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
549 ULONG num_compat_contexts;
550 ACTCTX_REQUESTED_RUN_LEVEL run_level;
551 ULONG ui_access;
554 enum context_sections
556 WINDOWCLASS_SECTION = 1,
557 DLLREDIRECT_SECTION = 2,
558 TLIBREDIRECT_SECTION = 4,
559 SERVERREDIRECT_SECTION = 8,
560 IFACEREDIRECT_SECTION = 16,
561 CLRSURROGATES_SECTION = 32,
562 PROGIDREDIRECT_SECTION = 64,
563 ACTIVATABLE_CLASS_SECTION = 128,
566 typedef struct _ACTIVATION_CONTEXT
568 ULONG magic;
569 LONG ref_count;
570 struct file_info config;
571 struct file_info appdir;
572 struct assembly *assemblies;
573 unsigned int num_assemblies;
574 unsigned int allocated_assemblies;
575 /* section data */
576 DWORD sections;
577 struct strsection_header *wndclass_section;
578 struct strsection_header *dllredirect_section;
579 struct strsection_header *progid_section;
580 struct strsection_header *activatable_class_section;
581 struct guidsection_header *tlib_section;
582 struct guidsection_header *comserver_section;
583 struct guidsection_header *ifaceps_section;
584 struct guidsection_header *clrsurrogate_section;
585 } ACTIVATION_CONTEXT;
587 struct actctx_loader
589 ACTIVATION_CONTEXT *actctx;
590 struct assembly_identity *dependencies;
591 unsigned int num_dependencies;
592 unsigned int allocated_dependencies;
595 static const xmlstr_t empty_xmlstr;
597 #ifdef __i386__
598 static const WCHAR current_archW[] = L"x86";
599 #elif defined __x86_64__
600 static const WCHAR current_archW[] = L"amd64";
601 #elif defined __arm__
602 static const WCHAR current_archW[] = L"arm";
603 #elif defined __aarch64__
604 static const WCHAR current_archW[] = L"arm64";
605 #else
606 static const WCHAR current_archW[] = L"none";
607 #endif
609 static const WCHAR asmv1W[] = L"urn:schemas-microsoft-com:asm.v1";
610 static const WCHAR asmv2W[] = L"urn:schemas-microsoft-com:asm.v2";
611 static const WCHAR asmv3W[] = L"urn:schemas-microsoft-com:asm.v3";
612 static const WCHAR winrtv1W[] = L"urn:schemas-microsoft-com:winrt.v1";
613 static const WCHAR compatibilityNSW[] = L"urn:schemas-microsoft-com:compatibility.v1";
614 static const WCHAR windowsSettings2005NSW[] = L"http://schemas.microsoft.com/SMI/2005/WindowsSettings";
615 static const WCHAR windowsSettings2011NSW[] = L"http://schemas.microsoft.com/SMI/2011/WindowsSettings";
616 static const WCHAR windowsSettings2016NSW[] = L"http://schemas.microsoft.com/SMI/2016/WindowsSettings";
617 static const WCHAR windowsSettings2017NSW[] = L"http://schemas.microsoft.com/SMI/2017/WindowsSettings";
618 static const WCHAR windowsSettings2019NSW[] = L"http://schemas.microsoft.com/SMI/2019/WindowsSettings";
619 static const WCHAR windowsSettings2020NSW[] = L"http://schemas.microsoft.com/SMI/2020/WindowsSettings";
621 struct olemisc_entry
623 const WCHAR *name;
624 OLEMISC value;
627 static const struct olemisc_entry olemisc_values[] =
629 { L"activatewhenvisible", OLEMISC_ACTIVATEWHENVISIBLE },
630 { L"actslikebutton", OLEMISC_ACTSLIKEBUTTON },
631 { L"actslikelabel", OLEMISC_ACTSLIKELABEL },
632 { L"alignable", OLEMISC_ALIGNABLE },
633 { L"alwaysrun", OLEMISC_ALWAYSRUN },
634 { L"canlinkbyole1", OLEMISC_CANLINKBYOLE1 },
635 { L"cantlinkinside", OLEMISC_CANTLINKINSIDE },
636 { L"ignoreactivatewhenvisible", OLEMISC_IGNOREACTIVATEWHENVISIBLE },
637 { L"imemode", OLEMISC_IMEMODE },
638 { L"insertnotreplace", OLEMISC_INSERTNOTREPLACE },
639 { L"insideout", OLEMISC_INSIDEOUT },
640 { L"invisibleatruntime", OLEMISC_INVISIBLEATRUNTIME },
641 { L"islinkobject", OLEMISC_ISLINKOBJECT },
642 { L"nouiactivate", OLEMISC_NOUIACTIVATE },
643 { L"onlyiconic", OLEMISC_ONLYICONIC },
644 { L"recomposeonresize", OLEMISC_RECOMPOSEONRESIZE },
645 { L"renderingisdeviceindependent", OLEMISC_RENDERINGISDEVICEINDEPENDENT },
646 { L"setclientsitefirst", OLEMISC_SETCLIENTSITEFIRST },
647 { L"simpleframe", OLEMISC_SIMPLEFRAME },
648 { L"static", OLEMISC_STATIC },
649 { L"supportsmultilevelundo", OLEMISC_SUPPORTSMULTILEVELUNDO },
650 { L"wantstomenumerge", OLEMISC_WANTSTOMENUMERGE }
653 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
654 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
656 static WCHAR *strdupW(const WCHAR* str)
658 WCHAR* ptr;
660 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR))))
661 return NULL;
662 return wcscpy(ptr, str);
665 static WCHAR *xmlstrdupW(const xmlstr_t* str)
667 WCHAR *strW;
669 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
671 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
672 strW[str->len] = 0;
674 return strW;
677 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
679 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
682 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
684 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
687 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
689 return xmlstr_cmp( &attr->name, str );
692 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
694 return (elem1->name.len == elem2->name.len &&
695 elem1->ns.len == elem2->ns.len &&
696 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
697 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
700 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
702 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
703 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
704 if (!wcscmp( namespace, asmv1W ))
706 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
707 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
709 else if (!wcscmp( namespace, asmv2W ))
711 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
713 return FALSE;
716 static inline BOOL isxmlspace( WCHAR ch )
718 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
721 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
723 return debugstr_wn(str->ptr, str->len);
726 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
728 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
729 debugstr_wn( elem->ns.ptr, elem->ns.len ));
732 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
734 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
735 debugstr_wn( attr->value.ptr, attr->value.len ));
738 static inline const char* debugstr_version(const struct assembly_version *ver)
740 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
743 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
745 NTSTATUS status;
746 ULONG_PTR magic;
747 LDR_DATA_TABLE_ENTRY *pldr;
749 LdrLockLoaderLock(0, NULL, &magic);
750 status = LdrFindEntryForAddress( module, &pldr );
751 if (status == STATUS_SUCCESS)
753 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
754 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
756 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
757 str->Length = pldr->FullDllName.Length;
758 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
760 else status = STATUS_NO_MEMORY;
762 LdrUnlockLoaderLock(0, magic);
763 return status;
766 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
768 struct assembly *assembly;
770 if (actctx->num_assemblies == actctx->allocated_assemblies)
772 void *ptr;
773 unsigned int new_count;
774 if (actctx->assemblies)
776 new_count = actctx->allocated_assemblies * 2;
777 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
778 actctx->assemblies, new_count * sizeof(*assembly) );
780 else
782 new_count = 4;
783 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
785 if (!ptr) return NULL;
786 actctx->assemblies = ptr;
787 actctx->allocated_assemblies = new_count;
790 assembly = &actctx->assemblies[actctx->num_assemblies++];
791 assembly->type = at;
792 return assembly;
795 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
797 if (assembly->num_dlls == assembly->allocated_dlls)
799 void *ptr;
800 unsigned int new_count;
801 if (assembly->dlls)
803 new_count = assembly->allocated_dlls * 2;
804 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
805 assembly->dlls, new_count * sizeof(*assembly->dlls) );
807 else
809 new_count = 4;
810 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
812 if (!ptr) return NULL;
813 assembly->dlls = ptr;
814 assembly->allocated_dlls = new_count;
816 return &assembly->dlls[assembly->num_dlls++];
819 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
821 void *ptr;
822 if (assembly->num_compat_contexts)
824 unsigned int new_count = assembly->num_compat_contexts + 1;
825 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
826 assembly->compat_contexts,
827 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
829 else
831 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
833 if (!ptr) return NULL;
834 assembly->compat_contexts = ptr;
835 return &assembly->compat_contexts[assembly->num_compat_contexts++];
838 static void free_assembly_identity(struct assembly_identity *ai)
840 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
841 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
842 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
843 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
844 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
847 static struct entity* add_entity(struct entity_array *array, DWORD kind)
849 struct entity* entity;
851 if (array->num == array->allocated)
853 void *ptr;
854 unsigned int new_count;
855 if (array->base)
857 new_count = array->allocated * 2;
858 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
859 array->base, new_count * sizeof(*array->base) );
861 else
863 new_count = 4;
864 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
866 if (!ptr) return NULL;
867 array->base = ptr;
868 array->allocated = new_count;
870 entity = &array->base[array->num++];
871 entity->kind = kind;
872 return entity;
875 static void free_entity_array(struct entity_array *array)
877 unsigned int i, j;
878 for (i = 0; i < array->num; i++)
880 struct entity *entity = &array->base[i];
881 switch (entity->kind)
883 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
884 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
885 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
886 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
887 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
888 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
889 for (j = 0; j < entity->u.comclass.progids.num; j++)
890 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
891 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
892 break;
893 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
894 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
895 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
896 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
897 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
898 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
899 break;
900 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
901 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
902 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
903 break;
904 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
905 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
906 break;
907 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
908 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
909 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
910 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
911 break;
912 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
913 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
914 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
915 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
916 break;
917 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES:
918 RtlFreeHeap(GetProcessHeap(), 0, entity->u.activatable_class.name);
919 break;
920 default:
921 FIXME("Unknown entity kind %ld\n", entity->kind);
924 RtlFreeHeap( GetProcessHeap(), 0, array->base );
927 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
929 if (!str1) return !str2;
930 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE );
933 static BOOL is_matching_identity( const struct assembly_identity *id1,
934 const struct assembly_identity *id2 )
936 if (!is_matching_string( id1->name, id2->name )) return FALSE;
937 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
938 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
940 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language ))
942 if (wcscmp( L"*", id1->language ) && wcscmp( L"*", id2->language ))
943 return FALSE;
945 if (id1->version.major != id2->version.major) return FALSE;
946 if (id1->version.minor != id2->version.minor) return FALSE;
947 if (id1->version.build > id2->version.build) return FALSE;
948 if (id1->version.build == id2->version.build &&
949 id1->version.revision > id2->version.revision) return FALSE;
950 return TRUE;
953 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
954 struct assembly_identity* ai)
956 unsigned int i;
958 /* check if we already have that assembly */
960 for (i = 0; i < acl->actctx->num_assemblies; i++)
961 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
963 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
964 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
965 ai->version.build, ai->version.revision );
966 return TRUE;
969 for (i = 0; i < acl->num_dependencies; i++)
970 if (is_matching_identity( ai, &acl->dependencies[i] ))
972 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
973 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
974 ai->version.build, ai->version.revision );
975 return TRUE;
978 if (acl->num_dependencies == acl->allocated_dependencies)
980 void *ptr;
981 unsigned int new_count;
982 if (acl->dependencies)
984 new_count = acl->allocated_dependencies * 2;
985 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
986 new_count * sizeof(acl->dependencies[0]));
988 else
990 new_count = 4;
991 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
993 if (!ptr) return FALSE;
994 acl->dependencies = ptr;
995 acl->allocated_dependencies = new_count;
997 acl->dependencies[acl->num_dependencies++] = *ai;
999 return TRUE;
1002 static void free_depend_manifests(struct actctx_loader* acl)
1004 unsigned int i;
1005 for (i = 0; i < acl->num_dependencies; i++)
1006 free_assembly_identity(&acl->dependencies[i]);
1007 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1010 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1012 static const WCHAR mskeyW[] = L"deadbeef";
1013 const WCHAR *arch = ai->arch ? ai->arch : L"none";
1014 const WCHAR *key = ai->public_key ? ai->public_key : L"none";
1015 const WCHAR *lang = ai->language ? ai->language : L"none";
1016 const WCHAR *name = ai->name ? ai->name : L"none";
1017 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 +
1018 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1019 WCHAR *ret;
1021 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1023 wcscpy( ret, arch );
1024 wcscat( ret, L"_" );
1025 wcscat( ret, name );
1026 wcscat( ret, L"_" );
1027 wcscat( ret, key );
1028 wcscat( ret, L"_" );
1029 swprintf( ret + wcslen(ret), size - wcslen(ret), L"%u.%u.%u.%u",
1030 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1031 wcscat( ret, L"_" );
1032 wcscat( ret, lang );
1033 wcscat( ret, L"_" );
1034 wcscat( ret, mskeyW );
1035 return ret;
1038 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1040 WCHAR *p = buffer;
1042 if (!str) return;
1043 wcscat( buffer, prefix );
1044 p += wcslen(p);
1045 *p++ = '"';
1046 wcscpy( p, str );
1047 p += wcslen(p);
1048 *p++ = '"';
1049 *p = 0;
1052 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1054 WCHAR version[64], *ret;
1055 SIZE_T size = 0;
1057 swprintf( version, ARRAY_SIZE(version), L"%u.%u.%u.%u",
1058 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1059 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR);
1060 if (ai->arch) size += wcslen(L",processorArchitecture=") + wcslen(ai->arch) + 2;
1061 if (ai->public_key) size += wcslen(L",publicKeyToken=") + wcslen(ai->public_key) + 2;
1062 if (ai->type) size += wcslen(L",type=") + wcslen(ai->type) + 2;
1063 size += wcslen(L",version=") + wcslen(version) + 2;
1065 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1066 return NULL;
1068 if (ai->name) wcscpy( ret, ai->name );
1069 else *ret = 0;
1070 append_string( ret, L",processorArchitecture=", ai->arch );
1071 append_string( ret, L",publicKeyToken=", ai->public_key );
1072 append_string( ret, L",type=", ai->type );
1073 append_string( ret, L",version=", version );
1074 return ret;
1077 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1079 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1081 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1082 __TRY
1084 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1086 __EXCEPT_PAGE_FAULT
1089 __ENDTRY
1090 return ret;
1093 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1095 InterlockedIncrement( &actctx->ref_count );
1098 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1100 if (!InterlockedDecrement( &actctx->ref_count ))
1102 unsigned int i, j;
1104 for (i = 0; i < actctx->num_assemblies; i++)
1106 struct assembly *assembly = &actctx->assemblies[i];
1107 for (j = 0; j < assembly->num_dlls; j++)
1109 struct dll_redirect *dll = &assembly->dlls[j];
1110 free_entity_array( &dll->entities );
1111 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1112 RtlFreeHeap( GetProcessHeap(), 0, dll->load_from );
1113 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1115 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1116 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1117 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1118 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1119 free_entity_array( &assembly->entities );
1120 free_assembly_identity(&assembly->id);
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1125 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1127 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1128 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1129 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1130 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1131 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1132 RtlFreeHeap( GetProcessHeap(), 0, actctx->activatable_class_section );
1133 actctx->magic = 0;
1134 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1138 static BOOL set_error( xmlbuf_t *xmlbuf )
1140 xmlbuf->error = TRUE;
1141 return FALSE;
1144 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1146 const int len = wcslen( L"xmlns" );
1147 if (attr->name.len < len) return FALSE;
1148 if (wcsncmp( attr->name.ptr, L"xmlns", len )) return FALSE;
1149 return (attr->name.len == len || attr->name.ptr[len] == ':');
1152 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1154 const int len = wcslen( L"xmlns" );
1155 struct xml_attr *ns;
1157 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1159 FIXME( "too many namespaces in manifest\n" );
1160 set_error( xmlbuf );
1161 return;
1163 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1164 ns->value = attr->value;
1165 if (attr->name.len > len)
1167 ns->name.ptr = attr->name.ptr + len + 1;
1168 ns->name.len = attr->name.len - len - 1;
1170 else ns->name = empty_xmlstr;
1173 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1175 int i;
1177 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1179 if (xmlbuf->namespaces[i].name.len == name->len &&
1180 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1181 return xmlbuf->namespaces[i].value;
1183 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1184 return empty_xmlstr;
1187 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1189 const WCHAR* ptr;
1190 WCHAR quote;
1192 if (xmlbuf->error) return FALSE;
1194 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1195 xmlbuf->ptr++;
1197 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1199 if (*xmlbuf->ptr == '/')
1201 xmlbuf->ptr++;
1202 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1203 return set_error( xmlbuf );
1205 xmlbuf->ptr++;
1206 *end = TRUE;
1207 return FALSE;
1210 if (*xmlbuf->ptr == '>')
1212 xmlbuf->ptr++;
1213 return FALSE;
1216 ptr = xmlbuf->ptr;
1217 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1219 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1221 attr->name.ptr = xmlbuf->ptr;
1222 attr->name.len = ptr-xmlbuf->ptr;
1223 xmlbuf->ptr = ptr;
1225 /* skip spaces before '=' */
1226 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1227 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1229 /* skip '=' itself */
1230 ptr++;
1231 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1233 /* skip spaces after '=' */
1234 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1236 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1238 quote = *ptr++;
1239 attr->value.ptr = ptr;
1240 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1242 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1243 if (ptr == xmlbuf->end)
1245 xmlbuf->ptr = xmlbuf->end;
1246 return set_error( xmlbuf );
1249 attr->value.len = ptr - attr->value.ptr;
1250 xmlbuf->ptr = ptr + 1;
1251 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1253 return set_error( xmlbuf );
1256 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1258 const WCHAR* ptr = xmlbuf->ptr;
1260 elem->ns = empty_xmlstr;
1261 elem->name.ptr = ptr;
1262 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1264 if (*ptr == ':')
1266 elem->ns.ptr = elem->name.ptr;
1267 elem->ns.len = ptr - elem->ns.ptr;
1268 elem->name.ptr = ptr + 1;
1270 ptr++;
1272 elem->name.len = ptr - elem->name.ptr;
1273 xmlbuf->ptr = ptr;
1276 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1278 const WCHAR* ptr;
1279 struct xml_attr attr;
1280 xmlbuf_t attr_buf;
1281 BOOL end = FALSE;
1283 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1285 if (xmlbuf->error) return FALSE;
1287 for (;;)
1289 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1290 if (ptr == xmlbuf->end)
1292 xmlbuf->ptr = xmlbuf->end;
1293 return set_error( xmlbuf );
1295 ptr++;
1296 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1298 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1299 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1301 if (ptr + 3 > xmlbuf->end)
1303 xmlbuf->ptr = xmlbuf->end;
1304 return set_error( xmlbuf );
1306 xmlbuf->ptr = ptr + 3;
1308 else break;
1311 xmlbuf->ptr = ptr;
1312 /* check for element terminating the parent element */
1313 if (ptr < xmlbuf->end && *ptr == '/')
1315 xmlbuf->ptr++;
1316 read_xml_elem( xmlbuf, elem );
1317 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1318 if (!xml_name_cmp( elem, parent ))
1320 ERR( "wrong closing element %s for %s\n",
1321 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1322 return set_error( xmlbuf );
1324 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1325 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1326 return FALSE;
1329 read_xml_elem( xmlbuf, elem );
1331 /* parse namespace attributes */
1332 attr_buf = *xmlbuf;
1333 while (next_xml_attr( &attr_buf, &attr, &end ))
1335 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1337 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1338 elem->ns_pos = xmlbuf->ns_pos;
1340 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1342 return set_error( xmlbuf );
1345 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1347 /* FIXME: parse attributes */
1348 const WCHAR *ptr;
1350 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1352 if (ptr[0] == '?' && ptr[1] == '>')
1354 xmlbuf->ptr = ptr + 2;
1355 return TRUE;
1358 return FALSE;
1361 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1363 const WCHAR *ptr;
1365 if (xmlbuf->error) return FALSE;
1367 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1368 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1370 content->ptr = xmlbuf->ptr;
1371 content->len = ptr - xmlbuf->ptr;
1372 xmlbuf->ptr = ptr;
1374 return TRUE;
1377 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1379 unsigned int ver[4];
1380 unsigned int pos;
1381 const WCHAR *curr;
1383 /* major.minor.build.revision */
1384 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1385 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1387 if (*curr >= '0' && *curr <= '9')
1389 ver[pos] = ver[pos] * 10 + *curr - '0';
1390 if (ver[pos] >= 0x10000) goto error;
1392 else if (*curr == '.')
1394 if (++pos >= 4) goto error;
1396 else goto error;
1398 version->major = ver[0];
1399 version->minor = ver[1];
1400 version->build = ver[2];
1401 version->revision = ver[3];
1402 return TRUE;
1404 error:
1405 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1406 return FALSE;
1409 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1411 struct xml_attr attr;
1413 while (next_xml_attr(xmlbuf, &attr, end))
1415 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1419 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1421 struct xml_elem elem;
1423 if (next_xml_elem(xmlbuf, &elem, parent))
1425 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1426 set_error( xmlbuf );
1430 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1432 struct xml_elem elem;
1433 struct xml_attr attr;
1434 BOOL end = FALSE;
1436 while (next_xml_attr(xmlbuf, &attr, &end));
1437 if (end) return;
1439 while (next_xml_elem(xmlbuf, &elem, parent))
1440 parse_unknown_elem(xmlbuf, &elem);
1443 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1444 struct assembly_identity* ai, const struct xml_elem *parent)
1446 struct xml_attr attr;
1447 BOOL end = FALSE;
1449 while (next_xml_attr(xmlbuf, &attr, &end))
1451 if (xml_attr_cmp(&attr, L"name"))
1453 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1455 else if (xml_attr_cmp(&attr, L"type"))
1457 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1459 else if (xml_attr_cmp(&attr, L"version"))
1461 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1463 else if (xml_attr_cmp(&attr, L"processorArchitecture"))
1465 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1467 else if (xml_attr_cmp(&attr, L"publicKeyToken"))
1469 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1471 else if (xml_attr_cmp(&attr, L"language"))
1473 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1475 else if (!is_xmlns_attr( &attr ))
1477 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1481 TRACE( "name=%s version=%s arch=%s\n",
1482 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1484 if (!end) parse_expect_end_elem(xmlbuf, parent);
1487 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1489 if (value->len == 0) return ThreadingModel_No;
1490 if (xmlstr_cmp(value, L"Apartment"))
1491 return ThreadingModel_Apartment;
1492 else if (xmlstr_cmp(value, L"Free"))
1493 return ThreadingModel_Free;
1494 else if (xmlstr_cmp(value, L"Both"))
1495 return ThreadingModel_Both;
1496 else if (xmlstr_cmp(value, L"Neutral"))
1497 return ThreadingModel_Neutral;
1498 else
1499 return ThreadingModel_No;
1502 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1504 int min, max;
1506 min = 0;
1507 max = ARRAY_SIZE(olemisc_values) - 1;
1509 while (min <= max)
1511 int n, c;
1513 n = (min+max)/2;
1515 c = wcsncmp(olemisc_values[n].name, str, len);
1516 if (!c && !olemisc_values[n].name[len])
1517 return olemisc_values[n].value;
1519 if (c >= 0)
1520 max = n-1;
1521 else
1522 min = n+1;
1525 WARN("unknown flag %s\n", debugstr_wn(str, len));
1526 return 0;
1529 static DWORD parse_com_class_misc(const xmlstr_t *value)
1531 const WCHAR *str = value->ptr, *start;
1532 DWORD flags = 0;
1533 int i = 0;
1535 /* it's comma separated list of flags */
1536 while (i < value->len)
1538 start = str;
1539 while (*str != ',' && (i++ < value->len)) str++;
1541 flags |= get_olemisc_value(start, str-start);
1543 /* skip separator */
1544 str++;
1545 i++;
1548 return flags;
1551 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1553 struct progids *progids = &entity->u.comclass.progids;
1555 if (progids->allocated == 0)
1557 progids->allocated = 4;
1558 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1561 if (progids->allocated == progids->num)
1563 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1564 2 * progids->allocated * sizeof(WCHAR*));
1565 if (!new_progids) return FALSE;
1566 progids->allocated *= 2;
1567 progids->progids = new_progids;
1570 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1571 progids->num++;
1573 return TRUE;
1576 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1578 xmlstr_t content;
1579 BOOL end = FALSE;
1581 parse_expect_no_attr(xmlbuf, &end);
1582 if (end) set_error( xmlbuf );
1583 if (!parse_text_content(xmlbuf, &content)) return;
1585 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1586 parse_expect_end_elem(xmlbuf, parent);
1589 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1590 const struct xml_elem *parent )
1592 struct xml_elem elem;
1593 struct xml_attr attr;
1594 BOOL end = FALSE;
1595 struct entity* entity;
1597 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1599 set_error( xmlbuf );
1600 return;
1603 while (next_xml_attr(xmlbuf, &attr, &end))
1605 if (xml_attr_cmp(&attr, L"clsid"))
1607 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1609 else if (xml_attr_cmp(&attr, L"progid"))
1611 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1613 else if (xml_attr_cmp(&attr, L"tlbid"))
1615 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1617 else if (xml_attr_cmp(&attr, L"threadingModel"))
1619 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1621 else if (xml_attr_cmp(&attr, L"miscStatus"))
1623 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1625 else if (xml_attr_cmp(&attr, L"miscStatusContent"))
1627 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1629 else if (xml_attr_cmp(&attr, L"miscStatusThumbnail"))
1631 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1633 else if (xml_attr_cmp(&attr, L"miscStatusIcon"))
1635 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1637 else if (xml_attr_cmp(&attr, L"miscStatusDocPrint"))
1639 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1641 else if (xml_attr_cmp(&attr, L"description"))
1643 /* not stored */
1645 else if (!is_xmlns_attr( &attr ))
1647 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1651 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1652 if (entity->u.comclass.progid)
1653 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1655 if (end) return;
1657 while (next_xml_elem(xmlbuf, &elem, parent))
1659 if (xml_elem_cmp(&elem, L"progid", asmv1W))
1661 parse_com_class_progid(xmlbuf, entity, &elem);
1663 else
1665 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1666 parse_unknown_elem(xmlbuf, &elem);
1670 if (entity->u.comclass.progids.num)
1671 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1674 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1676 const WCHAR *curr;
1677 ULONG num = 0;
1679 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1681 if (*curr >= '0' && *curr <= '9')
1682 num = num * 10 + *curr - '0';
1683 else
1685 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1686 return FALSE;
1689 entity->u.ifaceps.nummethods = num;
1691 return TRUE;
1694 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1695 struct actctx_loader *acl, WCHAR *clsid )
1697 struct entity *entity;
1698 WCHAR *str;
1700 if (!clsid) return;
1702 if (!(str = strdupW(clsid)))
1704 set_error( xmlbuf );
1705 return;
1708 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1710 RtlFreeHeap(GetProcessHeap(), 0, str);
1711 set_error( xmlbuf );
1712 return;
1715 entity->u.comclass.clsid = str;
1716 entity->u.comclass.model = ThreadingModel_Both;
1718 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1721 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1722 struct actctx_loader *acl, const struct xml_elem *parent )
1724 WCHAR *psclsid = NULL;
1725 struct entity *entity;
1726 struct xml_attr attr;
1727 BOOL end = FALSE;
1729 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1731 set_error( xmlbuf );
1732 return;
1735 while (next_xml_attr(xmlbuf, &attr, &end))
1737 if (xml_attr_cmp(&attr, L"iid"))
1739 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1741 else if (xml_attr_cmp(&attr, L"name"))
1743 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1745 else if (xml_attr_cmp(&attr, L"baseInterface"))
1747 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1748 entity->u.ifaceps.mask |= BaseIface;
1750 else if (xml_attr_cmp(&attr, L"numMethods"))
1752 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1753 entity->u.ifaceps.mask |= NumMethods;
1755 else if (xml_attr_cmp(&attr, L"tlbid"))
1757 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1759 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
1761 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1763 /* not used */
1764 else if (xml_attr_cmp(&attr, L"threadingModel"))
1767 else if (!is_xmlns_attr( &attr ))
1769 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1773 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1774 if (!end) parse_expect_end_elem(xmlbuf, parent);
1776 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1778 RtlFreeHeap(GetProcessHeap(), 0, psclsid);
1781 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1783 WORD *flags = &entity->u.typelib.flags;
1784 const WCHAR *str = value->ptr, *start;
1785 int i = 0;
1787 *flags = 0;
1789 /* it's comma separated list of flags */
1790 while (i < value->len)
1792 start = str;
1793 while (*str != ',' && (i++ < value->len)) str++;
1795 if (!wcsnicmp(start, L"RESTRICTED", str-start))
1796 *flags |= LIBFLAG_FRESTRICTED;
1797 else if (!wcsnicmp(start, L"CONTROL", str-start))
1798 *flags |= LIBFLAG_FCONTROL;
1799 else if (!wcsnicmp(start, L"HIDDEN", str-start))
1800 *flags |= LIBFLAG_FHIDDEN;
1801 else if (!wcsnicmp(start, L"HASDISKIMAGE", str-start))
1802 *flags |= LIBFLAG_FHASDISKIMAGE;
1803 else
1805 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1806 return FALSE;
1809 /* skip separator */
1810 str++;
1811 i++;
1814 return TRUE;
1817 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1819 unsigned int ver[2];
1820 unsigned int pos;
1821 const WCHAR *curr;
1823 /* major.minor */
1824 ver[0] = ver[1] = pos = 0;
1825 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1827 if (*curr >= '0' && *curr <= '9')
1829 ver[pos] = ver[pos] * 10 + *curr - '0';
1830 if (ver[pos] >= 0x10000) goto error;
1832 else if (*curr == '.')
1834 if (++pos >= 2) goto error;
1836 else goto error;
1838 entity->u.typelib.major = ver[0];
1839 entity->u.typelib.minor = ver[1];
1840 return TRUE;
1842 error:
1843 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1844 return FALSE;
1847 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1848 struct actctx_loader *acl, const struct xml_elem *parent )
1850 struct xml_attr attr;
1851 BOOL end = FALSE;
1852 struct entity* entity;
1854 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1856 set_error( xmlbuf );
1857 return;
1860 while (next_xml_attr(xmlbuf, &attr, &end))
1862 if (xml_attr_cmp(&attr, L"tlbid"))
1864 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1866 else if (xml_attr_cmp(&attr, L"version"))
1868 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1870 else if (xml_attr_cmp(&attr, L"helpdir"))
1872 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1874 else if (xml_attr_cmp(&attr, L"flags"))
1876 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1878 else if (!is_xmlns_attr( &attr ))
1880 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1884 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1885 if (!end) parse_expect_end_elem(xmlbuf, parent);
1888 static inline int aligned_string_len(int len)
1890 return (len + 3) & ~3;
1893 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1895 struct assembly_version *ver = &assembly->id.version;
1896 WCHAR buff[25];
1898 if (!ret) ret = buff;
1899 return swprintf(ret, ARRAY_SIZE(buff), L"%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
1902 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1903 struct actctx_loader *acl, const struct xml_elem *parent )
1905 struct xml_elem elem;
1906 struct xml_attr attr;
1907 xmlstr_t content;
1908 BOOL end = FALSE;
1909 struct entity* entity;
1911 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1913 set_error( xmlbuf );
1914 return;
1916 entity->u.class.versioned = TRUE;
1917 while (next_xml_attr(xmlbuf, &attr, &end))
1919 if (xml_attr_cmp(&attr, L"versioned"))
1921 if (xmlstr_cmpi(&attr.value, L"no"))
1922 entity->u.class.versioned = FALSE;
1923 else if (!xmlstr_cmpi(&attr.value, L"yes"))
1924 set_error( xmlbuf );
1926 else if (!is_xmlns_attr( &attr ))
1928 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1932 if (end) return;
1934 if (!parse_text_content(xmlbuf, &content)) return;
1935 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1937 acl->actctx->sections |= WINDOWCLASS_SECTION;
1939 while (next_xml_elem(xmlbuf, &elem, parent))
1941 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1942 parse_unknown_elem(xmlbuf, &elem);
1946 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1948 struct xml_attr attr;
1949 BOOL end = FALSE;
1951 while (next_xml_attr(xmlbuf, &attr, &end))
1953 if (xml_attr_cmp(&attr, L"oldVersion"))
1955 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1957 else if (xml_attr_cmp(&attr, L"newVersion"))
1959 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1961 else if (!is_xmlns_attr( &attr ))
1963 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1967 if (!end) parse_expect_end_elem(xmlbuf, parent);
1970 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1972 struct xml_elem elem;
1973 struct xml_attr attr;
1974 xmlstr_t content;
1975 BOOL end = FALSE;
1977 while (next_xml_attr(xmlbuf, &attr, &end))
1979 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1982 if (end) return;
1983 if (!parse_text_content(xmlbuf, &content)) return;
1985 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1987 while (next_xml_elem(xmlbuf, &elem, parent))
1989 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1990 parse_unknown_elem(xmlbuf, &elem);
1994 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
1995 struct assembly* assembly,
1996 struct actctx_loader* acl,
1997 const struct xml_elem *parent)
1999 struct xml_attr attr;
2000 BOOL end = FALSE;
2001 struct entity* entity;
2003 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2005 set_error( xmlbuf );
2006 return;
2009 while (next_xml_attr(xmlbuf, &attr, &end))
2011 if (xml_attr_cmp(&attr, L"iid"))
2013 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2015 else if (xml_attr_cmp(&attr, L"name"))
2017 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2019 else if (xml_attr_cmp(&attr, L"baseInterface"))
2021 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2022 entity->u.ifaceps.mask |= BaseIface;
2024 else if (xml_attr_cmp(&attr, L"numMethods"))
2026 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2027 entity->u.ifaceps.mask |= NumMethods;
2029 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
2031 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2033 else if (xml_attr_cmp(&attr, L"tlbid"))
2035 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2037 else if (!is_xmlns_attr( &attr ))
2039 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2043 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2044 if (!end) parse_expect_end_elem(xmlbuf, parent);
2047 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2048 struct actctx_loader *acl, const struct xml_elem *parent )
2051 struct xml_elem elem;
2052 struct xml_attr attr;
2053 BOOL end = FALSE;
2054 struct entity* entity;
2056 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2058 set_error( xmlbuf );
2059 return;
2062 while (next_xml_attr(xmlbuf, &attr, &end))
2064 if (xml_attr_cmp(&attr, L"name"))
2066 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2068 else if (xml_attr_cmp(&attr, L"clsid"))
2070 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2072 else if (xml_attr_cmp(&attr, L"progid"))
2074 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2076 else if (xml_attr_cmp(&attr, L"tlbid"))
2078 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2080 else if (xml_attr_cmp(&attr, L"threadingModel"))
2082 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2084 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2086 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2088 else if (!is_xmlns_attr( &attr ))
2090 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2094 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2095 if (entity->u.comclass.progid)
2096 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2097 if (end) return;
2099 while (next_xml_elem(xmlbuf, &elem, parent))
2101 if (xml_elem_cmp(&elem, L"progid", asmv1W))
2103 parse_com_class_progid(xmlbuf, entity, &elem);
2105 else
2107 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2108 parse_unknown_elem(xmlbuf, &elem);
2112 if (entity->u.comclass.progids.num)
2113 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2116 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2117 struct actctx_loader *acl, const struct xml_elem *parent )
2119 struct xml_attr attr;
2120 BOOL end = FALSE;
2121 struct entity* entity;
2123 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2125 set_error( xmlbuf );
2126 return;
2129 while (next_xml_attr(xmlbuf, &attr, &end))
2131 if (xml_attr_cmp(&attr, L"name"))
2133 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2135 else if (xml_attr_cmp(&attr, L"clsid"))
2137 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2139 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2141 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2143 else if (!is_xmlns_attr( &attr ))
2145 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2149 acl->actctx->sections |= CLRSURROGATES_SECTION;
2150 if (!end) parse_expect_end_elem(xmlbuf, parent);
2153 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2154 const struct xml_elem *parent, BOOL optional )
2156 struct xml_elem elem;
2157 struct xml_attr attr;
2158 struct assembly_identity ai;
2159 BOOL end = FALSE;
2161 memset(&ai, 0, sizeof(ai));
2162 ai.optional = optional;
2164 while (next_xml_attr(xmlbuf, &attr, &end))
2166 if (xml_attr_cmp(&attr, L"allowDelayedBinding"))
2167 ai.delayed = xmlstr_cmp(&attr.value, L"true");
2168 else if (!is_xmlns_attr( &attr ))
2169 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2172 if (end) return;
2174 while (next_xml_elem(xmlbuf, &elem, parent))
2176 if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2178 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2179 /* store the newly found identity for later loading */
2180 if (ai.arch && !wcscmp(ai.arch, L"*"))
2182 RtlFreeHeap( GetProcessHeap(), 0, ai.arch );
2183 ai.arch = strdupW( current_archW );
2185 TRACE( "adding name=%s version=%s arch=%s\n",
2186 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2187 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2189 else if (xml_elem_cmp(&elem, L"bindingRedirect", asmv1W))
2191 parse_binding_redirect_elem(xmlbuf, &elem);
2193 else
2195 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2196 parse_unknown_elem(xmlbuf, &elem);
2201 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2202 const struct xml_elem *parent )
2205 struct xml_elem elem;
2206 struct xml_attr attr;
2207 BOOL end = FALSE, optional = FALSE;
2209 while (next_xml_attr(xmlbuf, &attr, &end))
2211 if (xml_attr_cmp(&attr, L"optional"))
2213 optional = xmlstr_cmpi( &attr.value, L"yes" );
2214 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2216 else if (!is_xmlns_attr( &attr ))
2218 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2222 if (end) return;
2224 while (next_xml_elem(xmlbuf, &elem, parent))
2226 if (xml_elem_cmp(&elem, L"dependentAssembly", asmv1W))
2228 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2230 else
2232 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2233 parse_unknown_elem(xmlbuf, &elem);
2238 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2240 BOOL end = FALSE;
2242 parse_expect_no_attr(xmlbuf, &end);
2243 if (!end) parse_expect_end_elem(xmlbuf, parent);
2246 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2248 BOOL end = FALSE;
2250 parse_expect_no_attr(xmlbuf, &end);
2251 if (!end) parse_expect_end_elem(xmlbuf, parent);
2254 static void parse_activatable_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
2255 struct actctx_loader *acl, const struct xml_elem *parent )
2257 struct xml_elem elem;
2258 struct xml_attr attr;
2259 BOOL end = FALSE;
2260 struct entity *entity;
2262 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)))
2264 set_error( xmlbuf );
2265 return;
2267 while (next_xml_attr(xmlbuf, &attr, &end))
2269 if (xml_attr_cmp(&attr, L"name"))
2271 if (!(entity->u.activatable_class.name = xmlstrdupW(&attr.value)))
2272 set_error( xmlbuf );
2274 else if (xml_attr_cmp(&attr, L"threadingModel"))
2276 if (xmlstr_cmpi(&attr.value, L"both"))
2277 entity->u.activatable_class.threading_model = 0;
2278 else if (xmlstr_cmpi(&attr.value, L"sta"))
2279 entity->u.activatable_class.threading_model = 1;
2280 else if (xmlstr_cmpi(&attr.value, L"mta"))
2281 entity->u.activatable_class.threading_model = 2;
2282 else
2283 set_error( xmlbuf );
2285 else if (!is_xmlns_attr( &attr ))
2287 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2291 acl->actctx->sections |= ACTIVATABLE_CLASS_SECTION;
2293 if (end) return;
2295 while (next_xml_elem(xmlbuf, &elem, parent))
2297 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2298 parse_unknown_elem(xmlbuf, &elem);
2302 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2303 struct actctx_loader* acl, const struct xml_elem *parent )
2305 struct xml_elem elem;
2306 struct xml_attr attr;
2307 BOOL end = FALSE;
2308 struct dll_redirect* dll;
2310 if (!(dll = add_dll_redirect(assembly)))
2312 set_error( xmlbuf );
2313 return;
2316 while (next_xml_attr(xmlbuf, &attr, &end))
2318 if (xml_attr_cmp(&attr, L"name"))
2320 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2321 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2323 else if (xml_attr_cmp(&attr, L"loadFrom"))
2325 if (!(dll->load_from = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2327 else if (xml_attr_cmp(&attr, L"hash"))
2329 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2331 else if (xml_attr_cmp(&attr, L"hashalg"))
2333 if (!xmlstr_cmpi(&attr.value, L"SHA1"))
2334 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2336 else if (!is_xmlns_attr( &attr ))
2338 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2342 if (!dll->name) set_error( xmlbuf );
2344 acl->actctx->sections |= DLLREDIRECT_SECTION;
2346 if (end) return;
2348 while (next_xml_elem(xmlbuf, &elem, parent))
2350 if (xml_elem_cmp(&elem, L"comClass", asmv1W))
2352 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2354 else if (xml_elem_cmp(&elem, L"comInterfaceProxyStub", asmv1W))
2356 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2358 else if (xml_elem_cmp(&elem, L"hash", asmv2W))
2360 WARN("asmv2:hash (undocumented) not supported\n");
2361 parse_unknown_elem(xmlbuf, &elem);
2363 else if (xml_elem_cmp(&elem, L"typelib", asmv1W))
2365 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2367 else if (xml_elem_cmp(&elem, L"windowClass", asmv1W))
2369 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2371 else if (xml_elem_cmp(&elem, L"activatableClass", winrtv1W))
2373 parse_activatable_class_elem(xmlbuf, dll, acl, &elem);
2375 else
2377 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2378 parse_unknown_elem( xmlbuf, &elem );
2383 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2384 struct actctx_loader *acl, const struct xml_elem *parent )
2386 struct xml_attr attr;
2387 BOOL end = FALSE;
2389 while (next_xml_attr(xmlbuf, &attr, &end))
2391 if (xml_attr_cmp(&attr, L"Id"))
2393 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2394 UNICODE_STRING str;
2395 GUID compat_id;
2397 str.Buffer = (PWSTR)attr.value.ptr;
2398 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2399 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2401 if (!(compat = add_compat_context(assembly)))
2403 set_error( xmlbuf );
2404 return;
2406 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2407 compat->Id = compat_id;
2409 else
2411 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2414 else if (!is_xmlns_attr( &attr ))
2416 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2420 if (!end) parse_expect_end_elem(xmlbuf, parent);
2423 static void parse_maxversiontested_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2424 struct actctx_loader *acl, const struct xml_elem *parent )
2426 struct xml_attr attr;
2427 BOOL end = FALSE;
2429 while (next_xml_attr(xmlbuf, &attr, &end))
2431 if (xml_attr_cmp(&attr, L"Id"))
2433 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2434 struct assembly_version version;
2436 if (!(compat = add_compat_context(assembly)))
2438 set_error( xmlbuf );
2439 return;
2441 parse_version( &attr.value, &version );
2442 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED;
2443 compat->MaxVersionTested = (ULONGLONG)version.major << 48 |
2444 (ULONGLONG)version.minor << 32 | version.build << 16 | version.revision;
2446 else if (!is_xmlns_attr( &attr ))
2448 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2452 if (!end) parse_expect_end_elem(xmlbuf, parent);
2455 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2456 struct actctx_loader* acl, const struct xml_elem *parent)
2458 struct xml_elem elem;
2460 while (next_xml_elem(xmlbuf, &elem, parent))
2462 if (xml_elem_cmp(&elem, L"supportedOS", compatibilityNSW))
2464 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2466 else if (xml_elem_cmp(&elem, L"maxversiontested", compatibilityNSW))
2468 parse_maxversiontested_elem(xmlbuf, assembly, acl, &elem);
2470 else
2472 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2473 parse_unknown_elem(xmlbuf, &elem);
2478 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2479 struct actctx_loader* acl, const struct xml_elem *parent)
2481 struct xml_elem elem;
2483 while (next_xml_elem(xmlbuf, &elem, parent))
2485 if (xml_elem_cmp(&elem, L"application", compatibilityNSW))
2487 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2489 else
2491 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2492 parse_unknown_elem(xmlbuf, &elem);
2497 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2498 struct xml_elem *parent )
2500 struct xml_elem elem;
2501 struct xml_attr attr;
2502 xmlstr_t content;
2503 BOOL end = FALSE;
2504 struct entity *entity;
2506 while (next_xml_attr( xmlbuf, &attr, &end ))
2508 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2511 if (end) return;
2513 if (!parse_text_content( xmlbuf, &content )) return;
2514 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2516 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2517 if (!entity)
2519 set_error( xmlbuf );
2520 return;
2522 entity->u.settings.name = xmlstrdupW( &parent->name );
2523 entity->u.settings.value = xmlstrdupW( &content );
2524 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2526 while (next_xml_elem(xmlbuf, &elem, parent))
2528 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2529 parse_unknown_elem( xmlbuf, &elem );
2533 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2534 struct actctx_loader *acl, const struct xml_elem *parent )
2536 struct xml_elem elem;
2538 while (next_xml_elem( xmlbuf, &elem, parent ))
2540 if (xml_elem_cmp( &elem, L"activeCodePage", windowsSettings2019NSW ) ||
2541 xml_elem_cmp( &elem, L"autoElevate", windowsSettings2005NSW ) ||
2542 xml_elem_cmp( &elem, L"disableTheming", windowsSettings2005NSW ) ||
2543 xml_elem_cmp( &elem, L"disableWindowFiltering", windowsSettings2011NSW ) ||
2544 xml_elem_cmp( &elem, L"dpiAware", windowsSettings2005NSW ) ||
2545 xml_elem_cmp( &elem, L"dpiAwareness", windowsSettings2016NSW ) ||
2546 xml_elem_cmp( &elem, L"gdiScaling", windowsSettings2017NSW ) ||
2547 xml_elem_cmp( &elem, L"heapType", windowsSettings2020NSW ) ||
2548 xml_elem_cmp( &elem, L"highResolutionScrollingAware", windowsSettings2017NSW ) ||
2549 xml_elem_cmp( &elem, L"longPathAware", windowsSettings2016NSW ) ||
2550 xml_elem_cmp( &elem, L"magicFutureSetting", windowsSettings2017NSW ) ||
2551 xml_elem_cmp( &elem, L"printerDriverIsolation", windowsSettings2011NSW ) ||
2552 xml_elem_cmp( &elem, L"ultraHighResolutionScrollingAware", windowsSettings2017NSW ))
2554 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2556 else
2558 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2559 parse_unknown_elem( xmlbuf, &elem );
2564 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2565 struct actctx_loader *acl, const struct xml_elem *parent )
2567 struct xml_elem elem;
2569 while (next_xml_elem( xmlbuf, &elem, parent ))
2571 if (xml_elem_cmp( &elem, L"windowsSettings", asmv1W ))
2573 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2575 else
2577 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2578 parse_unknown_elem( xmlbuf, &elem );
2583 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2584 struct actctx_loader *acl, const struct xml_elem *parent )
2586 struct xml_elem elem;
2587 struct xml_attr attr;
2588 BOOL end = FALSE;
2590 /* Multiple requestedExecutionLevel elements are not supported. */
2591 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2593 while (next_xml_attr(xmlbuf, &attr, &end))
2595 if (xml_attr_cmp(&attr, L"level"))
2597 if (xmlstr_cmpi(&attr.value, L"asInvoker"))
2598 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2599 else if (xmlstr_cmpi(&attr.value, L"highestAvailable"))
2600 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2601 else if (xmlstr_cmpi(&attr.value, L"requireAdministrator"))
2602 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2603 else
2604 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2606 else if (xml_attr_cmp(&attr, L"uiAccess"))
2608 if (xmlstr_cmpi(&attr.value, L"false"))
2609 assembly->ui_access = FALSE;
2610 else if (xmlstr_cmpi(&attr.value, L"true"))
2611 assembly->ui_access = TRUE;
2612 else
2613 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2615 else if (!is_xmlns_attr( &attr ))
2616 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2619 if (end) return;
2621 while (next_xml_elem(xmlbuf, &elem, parent))
2623 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2624 parse_unknown_elem(xmlbuf, &elem);
2628 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2629 struct actctx_loader *acl, const struct xml_elem *parent )
2631 struct xml_elem elem;
2633 while (next_xml_elem(xmlbuf, &elem, parent))
2635 if (xml_elem_cmp(&elem, L"requestedExecutionLevel", asmv1W))
2637 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2639 else
2641 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2642 parse_unknown_elem(xmlbuf, &elem);
2647 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2648 struct actctx_loader *acl, const struct xml_elem *parent )
2650 struct xml_elem elem;
2652 while (next_xml_elem(xmlbuf, &elem, parent))
2654 if (xml_elem_cmp(&elem, L"requestedPrivileges", asmv1W))
2656 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2658 else
2660 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2661 parse_unknown_elem(xmlbuf, &elem);
2666 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2667 struct actctx_loader *acl, const struct xml_elem *parent )
2669 struct xml_elem elem;
2671 while (next_xml_elem(xmlbuf, &elem, parent))
2673 if (xml_elem_cmp(&elem, L"security", asmv1W))
2675 parse_security_elem(xmlbuf, assembly, acl, &elem);
2677 else
2679 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2680 parse_unknown_elem(xmlbuf, &elem);
2685 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2686 struct actctx_loader* acl, const struct xml_elem *parent,
2687 struct assembly_identity* expected_ai)
2689 struct xml_elem elem;
2690 struct xml_attr attr;
2691 BOOL end = FALSE, version = FALSE;
2693 TRACE("(%p)\n", xmlbuf);
2695 while (next_xml_attr(xmlbuf, &attr, &end))
2697 if (xml_attr_cmp(&attr, L"manifestVersion"))
2699 if (!xmlstr_cmp(&attr.value, L"1.0"))
2701 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2702 break;
2704 version = TRUE;
2706 else if (!is_xmlns_attr( &attr ))
2708 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2712 if (end || !version)
2714 set_error( xmlbuf );
2715 return;
2718 while (next_xml_elem(xmlbuf, &elem, parent))
2720 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, L"noInherit", asmv1W))
2722 parse_noinherit_elem(xmlbuf, &elem);
2723 assembly->no_inherit = TRUE;
2725 else if (xml_elem_cmp(&elem, L"noInheritable", asmv1W))
2727 parse_noinheritable_elem(xmlbuf, &elem);
2729 else if (xml_elem_cmp(&elem, L"description", asmv1W))
2731 parse_description_elem(xmlbuf, &elem);
2733 else if (xml_elem_cmp(&elem, L"comInterfaceExternalProxyStub", asmv1W))
2735 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2737 else if (xml_elem_cmp(&elem, L"dependency", asmv1W))
2739 parse_dependency_elem(xmlbuf, acl, &elem);
2741 else if (xml_elem_cmp(&elem, L"file", asmv1W))
2743 parse_file_elem(xmlbuf, assembly, acl, &elem);
2745 else if (xml_elem_cmp(&elem, L"clrClass", asmv1W))
2747 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2749 else if (xml_elem_cmp(&elem, L"clrSurrogate", asmv1W))
2751 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2753 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2755 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2757 else if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2759 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2761 if (!xmlbuf->error && expected_ai)
2763 /* FIXME: more tests */
2764 if (assembly->type == ASSEMBLY_MANIFEST &&
2765 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2767 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2768 expected_ai->version.major, expected_ai->version.minor,
2769 expected_ai->version.build, expected_ai->version.revision,
2770 assembly->id.version.major, assembly->id.version.minor,
2771 assembly->id.version.build, assembly->id.version.revision);
2772 set_error( xmlbuf );
2774 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2775 (assembly->id.version.major != expected_ai->version.major ||
2776 assembly->id.version.minor != expected_ai->version.minor ||
2777 assembly->id.version.build < expected_ai->version.build ||
2778 (assembly->id.version.build == expected_ai->version.build &&
2779 assembly->id.version.revision < expected_ai->version.revision)))
2781 FIXME("wrong version for shared assembly manifest\n");
2782 set_error( xmlbuf );
2786 else if (xml_elem_cmp(&elem, L"compatibility", compatibilityNSW))
2788 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2790 else if (xml_elem_cmp(&elem, L"application", asmv1W))
2792 parse_application_elem(xmlbuf, assembly, acl, &elem);
2794 else
2796 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2797 parse_unknown_elem(xmlbuf, &elem);
2801 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2802 assembly->no_inherit)
2804 set_error( xmlbuf );
2808 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2809 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2811 struct xml_elem elem;
2812 struct xml_elem parent = {};
2814 xmlbuf->error = FALSE;
2815 xmlbuf->ns_pos = 0;
2817 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2819 if (xmlstr_cmp(&elem.name, L"?xml") &&
2820 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2821 return STATUS_SXS_CANT_GEN_ACTCTX;
2823 if (!xml_elem_cmp(&elem, L"assembly", asmv1W))
2825 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2826 return STATUS_SXS_CANT_GEN_ACTCTX;
2829 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2830 if (xmlbuf->error)
2832 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2833 return STATUS_SXS_CANT_GEN_ACTCTX;
2836 if (next_xml_elem(xmlbuf, &elem, &parent))
2838 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2839 return STATUS_SXS_CANT_GEN_ACTCTX;
2842 if (xmlbuf->ptr != xmlbuf->end)
2844 FIXME("parse error\n");
2845 return STATUS_SXS_CANT_GEN_ACTCTX;
2847 return STATUS_SUCCESS;
2850 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2851 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2852 const void *buffer, SIZE_T size )
2854 xmlbuf_t xmlbuf;
2855 NTSTATUS status;
2856 struct assembly *assembly;
2857 int unicode_tests;
2859 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2861 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2862 return STATUS_SXS_CANT_GEN_ACTCTX;
2864 if (directory && !(assembly->directory = strdupW(directory)))
2865 return STATUS_NO_MEMORY;
2867 if (!filename)
2869 UNICODE_STRING module_path;
2870 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2871 assembly->manifest.info = module_path.Buffer;
2873 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2875 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2876 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2878 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2879 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2881 xmlbuf.ptr = buffer;
2882 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2883 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2885 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2887 const WCHAR *buf = buffer;
2888 WCHAR *new_buff;
2889 unsigned int i;
2891 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2892 return STATUS_NO_MEMORY;
2893 for (i = 0; i < size / sizeof(WCHAR); i++)
2894 new_buff[i] = RtlUshortByteSwap( buf[i] );
2895 xmlbuf.ptr = new_buff;
2896 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2897 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2898 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2900 else
2902 DWORD len;
2903 WCHAR *new_buff;
2905 /* let's assume utf-8 for now */
2906 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2907 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2908 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2909 xmlbuf.ptr = new_buff;
2910 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2911 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2912 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2914 return status;
2917 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2919 OBJECT_ATTRIBUTES attr;
2920 IO_STATUS_BLOCK io;
2922 attr.Length = sizeof(attr);
2923 attr.RootDirectory = 0;
2924 attr.Attributes = OBJ_CASE_INSENSITIVE;
2925 attr.ObjectName = name;
2926 attr.SecurityDescriptor = NULL;
2927 attr.SecurityQualityOfService = NULL;
2928 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2931 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2932 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2933 HANDLE hModule, LPCWSTR resname, ULONG lang )
2935 NTSTATUS status;
2936 UNICODE_STRING nameW;
2937 LDR_RESOURCE_INFO info;
2938 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2939 void *ptr;
2941 if (TRACE_ON(actctx))
2943 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2945 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2946 hModule, debugstr_w(nameW.Buffer) );
2947 RtlFreeUnicodeString( &nameW );
2949 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2950 hModule, debugstr_w(filename) );
2953 if (!resname) return STATUS_INVALID_PARAMETER;
2955 info.Type = RT_MANIFEST;
2956 info.Language = lang;
2957 if (!((ULONG_PTR)resname >> 16))
2959 info.Name = (ULONG_PTR)resname;
2960 status = LdrFindResource_U(hModule, &info, 3, &entry);
2962 else if (resname[0] == '#')
2964 ULONG value;
2965 RtlInitUnicodeString(&nameW, resname + 1);
2966 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2967 return STATUS_INVALID_PARAMETER;
2968 info.Name = value;
2969 status = LdrFindResource_U(hModule, &info, 3, &entry);
2971 else
2973 RtlCreateUnicodeString(&nameW, resname);
2974 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2975 info.Name = (ULONG_PTR)nameW.Buffer;
2976 status = LdrFindResource_U(hModule, &info, 3, &entry);
2977 RtlFreeUnicodeString(&nameW);
2979 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2981 if (status == STATUS_SUCCESS)
2982 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2984 return status;
2987 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2988 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2989 HANDLE file, LPCWSTR resname, ULONG lang )
2991 HANDLE mapping;
2992 OBJECT_ATTRIBUTES attr;
2993 LARGE_INTEGER size;
2994 LARGE_INTEGER offset;
2995 NTSTATUS status;
2996 SIZE_T count;
2997 void *base;
2999 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
3001 attr.Length = sizeof(attr);
3002 attr.RootDirectory = 0;
3003 attr.ObjectName = NULL;
3004 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3005 attr.SecurityDescriptor = NULL;
3006 attr.SecurityQualityOfService = NULL;
3008 size.QuadPart = 0;
3009 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3010 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3011 if (status != STATUS_SUCCESS) return status;
3013 offset.QuadPart = 0;
3014 count = 0;
3015 base = NULL;
3016 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3017 &count, ViewShare, 0, PAGE_READONLY );
3018 NtClose( mapping );
3019 if (status != STATUS_SUCCESS) return status;
3021 if (RtlImageNtHeader(base)) /* we got a PE file */
3023 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3024 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3026 else status = STATUS_INVALID_IMAGE_FORMAT;
3028 NtUnmapViewOfSection( GetCurrentProcess(), base );
3029 return status;
3032 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3033 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3035 FILE_END_OF_FILE_INFORMATION info;
3036 IO_STATUS_BLOCK io;
3037 HANDLE mapping;
3038 OBJECT_ATTRIBUTES attr;
3039 LARGE_INTEGER size;
3040 LARGE_INTEGER offset;
3041 NTSTATUS status;
3042 SIZE_T count;
3043 void *base;
3045 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3047 attr.Length = sizeof(attr);
3048 attr.RootDirectory = 0;
3049 attr.ObjectName = NULL;
3050 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3051 attr.SecurityDescriptor = NULL;
3052 attr.SecurityQualityOfService = NULL;
3054 size.QuadPart = 0;
3055 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3056 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3057 if (status != STATUS_SUCCESS) return status;
3059 offset.QuadPart = 0;
3060 count = 0;
3061 base = NULL;
3062 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3063 &count, ViewShare, 0, PAGE_READONLY );
3064 NtClose( mapping );
3065 if (status != STATUS_SUCCESS) return status;
3067 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3068 if (status == STATUS_SUCCESS)
3069 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3071 NtUnmapViewOfSection( GetCurrentProcess(), base );
3072 return status;
3075 /* try to load the .manifest file associated to the file */
3076 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3077 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3079 WCHAR *buffer;
3080 NTSTATUS status;
3081 UNICODE_STRING nameW;
3082 HANDLE file;
3083 UINT resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3085 if (!((ULONG_PTR)resname >> 16)) resid = LOWORD(resname);
3087 TRACE( "looking for manifest associated with %s id %u\n", debugstr_w(filename), resid );
3089 if (module) /* use the module filename */
3091 UNICODE_STRING name;
3093 if (!(status = get_module_filename( module, &name, sizeof(L".manifest") + 10*sizeof(WCHAR) )))
3095 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, L".%u", resid );
3096 wcscat( name.Buffer, L".manifest" );
3097 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3098 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3099 RtlFreeUnicodeString( &name );
3101 if (status) return status;
3103 else
3105 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3106 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(L".manifest") )))
3107 return STATUS_NO_MEMORY;
3108 wcscpy( buffer, filename );
3109 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, L".%u", resid );
3110 wcscat( buffer, L".manifest" );
3111 RtlInitUnicodeString( &nameW, buffer );
3114 if (!open_nt_file( &file, &nameW ))
3116 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3117 NtClose( file );
3119 else status = STATUS_RESOURCE_NAME_NOT_FOUND;
3120 RtlFreeUnicodeString( &nameW );
3121 return status;
3124 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3126 static const WCHAR lookup_fmtW[] = L"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3127 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3129 WCHAR *lookup, *ret = NULL;
3130 UNICODE_STRING lookup_us;
3131 IO_STATUS_BLOCK io;
3132 const WCHAR *lang = ai->language;
3133 unsigned int data_pos = 0, data_len, len;
3134 char buffer[8192];
3136 if (!lang || !wcsicmp( lang, L"neutral" )) lang = L"*";
3138 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3139 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3140 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3141 ai->version.major, ai->version.minor, lang );
3142 RtlInitUnicodeString( &lookup_us, lookup );
3144 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3145 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3147 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3148 FILE_BOTH_DIR_INFORMATION *dir_info;
3149 WCHAR *tmp;
3150 ULONG build, revision;
3152 data_len = io.Information;
3154 for (;;)
3156 if (data_pos >= data_len)
3158 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3159 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3160 break;
3161 data_len = io.Information;
3162 data_pos = 0;
3164 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3166 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3167 else data_pos = data_len;
3169 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3170 build = wcstoul( tmp, NULL, 10 );
3171 if (build < min_build) continue;
3172 tmp = wcschr(tmp, '.') + 1;
3173 revision = wcstoul( tmp, NULL, 10 );
3174 if (build == min_build && revision < min_revision) continue;
3175 tmp = wcschr(tmp, '_') + 1;
3176 tmp = wcschr(tmp, '_') + 1;
3177 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3178 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3180 /* prefer a non-Wine manifest if we already have one */
3181 /* we'll still load the builtin dll if specified through DllOverrides */
3182 if (ret) continue;
3184 else
3186 min_build = build;
3187 min_revision = revision;
3189 ai->version.build = build;
3190 ai->version.revision = revision;
3191 RtlFreeHeap( GetProcessHeap(), 0, ret );
3192 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3194 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3195 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3199 else WARN("no matching file for %s\n", debugstr_w(lookup));
3200 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3201 return ret;
3204 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3206 struct assembly_identity sxs_ai;
3207 UNICODE_STRING path_us;
3208 OBJECT_ATTRIBUTES attr;
3209 IO_STATUS_BLOCK io;
3210 WCHAR *path, *file = NULL;
3211 HANDLE handle;
3213 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3215 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L"\\winsxs\\manifests") +
3216 wcslen(windows_dir) * sizeof(WCHAR) )))
3217 return STATUS_NO_MEMORY;
3219 wcscpy( path, windows_dir );
3220 wcscat( path, L"\\winsxs\\manifests" );
3222 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3224 RtlFreeHeap( GetProcessHeap(), 0, path );
3225 return STATUS_NO_SUCH_FILE;
3227 RtlFreeHeap( GetProcessHeap(), 0, path );
3229 attr.Length = sizeof(attr);
3230 attr.RootDirectory = 0;
3231 attr.Attributes = OBJ_CASE_INSENSITIVE;
3232 attr.ObjectName = &path_us;
3233 attr.SecurityDescriptor = NULL;
3234 attr.SecurityQualityOfService = NULL;
3236 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3237 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3239 sxs_ai = *ai;
3240 file = lookup_manifest_file( handle, &sxs_ai );
3241 NtClose( handle );
3243 if (!file)
3245 RtlFreeUnicodeString( &path_us );
3246 return STATUS_NO_SUCH_FILE;
3249 /* append file name to directory path */
3250 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3251 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3253 RtlFreeHeap( GetProcessHeap(), 0, file );
3254 RtlFreeUnicodeString( &path_us );
3255 return STATUS_NO_MEMORY;
3258 path[path_us.Length/sizeof(WCHAR)] = '\\';
3259 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3260 RtlInitUnicodeString( &path_us, path );
3261 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3263 if (!open_nt_file( &handle, &path_us ))
3265 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3266 NtClose( handle );
3268 else io.u.Status = STATUS_NO_SUCH_FILE;
3270 RtlFreeHeap( GetProcessHeap(), 0, file );
3271 RtlFreeUnicodeString( &path_us );
3272 return io.u.Status;
3275 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3276 struct assembly_identity* ai)
3278 unsigned int i;
3279 WCHAR *buffer, *p, *directory;
3280 NTSTATUS status;
3281 UNICODE_STRING nameW;
3282 HANDLE file;
3283 DWORD len;
3285 TRACE( "looking for name=%s version=%s arch=%s\n",
3286 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3288 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3290 /* FIXME: add support for language specific lookup */
3292 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3293 wcslen(acl->actctx->appdir.info));
3295 nameW.Buffer = NULL;
3296 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3297 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(L".manifest") )))
3298 return STATUS_NO_MEMORY;
3300 if (!(directory = build_assembly_dir( ai )))
3302 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3303 return STATUS_NO_MEMORY;
3306 /* Lookup in <dir>\name.dll
3307 * <dir>\name.manifest
3308 * <dir>\name\name.dll
3309 * <dir>\name\name.manifest
3311 * First 'appdir' is used as <dir>, if that failed
3312 * it tries application manifest file path.
3314 wcscpy( buffer, acl->actctx->appdir.info );
3315 p = buffer + wcslen(buffer);
3316 for (i = 0; i < 4; i++)
3318 if (i == 2)
3320 struct assembly *assembly = acl->actctx->assemblies;
3321 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3323 else *p++ = '\\';
3325 wcscpy( p, ai->name );
3326 p += wcslen(p);
3328 wcscpy( p, L".dll" );
3329 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3331 status = open_nt_file( &file, &nameW );
3332 if (!status)
3334 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3335 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3336 NtClose( file );
3337 if (status == STATUS_SUCCESS)
3338 break;
3340 RtlFreeUnicodeString( &nameW );
3343 wcscpy( p, L".manifest" );
3344 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3346 status = open_nt_file( &file, &nameW );
3347 if (!status)
3349 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3350 NtClose( file );
3351 break;
3353 RtlFreeUnicodeString( &nameW );
3355 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3357 RtlFreeUnicodeString( &nameW );
3358 RtlFreeHeap( GetProcessHeap(), 0, directory );
3359 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3360 return status;
3363 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3365 NTSTATUS status = STATUS_SUCCESS;
3366 unsigned int i;
3368 for (i = 0; i < acl->num_dependencies; i++)
3370 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3372 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3374 FIXME( "Could not find dependent assembly %s (%s)\n",
3375 debugstr_w(acl->dependencies[i].name),
3376 debugstr_version(&acl->dependencies[i].version) );
3377 status = STATUS_SXS_CANT_GEN_ACTCTX;
3378 break;
3382 /* FIXME should now iterate through all refs */
3383 return status;
3386 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3387 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3389 NTSTATUS status = STATUS_SUCCESS;
3391 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3393 if (*handle) return STATUS_INVALID_PARAMETER;
3395 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3396 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3398 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3400 ULONG_PTR magic;
3401 LDR_DATA_TABLE_ENTRY *pldr;
3403 if (!*handle) return STATUS_INVALID_PARAMETER;
3405 LdrLockLoaderLock( 0, NULL, &magic );
3406 if (!LdrFindEntryForAddress( *handle, &pldr ))
3408 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3409 status = STATUS_DLL_NOT_FOUND;
3410 else
3411 *handle = pldr->ActivationContext;
3413 else status = STATUS_DLL_NOT_FOUND;
3414 LdrUnlockLoaderLock( 0, magic );
3416 else if (!*handle && (class != ActivationContextBasicInformation))
3417 *handle = process_actctx;
3419 return status;
3422 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3424 unsigned int i, j, total_len = 0, dll_count = 0;
3425 struct strsection_header *header;
3426 struct dllredirect_data *data;
3427 struct string_index *index;
3428 ULONG name_offset;
3430 /* compute section length */
3431 for (i = 0; i < actctx->num_assemblies; i++)
3433 struct assembly *assembly = &actctx->assemblies[i];
3434 for (j = 0; j < assembly->num_dlls; j++)
3436 struct dll_redirect *dll = &assembly->dlls[j];
3438 /* each entry needs index, data and string data */
3439 total_len += sizeof(*index);
3440 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3441 if (dll->load_from)
3443 total_len += offsetof( struct dllredirect_data, paths[1] );
3444 total_len += aligned_string_len( wcslen(dll->load_from) * sizeof(WCHAR) );
3446 else total_len += offsetof( struct dllredirect_data, paths[0] );
3449 dll_count += assembly->num_dlls;
3452 total_len += sizeof(*header);
3454 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3455 if (!header) return STATUS_NO_MEMORY;
3457 memset(header, 0, sizeof(*header));
3458 header->magic = STRSECTION_MAGIC;
3459 header->size = sizeof(*header);
3460 header->count = dll_count;
3461 header->index_offset = sizeof(*header);
3462 index = (struct string_index*)((BYTE*)header + header->index_offset);
3463 name_offset = header->index_offset + header->count*sizeof(*index);
3465 for (i = 0; i < actctx->num_assemblies; i++)
3467 struct assembly *assembly = &actctx->assemblies[i];
3468 for (j = 0; j < assembly->num_dlls; j++)
3470 struct dll_redirect *dll = &assembly->dlls[j];
3471 UNICODE_STRING str;
3472 WCHAR *ptrW;
3474 /* setup new index entry */
3475 str.Buffer = dll->name;
3476 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3477 str.MaximumLength = str.Length + sizeof(WCHAR);
3478 /* hash original class name */
3479 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3481 index->name_offset = name_offset;
3482 index->name_len = str.Length;
3483 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3484 index->data_len = offsetof( struct dllredirect_data, paths[0] );
3485 index->rosterindex = i + 1;
3487 /* dll name */
3488 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3489 memcpy(ptrW, dll->name, index->name_len);
3490 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3491 name_offset += aligned_string_len(str.MaximumLength);
3493 /* setup data */
3494 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3495 if (dll->load_from)
3497 ULONG len = wcslen(dll->load_from) * sizeof(WCHAR);
3498 data->size = offsetof( struct dllredirect_data, paths[1] );
3499 data->flags = 0;
3500 data->total_len = aligned_string_len( len );
3501 data->paths_count = 1;
3502 data->paths_offset = index->data_offset + offsetof( struct dllredirect_data, paths[0] );
3503 data->paths[0].offset = index->data_offset + data->size;
3504 data->paths[0].len = len;
3505 ptrW = (WCHAR *)((BYTE *)header + data->paths[0].offset);
3506 memcpy( ptrW, dll->load_from, len );
3507 if (wcschr( dll->load_from, '%' )) data->flags |= DLL_REDIRECT_PATH_EXPAND;
3509 else
3511 data->size = offsetof( struct dllredirect_data, paths[0] );
3512 data->flags = DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT;
3513 data->total_len = 0;
3514 data->paths_count = 0;
3515 data->paths_offset = 0;
3517 name_offset += data->size + data->total_len;
3519 index++;
3523 *section = header;
3525 return STATUS_SUCCESS;
3528 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3530 struct string_index *iter, *index = NULL;
3531 UNICODE_STRING str;
3532 ULONG hash = 0, i;
3534 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3535 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3537 for (i = 0; i < section->count; i++)
3539 if (iter->hash == hash)
3541 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3542 str.Length = iter->name_len;
3543 if (RtlEqualUnicodeString( &str, name, TRUE ))
3545 index = iter;
3546 break;
3548 else
3549 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3551 iter++;
3554 return index;
3557 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3559 struct guid_index *iter, *index = NULL;
3560 ULONG i;
3562 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3564 for (i = 0; i < section->count; i++)
3566 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3568 index = iter;
3569 break;
3571 iter++;
3574 return index;
3577 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3579 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3582 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3583 PACTCTX_SECTION_KEYED_DATA data)
3585 struct dllredirect_data *dll;
3586 struct string_index *index;
3588 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3590 if (!actctx->dllredirect_section)
3592 struct strsection_header *section;
3594 NTSTATUS status = build_dllredirect_section(actctx, &section);
3595 if (status) return status;
3597 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3598 RtlFreeHeap(GetProcessHeap(), 0, section);
3601 index = find_string_index(actctx->dllredirect_section, name);
3602 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3604 if (data)
3606 dll = get_dllredirect_data(actctx, index);
3608 data->ulDataFormatVersion = 1;
3609 data->lpData = dll;
3610 data->ulLength = dll->size;
3611 data->lpSectionGlobalData = NULL;
3612 data->ulSectionGlobalDataLength = 0;
3613 data->lpSectionBase = actctx->dllredirect_section;
3614 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3615 data->hActCtx = NULL;
3617 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3618 data->ulAssemblyRosterIndex = index->rosterindex;
3621 return STATUS_SUCCESS;
3624 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3626 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3629 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3631 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3634 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3636 unsigned int i, j, k, total_len = 0, class_count = 0;
3637 struct wndclass_redirect_data *data;
3638 struct strsection_header *header;
3639 struct string_index *index;
3640 ULONG name_offset;
3642 /* compute section length */
3643 for (i = 0; i < actctx->num_assemblies; i++)
3645 struct assembly *assembly = &actctx->assemblies[i];
3646 for (j = 0; j < assembly->num_dlls; j++)
3648 struct dll_redirect *dll = &assembly->dlls[j];
3649 for (k = 0; k < dll->entities.num; k++)
3651 struct entity *entity = &dll->entities.base[k];
3652 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3654 int class_len = wcslen(entity->u.class.name) + 1;
3655 int len;
3657 /* each class entry needs index, data and string data */
3658 total_len += sizeof(*index);
3659 total_len += sizeof(*data);
3660 /* original name is stored separately */
3661 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3662 /* versioned name and module name are stored one after another */
3663 if (entity->u.class.versioned)
3664 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3665 else
3666 len = class_len;
3667 len += wcslen(dll->name) + 1;
3668 total_len += aligned_string_len(len*sizeof(WCHAR));
3670 class_count++;
3676 total_len += sizeof(*header);
3678 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3679 if (!header) return STATUS_NO_MEMORY;
3681 memset(header, 0, sizeof(*header));
3682 header->magic = STRSECTION_MAGIC;
3683 header->size = sizeof(*header);
3684 header->count = class_count;
3685 header->index_offset = sizeof(*header);
3686 index = (struct string_index*)((BYTE*)header + header->index_offset);
3687 name_offset = header->index_offset + header->count*sizeof(*index);
3689 for (i = 0; i < actctx->num_assemblies; i++)
3691 struct assembly *assembly = &actctx->assemblies[i];
3692 for (j = 0; j < assembly->num_dlls; j++)
3694 struct dll_redirect *dll = &assembly->dlls[j];
3695 for (k = 0; k < dll->entities.num; k++)
3697 struct entity *entity = &dll->entities.base[k];
3698 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3700 ULONG versioned_len, module_len;
3701 UNICODE_STRING str;
3702 WCHAR *ptrW;
3704 /* setup new index entry */
3705 str.Buffer = entity->u.class.name;
3706 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3707 str.MaximumLength = str.Length + sizeof(WCHAR);
3708 /* hash original class name */
3709 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3711 /* include '!' separator too */
3712 if (entity->u.class.versioned)
3713 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3714 else
3715 versioned_len = str.Length;
3716 module_len = wcslen(dll->name)*sizeof(WCHAR);
3718 index->name_offset = name_offset;
3719 index->name_len = str.Length;
3720 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3721 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3722 index->rosterindex = i + 1;
3724 /* setup data */
3725 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3726 data->size = sizeof(*data);
3727 data->res = 0;
3728 data->name_len = versioned_len;
3729 data->name_offset = sizeof(*data);
3730 data->module_len = module_len;
3731 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3733 /* original class name */
3734 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3735 memcpy(ptrW, entity->u.class.name, index->name_len);
3736 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3738 /* module name */
3739 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3740 memcpy(ptrW, dll->name, data->module_len);
3741 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3743 /* versioned name */
3744 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3745 if (entity->u.class.versioned)
3747 get_assembly_version(assembly, ptrW);
3748 wcscat(ptrW, L"!");
3749 wcscat(ptrW, entity->u.class.name);
3751 else
3753 memcpy(ptrW, entity->u.class.name, index->name_len);
3754 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3757 name_offset += sizeof(*data);
3758 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3760 index++;
3766 *section = header;
3768 return STATUS_SUCCESS;
3771 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3772 PACTCTX_SECTION_KEYED_DATA data)
3774 struct string_index *iter, *index = NULL;
3775 struct wndclass_redirect_data *class;
3776 UNICODE_STRING str;
3777 ULONG hash;
3778 int i;
3780 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3782 if (!actctx->wndclass_section)
3784 struct strsection_header *section;
3786 NTSTATUS status = build_wndclass_section(actctx, &section);
3787 if (status) return status;
3789 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3790 RtlFreeHeap(GetProcessHeap(), 0, section);
3793 hash = 0;
3794 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3795 iter = get_wndclass_first_index(actctx);
3797 for (i = 0; i < actctx->wndclass_section->count; i++)
3799 if (iter->hash == hash)
3801 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3802 str.Length = iter->name_len;
3803 if (RtlEqualUnicodeString( &str, name, TRUE ))
3805 index = iter;
3806 break;
3808 else
3809 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3811 iter++;
3814 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3816 if (data)
3818 class = get_wndclass_data(actctx, index);
3820 data->ulDataFormatVersion = 1;
3821 data->lpData = class;
3822 /* full length includes string length with nulls */
3823 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3824 data->lpSectionGlobalData = NULL;
3825 data->ulSectionGlobalDataLength = 0;
3826 data->lpSectionBase = actctx->wndclass_section;
3827 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3828 data->hActCtx = NULL;
3830 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3831 data->ulAssemblyRosterIndex = index->rosterindex;
3834 return STATUS_SUCCESS;
3837 static inline struct string_index *get_activatable_class_first_index(ACTIVATION_CONTEXT *actctx)
3839 return (struct string_index *)((BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->index_offset);
3842 static inline struct activatable_class_data *get_activatable_class_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3844 return (struct activatable_class_data *)((BYTE *)ctxt->activatable_class_section + index->data_offset);
3847 static NTSTATUS build_activatable_class_section(ACTIVATION_CONTEXT *actctx, struct strsection_header **section)
3849 unsigned int i, j, k, total_len = 0, class_count = 0, global_offset = 0, global_len = 0;
3850 struct activatable_class_data *data;
3851 struct strsection_header *header;
3852 struct string_index *index;
3853 ULONG name_offset;
3855 /* compute section length */
3856 for (i = 0; i < actctx->num_assemblies; i++)
3858 struct assembly *assembly = &actctx->assemblies[i];
3859 for (j = 0; j < assembly->num_dlls; j++)
3861 struct dll_redirect *dll = &assembly->dlls[j];
3862 BOOL has_class = FALSE;
3864 for (k = 0; k < dll->entities.num; k++)
3866 struct entity *entity = &dll->entities.base[k];
3867 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3869 int class_len = wcslen(entity->u.activatable_class.name) + 1;
3871 /* each class entry needs index, data and string data */
3872 total_len += sizeof(*index);
3873 total_len += aligned_string_len(class_len * sizeof(WCHAR));
3874 total_len += sizeof(*data);
3876 class_count++;
3877 has_class = TRUE;
3881 if (has_class)
3883 int module_len = wcslen(dll->name) + 1;
3884 global_len += aligned_string_len(module_len * sizeof(WCHAR));
3889 total_len += sizeof(*header) + global_len;
3891 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3892 if (!header) return STATUS_NO_MEMORY;
3894 memset(header, 0, sizeof(*header));
3895 header->magic = STRSECTION_MAGIC;
3896 header->size = sizeof(*header);
3897 header->count = class_count;
3898 header->global_offset = header->size;
3899 header->global_len = global_len;
3900 header->index_offset = header->global_offset + header->global_len;
3901 index = (struct string_index *)((BYTE *)header + header->index_offset);
3902 name_offset = header->index_offset + header->count * sizeof(*index);
3904 global_offset = header->size;
3905 for (i = 0; i < actctx->num_assemblies; i++)
3907 struct assembly *assembly = &actctx->assemblies[i];
3908 for (j = 0; j < assembly->num_dlls; j++)
3910 struct dll_redirect *dll = &assembly->dlls[j];
3911 int module_len = wcslen(dll->name) * sizeof(WCHAR);
3912 BOOL has_class = FALSE;
3914 for (k = 0; k < dll->entities.num; k++)
3916 struct entity *entity = &dll->entities.base[k];
3918 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3920 UNICODE_STRING str;
3921 WCHAR *ptrW;
3923 /* setup new index entry */
3924 str.Buffer = entity->u.activatable_class.name;
3925 str.Length = wcslen(entity->u.activatable_class.name) * sizeof(WCHAR);
3926 str.MaximumLength = str.Length + sizeof(WCHAR);
3927 /* hash class name */
3928 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3930 index->name_offset = name_offset;
3931 index->name_len = str.Length;
3932 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3933 index->data_len = sizeof(*data);
3934 index->rosterindex = i + 1;
3936 /* class name */
3937 ptrW = (WCHAR *)((BYTE *)header + index->name_offset);
3938 memcpy(ptrW, entity->u.activatable_class.name, index->name_len);
3939 ptrW[index->name_len / sizeof(WCHAR)] = 0;
3941 /* class data */
3942 data = (struct activatable_class_data *)((BYTE *)header + index->data_offset);
3943 data->size = sizeof(*data);
3944 data->threading_model = entity->u.activatable_class.threading_model;
3945 data->module_len = module_len;
3946 data->module_offset = global_offset;
3948 name_offset += aligned_string_len(str.MaximumLength);
3949 name_offset += sizeof(*data);
3951 index++;
3952 has_class = TRUE;
3956 if (has_class)
3958 WCHAR *ptrW = (WCHAR *)((BYTE *)header + global_offset);
3959 memcpy(ptrW, dll->name, module_len);
3960 ptrW[module_len / sizeof(WCHAR)] = 0;
3961 global_offset += aligned_string_len(module_len + sizeof(WCHAR));
3966 *section = header;
3968 return STATUS_SUCCESS;
3971 static NTSTATUS find_activatable_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3972 PACTCTX_SECTION_KEYED_DATA data)
3974 struct string_index *iter, *index = NULL;
3975 struct activatable_class_data *class;
3976 UNICODE_STRING str;
3977 ULONG hash;
3978 int i;
3980 if (!(actctx->sections & ACTIVATABLE_CLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3982 if (!actctx->activatable_class_section)
3984 struct strsection_header *section;
3986 NTSTATUS status = build_activatable_class_section(actctx, &section);
3987 if (status) return status;
3989 if (InterlockedCompareExchangePointer((void**)&actctx->activatable_class_section, section, NULL))
3990 RtlFreeHeap(GetProcessHeap(), 0, section);
3993 hash = 0;
3994 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3995 iter = get_activatable_class_first_index(actctx);
3997 for (i = 0; i < actctx->activatable_class_section->count; i++)
3999 if (iter->hash == hash)
4001 str.Buffer = (WCHAR *)((BYTE *)actctx->activatable_class_section + iter->name_offset);
4002 str.Length = iter->name_len;
4003 if (RtlEqualUnicodeString( &str, name, TRUE ))
4005 index = iter;
4006 break;
4008 else
4009 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
4011 iter++;
4014 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4016 if (data)
4018 class = get_activatable_class_data(actctx, index);
4020 data->ulDataFormatVersion = 1;
4021 data->lpData = class;
4022 /* full length includes string length with nulls */
4023 data->ulLength = class->size + class->module_len + sizeof(WCHAR);
4024 data->lpSectionGlobalData = (BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->global_offset;
4025 data->ulSectionGlobalDataLength = actctx->activatable_class_section->global_len;
4026 data->lpSectionBase = actctx->activatable_class_section;
4027 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->activatable_class_section );
4028 data->hActCtx = NULL;
4030 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4031 data->ulAssemblyRosterIndex = index->rosterindex;
4034 return STATUS_SUCCESS;
4037 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4039 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
4040 struct guidsection_header *header;
4041 ULONG module_offset, data_offset;
4042 struct tlibredirect_data *data;
4043 struct guid_index *index;
4045 /* compute section length */
4046 for (i = 0; i < actctx->num_assemblies; i++)
4048 struct assembly *assembly = &actctx->assemblies[i];
4049 for (j = 0; j < assembly->num_dlls; j++)
4051 struct dll_redirect *dll = &assembly->dlls[j];
4052 for (k = 0; k < dll->entities.num; k++)
4054 struct entity *entity = &dll->entities.base[k];
4055 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4057 /* each entry needs index, data and string data for module name and help string */
4058 total_len += sizeof(*index);
4059 total_len += sizeof(*data);
4060 /* help string is stored separately */
4061 if (*entity->u.typelib.helpdir)
4062 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
4064 /* module names are packed one after another */
4065 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4067 tlib_count++;
4073 total_len += aligned_string_len(names_len);
4074 total_len += sizeof(*header);
4076 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4077 if (!header) return STATUS_NO_MEMORY;
4079 memset(header, 0, sizeof(*header));
4080 header->magic = GUIDSECTION_MAGIC;
4081 header->size = sizeof(*header);
4082 header->count = tlib_count;
4083 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4084 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4085 module_offset = sizeof(*header);
4086 data_offset = header->index_offset + tlib_count*sizeof(*index);
4088 for (i = 0; i < actctx->num_assemblies; i++)
4090 struct assembly *assembly = &actctx->assemblies[i];
4091 for (j = 0; j < assembly->num_dlls; j++)
4093 struct dll_redirect *dll = &assembly->dlls[j];
4094 for (k = 0; k < dll->entities.num; k++)
4096 struct entity *entity = &dll->entities.base[k];
4097 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4099 ULONG module_len, help_len;
4100 UNICODE_STRING str;
4101 WCHAR *ptrW;
4103 if (*entity->u.typelib.helpdir)
4104 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
4105 else
4106 help_len = 0;
4108 module_len = wcslen(dll->name)*sizeof(WCHAR);
4110 /* setup new index entry */
4111 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
4112 RtlGUIDFromString(&str, &index->guid);
4113 index->data_offset = data_offset;
4114 index->data_len = sizeof(*data) + aligned_string_len(help_len);
4115 index->rosterindex = i + 1;
4117 /* setup data */
4118 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
4119 data->size = sizeof(*data);
4120 data->res = 0;
4121 data->name_len = module_len;
4122 data->name_offset = module_offset;
4123 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
4124 data->langid = 0;
4125 data->flags = entity->u.typelib.flags;
4126 data->help_len = help_len;
4127 data->help_offset = sizeof(*data);
4128 data->major_version = entity->u.typelib.major;
4129 data->minor_version = entity->u.typelib.minor;
4131 /* module name */
4132 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
4133 memcpy(ptrW, dll->name, data->name_len);
4134 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4136 /* help string */
4137 if (data->help_len)
4139 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
4140 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
4141 ptrW[data->help_len/sizeof(WCHAR)] = 0;
4144 data_offset += sizeof(*data);
4145 if (help_len)
4146 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
4148 module_offset += module_len + sizeof(WCHAR);
4150 index++;
4156 *section = header;
4158 return STATUS_SUCCESS;
4161 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4163 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
4166 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4168 struct guid_index *index = NULL;
4169 struct tlibredirect_data *tlib;
4171 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4173 if (!actctx->tlib_section)
4175 struct guidsection_header *section;
4177 NTSTATUS status = build_tlib_section(actctx, &section);
4178 if (status) return status;
4180 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
4181 RtlFreeHeap(GetProcessHeap(), 0, section);
4184 index = find_guid_index(actctx->tlib_section, guid);
4185 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4187 tlib = get_tlib_data(actctx, index);
4189 data->ulDataFormatVersion = 1;
4190 data->lpData = tlib;
4191 /* full length includes string length with nulls */
4192 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
4193 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
4194 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
4195 data->lpSectionBase = actctx->tlib_section;
4196 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
4197 data->hActCtx = NULL;
4199 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4200 data->ulAssemblyRosterIndex = index->rosterindex;
4202 return STATUS_SUCCESS;
4205 static void generate_uuid(ULONG *seed, GUID *guid)
4207 ULONG *ptr = (ULONG*)guid;
4208 int i;
4210 /* GUID is 16 bytes long */
4211 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
4212 *ptr = RtlUniform(seed);
4214 guid->Data3 &= 0x0fff;
4215 guid->Data3 |= (4 << 12);
4216 guid->Data4[0] &= 0x3f;
4217 guid->Data4[0] |= 0x80;
4220 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4221 unsigned int *count, unsigned int *len, unsigned int *module_len)
4223 unsigned int i;
4225 for (i = 0; i < entities->num; i++)
4227 struct entity *entity = &entities->base[i];
4228 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4230 /* each entry needs two index entries, extra one goes for alias GUID */
4231 *len += 2*sizeof(struct guid_index);
4232 /* To save some memory we don't allocated two data structures,
4233 instead alias index and normal index point to the same data structure. */
4234 *len += sizeof(struct comclassredirect_data);
4236 /* for clrClass store some more */
4237 if (entity->u.comclass.name)
4239 unsigned int str_len;
4241 /* all string data is stored together in aligned block */
4242 str_len = wcslen(entity->u.comclass.name)+1;
4243 if (entity->u.comclass.progid)
4244 str_len += wcslen(entity->u.comclass.progid)+1;
4245 if (entity->u.comclass.version)
4246 str_len += wcslen(entity->u.comclass.version)+1;
4248 *len += sizeof(struct clrclass_data);
4249 *len += aligned_string_len(str_len*sizeof(WCHAR));
4251 /* module name is forced to mscoree.dll, and stored two times with different case */
4252 *module_len += sizeof(L"MSCOREE.DLL") + sizeof(L"mscoree.dll");
4254 else
4256 /* progid string is stored separately */
4257 if (entity->u.comclass.progid)
4258 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4260 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4263 *count += 1;
4268 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4269 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4270 ULONG *seed, ULONG rosterindex)
4272 unsigned int i;
4274 for (i = 0; i < entities->num; i++)
4276 struct entity *entity = &entities->base[i];
4277 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4279 ULONG module_len, progid_len, str_len = 0, miscmask;
4280 struct comclassredirect_data *data;
4281 struct guid_index *alias_index;
4282 struct clrclass_data *clrdata;
4283 UNICODE_STRING str;
4284 WCHAR *ptrW;
4286 if (entity->u.comclass.progid)
4287 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4288 else
4289 progid_len = 0;
4291 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4293 /* setup new index entry */
4294 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4295 RtlGUIDFromString(&str, &(*index)->guid);
4297 (*index)->data_offset = *data_offset;
4298 (*index)->data_len = sizeof(*data); /* additional length added later */
4299 (*index)->rosterindex = rosterindex;
4301 /* Setup new index entry for alias guid. Alias index records are placed after
4302 normal records, so normal guids are hit first on search. Note that class count
4303 is doubled. */
4304 alias_index = (*index) + section->count/2;
4305 generate_uuid(seed, &alias_index->guid);
4306 alias_index->data_offset = (*index)->data_offset;
4307 alias_index->data_len = 0;
4308 alias_index->rosterindex = (*index)->rosterindex;
4310 /* setup data */
4311 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4312 data->size = sizeof(*data);
4313 data->model = entity->u.comclass.model;
4314 data->clsid = (*index)->guid;
4315 data->alias = alias_index->guid;
4316 data->clsid2 = data->clsid;
4317 if (entity->u.comclass.tlbid)
4319 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4320 RtlGUIDFromString(&str, &data->tlbid);
4322 else
4323 memset(&data->tlbid, 0, sizeof(data->tlbid));
4324 data->name_len = module_len;
4325 data->name_offset = *module_offset;
4326 data->progid_len = progid_len;
4327 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4328 data->clrdata_len = 0; /* will be set later */
4329 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4330 data->miscstatus = entity->u.comclass.miscstatus;
4331 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4332 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4333 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4334 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4336 /* mask describes which misc* data is available */
4337 miscmask = 0;
4338 if (data->miscstatus)
4339 miscmask |= MiscStatus;
4340 if (data->miscstatuscontent)
4341 miscmask |= MiscStatusContent;
4342 if (data->miscstatusthumbnail)
4343 miscmask |= MiscStatusThumbnail;
4344 if (data->miscstatusicon)
4345 miscmask |= MiscStatusIcon;
4346 if (data->miscstatusdocprint)
4347 miscmask |= MiscStatusDocPrint;
4348 data->flags = miscmask << 8;
4350 if (data->clrdata_offset)
4352 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4354 clrdata->size = sizeof(*clrdata);
4355 clrdata->res[0] = 0;
4356 clrdata->res[1] = 2; /* FIXME: unknown field */
4357 clrdata->module_len = wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4358 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4359 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4360 clrdata->name_offset = clrdata->size;
4361 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4362 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4363 clrdata->res2[0] = 0;
4364 clrdata->res2[1] = 0;
4366 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4368 /* module name */
4369 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4370 memcpy(ptrW, L"mscoree.dll", clrdata->module_len);
4371 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4373 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4374 memcpy(ptrW, L"MSCOREE.DLL", data->name_len);
4375 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4377 /* class name */
4378 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4379 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4380 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4382 /* runtime version, optional */
4383 if (clrdata->version_len)
4385 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4387 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4388 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4389 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4392 if (data->progid_len)
4393 data->progid_offset += data->clrdata_len;
4394 (*index)->data_len += sizeof(*clrdata);
4396 else
4398 clrdata = NULL;
4400 /* module name */
4401 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4402 memcpy(ptrW, dll->name, data->name_len);
4403 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4406 /* progid string */
4407 if (data->progid_len)
4409 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4410 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4411 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4414 /* string block length */
4415 str_len = 0;
4416 if (clrdata)
4418 str_len += clrdata->name_len + sizeof(WCHAR);
4419 if (clrdata->version_len)
4420 str_len += clrdata->version_len + sizeof(WCHAR);
4422 if (progid_len)
4423 str_len += progid_len + sizeof(WCHAR);
4425 (*index)->data_len += aligned_string_len(str_len);
4426 alias_index->data_len = (*index)->data_len;
4428 /* move to next data record */
4429 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4430 (*module_offset) += module_len + sizeof(WCHAR);
4432 if (clrdata)
4434 (*data_offset) += sizeof(*clrdata);
4435 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4437 (*index) += 1;
4442 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4444 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4445 struct guidsection_header *header;
4446 ULONG module_offset, data_offset;
4447 struct guid_index *index;
4448 ULONG seed;
4450 /* compute section length */
4451 for (i = 0; i < actctx->num_assemblies; i++)
4453 struct assembly *assembly = &actctx->assemblies[i];
4454 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4455 for (j = 0; j < assembly->num_dlls; j++)
4457 struct dll_redirect *dll = &assembly->dlls[j];
4458 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4462 total_len += aligned_string_len(names_len);
4463 total_len += sizeof(*header);
4465 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4466 if (!header) return STATUS_NO_MEMORY;
4468 memset(header, 0, sizeof(*header));
4469 header->magic = GUIDSECTION_MAGIC;
4470 header->size = sizeof(*header);
4471 header->count = 2*class_count;
4472 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4473 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4474 module_offset = sizeof(*header);
4475 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4477 seed = NtGetTickCount();
4478 for (i = 0; i < actctx->num_assemblies; i++)
4480 struct assembly *assembly = &actctx->assemblies[i];
4481 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4482 for (j = 0; j < assembly->num_dlls; j++)
4484 struct dll_redirect *dll = &assembly->dlls[j];
4485 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4489 *section = header;
4491 return STATUS_SUCCESS;
4494 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4496 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4499 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4501 struct comclassredirect_data *comclass;
4502 struct guid_index *index = NULL;
4504 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4506 if (!actctx->comserver_section)
4508 struct guidsection_header *section;
4510 NTSTATUS status = build_comserver_section(actctx, &section);
4511 if (status) return status;
4513 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4514 RtlFreeHeap(GetProcessHeap(), 0, section);
4517 index = find_guid_index(actctx->comserver_section, guid);
4518 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4520 comclass = get_comclass_data(actctx, index);
4522 data->ulDataFormatVersion = 1;
4523 data->lpData = comclass;
4524 /* full length includes string length with nulls */
4525 data->ulLength = comclass->size + comclass->clrdata_len;
4526 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4527 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4528 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4529 data->lpSectionBase = actctx->comserver_section;
4530 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4531 data->hActCtx = NULL;
4533 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4534 data->ulAssemblyRosterIndex = index->rosterindex;
4536 return STATUS_SUCCESS;
4539 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4541 unsigned int i;
4543 for (i = 0; i < entities->num; i++)
4545 struct entity *entity = &entities->base[i];
4546 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4548 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4549 if (entity->u.ifaceps.name)
4550 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4551 *count += 1;
4556 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4557 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4559 unsigned int i;
4561 for (i = 0; i < entities->num; i++)
4563 struct entity *entity = &entities->base[i];
4564 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4566 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4567 UNICODE_STRING str;
4568 ULONG name_len;
4570 if (entity->u.ifaceps.name)
4571 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4572 else
4573 name_len = 0;
4575 /* setup index */
4576 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4577 RtlGUIDFromString(&str, &(*index)->guid);
4578 (*index)->data_offset = *data_offset;
4579 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4580 (*index)->rosterindex = rosterindex;
4582 /* setup data record */
4583 data->size = sizeof(*data);
4584 data->mask = entity->u.ifaceps.mask;
4586 /* proxyStubClsid32 value is only stored for external PS,
4587 if set it's used as iid, otherwise 'iid' attribute value is used */
4588 if (entity->u.ifaceps.ps32)
4590 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4591 RtlGUIDFromString(&str, &data->iid);
4593 else
4594 data->iid = (*index)->guid;
4596 data->nummethods = entity->u.ifaceps.nummethods;
4598 if (entity->u.ifaceps.tlib)
4600 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4601 RtlGUIDFromString(&str, &data->tlbid);
4603 else
4604 memset(&data->tlbid, 0, sizeof(data->tlbid));
4606 if (entity->u.ifaceps.base)
4608 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4609 RtlGUIDFromString(&str, &data->base);
4611 else
4612 memset(&data->base, 0, sizeof(data->base));
4614 data->name_len = name_len;
4615 data->name_offset = data->name_len ? sizeof(*data) : 0;
4617 /* name string */
4618 if (data->name_len)
4620 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4621 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4622 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4625 /* move to next record */
4626 (*index) += 1;
4627 *data_offset += sizeof(*data);
4628 if (data->name_len)
4629 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4634 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4636 unsigned int i, j, total_len = 0, count = 0;
4637 struct guidsection_header *header;
4638 struct guid_index *index;
4639 ULONG data_offset;
4641 /* compute section length */
4642 for (i = 0; i < actctx->num_assemblies; i++)
4644 struct assembly *assembly = &actctx->assemblies[i];
4646 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4647 for (j = 0; j < assembly->num_dlls; j++)
4649 struct dll_redirect *dll = &assembly->dlls[j];
4650 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4654 total_len += sizeof(*header);
4656 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4657 if (!header) return STATUS_NO_MEMORY;
4659 memset(header, 0, sizeof(*header));
4660 header->magic = GUIDSECTION_MAGIC;
4661 header->size = sizeof(*header);
4662 header->count = count;
4663 header->index_offset = sizeof(*header);
4664 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4665 data_offset = header->index_offset + count*sizeof(*index);
4667 for (i = 0; i < actctx->num_assemblies; i++)
4669 struct assembly *assembly = &actctx->assemblies[i];
4671 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4672 for (j = 0; j < assembly->num_dlls; j++)
4674 struct dll_redirect *dll = &assembly->dlls[j];
4675 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4679 *section = header;
4681 return STATUS_SUCCESS;
4684 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4686 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4689 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4691 struct ifacepsredirect_data *iface;
4692 struct guid_index *index = NULL;
4694 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4696 if (!actctx->ifaceps_section)
4698 struct guidsection_header *section;
4700 NTSTATUS status = build_ifaceps_section(actctx, &section);
4701 if (status) return status;
4703 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4704 RtlFreeHeap(GetProcessHeap(), 0, section);
4707 index = find_guid_index(actctx->ifaceps_section, guid);
4708 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4710 iface = get_ifaceps_data(actctx, index);
4712 data->ulDataFormatVersion = 1;
4713 data->lpData = iface;
4714 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4715 data->lpSectionGlobalData = NULL;
4716 data->ulSectionGlobalDataLength = 0;
4717 data->lpSectionBase = actctx->ifaceps_section;
4718 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4719 data->hActCtx = NULL;
4721 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4722 data->ulAssemblyRosterIndex = index->rosterindex;
4724 return STATUS_SUCCESS;
4727 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4729 unsigned int i, j, total_len = 0, count = 0;
4730 struct guidsection_header *header;
4731 struct clrsurrogate_data *data;
4732 struct guid_index *index;
4733 ULONG data_offset;
4735 /* compute section length */
4736 for (i = 0; i < actctx->num_assemblies; i++)
4738 struct assembly *assembly = &actctx->assemblies[i];
4739 for (j = 0; j < assembly->entities.num; j++)
4741 struct entity *entity = &assembly->entities.base[j];
4742 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4744 ULONG len;
4746 total_len += sizeof(*index) + sizeof(*data);
4747 len = wcslen(entity->u.clrsurrogate.name) + 1;
4748 if (entity->u.clrsurrogate.version)
4749 len += wcslen(entity->u.clrsurrogate.version) + 1;
4750 total_len += aligned_string_len(len*sizeof(WCHAR));
4752 count++;
4757 total_len += sizeof(*header);
4759 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4760 if (!header) return STATUS_NO_MEMORY;
4762 memset(header, 0, sizeof(*header));
4763 header->magic = GUIDSECTION_MAGIC;
4764 header->size = sizeof(*header);
4765 header->count = count;
4766 header->index_offset = sizeof(*header);
4767 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4768 data_offset = header->index_offset + count*sizeof(*index);
4770 for (i = 0; i < actctx->num_assemblies; i++)
4772 struct assembly *assembly = &actctx->assemblies[i];
4773 for (j = 0; j < assembly->entities.num; j++)
4775 struct entity *entity = &assembly->entities.base[j];
4776 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4778 ULONG version_len, name_len;
4779 UNICODE_STRING str;
4780 WCHAR *ptrW;
4782 if (entity->u.clrsurrogate.version)
4783 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4784 else
4785 version_len = 0;
4786 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4788 /* setup new index entry */
4789 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4790 RtlGUIDFromString(&str, &index->guid);
4792 index->data_offset = data_offset;
4793 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4794 index->rosterindex = i + 1;
4796 /* setup data */
4797 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4798 data->size = sizeof(*data);
4799 data->res = 0;
4800 data->clsid = index->guid;
4801 data->version_offset = version_len ? data->size : 0;
4802 data->version_len = version_len;
4803 data->name_offset = data->size + version_len;
4804 if (version_len)
4805 data->name_offset += sizeof(WCHAR);
4806 data->name_len = name_len;
4808 /* surrogate name */
4809 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4810 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4811 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4813 /* runtime version */
4814 if (data->version_len)
4816 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4817 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4818 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4821 data_offset += index->data_offset;
4822 index++;
4827 *section = header;
4829 return STATUS_SUCCESS;
4832 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4834 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4837 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4839 struct clrsurrogate_data *surrogate;
4840 struct guid_index *index = NULL;
4842 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4844 if (!actctx->clrsurrogate_section)
4846 struct guidsection_header *section;
4848 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4849 if (status) return status;
4851 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4852 RtlFreeHeap(GetProcessHeap(), 0, section);
4855 index = find_guid_index(actctx->clrsurrogate_section, guid);
4856 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4858 surrogate = get_surrogate_data(actctx, index);
4860 data->ulDataFormatVersion = 1;
4861 data->lpData = surrogate;
4862 /* full length includes string length with nulls */
4863 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4864 if (surrogate->version_len)
4865 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4867 data->lpSectionGlobalData = NULL;
4868 data->ulSectionGlobalDataLength = 0;
4869 data->lpSectionBase = actctx->clrsurrogate_section;
4870 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4871 data->hActCtx = NULL;
4873 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4874 data->ulAssemblyRosterIndex = index->rosterindex;
4876 return STATUS_SUCCESS;
4879 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4881 unsigned int i, j, single_len;
4883 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4884 for (i = 0; i < entities->num; i++)
4886 struct entity *entity = &entities->base[i];
4887 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4889 if (entity->u.comclass.progid)
4891 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4892 *count += 1;
4895 for (j = 0; j < entity->u.comclass.progids.num; j++)
4896 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4898 *total_len += single_len*entity->u.comclass.progids.num;
4899 *count += entity->u.comclass.progids.num;
4904 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4905 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4907 struct progidredirect_data *data;
4908 UNICODE_STRING str;
4909 GUID *guid_ptr;
4910 WCHAR *ptrW;
4912 /* setup new index entry */
4914 /* hash progid name */
4915 RtlInitUnicodeString(&str, progid);
4916 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4918 (*index)->name_offset = *data_offset;
4919 (*index)->name_len = str.Length;
4920 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4921 (*index)->data_len = sizeof(*data);
4922 (*index)->rosterindex = rosterindex;
4924 *data_offset += aligned_string_len(str.MaximumLength);
4926 /* setup data structure */
4927 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4928 data->size = sizeof(*data);
4929 data->reserved = 0;
4930 data->clsid_offset = *global_offset;
4932 /* write progid string */
4933 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4934 memcpy(ptrW, progid, (*index)->name_len);
4935 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4937 /* write guid to global area */
4938 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4939 *guid_ptr = *alias;
4941 /* to next entry */
4942 *global_offset += sizeof(GUID);
4943 *data_offset += data->size;
4944 (*index) += 1;
4947 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4948 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4950 unsigned int i, j;
4952 for (i = 0; i < entities->num; i++)
4954 struct entity *entity = &entities->base[i];
4955 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4957 const struct progids *progids = &entity->u.comclass.progids;
4958 struct comclassredirect_data *comclass;
4959 struct guid_index *guid_index;
4960 UNICODE_STRING str;
4961 GUID clsid;
4963 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4964 RtlGUIDFromString(&str, &clsid);
4966 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4967 comclass = get_comclass_data(actctx, guid_index);
4969 if (entity->u.comclass.progid)
4970 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4971 index, data_offset, global_offset, rosterindex);
4973 for (j = 0; j < progids->num; j++)
4974 write_progid_record(section, progids->progids[j], &comclass->alias,
4975 index, data_offset, global_offset, rosterindex);
4980 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4982 unsigned int i, j, total_len = 0, count = 0;
4983 struct strsection_header *header;
4984 ULONG data_offset, global_offset;
4985 struct string_index *index;
4987 /* compute section length */
4988 for (i = 0; i < actctx->num_assemblies; i++)
4990 struct assembly *assembly = &actctx->assemblies[i];
4992 get_progid_datalen(&assembly->entities, &count, &total_len);
4993 for (j = 0; j < assembly->num_dlls; j++)
4995 struct dll_redirect *dll = &assembly->dlls[j];
4996 get_progid_datalen(&dll->entities, &count, &total_len);
5000 total_len += sizeof(*header);
5002 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
5003 if (!header) return STATUS_NO_MEMORY;
5005 memset(header, 0, sizeof(*header));
5006 header->magic = STRSECTION_MAGIC;
5007 header->size = sizeof(*header);
5008 header->count = count;
5009 header->global_offset = header->size;
5010 header->global_len = count*sizeof(GUID);
5011 header->index_offset = header->size + header->global_len;
5013 index = (struct string_index*)((BYTE*)header + header->index_offset);
5014 data_offset = header->index_offset + count*sizeof(*index);
5015 global_offset = header->global_offset;
5017 for (i = 0; i < actctx->num_assemblies; i++)
5019 struct assembly *assembly = &actctx->assemblies[i];
5021 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
5022 for (j = 0; j < assembly->num_dlls; j++)
5024 struct dll_redirect *dll = &assembly->dlls[j];
5025 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
5029 *section = header;
5031 return STATUS_SUCCESS;
5034 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
5036 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
5039 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
5040 PACTCTX_SECTION_KEYED_DATA data)
5042 struct progidredirect_data *progid;
5043 struct string_index *index;
5045 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
5047 if (!actctx->comserver_section)
5049 struct guidsection_header *section;
5051 NTSTATUS status = build_comserver_section(actctx, &section);
5052 if (status) return status;
5054 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
5055 RtlFreeHeap(GetProcessHeap(), 0, section);
5058 if (!actctx->progid_section)
5060 struct strsection_header *section;
5062 NTSTATUS status = build_progid_section(actctx, &section);
5063 if (status) return status;
5065 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
5066 RtlFreeHeap(GetProcessHeap(), 0, section);
5069 index = find_string_index(actctx->progid_section, name);
5070 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
5072 if (data)
5074 progid = get_progid_data(actctx, index);
5076 data->ulDataFormatVersion = 1;
5077 data->lpData = progid;
5078 data->ulLength = progid->size;
5079 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
5080 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
5081 data->lpSectionBase = actctx->progid_section;
5082 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
5083 data->hActCtx = NULL;
5085 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
5086 data->ulAssemblyRosterIndex = index->rosterindex;
5089 return STATUS_SUCCESS;
5092 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5093 const UNICODE_STRING *section_name,
5094 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5096 NTSTATUS status;
5098 switch (section_kind)
5100 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
5101 status = find_dll_redirection(actctx, section_name, data);
5102 break;
5103 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
5104 status = find_window_class(actctx, section_name, data);
5105 break;
5106 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
5107 status = find_progid_redirection(actctx, section_name, data);
5108 break;
5109 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
5110 FIXME("Unsupported yet section_kind %lx\n", section_kind);
5111 return STATUS_SXS_SECTION_NOT_FOUND;
5112 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES:
5113 status = find_activatable_class(actctx, section_name, data);
5114 break;
5115 default:
5116 WARN("Unknown section_kind %lx\n", section_kind);
5117 return STATUS_SXS_SECTION_NOT_FOUND;
5120 if (status != STATUS_SUCCESS) return status;
5122 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
5124 actctx_addref(actctx);
5125 data->hActCtx = actctx;
5127 return STATUS_SUCCESS;
5130 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5131 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5133 NTSTATUS status;
5135 switch (section_kind)
5137 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
5138 status = find_tlib_redirection(actctx, guid, data);
5139 break;
5140 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
5141 status = find_comserver_redirection(actctx, guid, data);
5142 break;
5143 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
5144 status = find_cominterface_redirection(actctx, guid, data);
5145 break;
5146 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
5147 status = find_clr_surrogate(actctx, guid, data);
5148 break;
5149 default:
5150 WARN("Unknown section_kind %lx\n", section_kind);
5151 return STATUS_SXS_SECTION_NOT_FOUND;
5154 if (status != STATUS_SUCCESS) return status;
5156 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5158 actctx_addref(actctx);
5159 data->hActCtx = actctx;
5161 return STATUS_SUCCESS;
5164 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
5166 unsigned int i, j;
5168 for (i = 0; i < actctx->num_assemblies; i++)
5170 struct assembly *assembly = &actctx->assemblies[i];
5171 for (j = 0; j < assembly->entities.num; j++)
5173 struct entity *entity = &assembly->entities.base[j];
5174 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
5175 !wcscmp( entity->u.settings.name, settings ) &&
5176 !wcscmp( entity->u.settings.ns, ns ))
5177 return entity->u.settings.value;
5180 return NULL;
5183 /* initialize the activation context for the current process */
5184 void actctx_init(void)
5186 ACTCTXW ctx;
5187 HANDLE handle;
5189 ctx.cbSize = sizeof(ctx);
5190 ctx.lpSource = NULL;
5191 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
5192 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
5193 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
5195 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
5197 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
5201 /***********************************************************************
5202 * RtlCreateActivationContext (NTDLL.@)
5204 * Create an activation context.
5206 * FIXME: function signature/prototype is wrong
5208 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
5210 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
5211 const WCHAR *directory = NULL;
5212 ACTIVATION_CONTEXT *actctx;
5213 UNICODE_STRING nameW;
5214 ULONG lang = 0;
5215 NTSTATUS status = STATUS_NO_MEMORY;
5216 HANDLE file = 0;
5217 struct actctx_loader acl;
5219 TRACE("%p %08lx\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
5221 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5222 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5223 return STATUS_INVALID_PARAMETER;
5225 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
5226 return STATUS_NO_MEMORY;
5228 actctx->magic = ACTCTX_MAGIC;
5229 actctx->ref_count = 1;
5230 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5231 actctx->config.info = NULL;
5232 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5233 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5235 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5237 else
5239 UNICODE_STRING dir;
5240 WCHAR *p;
5241 HMODULE module;
5243 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5244 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
5246 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5247 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5248 actctx->appdir.info = dir.Buffer;
5251 nameW.Buffer = NULL;
5253 /* open file only if it's going to be used */
5254 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5255 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5257 WCHAR *source = NULL;
5258 BOOLEAN ret;
5260 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5261 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5263 DWORD dir_len, source_len;
5265 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5266 source_len = wcslen(pActCtx->lpSource);
5267 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5269 status = STATUS_NO_MEMORY;
5270 goto error;
5273 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5274 source[dir_len] = '\\';
5275 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5278 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5279 RtlFreeHeap( GetProcessHeap(), 0, source );
5280 if (!ret)
5282 status = STATUS_NO_SUCH_FILE;
5283 goto error;
5285 status = open_nt_file( &file, &nameW );
5286 if (status)
5288 RtlFreeUnicodeString( &nameW );
5289 goto error;
5293 acl.actctx = actctx;
5294 acl.dependencies = NULL;
5295 acl.num_dependencies = 0;
5296 acl.allocated_dependencies = 0;
5298 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5299 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5301 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5303 /* if we have a resource it's a PE file */
5304 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5306 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5307 pActCtx->lpResourceName, lang );
5308 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5309 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5310 pActCtx->hModule, pActCtx->lpResourceName );
5312 else if (pActCtx->lpSource)
5314 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5315 file, pActCtx->lpResourceName, lang );
5316 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5317 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5318 NULL, pActCtx->lpResourceName );
5320 else status = STATUS_INVALID_PARAMETER;
5322 else
5324 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5327 if (file) NtClose( file );
5328 RtlFreeUnicodeString( &nameW );
5330 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5331 free_depend_manifests( &acl );
5333 if (status == STATUS_SUCCESS) *handle = actctx;
5334 else actctx_release( actctx );
5335 return status;
5337 error:
5338 if (file) NtClose( file );
5339 actctx_release( actctx );
5340 return status;
5344 /***********************************************************************
5345 * RtlAddRefActivationContext (NTDLL.@)
5347 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5349 ACTIVATION_CONTEXT *actctx;
5351 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5355 /******************************************************************
5356 * RtlReleaseActivationContext (NTDLL.@)
5358 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5360 ACTIVATION_CONTEXT *actctx;
5362 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5365 /******************************************************************
5366 * RtlZombifyActivationContext (NTDLL.@)
5368 * FIXME: function prototype might be wrong
5370 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5372 FIXME("%p: stub\n", handle);
5373 return STATUS_NOT_IMPLEMENTED;
5376 /******************************************************************
5377 * RtlActivateActivationContext (NTDLL.@)
5379 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5381 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5385 /******************************************************************
5386 * RtlActivateActivationContextEx (NTDLL.@)
5388 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5390 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5392 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5393 return STATUS_NO_MEMORY;
5395 frame->Previous = teb->ActivationContextStack.ActiveFrame;
5396 frame->ActivationContext = handle;
5397 frame->Flags = 0;
5398 teb->ActivationContextStack.ActiveFrame = frame;
5399 RtlAddRefActivationContext( handle );
5401 *cookie = (ULONG_PTR)frame;
5402 TRACE( "%p cookie=%Ix\n", handle, *cookie );
5403 return STATUS_SUCCESS;
5407 /***********************************************************************
5408 * RtlDeactivateActivationContext (NTDLL.@)
5410 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5412 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5414 TRACE( "%lx cookie=%Ix\n", flags, cookie );
5416 /* find the right frame */
5417 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5418 for (frame = top; frame; frame = frame->Previous)
5419 if ((ULONG_PTR)frame == cookie) break;
5421 if (!frame)
5422 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5424 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5425 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5427 /* pop everything up to and including frame */
5428 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5430 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5432 frame = top->Previous;
5433 RtlReleaseActivationContext( top->ActivationContext );
5434 RtlFreeHeap( GetProcessHeap(), 0, top );
5435 top = frame;
5440 /******************************************************************
5441 * RtlFreeThreadActivationContextStack (NTDLL.@)
5443 void WINAPI RtlFreeThreadActivationContextStack(void)
5445 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5447 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5448 while (frame)
5450 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5451 RtlReleaseActivationContext( frame->ActivationContext );
5452 RtlFreeHeap( GetProcessHeap(), 0, frame );
5453 frame = prev;
5455 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5459 /******************************************************************
5460 * RtlGetActiveActivationContext (NTDLL.@)
5462 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5464 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5466 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5467 RtlAddRefActivationContext( *handle );
5469 else
5470 *handle = 0;
5472 return STATUS_SUCCESS;
5476 /******************************************************************
5477 * RtlIsActivationContextActive (NTDLL.@)
5479 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5481 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5483 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5484 if (frame->ActivationContext == handle) return TRUE;
5485 return FALSE;
5489 /***********************************************************************
5490 * RtlQueryInformationActivationContext (NTDLL.@)
5492 * Get information about an activation context.
5493 * FIXME: function signature/prototype may be wrong
5495 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5496 ULONG class, PVOID buffer,
5497 SIZE_T bufsize, SIZE_T *retlen )
5499 ACTIVATION_CONTEXT *actctx;
5500 NTSTATUS status;
5502 TRACE("%08lx %p %p %lu %p %Id %p\n", flags, handle,
5503 subinst, class, buffer, bufsize, retlen);
5505 if (retlen) *retlen = 0;
5506 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5508 switch (class)
5510 case ActivationContextBasicInformation:
5512 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5514 if (retlen) *retlen = sizeof(*info);
5515 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5517 info->hActCtx = handle;
5518 info->dwFlags = 0; /* FIXME */
5519 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5521 break;
5523 case ActivationContextDetailedInformation:
5525 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5526 struct assembly *assembly = NULL;
5527 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5528 LPWSTR ptr;
5530 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5532 if (actctx->num_assemblies) assembly = actctx->assemblies;
5534 if (assembly && assembly->manifest.info)
5535 manifest_len = wcslen(assembly->manifest.info) + 1;
5536 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5537 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5538 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5540 if (retlen) *retlen = len;
5541 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5543 acdi->dwFlags = 0;
5544 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5545 acdi->ulAssemblyCount = actctx->num_assemblies;
5546 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5547 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5548 acdi->ulRootConfigurationPathType = actctx->config.type;
5549 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5550 acdi->ulAppDirPathType = actctx->appdir.type;
5551 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5552 ptr = (LPWSTR)(acdi + 1);
5553 if (manifest_len)
5555 acdi->lpRootManifestPath = ptr;
5556 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5557 ptr += manifest_len;
5559 else acdi->lpRootManifestPath = NULL;
5560 if (config_len)
5562 acdi->lpRootConfigurationPath = ptr;
5563 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5564 ptr += config_len;
5566 else acdi->lpRootConfigurationPath = NULL;
5567 if (appdir_len)
5569 acdi->lpAppDirPath = ptr;
5570 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5572 else acdi->lpAppDirPath = NULL;
5574 break;
5576 case AssemblyDetailedInformationInActivationContext:
5578 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5579 struct assembly *assembly;
5580 WCHAR *assembly_id;
5581 DWORD index;
5582 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5583 LPWSTR ptr;
5585 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5586 if (!subinst) return STATUS_INVALID_PARAMETER;
5588 index = *(DWORD*)subinst;
5589 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5591 assembly = &actctx->assemblies[index - 1];
5593 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5594 id_len = wcslen(assembly_id) + 1;
5595 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5597 if (assembly->manifest.info &&
5598 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5599 path_len = wcslen(assembly->manifest.info) + 1;
5601 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5603 if (retlen) *retlen = len;
5604 if (!buffer || bufsize < len)
5606 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5607 return STATUS_BUFFER_TOO_SMALL;
5610 afdi->ulFlags = 0; /* FIXME */
5611 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5612 afdi->ulManifestPathType = assembly->manifest.type;
5613 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5614 /* FIXME afdi->liManifestLastWriteTime = 0; */
5615 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5616 afdi->ulPolicyPathLength = 0;
5617 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5618 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5619 afdi->ulManifestVersionMajor = 1;
5620 afdi->ulManifestVersionMinor = 0;
5621 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5622 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5623 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5624 ptr = (LPWSTR)(afdi + 1);
5625 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5626 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5627 ptr += id_len;
5628 if (path_len)
5630 afdi->lpAssemblyManifestPath = ptr;
5631 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5632 ptr += path_len;
5633 } else afdi->lpAssemblyManifestPath = NULL;
5634 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5635 if (ad_len)
5637 afdi->lpAssemblyDirectoryName = ptr;
5638 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5640 else afdi->lpAssemblyDirectoryName = NULL;
5641 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5643 break;
5645 case FileInformationInAssemblyOfAssemblyInActivationContext:
5647 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5648 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5649 struct assembly *assembly;
5650 struct dll_redirect *dll;
5651 SIZE_T len, dll_len = 0;
5652 LPWSTR ptr;
5654 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5655 if (!acqi) return STATUS_INVALID_PARAMETER;
5657 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5658 return STATUS_INVALID_PARAMETER;
5659 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5661 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5662 return STATUS_INVALID_PARAMETER;
5663 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5665 if (dll->name) dll_len = wcslen(dll->name) + 1;
5666 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5668 if (!buffer || bufsize < len)
5670 if (retlen) *retlen = len;
5671 return STATUS_BUFFER_TOO_SMALL;
5673 if (retlen) *retlen = 0; /* yes that's what native does !! */
5674 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5675 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5676 afdi->ulPathLength = 0; /* FIXME */
5677 ptr = (LPWSTR)(afdi + 1);
5678 if (dll_len)
5680 afdi->lpFileName = ptr;
5681 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5682 } else afdi->lpFileName = NULL;
5683 afdi->lpFilePath = NULL; /* FIXME */
5685 break;
5687 case CompatibilityInformationInActivationContext:
5689 struct acci
5691 DWORD ElementCount;
5692 COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
5693 } *acci = buffer;
5694 struct assembly *assembly = NULL;
5695 ULONG num_compat_contexts = 0, n;
5696 SIZE_T len;
5698 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5700 if (actctx->num_assemblies) assembly = actctx->assemblies;
5702 if (assembly)
5703 num_compat_contexts = assembly->num_compat_contexts;
5704 len = offsetof( struct acci, Elements[num_compat_contexts] );
5706 if (retlen) *retlen = len;
5707 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5709 acci->ElementCount = num_compat_contexts;
5710 for (n = 0; n < num_compat_contexts; ++n)
5712 acci->Elements[n] = assembly->compat_contexts[n];
5715 break;
5717 case RunlevelInformationInActivationContext:
5719 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5720 struct assembly *assembly;
5721 SIZE_T len;
5723 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5725 len = sizeof(*acrli);
5726 if (retlen) *retlen = len;
5727 if (!buffer || bufsize < len)
5728 return STATUS_BUFFER_TOO_SMALL;
5730 assembly = actctx->assemblies;
5732 acrli->ulFlags = 0;
5733 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5734 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5736 break;
5738 default:
5739 FIXME( "class %lu not implemented\n", class );
5740 return STATUS_NOT_IMPLEMENTED;
5742 return STATUS_SUCCESS;
5745 /***********************************************************************
5746 * RtlFindActivationContextSectionString (NTDLL.@)
5748 * Find information about a string in an activation context.
5749 * FIXME: function signature/prototype may be wrong
5751 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5752 const UNICODE_STRING *section_name, PVOID ptr )
5754 PACTCTX_SECTION_KEYED_DATA data = ptr;
5755 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5757 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(guid), section_kind,
5758 debugstr_us(section_name), data);
5760 if (guid)
5762 FIXME("expected guid == NULL\n");
5763 return STATUS_INVALID_PARAMETER;
5765 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5767 FIXME("unknown flags %08lx\n", flags);
5768 return STATUS_INVALID_PARAMETER;
5770 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5771 !section_name || !section_name->Buffer)
5773 WARN("invalid parameter\n");
5774 return STATUS_INVALID_PARAMETER;
5777 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5779 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5780 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5783 if (status != STATUS_SUCCESS)
5784 status = find_string( process_actctx, section_kind, section_name, flags, data );
5786 return status;
5789 /***********************************************************************
5790 * RtlFindActivationContextSectionGuid (NTDLL.@)
5792 * Find information about a GUID in an activation context.
5793 * FIXME: function signature/prototype may be wrong
5795 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5796 const GUID *guid, void *ptr )
5798 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5799 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5801 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5803 if (extguid)
5805 FIXME("expected extguid == NULL\n");
5806 return STATUS_INVALID_PARAMETER;
5809 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5811 FIXME("unknown flags %08lx\n", flags);
5812 return STATUS_INVALID_PARAMETER;
5815 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5816 return STATUS_INVALID_PARAMETER;
5818 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5820 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5821 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5824 if (status != STATUS_SUCCESS)
5825 status = find_guid( process_actctx, section_kind, guid, flags, data );
5827 return status;
5831 /***********************************************************************
5832 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5834 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5835 const WCHAR *settings, WCHAR *buffer,
5836 SIZE_T size, SIZE_T *written )
5838 ACTIVATION_CONTEXT *actctx;
5839 const WCHAR *res;
5841 if (flags)
5843 WARN( "unknown flags %08lx\n", flags );
5844 return STATUS_INVALID_PARAMETER;
5847 if (ns)
5849 if (wcscmp( ns, windowsSettings2005NSW ) &&
5850 wcscmp( ns, windowsSettings2011NSW ) &&
5851 wcscmp( ns, windowsSettings2016NSW ) &&
5852 wcscmp( ns, windowsSettings2017NSW ) &&
5853 wcscmp( ns, windowsSettings2019NSW ) &&
5854 wcscmp( ns, windowsSettings2020NSW ))
5855 return STATUS_INVALID_PARAMETER;
5857 else ns = windowsSettings2005NSW;
5859 if (!handle) handle = process_actctx;
5860 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5862 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5864 if (written) *written = wcslen(res) + 1;
5865 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5866 wcscpy( buffer, res );
5867 return STATUS_SUCCESS;