windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / ntdll / actctx.c
blob73f852f2547b488cb8e03447ebb8155fbe6c25cf
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 #include "winternl.h"
32 #include "ddk/wdm.h"
33 #include "ntdll_misc.h"
34 #include "wine/exception.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
39 #define ACTCTX_FLAGS_ALL (\
40 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
41 ACTCTX_FLAG_LANGID_VALID |\
42 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
43 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
44 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
45 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
46 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
47 ACTCTX_FLAG_HMODULE_VALID )
49 #define ACTCTX_MAGIC 0xC07E3E11
50 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
51 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
53 /* we don't want to include winuser.h */
54 #define RT_MANIFEST ((ULONG_PTR)24)
55 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
57 /* from oaidl.h */
58 typedef enum tagLIBFLAGS {
59 LIBFLAG_FRESTRICTED = 0x1,
60 LIBFLAG_FCONTROL = 0x2,
61 LIBFLAG_FHIDDEN = 0x4,
62 LIBFLAG_FHASDISKIMAGE = 0x8
63 } LIBFLAGS;
65 /* from oleidl.idl */
66 typedef enum tagOLEMISC
68 OLEMISC_RECOMPOSEONRESIZE = 0x1,
69 OLEMISC_ONLYICONIC = 0x2,
70 OLEMISC_INSERTNOTREPLACE = 0x4,
71 OLEMISC_STATIC = 0x8,
72 OLEMISC_CANTLINKINSIDE = 0x10,
73 OLEMISC_CANLINKBYOLE1 = 0x20,
74 OLEMISC_ISLINKOBJECT = 0x40,
75 OLEMISC_INSIDEOUT = 0x80,
76 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
77 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
78 OLEMISC_INVISIBLEATRUNTIME = 0x400,
79 OLEMISC_ALWAYSRUN = 0x800,
80 OLEMISC_ACTSLIKEBUTTON = 0x1000,
81 OLEMISC_ACTSLIKELABEL = 0x2000,
82 OLEMISC_NOUIACTIVATE = 0x4000,
83 OLEMISC_ALIGNABLE = 0x8000,
84 OLEMISC_SIMPLEFRAME = 0x10000,
85 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
86 OLEMISC_IMEMODE = 0x40000,
87 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
88 OLEMISC_WANTSTOMENUMERGE = 0x100000,
89 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
90 } OLEMISC;
92 #define MAX_NAMESPACES 64
94 typedef struct
96 const WCHAR *ptr;
97 unsigned int len;
98 } xmlstr_t;
100 struct xml_elem
102 xmlstr_t name;
103 xmlstr_t ns;
104 int ns_pos;
107 struct xml_attr
109 xmlstr_t name;
110 xmlstr_t value;
113 typedef struct
115 const WCHAR *ptr;
116 const WCHAR *end;
117 struct xml_attr namespaces[MAX_NAMESPACES];
118 int ns_pos;
119 BOOL error;
120 } xmlbuf_t;
122 struct file_info
124 ULONG type;
125 WCHAR *info;
128 struct assembly_version
130 USHORT major;
131 USHORT minor;
132 USHORT build;
133 USHORT revision;
136 struct assembly_identity
138 WCHAR *name;
139 WCHAR *arch;
140 WCHAR *public_key;
141 WCHAR *language;
142 WCHAR *type;
143 struct assembly_version version;
144 BOOL optional;
145 BOOL delayed;
148 struct strsection_header
150 DWORD magic;
151 ULONG size;
152 DWORD unk1[3];
153 ULONG count;
154 ULONG index_offset;
155 DWORD unk2[2];
156 ULONG global_offset;
157 ULONG global_len;
160 struct string_index
162 ULONG hash; /* key string hash */
163 ULONG name_offset;
164 ULONG name_len;
165 ULONG data_offset; /* redirect data offset */
166 ULONG data_len;
167 ULONG rosterindex;
170 struct guidsection_header
172 DWORD magic;
173 ULONG size;
174 DWORD unk[3];
175 ULONG count;
176 ULONG index_offset;
177 DWORD unk2;
178 ULONG names_offset;
179 ULONG names_len;
182 struct guid_index
184 GUID guid;
185 ULONG data_offset;
186 ULONG data_len;
187 ULONG rosterindex;
190 struct wndclass_redirect_data
192 ULONG size;
193 DWORD res;
194 ULONG name_len;
195 ULONG name_offset; /* versioned name offset */
196 ULONG module_len;
197 ULONG module_offset;/* container name offset */
200 struct tlibredirect_data
202 ULONG size;
203 DWORD res;
204 ULONG name_len;
205 ULONG name_offset;
206 LANGID langid;
207 WORD flags;
208 ULONG help_len;
209 ULONG help_offset;
210 WORD major_version;
211 WORD minor_version;
214 enum comclass_threadingmodel
216 ThreadingModel_Apartment = 1,
217 ThreadingModel_Free = 2,
218 ThreadingModel_No = 3,
219 ThreadingModel_Both = 4,
220 ThreadingModel_Neutral = 5
223 enum comclass_miscfields
225 MiscStatus = 1,
226 MiscStatusIcon = 2,
227 MiscStatusContent = 4,
228 MiscStatusThumbnail = 8,
229 MiscStatusDocPrint = 16
232 struct comclassredirect_data
234 ULONG size;
235 ULONG flags;
236 DWORD model;
237 GUID clsid;
238 GUID alias;
239 GUID clsid2;
240 GUID tlbid;
241 ULONG name_len;
242 ULONG name_offset;
243 ULONG progid_len;
244 ULONG progid_offset;
245 ULONG clrdata_len;
246 ULONG clrdata_offset;
247 DWORD miscstatus;
248 DWORD miscstatuscontent;
249 DWORD miscstatusthumbnail;
250 DWORD miscstatusicon;
251 DWORD miscstatusdocprint;
254 enum ifaceps_mask
256 NumMethods = 1,
257 BaseIface = 2
260 struct ifacepsredirect_data
262 ULONG size;
263 DWORD mask;
264 GUID iid;
265 ULONG nummethods;
266 GUID tlbid;
267 GUID base;
268 ULONG name_len;
269 ULONG name_offset;
272 struct clrsurrogate_data
274 ULONG size;
275 DWORD res;
276 GUID clsid;
277 ULONG version_offset;
278 ULONG version_len;
279 ULONG name_offset;
280 ULONG name_len;
283 struct clrclass_data
285 ULONG size;
286 DWORD res[2];
287 ULONG module_len;
288 ULONG module_offset;
289 ULONG name_len;
290 ULONG name_offset;
291 ULONG version_len;
292 ULONG version_offset;
293 DWORD res2[2];
296 struct progidredirect_data
298 ULONG size;
299 DWORD reserved;
300 ULONG clsid_offset;
303 struct activatable_class_data
305 ULONG size;
306 DWORD unk;
307 DWORD module_len;
308 DWORD module_offset;
309 DWORD threading_model;
314 Sections structure.
316 Sections are accessible by string or guid key, that defines two types of sections.
317 All sections of each type have same magic value and header structure, index
318 data could be of two possible types too. So every string based section uses
319 the same index format, same applies to guid sections - they share same guid index
320 format.
322 - window class redirection section is a plain buffer with following format:
324 <section header>
325 <index[]>
326 <data[]> --- <original name>
327 <redirect data>
328 <versioned name>
329 <module name>
331 Header is fixed length structure - struct strsection_header,
332 contains redirected classes count;
334 Index is an array of fixed length index records, each record is
335 struct string_index.
337 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
339 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
340 others are relative to section itself.
342 - dll redirect section format:
344 <section header>
345 <index[]>
346 <data[]> --- <dll name>
347 <data>
349 This section doesn't seem to carry any payload data except dll names.
351 - typelib section format:
353 <section header>
354 <module names[]>
355 <index[]>
356 <data[]> --- <data>
357 <helpstring>
359 Header is fixed length, index is an array of fixed length 'struct guid_index'.
360 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
361 4-bytes aligned as a whole.
363 Module name offsets are relative to section, helpstring offset is relative to data
364 structure itself.
366 - comclass section format:
368 <section header>
369 <module names[]>
370 <index[]>
371 <data[]> --- <data> --- <data>
372 <progid> <clrdata>
373 <name>
374 <version>
375 <progid>
377 This section uses two index records per comclass, one entry contains original guid
378 as specified by context, another one has a generated guid. Index and strings handling
379 is similar to typelib sections.
381 For CLR classes additional data is stored after main COM class data, it contains
382 class name and runtime version string, see 'struct clrclass_data'.
384 Module name offsets are relative to section, progid offset is relative to data
385 structure itself.
387 - COM interface section format:
389 <section header>
390 <index[]>
391 <data[]> --- <data>
392 <name>
394 Interface section contains data for proxy/stubs and external proxy/stubs. External
395 ones are defined at assembly level, so this section has no module information.
396 All records are indexed with 'iid' value from manifest. There an exception for
397 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
398 redirect data, but index is still 'iid' from manifest.
400 Interface name offset is relative to data structure itself.
402 - CLR surrogates section format:
404 <section header>
405 <index[]>
406 <data[]> --- <data>
407 <name>
408 <version>
410 There's nothing special about this section, same way to store strings is used,
411 no modules part as it belongs to assembly level, not a file.
413 - ProgID section format:
415 <section header>
416 <guids[]>
417 <index[]>
418 <data[]> --- <progid>
419 <data>
421 This sections uses generated alias guids from COM server section. This way
422 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
423 is stored too, aligned.
425 - WinRT activatable class section is a plain buffer with following format:
427 <section header>
428 <module names[]>
429 <index[]>
430 <data[]> --- <class name>
431 <data>
433 Header is fixed length structure - struct strsection_header,
434 contains classes count;
436 Index is an array of fixed length index records, each record is
437 struct string_index.
439 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
441 All offsets are relative to section itself.
445 struct progids
447 WCHAR **progids;
448 unsigned int num;
449 unsigned int allocated;
452 struct entity
454 DWORD kind;
455 union
457 struct
459 WCHAR *tlbid;
460 WCHAR *helpdir;
461 WORD flags;
462 WORD major;
463 WORD minor;
464 } typelib;
465 struct
467 WCHAR *clsid;
468 WCHAR *tlbid;
469 WCHAR *progid;
470 WCHAR *name; /* clrClass: class name */
471 WCHAR *version; /* clrClass: CLR runtime version */
472 DWORD model;
473 DWORD miscstatus;
474 DWORD miscstatuscontent;
475 DWORD miscstatusthumbnail;
476 DWORD miscstatusicon;
477 DWORD miscstatusdocprint;
478 struct progids progids;
479 } comclass;
480 struct {
481 WCHAR *iid;
482 WCHAR *base;
483 WCHAR *tlib;
484 WCHAR *name;
485 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
486 DWORD mask;
487 ULONG nummethods;
488 } ifaceps;
489 struct
491 WCHAR *name;
492 BOOL versioned;
493 } class;
494 struct
496 WCHAR *name;
497 WCHAR *clsid;
498 WCHAR *version;
499 } clrsurrogate;
500 struct
502 WCHAR *name;
503 WCHAR *value;
504 WCHAR *ns;
505 } settings;
506 struct
508 WCHAR *name;
509 DWORD threading_model;
510 } activatable_class;
511 } u;
514 struct entity_array
516 struct entity *base;
517 unsigned int num;
518 unsigned int allocated;
521 struct dll_redirect
523 WCHAR *name;
524 WCHAR *load_from;
525 WCHAR *hash;
526 struct entity_array entities;
529 enum assembly_type
531 APPLICATION_MANIFEST,
532 ASSEMBLY_MANIFEST,
533 ASSEMBLY_SHARED_MANIFEST,
536 struct assembly
538 enum assembly_type type;
539 struct assembly_identity id;
540 struct file_info manifest;
541 WCHAR *directory;
542 BOOL no_inherit;
543 struct dll_redirect *dlls;
544 unsigned int num_dlls;
545 unsigned int allocated_dlls;
546 struct entity_array entities;
547 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
548 ULONG num_compat_contexts;
549 ACTCTX_REQUESTED_RUN_LEVEL run_level;
550 ULONG ui_access;
553 enum context_sections
555 WINDOWCLASS_SECTION = 1,
556 DLLREDIRECT_SECTION = 2,
557 TLIBREDIRECT_SECTION = 4,
558 SERVERREDIRECT_SECTION = 8,
559 IFACEREDIRECT_SECTION = 16,
560 CLRSURROGATES_SECTION = 32,
561 PROGIDREDIRECT_SECTION = 64,
562 ACTIVATABLE_CLASS_SECTION = 128,
565 typedef struct _ACTIVATION_CONTEXT
567 ULONG magic;
568 LONG ref_count;
569 struct file_info config;
570 struct file_info appdir;
571 struct assembly *assemblies;
572 unsigned int num_assemblies;
573 unsigned int allocated_assemblies;
574 /* section data */
575 DWORD sections;
576 struct strsection_header *wndclass_section;
577 struct strsection_header *dllredirect_section;
578 struct strsection_header *progid_section;
579 struct strsection_header *activatable_class_section;
580 struct guidsection_header *tlib_section;
581 struct guidsection_header *comserver_section;
582 struct guidsection_header *ifaceps_section;
583 struct guidsection_header *clrsurrogate_section;
584 } ACTIVATION_CONTEXT;
586 struct actctx_loader
588 ACTIVATION_CONTEXT *actctx;
589 struct assembly_identity *dependencies;
590 unsigned int num_dependencies;
591 unsigned int allocated_dependencies;
594 static const xmlstr_t empty_xmlstr;
596 #ifdef __i386__
597 static const WCHAR current_archW[] = L"x86";
598 #elif defined __x86_64__
599 static const WCHAR current_archW[] = L"amd64";
600 #elif defined __arm__
601 static const WCHAR current_archW[] = L"arm";
602 #elif defined __aarch64__
603 static const WCHAR current_archW[] = L"arm64";
604 #else
605 static const WCHAR current_archW[] = L"none";
606 #endif
608 static const WCHAR asmv1W[] = L"urn:schemas-microsoft-com:asm.v1";
609 static const WCHAR asmv2W[] = L"urn:schemas-microsoft-com:asm.v2";
610 static const WCHAR asmv3W[] = L"urn:schemas-microsoft-com:asm.v3";
611 static const WCHAR winrtv1W[] = L"urn:schemas-microsoft-com:winrt.v1";
612 static const WCHAR compatibilityNSW[] = L"urn:schemas-microsoft-com:compatibility.v1";
613 static const WCHAR windowsSettings2005NSW[] = L"http://schemas.microsoft.com/SMI/2005/WindowsSettings";
614 static const WCHAR windowsSettings2011NSW[] = L"http://schemas.microsoft.com/SMI/2011/WindowsSettings";
615 static const WCHAR windowsSettings2016NSW[] = L"http://schemas.microsoft.com/SMI/2016/WindowsSettings";
616 static const WCHAR windowsSettings2017NSW[] = L"http://schemas.microsoft.com/SMI/2017/WindowsSettings";
617 static const WCHAR windowsSettings2019NSW[] = L"http://schemas.microsoft.com/SMI/2019/WindowsSettings";
618 static const WCHAR windowsSettings2020NSW[] = L"http://schemas.microsoft.com/SMI/2020/WindowsSettings";
620 struct olemisc_entry
622 const WCHAR *name;
623 OLEMISC value;
626 static const struct olemisc_entry olemisc_values[] =
628 { L"activatewhenvisible", OLEMISC_ACTIVATEWHENVISIBLE },
629 { L"actslikebutton", OLEMISC_ACTSLIKEBUTTON },
630 { L"actslikelabel", OLEMISC_ACTSLIKELABEL },
631 { L"alignable", OLEMISC_ALIGNABLE },
632 { L"alwaysrun", OLEMISC_ALWAYSRUN },
633 { L"canlinkbyole1", OLEMISC_CANLINKBYOLE1 },
634 { L"cantlinkinside", OLEMISC_CANTLINKINSIDE },
635 { L"ignoreactivatewhenvisible", OLEMISC_IGNOREACTIVATEWHENVISIBLE },
636 { L"imemode", OLEMISC_IMEMODE },
637 { L"insertnotreplace", OLEMISC_INSERTNOTREPLACE },
638 { L"insideout", OLEMISC_INSIDEOUT },
639 { L"invisibleatruntime", OLEMISC_INVISIBLEATRUNTIME },
640 { L"islinkobject", OLEMISC_ISLINKOBJECT },
641 { L"nouiactivate", OLEMISC_NOUIACTIVATE },
642 { L"onlyiconic", OLEMISC_ONLYICONIC },
643 { L"recomposeonresize", OLEMISC_RECOMPOSEONRESIZE },
644 { L"renderingisdeviceindependent", OLEMISC_RENDERINGISDEVICEINDEPENDENT },
645 { L"setclientsitefirst", OLEMISC_SETCLIENTSITEFIRST },
646 { L"simpleframe", OLEMISC_SIMPLEFRAME },
647 { L"static", OLEMISC_STATIC },
648 { L"supportsmultilevelundo", OLEMISC_SUPPORTSMULTILEVELUNDO },
649 { L"wantstomenumerge", OLEMISC_WANTSTOMENUMERGE }
652 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
653 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
655 static WCHAR *strdupW(const WCHAR* str)
657 WCHAR* ptr;
659 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR))))
660 return NULL;
661 return wcscpy(ptr, str);
664 static WCHAR *xmlstrdupW(const xmlstr_t* str)
666 WCHAR *strW;
668 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
670 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
671 strW[str->len] = 0;
673 return strW;
676 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
678 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
681 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
683 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
686 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
688 return xmlstr_cmp( &attr->name, str );
691 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
693 return (elem1->name.len == elem2->name.len &&
694 elem1->ns.len == elem2->ns.len &&
695 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
696 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
699 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
701 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
702 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
703 if (!wcscmp( namespace, asmv1W ))
705 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
706 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
708 else if (!wcscmp( namespace, asmv2W ))
710 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
712 return FALSE;
715 static inline BOOL isxmlspace( WCHAR ch )
717 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
720 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
722 return debugstr_wn(str->ptr, str->len);
725 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
727 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
728 debugstr_wn( elem->ns.ptr, elem->ns.len ));
731 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
733 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
734 debugstr_wn( attr->value.ptr, attr->value.len ));
737 static inline const char* debugstr_version(const struct assembly_version *ver)
739 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
742 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
744 NTSTATUS status;
745 ULONG_PTR magic;
746 LDR_DATA_TABLE_ENTRY *pldr;
748 LdrLockLoaderLock(0, NULL, &magic);
749 status = LdrFindEntryForAddress( module, &pldr );
750 if (status == STATUS_SUCCESS)
752 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
753 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
755 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
756 str->Length = pldr->FullDllName.Length;
757 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
759 else status = STATUS_NO_MEMORY;
761 LdrUnlockLoaderLock(0, magic);
762 return status;
765 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
767 struct assembly *assembly;
769 if (actctx->num_assemblies == actctx->allocated_assemblies)
771 void *ptr;
772 unsigned int new_count;
773 if (actctx->assemblies)
775 new_count = actctx->allocated_assemblies * 2;
776 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
777 actctx->assemblies, new_count * sizeof(*assembly) );
779 else
781 new_count = 4;
782 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
784 if (!ptr) return NULL;
785 actctx->assemblies = ptr;
786 actctx->allocated_assemblies = new_count;
789 assembly = &actctx->assemblies[actctx->num_assemblies++];
790 assembly->type = at;
791 return assembly;
794 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
796 if (assembly->num_dlls == assembly->allocated_dlls)
798 void *ptr;
799 unsigned int new_count;
800 if (assembly->dlls)
802 new_count = assembly->allocated_dlls * 2;
803 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
804 assembly->dlls, new_count * sizeof(*assembly->dlls) );
806 else
808 new_count = 4;
809 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
811 if (!ptr) return NULL;
812 assembly->dlls = ptr;
813 assembly->allocated_dlls = new_count;
815 return &assembly->dlls[assembly->num_dlls++];
818 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
820 void *ptr;
821 if (assembly->num_compat_contexts)
823 unsigned int new_count = assembly->num_compat_contexts + 1;
824 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
825 assembly->compat_contexts,
826 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
828 else
830 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
832 if (!ptr) return NULL;
833 assembly->compat_contexts = ptr;
834 return &assembly->compat_contexts[assembly->num_compat_contexts++];
837 static void free_assembly_identity(struct assembly_identity *ai)
839 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
840 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
841 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
842 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
843 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
846 static struct entity* add_entity(struct entity_array *array, DWORD kind)
848 struct entity* entity;
850 if (array->num == array->allocated)
852 void *ptr;
853 unsigned int new_count;
854 if (array->base)
856 new_count = array->allocated * 2;
857 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
858 array->base, new_count * sizeof(*array->base) );
860 else
862 new_count = 4;
863 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
865 if (!ptr) return NULL;
866 array->base = ptr;
867 array->allocated = new_count;
869 entity = &array->base[array->num++];
870 entity->kind = kind;
871 return entity;
874 static void free_entity_array(struct entity_array *array)
876 unsigned int i, j;
877 for (i = 0; i < array->num; i++)
879 struct entity *entity = &array->base[i];
880 switch (entity->kind)
882 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
883 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
884 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
885 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
886 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
887 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
888 for (j = 0; j < entity->u.comclass.progids.num; j++)
889 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
890 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
891 break;
892 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
893 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
894 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
895 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
896 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
897 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
898 break;
899 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
900 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
901 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
902 break;
903 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
904 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
905 break;
906 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
907 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
908 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
909 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
910 break;
911 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
912 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
913 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
914 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
915 break;
916 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES:
917 RtlFreeHeap(GetProcessHeap(), 0, entity->u.activatable_class.name);
918 break;
919 default:
920 FIXME("Unknown entity kind %ld\n", entity->kind);
923 RtlFreeHeap( GetProcessHeap(), 0, array->base );
926 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
928 if (!str1) return !str2;
929 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE );
932 static BOOL is_matching_identity( const struct assembly_identity *id1,
933 const struct assembly_identity *id2 )
935 if (!is_matching_string( id1->name, id2->name )) return FALSE;
936 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
937 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
939 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language ))
941 if (wcscmp( L"*", id1->language ) && wcscmp( L"*", id2->language ))
942 return FALSE;
944 if (id1->version.major != id2->version.major) return FALSE;
945 if (id1->version.minor != id2->version.minor) return FALSE;
946 if (id1->version.build > id2->version.build) return FALSE;
947 if (id1->version.build == id2->version.build &&
948 id1->version.revision > id2->version.revision) return FALSE;
949 return TRUE;
952 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
953 struct assembly_identity* ai)
955 unsigned int i;
957 /* check if we already have that assembly */
959 for (i = 0; i < acl->actctx->num_assemblies; i++)
960 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
962 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
963 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
964 ai->version.build, ai->version.revision );
965 return TRUE;
968 for (i = 0; i < acl->num_dependencies; i++)
969 if (is_matching_identity( ai, &acl->dependencies[i] ))
971 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
972 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
973 ai->version.build, ai->version.revision );
974 return TRUE;
977 if (acl->num_dependencies == acl->allocated_dependencies)
979 void *ptr;
980 unsigned int new_count;
981 if (acl->dependencies)
983 new_count = acl->allocated_dependencies * 2;
984 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
985 new_count * sizeof(acl->dependencies[0]));
987 else
989 new_count = 4;
990 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
992 if (!ptr) return FALSE;
993 acl->dependencies = ptr;
994 acl->allocated_dependencies = new_count;
996 acl->dependencies[acl->num_dependencies++] = *ai;
998 return TRUE;
1001 static void free_depend_manifests(struct actctx_loader* acl)
1003 unsigned int i;
1004 for (i = 0; i < acl->num_dependencies; i++)
1005 free_assembly_identity(&acl->dependencies[i]);
1006 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1009 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1011 static const WCHAR mskeyW[] = L"deadbeef";
1012 const WCHAR *arch = ai->arch ? ai->arch : L"none";
1013 const WCHAR *key = ai->public_key ? ai->public_key : L"none";
1014 const WCHAR *lang = ai->language ? ai->language : L"none";
1015 const WCHAR *name = ai->name ? ai->name : L"none";
1016 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 +
1017 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1018 WCHAR *ret;
1020 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1022 wcscpy( ret, arch );
1023 wcscat( ret, L"_" );
1024 wcscat( ret, name );
1025 wcscat( ret, L"_" );
1026 wcscat( ret, key );
1027 wcscat( ret, L"_" );
1028 swprintf( ret + wcslen(ret), size - wcslen(ret), L"%u.%u.%u.%u",
1029 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1030 wcscat( ret, L"_" );
1031 wcscat( ret, lang );
1032 wcscat( ret, L"_" );
1033 wcscat( ret, mskeyW );
1034 return ret;
1037 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1039 WCHAR *p = buffer;
1041 if (!str) return;
1042 wcscat( buffer, prefix );
1043 p += wcslen(p);
1044 *p++ = '"';
1045 wcscpy( p, str );
1046 p += wcslen(p);
1047 *p++ = '"';
1048 *p = 0;
1051 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1053 WCHAR version[64], *ret;
1054 SIZE_T size = 0;
1056 swprintf( version, ARRAY_SIZE(version), L"%u.%u.%u.%u",
1057 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1058 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR);
1059 if (ai->arch) size += wcslen(L",processorArchitecture=") + wcslen(ai->arch) + 2;
1060 if (ai->public_key) size += wcslen(L",publicKeyToken=") + wcslen(ai->public_key) + 2;
1061 if (ai->type) size += wcslen(L",type=") + wcslen(ai->type) + 2;
1062 size += wcslen(L",version=") + wcslen(version) + 2;
1064 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1065 return NULL;
1067 if (ai->name) wcscpy( ret, ai->name );
1068 else *ret = 0;
1069 append_string( ret, L",processorArchitecture=", ai->arch );
1070 append_string( ret, L",publicKeyToken=", ai->public_key );
1071 append_string( ret, L",type=", ai->type );
1072 append_string( ret, L",version=", version );
1073 return ret;
1076 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1078 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1080 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1081 __TRY
1083 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1085 __EXCEPT_PAGE_FAULT
1088 __ENDTRY
1089 return ret;
1092 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1094 InterlockedIncrement( &actctx->ref_count );
1097 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1099 if (!InterlockedDecrement( &actctx->ref_count ))
1101 unsigned int i, j;
1103 for (i = 0; i < actctx->num_assemblies; i++)
1105 struct assembly *assembly = &actctx->assemblies[i];
1106 for (j = 0; j < assembly->num_dlls; j++)
1108 struct dll_redirect *dll = &assembly->dlls[j];
1109 free_entity_array( &dll->entities );
1110 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1111 RtlFreeHeap( GetProcessHeap(), 0, dll->load_from );
1112 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1114 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1115 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1116 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1117 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1118 free_entity_array( &assembly->entities );
1119 free_assembly_identity(&assembly->id);
1121 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1125 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1127 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1128 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1129 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1130 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1131 RtlFreeHeap( GetProcessHeap(), 0, actctx->activatable_class_section );
1132 actctx->magic = 0;
1133 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1137 static BOOL set_error( xmlbuf_t *xmlbuf )
1139 xmlbuf->error = TRUE;
1140 return FALSE;
1143 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1145 const int len = wcslen( L"xmlns" );
1146 if (attr->name.len < len) return FALSE;
1147 if (wcsncmp( attr->name.ptr, L"xmlns", len )) return FALSE;
1148 return (attr->name.len == len || attr->name.ptr[len] == ':');
1151 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1153 const int len = wcslen( L"xmlns" );
1154 struct xml_attr *ns;
1156 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1158 FIXME( "too many namespaces in manifest\n" );
1159 set_error( xmlbuf );
1160 return;
1162 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1163 ns->value = attr->value;
1164 if (attr->name.len > len)
1166 ns->name.ptr = attr->name.ptr + len + 1;
1167 ns->name.len = attr->name.len - len - 1;
1169 else ns->name = empty_xmlstr;
1172 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1174 int i;
1176 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1178 if (xmlbuf->namespaces[i].name.len == name->len &&
1179 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1180 return xmlbuf->namespaces[i].value;
1182 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1183 return empty_xmlstr;
1186 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1188 const WCHAR* ptr;
1189 WCHAR quote;
1191 if (xmlbuf->error) return FALSE;
1193 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1194 xmlbuf->ptr++;
1196 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1198 if (*xmlbuf->ptr == '/')
1200 xmlbuf->ptr++;
1201 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1202 return set_error( xmlbuf );
1204 xmlbuf->ptr++;
1205 *end = TRUE;
1206 return FALSE;
1209 if (*xmlbuf->ptr == '>')
1211 xmlbuf->ptr++;
1212 return FALSE;
1215 ptr = xmlbuf->ptr;
1216 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1218 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1220 attr->name.ptr = xmlbuf->ptr;
1221 attr->name.len = ptr-xmlbuf->ptr;
1222 xmlbuf->ptr = ptr;
1224 /* skip spaces before '=' */
1225 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1226 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1228 /* skip '=' itself */
1229 ptr++;
1230 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1232 /* skip spaces after '=' */
1233 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1235 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1237 quote = *ptr++;
1238 attr->value.ptr = ptr;
1239 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1241 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1242 if (ptr == xmlbuf->end)
1244 xmlbuf->ptr = xmlbuf->end;
1245 return set_error( xmlbuf );
1248 attr->value.len = ptr - attr->value.ptr;
1249 xmlbuf->ptr = ptr + 1;
1250 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1252 return set_error( xmlbuf );
1255 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1257 const WCHAR* ptr = xmlbuf->ptr;
1259 elem->ns = empty_xmlstr;
1260 elem->name.ptr = ptr;
1261 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1263 if (*ptr == ':')
1265 elem->ns.ptr = elem->name.ptr;
1266 elem->ns.len = ptr - elem->ns.ptr;
1267 elem->name.ptr = ptr + 1;
1269 ptr++;
1271 elem->name.len = ptr - elem->name.ptr;
1272 xmlbuf->ptr = ptr;
1275 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1277 const WCHAR* ptr;
1278 struct xml_attr attr;
1279 xmlbuf_t attr_buf;
1280 BOOL end = FALSE;
1282 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1284 if (xmlbuf->error) return FALSE;
1286 for (;;)
1288 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1289 if (ptr == xmlbuf->end)
1291 xmlbuf->ptr = xmlbuf->end;
1292 return set_error( xmlbuf );
1294 ptr++;
1295 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1297 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1298 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1300 if (ptr + 3 > xmlbuf->end)
1302 xmlbuf->ptr = xmlbuf->end;
1303 return set_error( xmlbuf );
1305 xmlbuf->ptr = ptr + 3;
1307 else break;
1310 xmlbuf->ptr = ptr;
1311 /* check for element terminating the parent element */
1312 if (ptr < xmlbuf->end && *ptr == '/')
1314 xmlbuf->ptr++;
1315 read_xml_elem( xmlbuf, elem );
1316 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1317 if (!xml_name_cmp( elem, parent ))
1319 ERR( "wrong closing element %s for %s\n",
1320 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1321 return set_error( xmlbuf );
1323 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1324 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1325 return FALSE;
1328 read_xml_elem( xmlbuf, elem );
1330 /* parse namespace attributes */
1331 attr_buf = *xmlbuf;
1332 while (next_xml_attr( &attr_buf, &attr, &end ))
1334 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1336 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1337 elem->ns_pos = xmlbuf->ns_pos;
1339 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1341 return set_error( xmlbuf );
1344 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1346 /* FIXME: parse attributes */
1347 const WCHAR *ptr;
1349 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1351 if (ptr[0] == '?' && ptr[1] == '>')
1353 xmlbuf->ptr = ptr + 2;
1354 return TRUE;
1357 return FALSE;
1360 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1362 const WCHAR *ptr;
1364 if (xmlbuf->error) return FALSE;
1366 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1367 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1369 content->ptr = xmlbuf->ptr;
1370 content->len = ptr - xmlbuf->ptr;
1371 xmlbuf->ptr = ptr;
1373 return TRUE;
1376 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1378 unsigned int ver[4];
1379 unsigned int pos;
1380 const WCHAR *curr;
1382 /* major.minor.build.revision */
1383 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1384 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1386 if (*curr >= '0' && *curr <= '9')
1388 ver[pos] = ver[pos] * 10 + *curr - '0';
1389 if (ver[pos] >= 0x10000) goto error;
1391 else if (*curr == '.')
1393 if (++pos >= 4) goto error;
1395 else goto error;
1397 version->major = ver[0];
1398 version->minor = ver[1];
1399 version->build = ver[2];
1400 version->revision = ver[3];
1401 return TRUE;
1403 error:
1404 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1405 return FALSE;
1408 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1410 struct xml_attr attr;
1412 while (next_xml_attr(xmlbuf, &attr, end))
1414 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1418 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1420 struct xml_elem elem;
1422 if (next_xml_elem(xmlbuf, &elem, parent))
1424 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1425 set_error( xmlbuf );
1429 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1431 struct xml_elem elem;
1432 struct xml_attr attr;
1433 BOOL end = FALSE;
1435 while (next_xml_attr(xmlbuf, &attr, &end));
1436 if (end) return;
1438 while (next_xml_elem(xmlbuf, &elem, parent))
1439 parse_unknown_elem(xmlbuf, &elem);
1442 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1443 struct assembly_identity* ai, const struct xml_elem *parent)
1445 struct xml_attr attr;
1446 BOOL end = FALSE;
1448 while (next_xml_attr(xmlbuf, &attr, &end))
1450 if (xml_attr_cmp(&attr, L"name"))
1452 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1454 else if (xml_attr_cmp(&attr, L"type"))
1456 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1458 else if (xml_attr_cmp(&attr, L"version"))
1460 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1462 else if (xml_attr_cmp(&attr, L"processorArchitecture"))
1464 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1466 else if (xml_attr_cmp(&attr, L"publicKeyToken"))
1468 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1470 else if (xml_attr_cmp(&attr, L"language"))
1472 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1474 else if (!is_xmlns_attr( &attr ))
1476 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1480 TRACE( "name=%s version=%s arch=%s\n",
1481 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1483 if (!end) parse_expect_end_elem(xmlbuf, parent);
1486 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1488 if (value->len == 0) return ThreadingModel_No;
1489 if (xmlstr_cmp(value, L"Apartment"))
1490 return ThreadingModel_Apartment;
1491 else if (xmlstr_cmp(value, L"Free"))
1492 return ThreadingModel_Free;
1493 else if (xmlstr_cmp(value, L"Both"))
1494 return ThreadingModel_Both;
1495 else if (xmlstr_cmp(value, L"Neutral"))
1496 return ThreadingModel_Neutral;
1497 else
1498 return ThreadingModel_No;
1501 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1503 int min, max;
1505 min = 0;
1506 max = ARRAY_SIZE(olemisc_values) - 1;
1508 while (min <= max)
1510 int n, c;
1512 n = (min+max)/2;
1514 c = wcsncmp(olemisc_values[n].name, str, len);
1515 if (!c && !olemisc_values[n].name[len])
1516 return olemisc_values[n].value;
1518 if (c >= 0)
1519 max = n-1;
1520 else
1521 min = n+1;
1524 WARN("unknown flag %s\n", debugstr_wn(str, len));
1525 return 0;
1528 static DWORD parse_com_class_misc(const xmlstr_t *value)
1530 const WCHAR *str = value->ptr, *start;
1531 DWORD flags = 0;
1532 int i = 0;
1534 /* it's comma separated list of flags */
1535 while (i < value->len)
1537 start = str;
1538 while (*str != ',' && (i++ < value->len)) str++;
1540 flags |= get_olemisc_value(start, str-start);
1542 /* skip separator */
1543 str++;
1544 i++;
1547 return flags;
1550 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1552 struct progids *progids = &entity->u.comclass.progids;
1554 if (progids->allocated == 0)
1556 progids->allocated = 4;
1557 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1560 if (progids->allocated == progids->num)
1562 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1563 2 * progids->allocated * sizeof(WCHAR*));
1564 if (!new_progids) return FALSE;
1565 progids->allocated *= 2;
1566 progids->progids = new_progids;
1569 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1570 progids->num++;
1572 return TRUE;
1575 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1577 xmlstr_t content;
1578 BOOL end = FALSE;
1580 parse_expect_no_attr(xmlbuf, &end);
1581 if (end) set_error( xmlbuf );
1582 if (!parse_text_content(xmlbuf, &content)) return;
1584 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1585 parse_expect_end_elem(xmlbuf, parent);
1588 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1589 const struct xml_elem *parent )
1591 struct xml_elem elem;
1592 struct xml_attr attr;
1593 BOOL end = FALSE;
1594 struct entity* entity;
1596 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1598 set_error( xmlbuf );
1599 return;
1602 while (next_xml_attr(xmlbuf, &attr, &end))
1604 if (xml_attr_cmp(&attr, L"clsid"))
1606 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1608 else if (xml_attr_cmp(&attr, L"progid"))
1610 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1612 else if (xml_attr_cmp(&attr, L"tlbid"))
1614 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1616 else if (xml_attr_cmp(&attr, L"threadingModel"))
1618 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1620 else if (xml_attr_cmp(&attr, L"miscStatus"))
1622 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1624 else if (xml_attr_cmp(&attr, L"miscStatusContent"))
1626 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1628 else if (xml_attr_cmp(&attr, L"miscStatusThumbnail"))
1630 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1632 else if (xml_attr_cmp(&attr, L"miscStatusIcon"))
1634 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1636 else if (xml_attr_cmp(&attr, L"miscStatusDocPrint"))
1638 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1640 else if (xml_attr_cmp(&attr, L"description"))
1642 /* not stored */
1644 else if (!is_xmlns_attr( &attr ))
1646 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1650 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1651 if (entity->u.comclass.progid)
1652 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1654 if (end) return;
1656 while (next_xml_elem(xmlbuf, &elem, parent))
1658 if (xml_elem_cmp(&elem, L"progid", asmv1W))
1660 parse_com_class_progid(xmlbuf, entity, &elem);
1662 else
1664 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1665 parse_unknown_elem(xmlbuf, &elem);
1669 if (entity->u.comclass.progids.num)
1670 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1673 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1675 const WCHAR *curr;
1676 ULONG num = 0;
1678 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1680 if (*curr >= '0' && *curr <= '9')
1681 num = num * 10 + *curr - '0';
1682 else
1684 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1685 return FALSE;
1688 entity->u.ifaceps.nummethods = num;
1690 return TRUE;
1693 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1694 struct actctx_loader *acl, WCHAR *clsid )
1696 struct entity *entity;
1697 WCHAR *str;
1699 if (!clsid) return;
1701 if (!(str = strdupW(clsid)))
1703 set_error( xmlbuf );
1704 return;
1707 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1709 RtlFreeHeap(GetProcessHeap(), 0, str);
1710 set_error( xmlbuf );
1711 return;
1714 entity->u.comclass.clsid = str;
1715 entity->u.comclass.model = ThreadingModel_Both;
1717 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1720 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1721 struct actctx_loader *acl, const struct xml_elem *parent )
1723 WCHAR *psclsid = NULL;
1724 struct entity *entity;
1725 struct xml_attr attr;
1726 BOOL end = FALSE;
1728 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1730 set_error( xmlbuf );
1731 return;
1734 while (next_xml_attr(xmlbuf, &attr, &end))
1736 if (xml_attr_cmp(&attr, L"iid"))
1738 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1740 else if (xml_attr_cmp(&attr, L"name"))
1742 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1744 else if (xml_attr_cmp(&attr, L"baseInterface"))
1746 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1747 entity->u.ifaceps.mask |= BaseIface;
1749 else if (xml_attr_cmp(&attr, L"numMethods"))
1751 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1752 entity->u.ifaceps.mask |= NumMethods;
1754 else if (xml_attr_cmp(&attr, L"tlbid"))
1756 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1758 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
1760 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1762 /* not used */
1763 else if (xml_attr_cmp(&attr, L"threadingModel"))
1766 else if (!is_xmlns_attr( &attr ))
1768 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1772 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1773 if (!end) parse_expect_end_elem(xmlbuf, parent);
1775 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1777 RtlFreeHeap(GetProcessHeap(), 0, psclsid);
1780 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1782 WORD *flags = &entity->u.typelib.flags;
1783 const WCHAR *str = value->ptr, *start;
1784 int i = 0;
1786 *flags = 0;
1788 /* it's comma separated list of flags */
1789 while (i < value->len)
1791 start = str;
1792 while (*str != ',' && (i++ < value->len)) str++;
1794 if (!wcsnicmp(start, L"RESTRICTED", str-start))
1795 *flags |= LIBFLAG_FRESTRICTED;
1796 else if (!wcsnicmp(start, L"CONTROL", str-start))
1797 *flags |= LIBFLAG_FCONTROL;
1798 else if (!wcsnicmp(start, L"HIDDEN", str-start))
1799 *flags |= LIBFLAG_FHIDDEN;
1800 else if (!wcsnicmp(start, L"HASDISKIMAGE", str-start))
1801 *flags |= LIBFLAG_FHASDISKIMAGE;
1802 else
1804 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1805 return FALSE;
1808 /* skip separator */
1809 str++;
1810 i++;
1813 return TRUE;
1816 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1818 unsigned int ver[2];
1819 unsigned int pos;
1820 const WCHAR *curr;
1822 /* major.minor */
1823 ver[0] = ver[1] = pos = 0;
1824 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1826 if (*curr >= '0' && *curr <= '9')
1828 ver[pos] = ver[pos] * 10 + *curr - '0';
1829 if (ver[pos] >= 0x10000) goto error;
1831 else if (*curr == '.')
1833 if (++pos >= 2) goto error;
1835 else goto error;
1837 entity->u.typelib.major = ver[0];
1838 entity->u.typelib.minor = ver[1];
1839 return TRUE;
1841 error:
1842 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1843 return FALSE;
1846 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1847 struct actctx_loader *acl, const struct xml_elem *parent )
1849 struct xml_attr attr;
1850 BOOL end = FALSE;
1851 struct entity* entity;
1853 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1855 set_error( xmlbuf );
1856 return;
1859 while (next_xml_attr(xmlbuf, &attr, &end))
1861 if (xml_attr_cmp(&attr, L"tlbid"))
1863 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1865 else if (xml_attr_cmp(&attr, L"version"))
1867 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1869 else if (xml_attr_cmp(&attr, L"helpdir"))
1871 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1873 else if (xml_attr_cmp(&attr, L"flags"))
1875 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1877 else if (!is_xmlns_attr( &attr ))
1879 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1883 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1884 if (!end) parse_expect_end_elem(xmlbuf, parent);
1887 static inline int aligned_string_len(int len)
1889 return (len + 3) & ~3;
1892 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1894 struct assembly_version *ver = &assembly->id.version;
1895 WCHAR buff[25];
1897 if (!ret) ret = buff;
1898 return swprintf(ret, ARRAY_SIZE(buff), L"%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
1901 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1902 struct actctx_loader *acl, const struct xml_elem *parent )
1904 struct xml_elem elem;
1905 struct xml_attr attr;
1906 xmlstr_t content;
1907 BOOL end = FALSE;
1908 struct entity* entity;
1910 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1912 set_error( xmlbuf );
1913 return;
1915 entity->u.class.versioned = TRUE;
1916 while (next_xml_attr(xmlbuf, &attr, &end))
1918 if (xml_attr_cmp(&attr, L"versioned"))
1920 if (xmlstr_cmpi(&attr.value, L"no"))
1921 entity->u.class.versioned = FALSE;
1922 else if (!xmlstr_cmpi(&attr.value, L"yes"))
1923 set_error( xmlbuf );
1925 else if (!is_xmlns_attr( &attr ))
1927 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1931 if (end) return;
1933 if (!parse_text_content(xmlbuf, &content)) return;
1934 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1936 acl->actctx->sections |= WINDOWCLASS_SECTION;
1938 while (next_xml_elem(xmlbuf, &elem, parent))
1940 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1941 parse_unknown_elem(xmlbuf, &elem);
1945 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1947 struct xml_attr attr;
1948 BOOL end = FALSE;
1950 while (next_xml_attr(xmlbuf, &attr, &end))
1952 if (xml_attr_cmp(&attr, L"oldVersion"))
1954 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1956 else if (xml_attr_cmp(&attr, L"newVersion"))
1958 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1960 else if (!is_xmlns_attr( &attr ))
1962 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1966 if (!end) parse_expect_end_elem(xmlbuf, parent);
1969 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1971 struct xml_elem elem;
1972 struct xml_attr attr;
1973 xmlstr_t content;
1974 BOOL end = FALSE;
1976 while (next_xml_attr(xmlbuf, &attr, &end))
1978 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1981 if (end) return;
1982 if (!parse_text_content(xmlbuf, &content)) return;
1984 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1986 while (next_xml_elem(xmlbuf, &elem, parent))
1988 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1989 parse_unknown_elem(xmlbuf, &elem);
1993 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
1994 struct assembly* assembly,
1995 struct actctx_loader* acl,
1996 const struct xml_elem *parent)
1998 struct xml_attr attr;
1999 BOOL end = FALSE;
2000 struct entity* entity;
2002 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2004 set_error( xmlbuf );
2005 return;
2008 while (next_xml_attr(xmlbuf, &attr, &end))
2010 if (xml_attr_cmp(&attr, L"iid"))
2012 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2014 else if (xml_attr_cmp(&attr, L"name"))
2016 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2018 else if (xml_attr_cmp(&attr, L"baseInterface"))
2020 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2021 entity->u.ifaceps.mask |= BaseIface;
2023 else if (xml_attr_cmp(&attr, L"numMethods"))
2025 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2026 entity->u.ifaceps.mask |= NumMethods;
2028 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
2030 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2032 else if (xml_attr_cmp(&attr, L"tlbid"))
2034 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2036 else if (!is_xmlns_attr( &attr ))
2038 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2042 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2043 if (!end) parse_expect_end_elem(xmlbuf, parent);
2046 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2047 struct actctx_loader *acl, const struct xml_elem *parent )
2050 struct xml_elem elem;
2051 struct xml_attr attr;
2052 BOOL end = FALSE;
2053 struct entity* entity;
2055 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2057 set_error( xmlbuf );
2058 return;
2061 while (next_xml_attr(xmlbuf, &attr, &end))
2063 if (xml_attr_cmp(&attr, L"name"))
2065 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2067 else if (xml_attr_cmp(&attr, L"clsid"))
2069 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2071 else if (xml_attr_cmp(&attr, L"progid"))
2073 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2075 else if (xml_attr_cmp(&attr, L"tlbid"))
2077 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2079 else if (xml_attr_cmp(&attr, L"threadingModel"))
2081 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2083 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2085 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2087 else if (!is_xmlns_attr( &attr ))
2089 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2093 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2094 if (entity->u.comclass.progid)
2095 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2096 if (end) return;
2098 while (next_xml_elem(xmlbuf, &elem, parent))
2100 if (xml_elem_cmp(&elem, L"progid", asmv1W))
2102 parse_com_class_progid(xmlbuf, entity, &elem);
2104 else
2106 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2107 parse_unknown_elem(xmlbuf, &elem);
2111 if (entity->u.comclass.progids.num)
2112 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2115 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2116 struct actctx_loader *acl, const struct xml_elem *parent )
2118 struct xml_attr attr;
2119 BOOL end = FALSE;
2120 struct entity* entity;
2122 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2124 set_error( xmlbuf );
2125 return;
2128 while (next_xml_attr(xmlbuf, &attr, &end))
2130 if (xml_attr_cmp(&attr, L"name"))
2132 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2134 else if (xml_attr_cmp(&attr, L"clsid"))
2136 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2138 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2140 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2142 else if (!is_xmlns_attr( &attr ))
2144 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2148 acl->actctx->sections |= CLRSURROGATES_SECTION;
2149 if (!end) parse_expect_end_elem(xmlbuf, parent);
2152 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2153 const struct xml_elem *parent, BOOL optional )
2155 struct xml_elem elem;
2156 struct xml_attr attr;
2157 struct assembly_identity ai;
2158 BOOL end = FALSE;
2160 memset(&ai, 0, sizeof(ai));
2161 ai.optional = optional;
2163 while (next_xml_attr(xmlbuf, &attr, &end))
2165 if (xml_attr_cmp(&attr, L"allowDelayedBinding"))
2166 ai.delayed = xmlstr_cmp(&attr.value, L"true");
2167 else if (!is_xmlns_attr( &attr ))
2168 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2171 if (end) return;
2173 while (next_xml_elem(xmlbuf, &elem, parent))
2175 if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2177 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2178 /* store the newly found identity for later loading */
2179 if (ai.arch && !wcscmp(ai.arch, L"*"))
2181 RtlFreeHeap( GetProcessHeap(), 0, ai.arch );
2182 ai.arch = strdupW( current_archW );
2184 TRACE( "adding name=%s version=%s arch=%s\n",
2185 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2186 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2188 else if (xml_elem_cmp(&elem, L"bindingRedirect", asmv1W))
2190 parse_binding_redirect_elem(xmlbuf, &elem);
2192 else
2194 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2195 parse_unknown_elem(xmlbuf, &elem);
2200 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2201 const struct xml_elem *parent )
2204 struct xml_elem elem;
2205 struct xml_attr attr;
2206 BOOL end = FALSE, optional = FALSE;
2208 while (next_xml_attr(xmlbuf, &attr, &end))
2210 if (xml_attr_cmp(&attr, L"optional"))
2212 optional = xmlstr_cmpi( &attr.value, L"yes" );
2213 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2215 else if (!is_xmlns_attr( &attr ))
2217 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2221 if (end) return;
2223 while (next_xml_elem(xmlbuf, &elem, parent))
2225 if (xml_elem_cmp(&elem, L"dependentAssembly", asmv1W))
2227 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2229 else
2231 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2232 parse_unknown_elem(xmlbuf, &elem);
2237 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2239 BOOL end = FALSE;
2241 parse_expect_no_attr(xmlbuf, &end);
2242 if (!end) parse_expect_end_elem(xmlbuf, parent);
2245 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2247 BOOL end = FALSE;
2249 parse_expect_no_attr(xmlbuf, &end);
2250 if (!end) parse_expect_end_elem(xmlbuf, parent);
2253 static void parse_activatable_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
2254 struct actctx_loader *acl, const struct xml_elem *parent )
2256 struct xml_elem elem;
2257 struct xml_attr attr;
2258 BOOL end = FALSE;
2259 struct entity *entity;
2261 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)))
2263 set_error( xmlbuf );
2264 return;
2266 while (next_xml_attr(xmlbuf, &attr, &end))
2268 if (xml_attr_cmp(&attr, L"name"))
2270 if (!(entity->u.activatable_class.name = xmlstrdupW(&attr.value)))
2271 set_error( xmlbuf );
2273 else if (xml_attr_cmp(&attr, L"threadingModel"))
2275 if (xmlstr_cmpi(&attr.value, L"both"))
2276 entity->u.activatable_class.threading_model = 0;
2277 else if (xmlstr_cmpi(&attr.value, L"sta"))
2278 entity->u.activatable_class.threading_model = 1;
2279 else if (xmlstr_cmpi(&attr.value, L"mta"))
2280 entity->u.activatable_class.threading_model = 2;
2281 else
2282 set_error( xmlbuf );
2284 else if (!is_xmlns_attr( &attr ))
2286 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2290 acl->actctx->sections |= ACTIVATABLE_CLASS_SECTION;
2292 if (end) return;
2294 while (next_xml_elem(xmlbuf, &elem, parent))
2296 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2297 parse_unknown_elem(xmlbuf, &elem);
2301 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2302 struct actctx_loader* acl, const struct xml_elem *parent )
2304 struct xml_elem elem;
2305 struct xml_attr attr;
2306 BOOL end = FALSE;
2307 struct dll_redirect* dll;
2309 if (!(dll = add_dll_redirect(assembly)))
2311 set_error( xmlbuf );
2312 return;
2315 while (next_xml_attr(xmlbuf, &attr, &end))
2317 if (xml_attr_cmp(&attr, L"name"))
2319 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2320 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2322 else if (xml_attr_cmp(&attr, L"loadFrom"))
2324 if (!(dll->load_from = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2326 else if (xml_attr_cmp(&attr, L"hash"))
2328 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2330 else if (xml_attr_cmp(&attr, L"hashalg"))
2332 if (!xmlstr_cmpi(&attr.value, L"SHA1"))
2333 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2335 else if (!is_xmlns_attr( &attr ))
2337 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2341 if (!dll->name) set_error( xmlbuf );
2343 acl->actctx->sections |= DLLREDIRECT_SECTION;
2345 if (end) return;
2347 while (next_xml_elem(xmlbuf, &elem, parent))
2349 if (xml_elem_cmp(&elem, L"comClass", asmv1W))
2351 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2353 else if (xml_elem_cmp(&elem, L"comInterfaceProxyStub", asmv1W))
2355 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2357 else if (xml_elem_cmp(&elem, L"hash", asmv2W))
2359 WARN("asmv2:hash (undocumented) not supported\n");
2360 parse_unknown_elem(xmlbuf, &elem);
2362 else if (xml_elem_cmp(&elem, L"typelib", asmv1W))
2364 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2366 else if (xml_elem_cmp(&elem, L"windowClass", asmv1W))
2368 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2370 else if (xml_elem_cmp(&elem, L"activatableClass", winrtv1W))
2372 parse_activatable_class_elem(xmlbuf, dll, acl, &elem);
2374 else
2376 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2377 parse_unknown_elem( xmlbuf, &elem );
2382 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2383 struct actctx_loader *acl, const struct xml_elem *parent )
2385 struct xml_attr attr;
2386 BOOL end = FALSE;
2388 while (next_xml_attr(xmlbuf, &attr, &end))
2390 if (xml_attr_cmp(&attr, L"Id"))
2392 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2393 UNICODE_STRING str;
2394 GUID compat_id;
2396 str.Buffer = (PWSTR)attr.value.ptr;
2397 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2398 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2400 if (!(compat = add_compat_context(assembly)))
2402 set_error( xmlbuf );
2403 return;
2405 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2406 compat->Id = compat_id;
2408 else
2410 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2413 else if (!is_xmlns_attr( &attr ))
2415 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2419 if (!end) parse_expect_end_elem(xmlbuf, parent);
2422 static void parse_maxversiontested_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2423 struct actctx_loader *acl, const struct xml_elem *parent )
2425 struct xml_attr attr;
2426 BOOL end = FALSE;
2428 while (next_xml_attr(xmlbuf, &attr, &end))
2430 if (xml_attr_cmp(&attr, L"Id"))
2432 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2433 struct assembly_version version;
2435 if (!(compat = add_compat_context(assembly)))
2437 set_error( xmlbuf );
2438 return;
2440 parse_version( &attr.value, &version );
2441 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED;
2442 compat->MaxVersionTested = (ULONGLONG)version.major << 48 |
2443 (ULONGLONG)version.minor << 32 | version.build << 16 | version.revision;
2445 else if (!is_xmlns_attr( &attr ))
2447 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2451 if (!end) parse_expect_end_elem(xmlbuf, parent);
2454 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2455 struct actctx_loader* acl, const struct xml_elem *parent)
2457 struct xml_elem elem;
2459 while (next_xml_elem(xmlbuf, &elem, parent))
2461 if (xml_elem_cmp(&elem, L"supportedOS", compatibilityNSW))
2463 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2465 else if (xml_elem_cmp(&elem, L"maxversiontested", compatibilityNSW))
2467 parse_maxversiontested_elem(xmlbuf, assembly, acl, &elem);
2469 else
2471 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2472 parse_unknown_elem(xmlbuf, &elem);
2477 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2478 struct actctx_loader* acl, const struct xml_elem *parent)
2480 struct xml_elem elem;
2482 while (next_xml_elem(xmlbuf, &elem, parent))
2484 if (xml_elem_cmp(&elem, L"application", compatibilityNSW))
2486 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2488 else
2490 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2491 parse_unknown_elem(xmlbuf, &elem);
2496 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2497 struct xml_elem *parent )
2499 struct xml_elem elem;
2500 struct xml_attr attr;
2501 xmlstr_t content;
2502 BOOL end = FALSE;
2503 struct entity *entity;
2505 while (next_xml_attr( xmlbuf, &attr, &end ))
2507 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2510 if (end) return;
2512 if (!parse_text_content( xmlbuf, &content )) return;
2513 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2515 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2516 if (!entity)
2518 set_error( xmlbuf );
2519 return;
2521 entity->u.settings.name = xmlstrdupW( &parent->name );
2522 entity->u.settings.value = xmlstrdupW( &content );
2523 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2525 while (next_xml_elem(xmlbuf, &elem, parent))
2527 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2528 parse_unknown_elem( xmlbuf, &elem );
2532 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2533 struct actctx_loader *acl, const struct xml_elem *parent )
2535 struct xml_elem elem;
2537 while (next_xml_elem( xmlbuf, &elem, parent ))
2539 if (xml_elem_cmp( &elem, L"activeCodePage", windowsSettings2019NSW ) ||
2540 xml_elem_cmp( &elem, L"autoElevate", windowsSettings2005NSW ) ||
2541 xml_elem_cmp( &elem, L"disableTheming", windowsSettings2005NSW ) ||
2542 xml_elem_cmp( &elem, L"disableWindowFiltering", windowsSettings2011NSW ) ||
2543 xml_elem_cmp( &elem, L"dpiAware", windowsSettings2005NSW ) ||
2544 xml_elem_cmp( &elem, L"dpiAwareness", windowsSettings2016NSW ) ||
2545 xml_elem_cmp( &elem, L"gdiScaling", windowsSettings2017NSW ) ||
2546 xml_elem_cmp( &elem, L"heapType", windowsSettings2020NSW ) ||
2547 xml_elem_cmp( &elem, L"highResolutionScrollingAware", windowsSettings2017NSW ) ||
2548 xml_elem_cmp( &elem, L"longPathAware", windowsSettings2016NSW ) ||
2549 xml_elem_cmp( &elem, L"magicFutureSetting", windowsSettings2017NSW ) ||
2550 xml_elem_cmp( &elem, L"printerDriverIsolation", windowsSettings2011NSW ) ||
2551 xml_elem_cmp( &elem, L"ultraHighResolutionScrollingAware", windowsSettings2017NSW ))
2553 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2555 else
2557 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2558 parse_unknown_elem( xmlbuf, &elem );
2563 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2564 struct actctx_loader *acl, const struct xml_elem *parent )
2566 struct xml_elem elem;
2568 while (next_xml_elem( xmlbuf, &elem, parent ))
2570 if (xml_elem_cmp( &elem, L"windowsSettings", asmv1W ))
2572 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2574 else
2576 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2577 parse_unknown_elem( xmlbuf, &elem );
2582 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2583 struct actctx_loader *acl, const struct xml_elem *parent )
2585 struct xml_elem elem;
2586 struct xml_attr attr;
2587 BOOL end = FALSE;
2589 /* Multiple requestedExecutionLevel elements are not supported. */
2590 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2592 while (next_xml_attr(xmlbuf, &attr, &end))
2594 if (xml_attr_cmp(&attr, L"level"))
2596 if (xmlstr_cmpi(&attr.value, L"asInvoker"))
2597 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2598 else if (xmlstr_cmpi(&attr.value, L"highestAvailable"))
2599 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2600 else if (xmlstr_cmpi(&attr.value, L"requireAdministrator"))
2601 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2602 else
2603 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2605 else if (xml_attr_cmp(&attr, L"uiAccess"))
2607 if (xmlstr_cmpi(&attr.value, L"false"))
2608 assembly->ui_access = FALSE;
2609 else if (xmlstr_cmpi(&attr.value, L"true"))
2610 assembly->ui_access = TRUE;
2611 else
2612 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2614 else if (!is_xmlns_attr( &attr ))
2615 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2618 if (end) return;
2620 while (next_xml_elem(xmlbuf, &elem, parent))
2622 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2623 parse_unknown_elem(xmlbuf, &elem);
2627 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2628 struct actctx_loader *acl, const struct xml_elem *parent )
2630 struct xml_elem elem;
2632 while (next_xml_elem(xmlbuf, &elem, parent))
2634 if (xml_elem_cmp(&elem, L"requestedExecutionLevel", asmv1W))
2636 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2638 else
2640 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2641 parse_unknown_elem(xmlbuf, &elem);
2646 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2647 struct actctx_loader *acl, const struct xml_elem *parent )
2649 struct xml_elem elem;
2651 while (next_xml_elem(xmlbuf, &elem, parent))
2653 if (xml_elem_cmp(&elem, L"requestedPrivileges", asmv1W))
2655 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2657 else
2659 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2660 parse_unknown_elem(xmlbuf, &elem);
2665 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2666 struct actctx_loader *acl, const struct xml_elem *parent )
2668 struct xml_elem elem;
2670 while (next_xml_elem(xmlbuf, &elem, parent))
2672 if (xml_elem_cmp(&elem, L"security", asmv1W))
2674 parse_security_elem(xmlbuf, assembly, acl, &elem);
2676 else
2678 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2679 parse_unknown_elem(xmlbuf, &elem);
2684 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2685 struct actctx_loader* acl, const struct xml_elem *parent,
2686 struct assembly_identity* expected_ai)
2688 struct xml_elem elem;
2689 struct xml_attr attr;
2690 BOOL end = FALSE, version = FALSE;
2692 TRACE("(%p)\n", xmlbuf);
2694 while (next_xml_attr(xmlbuf, &attr, &end))
2696 if (xml_attr_cmp(&attr, L"manifestVersion"))
2698 if (!xmlstr_cmp(&attr.value, L"1.0"))
2700 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2701 break;
2703 version = TRUE;
2705 else if (!is_xmlns_attr( &attr ))
2707 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2711 if (end || !version)
2713 set_error( xmlbuf );
2714 return;
2717 while (next_xml_elem(xmlbuf, &elem, parent))
2719 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, L"noInherit", asmv1W))
2721 parse_noinherit_elem(xmlbuf, &elem);
2722 assembly->no_inherit = TRUE;
2724 else if (xml_elem_cmp(&elem, L"noInheritable", asmv1W))
2726 parse_noinheritable_elem(xmlbuf, &elem);
2728 else if (xml_elem_cmp(&elem, L"description", asmv1W))
2730 parse_description_elem(xmlbuf, &elem);
2732 else if (xml_elem_cmp(&elem, L"comInterfaceExternalProxyStub", asmv1W))
2734 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2736 else if (xml_elem_cmp(&elem, L"dependency", asmv1W))
2738 parse_dependency_elem(xmlbuf, acl, &elem);
2740 else if (xml_elem_cmp(&elem, L"file", asmv1W))
2742 parse_file_elem(xmlbuf, assembly, acl, &elem);
2744 else if (xml_elem_cmp(&elem, L"clrClass", asmv1W))
2746 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2748 else if (xml_elem_cmp(&elem, L"clrSurrogate", asmv1W))
2750 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2752 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2754 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2756 else if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2758 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2760 if (!xmlbuf->error && expected_ai)
2762 /* FIXME: more tests */
2763 if (assembly->type == ASSEMBLY_MANIFEST &&
2764 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2766 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2767 expected_ai->version.major, expected_ai->version.minor,
2768 expected_ai->version.build, expected_ai->version.revision,
2769 assembly->id.version.major, assembly->id.version.minor,
2770 assembly->id.version.build, assembly->id.version.revision);
2771 set_error( xmlbuf );
2773 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2774 (assembly->id.version.major != expected_ai->version.major ||
2775 assembly->id.version.minor != expected_ai->version.minor ||
2776 assembly->id.version.build < expected_ai->version.build ||
2777 (assembly->id.version.build == expected_ai->version.build &&
2778 assembly->id.version.revision < expected_ai->version.revision)))
2780 FIXME("wrong version for shared assembly manifest\n");
2781 set_error( xmlbuf );
2785 else if (xml_elem_cmp(&elem, L"compatibility", compatibilityNSW))
2787 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2789 else if (xml_elem_cmp(&elem, L"application", asmv1W))
2791 parse_application_elem(xmlbuf, assembly, acl, &elem);
2793 else
2795 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2796 parse_unknown_elem(xmlbuf, &elem);
2800 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2801 assembly->no_inherit)
2803 set_error( xmlbuf );
2807 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2808 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2810 struct xml_elem elem;
2811 struct xml_elem parent = {};
2813 xmlbuf->error = FALSE;
2814 xmlbuf->ns_pos = 0;
2816 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2818 if (xmlstr_cmp(&elem.name, L"?xml") &&
2819 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2820 return STATUS_SXS_CANT_GEN_ACTCTX;
2822 if (!xml_elem_cmp(&elem, L"assembly", asmv1W))
2824 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2825 return STATUS_SXS_CANT_GEN_ACTCTX;
2828 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2829 if (xmlbuf->error)
2831 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2832 return STATUS_SXS_CANT_GEN_ACTCTX;
2835 if (next_xml_elem(xmlbuf, &elem, &parent))
2837 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2838 return STATUS_SXS_CANT_GEN_ACTCTX;
2841 if (xmlbuf->ptr != xmlbuf->end)
2843 FIXME("parse error\n");
2844 return STATUS_SXS_CANT_GEN_ACTCTX;
2846 return STATUS_SUCCESS;
2849 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2850 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2851 const void *buffer, SIZE_T size )
2853 xmlbuf_t xmlbuf;
2854 NTSTATUS status;
2855 struct assembly *assembly;
2856 int unicode_tests;
2858 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2860 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2861 return STATUS_SXS_CANT_GEN_ACTCTX;
2863 if (directory && !(assembly->directory = strdupW(directory)))
2864 return STATUS_NO_MEMORY;
2866 if (!filename)
2868 UNICODE_STRING module_path;
2869 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2870 assembly->manifest.info = module_path.Buffer;
2872 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2874 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2875 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2877 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2878 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2880 xmlbuf.ptr = buffer;
2881 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2882 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2884 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2886 const WCHAR *buf = buffer;
2887 WCHAR *new_buff;
2888 unsigned int i;
2890 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2891 return STATUS_NO_MEMORY;
2892 for (i = 0; i < size / sizeof(WCHAR); i++)
2893 new_buff[i] = RtlUshortByteSwap( buf[i] );
2894 xmlbuf.ptr = new_buff;
2895 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2896 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2897 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2899 else
2901 DWORD len;
2902 WCHAR *new_buff;
2904 /* let's assume utf-8 for now */
2905 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2906 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2907 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2908 xmlbuf.ptr = new_buff;
2909 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2910 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2911 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2913 return status;
2916 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2918 OBJECT_ATTRIBUTES attr;
2919 IO_STATUS_BLOCK io;
2921 attr.Length = sizeof(attr);
2922 attr.RootDirectory = 0;
2923 attr.Attributes = OBJ_CASE_INSENSITIVE;
2924 attr.ObjectName = name;
2925 attr.SecurityDescriptor = NULL;
2926 attr.SecurityQualityOfService = NULL;
2927 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io,
2928 FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT );
2931 static NTSTATUS find_first_manifest_resource_in_module( HANDLE hModule, const WCHAR **resname )
2933 static const LDR_RESOURCE_INFO manifest_res_info = { RT_MANIFEST };
2934 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry_base, *entry;
2935 const IMAGE_RESOURCE_DIRECTORY *resdir;
2936 NTSTATUS status;
2938 status = LdrFindResourceDirectory_U( hModule, &manifest_res_info, 1, &resdir );
2939 if (status != STATUS_SUCCESS) return status;
2941 if (!resdir->NumberOfIdEntries) return STATUS_RESOURCE_NAME_NOT_FOUND;
2942 entry_base = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1);
2943 entry = entry_base + resdir->NumberOfNamedEntries;
2944 *resname = (const WCHAR *)(ULONG_PTR)entry->Id;
2946 return STATUS_SUCCESS;
2949 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2950 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2951 HANDLE hModule, LPCWSTR resname, ULONG lang )
2953 NTSTATUS status;
2954 UNICODE_STRING nameW;
2955 LDR_RESOURCE_INFO info;
2956 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2957 void *ptr;
2959 if (TRACE_ON(actctx))
2961 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2963 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2964 hModule, debugstr_w(nameW.Buffer) );
2965 RtlFreeUnicodeString( &nameW );
2967 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2968 hModule, debugstr_w(filename) );
2971 if (!resname)
2973 status = find_first_manifest_resource_in_module( hModule, &resname );
2974 if (status != STATUS_SUCCESS) return status;
2977 info.Type = RT_MANIFEST;
2978 info.Language = lang;
2979 if (!((ULONG_PTR)resname >> 16))
2981 info.Name = (ULONG_PTR)resname;
2982 status = LdrFindResource_U(hModule, &info, 3, &entry);
2984 else if (resname[0] == '#')
2986 ULONG value;
2987 RtlInitUnicodeString(&nameW, resname + 1);
2988 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2989 return STATUS_INVALID_PARAMETER;
2990 info.Name = value;
2991 status = LdrFindResource_U(hModule, &info, 3, &entry);
2993 else
2995 RtlCreateUnicodeString(&nameW, resname);
2996 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2997 info.Name = (ULONG_PTR)nameW.Buffer;
2998 status = LdrFindResource_U(hModule, &info, 3, &entry);
2999 RtlFreeUnicodeString(&nameW);
3001 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
3003 if (status == STATUS_SUCCESS)
3004 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
3006 return status;
3009 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
3010 LPCWSTR filename, LPCWSTR directory, BOOL shared,
3011 HANDLE file, LPCWSTR resname, ULONG lang )
3013 HANDLE mapping;
3014 OBJECT_ATTRIBUTES attr;
3015 LARGE_INTEGER size;
3016 LARGE_INTEGER offset;
3017 NTSTATUS status;
3018 SIZE_T count;
3019 void *base;
3021 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
3023 attr.Length = sizeof(attr);
3024 attr.RootDirectory = 0;
3025 attr.ObjectName = NULL;
3026 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3027 attr.SecurityDescriptor = NULL;
3028 attr.SecurityQualityOfService = NULL;
3030 size.QuadPart = 0;
3031 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3032 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3033 if (status != STATUS_SUCCESS) return status;
3035 offset.QuadPart = 0;
3036 count = 0;
3037 base = NULL;
3038 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3039 &count, ViewShare, 0, PAGE_READONLY );
3040 NtClose( mapping );
3041 if (status != STATUS_SUCCESS) return status;
3043 if (RtlImageNtHeader(base)) /* we got a PE file */
3045 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3046 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3048 else status = STATUS_INVALID_IMAGE_FORMAT;
3050 NtUnmapViewOfSection( GetCurrentProcess(), base );
3051 return status;
3054 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3055 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3057 FILE_END_OF_FILE_INFORMATION info;
3058 IO_STATUS_BLOCK io;
3059 HANDLE mapping;
3060 OBJECT_ATTRIBUTES attr;
3061 LARGE_INTEGER size;
3062 LARGE_INTEGER offset;
3063 NTSTATUS status;
3064 SIZE_T count;
3065 void *base;
3067 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3069 attr.Length = sizeof(attr);
3070 attr.RootDirectory = 0;
3071 attr.ObjectName = NULL;
3072 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3073 attr.SecurityDescriptor = NULL;
3074 attr.SecurityQualityOfService = NULL;
3076 size.QuadPart = 0;
3077 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3078 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3079 if (status != STATUS_SUCCESS) return status;
3081 offset.QuadPart = 0;
3082 count = 0;
3083 base = NULL;
3084 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3085 &count, ViewShare, 0, PAGE_READONLY );
3086 NtClose( mapping );
3087 if (status != STATUS_SUCCESS) return status;
3089 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3090 if (status == STATUS_SUCCESS)
3091 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3093 NtUnmapViewOfSection( GetCurrentProcess(), base );
3094 return status;
3097 /* try to load the .manifest file associated to the file */
3098 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3099 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3101 WCHAR *buffer;
3102 NTSTATUS status;
3103 UNICODE_STRING nameW;
3104 HANDLE file;
3105 UINT resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3107 if (!((ULONG_PTR)resname >> 16)) resid = LOWORD(resname);
3109 TRACE( "looking for manifest associated with %s id %u\n", debugstr_w(filename), resid );
3111 if (module) /* use the module filename */
3113 UNICODE_STRING name;
3115 if (!(status = get_module_filename( module, &name, sizeof(L".manifest") + 10*sizeof(WCHAR) )))
3117 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, L".%u", resid );
3118 wcscat( name.Buffer, L".manifest" );
3119 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3120 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3121 RtlFreeUnicodeString( &name );
3123 if (status) return status;
3125 else
3127 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3128 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(L".manifest") )))
3129 return STATUS_NO_MEMORY;
3130 wcscpy( buffer, filename );
3131 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, L".%u", resid );
3132 wcscat( buffer, L".manifest" );
3133 RtlInitUnicodeString( &nameW, buffer );
3136 if (!open_nt_file( &file, &nameW ))
3138 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3139 NtClose( file );
3141 else status = STATUS_RESOURCE_NAME_NOT_FOUND;
3142 RtlFreeUnicodeString( &nameW );
3143 return status;
3146 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3148 static const WCHAR lookup_fmtW[] = L"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3149 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3151 WCHAR *lookup, *ret = NULL;
3152 UNICODE_STRING lookup_us;
3153 IO_STATUS_BLOCK io;
3154 const WCHAR *lang = ai->language;
3155 unsigned int data_pos = 0, data_len, len;
3156 char buffer[8192];
3158 if (!lang || !wcsicmp( lang, L"neutral" )) lang = L"*";
3160 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3161 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3162 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3163 ai->version.major, ai->version.minor, lang );
3164 RtlInitUnicodeString( &lookup_us, lookup );
3166 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3167 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3169 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3170 FILE_BOTH_DIR_INFORMATION *dir_info;
3171 WCHAR *tmp;
3172 ULONG build, revision;
3174 data_len = io.Information;
3176 for (;;)
3178 if (data_pos >= data_len)
3180 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3181 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3182 break;
3183 data_len = io.Information;
3184 data_pos = 0;
3186 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3188 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3189 else data_pos = data_len;
3191 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3192 build = wcstoul( tmp, NULL, 10 );
3193 if (build < min_build) continue;
3194 tmp = wcschr(tmp, '.') + 1;
3195 revision = wcstoul( tmp, NULL, 10 );
3196 if (build == min_build && revision < min_revision) continue;
3197 tmp = wcschr(tmp, '_') + 1;
3198 tmp = wcschr(tmp, '_') + 1;
3199 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3200 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3202 /* prefer a non-Wine manifest if we already have one */
3203 /* we'll still load the builtin dll if specified through DllOverrides */
3204 if (ret) continue;
3206 else
3208 min_build = build;
3209 min_revision = revision;
3211 ai->version.build = build;
3212 ai->version.revision = revision;
3213 RtlFreeHeap( GetProcessHeap(), 0, ret );
3214 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3216 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3217 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3221 else WARN("no matching file for %s\n", debugstr_w(lookup));
3222 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3223 return ret;
3226 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3228 struct assembly_identity sxs_ai;
3229 UNICODE_STRING path_us;
3230 OBJECT_ATTRIBUTES attr;
3231 IO_STATUS_BLOCK io;
3232 WCHAR *path, *file = NULL;
3233 HANDLE handle;
3235 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3237 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L"\\winsxs\\manifests") +
3238 wcslen(windows_dir) * sizeof(WCHAR) )))
3239 return STATUS_NO_MEMORY;
3241 wcscpy( path, windows_dir );
3242 wcscat( path, L"\\winsxs\\manifests" );
3244 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3246 RtlFreeHeap( GetProcessHeap(), 0, path );
3247 return STATUS_NO_SUCH_FILE;
3249 RtlFreeHeap( GetProcessHeap(), 0, path );
3251 attr.Length = sizeof(attr);
3252 attr.RootDirectory = 0;
3253 attr.Attributes = OBJ_CASE_INSENSITIVE;
3254 attr.ObjectName = &path_us;
3255 attr.SecurityDescriptor = NULL;
3256 attr.SecurityQualityOfService = NULL;
3258 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3259 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3261 sxs_ai = *ai;
3262 file = lookup_manifest_file( handle, &sxs_ai );
3263 NtClose( handle );
3265 if (!file)
3267 RtlFreeUnicodeString( &path_us );
3268 return STATUS_NO_SUCH_FILE;
3271 /* append file name to directory path */
3272 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3273 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3275 RtlFreeHeap( GetProcessHeap(), 0, file );
3276 RtlFreeUnicodeString( &path_us );
3277 return STATUS_NO_MEMORY;
3280 path[path_us.Length/sizeof(WCHAR)] = '\\';
3281 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3282 RtlInitUnicodeString( &path_us, path );
3283 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3285 if (!open_nt_file( &handle, &path_us ))
3287 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3288 NtClose( handle );
3290 else io.Status = STATUS_NO_SUCH_FILE;
3292 RtlFreeHeap( GetProcessHeap(), 0, file );
3293 RtlFreeUnicodeString( &path_us );
3294 return io.Status;
3297 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3298 struct assembly_identity* ai)
3300 unsigned int i;
3301 WCHAR *buffer, *p, *directory;
3302 NTSTATUS status;
3303 UNICODE_STRING nameW;
3304 HANDLE file;
3305 DWORD len;
3307 TRACE( "looking for name=%s version=%s arch=%s\n",
3308 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3310 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3312 /* FIXME: add support for language specific lookup */
3314 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3315 wcslen(acl->actctx->appdir.info));
3317 nameW.Buffer = NULL;
3318 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3319 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(L".manifest") )))
3320 return STATUS_NO_MEMORY;
3322 if (!(directory = build_assembly_dir( ai )))
3324 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3325 return STATUS_NO_MEMORY;
3328 /* Lookup in <dir>\name.dll
3329 * <dir>\name.manifest
3330 * <dir>\name\name.dll
3331 * <dir>\name\name.manifest
3333 * First 'appdir' is used as <dir>, if that failed
3334 * it tries application manifest file path.
3336 wcscpy( buffer, acl->actctx->appdir.info );
3337 p = buffer + wcslen(buffer);
3338 for (i = 0; i < 4; i++)
3340 if (i == 2)
3342 struct assembly *assembly = acl->actctx->assemblies;
3343 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3345 else *p++ = '\\';
3347 wcscpy( p, ai->name );
3348 p += wcslen(p);
3350 wcscpy( p, L".dll" );
3351 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3353 status = open_nt_file( &file, &nameW );
3354 if (!status)
3356 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, NULL, 0 );
3357 NtClose( file );
3358 if (status == STATUS_SUCCESS)
3359 break;
3361 RtlFreeUnicodeString( &nameW );
3364 wcscpy( p, L".manifest" );
3365 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3367 status = open_nt_file( &file, &nameW );
3368 if (!status)
3370 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3371 NtClose( file );
3372 break;
3374 RtlFreeUnicodeString( &nameW );
3376 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3378 RtlFreeUnicodeString( &nameW );
3379 RtlFreeHeap( GetProcessHeap(), 0, directory );
3380 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3381 return status;
3384 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3386 NTSTATUS status = STATUS_SUCCESS;
3387 unsigned int i;
3389 for (i = 0; i < acl->num_dependencies; i++)
3391 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3393 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3395 FIXME( "Could not find dependent assembly %s (%s)\n",
3396 debugstr_w(acl->dependencies[i].name),
3397 debugstr_version(&acl->dependencies[i].version) );
3398 status = STATUS_SXS_CANT_GEN_ACTCTX;
3399 break;
3403 /* FIXME should now iterate through all refs */
3404 return status;
3407 static HANDLE get_current_actctx_no_addref(void)
3409 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
3411 if (actctx_stack->ActiveFrame)
3412 return actctx_stack->ActiveFrame->ActivationContext;
3414 return NULL;
3417 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3418 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3420 NTSTATUS status = STATUS_SUCCESS;
3422 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3424 if (*handle) return STATUS_INVALID_PARAMETER;
3426 *handle = get_current_actctx_no_addref();
3428 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3430 ULONG_PTR magic;
3431 LDR_DATA_TABLE_ENTRY *pldr;
3433 if (!*handle) return STATUS_INVALID_PARAMETER;
3435 LdrLockLoaderLock( 0, NULL, &magic );
3436 if (!LdrFindEntryForAddress( *handle, &pldr ))
3438 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3439 status = STATUS_DLL_NOT_FOUND;
3440 else
3441 *handle = pldr->ActivationContext;
3443 else status = STATUS_DLL_NOT_FOUND;
3444 LdrUnlockLoaderLock( 0, magic );
3446 else if (!*handle && (class != ActivationContextBasicInformation))
3447 *handle = process_actctx;
3449 return status;
3452 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3454 unsigned int i, j, total_len = 0, dll_count = 0;
3455 struct strsection_header *header;
3456 struct dllredirect_data *data;
3457 struct string_index *index;
3458 ULONG name_offset;
3460 /* compute section length */
3461 for (i = 0; i < actctx->num_assemblies; i++)
3463 struct assembly *assembly = &actctx->assemblies[i];
3464 for (j = 0; j < assembly->num_dlls; j++)
3466 struct dll_redirect *dll = &assembly->dlls[j];
3468 /* each entry needs index, data and string data */
3469 total_len += sizeof(*index);
3470 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3471 if (dll->load_from)
3473 total_len += offsetof( struct dllredirect_data, paths[1] );
3474 total_len += aligned_string_len( wcslen(dll->load_from) * sizeof(WCHAR) );
3476 else total_len += offsetof( struct dllredirect_data, paths[0] );
3479 dll_count += assembly->num_dlls;
3482 total_len += sizeof(*header);
3484 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3485 if (!header) return STATUS_NO_MEMORY;
3487 memset(header, 0, sizeof(*header));
3488 header->magic = STRSECTION_MAGIC;
3489 header->size = sizeof(*header);
3490 header->count = dll_count;
3491 header->index_offset = sizeof(*header);
3492 index = (struct string_index*)((BYTE*)header + header->index_offset);
3493 name_offset = header->index_offset + header->count*sizeof(*index);
3495 for (i = 0; i < actctx->num_assemblies; i++)
3497 struct assembly *assembly = &actctx->assemblies[i];
3498 for (j = 0; j < assembly->num_dlls; j++)
3500 struct dll_redirect *dll = &assembly->dlls[j];
3501 UNICODE_STRING str;
3502 WCHAR *ptrW;
3504 /* setup new index entry */
3505 str.Buffer = dll->name;
3506 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3507 str.MaximumLength = str.Length + sizeof(WCHAR);
3508 /* hash original class name */
3509 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3511 index->name_offset = name_offset;
3512 index->name_len = str.Length;
3513 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3514 index->data_len = offsetof( struct dllredirect_data, paths[0] );
3515 index->rosterindex = i + 1;
3517 /* dll name */
3518 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3519 memcpy(ptrW, dll->name, index->name_len);
3520 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3521 name_offset += aligned_string_len(str.MaximumLength);
3523 /* setup data */
3524 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3525 if (dll->load_from)
3527 ULONG len = wcslen(dll->load_from) * sizeof(WCHAR);
3528 data->size = offsetof( struct dllredirect_data, paths[1] );
3529 data->flags = 0;
3530 data->total_len = aligned_string_len( len );
3531 data->paths_count = 1;
3532 data->paths_offset = index->data_offset + offsetof( struct dllredirect_data, paths[0] );
3533 data->paths[0].offset = index->data_offset + data->size;
3534 data->paths[0].len = len;
3535 ptrW = (WCHAR *)((BYTE *)header + data->paths[0].offset);
3536 memcpy( ptrW, dll->load_from, len );
3537 if (wcschr( dll->load_from, '%' )) data->flags |= DLL_REDIRECT_PATH_EXPAND;
3539 else
3541 data->size = offsetof( struct dllredirect_data, paths[0] );
3542 data->flags = DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT;
3543 data->total_len = 0;
3544 data->paths_count = 0;
3545 data->paths_offset = 0;
3547 name_offset += data->size + data->total_len;
3549 index++;
3553 *section = header;
3555 return STATUS_SUCCESS;
3558 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3560 struct string_index *iter, *index = NULL;
3561 UNICODE_STRING str;
3562 ULONG hash = 0, i;
3564 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3565 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3567 for (i = 0; i < section->count; i++)
3569 if (iter->hash == hash)
3571 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3572 str.Length = iter->name_len;
3573 if (RtlEqualUnicodeString( &str, name, TRUE ))
3575 index = iter;
3576 break;
3578 else
3579 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3581 iter++;
3584 return index;
3587 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3589 struct guid_index *iter, *index = NULL;
3590 ULONG i;
3592 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3594 for (i = 0; i < section->count; i++)
3596 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3598 index = iter;
3599 break;
3601 iter++;
3604 return index;
3607 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3609 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3612 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3613 PACTCTX_SECTION_KEYED_DATA data)
3615 struct dllredirect_data *dll;
3616 struct string_index *index;
3618 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3620 if (!actctx->dllredirect_section)
3622 struct strsection_header *section;
3624 NTSTATUS status = build_dllredirect_section(actctx, &section);
3625 if (status) return status;
3627 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3628 RtlFreeHeap(GetProcessHeap(), 0, section);
3631 index = find_string_index(actctx->dllredirect_section, name);
3632 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3634 if (data)
3636 dll = get_dllredirect_data(actctx, index);
3638 data->ulDataFormatVersion = 1;
3639 data->lpData = dll;
3640 data->ulLength = dll->size;
3641 data->lpSectionGlobalData = NULL;
3642 data->ulSectionGlobalDataLength = 0;
3643 data->lpSectionBase = actctx->dllredirect_section;
3644 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3645 data->hActCtx = NULL;
3647 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3648 data->ulAssemblyRosterIndex = index->rosterindex;
3651 return STATUS_SUCCESS;
3654 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3656 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3659 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3661 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3664 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3666 unsigned int i, j, k, total_len = 0, class_count = 0;
3667 struct wndclass_redirect_data *data;
3668 struct strsection_header *header;
3669 struct string_index *index;
3670 ULONG name_offset;
3672 /* compute section length */
3673 for (i = 0; i < actctx->num_assemblies; i++)
3675 struct assembly *assembly = &actctx->assemblies[i];
3676 for (j = 0; j < assembly->num_dlls; j++)
3678 struct dll_redirect *dll = &assembly->dlls[j];
3679 for (k = 0; k < dll->entities.num; k++)
3681 struct entity *entity = &dll->entities.base[k];
3682 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3684 int class_len = wcslen(entity->u.class.name) + 1;
3685 int len;
3687 /* each class entry needs index, data and string data */
3688 total_len += sizeof(*index);
3689 total_len += sizeof(*data);
3690 /* original name is stored separately */
3691 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3692 /* versioned name and module name are stored one after another */
3693 if (entity->u.class.versioned)
3694 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3695 else
3696 len = class_len;
3697 len += wcslen(dll->name) + 1;
3698 total_len += aligned_string_len(len*sizeof(WCHAR));
3700 class_count++;
3706 total_len += sizeof(*header);
3708 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3709 if (!header) return STATUS_NO_MEMORY;
3711 memset(header, 0, sizeof(*header));
3712 header->magic = STRSECTION_MAGIC;
3713 header->size = sizeof(*header);
3714 header->count = class_count;
3715 header->index_offset = sizeof(*header);
3716 index = (struct string_index*)((BYTE*)header + header->index_offset);
3717 name_offset = header->index_offset + header->count*sizeof(*index);
3719 for (i = 0; i < actctx->num_assemblies; i++)
3721 struct assembly *assembly = &actctx->assemblies[i];
3722 for (j = 0; j < assembly->num_dlls; j++)
3724 struct dll_redirect *dll = &assembly->dlls[j];
3725 for (k = 0; k < dll->entities.num; k++)
3727 struct entity *entity = &dll->entities.base[k];
3728 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3730 ULONG versioned_len, module_len;
3731 UNICODE_STRING str;
3732 WCHAR *ptrW;
3734 /* setup new index entry */
3735 str.Buffer = entity->u.class.name;
3736 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3737 str.MaximumLength = str.Length + sizeof(WCHAR);
3738 /* hash original class name */
3739 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3741 /* include '!' separator too */
3742 if (entity->u.class.versioned)
3743 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3744 else
3745 versioned_len = str.Length;
3746 module_len = wcslen(dll->name)*sizeof(WCHAR);
3748 index->name_offset = name_offset;
3749 index->name_len = str.Length;
3750 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3751 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3752 index->rosterindex = i + 1;
3754 /* setup data */
3755 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3756 data->size = sizeof(*data);
3757 data->res = 0;
3758 data->name_len = versioned_len;
3759 data->name_offset = sizeof(*data);
3760 data->module_len = module_len;
3761 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3763 /* original class name */
3764 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3765 memcpy(ptrW, entity->u.class.name, index->name_len);
3766 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3768 /* module name */
3769 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3770 memcpy(ptrW, dll->name, data->module_len);
3771 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3773 /* versioned name */
3774 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3775 if (entity->u.class.versioned)
3777 get_assembly_version(assembly, ptrW);
3778 wcscat(ptrW, L"!");
3779 wcscat(ptrW, entity->u.class.name);
3781 else
3783 memcpy(ptrW, entity->u.class.name, index->name_len);
3784 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3787 name_offset += sizeof(*data);
3788 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3790 index++;
3796 *section = header;
3798 return STATUS_SUCCESS;
3801 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3802 PACTCTX_SECTION_KEYED_DATA data)
3804 struct string_index *iter, *index = NULL;
3805 struct wndclass_redirect_data *class;
3806 UNICODE_STRING str;
3807 ULONG hash;
3808 int i;
3810 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3812 if (!actctx->wndclass_section)
3814 struct strsection_header *section;
3816 NTSTATUS status = build_wndclass_section(actctx, &section);
3817 if (status) return status;
3819 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3820 RtlFreeHeap(GetProcessHeap(), 0, section);
3823 hash = 0;
3824 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3825 iter = get_wndclass_first_index(actctx);
3827 for (i = 0; i < actctx->wndclass_section->count; i++)
3829 if (iter->hash == hash)
3831 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3832 str.Length = iter->name_len;
3833 if (RtlEqualUnicodeString( &str, name, TRUE ))
3835 index = iter;
3836 break;
3838 else
3839 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3841 iter++;
3844 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3846 if (data)
3848 class = get_wndclass_data(actctx, index);
3850 data->ulDataFormatVersion = 1;
3851 data->lpData = class;
3852 /* full length includes string length with nulls */
3853 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3854 data->lpSectionGlobalData = NULL;
3855 data->ulSectionGlobalDataLength = 0;
3856 data->lpSectionBase = actctx->wndclass_section;
3857 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3858 data->hActCtx = NULL;
3860 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3861 data->ulAssemblyRosterIndex = index->rosterindex;
3864 return STATUS_SUCCESS;
3867 static inline struct string_index *get_activatable_class_first_index(ACTIVATION_CONTEXT *actctx)
3869 return (struct string_index *)((BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->index_offset);
3872 static inline struct activatable_class_data *get_activatable_class_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3874 return (struct activatable_class_data *)((BYTE *)ctxt->activatable_class_section + index->data_offset);
3877 static NTSTATUS build_activatable_class_section(ACTIVATION_CONTEXT *actctx, struct strsection_header **section)
3879 unsigned int i, j, k, total_len = 0, class_count = 0, global_offset = 0, global_len = 0;
3880 struct activatable_class_data *data;
3881 struct strsection_header *header;
3882 struct string_index *index;
3883 ULONG name_offset;
3885 /* compute section length */
3886 for (i = 0; i < actctx->num_assemblies; i++)
3888 struct assembly *assembly = &actctx->assemblies[i];
3889 for (j = 0; j < assembly->num_dlls; j++)
3891 struct dll_redirect *dll = &assembly->dlls[j];
3892 BOOL has_class = FALSE;
3894 for (k = 0; k < dll->entities.num; k++)
3896 struct entity *entity = &dll->entities.base[k];
3897 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3899 int class_len = wcslen(entity->u.activatable_class.name) + 1;
3901 /* each class entry needs index, data and string data */
3902 total_len += sizeof(*index);
3903 total_len += aligned_string_len(class_len * sizeof(WCHAR));
3904 total_len += sizeof(*data);
3906 class_count++;
3907 has_class = TRUE;
3911 if (has_class)
3913 int module_len = wcslen(dll->name) + 1;
3914 global_len += aligned_string_len(module_len * sizeof(WCHAR));
3919 total_len += sizeof(*header) + global_len;
3921 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3922 if (!header) return STATUS_NO_MEMORY;
3924 memset(header, 0, sizeof(*header));
3925 header->magic = STRSECTION_MAGIC;
3926 header->size = sizeof(*header);
3927 header->count = class_count;
3928 header->global_offset = header->size;
3929 header->global_len = global_len;
3930 header->index_offset = header->global_offset + header->global_len;
3931 index = (struct string_index *)((BYTE *)header + header->index_offset);
3932 name_offset = header->index_offset + header->count * sizeof(*index);
3934 global_offset = header->size;
3935 for (i = 0; i < actctx->num_assemblies; i++)
3937 struct assembly *assembly = &actctx->assemblies[i];
3938 for (j = 0; j < assembly->num_dlls; j++)
3940 struct dll_redirect *dll = &assembly->dlls[j];
3941 int module_len = wcslen(dll->name) * sizeof(WCHAR);
3942 BOOL has_class = FALSE;
3944 for (k = 0; k < dll->entities.num; k++)
3946 struct entity *entity = &dll->entities.base[k];
3948 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES)
3950 UNICODE_STRING str;
3951 WCHAR *ptrW;
3953 /* setup new index entry */
3954 str.Buffer = entity->u.activatable_class.name;
3955 str.Length = wcslen(entity->u.activatable_class.name) * sizeof(WCHAR);
3956 str.MaximumLength = str.Length + sizeof(WCHAR);
3957 /* hash class name */
3958 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3960 index->name_offset = name_offset;
3961 index->name_len = str.Length;
3962 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3963 index->data_len = sizeof(*data);
3964 index->rosterindex = i + 1;
3966 /* class name */
3967 ptrW = (WCHAR *)((BYTE *)header + index->name_offset);
3968 memcpy(ptrW, entity->u.activatable_class.name, index->name_len);
3969 ptrW[index->name_len / sizeof(WCHAR)] = 0;
3971 /* class data */
3972 data = (struct activatable_class_data *)((BYTE *)header + index->data_offset);
3973 data->size = sizeof(*data);
3974 data->threading_model = entity->u.activatable_class.threading_model;
3975 data->module_len = module_len;
3976 data->module_offset = global_offset;
3978 name_offset += aligned_string_len(str.MaximumLength);
3979 name_offset += sizeof(*data);
3981 index++;
3982 has_class = TRUE;
3986 if (has_class)
3988 WCHAR *ptrW = (WCHAR *)((BYTE *)header + global_offset);
3989 memcpy(ptrW, dll->name, module_len);
3990 ptrW[module_len / sizeof(WCHAR)] = 0;
3991 global_offset += aligned_string_len(module_len + sizeof(WCHAR));
3996 *section = header;
3998 return STATUS_SUCCESS;
4001 static NTSTATUS find_activatable_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4002 PACTCTX_SECTION_KEYED_DATA data)
4004 struct string_index *iter, *index = NULL;
4005 struct activatable_class_data *class;
4006 UNICODE_STRING str;
4007 ULONG hash;
4008 int i;
4010 if (!(actctx->sections & ACTIVATABLE_CLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4012 if (!actctx->activatable_class_section)
4014 struct strsection_header *section;
4016 NTSTATUS status = build_activatable_class_section(actctx, &section);
4017 if (status) return status;
4019 if (InterlockedCompareExchangePointer((void**)&actctx->activatable_class_section, section, NULL))
4020 RtlFreeHeap(GetProcessHeap(), 0, section);
4023 hash = 0;
4024 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
4025 iter = get_activatable_class_first_index(actctx);
4027 for (i = 0; i < actctx->activatable_class_section->count; i++)
4029 if (iter->hash == hash)
4031 str.Buffer = (WCHAR *)((BYTE *)actctx->activatable_class_section + iter->name_offset);
4032 str.Length = iter->name_len;
4033 if (RtlEqualUnicodeString( &str, name, TRUE ))
4035 index = iter;
4036 break;
4038 else
4039 WARN("hash collision 0x%08lx, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
4041 iter++;
4044 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4046 if (data)
4048 class = get_activatable_class_data(actctx, index);
4050 data->ulDataFormatVersion = 1;
4051 data->lpData = class;
4052 /* full length includes string length with nulls */
4053 data->ulLength = class->size + class->module_len + sizeof(WCHAR);
4054 data->lpSectionGlobalData = (BYTE *)actctx->activatable_class_section + actctx->activatable_class_section->global_offset;
4055 data->ulSectionGlobalDataLength = actctx->activatable_class_section->global_len;
4056 data->lpSectionBase = actctx->activatable_class_section;
4057 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->activatable_class_section );
4058 data->hActCtx = NULL;
4060 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4061 data->ulAssemblyRosterIndex = index->rosterindex;
4064 return STATUS_SUCCESS;
4067 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4069 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
4070 struct guidsection_header *header;
4071 ULONG module_offset, data_offset;
4072 struct tlibredirect_data *data;
4073 struct guid_index *index;
4075 /* compute section length */
4076 for (i = 0; i < actctx->num_assemblies; i++)
4078 struct assembly *assembly = &actctx->assemblies[i];
4079 for (j = 0; j < assembly->num_dlls; j++)
4081 struct dll_redirect *dll = &assembly->dlls[j];
4082 for (k = 0; k < dll->entities.num; k++)
4084 struct entity *entity = &dll->entities.base[k];
4085 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4087 /* each entry needs index, data and string data for module name and help string */
4088 total_len += sizeof(*index);
4089 total_len += sizeof(*data);
4090 /* help string is stored separately */
4091 if (*entity->u.typelib.helpdir)
4092 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
4094 /* module names are packed one after another */
4095 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4097 tlib_count++;
4103 total_len += aligned_string_len(names_len);
4104 total_len += sizeof(*header);
4106 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4107 if (!header) return STATUS_NO_MEMORY;
4109 memset(header, 0, sizeof(*header));
4110 header->magic = GUIDSECTION_MAGIC;
4111 header->size = sizeof(*header);
4112 header->count = tlib_count;
4113 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4114 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4115 module_offset = sizeof(*header);
4116 data_offset = header->index_offset + tlib_count*sizeof(*index);
4118 for (i = 0; i < actctx->num_assemblies; i++)
4120 struct assembly *assembly = &actctx->assemblies[i];
4121 for (j = 0; j < assembly->num_dlls; j++)
4123 struct dll_redirect *dll = &assembly->dlls[j];
4124 for (k = 0; k < dll->entities.num; k++)
4126 struct entity *entity = &dll->entities.base[k];
4127 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
4129 ULONG module_len, help_len;
4130 UNICODE_STRING str;
4131 WCHAR *ptrW;
4133 if (*entity->u.typelib.helpdir)
4134 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
4135 else
4136 help_len = 0;
4138 module_len = wcslen(dll->name)*sizeof(WCHAR);
4140 /* setup new index entry */
4141 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
4142 RtlGUIDFromString(&str, &index->guid);
4143 index->data_offset = data_offset;
4144 index->data_len = sizeof(*data) + aligned_string_len(help_len);
4145 index->rosterindex = i + 1;
4147 /* setup data */
4148 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
4149 data->size = sizeof(*data);
4150 data->res = 0;
4151 data->name_len = module_len;
4152 data->name_offset = module_offset;
4153 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
4154 data->langid = 0;
4155 data->flags = entity->u.typelib.flags;
4156 data->help_len = help_len;
4157 data->help_offset = sizeof(*data);
4158 data->major_version = entity->u.typelib.major;
4159 data->minor_version = entity->u.typelib.minor;
4161 /* module name */
4162 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
4163 memcpy(ptrW, dll->name, data->name_len);
4164 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4166 /* help string */
4167 if (data->help_len)
4169 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
4170 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
4171 ptrW[data->help_len/sizeof(WCHAR)] = 0;
4174 data_offset += sizeof(*data);
4175 if (help_len)
4176 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
4178 module_offset += module_len + sizeof(WCHAR);
4180 index++;
4186 *section = header;
4188 return STATUS_SUCCESS;
4191 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4193 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
4196 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4198 struct guid_index *index = NULL;
4199 struct tlibredirect_data *tlib;
4201 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4203 if (!actctx->tlib_section)
4205 struct guidsection_header *section;
4207 NTSTATUS status = build_tlib_section(actctx, &section);
4208 if (status) return status;
4210 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
4211 RtlFreeHeap(GetProcessHeap(), 0, section);
4214 index = find_guid_index(actctx->tlib_section, guid);
4215 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4217 tlib = get_tlib_data(actctx, index);
4219 data->ulDataFormatVersion = 1;
4220 data->lpData = tlib;
4221 /* full length includes string length with nulls */
4222 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
4223 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
4224 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
4225 data->lpSectionBase = actctx->tlib_section;
4226 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
4227 data->hActCtx = NULL;
4229 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4230 data->ulAssemblyRosterIndex = index->rosterindex;
4232 return STATUS_SUCCESS;
4235 static void generate_uuid(ULONG *seed, GUID *guid)
4237 ULONG *ptr = (ULONG*)guid;
4238 int i;
4240 /* GUID is 16 bytes long */
4241 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
4242 *ptr = RtlUniform(seed);
4244 guid->Data3 &= 0x0fff;
4245 guid->Data3 |= (4 << 12);
4246 guid->Data4[0] &= 0x3f;
4247 guid->Data4[0] |= 0x80;
4250 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4251 unsigned int *count, unsigned int *len, unsigned int *module_len)
4253 unsigned int i;
4255 for (i = 0; i < entities->num; i++)
4257 struct entity *entity = &entities->base[i];
4258 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4260 /* each entry needs two index entries, extra one goes for alias GUID */
4261 *len += 2*sizeof(struct guid_index);
4262 /* To save some memory we don't allocated two data structures,
4263 instead alias index and normal index point to the same data structure. */
4264 *len += sizeof(struct comclassredirect_data);
4266 /* for clrClass store some more */
4267 if (entity->u.comclass.name)
4269 unsigned int str_len;
4271 /* all string data is stored together in aligned block */
4272 str_len = wcslen(entity->u.comclass.name)+1;
4273 if (entity->u.comclass.progid)
4274 str_len += wcslen(entity->u.comclass.progid)+1;
4275 if (entity->u.comclass.version)
4276 str_len += wcslen(entity->u.comclass.version)+1;
4278 *len += sizeof(struct clrclass_data);
4279 *len += aligned_string_len(str_len*sizeof(WCHAR));
4281 /* module name is forced to mscoree.dll, and stored two times with different case */
4282 *module_len += sizeof(L"MSCOREE.DLL") + sizeof(L"mscoree.dll");
4284 else
4286 /* progid string is stored separately */
4287 if (entity->u.comclass.progid)
4288 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4290 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4293 *count += 1;
4298 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4299 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4300 ULONG *seed, ULONG rosterindex)
4302 unsigned int i;
4304 for (i = 0; i < entities->num; i++)
4306 struct entity *entity = &entities->base[i];
4307 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4309 ULONG module_len, progid_len, str_len = 0, miscmask;
4310 struct comclassredirect_data *data;
4311 struct guid_index *alias_index;
4312 struct clrclass_data *clrdata;
4313 UNICODE_STRING str;
4314 WCHAR *ptrW;
4316 if (entity->u.comclass.progid)
4317 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4318 else
4319 progid_len = 0;
4321 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4323 /* setup new index entry */
4324 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4325 RtlGUIDFromString(&str, &(*index)->guid);
4327 (*index)->data_offset = *data_offset;
4328 (*index)->data_len = sizeof(*data); /* additional length added later */
4329 (*index)->rosterindex = rosterindex;
4331 /* Setup new index entry for alias guid. Alias index records are placed after
4332 normal records, so normal guids are hit first on search. Note that class count
4333 is doubled. */
4334 alias_index = (*index) + section->count/2;
4335 generate_uuid(seed, &alias_index->guid);
4336 alias_index->data_offset = (*index)->data_offset;
4337 alias_index->data_len = 0;
4338 alias_index->rosterindex = (*index)->rosterindex;
4340 /* setup data */
4341 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4342 data->size = sizeof(*data);
4343 data->model = entity->u.comclass.model;
4344 data->clsid = (*index)->guid;
4345 data->alias = alias_index->guid;
4346 data->clsid2 = data->clsid;
4347 if (entity->u.comclass.tlbid)
4349 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4350 RtlGUIDFromString(&str, &data->tlbid);
4352 else
4353 memset(&data->tlbid, 0, sizeof(data->tlbid));
4354 data->name_len = module_len;
4355 data->name_offset = *module_offset;
4356 data->progid_len = progid_len;
4357 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4358 data->clrdata_len = 0; /* will be set later */
4359 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4360 data->miscstatus = entity->u.comclass.miscstatus;
4361 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4362 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4363 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4364 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4366 /* mask describes which misc* data is available */
4367 miscmask = 0;
4368 if (data->miscstatus)
4369 miscmask |= MiscStatus;
4370 if (data->miscstatuscontent)
4371 miscmask |= MiscStatusContent;
4372 if (data->miscstatusthumbnail)
4373 miscmask |= MiscStatusThumbnail;
4374 if (data->miscstatusicon)
4375 miscmask |= MiscStatusIcon;
4376 if (data->miscstatusdocprint)
4377 miscmask |= MiscStatusDocPrint;
4378 data->flags = miscmask << 8;
4380 if (data->clrdata_offset)
4382 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4384 clrdata->size = sizeof(*clrdata);
4385 clrdata->res[0] = 0;
4386 clrdata->res[1] = 2; /* FIXME: unknown field */
4387 clrdata->module_len = wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4388 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4389 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4390 clrdata->name_offset = clrdata->size;
4391 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4392 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4393 clrdata->res2[0] = 0;
4394 clrdata->res2[1] = 0;
4396 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4398 /* module name */
4399 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4400 memcpy(ptrW, L"mscoree.dll", clrdata->module_len);
4401 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4403 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4404 memcpy(ptrW, L"MSCOREE.DLL", data->name_len);
4405 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4407 /* class name */
4408 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4409 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4410 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4412 /* runtime version, optional */
4413 if (clrdata->version_len)
4415 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4417 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4418 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4419 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4422 if (data->progid_len)
4423 data->progid_offset += data->clrdata_len;
4424 (*index)->data_len += sizeof(*clrdata);
4426 else
4428 clrdata = NULL;
4430 /* module name */
4431 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4432 memcpy(ptrW, dll->name, data->name_len);
4433 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4436 /* progid string */
4437 if (data->progid_len)
4439 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4440 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4441 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4444 /* string block length */
4445 str_len = 0;
4446 if (clrdata)
4448 str_len += clrdata->name_len + sizeof(WCHAR);
4449 if (clrdata->version_len)
4450 str_len += clrdata->version_len + sizeof(WCHAR);
4452 if (progid_len)
4453 str_len += progid_len + sizeof(WCHAR);
4455 (*index)->data_len += aligned_string_len(str_len);
4456 alias_index->data_len = (*index)->data_len;
4458 /* move to next data record */
4459 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4460 (*module_offset) += module_len + sizeof(WCHAR);
4462 if (clrdata)
4464 (*data_offset) += sizeof(*clrdata);
4465 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4467 (*index) += 1;
4472 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4474 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4475 struct guidsection_header *header;
4476 ULONG module_offset, data_offset;
4477 struct guid_index *index;
4478 ULONG seed;
4480 /* compute section length */
4481 for (i = 0; i < actctx->num_assemblies; i++)
4483 struct assembly *assembly = &actctx->assemblies[i];
4484 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4485 for (j = 0; j < assembly->num_dlls; j++)
4487 struct dll_redirect *dll = &assembly->dlls[j];
4488 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4492 total_len += aligned_string_len(names_len);
4493 total_len += sizeof(*header);
4495 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4496 if (!header) return STATUS_NO_MEMORY;
4498 memset(header, 0, sizeof(*header));
4499 header->magic = GUIDSECTION_MAGIC;
4500 header->size = sizeof(*header);
4501 header->count = 2*class_count;
4502 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4503 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4504 module_offset = sizeof(*header);
4505 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4507 seed = NtGetTickCount();
4508 for (i = 0; i < actctx->num_assemblies; i++)
4510 struct assembly *assembly = &actctx->assemblies[i];
4511 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4512 for (j = 0; j < assembly->num_dlls; j++)
4514 struct dll_redirect *dll = &assembly->dlls[j];
4515 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4519 *section = header;
4521 return STATUS_SUCCESS;
4524 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4526 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4529 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4531 struct comclassredirect_data *comclass;
4532 struct guid_index *index = NULL;
4534 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4536 if (!actctx->comserver_section)
4538 struct guidsection_header *section;
4540 NTSTATUS status = build_comserver_section(actctx, &section);
4541 if (status) return status;
4543 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4544 RtlFreeHeap(GetProcessHeap(), 0, section);
4547 index = find_guid_index(actctx->comserver_section, guid);
4548 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4550 comclass = get_comclass_data(actctx, index);
4552 data->ulDataFormatVersion = 1;
4553 data->lpData = comclass;
4554 /* full length includes string length with nulls */
4555 data->ulLength = comclass->size + comclass->clrdata_len;
4556 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4557 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4558 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4559 data->lpSectionBase = actctx->comserver_section;
4560 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4561 data->hActCtx = NULL;
4563 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4564 data->ulAssemblyRosterIndex = index->rosterindex;
4566 return STATUS_SUCCESS;
4569 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4571 unsigned int i;
4573 for (i = 0; i < entities->num; i++)
4575 struct entity *entity = &entities->base[i];
4576 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4578 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4579 if (entity->u.ifaceps.name)
4580 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4581 *count += 1;
4586 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4587 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4589 unsigned int i;
4591 for (i = 0; i < entities->num; i++)
4593 struct entity *entity = &entities->base[i];
4594 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4596 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4597 UNICODE_STRING str;
4598 ULONG name_len;
4600 if (entity->u.ifaceps.name)
4601 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4602 else
4603 name_len = 0;
4605 /* setup index */
4606 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4607 RtlGUIDFromString(&str, &(*index)->guid);
4608 (*index)->data_offset = *data_offset;
4609 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4610 (*index)->rosterindex = rosterindex;
4612 /* setup data record */
4613 data->size = sizeof(*data);
4614 data->mask = entity->u.ifaceps.mask;
4616 /* proxyStubClsid32 value is only stored for external PS,
4617 if set it's used as iid, otherwise 'iid' attribute value is used */
4618 if (entity->u.ifaceps.ps32)
4620 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4621 RtlGUIDFromString(&str, &data->iid);
4623 else
4624 data->iid = (*index)->guid;
4626 data->nummethods = entity->u.ifaceps.nummethods;
4628 if (entity->u.ifaceps.tlib)
4630 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4631 RtlGUIDFromString(&str, &data->tlbid);
4633 else
4634 memset(&data->tlbid, 0, sizeof(data->tlbid));
4636 if (entity->u.ifaceps.base)
4638 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4639 RtlGUIDFromString(&str, &data->base);
4641 else
4642 memset(&data->base, 0, sizeof(data->base));
4644 data->name_len = name_len;
4645 data->name_offset = data->name_len ? sizeof(*data) : 0;
4647 /* name string */
4648 if (data->name_len)
4650 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4651 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4652 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4655 /* move to next record */
4656 (*index) += 1;
4657 *data_offset += sizeof(*data);
4658 if (data->name_len)
4659 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4664 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4666 unsigned int i, j, total_len = 0, count = 0;
4667 struct guidsection_header *header;
4668 struct guid_index *index;
4669 ULONG data_offset;
4671 /* compute section length */
4672 for (i = 0; i < actctx->num_assemblies; i++)
4674 struct assembly *assembly = &actctx->assemblies[i];
4676 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4677 for (j = 0; j < assembly->num_dlls; j++)
4679 struct dll_redirect *dll = &assembly->dlls[j];
4680 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4684 total_len += sizeof(*header);
4686 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4687 if (!header) return STATUS_NO_MEMORY;
4689 memset(header, 0, sizeof(*header));
4690 header->magic = GUIDSECTION_MAGIC;
4691 header->size = sizeof(*header);
4692 header->count = count;
4693 header->index_offset = sizeof(*header);
4694 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4695 data_offset = header->index_offset + count*sizeof(*index);
4697 for (i = 0; i < actctx->num_assemblies; i++)
4699 struct assembly *assembly = &actctx->assemblies[i];
4701 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4702 for (j = 0; j < assembly->num_dlls; j++)
4704 struct dll_redirect *dll = &assembly->dlls[j];
4705 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4709 *section = header;
4711 return STATUS_SUCCESS;
4714 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4716 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4719 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4721 struct ifacepsredirect_data *iface;
4722 struct guid_index *index = NULL;
4724 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4726 if (!actctx->ifaceps_section)
4728 struct guidsection_header *section;
4730 NTSTATUS status = build_ifaceps_section(actctx, &section);
4731 if (status) return status;
4733 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4734 RtlFreeHeap(GetProcessHeap(), 0, section);
4737 index = find_guid_index(actctx->ifaceps_section, guid);
4738 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4740 iface = get_ifaceps_data(actctx, index);
4742 data->ulDataFormatVersion = 1;
4743 data->lpData = iface;
4744 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4745 data->lpSectionGlobalData = NULL;
4746 data->ulSectionGlobalDataLength = 0;
4747 data->lpSectionBase = actctx->ifaceps_section;
4748 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4749 data->hActCtx = NULL;
4751 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4752 data->ulAssemblyRosterIndex = index->rosterindex;
4754 return STATUS_SUCCESS;
4757 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4759 unsigned int i, j, total_len = 0, count = 0;
4760 struct guidsection_header *header;
4761 struct clrsurrogate_data *data;
4762 struct guid_index *index;
4763 ULONG data_offset;
4765 /* compute section length */
4766 for (i = 0; i < actctx->num_assemblies; i++)
4768 struct assembly *assembly = &actctx->assemblies[i];
4769 for (j = 0; j < assembly->entities.num; j++)
4771 struct entity *entity = &assembly->entities.base[j];
4772 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4774 ULONG len;
4776 total_len += sizeof(*index) + sizeof(*data);
4777 len = wcslen(entity->u.clrsurrogate.name) + 1;
4778 if (entity->u.clrsurrogate.version)
4779 len += wcslen(entity->u.clrsurrogate.version) + 1;
4780 total_len += aligned_string_len(len*sizeof(WCHAR));
4782 count++;
4787 total_len += sizeof(*header);
4789 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4790 if (!header) return STATUS_NO_MEMORY;
4792 memset(header, 0, sizeof(*header));
4793 header->magic = GUIDSECTION_MAGIC;
4794 header->size = sizeof(*header);
4795 header->count = count;
4796 header->index_offset = sizeof(*header);
4797 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4798 data_offset = header->index_offset + count*sizeof(*index);
4800 for (i = 0; i < actctx->num_assemblies; i++)
4802 struct assembly *assembly = &actctx->assemblies[i];
4803 for (j = 0; j < assembly->entities.num; j++)
4805 struct entity *entity = &assembly->entities.base[j];
4806 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4808 ULONG version_len, name_len;
4809 UNICODE_STRING str;
4810 WCHAR *ptrW;
4812 if (entity->u.clrsurrogate.version)
4813 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4814 else
4815 version_len = 0;
4816 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4818 /* setup new index entry */
4819 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4820 RtlGUIDFromString(&str, &index->guid);
4822 index->data_offset = data_offset;
4823 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4824 index->rosterindex = i + 1;
4826 /* setup data */
4827 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4828 data->size = sizeof(*data);
4829 data->res = 0;
4830 data->clsid = index->guid;
4831 data->version_offset = version_len ? data->size : 0;
4832 data->version_len = version_len;
4833 data->name_offset = data->size + version_len;
4834 if (version_len)
4835 data->name_offset += sizeof(WCHAR);
4836 data->name_len = name_len;
4838 /* surrogate name */
4839 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4840 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4841 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4843 /* runtime version */
4844 if (data->version_len)
4846 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4847 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4848 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4851 data_offset += index->data_len;
4852 index++;
4857 *section = header;
4859 return STATUS_SUCCESS;
4862 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4864 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4867 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4869 struct clrsurrogate_data *surrogate;
4870 struct guid_index *index = NULL;
4872 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4874 if (!actctx->clrsurrogate_section)
4876 struct guidsection_header *section;
4878 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4879 if (status) return status;
4881 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4882 RtlFreeHeap(GetProcessHeap(), 0, section);
4885 index = find_guid_index(actctx->clrsurrogate_section, guid);
4886 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4888 surrogate = get_surrogate_data(actctx, index);
4890 data->ulDataFormatVersion = 1;
4891 data->lpData = surrogate;
4892 /* full length includes string length with nulls */
4893 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4894 if (surrogate->version_len)
4895 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4897 data->lpSectionGlobalData = NULL;
4898 data->ulSectionGlobalDataLength = 0;
4899 data->lpSectionBase = actctx->clrsurrogate_section;
4900 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4901 data->hActCtx = NULL;
4903 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4904 data->ulAssemblyRosterIndex = index->rosterindex;
4906 return STATUS_SUCCESS;
4909 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4911 unsigned int i, j, single_len;
4913 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4914 for (i = 0; i < entities->num; i++)
4916 struct entity *entity = &entities->base[i];
4917 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4919 if (entity->u.comclass.progid)
4921 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4922 *count += 1;
4925 for (j = 0; j < entity->u.comclass.progids.num; j++)
4926 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4928 *total_len += single_len*entity->u.comclass.progids.num;
4929 *count += entity->u.comclass.progids.num;
4934 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4935 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4937 struct progidredirect_data *data;
4938 UNICODE_STRING str;
4939 GUID *guid_ptr;
4940 WCHAR *ptrW;
4942 /* setup new index entry */
4944 /* hash progid name */
4945 RtlInitUnicodeString(&str, progid);
4946 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4948 (*index)->name_offset = *data_offset;
4949 (*index)->name_len = str.Length;
4950 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4951 (*index)->data_len = sizeof(*data);
4952 (*index)->rosterindex = rosterindex;
4954 *data_offset += aligned_string_len(str.MaximumLength);
4956 /* setup data structure */
4957 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4958 data->size = sizeof(*data);
4959 data->reserved = 0;
4960 data->clsid_offset = *global_offset;
4962 /* write progid string */
4963 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4964 memcpy(ptrW, progid, (*index)->name_len);
4965 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4967 /* write guid to global area */
4968 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4969 *guid_ptr = *alias;
4971 /* to next entry */
4972 *global_offset += sizeof(GUID);
4973 *data_offset += data->size;
4974 (*index) += 1;
4977 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4978 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4980 unsigned int i, j;
4982 for (i = 0; i < entities->num; i++)
4984 struct entity *entity = &entities->base[i];
4985 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4987 const struct progids *progids = &entity->u.comclass.progids;
4988 struct comclassredirect_data *comclass;
4989 struct guid_index *guid_index;
4990 UNICODE_STRING str;
4991 GUID clsid;
4993 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4994 RtlGUIDFromString(&str, &clsid);
4996 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4997 comclass = get_comclass_data(actctx, guid_index);
4999 if (entity->u.comclass.progid)
5000 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
5001 index, data_offset, global_offset, rosterindex);
5003 for (j = 0; j < progids->num; j++)
5004 write_progid_record(section, progids->progids[j], &comclass->alias,
5005 index, data_offset, global_offset, rosterindex);
5010 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
5012 unsigned int i, j, total_len = 0, count = 0;
5013 struct strsection_header *header;
5014 ULONG data_offset, global_offset;
5015 struct string_index *index;
5017 /* compute section length */
5018 for (i = 0; i < actctx->num_assemblies; i++)
5020 struct assembly *assembly = &actctx->assemblies[i];
5022 get_progid_datalen(&assembly->entities, &count, &total_len);
5023 for (j = 0; j < assembly->num_dlls; j++)
5025 struct dll_redirect *dll = &assembly->dlls[j];
5026 get_progid_datalen(&dll->entities, &count, &total_len);
5030 total_len += sizeof(*header);
5032 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
5033 if (!header) return STATUS_NO_MEMORY;
5035 memset(header, 0, sizeof(*header));
5036 header->magic = STRSECTION_MAGIC;
5037 header->size = sizeof(*header);
5038 header->count = count;
5039 header->global_offset = header->size;
5040 header->global_len = count*sizeof(GUID);
5041 header->index_offset = header->size + header->global_len;
5043 index = (struct string_index*)((BYTE*)header + header->index_offset);
5044 data_offset = header->index_offset + count*sizeof(*index);
5045 global_offset = header->global_offset;
5047 for (i = 0; i < actctx->num_assemblies; i++)
5049 struct assembly *assembly = &actctx->assemblies[i];
5051 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
5052 for (j = 0; j < assembly->num_dlls; j++)
5054 struct dll_redirect *dll = &assembly->dlls[j];
5055 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
5059 *section = header;
5061 return STATUS_SUCCESS;
5064 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
5066 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
5069 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
5070 PACTCTX_SECTION_KEYED_DATA data)
5072 struct progidredirect_data *progid;
5073 struct string_index *index;
5075 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
5077 if (!actctx->comserver_section)
5079 struct guidsection_header *section;
5081 NTSTATUS status = build_comserver_section(actctx, &section);
5082 if (status) return status;
5084 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
5085 RtlFreeHeap(GetProcessHeap(), 0, section);
5088 if (!actctx->progid_section)
5090 struct strsection_header *section;
5092 NTSTATUS status = build_progid_section(actctx, &section);
5093 if (status) return status;
5095 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
5096 RtlFreeHeap(GetProcessHeap(), 0, section);
5099 index = find_string_index(actctx->progid_section, name);
5100 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
5102 if (data)
5104 progid = get_progid_data(actctx, index);
5106 data->ulDataFormatVersion = 1;
5107 data->lpData = progid;
5108 data->ulLength = progid->size;
5109 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
5110 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
5111 data->lpSectionBase = actctx->progid_section;
5112 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
5113 data->hActCtx = NULL;
5115 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
5116 data->ulAssemblyRosterIndex = index->rosterindex;
5119 return STATUS_SUCCESS;
5122 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5123 const UNICODE_STRING *section_name,
5124 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5126 NTSTATUS status;
5128 switch (section_kind)
5130 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
5131 status = find_dll_redirection(actctx, section_name, data);
5132 break;
5133 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
5134 status = find_window_class(actctx, section_name, data);
5135 break;
5136 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
5137 status = find_progid_redirection(actctx, section_name, data);
5138 break;
5139 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
5140 FIXME("Unsupported yet section_kind %lx\n", section_kind);
5141 return STATUS_SXS_SECTION_NOT_FOUND;
5142 case ACTIVATION_CONTEXT_SECTION_WINRT_ACTIVATABLE_CLASSES:
5143 status = find_activatable_class(actctx, section_name, data);
5144 break;
5145 default:
5146 WARN("Unknown section_kind %lx\n", section_kind);
5147 return STATUS_SXS_SECTION_NOT_FOUND;
5150 if (status != STATUS_SUCCESS) return status;
5152 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
5154 actctx_addref(actctx);
5155 data->hActCtx = actctx;
5157 return STATUS_SUCCESS;
5160 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
5161 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
5163 NTSTATUS status;
5165 switch (section_kind)
5167 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
5168 status = find_tlib_redirection(actctx, guid, data);
5169 break;
5170 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
5171 status = find_comserver_redirection(actctx, guid, data);
5172 break;
5173 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
5174 status = find_cominterface_redirection(actctx, guid, data);
5175 break;
5176 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
5177 status = find_clr_surrogate(actctx, guid, data);
5178 break;
5179 default:
5180 WARN("Unknown section_kind %lx\n", section_kind);
5181 return STATUS_SXS_SECTION_NOT_FOUND;
5184 if (status != STATUS_SUCCESS) return status;
5186 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5188 actctx_addref(actctx);
5189 data->hActCtx = actctx;
5191 return STATUS_SUCCESS;
5194 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
5196 unsigned int i, j;
5198 for (i = 0; i < actctx->num_assemblies; i++)
5200 struct assembly *assembly = &actctx->assemblies[i];
5201 for (j = 0; j < assembly->entities.num; j++)
5203 struct entity *entity = &assembly->entities.base[j];
5204 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
5205 !wcscmp( entity->u.settings.name, settings ) &&
5206 !wcscmp( entity->u.settings.ns, ns ))
5207 return entity->u.settings.value;
5210 return NULL;
5213 /* initialize the activation context for the current process */
5214 void actctx_init(void)
5216 ACTCTXW ctx;
5217 HANDLE handle;
5219 ctx.cbSize = sizeof(ctx);
5220 ctx.lpSource = NULL;
5221 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
5222 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
5223 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
5225 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
5227 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
5231 /***********************************************************************
5232 * RtlCreateActivationContext (NTDLL.@)
5234 * Create an activation context.
5236 * FIXME: function signature/prototype is wrong
5238 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
5240 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
5241 const WCHAR *directory = NULL;
5242 ACTIVATION_CONTEXT *actctx;
5243 UNICODE_STRING nameW;
5244 ULONG lang = 0;
5245 NTSTATUS status = STATUS_NO_MEMORY;
5246 HANDLE file = 0;
5247 struct actctx_loader acl;
5249 TRACE("%p %08lx\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
5251 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5252 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5253 return STATUS_INVALID_PARAMETER;
5255 if ((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && !pActCtx->lpResourceName)
5256 return STATUS_INVALID_PARAMETER;
5258 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
5259 return STATUS_NO_MEMORY;
5261 actctx->magic = ACTCTX_MAGIC;
5262 actctx->ref_count = 1;
5263 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5264 actctx->config.info = NULL;
5265 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5266 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5268 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5270 else
5272 UNICODE_STRING dir;
5273 WCHAR *p;
5274 HMODULE module;
5276 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5277 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
5279 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5280 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5281 actctx->appdir.info = dir.Buffer;
5284 nameW.Buffer = NULL;
5286 /* open file only if it's going to be used */
5287 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5288 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5290 WCHAR *source = NULL;
5291 BOOLEAN ret;
5293 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5294 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5296 DWORD dir_len, source_len;
5298 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5299 source_len = wcslen(pActCtx->lpSource);
5300 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5302 status = STATUS_NO_MEMORY;
5303 goto error;
5306 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5307 source[dir_len] = '\\';
5308 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5311 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5312 RtlFreeHeap( GetProcessHeap(), 0, source );
5313 if (!ret)
5315 status = STATUS_NO_SUCH_FILE;
5316 goto error;
5318 status = open_nt_file( &file, &nameW );
5319 if (status)
5321 RtlFreeUnicodeString( &nameW );
5322 goto error;
5326 acl.actctx = actctx;
5327 acl.dependencies = NULL;
5328 acl.num_dependencies = 0;
5329 acl.allocated_dependencies = 0;
5331 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5332 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5334 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5336 /* if we have a resource it's a PE file */
5337 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5339 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5340 pActCtx->lpResourceName, lang );
5341 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5342 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5343 pActCtx->hModule, pActCtx->lpResourceName );
5345 else if (pActCtx->lpSource)
5347 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5348 file, pActCtx->lpResourceName, lang );
5349 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5350 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5351 NULL, pActCtx->lpResourceName );
5353 else status = STATUS_INVALID_PARAMETER;
5355 else
5357 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5360 if (file) NtClose( file );
5361 RtlFreeUnicodeString( &nameW );
5363 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5364 free_depend_manifests( &acl );
5366 if (status == STATUS_SUCCESS) *handle = actctx;
5367 else actctx_release( actctx );
5368 return status;
5370 error:
5371 if (file) NtClose( file );
5372 actctx_release( actctx );
5373 return status;
5377 /***********************************************************************
5378 * RtlAddRefActivationContext (NTDLL.@)
5380 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5382 ACTIVATION_CONTEXT *actctx;
5384 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5388 /******************************************************************
5389 * RtlReleaseActivationContext (NTDLL.@)
5391 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5393 ACTIVATION_CONTEXT *actctx;
5395 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5398 /******************************************************************
5399 * RtlZombifyActivationContext (NTDLL.@)
5401 * FIXME: function prototype might be wrong
5403 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5405 FIXME("%p: stub\n", handle);
5406 return STATUS_NOT_IMPLEMENTED;
5409 /******************************************************************
5410 * RtlActivateActivationContext (NTDLL.@)
5412 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5414 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5418 /******************************************************************
5419 * RtlActivateActivationContextEx (NTDLL.@)
5421 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5423 ACTIVATION_CONTEXT_STACK *actctx_stack = teb->ActivationContextStackPointer;
5424 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5426 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5427 return STATUS_NO_MEMORY;
5429 frame->Previous = actctx_stack->ActiveFrame;
5430 frame->ActivationContext = handle;
5431 frame->Flags = 0;
5432 actctx_stack->ActiveFrame = frame;
5433 RtlAddRefActivationContext( handle );
5435 *cookie = (ULONG_PTR)frame;
5436 TRACE( "%p cookie=%Ix\n", handle, *cookie );
5437 return STATUS_SUCCESS;
5441 /***********************************************************************
5442 * RtlDeactivateActivationContext (NTDLL.@)
5444 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5446 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
5447 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5449 TRACE( "%lx cookie=%Ix\n", flags, cookie );
5451 /* find the right frame */
5452 top = actctx_stack->ActiveFrame;
5453 for (frame = top; frame; frame = frame->Previous)
5454 if ((ULONG_PTR)frame == cookie) break;
5456 if (!frame)
5457 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5459 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5460 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5462 /* pop everything up to and including frame */
5463 actctx_stack->ActiveFrame = frame->Previous;
5465 while (top != actctx_stack->ActiveFrame)
5467 frame = top->Previous;
5468 RtlReleaseActivationContext( top->ActivationContext );
5469 RtlFreeHeap( GetProcessHeap(), 0, top );
5470 top = frame;
5475 /******************************************************************
5476 * RtlFreeThreadActivationContextStack (NTDLL.@)
5478 void WINAPI RtlFreeThreadActivationContextStack(void)
5480 RtlFreeActivationContextStack( NtCurrentTeb()->ActivationContextStackPointer );
5484 /******************************************************************
5485 * RtlFreeActivationContextStack (NTDLL.@)
5487 void WINAPI RtlFreeActivationContextStack( ACTIVATION_CONTEXT_STACK *actctx_stack )
5489 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5491 frame = actctx_stack->ActiveFrame;
5492 while (frame)
5494 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5495 RtlReleaseActivationContext( frame->ActivationContext );
5496 RtlFreeHeap( GetProcessHeap(), 0, frame );
5497 frame = prev;
5499 actctx_stack->ActiveFrame = NULL;
5503 /******************************************************************
5504 * RtlGetActiveActivationContext (NTDLL.@)
5506 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5508 RtlAddRefActivationContext( *handle = get_current_actctx_no_addref() );
5509 return STATUS_SUCCESS;
5513 /******************************************************************
5514 * RtlIsActivationContextActive (NTDLL.@)
5516 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5518 ACTIVATION_CONTEXT_STACK *actctx_stack = NtCurrentTeb()->ActivationContextStackPointer;
5519 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5521 for (frame = actctx_stack->ActiveFrame; frame; frame = frame->Previous)
5522 if (frame->ActivationContext == handle) return TRUE;
5523 return FALSE;
5527 /***********************************************************************
5528 * RtlQueryInformationActivationContext (NTDLL.@)
5530 * Get information about an activation context.
5531 * FIXME: function signature/prototype may be wrong
5533 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5534 ULONG class, PVOID buffer,
5535 SIZE_T bufsize, SIZE_T *retlen )
5537 ACTIVATION_CONTEXT *actctx;
5538 NTSTATUS status;
5540 TRACE("%08lx %p %p %lu %p %Id %p\n", flags, handle,
5541 subinst, class, buffer, bufsize, retlen);
5543 if (retlen) *retlen = 0;
5544 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5546 switch (class)
5548 case ActivationContextBasicInformation:
5550 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5552 if (retlen) *retlen = sizeof(*info);
5553 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5555 info->hActCtx = handle;
5556 info->dwFlags = 0; /* FIXME */
5557 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5559 break;
5561 case ActivationContextDetailedInformation:
5563 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5564 struct assembly *assembly = NULL;
5565 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5566 LPWSTR ptr;
5568 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5570 if (actctx->num_assemblies) assembly = actctx->assemblies;
5572 if (assembly && assembly->manifest.info)
5573 manifest_len = wcslen(assembly->manifest.info) + 1;
5574 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5575 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5576 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5578 if (retlen) *retlen = len;
5579 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5581 acdi->dwFlags = 0;
5582 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5583 acdi->ulAssemblyCount = actctx->num_assemblies;
5584 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5585 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5586 acdi->ulRootConfigurationPathType = actctx->config.type;
5587 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5588 acdi->ulAppDirPathType = actctx->appdir.type;
5589 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5590 ptr = (LPWSTR)(acdi + 1);
5591 if (manifest_len)
5593 acdi->lpRootManifestPath = ptr;
5594 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5595 ptr += manifest_len;
5597 else acdi->lpRootManifestPath = NULL;
5598 if (config_len)
5600 acdi->lpRootConfigurationPath = ptr;
5601 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5602 ptr += config_len;
5604 else acdi->lpRootConfigurationPath = NULL;
5605 if (appdir_len)
5607 acdi->lpAppDirPath = ptr;
5608 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5610 else acdi->lpAppDirPath = NULL;
5612 break;
5614 case AssemblyDetailedInformationInActivationContext:
5616 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5617 struct assembly *assembly;
5618 WCHAR *assembly_id;
5619 DWORD index;
5620 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5621 LPWSTR ptr;
5623 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5624 if (!subinst) return STATUS_INVALID_PARAMETER;
5626 index = *(DWORD*)subinst;
5627 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5629 assembly = &actctx->assemblies[index - 1];
5631 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5632 id_len = wcslen(assembly_id) + 1;
5633 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5635 if (assembly->manifest.info &&
5636 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5637 path_len = wcslen(assembly->manifest.info) + 1;
5639 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5641 if (retlen) *retlen = len;
5642 if (!buffer || bufsize < len)
5644 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5645 return STATUS_BUFFER_TOO_SMALL;
5648 afdi->ulFlags = 0; /* FIXME */
5649 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5650 afdi->ulManifestPathType = assembly->manifest.type;
5651 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5652 /* FIXME afdi->liManifestLastWriteTime = 0; */
5653 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5654 afdi->ulPolicyPathLength = 0;
5655 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5656 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5657 afdi->ulManifestVersionMajor = 1;
5658 afdi->ulManifestVersionMinor = 0;
5659 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5660 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5661 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5662 ptr = (LPWSTR)(afdi + 1);
5663 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5664 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5665 ptr += id_len;
5666 if (path_len)
5668 afdi->lpAssemblyManifestPath = ptr;
5669 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5670 ptr += path_len;
5671 } else afdi->lpAssemblyManifestPath = NULL;
5672 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5673 if (ad_len)
5675 afdi->lpAssemblyDirectoryName = ptr;
5676 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5678 else afdi->lpAssemblyDirectoryName = NULL;
5679 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5681 break;
5683 case FileInformationInAssemblyOfAssemblyInActivationContext:
5685 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5686 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5687 struct assembly *assembly;
5688 struct dll_redirect *dll;
5689 SIZE_T len, dll_len = 0;
5690 LPWSTR ptr;
5692 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5693 if (!acqi) return STATUS_INVALID_PARAMETER;
5695 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5696 return STATUS_INVALID_PARAMETER;
5697 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5699 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5700 return STATUS_INVALID_PARAMETER;
5701 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5703 if (dll->name) dll_len = wcslen(dll->name) + 1;
5704 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5706 if (!buffer || bufsize < len)
5708 if (retlen) *retlen = len;
5709 return STATUS_BUFFER_TOO_SMALL;
5711 if (retlen) *retlen = 0; /* yes that's what native does !! */
5712 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5713 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5714 afdi->ulPathLength = 0; /* FIXME */
5715 ptr = (LPWSTR)(afdi + 1);
5716 if (dll_len)
5718 afdi->lpFileName = ptr;
5719 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5720 } else afdi->lpFileName = NULL;
5721 afdi->lpFilePath = NULL; /* FIXME */
5723 break;
5725 case CompatibilityInformationInActivationContext:
5727 struct acci
5729 DWORD ElementCount;
5730 COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
5731 } *acci = buffer;
5732 struct assembly *assembly = NULL;
5733 ULONG num_compat_contexts = 0, n;
5734 SIZE_T len;
5736 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5738 if (actctx->num_assemblies) assembly = actctx->assemblies;
5740 if (assembly)
5741 num_compat_contexts = assembly->num_compat_contexts;
5742 len = offsetof( struct acci, Elements[num_compat_contexts] );
5744 if (retlen) *retlen = len;
5745 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5747 acci->ElementCount = num_compat_contexts;
5748 for (n = 0; n < num_compat_contexts; ++n)
5750 acci->Elements[n] = assembly->compat_contexts[n];
5753 break;
5755 case RunlevelInformationInActivationContext:
5757 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5758 struct assembly *assembly;
5759 SIZE_T len;
5761 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5763 len = sizeof(*acrli);
5764 if (retlen) *retlen = len;
5765 if (!buffer || bufsize < len)
5766 return STATUS_BUFFER_TOO_SMALL;
5768 assembly = actctx->assemblies;
5770 acrli->ulFlags = 0;
5771 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5772 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5774 break;
5776 default:
5777 FIXME( "class %lu not implemented\n", class );
5778 return STATUS_NOT_IMPLEMENTED;
5780 return STATUS_SUCCESS;
5783 /***********************************************************************
5784 * RtlFindActivationContextSectionString (NTDLL.@)
5786 * Find information about a string in an activation context.
5787 * FIXME: function signature/prototype may be wrong
5789 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5790 const UNICODE_STRING *section_name, PVOID ptr )
5792 PACTCTX_SECTION_KEYED_DATA data = ptr;
5793 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5794 ACTIVATION_CONTEXT *actctx;
5796 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(guid), section_kind,
5797 debugstr_us(section_name), data);
5799 if (guid)
5801 FIXME("expected guid == NULL\n");
5802 return STATUS_INVALID_PARAMETER;
5804 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5806 FIXME("unknown flags %08lx\n", flags);
5807 return STATUS_INVALID_PARAMETER;
5809 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5810 !section_name || !section_name->Buffer)
5812 WARN("invalid parameter\n");
5813 return STATUS_INVALID_PARAMETER;
5816 actctx = check_actctx( get_current_actctx_no_addref() );
5817 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5819 if (status != STATUS_SUCCESS)
5820 status = find_string( process_actctx, section_kind, section_name, flags, data );
5822 return status;
5825 /***********************************************************************
5826 * RtlFindActivationContextSectionGuid (NTDLL.@)
5828 * Find information about a GUID in an activation context.
5829 * FIXME: function signature/prototype may be wrong
5831 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5832 const GUID *guid, void *ptr )
5834 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5835 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5836 ACTIVATION_CONTEXT *actctx;
5838 TRACE("%08lx %s %lu %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5840 if (extguid)
5842 FIXME("expected extguid == NULL\n");
5843 return STATUS_INVALID_PARAMETER;
5846 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5848 FIXME("unknown flags %08lx\n", flags);
5849 return STATUS_INVALID_PARAMETER;
5852 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5853 return STATUS_INVALID_PARAMETER;
5855 actctx = check_actctx( get_current_actctx_no_addref() );
5856 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5858 if (status != STATUS_SUCCESS)
5859 status = find_guid( process_actctx, section_kind, guid, flags, data );
5861 return status;
5865 /***********************************************************************
5866 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5868 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5869 const WCHAR *settings, WCHAR *buffer,
5870 SIZE_T size, SIZE_T *written )
5872 ACTIVATION_CONTEXT *actctx;
5873 const WCHAR *res;
5875 if (flags)
5877 WARN( "unknown flags %08lx\n", flags );
5878 return STATUS_INVALID_PARAMETER;
5881 if (ns)
5883 if (wcscmp( ns, windowsSettings2005NSW ) &&
5884 wcscmp( ns, windowsSettings2011NSW ) &&
5885 wcscmp( ns, windowsSettings2016NSW ) &&
5886 wcscmp( ns, windowsSettings2017NSW ) &&
5887 wcscmp( ns, windowsSettings2019NSW ) &&
5888 wcscmp( ns, windowsSettings2020NSW ))
5889 return STATUS_INVALID_PARAMETER;
5891 else ns = windowsSettings2005NSW;
5893 if (!handle) handle = process_actctx;
5894 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5896 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5898 if (written) *written = wcslen(res) + 1;
5899 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5900 wcscpy( buffer, res );
5901 return STATUS_SUCCESS;