d3d9: Create sub-resource surfaces manually.
[wine.git] / dlls / ntdll / actctx.c
blob54167a2db67b52f9476d10c8d8012100baaf8f77
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,
2929 FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT );
2932 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2933 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2934 HANDLE hModule, LPCWSTR resname, ULONG lang )
2936 NTSTATUS status;
2937 UNICODE_STRING nameW;
2938 LDR_RESOURCE_INFO info;
2939 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2940 void *ptr;
2942 if (TRACE_ON(actctx))
2944 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2946 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2947 hModule, debugstr_w(nameW.Buffer) );
2948 RtlFreeUnicodeString( &nameW );
2950 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2951 hModule, debugstr_w(filename) );
2954 if (!resname) return STATUS_INVALID_PARAMETER;
2956 info.Type = RT_MANIFEST;
2957 info.Language = lang;
2958 if (!((ULONG_PTR)resname >> 16))
2960 info.Name = (ULONG_PTR)resname;
2961 status = LdrFindResource_U(hModule, &info, 3, &entry);
2963 else if (resname[0] == '#')
2965 ULONG value;
2966 RtlInitUnicodeString(&nameW, resname + 1);
2967 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2968 return STATUS_INVALID_PARAMETER;
2969 info.Name = value;
2970 status = LdrFindResource_U(hModule, &info, 3, &entry);
2972 else
2974 RtlCreateUnicodeString(&nameW, resname);
2975 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2976 info.Name = (ULONG_PTR)nameW.Buffer;
2977 status = LdrFindResource_U(hModule, &info, 3, &entry);
2978 RtlFreeUnicodeString(&nameW);
2980 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2982 if (status == STATUS_SUCCESS)
2983 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2985 return status;
2988 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2989 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2990 HANDLE file, LPCWSTR resname, ULONG lang )
2992 HANDLE mapping;
2993 OBJECT_ATTRIBUTES attr;
2994 LARGE_INTEGER size;
2995 LARGE_INTEGER offset;
2996 NTSTATUS status;
2997 SIZE_T count;
2998 void *base;
3000 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
3002 attr.Length = sizeof(attr);
3003 attr.RootDirectory = 0;
3004 attr.ObjectName = NULL;
3005 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3006 attr.SecurityDescriptor = NULL;
3007 attr.SecurityQualityOfService = NULL;
3009 size.QuadPart = 0;
3010 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3011 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3012 if (status != STATUS_SUCCESS) return status;
3014 offset.QuadPart = 0;
3015 count = 0;
3016 base = NULL;
3017 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3018 &count, ViewShare, 0, PAGE_READONLY );
3019 NtClose( mapping );
3020 if (status != STATUS_SUCCESS) return status;
3022 if (RtlImageNtHeader(base)) /* we got a PE file */
3024 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3025 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3027 else status = STATUS_INVALID_IMAGE_FORMAT;
3029 NtUnmapViewOfSection( GetCurrentProcess(), base );
3030 return status;
3033 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3034 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3036 FILE_END_OF_FILE_INFORMATION info;
3037 IO_STATUS_BLOCK io;
3038 HANDLE mapping;
3039 OBJECT_ATTRIBUTES attr;
3040 LARGE_INTEGER size;
3041 LARGE_INTEGER offset;
3042 NTSTATUS status;
3043 SIZE_T count;
3044 void *base;
3046 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3048 attr.Length = sizeof(attr);
3049 attr.RootDirectory = 0;
3050 attr.ObjectName = NULL;
3051 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3052 attr.SecurityDescriptor = NULL;
3053 attr.SecurityQualityOfService = NULL;
3055 size.QuadPart = 0;
3056 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3057 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3058 if (status != STATUS_SUCCESS) return status;
3060 offset.QuadPart = 0;
3061 count = 0;
3062 base = NULL;
3063 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3064 &count, ViewShare, 0, PAGE_READONLY );
3065 NtClose( mapping );
3066 if (status != STATUS_SUCCESS) return status;
3068 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3069 if (status == STATUS_SUCCESS)
3070 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3072 NtUnmapViewOfSection( GetCurrentProcess(), base );
3073 return status;
3076 /* try to load the .manifest file associated to the file */
3077 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3078 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3080 WCHAR *buffer;
3081 NTSTATUS status;
3082 UNICODE_STRING nameW;
3083 HANDLE file;
3084 UINT resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3086 if (!((ULONG_PTR)resname >> 16)) resid = LOWORD(resname);
3088 TRACE( "looking for manifest associated with %s id %u\n", debugstr_w(filename), resid );
3090 if (module) /* use the module filename */
3092 UNICODE_STRING name;
3094 if (!(status = get_module_filename( module, &name, sizeof(L".manifest") + 10*sizeof(WCHAR) )))
3096 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, L".%u", resid );
3097 wcscat( name.Buffer, L".manifest" );
3098 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3099 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3100 RtlFreeUnicodeString( &name );
3102 if (status) return status;
3104 else
3106 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3107 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(L".manifest") )))
3108 return STATUS_NO_MEMORY;
3109 wcscpy( buffer, filename );
3110 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, L".%u", resid );
3111 wcscat( buffer, L".manifest" );
3112 RtlInitUnicodeString( &nameW, buffer );
3115 if (!open_nt_file( &file, &nameW ))
3117 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3118 NtClose( file );
3120 else status = STATUS_RESOURCE_NAME_NOT_FOUND;
3121 RtlFreeUnicodeString( &nameW );
3122 return status;
3125 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3127 static const WCHAR lookup_fmtW[] = L"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3128 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3130 WCHAR *lookup, *ret = NULL;
3131 UNICODE_STRING lookup_us;
3132 IO_STATUS_BLOCK io;
3133 const WCHAR *lang = ai->language;
3134 unsigned int data_pos = 0, data_len, len;
3135 char buffer[8192];
3137 if (!lang || !wcsicmp( lang, L"neutral" )) lang = L"*";
3139 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3140 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3141 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3142 ai->version.major, ai->version.minor, lang );
3143 RtlInitUnicodeString( &lookup_us, lookup );
3145 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3146 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3148 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3149 FILE_BOTH_DIR_INFORMATION *dir_info;
3150 WCHAR *tmp;
3151 ULONG build, revision;
3153 data_len = io.Information;
3155 for (;;)
3157 if (data_pos >= data_len)
3159 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3160 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3161 break;
3162 data_len = io.Information;
3163 data_pos = 0;
3165 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3167 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3168 else data_pos = data_len;
3170 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3171 build = wcstoul( tmp, NULL, 10 );
3172 if (build < min_build) continue;
3173 tmp = wcschr(tmp, '.') + 1;
3174 revision = wcstoul( tmp, NULL, 10 );
3175 if (build == min_build && revision < min_revision) continue;
3176 tmp = wcschr(tmp, '_') + 1;
3177 tmp = wcschr(tmp, '_') + 1;
3178 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3179 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3181 /* prefer a non-Wine manifest if we already have one */
3182 /* we'll still load the builtin dll if specified through DllOverrides */
3183 if (ret) continue;
3185 else
3187 min_build = build;
3188 min_revision = revision;
3190 ai->version.build = build;
3191 ai->version.revision = revision;
3192 RtlFreeHeap( GetProcessHeap(), 0, ret );
3193 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3195 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3196 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3200 else WARN("no matching file for %s\n", debugstr_w(lookup));
3201 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3202 return ret;
3205 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3207 struct assembly_identity sxs_ai;
3208 UNICODE_STRING path_us;
3209 OBJECT_ATTRIBUTES attr;
3210 IO_STATUS_BLOCK io;
3211 WCHAR *path, *file = NULL;
3212 HANDLE handle;
3214 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3216 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L"\\winsxs\\manifests") +
3217 wcslen(windows_dir) * sizeof(WCHAR) )))
3218 return STATUS_NO_MEMORY;
3220 wcscpy( path, windows_dir );
3221 wcscat( path, L"\\winsxs\\manifests" );
3223 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3225 RtlFreeHeap( GetProcessHeap(), 0, path );
3226 return STATUS_NO_SUCH_FILE;
3228 RtlFreeHeap( GetProcessHeap(), 0, path );
3230 attr.Length = sizeof(attr);
3231 attr.RootDirectory = 0;
3232 attr.Attributes = OBJ_CASE_INSENSITIVE;
3233 attr.ObjectName = &path_us;
3234 attr.SecurityDescriptor = NULL;
3235 attr.SecurityQualityOfService = NULL;
3237 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3238 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3240 sxs_ai = *ai;
3241 file = lookup_manifest_file( handle, &sxs_ai );
3242 NtClose( handle );
3244 if (!file)
3246 RtlFreeUnicodeString( &path_us );
3247 return STATUS_NO_SUCH_FILE;
3250 /* append file name to directory path */
3251 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3252 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3254 RtlFreeHeap( GetProcessHeap(), 0, file );
3255 RtlFreeUnicodeString( &path_us );
3256 return STATUS_NO_MEMORY;
3259 path[path_us.Length/sizeof(WCHAR)] = '\\';
3260 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3261 RtlInitUnicodeString( &path_us, path );
3262 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3264 if (!open_nt_file( &handle, &path_us ))
3266 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3267 NtClose( handle );
3269 else io.u.Status = STATUS_NO_SUCH_FILE;
3271 RtlFreeHeap( GetProcessHeap(), 0, file );
3272 RtlFreeUnicodeString( &path_us );
3273 return io.u.Status;
3276 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3277 struct assembly_identity* ai)
3279 unsigned int i;
3280 WCHAR *buffer, *p, *directory;
3281 NTSTATUS status;
3282 UNICODE_STRING nameW;
3283 HANDLE file;
3284 DWORD len;
3286 TRACE( "looking for name=%s version=%s arch=%s\n",
3287 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3289 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3291 /* FIXME: add support for language specific lookup */
3293 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3294 wcslen(acl->actctx->appdir.info));
3296 nameW.Buffer = NULL;
3297 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3298 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(L".manifest") )))
3299 return STATUS_NO_MEMORY;
3301 if (!(directory = build_assembly_dir( ai )))
3303 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3304 return STATUS_NO_MEMORY;
3307 /* Lookup in <dir>\name.dll
3308 * <dir>\name.manifest
3309 * <dir>\name\name.dll
3310 * <dir>\name\name.manifest
3312 * First 'appdir' is used as <dir>, if that failed
3313 * it tries application manifest file path.
3315 wcscpy( buffer, acl->actctx->appdir.info );
3316 p = buffer + wcslen(buffer);
3317 for (i = 0; i < 4; i++)
3319 if (i == 2)
3321 struct assembly *assembly = acl->actctx->assemblies;
3322 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3324 else *p++ = '\\';
3326 wcscpy( p, ai->name );
3327 p += wcslen(p);
3329 wcscpy( p, L".dll" );
3330 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3332 status = open_nt_file( &file, &nameW );
3333 if (!status)
3335 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3336 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3337 NtClose( file );
3338 if (status == STATUS_SUCCESS)
3339 break;
3341 RtlFreeUnicodeString( &nameW );
3344 wcscpy( p, L".manifest" );
3345 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3347 status = open_nt_file( &file, &nameW );
3348 if (!status)
3350 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3351 NtClose( file );
3352 break;
3354 RtlFreeUnicodeString( &nameW );
3356 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3358 RtlFreeUnicodeString( &nameW );
3359 RtlFreeHeap( GetProcessHeap(), 0, directory );
3360 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3361 return status;
3364 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3366 NTSTATUS status = STATUS_SUCCESS;
3367 unsigned int i;
3369 for (i = 0; i < acl->num_dependencies; i++)
3371 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3373 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3375 FIXME( "Could not find dependent assembly %s (%s)\n",
3376 debugstr_w(acl->dependencies[i].name),
3377 debugstr_version(&acl->dependencies[i].version) );
3378 status = STATUS_SXS_CANT_GEN_ACTCTX;
3379 break;
3383 /* FIXME should now iterate through all refs */
3384 return status;
3387 static HANDLE get_current_actctx_no_addref(void)
3389 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
3391 if (actctx_stack->ActiveFrame)
3392 return actctx_stack->ActiveFrame->ActivationContext;
3394 return NULL;
3397 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3398 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3400 NTSTATUS status = STATUS_SUCCESS;
3402 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3404 if (*handle) return STATUS_INVALID_PARAMETER;
3406 *handle = get_current_actctx_no_addref();
3408 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3410 ULONG_PTR magic;
3411 LDR_DATA_TABLE_ENTRY *pldr;
3413 if (!*handle) return STATUS_INVALID_PARAMETER;
3415 LdrLockLoaderLock( 0, NULL, &magic );
3416 if (!LdrFindEntryForAddress( *handle, &pldr ))
3418 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3419 status = STATUS_DLL_NOT_FOUND;
3420 else
3421 *handle = pldr->ActivationContext;
3423 else status = STATUS_DLL_NOT_FOUND;
3424 LdrUnlockLoaderLock( 0, magic );
3426 else if (!*handle && (class != ActivationContextBasicInformation))
3427 *handle = process_actctx;
3429 return status;
3432 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3434 unsigned int i, j, total_len = 0, dll_count = 0;
3435 struct strsection_header *header;
3436 struct dllredirect_data *data;
3437 struct string_index *index;
3438 ULONG name_offset;
3440 /* compute section length */
3441 for (i = 0; i < actctx->num_assemblies; i++)
3443 struct assembly *assembly = &actctx->assemblies[i];
3444 for (j = 0; j < assembly->num_dlls; j++)
3446 struct dll_redirect *dll = &assembly->dlls[j];
3448 /* each entry needs index, data and string data */
3449 total_len += sizeof(*index);
3450 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3451 if (dll->load_from)
3453 total_len += offsetof( struct dllredirect_data, paths[1] );
3454 total_len += aligned_string_len( wcslen(dll->load_from) * sizeof(WCHAR) );
3456 else total_len += offsetof( struct dllredirect_data, paths[0] );
3459 dll_count += assembly->num_dlls;
3462 total_len += sizeof(*header);
3464 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3465 if (!header) return STATUS_NO_MEMORY;
3467 memset(header, 0, sizeof(*header));
3468 header->magic = STRSECTION_MAGIC;
3469 header->size = sizeof(*header);
3470 header->count = dll_count;
3471 header->index_offset = sizeof(*header);
3472 index = (struct string_index*)((BYTE*)header + header->index_offset);
3473 name_offset = header->index_offset + header->count*sizeof(*index);
3475 for (i = 0; i < actctx->num_assemblies; i++)
3477 struct assembly *assembly = &actctx->assemblies[i];
3478 for (j = 0; j < assembly->num_dlls; j++)
3480 struct dll_redirect *dll = &assembly->dlls[j];
3481 UNICODE_STRING str;
3482 WCHAR *ptrW;
3484 /* setup new index entry */
3485 str.Buffer = dll->name;
3486 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3487 str.MaximumLength = str.Length + sizeof(WCHAR);
3488 /* hash original class name */
3489 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3491 index->name_offset = name_offset;
3492 index->name_len = str.Length;
3493 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3494 index->data_len = offsetof( struct dllredirect_data, paths[0] );
3495 index->rosterindex = i + 1;
3497 /* dll name */
3498 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3499 memcpy(ptrW, dll->name, index->name_len);
3500 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3501 name_offset += aligned_string_len(str.MaximumLength);
3503 /* setup data */
3504 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3505 if (dll->load_from)
3507 ULONG len = wcslen(dll->load_from) * sizeof(WCHAR);
3508 data->size = offsetof( struct dllredirect_data, paths[1] );
3509 data->flags = 0;
3510 data->total_len = aligned_string_len( len );
3511 data->paths_count = 1;
3512 data->paths_offset = index->data_offset + offsetof( struct dllredirect_data, paths[0] );
3513 data->paths[0].offset = index->data_offset + data->size;
3514 data->paths[0].len = len;
3515 ptrW = (WCHAR *)((BYTE *)header + data->paths[0].offset);
3516 memcpy( ptrW, dll->load_from, len );
3517 if (wcschr( dll->load_from, '%' )) data->flags |= DLL_REDIRECT_PATH_EXPAND;
3519 else
3521 data->size = offsetof( struct dllredirect_data, paths[0] );
3522 data->flags = DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT;
3523 data->total_len = 0;
3524 data->paths_count = 0;
3525 data->paths_offset = 0;
3527 name_offset += data->size + data->total_len;
3529 index++;
3533 *section = header;
3535 return STATUS_SUCCESS;
3538 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3540 struct string_index *iter, *index = NULL;
3541 UNICODE_STRING str;
3542 ULONG hash = 0, i;
3544 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3545 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3547 for (i = 0; i < section->count; i++)
3549 if (iter->hash == hash)
3551 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3552 str.Length = iter->name_len;
3553 if (RtlEqualUnicodeString( &str, name, TRUE ))
3555 index = iter;
3556 break;
3558 else
3559 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3561 iter++;
3564 return index;
3567 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3569 struct guid_index *iter, *index = NULL;
3570 ULONG i;
3572 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3574 for (i = 0; i < section->count; i++)
3576 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3578 index = iter;
3579 break;
3581 iter++;
3584 return index;
3587 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3589 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3592 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3593 PACTCTX_SECTION_KEYED_DATA data)
3595 struct dllredirect_data *dll;
3596 struct string_index *index;
3598 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3600 if (!actctx->dllredirect_section)
3602 struct strsection_header *section;
3604 NTSTATUS status = build_dllredirect_section(actctx, &section);
3605 if (status) return status;
3607 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3608 RtlFreeHeap(GetProcessHeap(), 0, section);
3611 index = find_string_index(actctx->dllredirect_section, name);
3612 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3614 if (data)
3616 dll = get_dllredirect_data(actctx, index);
3618 data->ulDataFormatVersion = 1;
3619 data->lpData = dll;
3620 data->ulLength = dll->size;
3621 data->lpSectionGlobalData = NULL;
3622 data->ulSectionGlobalDataLength = 0;
3623 data->lpSectionBase = actctx->dllredirect_section;
3624 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3625 data->hActCtx = NULL;
3627 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3628 data->ulAssemblyRosterIndex = index->rosterindex;
3631 return STATUS_SUCCESS;
3634 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3636 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3639 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3641 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3644 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3646 unsigned int i, j, k, total_len = 0, class_count = 0;
3647 struct wndclass_redirect_data *data;
3648 struct strsection_header *header;
3649 struct string_index *index;
3650 ULONG name_offset;
3652 /* compute section length */
3653 for (i = 0; i < actctx->num_assemblies; i++)
3655 struct assembly *assembly = &actctx->assemblies[i];
3656 for (j = 0; j < assembly->num_dlls; j++)
3658 struct dll_redirect *dll = &assembly->dlls[j];
3659 for (k = 0; k < dll->entities.num; k++)
3661 struct entity *entity = &dll->entities.base[k];
3662 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3664 int class_len = wcslen(entity->u.class.name) + 1;
3665 int len;
3667 /* each class entry needs index, data and string data */
3668 total_len += sizeof(*index);
3669 total_len += sizeof(*data);
3670 /* original name is stored separately */
3671 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3672 /* versioned name and module name are stored one after another */
3673 if (entity->u.class.versioned)
3674 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3675 else
3676 len = class_len;
3677 len += wcslen(dll->name) + 1;
3678 total_len += aligned_string_len(len*sizeof(WCHAR));
3680 class_count++;
3686 total_len += sizeof(*header);
3688 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3689 if (!header) return STATUS_NO_MEMORY;
3691 memset(header, 0, sizeof(*header));
3692 header->magic = STRSECTION_MAGIC;
3693 header->size = sizeof(*header);
3694 header->count = class_count;
3695 header->index_offset = sizeof(*header);
3696 index = (struct string_index*)((BYTE*)header + header->index_offset);
3697 name_offset = header->index_offset + header->count*sizeof(*index);
3699 for (i = 0; i < actctx->num_assemblies; i++)
3701 struct assembly *assembly = &actctx->assemblies[i];
3702 for (j = 0; j < assembly->num_dlls; j++)
3704 struct dll_redirect *dll = &assembly->dlls[j];
3705 for (k = 0; k < dll->entities.num; k++)
3707 struct entity *entity = &dll->entities.base[k];
3708 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3710 ULONG versioned_len, module_len;
3711 UNICODE_STRING str;
3712 WCHAR *ptrW;
3714 /* setup new index entry */
3715 str.Buffer = entity->u.class.name;
3716 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3717 str.MaximumLength = str.Length + sizeof(WCHAR);
3718 /* hash original class name */
3719 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3721 /* include '!' separator too */
3722 if (entity->u.class.versioned)
3723 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3724 else
3725 versioned_len = str.Length;
3726 module_len = wcslen(dll->name)*sizeof(WCHAR);
3728 index->name_offset = name_offset;
3729 index->name_len = str.Length;
3730 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3731 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3732 index->rosterindex = i + 1;
3734 /* setup data */
3735 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3736 data->size = sizeof(*data);
3737 data->res = 0;
3738 data->name_len = versioned_len;
3739 data->name_offset = sizeof(*data);
3740 data->module_len = module_len;
3741 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3743 /* original class name */
3744 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3745 memcpy(ptrW, entity->u.class.name, index->name_len);
3746 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3748 /* module name */
3749 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3750 memcpy(ptrW, dll->name, data->module_len);
3751 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3753 /* versioned name */
3754 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3755 if (entity->u.class.versioned)
3757 get_assembly_version(assembly, ptrW);
3758 wcscat(ptrW, L"!");
3759 wcscat(ptrW, entity->u.class.name);
3761 else
3763 memcpy(ptrW, entity->u.class.name, index->name_len);
3764 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3767 name_offset += sizeof(*data);
3768 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3770 index++;
3776 *section = header;
3778 return STATUS_SUCCESS;
3781 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3782 PACTCTX_SECTION_KEYED_DATA data)
3784 struct string_index *iter, *index = NULL;
3785 struct wndclass_redirect_data *class;
3786 UNICODE_STRING str;
3787 ULONG hash;
3788 int i;
3790 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3792 if (!actctx->wndclass_section)
3794 struct strsection_header *section;
3796 NTSTATUS status = build_wndclass_section(actctx, &section);
3797 if (status) return status;
3799 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3800 RtlFreeHeap(GetProcessHeap(), 0, section);
3803 hash = 0;
3804 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3805 iter = get_wndclass_first_index(actctx);
3807 for (i = 0; i < actctx->wndclass_section->count; i++)
3809 if (iter->hash == hash)
3811 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3812 str.Length = iter->name_len;
3813 if (RtlEqualUnicodeString( &str, name, TRUE ))
3815 index = iter;
3816 break;
3818 else
3819 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3821 iter++;
3824 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3826 if (data)
3828 class = get_wndclass_data(actctx, index);
3830 data->ulDataFormatVersion = 1;
3831 data->lpData = class;
3832 /* full length includes string length with nulls */
3833 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3834 data->lpSectionGlobalData = NULL;
3835 data->ulSectionGlobalDataLength = 0;
3836 data->lpSectionBase = actctx->wndclass_section;
3837 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3838 data->hActCtx = NULL;
3840 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3841 data->ulAssemblyRosterIndex = index->rosterindex;
3844 return STATUS_SUCCESS;
3847 static inline struct string_index *get_activatable_class_first_index(ACTIVATION_CONTEXT *actctx)
3849 return (struct string_index *)((BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->index_offset);
3852 static inline struct activatable_class_data *get_activatable_class_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3854 return (struct activatable_class_data *)((BYTE *)ctxt->activatable_class_section + index->data_offset);
3857 static NTSTATUS build_activatable_class_section(ACTIVATION_CONTEXT *actctx, struct strsection_header **section)
3859 unsigned int i, j, k, total_len = 0, class_count = 0, global_offset = 0, global_len = 0;
3860 struct activatable_class_data *data;
3861 struct strsection_header *header;
3862 struct string_index *index;
3863 ULONG name_offset;
3865 /* compute section length */
3866 for (i = 0; i < actctx->num_assemblies; i++)
3868 struct assembly *assembly = &actctx->assemblies[i];
3869 for (j = 0; j < assembly->num_dlls; j++)
3871 struct dll_redirect *dll = &assembly->dlls[j];
3872 BOOL has_class = FALSE;
3874 for (k = 0; k < dll->entities.num; k++)
3876 struct entity *entity = &dll->entities.base[k];
3877 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3879 int class_len = wcslen(entity->u.activatable_class.name) + 1;
3881 /* each class entry needs index, data and string data */
3882 total_len += sizeof(*index);
3883 total_len += aligned_string_len(class_len * sizeof(WCHAR));
3884 total_len += sizeof(*data);
3886 class_count++;
3887 has_class = TRUE;
3891 if (has_class)
3893 int module_len = wcslen(dll->name) + 1;
3894 global_len += aligned_string_len(module_len * sizeof(WCHAR));
3899 total_len += sizeof(*header) + global_len;
3901 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3902 if (!header) return STATUS_NO_MEMORY;
3904 memset(header, 0, sizeof(*header));
3905 header->magic = STRSECTION_MAGIC;
3906 header->size = sizeof(*header);
3907 header->count = class_count;
3908 header->global_offset = header->size;
3909 header->global_len = global_len;
3910 header->index_offset = header->global_offset + header->global_len;
3911 index = (struct string_index *)((BYTE *)header + header->index_offset);
3912 name_offset = header->index_offset + header->count * sizeof(*index);
3914 global_offset = header->size;
3915 for (i = 0; i < actctx->num_assemblies; i++)
3917 struct assembly *assembly = &actctx->assemblies[i];
3918 for (j = 0; j < assembly->num_dlls; j++)
3920 struct dll_redirect *dll = &assembly->dlls[j];
3921 int module_len = wcslen(dll->name) * sizeof(WCHAR);
3922 BOOL has_class = FALSE;
3924 for (k = 0; k < dll->entities.num; k++)
3926 struct entity *entity = &dll->entities.base[k];
3928 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3930 UNICODE_STRING str;
3931 WCHAR *ptrW;
3933 /* setup new index entry */
3934 str.Buffer = entity->u.activatable_class.name;
3935 str.Length = wcslen(entity->u.activatable_class.name) * sizeof(WCHAR);
3936 str.MaximumLength = str.Length + sizeof(WCHAR);
3937 /* hash class name */
3938 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3940 index->name_offset = name_offset;
3941 index->name_len = str.Length;
3942 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3943 index->data_len = sizeof(*data);
3944 index->rosterindex = i + 1;
3946 /* class name */
3947 ptrW = (WCHAR *)((BYTE *)header + index->name_offset);
3948 memcpy(ptrW, entity->u.activatable_class.name, index->name_len);
3949 ptrW[index->name_len / sizeof(WCHAR)] = 0;
3951 /* class data */
3952 data = (struct activatable_class_data *)((BYTE *)header + index->data_offset);
3953 data->size = sizeof(*data);
3954 data->threading_model = entity->u.activatable_class.threading_model;
3955 data->module_len = module_len;
3956 data->module_offset = global_offset;
3958 name_offset += aligned_string_len(str.MaximumLength);
3959 name_offset += sizeof(*data);
3961 index++;
3962 has_class = TRUE;
3966 if (has_class)
3968 WCHAR *ptrW = (WCHAR *)((BYTE *)header + global_offset);
3969 memcpy(ptrW, dll->name, module_len);
3970 ptrW[module_len / sizeof(WCHAR)] = 0;
3971 global_offset += aligned_string_len(module_len + sizeof(WCHAR));
3976 *section = header;
3978 return STATUS_SUCCESS;
3981 static NTSTATUS find_activatable_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3982 PACTCTX_SECTION_KEYED_DATA data)
3984 struct string_index *iter, *index = NULL;
3985 struct activatable_class_data *class;
3986 UNICODE_STRING str;
3987 ULONG hash;
3988 int i;
3990 if (!(actctx->sections & ACTIVATABLE_CLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3992 if (!actctx->activatable_class_section)
3994 struct strsection_header *section;
3996 NTSTATUS status = build_activatable_class_section(actctx, &section);
3997 if (status) return status;
3999 if (InterlockedCompareExchangePointer((void**)&actctx->activatable_class_section, section, NULL))
4000 RtlFreeHeap(GetProcessHeap(), 0, section);
4003 hash = 0;
4004 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
4005 iter = get_activatable_class_first_index(actctx);
4007 for (i = 0; i < actctx->activatable_class_section->count; i++)
4009 if (iter->hash == hash)
4011 str.Buffer = (WCHAR *)((BYTE *)actctx->activatable_class_section + iter->name_offset);
4012 str.Length = iter->name_len;
4013 if (RtlEqualUnicodeString( &str, name, TRUE ))
4015 index = iter;
4016 break;
4018 else
4019 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
4021 iter++;
4024 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4026 if (data)
4028 class = get_activatable_class_data(actctx, index);
4030 data->ulDataFormatVersion = 1;
4031 data->lpData = class;
4032 /* full length includes string length with nulls */
4033 data->ulLength = class->size + class->module_len + sizeof(WCHAR);
4034 data->lpSectionGlobalData = (BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->global_offset;
4035 data->ulSectionGlobalDataLength = actctx->activatable_class_section->global_len;
4036 data->lpSectionBase = actctx->activatable_class_section;
4037 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->activatable_class_section );
4038 data->hActCtx = NULL;
4040 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4041 data->ulAssemblyRosterIndex = index->rosterindex;
4044 return STATUS_SUCCESS;
4047 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4049 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
4050 struct guidsection_header *header;
4051 ULONG module_offset, data_offset;
4052 struct tlibredirect_data *data;
4053 struct guid_index *index;
4055 /* compute section length */
4056 for (i = 0; i < actctx->num_assemblies; i++)
4058 struct assembly *assembly = &actctx->assemblies[i];
4059 for (j = 0; j < assembly->num_dlls; j++)
4061 struct dll_redirect *dll = &assembly->dlls[j];
4062 for (k = 0; k < dll->entities.num; k++)
4064 struct entity *entity = &dll->entities.base[k];
4065 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4067 /* each entry needs index, data and string data for module name and help string */
4068 total_len += sizeof(*index);
4069 total_len += sizeof(*data);
4070 /* help string is stored separately */
4071 if (*entity->u.typelib.helpdir)
4072 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
4074 /* module names are packed one after another */
4075 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4077 tlib_count++;
4083 total_len += aligned_string_len(names_len);
4084 total_len += sizeof(*header);
4086 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4087 if (!header) return STATUS_NO_MEMORY;
4089 memset(header, 0, sizeof(*header));
4090 header->magic = GUIDSECTION_MAGIC;
4091 header->size = sizeof(*header);
4092 header->count = tlib_count;
4093 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4094 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4095 module_offset = sizeof(*header);
4096 data_offset = header->index_offset + tlib_count*sizeof(*index);
4098 for (i = 0; i < actctx->num_assemblies; i++)
4100 struct assembly *assembly = &actctx->assemblies[i];
4101 for (j = 0; j < assembly->num_dlls; j++)
4103 struct dll_redirect *dll = &assembly->dlls[j];
4104 for (k = 0; k < dll->entities.num; k++)
4106 struct entity *entity = &dll->entities.base[k];
4107 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4109 ULONG module_len, help_len;
4110 UNICODE_STRING str;
4111 WCHAR *ptrW;
4113 if (*entity->u.typelib.helpdir)
4114 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
4115 else
4116 help_len = 0;
4118 module_len = wcslen(dll->name)*sizeof(WCHAR);
4120 /* setup new index entry */
4121 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
4122 RtlGUIDFromString(&str, &index->guid);
4123 index->data_offset = data_offset;
4124 index->data_len = sizeof(*data) + aligned_string_len(help_len);
4125 index->rosterindex = i + 1;
4127 /* setup data */
4128 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
4129 data->size = sizeof(*data);
4130 data->res = 0;
4131 data->name_len = module_len;
4132 data->name_offset = module_offset;
4133 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
4134 data->langid = 0;
4135 data->flags = entity->u.typelib.flags;
4136 data->help_len = help_len;
4137 data->help_offset = sizeof(*data);
4138 data->major_version = entity->u.typelib.major;
4139 data->minor_version = entity->u.typelib.minor;
4141 /* module name */
4142 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
4143 memcpy(ptrW, dll->name, data->name_len);
4144 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4146 /* help string */
4147 if (data->help_len)
4149 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
4150 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
4151 ptrW[data->help_len/sizeof(WCHAR)] = 0;
4154 data_offset += sizeof(*data);
4155 if (help_len)
4156 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
4158 module_offset += module_len + sizeof(WCHAR);
4160 index++;
4166 *section = header;
4168 return STATUS_SUCCESS;
4171 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4173 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
4176 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4178 struct guid_index *index = NULL;
4179 struct tlibredirect_data *tlib;
4181 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4183 if (!actctx->tlib_section)
4185 struct guidsection_header *section;
4187 NTSTATUS status = build_tlib_section(actctx, &section);
4188 if (status) return status;
4190 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
4191 RtlFreeHeap(GetProcessHeap(), 0, section);
4194 index = find_guid_index(actctx->tlib_section, guid);
4195 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4197 tlib = get_tlib_data(actctx, index);
4199 data->ulDataFormatVersion = 1;
4200 data->lpData = tlib;
4201 /* full length includes string length with nulls */
4202 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
4203 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
4204 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
4205 data->lpSectionBase = actctx->tlib_section;
4206 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
4207 data->hActCtx = NULL;
4209 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4210 data->ulAssemblyRosterIndex = index->rosterindex;
4212 return STATUS_SUCCESS;
4215 static void generate_uuid(ULONG *seed, GUID *guid)
4217 ULONG *ptr = (ULONG*)guid;
4218 int i;
4220 /* GUID is 16 bytes long */
4221 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
4222 *ptr = RtlUniform(seed);
4224 guid->Data3 &= 0x0fff;
4225 guid->Data3 |= (4 << 12);
4226 guid->Data4[0] &= 0x3f;
4227 guid->Data4[0] |= 0x80;
4230 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4231 unsigned int *count, unsigned int *len, unsigned int *module_len)
4233 unsigned int i;
4235 for (i = 0; i < entities->num; i++)
4237 struct entity *entity = &entities->base[i];
4238 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4240 /* each entry needs two index entries, extra one goes for alias GUID */
4241 *len += 2*sizeof(struct guid_index);
4242 /* To save some memory we don't allocated two data structures,
4243 instead alias index and normal index point to the same data structure. */
4244 *len += sizeof(struct comclassredirect_data);
4246 /* for clrClass store some more */
4247 if (entity->u.comclass.name)
4249 unsigned int str_len;
4251 /* all string data is stored together in aligned block */
4252 str_len = wcslen(entity->u.comclass.name)+1;
4253 if (entity->u.comclass.progid)
4254 str_len += wcslen(entity->u.comclass.progid)+1;
4255 if (entity->u.comclass.version)
4256 str_len += wcslen(entity->u.comclass.version)+1;
4258 *len += sizeof(struct clrclass_data);
4259 *len += aligned_string_len(str_len*sizeof(WCHAR));
4261 /* module name is forced to mscoree.dll, and stored two times with different case */
4262 *module_len += sizeof(L"MSCOREE.DLL") + sizeof(L"mscoree.dll");
4264 else
4266 /* progid string is stored separately */
4267 if (entity->u.comclass.progid)
4268 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4270 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4273 *count += 1;
4278 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4279 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4280 ULONG *seed, ULONG rosterindex)
4282 unsigned int i;
4284 for (i = 0; i < entities->num; i++)
4286 struct entity *entity = &entities->base[i];
4287 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4289 ULONG module_len, progid_len, str_len = 0, miscmask;
4290 struct comclassredirect_data *data;
4291 struct guid_index *alias_index;
4292 struct clrclass_data *clrdata;
4293 UNICODE_STRING str;
4294 WCHAR *ptrW;
4296 if (entity->u.comclass.progid)
4297 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4298 else
4299 progid_len = 0;
4301 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4303 /* setup new index entry */
4304 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4305 RtlGUIDFromString(&str, &(*index)->guid);
4307 (*index)->data_offset = *data_offset;
4308 (*index)->data_len = sizeof(*data); /* additional length added later */
4309 (*index)->rosterindex = rosterindex;
4311 /* Setup new index entry for alias guid. Alias index records are placed after
4312 normal records, so normal guids are hit first on search. Note that class count
4313 is doubled. */
4314 alias_index = (*index) + section->count/2;
4315 generate_uuid(seed, &alias_index->guid);
4316 alias_index->data_offset = (*index)->data_offset;
4317 alias_index->data_len = 0;
4318 alias_index->rosterindex = (*index)->rosterindex;
4320 /* setup data */
4321 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4322 data->size = sizeof(*data);
4323 data->model = entity->u.comclass.model;
4324 data->clsid = (*index)->guid;
4325 data->alias = alias_index->guid;
4326 data->clsid2 = data->clsid;
4327 if (entity->u.comclass.tlbid)
4329 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4330 RtlGUIDFromString(&str, &data->tlbid);
4332 else
4333 memset(&data->tlbid, 0, sizeof(data->tlbid));
4334 data->name_len = module_len;
4335 data->name_offset = *module_offset;
4336 data->progid_len = progid_len;
4337 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4338 data->clrdata_len = 0; /* will be set later */
4339 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4340 data->miscstatus = entity->u.comclass.miscstatus;
4341 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4342 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4343 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4344 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4346 /* mask describes which misc* data is available */
4347 miscmask = 0;
4348 if (data->miscstatus)
4349 miscmask |= MiscStatus;
4350 if (data->miscstatuscontent)
4351 miscmask |= MiscStatusContent;
4352 if (data->miscstatusthumbnail)
4353 miscmask |= MiscStatusThumbnail;
4354 if (data->miscstatusicon)
4355 miscmask |= MiscStatusIcon;
4356 if (data->miscstatusdocprint)
4357 miscmask |= MiscStatusDocPrint;
4358 data->flags = miscmask << 8;
4360 if (data->clrdata_offset)
4362 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4364 clrdata->size = sizeof(*clrdata);
4365 clrdata->res[0] = 0;
4366 clrdata->res[1] = 2; /* FIXME: unknown field */
4367 clrdata->module_len = wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4368 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4369 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4370 clrdata->name_offset = clrdata->size;
4371 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4372 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4373 clrdata->res2[0] = 0;
4374 clrdata->res2[1] = 0;
4376 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4378 /* module name */
4379 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4380 memcpy(ptrW, L"mscoree.dll", clrdata->module_len);
4381 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4383 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4384 memcpy(ptrW, L"MSCOREE.DLL", data->name_len);
4385 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4387 /* class name */
4388 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4389 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4390 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4392 /* runtime version, optional */
4393 if (clrdata->version_len)
4395 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4397 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4398 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4399 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4402 if (data->progid_len)
4403 data->progid_offset += data->clrdata_len;
4404 (*index)->data_len += sizeof(*clrdata);
4406 else
4408 clrdata = NULL;
4410 /* module name */
4411 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4412 memcpy(ptrW, dll->name, data->name_len);
4413 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4416 /* progid string */
4417 if (data->progid_len)
4419 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4420 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4421 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4424 /* string block length */
4425 str_len = 0;
4426 if (clrdata)
4428 str_len += clrdata->name_len + sizeof(WCHAR);
4429 if (clrdata->version_len)
4430 str_len += clrdata->version_len + sizeof(WCHAR);
4432 if (progid_len)
4433 str_len += progid_len + sizeof(WCHAR);
4435 (*index)->data_len += aligned_string_len(str_len);
4436 alias_index->data_len = (*index)->data_len;
4438 /* move to next data record */
4439 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4440 (*module_offset) += module_len + sizeof(WCHAR);
4442 if (clrdata)
4444 (*data_offset) += sizeof(*clrdata);
4445 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4447 (*index) += 1;
4452 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4454 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4455 struct guidsection_header *header;
4456 ULONG module_offset, data_offset;
4457 struct guid_index *index;
4458 ULONG seed;
4460 /* compute section length */
4461 for (i = 0; i < actctx->num_assemblies; i++)
4463 struct assembly *assembly = &actctx->assemblies[i];
4464 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4465 for (j = 0; j < assembly->num_dlls; j++)
4467 struct dll_redirect *dll = &assembly->dlls[j];
4468 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4472 total_len += aligned_string_len(names_len);
4473 total_len += sizeof(*header);
4475 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4476 if (!header) return STATUS_NO_MEMORY;
4478 memset(header, 0, sizeof(*header));
4479 header->magic = GUIDSECTION_MAGIC;
4480 header->size = sizeof(*header);
4481 header->count = 2*class_count;
4482 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4483 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4484 module_offset = sizeof(*header);
4485 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4487 seed = NtGetTickCount();
4488 for (i = 0; i < actctx->num_assemblies; i++)
4490 struct assembly *assembly = &actctx->assemblies[i];
4491 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4492 for (j = 0; j < assembly->num_dlls; j++)
4494 struct dll_redirect *dll = &assembly->dlls[j];
4495 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4499 *section = header;
4501 return STATUS_SUCCESS;
4504 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4506 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4509 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4511 struct comclassredirect_data *comclass;
4512 struct guid_index *index = NULL;
4514 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4516 if (!actctx->comserver_section)
4518 struct guidsection_header *section;
4520 NTSTATUS status = build_comserver_section(actctx, &section);
4521 if (status) return status;
4523 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4524 RtlFreeHeap(GetProcessHeap(), 0, section);
4527 index = find_guid_index(actctx->comserver_section, guid);
4528 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4530 comclass = get_comclass_data(actctx, index);
4532 data->ulDataFormatVersion = 1;
4533 data->lpData = comclass;
4534 /* full length includes string length with nulls */
4535 data->ulLength = comclass->size + comclass->clrdata_len;
4536 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4537 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4538 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4539 data->lpSectionBase = actctx->comserver_section;
4540 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4541 data->hActCtx = NULL;
4543 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4544 data->ulAssemblyRosterIndex = index->rosterindex;
4546 return STATUS_SUCCESS;
4549 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4551 unsigned int i;
4553 for (i = 0; i < entities->num; i++)
4555 struct entity *entity = &entities->base[i];
4556 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4558 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4559 if (entity->u.ifaceps.name)
4560 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4561 *count += 1;
4566 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4567 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4569 unsigned int i;
4571 for (i = 0; i < entities->num; i++)
4573 struct entity *entity = &entities->base[i];
4574 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4576 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4577 UNICODE_STRING str;
4578 ULONG name_len;
4580 if (entity->u.ifaceps.name)
4581 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4582 else
4583 name_len = 0;
4585 /* setup index */
4586 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4587 RtlGUIDFromString(&str, &(*index)->guid);
4588 (*index)->data_offset = *data_offset;
4589 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4590 (*index)->rosterindex = rosterindex;
4592 /* setup data record */
4593 data->size = sizeof(*data);
4594 data->mask = entity->u.ifaceps.mask;
4596 /* proxyStubClsid32 value is only stored for external PS,
4597 if set it's used as iid, otherwise 'iid' attribute value is used */
4598 if (entity->u.ifaceps.ps32)
4600 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4601 RtlGUIDFromString(&str, &data->iid);
4603 else
4604 data->iid = (*index)->guid;
4606 data->nummethods = entity->u.ifaceps.nummethods;
4608 if (entity->u.ifaceps.tlib)
4610 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4611 RtlGUIDFromString(&str, &data->tlbid);
4613 else
4614 memset(&data->tlbid, 0, sizeof(data->tlbid));
4616 if (entity->u.ifaceps.base)
4618 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4619 RtlGUIDFromString(&str, &data->base);
4621 else
4622 memset(&data->base, 0, sizeof(data->base));
4624 data->name_len = name_len;
4625 data->name_offset = data->name_len ? sizeof(*data) : 0;
4627 /* name string */
4628 if (data->name_len)
4630 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4631 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4632 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4635 /* move to next record */
4636 (*index) += 1;
4637 *data_offset += sizeof(*data);
4638 if (data->name_len)
4639 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4644 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4646 unsigned int i, j, total_len = 0, count = 0;
4647 struct guidsection_header *header;
4648 struct guid_index *index;
4649 ULONG data_offset;
4651 /* compute section length */
4652 for (i = 0; i < actctx->num_assemblies; i++)
4654 struct assembly *assembly = &actctx->assemblies[i];
4656 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4657 for (j = 0; j < assembly->num_dlls; j++)
4659 struct dll_redirect *dll = &assembly->dlls[j];
4660 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4664 total_len += sizeof(*header);
4666 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4667 if (!header) return STATUS_NO_MEMORY;
4669 memset(header, 0, sizeof(*header));
4670 header->magic = GUIDSECTION_MAGIC;
4671 header->size = sizeof(*header);
4672 header->count = count;
4673 header->index_offset = sizeof(*header);
4674 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4675 data_offset = header->index_offset + count*sizeof(*index);
4677 for (i = 0; i < actctx->num_assemblies; i++)
4679 struct assembly *assembly = &actctx->assemblies[i];
4681 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4682 for (j = 0; j < assembly->num_dlls; j++)
4684 struct dll_redirect *dll = &assembly->dlls[j];
4685 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4689 *section = header;
4691 return STATUS_SUCCESS;
4694 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4696 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4699 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4701 struct ifacepsredirect_data *iface;
4702 struct guid_index *index = NULL;
4704 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4706 if (!actctx->ifaceps_section)
4708 struct guidsection_header *section;
4710 NTSTATUS status = build_ifaceps_section(actctx, &section);
4711 if (status) return status;
4713 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4714 RtlFreeHeap(GetProcessHeap(), 0, section);
4717 index = find_guid_index(actctx->ifaceps_section, guid);
4718 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4720 iface = get_ifaceps_data(actctx, index);
4722 data->ulDataFormatVersion = 1;
4723 data->lpData = iface;
4724 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4725 data->lpSectionGlobalData = NULL;
4726 data->ulSectionGlobalDataLength = 0;
4727 data->lpSectionBase = actctx->ifaceps_section;
4728 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4729 data->hActCtx = NULL;
4731 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4732 data->ulAssemblyRosterIndex = index->rosterindex;
4734 return STATUS_SUCCESS;
4737 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4739 unsigned int i, j, total_len = 0, count = 0;
4740 struct guidsection_header *header;
4741 struct clrsurrogate_data *data;
4742 struct guid_index *index;
4743 ULONG data_offset;
4745 /* compute section length */
4746 for (i = 0; i < actctx->num_assemblies; i++)
4748 struct assembly *assembly = &actctx->assemblies[i];
4749 for (j = 0; j < assembly->entities.num; j++)
4751 struct entity *entity = &assembly->entities.base[j];
4752 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4754 ULONG len;
4756 total_len += sizeof(*index) + sizeof(*data);
4757 len = wcslen(entity->u.clrsurrogate.name) + 1;
4758 if (entity->u.clrsurrogate.version)
4759 len += wcslen(entity->u.clrsurrogate.version) + 1;
4760 total_len += aligned_string_len(len*sizeof(WCHAR));
4762 count++;
4767 total_len += sizeof(*header);
4769 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4770 if (!header) return STATUS_NO_MEMORY;
4772 memset(header, 0, sizeof(*header));
4773 header->magic = GUIDSECTION_MAGIC;
4774 header->size = sizeof(*header);
4775 header->count = count;
4776 header->index_offset = sizeof(*header);
4777 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4778 data_offset = header->index_offset + count*sizeof(*index);
4780 for (i = 0; i < actctx->num_assemblies; i++)
4782 struct assembly *assembly = &actctx->assemblies[i];
4783 for (j = 0; j < assembly->entities.num; j++)
4785 struct entity *entity = &assembly->entities.base[j];
4786 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4788 ULONG version_len, name_len;
4789 UNICODE_STRING str;
4790 WCHAR *ptrW;
4792 if (entity->u.clrsurrogate.version)
4793 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4794 else
4795 version_len = 0;
4796 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4798 /* setup new index entry */
4799 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4800 RtlGUIDFromString(&str, &index->guid);
4802 index->data_offset = data_offset;
4803 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4804 index->rosterindex = i + 1;
4806 /* setup data */
4807 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4808 data->size = sizeof(*data);
4809 data->res = 0;
4810 data->clsid = index->guid;
4811 data->version_offset = version_len ? data->size : 0;
4812 data->version_len = version_len;
4813 data->name_offset = data->size + version_len;
4814 if (version_len)
4815 data->name_offset += sizeof(WCHAR);
4816 data->name_len = name_len;
4818 /* surrogate name */
4819 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4820 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4821 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4823 /* runtime version */
4824 if (data->version_len)
4826 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4827 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4828 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4831 data_offset += index->data_len;
4832 index++;
4837 *section = header;
4839 return STATUS_SUCCESS;
4842 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4844 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4847 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4849 struct clrsurrogate_data *surrogate;
4850 struct guid_index *index = NULL;
4852 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4854 if (!actctx->clrsurrogate_section)
4856 struct guidsection_header *section;
4858 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4859 if (status) return status;
4861 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4862 RtlFreeHeap(GetProcessHeap(), 0, section);
4865 index = find_guid_index(actctx->clrsurrogate_section, guid);
4866 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4868 surrogate = get_surrogate_data(actctx, index);
4870 data->ulDataFormatVersion = 1;
4871 data->lpData = surrogate;
4872 /* full length includes string length with nulls */
4873 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4874 if (surrogate->version_len)
4875 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4877 data->lpSectionGlobalData = NULL;
4878 data->ulSectionGlobalDataLength = 0;
4879 data->lpSectionBase = actctx->clrsurrogate_section;
4880 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4881 data->hActCtx = NULL;
4883 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4884 data->ulAssemblyRosterIndex = index->rosterindex;
4886 return STATUS_SUCCESS;
4889 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4891 unsigned int i, j, single_len;
4893 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4894 for (i = 0; i < entities->num; i++)
4896 struct entity *entity = &entities->base[i];
4897 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4899 if (entity->u.comclass.progid)
4901 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4902 *count += 1;
4905 for (j = 0; j < entity->u.comclass.progids.num; j++)
4906 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4908 *total_len += single_len*entity->u.comclass.progids.num;
4909 *count += entity->u.comclass.progids.num;
4914 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4915 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4917 struct progidredirect_data *data;
4918 UNICODE_STRING str;
4919 GUID *guid_ptr;
4920 WCHAR *ptrW;
4922 /* setup new index entry */
4924 /* hash progid name */
4925 RtlInitUnicodeString(&str, progid);
4926 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4928 (*index)->name_offset = *data_offset;
4929 (*index)->name_len = str.Length;
4930 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4931 (*index)->data_len = sizeof(*data);
4932 (*index)->rosterindex = rosterindex;
4934 *data_offset += aligned_string_len(str.MaximumLength);
4936 /* setup data structure */
4937 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4938 data->size = sizeof(*data);
4939 data->reserved = 0;
4940 data->clsid_offset = *global_offset;
4942 /* write progid string */
4943 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4944 memcpy(ptrW, progid, (*index)->name_len);
4945 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4947 /* write guid to global area */
4948 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4949 *guid_ptr = *alias;
4951 /* to next entry */
4952 *global_offset += sizeof(GUID);
4953 *data_offset += data->size;
4954 (*index) += 1;
4957 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4958 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4960 unsigned int i, j;
4962 for (i = 0; i < entities->num; i++)
4964 struct entity *entity = &entities->base[i];
4965 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4967 const struct progids *progids = &entity->u.comclass.progids;
4968 struct comclassredirect_data *comclass;
4969 struct guid_index *guid_index;
4970 UNICODE_STRING str;
4971 GUID clsid;
4973 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4974 RtlGUIDFromString(&str, &clsid);
4976 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4977 comclass = get_comclass_data(actctx, guid_index);
4979 if (entity->u.comclass.progid)
4980 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4981 index, data_offset, global_offset, rosterindex);
4983 for (j = 0; j < progids->num; j++)
4984 write_progid_record(section, progids->progids[j], &comclass->alias,
4985 index, data_offset, global_offset, rosterindex);
4990 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4992 unsigned int i, j, total_len = 0, count = 0;
4993 struct strsection_header *header;
4994 ULONG data_offset, global_offset;
4995 struct string_index *index;
4997 /* compute section length */
4998 for (i = 0; i < actctx->num_assemblies; i++)
5000 struct assembly *assembly = &actctx->assemblies[i];
5002 get_progid_datalen(&assembly->entities, &count, &total_len);
5003 for (j = 0; j < assembly->num_dlls; j++)
5005 struct dll_redirect *dll = &assembly->dlls[j];
5006 get_progid_datalen(&dll->entities, &count, &total_len);
5010 total_len += sizeof(*header);
5012 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
5013 if (!header) return STATUS_NO_MEMORY;
5015 memset(header, 0, sizeof(*header));
5016 header->magic = STRSECTION_MAGIC;
5017 header->size = sizeof(*header);
5018 header->count = count;
5019 header->global_offset = header->size;
5020 header->global_len = count*sizeof(GUID);
5021 header->index_offset = header->size + header->global_len;
5023 index = (struct string_index*)((BYTE*)header + header->index_offset);
5024 data_offset = header->index_offset + count*sizeof(*index);
5025 global_offset = header->global_offset;
5027 for (i = 0; i < actctx->num_assemblies; i++)
5029 struct assembly *assembly = &actctx->assemblies[i];
5031 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
5032 for (j = 0; j < assembly->num_dlls; j++)
5034 struct dll_redirect *dll = &assembly->dlls[j];
5035 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
5039 *section = header;
5041 return STATUS_SUCCESS;
5044 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
5046 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
5049 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
5050 PACTCTX_SECTION_KEYED_DATA data)
5052 struct progidredirect_data *progid;
5053 struct string_index *index;
5055 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
5057 if (!actctx->comserver_section)
5059 struct guidsection_header *section;
5061 NTSTATUS status = build_comserver_section(actctx, &section);
5062 if (status) return status;
5064 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
5065 RtlFreeHeap(GetProcessHeap(), 0, section);
5068 if (!actctx->progid_section)
5070 struct strsection_header *section;
5072 NTSTATUS status = build_progid_section(actctx, &section);
5073 if (status) return status;
5075 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
5076 RtlFreeHeap(GetProcessHeap(), 0, section);
5079 index = find_string_index(actctx->progid_section, name);
5080 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
5082 if (data)
5084 progid = get_progid_data(actctx, index);
5086 data->ulDataFormatVersion = 1;
5087 data->lpData = progid;
5088 data->ulLength = progid->size;
5089 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
5090 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
5091 data->lpSectionBase = actctx->progid_section;
5092 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
5093 data->hActCtx = NULL;
5095 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
5096 data->ulAssemblyRosterIndex = index->rosterindex;
5099 return STATUS_SUCCESS;
5102 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5103 const UNICODE_STRING *section_name,
5104 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5106 NTSTATUS status;
5108 switch (section_kind)
5110 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
5111 status = find_dll_redirection(actctx, section_name, data);
5112 break;
5113 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
5114 status = find_window_class(actctx, section_name, data);
5115 break;
5116 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
5117 status = find_progid_redirection(actctx, section_name, data);
5118 break;
5119 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
5120 FIXME("Unsupported yet section_kind %lx\n", section_kind);
5121 return STATUS_SXS_SECTION_NOT_FOUND;
5122 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES:
5123 status = find_activatable_class(actctx, section_name, data);
5124 break;
5125 default:
5126 WARN("Unknown section_kind %lx\n", section_kind);
5127 return STATUS_SXS_SECTION_NOT_FOUND;
5130 if (status != STATUS_SUCCESS) return status;
5132 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
5134 actctx_addref(actctx);
5135 data->hActCtx = actctx;
5137 return STATUS_SUCCESS;
5140 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5141 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5143 NTSTATUS status;
5145 switch (section_kind)
5147 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
5148 status = find_tlib_redirection(actctx, guid, data);
5149 break;
5150 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
5151 status = find_comserver_redirection(actctx, guid, data);
5152 break;
5153 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
5154 status = find_cominterface_redirection(actctx, guid, data);
5155 break;
5156 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
5157 status = find_clr_surrogate(actctx, guid, data);
5158 break;
5159 default:
5160 WARN("Unknown section_kind %lx\n", section_kind);
5161 return STATUS_SXS_SECTION_NOT_FOUND;
5164 if (status != STATUS_SUCCESS) return status;
5166 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5168 actctx_addref(actctx);
5169 data->hActCtx = actctx;
5171 return STATUS_SUCCESS;
5174 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
5176 unsigned int i, j;
5178 for (i = 0; i < actctx->num_assemblies; i++)
5180 struct assembly *assembly = &actctx->assemblies[i];
5181 for (j = 0; j < assembly->entities.num; j++)
5183 struct entity *entity = &assembly->entities.base[j];
5184 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
5185 !wcscmp( entity->u.settings.name, settings ) &&
5186 !wcscmp( entity->u.settings.ns, ns ))
5187 return entity->u.settings.value;
5190 return NULL;
5193 /* initialize the activation context for the current process */
5194 void actctx_init(void)
5196 ACTCTXW ctx;
5197 HANDLE handle;
5199 ctx.cbSize = sizeof(ctx);
5200 ctx.lpSource = NULL;
5201 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
5202 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
5203 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
5205 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
5207 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
5211 /***********************************************************************
5212 * RtlCreateActivationContext (NTDLL.@)
5214 * Create an activation context.
5216 * FIXME: function signature/prototype is wrong
5218 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
5220 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
5221 const WCHAR *directory = NULL;
5222 ACTIVATION_CONTEXT *actctx;
5223 UNICODE_STRING nameW;
5224 ULONG lang = 0;
5225 NTSTATUS status = STATUS_NO_MEMORY;
5226 HANDLE file = 0;
5227 struct actctx_loader acl;
5229 TRACE("%p %08lx\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
5231 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5232 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5233 return STATUS_INVALID_PARAMETER;
5235 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
5236 return STATUS_NO_MEMORY;
5238 actctx->magic = ACTCTX_MAGIC;
5239 actctx->ref_count = 1;
5240 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5241 actctx->config.info = NULL;
5242 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5243 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5245 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5247 else
5249 UNICODE_STRING dir;
5250 WCHAR *p;
5251 HMODULE module;
5253 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5254 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
5256 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5257 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5258 actctx->appdir.info = dir.Buffer;
5261 nameW.Buffer = NULL;
5263 /* open file only if it's going to be used */
5264 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5265 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5267 WCHAR *source = NULL;
5268 BOOLEAN ret;
5270 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5271 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5273 DWORD dir_len, source_len;
5275 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5276 source_len = wcslen(pActCtx->lpSource);
5277 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5279 status = STATUS_NO_MEMORY;
5280 goto error;
5283 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5284 source[dir_len] = '\\';
5285 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5288 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5289 RtlFreeHeap( GetProcessHeap(), 0, source );
5290 if (!ret)
5292 status = STATUS_NO_SUCH_FILE;
5293 goto error;
5295 status = open_nt_file( &file, &nameW );
5296 if (status)
5298 RtlFreeUnicodeString( &nameW );
5299 goto error;
5303 acl.actctx = actctx;
5304 acl.dependencies = NULL;
5305 acl.num_dependencies = 0;
5306 acl.allocated_dependencies = 0;
5308 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5309 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5311 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5313 /* if we have a resource it's a PE file */
5314 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5316 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5317 pActCtx->lpResourceName, lang );
5318 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5319 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5320 pActCtx->hModule, pActCtx->lpResourceName );
5322 else if (pActCtx->lpSource)
5324 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5325 file, pActCtx->lpResourceName, lang );
5326 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5327 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5328 NULL, pActCtx->lpResourceName );
5330 else status = STATUS_INVALID_PARAMETER;
5332 else
5334 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5337 if (file) NtClose( file );
5338 RtlFreeUnicodeString( &nameW );
5340 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5341 free_depend_manifests( &acl );
5343 if (status == STATUS_SUCCESS) *handle = actctx;
5344 else actctx_release( actctx );
5345 return status;
5347 error:
5348 if (file) NtClose( file );
5349 actctx_release( actctx );
5350 return status;
5354 /***********************************************************************
5355 * RtlAddRefActivationContext (NTDLL.@)
5357 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5359 ACTIVATION_CONTEXT *actctx;
5361 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5365 /******************************************************************
5366 * RtlReleaseActivationContext (NTDLL.@)
5368 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5370 ACTIVATION_CONTEXT *actctx;
5372 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5375 /******************************************************************
5376 * RtlZombifyActivationContext (NTDLL.@)
5378 * FIXME: function prototype might be wrong
5380 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5382 FIXME("%p: stub\n", handle);
5383 return STATUS_NOT_IMPLEMENTED;
5386 /******************************************************************
5387 * RtlActivateActivationContext (NTDLL.@)
5389 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5391 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5395 /******************************************************************
5396 * RtlActivateActivationContextEx (NTDLL.@)
5398 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5400 ACTIVATION_CONTEXT_STACK *actctx_stack = teb->ActivationContextStackPointer;
5401 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5403 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5404 return STATUS_NO_MEMORY;
5406 frame->Previous = actctx_stack->ActiveFrame;
5407 frame->ActivationContext = handle;
5408 frame->Flags = 0;
5409 actctx_stack->ActiveFrame = frame;
5410 RtlAddRefActivationContext( handle );
5412 *cookie = (ULONG_PTR)frame;
5413 TRACE( "%p cookie=%Ix\n", handle, *cookie );
5414 return STATUS_SUCCESS;
5418 /***********************************************************************
5419 * RtlDeactivateActivationContext (NTDLL.@)
5421 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5423 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
5424 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5426 TRACE( "%lx cookie=%Ix\n", flags, cookie );
5428 /* find the right frame */
5429 top = actctx_stack->ActiveFrame;
5430 for (frame = top; frame; frame = frame->Previous)
5431 if ((ULONG_PTR)frame == cookie) break;
5433 if (!frame)
5434 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5436 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5437 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5439 /* pop everything up to and including frame */
5440 actctx_stack->ActiveFrame = frame->Previous;
5442 while (top != actctx_stack->ActiveFrame)
5444 frame = top->Previous;
5445 RtlReleaseActivationContext( top->ActivationContext );
5446 RtlFreeHeap( GetProcessHeap(), 0, top );
5447 top = frame;
5452 /******************************************************************
5453 * RtlFreeThreadActivationContextStack (NTDLL.@)
5455 void WINAPI RtlFreeThreadActivationContextStack(void)
5457 RtlFreeActivationContextStack( NtCurrentTeb()->ActivationContextStackPointer );
5461 /******************************************************************
5462 * RtlFreeActivationContextStack (NTDLL.@)
5464 void WINAPI RtlFreeActivationContextStack( ACTIVATION_CONTEXT_STACK *actctx_stack )
5466 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5468 frame = actctx_stack->ActiveFrame;
5469 while (frame)
5471 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5472 RtlReleaseActivationContext( frame->ActivationContext );
5473 RtlFreeHeap( GetProcessHeap(), 0, frame );
5474 frame = prev;
5476 actctx_stack->ActiveFrame = NULL;
5480 /******************************************************************
5481 * RtlGetActiveActivationContext (NTDLL.@)
5483 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5485 RtlAddRefActivationContext( *handle = get_current_actctx_no_addref() );
5486 return STATUS_SUCCESS;
5490 /******************************************************************
5491 * RtlIsActivationContextActive (NTDLL.@)
5493 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5495 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
5496 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5498 for (frame = actctx_stack->ActiveFrame; frame; frame = frame->Previous)
5499 if (frame->ActivationContext == handle) return TRUE;
5500 return FALSE;
5504 /***********************************************************************
5505 * RtlQueryInformationActivationContext (NTDLL.@)
5507 * Get information about an activation context.
5508 * FIXME: function signature/prototype may be wrong
5510 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5511 ULONG class, PVOID buffer,
5512 SIZE_T bufsize, SIZE_T *retlen )
5514 ACTIVATION_CONTEXT *actctx;
5515 NTSTATUS status;
5517 TRACE("%08lx %p %p %lu %p %Id %p\n", flags, handle,
5518 subinst, class, buffer, bufsize, retlen);
5520 if (retlen) *retlen = 0;
5521 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5523 switch (class)
5525 case ActivationContextBasicInformation:
5527 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5529 if (retlen) *retlen = sizeof(*info);
5530 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5532 info->hActCtx = handle;
5533 info->dwFlags = 0; /* FIXME */
5534 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5536 break;
5538 case ActivationContextDetailedInformation:
5540 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5541 struct assembly *assembly = NULL;
5542 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5543 LPWSTR ptr;
5545 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5547 if (actctx->num_assemblies) assembly = actctx->assemblies;
5549 if (assembly && assembly->manifest.info)
5550 manifest_len = wcslen(assembly->manifest.info) + 1;
5551 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5552 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5553 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5555 if (retlen) *retlen = len;
5556 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5558 acdi->dwFlags = 0;
5559 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5560 acdi->ulAssemblyCount = actctx->num_assemblies;
5561 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5562 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5563 acdi->ulRootConfigurationPathType = actctx->config.type;
5564 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5565 acdi->ulAppDirPathType = actctx->appdir.type;
5566 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5567 ptr = (LPWSTR)(acdi + 1);
5568 if (manifest_len)
5570 acdi->lpRootManifestPath = ptr;
5571 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5572 ptr += manifest_len;
5574 else acdi->lpRootManifestPath = NULL;
5575 if (config_len)
5577 acdi->lpRootConfigurationPath = ptr;
5578 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5579 ptr += config_len;
5581 else acdi->lpRootConfigurationPath = NULL;
5582 if (appdir_len)
5584 acdi->lpAppDirPath = ptr;
5585 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5587 else acdi->lpAppDirPath = NULL;
5589 break;
5591 case AssemblyDetailedInformationInActivationContext:
5593 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5594 struct assembly *assembly;
5595 WCHAR *assembly_id;
5596 DWORD index;
5597 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5598 LPWSTR ptr;
5600 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5601 if (!subinst) return STATUS_INVALID_PARAMETER;
5603 index = *(DWORD*)subinst;
5604 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5606 assembly = &actctx->assemblies[index - 1];
5608 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5609 id_len = wcslen(assembly_id) + 1;
5610 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5612 if (assembly->manifest.info &&
5613 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5614 path_len = wcslen(assembly->manifest.info) + 1;
5616 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5618 if (retlen) *retlen = len;
5619 if (!buffer || bufsize < len)
5621 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5622 return STATUS_BUFFER_TOO_SMALL;
5625 afdi->ulFlags = 0; /* FIXME */
5626 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5627 afdi->ulManifestPathType = assembly->manifest.type;
5628 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5629 /* FIXME afdi->liManifestLastWriteTime = 0; */
5630 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5631 afdi->ulPolicyPathLength = 0;
5632 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5633 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5634 afdi->ulManifestVersionMajor = 1;
5635 afdi->ulManifestVersionMinor = 0;
5636 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5637 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5638 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5639 ptr = (LPWSTR)(afdi + 1);
5640 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5641 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5642 ptr += id_len;
5643 if (path_len)
5645 afdi->lpAssemblyManifestPath = ptr;
5646 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5647 ptr += path_len;
5648 } else afdi->lpAssemblyManifestPath = NULL;
5649 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5650 if (ad_len)
5652 afdi->lpAssemblyDirectoryName = ptr;
5653 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5655 else afdi->lpAssemblyDirectoryName = NULL;
5656 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5658 break;
5660 case FileInformationInAssemblyOfAssemblyInActivationContext:
5662 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5663 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5664 struct assembly *assembly;
5665 struct dll_redirect *dll;
5666 SIZE_T len, dll_len = 0;
5667 LPWSTR ptr;
5669 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5670 if (!acqi) return STATUS_INVALID_PARAMETER;
5672 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5673 return STATUS_INVALID_PARAMETER;
5674 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5676 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5677 return STATUS_INVALID_PARAMETER;
5678 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5680 if (dll->name) dll_len = wcslen(dll->name) + 1;
5681 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5683 if (!buffer || bufsize < len)
5685 if (retlen) *retlen = len;
5686 return STATUS_BUFFER_TOO_SMALL;
5688 if (retlen) *retlen = 0; /* yes that's what native does !! */
5689 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5690 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5691 afdi->ulPathLength = 0; /* FIXME */
5692 ptr = (LPWSTR)(afdi + 1);
5693 if (dll_len)
5695 afdi->lpFileName = ptr;
5696 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5697 } else afdi->lpFileName = NULL;
5698 afdi->lpFilePath = NULL; /* FIXME */
5700 break;
5702 case CompatibilityInformationInActivationContext:
5704 struct acci
5706 DWORD ElementCount;
5707 COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
5708 } *acci = buffer;
5709 struct assembly *assembly = NULL;
5710 ULONG num_compat_contexts = 0, n;
5711 SIZE_T len;
5713 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5715 if (actctx->num_assemblies) assembly = actctx->assemblies;
5717 if (assembly)
5718 num_compat_contexts = assembly->num_compat_contexts;
5719 len = offsetof( struct acci, Elements[num_compat_contexts] );
5721 if (retlen) *retlen = len;
5722 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5724 acci->ElementCount = num_compat_contexts;
5725 for (n = 0; n < num_compat_contexts; ++n)
5727 acci->Elements[n] = assembly->compat_contexts[n];
5730 break;
5732 case RunlevelInformationInActivationContext:
5734 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5735 struct assembly *assembly;
5736 SIZE_T len;
5738 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5740 len = sizeof(*acrli);
5741 if (retlen) *retlen = len;
5742 if (!buffer || bufsize < len)
5743 return STATUS_BUFFER_TOO_SMALL;
5745 assembly = actctx->assemblies;
5747 acrli->ulFlags = 0;
5748 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5749 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5751 break;
5753 default:
5754 FIXME( "class %lu not implemented\n", class );
5755 return STATUS_NOT_IMPLEMENTED;
5757 return STATUS_SUCCESS;
5760 /***********************************************************************
5761 * RtlFindActivationContextSectionString (NTDLL.@)
5763 * Find information about a string in an activation context.
5764 * FIXME: function signature/prototype may be wrong
5766 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5767 const UNICODE_STRING *section_name, PVOID ptr )
5769 PACTCTX_SECTION_KEYED_DATA data = ptr;
5770 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5771 ACTIVATION_CONTEXT *actctx;
5773 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(guid), section_kind,
5774 debugstr_us(section_name), data);
5776 if (guid)
5778 FIXME("expected guid == NULL\n");
5779 return STATUS_INVALID_PARAMETER;
5781 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5783 FIXME("unknown flags %08lx\n", flags);
5784 return STATUS_INVALID_PARAMETER;
5786 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5787 !section_name || !section_name->Buffer)
5789 WARN("invalid parameter\n");
5790 return STATUS_INVALID_PARAMETER;
5793 actctx = check_actctx( get_current_actctx_no_addref() );
5794 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5796 if (status != STATUS_SUCCESS)
5797 status = find_string( process_actctx, section_kind, section_name, flags, data );
5799 return status;
5802 /***********************************************************************
5803 * RtlFindActivationContextSectionGuid (NTDLL.@)
5805 * Find information about a GUID in an activation context.
5806 * FIXME: function signature/prototype may be wrong
5808 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5809 const GUID *guid, void *ptr )
5811 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5812 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5813 ACTIVATION_CONTEXT *actctx;
5815 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5817 if (extguid)
5819 FIXME("expected extguid == NULL\n");
5820 return STATUS_INVALID_PARAMETER;
5823 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5825 FIXME("unknown flags %08lx\n", flags);
5826 return STATUS_INVALID_PARAMETER;
5829 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5830 return STATUS_INVALID_PARAMETER;
5832 actctx = check_actctx( get_current_actctx_no_addref() );
5833 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5835 if (status != STATUS_SUCCESS)
5836 status = find_guid( process_actctx, section_kind, guid, flags, data );
5838 return status;
5842 /***********************************************************************
5843 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5845 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5846 const WCHAR *settings, WCHAR *buffer,
5847 SIZE_T size, SIZE_T *written )
5849 ACTIVATION_CONTEXT *actctx;
5850 const WCHAR *res;
5852 if (flags)
5854 WARN( "unknown flags %08lx\n", flags );
5855 return STATUS_INVALID_PARAMETER;
5858 if (ns)
5860 if (wcscmp( ns, windowsSettings2005NSW ) &&
5861 wcscmp( ns, windowsSettings2011NSW ) &&
5862 wcscmp( ns, windowsSettings2016NSW ) &&
5863 wcscmp( ns, windowsSettings2017NSW ) &&
5864 wcscmp( ns, windowsSettings2019NSW ) &&
5865 wcscmp( ns, windowsSettings2020NSW ))
5866 return STATUS_INVALID_PARAMETER;
5868 else ns = windowsSettings2005NSW;
5870 if (!handle) handle = process_actctx;
5871 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5873 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5875 if (written) *written = wcslen(res) + 1;
5876 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5877 wcscpy( buffer, res );
5878 return STATUS_SUCCESS;