hidclass.sys: Remove old reports from WINE_HIDP_PREPARSED_DATA.
[wine.git] / dlls / ntdll / actctx.c
blobf9afb655885b3ec19e4a0524f017c408dcb89964
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #define NONAMELESSUNION
32 #include "winternl.h"
33 #include "ddk/wdm.h"
34 #include "ntdll_misc.h"
35 #include "wine/exception.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
40 #define ACTCTX_FLAGS_ALL (\
41 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
42 ACTCTX_FLAG_LANGID_VALID |\
43 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
44 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
45 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
46 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
47 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
48 ACTCTX_FLAG_HMODULE_VALID )
50 #define ACTCTX_MAGIC 0xC07E3E11
51 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
52 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
54 /* we don't want to include winuser.h */
55 #define RT_MANIFEST ((ULONG_PTR)24)
56 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
58 /* from oaidl.h */
59 typedef enum tagLIBFLAGS {
60 LIBFLAG_FRESTRICTED = 0x1,
61 LIBFLAG_FCONTROL = 0x2,
62 LIBFLAG_FHIDDEN = 0x4,
63 LIBFLAG_FHASDISKIMAGE = 0x8
64 } LIBFLAGS;
66 /* from oleidl.idl */
67 typedef enum tagOLEMISC
69 OLEMISC_RECOMPOSEONRESIZE = 0x1,
70 OLEMISC_ONLYICONIC = 0x2,
71 OLEMISC_INSERTNOTREPLACE = 0x4,
72 OLEMISC_STATIC = 0x8,
73 OLEMISC_CANTLINKINSIDE = 0x10,
74 OLEMISC_CANLINKBYOLE1 = 0x20,
75 OLEMISC_ISLINKOBJECT = 0x40,
76 OLEMISC_INSIDEOUT = 0x80,
77 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
78 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
79 OLEMISC_INVISIBLEATRUNTIME = 0x400,
80 OLEMISC_ALWAYSRUN = 0x800,
81 OLEMISC_ACTSLIKEBUTTON = 0x1000,
82 OLEMISC_ACTSLIKELABEL = 0x2000,
83 OLEMISC_NOUIACTIVATE = 0x4000,
84 OLEMISC_ALIGNABLE = 0x8000,
85 OLEMISC_SIMPLEFRAME = 0x10000,
86 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
87 OLEMISC_IMEMODE = 0x40000,
88 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
89 OLEMISC_WANTSTOMENUMERGE = 0x100000,
90 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
91 } OLEMISC;
93 #define MAX_NAMESPACES 64
95 typedef struct
97 const WCHAR *ptr;
98 unsigned int len;
99 } xmlstr_t;
101 struct xml_elem
103 xmlstr_t name;
104 xmlstr_t ns;
105 int ns_pos;
108 struct xml_attr
110 xmlstr_t name;
111 xmlstr_t value;
114 typedef struct
116 const WCHAR *ptr;
117 const WCHAR *end;
118 struct xml_attr namespaces[MAX_NAMESPACES];
119 int ns_pos;
120 BOOL error;
121 } xmlbuf_t;
123 struct file_info
125 ULONG type;
126 WCHAR *info;
129 struct assembly_version
131 USHORT major;
132 USHORT minor;
133 USHORT build;
134 USHORT revision;
137 struct assembly_identity
139 WCHAR *name;
140 WCHAR *arch;
141 WCHAR *public_key;
142 WCHAR *language;
143 WCHAR *type;
144 struct assembly_version version;
145 BOOL optional;
146 BOOL delayed;
149 struct strsection_header
151 DWORD magic;
152 ULONG size;
153 DWORD unk1[3];
154 ULONG count;
155 ULONG index_offset;
156 DWORD unk2[2];
157 ULONG global_offset;
158 ULONG global_len;
161 struct string_index
163 ULONG hash; /* key string hash */
164 ULONG name_offset;
165 ULONG name_len;
166 ULONG data_offset; /* redirect data offset */
167 ULONG data_len;
168 ULONG rosterindex;
171 struct guidsection_header
173 DWORD magic;
174 ULONG size;
175 DWORD unk[3];
176 ULONG count;
177 ULONG index_offset;
178 DWORD unk2;
179 ULONG names_offset;
180 ULONG names_len;
183 struct guid_index
185 GUID guid;
186 ULONG data_offset;
187 ULONG data_len;
188 ULONG rosterindex;
191 struct wndclass_redirect_data
193 ULONG size;
194 DWORD res;
195 ULONG name_len;
196 ULONG name_offset; /* versioned name offset */
197 ULONG module_len;
198 ULONG module_offset;/* container name offset */
201 struct tlibredirect_data
203 ULONG size;
204 DWORD res;
205 ULONG name_len;
206 ULONG name_offset;
207 LANGID langid;
208 WORD flags;
209 ULONG help_len;
210 ULONG help_offset;
211 WORD major_version;
212 WORD minor_version;
215 enum comclass_threadingmodel
217 ThreadingModel_Apartment = 1,
218 ThreadingModel_Free = 2,
219 ThreadingModel_No = 3,
220 ThreadingModel_Both = 4,
221 ThreadingModel_Neutral = 5
224 enum comclass_miscfields
226 MiscStatus = 1,
227 MiscStatusIcon = 2,
228 MiscStatusContent = 4,
229 MiscStatusThumbnail = 8,
230 MiscStatusDocPrint = 16
233 struct comclassredirect_data
235 ULONG size;
236 ULONG flags;
237 DWORD model;
238 GUID clsid;
239 GUID alias;
240 GUID clsid2;
241 GUID tlbid;
242 ULONG name_len;
243 ULONG name_offset;
244 ULONG progid_len;
245 ULONG progid_offset;
246 ULONG clrdata_len;
247 ULONG clrdata_offset;
248 DWORD miscstatus;
249 DWORD miscstatuscontent;
250 DWORD miscstatusthumbnail;
251 DWORD miscstatusicon;
252 DWORD miscstatusdocprint;
255 enum ifaceps_mask
257 NumMethods = 1,
258 BaseIface = 2
261 struct ifacepsredirect_data
263 ULONG size;
264 DWORD mask;
265 GUID iid;
266 ULONG nummethods;
267 GUID tlbid;
268 GUID base;
269 ULONG name_len;
270 ULONG name_offset;
273 struct clrsurrogate_data
275 ULONG size;
276 DWORD res;
277 GUID clsid;
278 ULONG version_offset;
279 ULONG version_len;
280 ULONG name_offset;
281 ULONG name_len;
284 struct clrclass_data
286 ULONG size;
287 DWORD res[2];
288 ULONG module_len;
289 ULONG module_offset;
290 ULONG name_len;
291 ULONG name_offset;
292 ULONG version_len;
293 ULONG version_offset;
294 DWORD res2[2];
297 struct progidredirect_data
299 ULONG size;
300 DWORD reserved;
301 ULONG clsid_offset;
306 Sections structure.
308 Sections are accessible by string or guid key, that defines two types of sections.
309 All sections of each type have same magic value and header structure, index
310 data could be of two possible types too. So every string based section uses
311 the same index format, same applies to guid sections - they share same guid index
312 format.
314 - window class redirection section is a plain buffer with following format:
316 <section header>
317 <index[]>
318 <data[]> --- <original name>
319 <redirect data>
320 <versioned name>
321 <module name>
323 Header is fixed length structure - struct strsection_header,
324 contains redirected classes count;
326 Index is an array of fixed length index records, each record is
327 struct string_index.
329 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
331 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
332 others are relative to section itself.
334 - dll redirect section format:
336 <section header>
337 <index[]>
338 <data[]> --- <dll name>
339 <data>
341 This section doesn't seem to carry any payload data except dll names.
343 - typelib section format:
345 <section header>
346 <module names[]>
347 <index[]>
348 <data[]> --- <data>
349 <helpstring>
351 Header is fixed length, index is an array of fixed length 'struct guid_index'.
352 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
353 4-bytes aligned as a whole.
355 Module name offsets are relative to section, helpstring offset is relative to data
356 structure itself.
358 - comclass section format:
360 <section header>
361 <module names[]>
362 <index[]>
363 <data[]> --- <data> --- <data>
364 <progid> <clrdata>
365 <name>
366 <version>
367 <progid>
369 This section uses two index records per comclass, one entry contains original guid
370 as specified by context, another one has a generated guid. Index and strings handling
371 is similar to typelib sections.
373 For CLR classes additional data is stored after main COM class data, it contains
374 class name and runtime version string, see 'struct clrclass_data'.
376 Module name offsets are relative to section, progid offset is relative to data
377 structure itself.
379 - COM interface section format:
381 <section header>
382 <index[]>
383 <data[]> --- <data>
384 <name>
386 Interface section contains data for proxy/stubs and external proxy/stubs. External
387 ones are defined at assembly level, so this section has no module information.
388 All records are indexed with 'iid' value from manifest. There an exception for
389 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
390 redirect data, but index is still 'iid' from manifest.
392 Interface name offset is relative to data structure itself.
394 - CLR surrogates section format:
396 <section header>
397 <index[]>
398 <data[]> --- <data>
399 <name>
400 <version>
402 There's nothing special about this section, same way to store strings is used,
403 no modules part as it belongs to assembly level, not a file.
405 - ProgID section format:
407 <section header>
408 <guids[]>
409 <index[]>
410 <data[]> --- <progid>
411 <data>
413 This sections uses generated alias guids from COM server section. This way
414 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
415 is stored too, aligned.
418 struct progids
420 WCHAR **progids;
421 unsigned int num;
422 unsigned int allocated;
425 struct entity
427 DWORD kind;
428 union
430 struct
432 WCHAR *tlbid;
433 WCHAR *helpdir;
434 WORD flags;
435 WORD major;
436 WORD minor;
437 } typelib;
438 struct
440 WCHAR *clsid;
441 WCHAR *tlbid;
442 WCHAR *progid;
443 WCHAR *name; /* clrClass: class name */
444 WCHAR *version; /* clrClass: CLR runtime version */
445 DWORD model;
446 DWORD miscstatus;
447 DWORD miscstatuscontent;
448 DWORD miscstatusthumbnail;
449 DWORD miscstatusicon;
450 DWORD miscstatusdocprint;
451 struct progids progids;
452 } comclass;
453 struct {
454 WCHAR *iid;
455 WCHAR *base;
456 WCHAR *tlib;
457 WCHAR *name;
458 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
459 DWORD mask;
460 ULONG nummethods;
461 } ifaceps;
462 struct
464 WCHAR *name;
465 BOOL versioned;
466 } class;
467 struct
469 WCHAR *name;
470 WCHAR *clsid;
471 WCHAR *version;
472 } clrsurrogate;
473 struct
475 WCHAR *name;
476 WCHAR *value;
477 WCHAR *ns;
478 } settings;
479 } u;
482 struct entity_array
484 struct entity *base;
485 unsigned int num;
486 unsigned int allocated;
489 struct dll_redirect
491 WCHAR *name;
492 WCHAR *load_from;
493 WCHAR *hash;
494 struct entity_array entities;
497 enum assembly_type
499 APPLICATION_MANIFEST,
500 ASSEMBLY_MANIFEST,
501 ASSEMBLY_SHARED_MANIFEST,
504 struct assembly
506 enum assembly_type type;
507 struct assembly_identity id;
508 struct file_info manifest;
509 WCHAR *directory;
510 BOOL no_inherit;
511 struct dll_redirect *dlls;
512 unsigned int num_dlls;
513 unsigned int allocated_dlls;
514 struct entity_array entities;
515 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
516 ULONG num_compat_contexts;
517 ACTCTX_REQUESTED_RUN_LEVEL run_level;
518 ULONG ui_access;
521 enum context_sections
523 WINDOWCLASS_SECTION = 1,
524 DLLREDIRECT_SECTION = 2,
525 TLIBREDIRECT_SECTION = 4,
526 SERVERREDIRECT_SECTION = 8,
527 IFACEREDIRECT_SECTION = 16,
528 CLRSURROGATES_SECTION = 32,
529 PROGIDREDIRECT_SECTION = 64
532 typedef struct _ACTIVATION_CONTEXT
534 ULONG magic;
535 int ref_count;
536 struct file_info config;
537 struct file_info appdir;
538 struct assembly *assemblies;
539 unsigned int num_assemblies;
540 unsigned int allocated_assemblies;
541 /* section data */
542 DWORD sections;
543 struct strsection_header *wndclass_section;
544 struct strsection_header *dllredirect_section;
545 struct strsection_header *progid_section;
546 struct guidsection_header *tlib_section;
547 struct guidsection_header *comserver_section;
548 struct guidsection_header *ifaceps_section;
549 struct guidsection_header *clrsurrogate_section;
550 } ACTIVATION_CONTEXT;
552 struct actctx_loader
554 ACTIVATION_CONTEXT *actctx;
555 struct assembly_identity *dependencies;
556 unsigned int num_dependencies;
557 unsigned int allocated_dependencies;
560 static const xmlstr_t empty_xmlstr;
562 #ifdef __i386__
563 static const WCHAR current_archW[] = L"x86";
564 #elif defined __x86_64__
565 static const WCHAR current_archW[] = L"amd64";
566 #elif defined __arm__
567 static const WCHAR current_archW[] = L"arm";
568 #elif defined __aarch64__
569 static const WCHAR current_archW[] = L"arm64";
570 #else
571 static const WCHAR current_archW[] = L"none";
572 #endif
574 static const WCHAR asmv1W[] = L"urn:schemas-microsoft-com:asm.v1";
575 static const WCHAR asmv2W[] = L"urn:schemas-microsoft-com:asm.v2";
576 static const WCHAR asmv3W[] = L"urn:schemas-microsoft-com:asm.v3";
577 static const WCHAR compatibilityNSW[] = L"urn:schemas-microsoft-com:compatibility.v1";
578 static const WCHAR windowsSettings2005NSW[] = L"http://schemas.microsoft.com/SMI/2005/WindowsSettings";
579 static const WCHAR windowsSettings2011NSW[] = L"http://schemas.microsoft.com/SMI/2011/WindowsSettings";
580 static const WCHAR windowsSettings2016NSW[] = L"http://schemas.microsoft.com/SMI/2016/WindowsSettings";
581 static const WCHAR windowsSettings2017NSW[] = L"http://schemas.microsoft.com/SMI/2017/WindowsSettings";
583 struct olemisc_entry
585 const WCHAR *name;
586 OLEMISC value;
589 static const struct olemisc_entry olemisc_values[] =
591 { L"activatewhenvisible", OLEMISC_ACTIVATEWHENVISIBLE },
592 { L"actslikebutton", OLEMISC_ACTSLIKEBUTTON },
593 { L"actslikelabel", OLEMISC_ACTSLIKELABEL },
594 { L"alignable", OLEMISC_ALIGNABLE },
595 { L"alwaysrun", OLEMISC_ALWAYSRUN },
596 { L"canlinkbyole1", OLEMISC_CANLINKBYOLE1 },
597 { L"cantlinkinside", OLEMISC_CANTLINKINSIDE },
598 { L"ignoreactivatewhenvisible", OLEMISC_IGNOREACTIVATEWHENVISIBLE },
599 { L"imemode", OLEMISC_IMEMODE },
600 { L"insertnotreplace", OLEMISC_INSERTNOTREPLACE },
601 { L"insideout", OLEMISC_INSIDEOUT },
602 { L"invisibleatruntime", OLEMISC_INVISIBLEATRUNTIME },
603 { L"islinkobject", OLEMISC_ISLINKOBJECT },
604 { L"nouiactivate", OLEMISC_NOUIACTIVATE },
605 { L"onlyiconic", OLEMISC_ONLYICONIC },
606 { L"recomposeonresize", OLEMISC_RECOMPOSEONRESIZE },
607 { L"renderingisdeviceindependent", OLEMISC_RENDERINGISDEVICEINDEPENDENT },
608 { L"setclientsitefirst", OLEMISC_SETCLIENTSITEFIRST },
609 { L"simpleframe", OLEMISC_SIMPLEFRAME },
610 { L"static", OLEMISC_STATIC },
611 { L"supportsmultilevelundo", OLEMISC_SUPPORTSMULTILEVELUNDO },
612 { L"wantstomenumerge", OLEMISC_WANTSTOMENUMERGE }
615 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
616 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
618 static WCHAR *strdupW(const WCHAR* str)
620 WCHAR* ptr;
622 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR))))
623 return NULL;
624 return wcscpy(ptr, str);
627 static WCHAR *xmlstrdupW(const xmlstr_t* str)
629 WCHAR *strW;
631 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
633 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
634 strW[str->len] = 0;
636 return strW;
639 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
641 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
644 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
646 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
649 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
651 return xmlstr_cmp( &attr->name, str );
654 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
656 return (elem1->name.len == elem2->name.len &&
657 elem1->ns.len == elem2->ns.len &&
658 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
659 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
662 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
664 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
665 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
666 if (!wcscmp( namespace, asmv1W ))
668 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
669 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
671 else if (!wcscmp( namespace, asmv2W ))
673 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
675 return FALSE;
678 static inline BOOL isxmlspace( WCHAR ch )
680 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
683 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
685 return debugstr_wn(str->ptr, str->len);
688 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
690 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
691 debugstr_wn( elem->ns.ptr, elem->ns.len ));
694 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
696 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
697 debugstr_wn( attr->value.ptr, attr->value.len ));
700 static inline const char* debugstr_version(const struct assembly_version *ver)
702 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
705 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
707 NTSTATUS status;
708 ULONG_PTR magic;
709 LDR_DATA_TABLE_ENTRY *pldr;
711 LdrLockLoaderLock(0, NULL, &magic);
712 status = LdrFindEntryForAddress( module, &pldr );
713 if (status == STATUS_SUCCESS)
715 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
716 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
718 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
719 str->Length = pldr->FullDllName.Length;
720 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
722 else status = STATUS_NO_MEMORY;
724 LdrUnlockLoaderLock(0, magic);
725 return status;
728 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
730 struct assembly *assembly;
732 if (actctx->num_assemblies == actctx->allocated_assemblies)
734 void *ptr;
735 unsigned int new_count;
736 if (actctx->assemblies)
738 new_count = actctx->allocated_assemblies * 2;
739 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
740 actctx->assemblies, new_count * sizeof(*assembly) );
742 else
744 new_count = 4;
745 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
747 if (!ptr) return NULL;
748 actctx->assemblies = ptr;
749 actctx->allocated_assemblies = new_count;
752 assembly = &actctx->assemblies[actctx->num_assemblies++];
753 assembly->type = at;
754 return assembly;
757 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
759 if (assembly->num_dlls == assembly->allocated_dlls)
761 void *ptr;
762 unsigned int new_count;
763 if (assembly->dlls)
765 new_count = assembly->allocated_dlls * 2;
766 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
767 assembly->dlls, new_count * sizeof(*assembly->dlls) );
769 else
771 new_count = 4;
772 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
774 if (!ptr) return NULL;
775 assembly->dlls = ptr;
776 assembly->allocated_dlls = new_count;
778 return &assembly->dlls[assembly->num_dlls++];
781 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
783 void *ptr;
784 if (assembly->num_compat_contexts)
786 unsigned int new_count = assembly->num_compat_contexts + 1;
787 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
788 assembly->compat_contexts,
789 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
791 else
793 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
795 if (!ptr) return NULL;
796 assembly->compat_contexts = ptr;
797 return &assembly->compat_contexts[assembly->num_compat_contexts++];
800 static void free_assembly_identity(struct assembly_identity *ai)
802 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
803 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
804 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
805 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
806 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
809 static struct entity* add_entity(struct entity_array *array, DWORD kind)
811 struct entity* entity;
813 if (array->num == array->allocated)
815 void *ptr;
816 unsigned int new_count;
817 if (array->base)
819 new_count = array->allocated * 2;
820 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
821 array->base, new_count * sizeof(*array->base) );
823 else
825 new_count = 4;
826 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
828 if (!ptr) return NULL;
829 array->base = ptr;
830 array->allocated = new_count;
832 entity = &array->base[array->num++];
833 entity->kind = kind;
834 return entity;
837 static void free_entity_array(struct entity_array *array)
839 unsigned int i, j;
840 for (i = 0; i < array->num; i++)
842 struct entity *entity = &array->base[i];
843 switch (entity->kind)
845 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
846 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
847 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
848 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
849 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
850 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
851 for (j = 0; j < entity->u.comclass.progids.num; j++)
852 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
853 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
854 break;
855 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
856 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
857 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
858 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
859 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
860 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
861 break;
862 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
863 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
864 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
865 break;
866 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
867 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
868 break;
869 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
870 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
871 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
872 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
873 break;
874 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
875 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
876 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
877 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
878 break;
879 default:
880 FIXME("Unknown entity kind %d\n", entity->kind);
883 RtlFreeHeap( GetProcessHeap(), 0, array->base );
886 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
888 if (!str1) return !str2;
889 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE );
892 static BOOL is_matching_identity( const struct assembly_identity *id1,
893 const struct assembly_identity *id2 )
895 if (!is_matching_string( id1->name, id2->name )) return FALSE;
896 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
897 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
899 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language ))
901 if (wcscmp( L"*", id1->language ) && wcscmp( L"*", id2->language ))
902 return FALSE;
904 if (id1->version.major != id2->version.major) return FALSE;
905 if (id1->version.minor != id2->version.minor) return FALSE;
906 if (id1->version.build > id2->version.build) return FALSE;
907 if (id1->version.build == id2->version.build &&
908 id1->version.revision > id2->version.revision) return FALSE;
909 return TRUE;
912 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
913 struct assembly_identity* ai)
915 unsigned int i;
917 /* check if we already have that assembly */
919 for (i = 0; i < acl->actctx->num_assemblies; i++)
920 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
922 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
923 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
924 ai->version.build, ai->version.revision );
925 return TRUE;
928 for (i = 0; i < acl->num_dependencies; i++)
929 if (is_matching_identity( ai, &acl->dependencies[i] ))
931 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
932 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
933 ai->version.build, ai->version.revision );
934 return TRUE;
937 if (acl->num_dependencies == acl->allocated_dependencies)
939 void *ptr;
940 unsigned int new_count;
941 if (acl->dependencies)
943 new_count = acl->allocated_dependencies * 2;
944 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
945 new_count * sizeof(acl->dependencies[0]));
947 else
949 new_count = 4;
950 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
952 if (!ptr) return FALSE;
953 acl->dependencies = ptr;
954 acl->allocated_dependencies = new_count;
956 acl->dependencies[acl->num_dependencies++] = *ai;
958 return TRUE;
961 static void free_depend_manifests(struct actctx_loader* acl)
963 unsigned int i;
964 for (i = 0; i < acl->num_dependencies; i++)
965 free_assembly_identity(&acl->dependencies[i]);
966 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
969 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
971 static const WCHAR mskeyW[] = L"deadbeef";
972 const WCHAR *arch = ai->arch ? ai->arch : L"none";
973 const WCHAR *key = ai->public_key ? ai->public_key : L"none";
974 const WCHAR *lang = ai->language ? ai->language : L"none";
975 const WCHAR *name = ai->name ? ai->name : L"none";
976 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 +
977 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
978 WCHAR *ret;
980 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
982 wcscpy( ret, arch );
983 wcscat( ret, L"_" );
984 wcscat( ret, name );
985 wcscat( ret, L"_" );
986 wcscat( ret, key );
987 wcscat( ret, L"_" );
988 swprintf( ret + wcslen(ret), size - wcslen(ret), L"%u.%u.%u.%u",
989 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
990 wcscat( ret, L"_" );
991 wcscat( ret, lang );
992 wcscat( ret, L"_" );
993 wcscat( ret, mskeyW );
994 return ret;
997 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
999 WCHAR *p = buffer;
1001 if (!str) return;
1002 wcscat( buffer, prefix );
1003 p += wcslen(p);
1004 *p++ = '"';
1005 wcscpy( p, str );
1006 p += wcslen(p);
1007 *p++ = '"';
1008 *p = 0;
1011 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1013 WCHAR version[64], *ret;
1014 SIZE_T size = 0;
1016 swprintf( version, ARRAY_SIZE(version), L"%u.%u.%u.%u",
1017 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1018 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR);
1019 if (ai->arch) size += wcslen(L",processorArchitecture=") + wcslen(ai->arch) + 2;
1020 if (ai->public_key) size += wcslen(L",publicKeyToken=") + wcslen(ai->public_key) + 2;
1021 if (ai->type) size += wcslen(L",type=") + wcslen(ai->type) + 2;
1022 size += wcslen(L",version=") + wcslen(version) + 2;
1024 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1025 return NULL;
1027 if (ai->name) wcscpy( ret, ai->name );
1028 else *ret = 0;
1029 append_string( ret, L",processorArchitecture=", ai->arch );
1030 append_string( ret, L",publicKeyToken=", ai->public_key );
1031 append_string( ret, L",type=", ai->type );
1032 append_string( ret, L",version=", version );
1033 return ret;
1036 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1038 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1040 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1041 __TRY
1043 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1045 __EXCEPT_PAGE_FAULT
1048 __ENDTRY
1049 return ret;
1052 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1054 InterlockedIncrement( &actctx->ref_count );
1057 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1059 if (!InterlockedDecrement( &actctx->ref_count ))
1061 unsigned int i, j;
1063 for (i = 0; i < actctx->num_assemblies; i++)
1065 struct assembly *assembly = &actctx->assemblies[i];
1066 for (j = 0; j < assembly->num_dlls; j++)
1068 struct dll_redirect *dll = &assembly->dlls[j];
1069 free_entity_array( &dll->entities );
1070 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1071 RtlFreeHeap( GetProcessHeap(), 0, dll->load_from );
1072 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1074 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1077 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1078 free_entity_array( &assembly->entities );
1079 free_assembly_identity(&assembly->id);
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1091 actctx->magic = 0;
1092 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1096 static BOOL set_error( xmlbuf_t *xmlbuf )
1098 xmlbuf->error = TRUE;
1099 return FALSE;
1102 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1104 const int len = wcslen( L"xmlns" );
1105 if (attr->name.len < len) return FALSE;
1106 if (wcsncmp( attr->name.ptr, L"xmlns", len )) return FALSE;
1107 return (attr->name.len == len || attr->name.ptr[len] == ':');
1110 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1112 const int len = wcslen( L"xmlns" );
1113 struct xml_attr *ns;
1115 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1117 FIXME( "too many namespaces in manifest\n" );
1118 set_error( xmlbuf );
1119 return;
1121 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1122 ns->value = attr->value;
1123 if (attr->name.len > len)
1125 ns->name.ptr = attr->name.ptr + len + 1;
1126 ns->name.len = attr->name.len - len - 1;
1128 else ns->name = empty_xmlstr;
1131 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1133 int i;
1135 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1137 if (xmlbuf->namespaces[i].name.len == name->len &&
1138 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1139 return xmlbuf->namespaces[i].value;
1141 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1142 return empty_xmlstr;
1145 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1147 const WCHAR* ptr;
1148 WCHAR quote;
1150 if (xmlbuf->error) return FALSE;
1152 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1153 xmlbuf->ptr++;
1155 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1157 if (*xmlbuf->ptr == '/')
1159 xmlbuf->ptr++;
1160 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1161 return set_error( xmlbuf );
1163 xmlbuf->ptr++;
1164 *end = TRUE;
1165 return FALSE;
1168 if (*xmlbuf->ptr == '>')
1170 xmlbuf->ptr++;
1171 return FALSE;
1174 ptr = xmlbuf->ptr;
1175 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1177 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1179 attr->name.ptr = xmlbuf->ptr;
1180 attr->name.len = ptr-xmlbuf->ptr;
1181 xmlbuf->ptr = ptr;
1183 /* skip spaces before '=' */
1184 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1185 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1187 /* skip '=' itself */
1188 ptr++;
1189 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1191 /* skip spaces after '=' */
1192 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1194 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1196 quote = *ptr++;
1197 attr->value.ptr = ptr;
1198 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1200 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1201 if (ptr == xmlbuf->end)
1203 xmlbuf->ptr = xmlbuf->end;
1204 return set_error( xmlbuf );
1207 attr->value.len = ptr - attr->value.ptr;
1208 xmlbuf->ptr = ptr + 1;
1209 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1211 return set_error( xmlbuf );
1214 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1216 const WCHAR* ptr = xmlbuf->ptr;
1218 elem->ns = empty_xmlstr;
1219 elem->name.ptr = ptr;
1220 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1222 if (*ptr == ':')
1224 elem->ns.ptr = elem->name.ptr;
1225 elem->ns.len = ptr - elem->ns.ptr;
1226 elem->name.ptr = ptr + 1;
1228 ptr++;
1230 elem->name.len = ptr - elem->name.ptr;
1231 xmlbuf->ptr = ptr;
1234 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1236 const WCHAR* ptr;
1237 struct xml_attr attr;
1238 xmlbuf_t attr_buf;
1239 BOOL end = FALSE;
1241 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1243 if (xmlbuf->error) return FALSE;
1245 for (;;)
1247 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1248 if (ptr == xmlbuf->end)
1250 xmlbuf->ptr = xmlbuf->end;
1251 return set_error( xmlbuf );
1253 ptr++;
1254 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1256 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1257 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1259 if (ptr + 3 > xmlbuf->end)
1261 xmlbuf->ptr = xmlbuf->end;
1262 return set_error( xmlbuf );
1264 xmlbuf->ptr = ptr + 3;
1266 else break;
1269 xmlbuf->ptr = ptr;
1270 /* check for element terminating the parent element */
1271 if (ptr < xmlbuf->end && *ptr == '/')
1273 xmlbuf->ptr++;
1274 read_xml_elem( xmlbuf, elem );
1275 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1276 if (!xml_name_cmp( elem, parent ))
1278 ERR( "wrong closing element %s for %s\n",
1279 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1280 return set_error( xmlbuf );
1282 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1283 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1284 return FALSE;
1287 read_xml_elem( xmlbuf, elem );
1289 /* parse namespace attributes */
1290 attr_buf = *xmlbuf;
1291 while (next_xml_attr( &attr_buf, &attr, &end ))
1293 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1295 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1296 elem->ns_pos = xmlbuf->ns_pos;
1298 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1300 return set_error( xmlbuf );
1303 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1305 /* FIXME: parse attributes */
1306 const WCHAR *ptr;
1308 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1310 if (ptr[0] == '?' && ptr[1] == '>')
1312 xmlbuf->ptr = ptr + 2;
1313 return TRUE;
1316 return FALSE;
1319 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1321 const WCHAR *ptr;
1323 if (xmlbuf->error) return FALSE;
1325 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1326 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1328 content->ptr = xmlbuf->ptr;
1329 content->len = ptr - xmlbuf->ptr;
1330 xmlbuf->ptr = ptr;
1332 return TRUE;
1335 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1337 unsigned int ver[4];
1338 unsigned int pos;
1339 const WCHAR *curr;
1341 /* major.minor.build.revision */
1342 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1343 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1345 if (*curr >= '0' && *curr <= '9')
1347 ver[pos] = ver[pos] * 10 + *curr - '0';
1348 if (ver[pos] >= 0x10000) goto error;
1350 else if (*curr == '.')
1352 if (++pos >= 4) goto error;
1354 else goto error;
1356 version->major = ver[0];
1357 version->minor = ver[1];
1358 version->build = ver[2];
1359 version->revision = ver[3];
1360 return TRUE;
1362 error:
1363 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1364 return FALSE;
1367 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1369 struct xml_attr attr;
1371 while (next_xml_attr(xmlbuf, &attr, end))
1373 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1377 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1379 struct xml_elem elem;
1381 if (next_xml_elem(xmlbuf, &elem, parent))
1383 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1384 set_error( xmlbuf );
1388 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1390 struct xml_elem elem;
1391 struct xml_attr attr;
1392 BOOL end = FALSE;
1394 while (next_xml_attr(xmlbuf, &attr, &end));
1395 if (end) return;
1397 while (next_xml_elem(xmlbuf, &elem, parent))
1398 parse_unknown_elem(xmlbuf, &elem);
1401 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1402 struct assembly_identity* ai, const struct xml_elem *parent)
1404 struct xml_attr attr;
1405 BOOL end = FALSE;
1407 while (next_xml_attr(xmlbuf, &attr, &end))
1409 if (xml_attr_cmp(&attr, L"name"))
1411 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1413 else if (xml_attr_cmp(&attr, L"type"))
1415 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1417 else if (xml_attr_cmp(&attr, L"version"))
1419 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1421 else if (xml_attr_cmp(&attr, L"processorArchitecture"))
1423 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1425 else if (xml_attr_cmp(&attr, L"publicKeyToken"))
1427 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1429 else if (xml_attr_cmp(&attr, L"language"))
1431 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1433 else if (!is_xmlns_attr( &attr ))
1435 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1439 TRACE( "name=%s version=%s arch=%s\n",
1440 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1442 if (!end) parse_expect_end_elem(xmlbuf, parent);
1445 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1447 if (value->len == 0) return ThreadingModel_No;
1448 if (xmlstr_cmp(value, L"Apartment"))
1449 return ThreadingModel_Apartment;
1450 else if (xmlstr_cmp(value, L"Free"))
1451 return ThreadingModel_Free;
1452 else if (xmlstr_cmp(value, L"Both"))
1453 return ThreadingModel_Both;
1454 else if (xmlstr_cmp(value, L"Neutral"))
1455 return ThreadingModel_Neutral;
1456 else
1457 return ThreadingModel_No;
1460 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1462 int min, max;
1464 min = 0;
1465 max = ARRAY_SIZE(olemisc_values) - 1;
1467 while (min <= max)
1469 int n, c;
1471 n = (min+max)/2;
1473 c = wcsncmp(olemisc_values[n].name, str, len);
1474 if (!c && !olemisc_values[n].name[len])
1475 return olemisc_values[n].value;
1477 if (c >= 0)
1478 max = n-1;
1479 else
1480 min = n+1;
1483 WARN("unknown flag %s\n", debugstr_wn(str, len));
1484 return 0;
1487 static DWORD parse_com_class_misc(const xmlstr_t *value)
1489 const WCHAR *str = value->ptr, *start;
1490 DWORD flags = 0;
1491 int i = 0;
1493 /* it's comma separated list of flags */
1494 while (i < value->len)
1496 start = str;
1497 while (*str != ',' && (i++ < value->len)) str++;
1499 flags |= get_olemisc_value(start, str-start);
1501 /* skip separator */
1502 str++;
1503 i++;
1506 return flags;
1509 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1511 struct progids *progids = &entity->u.comclass.progids;
1513 if (progids->allocated == 0)
1515 progids->allocated = 4;
1516 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1519 if (progids->allocated == progids->num)
1521 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1522 2 * progids->allocated * sizeof(WCHAR*));
1523 if (!new_progids) return FALSE;
1524 progids->allocated *= 2;
1525 progids->progids = new_progids;
1528 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1529 progids->num++;
1531 return TRUE;
1534 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1536 xmlstr_t content;
1537 BOOL end = FALSE;
1539 parse_expect_no_attr(xmlbuf, &end);
1540 if (end) set_error( xmlbuf );
1541 if (!parse_text_content(xmlbuf, &content)) return;
1543 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1544 parse_expect_end_elem(xmlbuf, parent);
1547 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1548 const struct xml_elem *parent )
1550 struct xml_elem elem;
1551 struct xml_attr attr;
1552 BOOL end = FALSE;
1553 struct entity* entity;
1555 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1557 set_error( xmlbuf );
1558 return;
1561 while (next_xml_attr(xmlbuf, &attr, &end))
1563 if (xml_attr_cmp(&attr, L"clsid"))
1565 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1567 else if (xml_attr_cmp(&attr, L"progid"))
1569 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1571 else if (xml_attr_cmp(&attr, L"tlbid"))
1573 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1575 else if (xml_attr_cmp(&attr, L"threadingModel"))
1577 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1579 else if (xml_attr_cmp(&attr, L"miscStatus"))
1581 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1583 else if (xml_attr_cmp(&attr, L"miscStatusContent"))
1585 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1587 else if (xml_attr_cmp(&attr, L"miscStatusThumbnail"))
1589 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1591 else if (xml_attr_cmp(&attr, L"miscStatusIcon"))
1593 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1595 else if (xml_attr_cmp(&attr, L"miscStatusDocPrint"))
1597 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1599 else if (xml_attr_cmp(&attr, L"description"))
1601 /* not stored */
1603 else if (!is_xmlns_attr( &attr ))
1605 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1609 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1610 if (entity->u.comclass.progid)
1611 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1613 if (end) return;
1615 while (next_xml_elem(xmlbuf, &elem, parent))
1617 if (xml_elem_cmp(&elem, L"progid", asmv1W))
1619 parse_com_class_progid(xmlbuf, entity, &elem);
1621 else
1623 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1624 parse_unknown_elem(xmlbuf, &elem);
1628 if (entity->u.comclass.progids.num)
1629 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1632 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1634 const WCHAR *curr;
1635 ULONG num = 0;
1637 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1639 if (*curr >= '0' && *curr <= '9')
1640 num = num * 10 + *curr - '0';
1641 else
1643 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1644 return FALSE;
1647 entity->u.ifaceps.nummethods = num;
1649 return TRUE;
1652 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1653 struct actctx_loader *acl, WCHAR *clsid )
1655 struct entity *entity;
1656 WCHAR *str;
1658 if (!clsid) return;
1660 if (!(str = strdupW(clsid)))
1662 set_error( xmlbuf );
1663 return;
1666 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1668 RtlFreeHeap(GetProcessHeap(), 0, str);
1669 set_error( xmlbuf );
1670 return;
1673 entity->u.comclass.clsid = str;
1674 entity->u.comclass.model = ThreadingModel_Both;
1676 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1679 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1680 struct actctx_loader *acl, const struct xml_elem *parent )
1682 WCHAR *psclsid = NULL;
1683 struct entity *entity;
1684 struct xml_attr attr;
1685 BOOL end = FALSE;
1687 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1689 set_error( xmlbuf );
1690 return;
1693 while (next_xml_attr(xmlbuf, &attr, &end))
1695 if (xml_attr_cmp(&attr, L"iid"))
1697 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1699 else if (xml_attr_cmp(&attr, L"name"))
1701 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1703 else if (xml_attr_cmp(&attr, L"baseInterface"))
1705 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1706 entity->u.ifaceps.mask |= BaseIface;
1708 else if (xml_attr_cmp(&attr, L"numMethods"))
1710 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1711 entity->u.ifaceps.mask |= NumMethods;
1713 else if (xml_attr_cmp(&attr, L"tlbid"))
1715 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1717 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
1719 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1721 /* not used */
1722 else if (xml_attr_cmp(&attr, L"threadingModel"))
1725 else if (!is_xmlns_attr( &attr ))
1727 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1731 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1732 if (!end) parse_expect_end_elem(xmlbuf, parent);
1734 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1736 RtlFreeHeap(GetProcessHeap(), 0, psclsid);
1739 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1741 WORD *flags = &entity->u.typelib.flags;
1742 const WCHAR *str = value->ptr, *start;
1743 int i = 0;
1745 *flags = 0;
1747 /* it's comma separated list of flags */
1748 while (i < value->len)
1750 start = str;
1751 while (*str != ',' && (i++ < value->len)) str++;
1753 if (!wcsnicmp(start, L"RESTRICTED", str-start))
1754 *flags |= LIBFLAG_FRESTRICTED;
1755 else if (!wcsnicmp(start, L"CONTROL", str-start))
1756 *flags |= LIBFLAG_FCONTROL;
1757 else if (!wcsnicmp(start, L"HIDDEN", str-start))
1758 *flags |= LIBFLAG_FHIDDEN;
1759 else if (!wcsnicmp(start, L"HASDISKIMAGE", str-start))
1760 *flags |= LIBFLAG_FHASDISKIMAGE;
1761 else
1763 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1764 return FALSE;
1767 /* skip separator */
1768 str++;
1769 i++;
1772 return TRUE;
1775 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1777 unsigned int ver[2];
1778 unsigned int pos;
1779 const WCHAR *curr;
1781 /* major.minor */
1782 ver[0] = ver[1] = pos = 0;
1783 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1785 if (*curr >= '0' && *curr <= '9')
1787 ver[pos] = ver[pos] * 10 + *curr - '0';
1788 if (ver[pos] >= 0x10000) goto error;
1790 else if (*curr == '.')
1792 if (++pos >= 2) goto error;
1794 else goto error;
1796 entity->u.typelib.major = ver[0];
1797 entity->u.typelib.minor = ver[1];
1798 return TRUE;
1800 error:
1801 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1802 return FALSE;
1805 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1806 struct actctx_loader *acl, const struct xml_elem *parent )
1808 struct xml_attr attr;
1809 BOOL end = FALSE;
1810 struct entity* entity;
1812 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1814 set_error( xmlbuf );
1815 return;
1818 while (next_xml_attr(xmlbuf, &attr, &end))
1820 if (xml_attr_cmp(&attr, L"tlbid"))
1822 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1824 else if (xml_attr_cmp(&attr, L"version"))
1826 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1828 else if (xml_attr_cmp(&attr, L"helpdir"))
1830 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1832 else if (xml_attr_cmp(&attr, L"flags"))
1834 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1836 else if (!is_xmlns_attr( &attr ))
1838 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1842 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1843 if (!end) parse_expect_end_elem(xmlbuf, parent);
1846 static inline int aligned_string_len(int len)
1848 return (len + 3) & ~3;
1851 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1853 struct assembly_version *ver = &assembly->id.version;
1854 WCHAR buff[25];
1856 if (!ret) ret = buff;
1857 return swprintf(ret, ARRAY_SIZE(buff), L"%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
1860 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1861 struct actctx_loader *acl, const struct xml_elem *parent )
1863 struct xml_elem elem;
1864 struct xml_attr attr;
1865 xmlstr_t content;
1866 BOOL end = FALSE;
1867 struct entity* entity;
1869 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1871 set_error( xmlbuf );
1872 return;
1874 entity->u.class.versioned = TRUE;
1875 while (next_xml_attr(xmlbuf, &attr, &end))
1877 if (xml_attr_cmp(&attr, L"versioned"))
1879 if (xmlstr_cmpi(&attr.value, L"no"))
1880 entity->u.class.versioned = FALSE;
1881 else if (!xmlstr_cmpi(&attr.value, L"yes"))
1882 set_error( xmlbuf );
1884 else if (!is_xmlns_attr( &attr ))
1886 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1890 if (end) return;
1892 if (!parse_text_content(xmlbuf, &content)) return;
1893 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1895 acl->actctx->sections |= WINDOWCLASS_SECTION;
1897 while (next_xml_elem(xmlbuf, &elem, parent))
1899 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1900 parse_unknown_elem(xmlbuf, &elem);
1904 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1906 struct xml_attr attr;
1907 BOOL end = FALSE;
1909 while (next_xml_attr(xmlbuf, &attr, &end))
1911 if (xml_attr_cmp(&attr, L"oldVersion"))
1913 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1915 else if (xml_attr_cmp(&attr, L"newVersion"))
1917 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1919 else if (!is_xmlns_attr( &attr ))
1921 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1925 if (!end) parse_expect_end_elem(xmlbuf, parent);
1928 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1930 struct xml_elem elem;
1931 struct xml_attr attr;
1932 xmlstr_t content;
1933 BOOL end = FALSE;
1935 while (next_xml_attr(xmlbuf, &attr, &end))
1937 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1940 if (end) return;
1941 if (!parse_text_content(xmlbuf, &content)) return;
1943 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1945 while (next_xml_elem(xmlbuf, &elem, parent))
1947 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1948 parse_unknown_elem(xmlbuf, &elem);
1952 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
1953 struct assembly* assembly,
1954 struct actctx_loader* acl,
1955 const struct xml_elem *parent)
1957 struct xml_attr attr;
1958 BOOL end = FALSE;
1959 struct entity* entity;
1961 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1963 set_error( xmlbuf );
1964 return;
1967 while (next_xml_attr(xmlbuf, &attr, &end))
1969 if (xml_attr_cmp(&attr, L"iid"))
1971 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1973 else if (xml_attr_cmp(&attr, L"name"))
1975 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1977 else if (xml_attr_cmp(&attr, L"baseInterface"))
1979 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1980 entity->u.ifaceps.mask |= BaseIface;
1982 else if (xml_attr_cmp(&attr, L"numMethods"))
1984 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1985 entity->u.ifaceps.mask |= NumMethods;
1987 else if (xml_attr_cmp(&attr, L"proxyStubClsid32"))
1989 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1991 else if (xml_attr_cmp(&attr, L"tlbid"))
1993 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1995 else if (!is_xmlns_attr( &attr ))
1997 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2001 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2002 if (!end) parse_expect_end_elem(xmlbuf, parent);
2005 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2006 struct actctx_loader *acl, const struct xml_elem *parent )
2009 struct xml_elem elem;
2010 struct xml_attr attr;
2011 BOOL end = FALSE;
2012 struct entity* entity;
2014 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2016 set_error( xmlbuf );
2017 return;
2020 while (next_xml_attr(xmlbuf, &attr, &end))
2022 if (xml_attr_cmp(&attr, L"name"))
2024 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2026 else if (xml_attr_cmp(&attr, L"clsid"))
2028 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2030 else if (xml_attr_cmp(&attr, L"progid"))
2032 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2034 else if (xml_attr_cmp(&attr, L"tlbid"))
2036 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2038 else if (xml_attr_cmp(&attr, L"threadingModel"))
2040 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2042 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2044 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2046 else if (!is_xmlns_attr( &attr ))
2048 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2052 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2053 if (entity->u.comclass.progid)
2054 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2055 if (end) return;
2057 while (next_xml_elem(xmlbuf, &elem, parent))
2059 if (xml_elem_cmp(&elem, L"progid", asmv1W))
2061 parse_com_class_progid(xmlbuf, entity, &elem);
2063 else
2065 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2066 parse_unknown_elem(xmlbuf, &elem);
2070 if (entity->u.comclass.progids.num)
2071 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2074 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2075 struct actctx_loader *acl, const struct xml_elem *parent )
2077 struct xml_attr attr;
2078 BOOL end = FALSE;
2079 struct entity* entity;
2081 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2083 set_error( xmlbuf );
2084 return;
2087 while (next_xml_attr(xmlbuf, &attr, &end))
2089 if (xml_attr_cmp(&attr, L"name"))
2091 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2093 else if (xml_attr_cmp(&attr, L"clsid"))
2095 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2097 else if (xml_attr_cmp(&attr, L"runtimeVersion"))
2099 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2101 else if (!is_xmlns_attr( &attr ))
2103 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2107 acl->actctx->sections |= CLRSURROGATES_SECTION;
2108 if (!end) parse_expect_end_elem(xmlbuf, parent);
2111 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2112 const struct xml_elem *parent, BOOL optional )
2114 struct xml_elem elem;
2115 struct xml_attr attr;
2116 struct assembly_identity ai;
2117 BOOL end = FALSE;
2119 memset(&ai, 0, sizeof(ai));
2120 ai.optional = optional;
2122 while (next_xml_attr(xmlbuf, &attr, &end))
2124 if (xml_attr_cmp(&attr, L"allowDelayedBinding"))
2125 ai.delayed = xmlstr_cmp(&attr.value, L"true");
2126 else if (!is_xmlns_attr( &attr ))
2127 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2130 if (end) return;
2132 while (next_xml_elem(xmlbuf, &elem, parent))
2134 if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2136 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2137 /* store the newly found identity for later loading */
2138 if (ai.arch && !wcscmp(ai.arch, L"*"))
2140 RtlFreeHeap( GetProcessHeap(), 0, ai.arch );
2141 ai.arch = strdupW( current_archW );
2143 TRACE( "adding name=%s version=%s arch=%s\n",
2144 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2145 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2147 else if (xml_elem_cmp(&elem, L"bindingRedirect", asmv1W))
2149 parse_binding_redirect_elem(xmlbuf, &elem);
2151 else
2153 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2154 parse_unknown_elem(xmlbuf, &elem);
2159 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2160 const struct xml_elem *parent )
2163 struct xml_elem elem;
2164 struct xml_attr attr;
2165 BOOL end = FALSE, optional = FALSE;
2167 while (next_xml_attr(xmlbuf, &attr, &end))
2169 if (xml_attr_cmp(&attr, L"optional"))
2171 optional = xmlstr_cmpi( &attr.value, L"yes" );
2172 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2174 else if (!is_xmlns_attr( &attr ))
2176 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2180 if (end) return;
2182 while (next_xml_elem(xmlbuf, &elem, parent))
2184 if (xml_elem_cmp(&elem, L"dependentAssembly", asmv1W))
2186 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2188 else
2190 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2191 parse_unknown_elem(xmlbuf, &elem);
2196 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2198 BOOL end = FALSE;
2200 parse_expect_no_attr(xmlbuf, &end);
2201 if (!end) parse_expect_end_elem(xmlbuf, parent);
2204 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2206 BOOL end = FALSE;
2208 parse_expect_no_attr(xmlbuf, &end);
2209 if (!end) parse_expect_end_elem(xmlbuf, parent);
2212 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2213 struct actctx_loader* acl, const struct xml_elem *parent )
2215 struct xml_elem elem;
2216 struct xml_attr attr;
2217 BOOL end = FALSE;
2218 struct dll_redirect* dll;
2220 if (!(dll = add_dll_redirect(assembly)))
2222 set_error( xmlbuf );
2223 return;
2226 while (next_xml_attr(xmlbuf, &attr, &end))
2228 if (xml_attr_cmp(&attr, L"name"))
2230 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2231 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2233 else if (xml_attr_cmp(&attr, L"loadFrom"))
2235 if (!(dll->load_from = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2237 else if (xml_attr_cmp(&attr, L"hash"))
2239 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2241 else if (xml_attr_cmp(&attr, L"hashalg"))
2243 if (!xmlstr_cmpi(&attr.value, L"SHA1"))
2244 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2246 else if (!is_xmlns_attr( &attr ))
2248 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2252 if (!dll->name) set_error( xmlbuf );
2254 acl->actctx->sections |= DLLREDIRECT_SECTION;
2256 if (end) return;
2258 while (next_xml_elem(xmlbuf, &elem, parent))
2260 if (xml_elem_cmp(&elem, L"comClass", asmv1W))
2262 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2264 else if (xml_elem_cmp(&elem, L"comInterfaceProxyStub", asmv1W))
2266 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2268 else if (xml_elem_cmp(&elem, L"hash", asmv2W))
2270 WARN("asmv2:hash (undocumented) not supported\n");
2271 parse_unknown_elem(xmlbuf, &elem);
2273 else if (xml_elem_cmp(&elem, L"typelib", asmv1W))
2275 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2277 else if (xml_elem_cmp(&elem, L"windowClass", asmv1W))
2279 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2281 else
2283 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2284 parse_unknown_elem( xmlbuf, &elem );
2289 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2290 struct actctx_loader *acl, const struct xml_elem *parent )
2292 struct xml_attr attr;
2293 BOOL end = FALSE;
2295 while (next_xml_attr(xmlbuf, &attr, &end))
2297 if (xml_attr_cmp(&attr, L"Id"))
2299 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2300 UNICODE_STRING str;
2301 GUID compat_id;
2303 str.Buffer = (PWSTR)attr.value.ptr;
2304 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2305 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2307 if (!(compat = add_compat_context(assembly)))
2309 set_error( xmlbuf );
2310 return;
2312 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2313 compat->Id = compat_id;
2315 else
2317 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2320 else if (!is_xmlns_attr( &attr ))
2322 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2326 if (!end) parse_expect_end_elem(xmlbuf, parent);
2329 static void parse_maxversiontested_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2330 struct actctx_loader *acl, const struct xml_elem *parent )
2332 struct xml_attr attr;
2333 BOOL end = FALSE;
2335 while (next_xml_attr(xmlbuf, &attr, &end))
2337 if (xml_attr_cmp(&attr, L"Id"))
2339 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2340 struct assembly_version version;
2342 if (!(compat = add_compat_context(assembly)))
2344 set_error( xmlbuf );
2345 return;
2347 parse_version( &attr.value, &version );
2348 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_MAXVERSIONTESTED;
2349 compat->MaxVersionTested = (ULONGLONG)version.major << 48 |
2350 (ULONGLONG)version.minor << 32 | version.build << 16 | version.revision;
2352 else if (!is_xmlns_attr( &attr ))
2354 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2358 if (!end) parse_expect_end_elem(xmlbuf, parent);
2361 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2362 struct actctx_loader* acl, const struct xml_elem *parent)
2364 struct xml_elem elem;
2366 while (next_xml_elem(xmlbuf, &elem, parent))
2368 if (xml_elem_cmp(&elem, L"supportedOS", compatibilityNSW))
2370 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2372 else if (xml_elem_cmp(&elem, L"maxversiontested", compatibilityNSW))
2374 parse_maxversiontested_elem(xmlbuf, assembly, acl, &elem);
2376 else
2378 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2379 parse_unknown_elem(xmlbuf, &elem);
2384 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2385 struct actctx_loader* acl, const struct xml_elem *parent)
2387 struct xml_elem elem;
2389 while (next_xml_elem(xmlbuf, &elem, parent))
2391 if (xml_elem_cmp(&elem, L"application", compatibilityNSW))
2393 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2395 else
2397 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2398 parse_unknown_elem(xmlbuf, &elem);
2403 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2404 struct xml_elem *parent )
2406 struct xml_elem elem;
2407 struct xml_attr attr;
2408 xmlstr_t content;
2409 BOOL end = FALSE;
2410 struct entity *entity;
2412 while (next_xml_attr( xmlbuf, &attr, &end ))
2414 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2417 if (end) return;
2419 if (!parse_text_content( xmlbuf, &content )) return;
2420 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2422 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2423 if (!entity)
2425 set_error( xmlbuf );
2426 return;
2428 entity->u.settings.name = xmlstrdupW( &parent->name );
2429 entity->u.settings.value = xmlstrdupW( &content );
2430 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2432 while (next_xml_elem(xmlbuf, &elem, parent))
2434 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2435 parse_unknown_elem( xmlbuf, &elem );
2439 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2440 struct actctx_loader *acl, const struct xml_elem *parent )
2442 struct xml_elem elem;
2444 while (next_xml_elem( xmlbuf, &elem, parent ))
2446 if (xml_elem_cmp( &elem, L"autoElevate", windowsSettings2005NSW ) ||
2447 xml_elem_cmp( &elem, L"disableTheming", windowsSettings2005NSW ) ||
2448 xml_elem_cmp( &elem, L"disableWindowFiltering", windowsSettings2011NSW ) ||
2449 xml_elem_cmp( &elem, L"dpiAware", windowsSettings2005NSW ) ||
2450 xml_elem_cmp( &elem, L"dpiAwareness", windowsSettings2016NSW ) ||
2451 xml_elem_cmp( &elem, L"gdiScaling", windowsSettings2017NSW ) ||
2452 xml_elem_cmp( &elem, L"highResolutionScrollingAware", windowsSettings2017NSW ) ||
2453 xml_elem_cmp( &elem, L"longPathAware", windowsSettings2016NSW ) ||
2454 xml_elem_cmp( &elem, L"magicFutureSetting", windowsSettings2017NSW ) ||
2455 xml_elem_cmp( &elem, L"printerDriverIsolation", windowsSettings2011NSW ) ||
2456 xml_elem_cmp( &elem, L"ultraHighResolutionScrollingAware", windowsSettings2017NSW ))
2458 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2460 else
2462 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2463 parse_unknown_elem( xmlbuf, &elem );
2468 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2469 struct actctx_loader *acl, const struct xml_elem *parent )
2471 struct xml_elem elem;
2473 while (next_xml_elem( xmlbuf, &elem, parent ))
2475 if (xml_elem_cmp( &elem, L"windowsSettings", asmv3W ))
2477 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2479 else
2481 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2482 parse_unknown_elem( xmlbuf, &elem );
2487 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2488 struct actctx_loader *acl, const struct xml_elem *parent )
2490 struct xml_elem elem;
2491 struct xml_attr attr;
2492 BOOL end = FALSE;
2494 /* Multiple requestedExecutionLevel elements are not supported. */
2495 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2497 while (next_xml_attr(xmlbuf, &attr, &end))
2499 if (xml_attr_cmp(&attr, L"level"))
2501 if (xmlstr_cmpi(&attr.value, L"asInvoker"))
2502 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2503 else if (xmlstr_cmpi(&attr.value, L"highestAvailable"))
2504 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2505 else if (xmlstr_cmpi(&attr.value, L"requireAdministrator"))
2506 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2507 else
2508 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2510 else if (xml_attr_cmp(&attr, L"uiAccess"))
2512 if (xmlstr_cmpi(&attr.value, L"false"))
2513 assembly->ui_access = FALSE;
2514 else if (xmlstr_cmpi(&attr.value, L"true"))
2515 assembly->ui_access = TRUE;
2516 else
2517 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2519 else if (!is_xmlns_attr( &attr ))
2520 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2523 if (end) return;
2525 while (next_xml_elem(xmlbuf, &elem, parent))
2527 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2528 parse_unknown_elem(xmlbuf, &elem);
2532 static void parse_requested_privileges_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"requestedExecutionLevel", asmv1W))
2541 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2543 else
2545 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2546 parse_unknown_elem(xmlbuf, &elem);
2551 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2552 struct actctx_loader *acl, const struct xml_elem *parent )
2554 struct xml_elem elem;
2556 while (next_xml_elem(xmlbuf, &elem, parent))
2558 if (xml_elem_cmp(&elem, L"requestedPrivileges", asmv1W))
2560 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2562 else
2564 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2565 parse_unknown_elem(xmlbuf, &elem);
2570 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2571 struct actctx_loader *acl, const struct xml_elem *parent )
2573 struct xml_elem elem;
2575 while (next_xml_elem(xmlbuf, &elem, parent))
2577 if (xml_elem_cmp(&elem, L"security", asmv1W))
2579 parse_security_elem(xmlbuf, assembly, acl, &elem);
2581 else
2583 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2584 parse_unknown_elem(xmlbuf, &elem);
2589 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2590 struct actctx_loader* acl, const struct xml_elem *parent,
2591 struct assembly_identity* expected_ai)
2593 struct xml_elem elem;
2594 struct xml_attr attr;
2595 BOOL end = FALSE, version = FALSE;
2597 TRACE("(%p)\n", xmlbuf);
2599 while (next_xml_attr(xmlbuf, &attr, &end))
2601 if (xml_attr_cmp(&attr, L"manifestVersion"))
2603 if (!xmlstr_cmp(&attr.value, L"1.0"))
2605 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2606 break;
2608 version = TRUE;
2610 else if (!is_xmlns_attr( &attr ))
2612 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2616 if (end || !version)
2618 set_error( xmlbuf );
2619 return;
2622 while (next_xml_elem(xmlbuf, &elem, parent))
2624 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, L"noInherit", asmv1W))
2626 parse_noinherit_elem(xmlbuf, &elem);
2627 assembly->no_inherit = TRUE;
2629 else if (xml_elem_cmp(&elem, L"noInheritable", asmv1W))
2631 parse_noinheritable_elem(xmlbuf, &elem);
2633 else if (xml_elem_cmp(&elem, L"description", asmv1W))
2635 parse_description_elem(xmlbuf, &elem);
2637 else if (xml_elem_cmp(&elem, L"comInterfaceExternalProxyStub", asmv1W))
2639 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2641 else if (xml_elem_cmp(&elem, L"dependency", asmv1W))
2643 parse_dependency_elem(xmlbuf, acl, &elem);
2645 else if (xml_elem_cmp(&elem, L"file", asmv1W))
2647 parse_file_elem(xmlbuf, assembly, acl, &elem);
2649 else if (xml_elem_cmp(&elem, L"clrClass", asmv1W))
2651 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2653 else if (xml_elem_cmp(&elem, L"clrSurrogate", asmv1W))
2655 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2657 else if (xml_elem_cmp(&elem, L"trustInfo", asmv1W))
2659 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2661 else if (xml_elem_cmp(&elem, L"assemblyIdentity", asmv1W))
2663 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2665 if (!xmlbuf->error && expected_ai)
2667 /* FIXME: more tests */
2668 if (assembly->type == ASSEMBLY_MANIFEST &&
2669 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2671 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2672 expected_ai->version.major, expected_ai->version.minor,
2673 expected_ai->version.build, expected_ai->version.revision,
2674 assembly->id.version.major, assembly->id.version.minor,
2675 assembly->id.version.build, assembly->id.version.revision);
2676 set_error( xmlbuf );
2678 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2679 (assembly->id.version.major != expected_ai->version.major ||
2680 assembly->id.version.minor != expected_ai->version.minor ||
2681 assembly->id.version.build < expected_ai->version.build ||
2682 (assembly->id.version.build == expected_ai->version.build &&
2683 assembly->id.version.revision < expected_ai->version.revision)))
2685 FIXME("wrong version for shared assembly manifest\n");
2686 set_error( xmlbuf );
2690 else if (xml_elem_cmp(&elem, L"compatibility", compatibilityNSW))
2692 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2694 else if (xml_elem_cmp(&elem, L"application", asmv3W))
2696 parse_application_elem(xmlbuf, assembly, acl, &elem);
2698 else
2700 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2701 parse_unknown_elem(xmlbuf, &elem);
2705 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2706 assembly->no_inherit)
2708 set_error( xmlbuf );
2712 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2713 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2715 struct xml_elem elem;
2716 struct xml_elem parent = {};
2718 xmlbuf->error = FALSE;
2719 xmlbuf->ns_pos = 0;
2721 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2723 if (xmlstr_cmp(&elem.name, L"?xml") &&
2724 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2725 return STATUS_SXS_CANT_GEN_ACTCTX;
2727 if (!xml_elem_cmp(&elem, L"assembly", asmv1W))
2729 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2730 return STATUS_SXS_CANT_GEN_ACTCTX;
2733 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2734 if (xmlbuf->error)
2736 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2737 return STATUS_SXS_CANT_GEN_ACTCTX;
2740 if (next_xml_elem(xmlbuf, &elem, &parent))
2742 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2743 return STATUS_SXS_CANT_GEN_ACTCTX;
2746 if (xmlbuf->ptr != xmlbuf->end)
2748 FIXME("parse error\n");
2749 return STATUS_SXS_CANT_GEN_ACTCTX;
2751 return STATUS_SUCCESS;
2754 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2755 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2756 const void *buffer, SIZE_T size )
2758 xmlbuf_t xmlbuf;
2759 NTSTATUS status;
2760 struct assembly *assembly;
2761 int unicode_tests;
2763 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2765 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2766 return STATUS_SXS_CANT_GEN_ACTCTX;
2768 if (directory && !(assembly->directory = strdupW(directory)))
2769 return STATUS_NO_MEMORY;
2771 if (!filename)
2773 UNICODE_STRING module_path;
2774 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2775 assembly->manifest.info = module_path.Buffer;
2777 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2779 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2780 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2782 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2783 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2785 xmlbuf.ptr = buffer;
2786 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2787 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2789 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2791 const WCHAR *buf = buffer;
2792 WCHAR *new_buff;
2793 unsigned int i;
2795 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2796 return STATUS_NO_MEMORY;
2797 for (i = 0; i < size / sizeof(WCHAR); i++)
2798 new_buff[i] = RtlUshortByteSwap( buf[i] );
2799 xmlbuf.ptr = new_buff;
2800 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2801 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2802 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2804 else
2806 DWORD len;
2807 WCHAR *new_buff;
2809 /* let's assume utf-8 for now */
2810 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2811 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2812 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2813 xmlbuf.ptr = new_buff;
2814 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2815 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2816 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2818 return status;
2821 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2823 OBJECT_ATTRIBUTES attr;
2824 IO_STATUS_BLOCK io;
2826 attr.Length = sizeof(attr);
2827 attr.RootDirectory = 0;
2828 attr.Attributes = OBJ_CASE_INSENSITIVE;
2829 attr.ObjectName = name;
2830 attr.SecurityDescriptor = NULL;
2831 attr.SecurityQualityOfService = NULL;
2832 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2835 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2836 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2837 HANDLE hModule, LPCWSTR resname, ULONG lang )
2839 NTSTATUS status;
2840 UNICODE_STRING nameW;
2841 LDR_RESOURCE_INFO info;
2842 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2843 void *ptr;
2845 if (TRACE_ON(actctx))
2847 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2849 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2850 hModule, debugstr_w(nameW.Buffer) );
2851 RtlFreeUnicodeString( &nameW );
2853 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2854 hModule, debugstr_w(filename) );
2857 if (!resname) return STATUS_INVALID_PARAMETER;
2859 info.Type = RT_MANIFEST;
2860 info.Language = lang;
2861 if (!((ULONG_PTR)resname >> 16))
2863 info.Name = (ULONG_PTR)resname;
2864 status = LdrFindResource_U(hModule, &info, 3, &entry);
2866 else if (resname[0] == '#')
2868 ULONG value;
2869 RtlInitUnicodeString(&nameW, resname + 1);
2870 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2871 return STATUS_INVALID_PARAMETER;
2872 info.Name = value;
2873 status = LdrFindResource_U(hModule, &info, 3, &entry);
2875 else
2877 RtlCreateUnicodeString(&nameW, resname);
2878 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2879 info.Name = (ULONG_PTR)nameW.Buffer;
2880 status = LdrFindResource_U(hModule, &info, 3, &entry);
2881 RtlFreeUnicodeString(&nameW);
2883 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2885 if (status == STATUS_SUCCESS)
2886 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2888 return status;
2891 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2892 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2893 HANDLE file, LPCWSTR resname, ULONG lang )
2895 HANDLE mapping;
2896 OBJECT_ATTRIBUTES attr;
2897 LARGE_INTEGER size;
2898 LARGE_INTEGER offset;
2899 NTSTATUS status;
2900 SIZE_T count;
2901 void *base;
2903 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2905 attr.Length = sizeof(attr);
2906 attr.RootDirectory = 0;
2907 attr.ObjectName = NULL;
2908 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2909 attr.SecurityDescriptor = NULL;
2910 attr.SecurityQualityOfService = NULL;
2912 size.QuadPart = 0;
2913 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2914 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2915 if (status != STATUS_SUCCESS) return status;
2917 offset.QuadPart = 0;
2918 count = 0;
2919 base = NULL;
2920 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2921 &count, ViewShare, 0, PAGE_READONLY );
2922 NtClose( mapping );
2923 if (status != STATUS_SUCCESS) return status;
2925 if (RtlImageNtHeader(base)) /* we got a PE file */
2927 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2928 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2930 else status = STATUS_INVALID_IMAGE_FORMAT;
2932 NtUnmapViewOfSection( GetCurrentProcess(), base );
2933 return status;
2936 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2937 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2939 FILE_END_OF_FILE_INFORMATION info;
2940 IO_STATUS_BLOCK io;
2941 HANDLE mapping;
2942 OBJECT_ATTRIBUTES attr;
2943 LARGE_INTEGER size;
2944 LARGE_INTEGER offset;
2945 NTSTATUS status;
2946 SIZE_T count;
2947 void *base;
2949 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2951 attr.Length = sizeof(attr);
2952 attr.RootDirectory = 0;
2953 attr.ObjectName = NULL;
2954 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2955 attr.SecurityDescriptor = NULL;
2956 attr.SecurityQualityOfService = NULL;
2958 size.QuadPart = 0;
2959 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2960 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2961 if (status != STATUS_SUCCESS) return status;
2963 offset.QuadPart = 0;
2964 count = 0;
2965 base = NULL;
2966 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2967 &count, ViewShare, 0, PAGE_READONLY );
2968 NtClose( mapping );
2969 if (status != STATUS_SUCCESS) return status;
2971 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2972 if (status == STATUS_SUCCESS)
2973 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
2975 NtUnmapViewOfSection( GetCurrentProcess(), base );
2976 return status;
2979 /* try to load the .manifest file associated to the file */
2980 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2981 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2983 WCHAR *buffer;
2984 NTSTATUS status;
2985 UNICODE_STRING nameW;
2986 HANDLE file;
2987 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2989 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2991 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2993 if (module) /* use the module filename */
2995 UNICODE_STRING name;
2997 if (!(status = get_module_filename( module, &name, sizeof(L".manifest") + 10*sizeof(WCHAR) )))
2999 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, L".%lu", resid );
3000 wcscat( name.Buffer, L".manifest" );
3001 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3002 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3003 RtlFreeUnicodeString( &name );
3005 if (status) return status;
3007 else
3009 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3010 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(L".manifest") )))
3011 return STATUS_NO_MEMORY;
3012 wcscpy( buffer, filename );
3013 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, L".%lu", resid );
3014 wcscat( buffer, L".manifest" );
3015 RtlInitUnicodeString( &nameW, buffer );
3018 if (!open_nt_file( &file, &nameW ))
3020 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3021 NtClose( file );
3023 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3024 RtlFreeUnicodeString( &nameW );
3025 return status;
3028 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3030 static const WCHAR lookup_fmtW[] = L"%s_%s_%s_%u.%u.*.*_%s_*.manifest";
3031 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3033 WCHAR *lookup, *ret = NULL;
3034 UNICODE_STRING lookup_us;
3035 IO_STATUS_BLOCK io;
3036 const WCHAR *lang = ai->language;
3037 unsigned int data_pos = 0, data_len, len;
3038 char buffer[8192];
3040 if (!lang || !wcsicmp( lang, L"neutral" )) lang = L"*";
3042 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3043 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3044 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3045 ai->version.major, ai->version.minor, lang );
3046 RtlInitUnicodeString( &lookup_us, lookup );
3048 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3049 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3051 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3052 FILE_BOTH_DIR_INFORMATION *dir_info;
3053 WCHAR *tmp;
3054 ULONG build, revision;
3056 data_len = io.Information;
3058 for (;;)
3060 if (data_pos >= data_len)
3062 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3063 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3064 break;
3065 data_len = io.Information;
3066 data_pos = 0;
3068 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3070 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3071 else data_pos = data_len;
3073 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3074 build = wcstoul( tmp, NULL, 10 );
3075 if (build < min_build) continue;
3076 tmp = wcschr(tmp, '.') + 1;
3077 revision = wcstoul( tmp, NULL, 10 );
3078 if (build == min_build && revision < min_revision) continue;
3079 tmp = wcschr(tmp, '_') + 1;
3080 tmp = wcschr(tmp, '_') + 1;
3081 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3082 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3084 /* prefer a non-Wine manifest if we already have one */
3085 /* we'll still load the builtin dll if specified through DllOverrides */
3086 if (ret) continue;
3088 else
3090 min_build = build;
3091 min_revision = revision;
3093 ai->version.build = build;
3094 ai->version.revision = revision;
3095 RtlFreeHeap( GetProcessHeap(), 0, ret );
3096 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3098 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3099 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3103 else WARN("no matching file for %s\n", debugstr_w(lookup));
3104 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3105 return ret;
3108 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3110 struct assembly_identity sxs_ai;
3111 UNICODE_STRING path_us;
3112 OBJECT_ATTRIBUTES attr;
3113 IO_STATUS_BLOCK io;
3114 WCHAR *path, *file = NULL;
3115 HANDLE handle;
3117 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3119 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(L"\\winsxs\\manifests") +
3120 wcslen(windows_dir) * sizeof(WCHAR) )))
3121 return STATUS_NO_MEMORY;
3123 wcscpy( path, windows_dir );
3124 wcscat( path, L"\\winsxs\\manifests" );
3126 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3128 RtlFreeHeap( GetProcessHeap(), 0, path );
3129 return STATUS_NO_SUCH_FILE;
3131 RtlFreeHeap( GetProcessHeap(), 0, path );
3133 attr.Length = sizeof(attr);
3134 attr.RootDirectory = 0;
3135 attr.Attributes = OBJ_CASE_INSENSITIVE;
3136 attr.ObjectName = &path_us;
3137 attr.SecurityDescriptor = NULL;
3138 attr.SecurityQualityOfService = NULL;
3140 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3141 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3143 sxs_ai = *ai;
3144 file = lookup_manifest_file( handle, &sxs_ai );
3145 NtClose( handle );
3147 if (!file)
3149 RtlFreeUnicodeString( &path_us );
3150 return STATUS_NO_SUCH_FILE;
3153 /* append file name to directory path */
3154 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3155 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3157 RtlFreeHeap( GetProcessHeap(), 0, file );
3158 RtlFreeUnicodeString( &path_us );
3159 return STATUS_NO_MEMORY;
3162 path[path_us.Length/sizeof(WCHAR)] = '\\';
3163 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3164 RtlInitUnicodeString( &path_us, path );
3165 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3167 if (!open_nt_file( &handle, &path_us ))
3169 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3170 NtClose( handle );
3172 else io.u.Status = STATUS_NO_SUCH_FILE;
3174 RtlFreeHeap( GetProcessHeap(), 0, file );
3175 RtlFreeUnicodeString( &path_us );
3176 return io.u.Status;
3179 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3180 struct assembly_identity* ai)
3182 unsigned int i;
3183 WCHAR *buffer, *p, *directory;
3184 NTSTATUS status;
3185 UNICODE_STRING nameW;
3186 HANDLE file;
3187 DWORD len;
3189 TRACE( "looking for name=%s version=%s arch=%s\n",
3190 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3192 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3194 /* FIXME: add support for language specific lookup */
3196 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3197 wcslen(acl->actctx->appdir.info));
3199 nameW.Buffer = NULL;
3200 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3201 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(L".manifest") )))
3202 return STATUS_NO_MEMORY;
3204 if (!(directory = build_assembly_dir( ai )))
3206 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3207 return STATUS_NO_MEMORY;
3210 /* Lookup in <dir>\name.dll
3211 * <dir>\name.manifest
3212 * <dir>\name\name.dll
3213 * <dir>\name\name.manifest
3215 * First 'appdir' is used as <dir>, if that failed
3216 * it tries application manifest file path.
3218 wcscpy( buffer, acl->actctx->appdir.info );
3219 p = buffer + wcslen(buffer);
3220 for (i = 0; i < 4; i++)
3222 if (i == 2)
3224 struct assembly *assembly = acl->actctx->assemblies;
3225 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3227 else *p++ = '\\';
3229 wcscpy( p, ai->name );
3230 p += wcslen(p);
3232 wcscpy( p, L".dll" );
3233 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3235 status = open_nt_file( &file, &nameW );
3236 if (!status)
3238 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3239 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3240 NtClose( file );
3241 if (status == STATUS_SUCCESS)
3242 break;
3244 RtlFreeUnicodeString( &nameW );
3247 wcscpy( p, L".manifest" );
3248 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3250 status = open_nt_file( &file, &nameW );
3251 if (!status)
3253 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3254 NtClose( file );
3255 break;
3257 RtlFreeUnicodeString( &nameW );
3259 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3261 RtlFreeUnicodeString( &nameW );
3262 RtlFreeHeap( GetProcessHeap(), 0, directory );
3263 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3264 return status;
3267 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3269 NTSTATUS status = STATUS_SUCCESS;
3270 unsigned int i;
3272 for (i = 0; i < acl->num_dependencies; i++)
3274 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3276 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3278 FIXME( "Could not find dependent assembly %s (%s)\n",
3279 debugstr_w(acl->dependencies[i].name),
3280 debugstr_version(&acl->dependencies[i].version) );
3281 status = STATUS_SXS_CANT_GEN_ACTCTX;
3282 break;
3286 /* FIXME should now iterate through all refs */
3287 return status;
3290 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3291 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3293 NTSTATUS status = STATUS_SUCCESS;
3295 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3297 if (*handle) return STATUS_INVALID_PARAMETER;
3299 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3300 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3302 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3304 ULONG_PTR magic;
3305 LDR_DATA_TABLE_ENTRY *pldr;
3307 if (!*handle) return STATUS_INVALID_PARAMETER;
3309 LdrLockLoaderLock( 0, NULL, &magic );
3310 if (!LdrFindEntryForAddress( *handle, &pldr ))
3312 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3313 status = STATUS_DLL_NOT_FOUND;
3314 else
3315 *handle = pldr->ActivationContext;
3317 else status = STATUS_DLL_NOT_FOUND;
3318 LdrUnlockLoaderLock( 0, magic );
3320 else if (!*handle && (class != ActivationContextBasicInformation))
3321 *handle = process_actctx;
3323 return status;
3326 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3328 unsigned int i, j, total_len = 0, dll_count = 0;
3329 struct strsection_header *header;
3330 struct dllredirect_data *data;
3331 struct string_index *index;
3332 ULONG name_offset;
3334 /* compute section length */
3335 for (i = 0; i < actctx->num_assemblies; i++)
3337 struct assembly *assembly = &actctx->assemblies[i];
3338 for (j = 0; j < assembly->num_dlls; j++)
3340 struct dll_redirect *dll = &assembly->dlls[j];
3342 /* each entry needs index, data and string data */
3343 total_len += sizeof(*index);
3344 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3345 if (dll->load_from)
3347 total_len += offsetof( struct dllredirect_data, paths[1] );
3348 total_len += aligned_string_len( wcslen(dll->load_from) * sizeof(WCHAR) );
3350 else total_len += offsetof( struct dllredirect_data, paths[0] );
3353 dll_count += assembly->num_dlls;
3356 total_len += sizeof(*header);
3358 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3359 if (!header) return STATUS_NO_MEMORY;
3361 memset(header, 0, sizeof(*header));
3362 header->magic = STRSECTION_MAGIC;
3363 header->size = sizeof(*header);
3364 header->count = dll_count;
3365 header->index_offset = sizeof(*header);
3366 index = (struct string_index*)((BYTE*)header + header->index_offset);
3367 name_offset = header->index_offset + header->count*sizeof(*index);
3369 for (i = 0; i < actctx->num_assemblies; i++)
3371 struct assembly *assembly = &actctx->assemblies[i];
3372 for (j = 0; j < assembly->num_dlls; j++)
3374 struct dll_redirect *dll = &assembly->dlls[j];
3375 UNICODE_STRING str;
3376 WCHAR *ptrW;
3378 /* setup new index entry */
3379 str.Buffer = dll->name;
3380 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3381 str.MaximumLength = str.Length + sizeof(WCHAR);
3382 /* hash original class name */
3383 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3385 index->name_offset = name_offset;
3386 index->name_len = str.Length;
3387 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3388 index->data_len = offsetof( struct dllredirect_data, paths[0] );
3389 index->rosterindex = i + 1;
3391 /* dll name */
3392 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3393 memcpy(ptrW, dll->name, index->name_len);
3394 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3395 name_offset += aligned_string_len(str.MaximumLength);
3397 /* setup data */
3398 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3399 if (dll->load_from)
3401 ULONG len = wcslen(dll->load_from) * sizeof(WCHAR);
3402 data->size = offsetof( struct dllredirect_data, paths[1] );
3403 data->flags = 0;
3404 data->total_len = aligned_string_len( len );
3405 data->paths_count = 1;
3406 data->paths_offset = index->data_offset + offsetof( struct dllredirect_data, paths[0] );
3407 data->paths[0].offset = index->data_offset + data->size;
3408 data->paths[0].len = len;
3409 ptrW = (WCHAR *)((BYTE *)header + data->paths[0].offset);
3410 memcpy( ptrW, dll->load_from, len );
3411 if (wcschr( dll->load_from, '%' )) data->flags |= DLL_REDIRECT_PATH_EXPAND;
3413 else
3415 data->size = offsetof( struct dllredirect_data, paths[0] );
3416 data->flags = DLL_REDIRECT_PATH_OMITS_ASSEMBLY_ROOT;
3417 data->total_len = 0;
3418 data->paths_count = 0;
3419 data->paths_offset = 0;
3421 name_offset += data->size + data->total_len;
3423 index++;
3427 *section = header;
3429 return STATUS_SUCCESS;
3432 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3434 struct string_index *iter, *index = NULL;
3435 UNICODE_STRING str;
3436 ULONG hash = 0, i;
3438 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3439 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3441 for (i = 0; i < section->count; i++)
3443 if (iter->hash == hash)
3445 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3446 str.Length = iter->name_len;
3447 if (RtlEqualUnicodeString( &str, name, TRUE ))
3449 index = iter;
3450 break;
3452 else
3453 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3455 iter++;
3458 return index;
3461 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3463 struct guid_index *iter, *index = NULL;
3464 ULONG i;
3466 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3468 for (i = 0; i < section->count; i++)
3470 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3472 index = iter;
3473 break;
3475 iter++;
3478 return index;
3481 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3483 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3486 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3487 PACTCTX_SECTION_KEYED_DATA data)
3489 struct dllredirect_data *dll;
3490 struct string_index *index;
3492 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3494 if (!actctx->dllredirect_section)
3496 struct strsection_header *section;
3498 NTSTATUS status = build_dllredirect_section(actctx, &section);
3499 if (status) return status;
3501 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3502 RtlFreeHeap(GetProcessHeap(), 0, section);
3505 index = find_string_index(actctx->dllredirect_section, name);
3506 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3508 if (data)
3510 dll = get_dllredirect_data(actctx, index);
3512 data->ulDataFormatVersion = 1;
3513 data->lpData = dll;
3514 data->ulLength = dll->size;
3515 data->lpSectionGlobalData = NULL;
3516 data->ulSectionGlobalDataLength = 0;
3517 data->lpSectionBase = actctx->dllredirect_section;
3518 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3519 data->hActCtx = NULL;
3521 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3522 data->ulAssemblyRosterIndex = index->rosterindex;
3525 return STATUS_SUCCESS;
3528 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3530 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3533 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3535 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3538 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3540 unsigned int i, j, k, total_len = 0, class_count = 0;
3541 struct wndclass_redirect_data *data;
3542 struct strsection_header *header;
3543 struct string_index *index;
3544 ULONG name_offset;
3546 /* compute section length */
3547 for (i = 0; i < actctx->num_assemblies; i++)
3549 struct assembly *assembly = &actctx->assemblies[i];
3550 for (j = 0; j < assembly->num_dlls; j++)
3552 struct dll_redirect *dll = &assembly->dlls[j];
3553 for (k = 0; k < dll->entities.num; k++)
3555 struct entity *entity = &dll->entities.base[k];
3556 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3558 int class_len = wcslen(entity->u.class.name) + 1;
3559 int len;
3561 /* each class entry needs index, data and string data */
3562 total_len += sizeof(*index);
3563 total_len += sizeof(*data);
3564 /* original name is stored separately */
3565 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3566 /* versioned name and module name are stored one after another */
3567 if (entity->u.class.versioned)
3568 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3569 else
3570 len = class_len;
3571 len += wcslen(dll->name) + 1;
3572 total_len += aligned_string_len(len*sizeof(WCHAR));
3574 class_count++;
3580 total_len += sizeof(*header);
3582 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3583 if (!header) return STATUS_NO_MEMORY;
3585 memset(header, 0, sizeof(*header));
3586 header->magic = STRSECTION_MAGIC;
3587 header->size = sizeof(*header);
3588 header->count = class_count;
3589 header->index_offset = sizeof(*header);
3590 index = (struct string_index*)((BYTE*)header + header->index_offset);
3591 name_offset = header->index_offset + header->count*sizeof(*index);
3593 for (i = 0; i < actctx->num_assemblies; i++)
3595 struct assembly *assembly = &actctx->assemblies[i];
3596 for (j = 0; j < assembly->num_dlls; j++)
3598 struct dll_redirect *dll = &assembly->dlls[j];
3599 for (k = 0; k < dll->entities.num; k++)
3601 struct entity *entity = &dll->entities.base[k];
3602 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3604 ULONG versioned_len, module_len;
3605 UNICODE_STRING str;
3606 WCHAR *ptrW;
3608 /* setup new index entry */
3609 str.Buffer = entity->u.class.name;
3610 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3611 str.MaximumLength = str.Length + sizeof(WCHAR);
3612 /* hash original class name */
3613 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3615 /* include '!' separator too */
3616 if (entity->u.class.versioned)
3617 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3618 else
3619 versioned_len = str.Length;
3620 module_len = wcslen(dll->name)*sizeof(WCHAR);
3622 index->name_offset = name_offset;
3623 index->name_len = str.Length;
3624 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3625 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3626 index->rosterindex = i + 1;
3628 /* setup data */
3629 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3630 data->size = sizeof(*data);
3631 data->res = 0;
3632 data->name_len = versioned_len;
3633 data->name_offset = sizeof(*data);
3634 data->module_len = module_len;
3635 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3637 /* original class name */
3638 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3639 memcpy(ptrW, entity->u.class.name, index->name_len);
3640 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3642 /* module name */
3643 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3644 memcpy(ptrW, dll->name, data->module_len);
3645 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3647 /* versioned name */
3648 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3649 if (entity->u.class.versioned)
3651 get_assembly_version(assembly, ptrW);
3652 wcscat(ptrW, L"!");
3653 wcscat(ptrW, entity->u.class.name);
3655 else
3657 memcpy(ptrW, entity->u.class.name, index->name_len);
3658 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3661 name_offset += sizeof(*data);
3662 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3664 index++;
3670 *section = header;
3672 return STATUS_SUCCESS;
3675 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3676 PACTCTX_SECTION_KEYED_DATA data)
3678 struct string_index *iter, *index = NULL;
3679 struct wndclass_redirect_data *class;
3680 UNICODE_STRING str;
3681 ULONG hash;
3682 int i;
3684 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3686 if (!actctx->wndclass_section)
3688 struct strsection_header *section;
3690 NTSTATUS status = build_wndclass_section(actctx, &section);
3691 if (status) return status;
3693 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3694 RtlFreeHeap(GetProcessHeap(), 0, section);
3697 hash = 0;
3698 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3699 iter = get_wndclass_first_index(actctx);
3701 for (i = 0; i < actctx->wndclass_section->count; i++)
3703 if (iter->hash == hash)
3705 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3706 str.Length = iter->name_len;
3707 if (RtlEqualUnicodeString( &str, name, TRUE ))
3709 index = iter;
3710 break;
3712 else
3713 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_us(&str));
3715 iter++;
3718 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3720 if (data)
3722 class = get_wndclass_data(actctx, index);
3724 data->ulDataFormatVersion = 1;
3725 data->lpData = class;
3726 /* full length includes string length with nulls */
3727 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3728 data->lpSectionGlobalData = NULL;
3729 data->ulSectionGlobalDataLength = 0;
3730 data->lpSectionBase = actctx->wndclass_section;
3731 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3732 data->hActCtx = NULL;
3734 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3735 data->ulAssemblyRosterIndex = index->rosterindex;
3738 return STATUS_SUCCESS;
3741 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3743 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3744 struct guidsection_header *header;
3745 ULONG module_offset, data_offset;
3746 struct tlibredirect_data *data;
3747 struct guid_index *index;
3749 /* compute section length */
3750 for (i = 0; i < actctx->num_assemblies; i++)
3752 struct assembly *assembly = &actctx->assemblies[i];
3753 for (j = 0; j < assembly->num_dlls; j++)
3755 struct dll_redirect *dll = &assembly->dlls[j];
3756 for (k = 0; k < dll->entities.num; k++)
3758 struct entity *entity = &dll->entities.base[k];
3759 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3761 /* each entry needs index, data and string data for module name and help string */
3762 total_len += sizeof(*index);
3763 total_len += sizeof(*data);
3764 /* help string is stored separately */
3765 if (*entity->u.typelib.helpdir)
3766 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3768 /* module names are packed one after another */
3769 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
3771 tlib_count++;
3777 total_len += aligned_string_len(names_len);
3778 total_len += sizeof(*header);
3780 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3781 if (!header) return STATUS_NO_MEMORY;
3783 memset(header, 0, sizeof(*header));
3784 header->magic = GUIDSECTION_MAGIC;
3785 header->size = sizeof(*header);
3786 header->count = tlib_count;
3787 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3788 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3789 module_offset = sizeof(*header);
3790 data_offset = header->index_offset + tlib_count*sizeof(*index);
3792 for (i = 0; i < actctx->num_assemblies; i++)
3794 struct assembly *assembly = &actctx->assemblies[i];
3795 for (j = 0; j < assembly->num_dlls; j++)
3797 struct dll_redirect *dll = &assembly->dlls[j];
3798 for (k = 0; k < dll->entities.num; k++)
3800 struct entity *entity = &dll->entities.base[k];
3801 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3803 ULONG module_len, help_len;
3804 UNICODE_STRING str;
3805 WCHAR *ptrW;
3807 if (*entity->u.typelib.helpdir)
3808 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
3809 else
3810 help_len = 0;
3812 module_len = wcslen(dll->name)*sizeof(WCHAR);
3814 /* setup new index entry */
3815 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3816 RtlGUIDFromString(&str, &index->guid);
3817 index->data_offset = data_offset;
3818 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3819 index->rosterindex = i + 1;
3821 /* setup data */
3822 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3823 data->size = sizeof(*data);
3824 data->res = 0;
3825 data->name_len = module_len;
3826 data->name_offset = module_offset;
3827 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3828 data->langid = 0;
3829 data->flags = entity->u.typelib.flags;
3830 data->help_len = help_len;
3831 data->help_offset = sizeof(*data);
3832 data->major_version = entity->u.typelib.major;
3833 data->minor_version = entity->u.typelib.minor;
3835 /* module name */
3836 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3837 memcpy(ptrW, dll->name, data->name_len);
3838 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3840 /* help string */
3841 if (data->help_len)
3843 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3844 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3845 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3848 data_offset += sizeof(*data);
3849 if (help_len)
3850 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3852 module_offset += module_len + sizeof(WCHAR);
3854 index++;
3860 *section = header;
3862 return STATUS_SUCCESS;
3865 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3867 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3870 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3872 struct guid_index *index = NULL;
3873 struct tlibredirect_data *tlib;
3875 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3877 if (!actctx->tlib_section)
3879 struct guidsection_header *section;
3881 NTSTATUS status = build_tlib_section(actctx, &section);
3882 if (status) return status;
3884 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3885 RtlFreeHeap(GetProcessHeap(), 0, section);
3888 index = find_guid_index(actctx->tlib_section, guid);
3889 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3891 tlib = get_tlib_data(actctx, index);
3893 data->ulDataFormatVersion = 1;
3894 data->lpData = tlib;
3895 /* full length includes string length with nulls */
3896 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3897 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3898 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3899 data->lpSectionBase = actctx->tlib_section;
3900 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3901 data->hActCtx = NULL;
3903 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3904 data->ulAssemblyRosterIndex = index->rosterindex;
3906 return STATUS_SUCCESS;
3909 static void generate_uuid(ULONG *seed, GUID *guid)
3911 ULONG *ptr = (ULONG*)guid;
3912 int i;
3914 /* GUID is 16 bytes long */
3915 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3916 *ptr = RtlUniform(seed);
3918 guid->Data3 &= 0x0fff;
3919 guid->Data3 |= (4 << 12);
3920 guid->Data4[0] &= 0x3f;
3921 guid->Data4[0] |= 0x80;
3924 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3925 unsigned int *count, unsigned int *len, unsigned int *module_len)
3927 unsigned int i;
3929 for (i = 0; i < entities->num; i++)
3931 struct entity *entity = &entities->base[i];
3932 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3934 /* each entry needs two index entries, extra one goes for alias GUID */
3935 *len += 2*sizeof(struct guid_index);
3936 /* To save some memory we don't allocated two data structures,
3937 instead alias index and normal index point to the same data structure. */
3938 *len += sizeof(struct comclassredirect_data);
3940 /* for clrClass store some more */
3941 if (entity->u.comclass.name)
3943 unsigned int str_len;
3945 /* all string data is stored together in aligned block */
3946 str_len = wcslen(entity->u.comclass.name)+1;
3947 if (entity->u.comclass.progid)
3948 str_len += wcslen(entity->u.comclass.progid)+1;
3949 if (entity->u.comclass.version)
3950 str_len += wcslen(entity->u.comclass.version)+1;
3952 *len += sizeof(struct clrclass_data);
3953 *len += aligned_string_len(str_len*sizeof(WCHAR));
3955 /* module name is forced to mscoree.dll, and stored two times with different case */
3956 *module_len += sizeof(L"MSCOREE.DLL") + sizeof(L"mscoree.dll");
3958 else
3960 /* progid string is stored separately */
3961 if (entity->u.comclass.progid)
3962 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3964 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
3967 *count += 1;
3972 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3973 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3974 ULONG *seed, ULONG rosterindex)
3976 unsigned int i;
3978 for (i = 0; i < entities->num; i++)
3980 struct entity *entity = &entities->base[i];
3981 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3983 ULONG module_len, progid_len, str_len = 0, miscmask;
3984 struct comclassredirect_data *data;
3985 struct guid_index *alias_index;
3986 struct clrclass_data *clrdata;
3987 UNICODE_STRING str;
3988 WCHAR *ptrW;
3990 if (entity->u.comclass.progid)
3991 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
3992 else
3993 progid_len = 0;
3995 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
3997 /* setup new index entry */
3998 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3999 RtlGUIDFromString(&str, &(*index)->guid);
4001 (*index)->data_offset = *data_offset;
4002 (*index)->data_len = sizeof(*data); /* additional length added later */
4003 (*index)->rosterindex = rosterindex;
4005 /* Setup new index entry for alias guid. Alias index records are placed after
4006 normal records, so normal guids are hit first on search. Note that class count
4007 is doubled. */
4008 alias_index = (*index) + section->count/2;
4009 generate_uuid(seed, &alias_index->guid);
4010 alias_index->data_offset = (*index)->data_offset;
4011 alias_index->data_len = 0;
4012 alias_index->rosterindex = (*index)->rosterindex;
4014 /* setup data */
4015 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4016 data->size = sizeof(*data);
4017 data->model = entity->u.comclass.model;
4018 data->clsid = (*index)->guid;
4019 data->alias = alias_index->guid;
4020 data->clsid2 = data->clsid;
4021 if (entity->u.comclass.tlbid)
4023 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4024 RtlGUIDFromString(&str, &data->tlbid);
4026 else
4027 memset(&data->tlbid, 0, sizeof(data->tlbid));
4028 data->name_len = module_len;
4029 data->name_offset = *module_offset;
4030 data->progid_len = progid_len;
4031 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4032 data->clrdata_len = 0; /* will be set later */
4033 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4034 data->miscstatus = entity->u.comclass.miscstatus;
4035 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4036 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4037 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4038 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4040 /* mask describes which misc* data is available */
4041 miscmask = 0;
4042 if (data->miscstatus)
4043 miscmask |= MiscStatus;
4044 if (data->miscstatuscontent)
4045 miscmask |= MiscStatusContent;
4046 if (data->miscstatusthumbnail)
4047 miscmask |= MiscStatusThumbnail;
4048 if (data->miscstatusicon)
4049 miscmask |= MiscStatusIcon;
4050 if (data->miscstatusdocprint)
4051 miscmask |= MiscStatusDocPrint;
4052 data->flags = miscmask << 8;
4054 if (data->clrdata_offset)
4056 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4058 clrdata->size = sizeof(*clrdata);
4059 clrdata->res[0] = 0;
4060 clrdata->res[1] = 2; /* FIXME: unknown field */
4061 clrdata->module_len = wcslen(L"MSCOREE.DLL")*sizeof(WCHAR);
4062 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4063 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4064 clrdata->name_offset = clrdata->size;
4065 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4066 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4067 clrdata->res2[0] = 0;
4068 clrdata->res2[1] = 0;
4070 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4072 /* module name */
4073 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4074 memcpy(ptrW, L"mscoree.dll", clrdata->module_len);
4075 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4077 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4078 memcpy(ptrW, L"MSCOREE.DLL", data->name_len);
4079 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4081 /* class name */
4082 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4083 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4084 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4086 /* runtime version, optional */
4087 if (clrdata->version_len)
4089 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4091 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4092 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4093 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4096 if (data->progid_len)
4097 data->progid_offset += data->clrdata_len;
4098 (*index)->data_len += sizeof(*clrdata);
4100 else
4102 clrdata = NULL;
4104 /* module name */
4105 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4106 memcpy(ptrW, dll->name, data->name_len);
4107 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4110 /* progid string */
4111 if (data->progid_len)
4113 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4114 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4115 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4118 /* string block length */
4119 str_len = 0;
4120 if (clrdata)
4122 str_len += clrdata->name_len + sizeof(WCHAR);
4123 if (clrdata->version_len)
4124 str_len += clrdata->version_len + sizeof(WCHAR);
4126 if (progid_len)
4127 str_len += progid_len + sizeof(WCHAR);
4129 (*index)->data_len += aligned_string_len(str_len);
4130 alias_index->data_len = (*index)->data_len;
4132 /* move to next data record */
4133 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4134 (*module_offset) += module_len + sizeof(WCHAR);
4136 if (clrdata)
4138 (*data_offset) += sizeof(*clrdata);
4139 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4141 (*index) += 1;
4146 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4148 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4149 struct guidsection_header *header;
4150 ULONG module_offset, data_offset;
4151 struct guid_index *index;
4152 ULONG seed;
4154 /* compute section length */
4155 for (i = 0; i < actctx->num_assemblies; i++)
4157 struct assembly *assembly = &actctx->assemblies[i];
4158 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4159 for (j = 0; j < assembly->num_dlls; j++)
4161 struct dll_redirect *dll = &assembly->dlls[j];
4162 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4166 total_len += aligned_string_len(names_len);
4167 total_len += sizeof(*header);
4169 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4170 if (!header) return STATUS_NO_MEMORY;
4172 memset(header, 0, sizeof(*header));
4173 header->magic = GUIDSECTION_MAGIC;
4174 header->size = sizeof(*header);
4175 header->count = 2*class_count;
4176 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4177 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4178 module_offset = sizeof(*header);
4179 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4181 seed = NtGetTickCount();
4182 for (i = 0; i < actctx->num_assemblies; i++)
4184 struct assembly *assembly = &actctx->assemblies[i];
4185 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4186 for (j = 0; j < assembly->num_dlls; j++)
4188 struct dll_redirect *dll = &assembly->dlls[j];
4189 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4193 *section = header;
4195 return STATUS_SUCCESS;
4198 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4200 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4203 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4205 struct comclassredirect_data *comclass;
4206 struct guid_index *index = NULL;
4208 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4210 if (!actctx->comserver_section)
4212 struct guidsection_header *section;
4214 NTSTATUS status = build_comserver_section(actctx, &section);
4215 if (status) return status;
4217 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4218 RtlFreeHeap(GetProcessHeap(), 0, section);
4221 index = find_guid_index(actctx->comserver_section, guid);
4222 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4224 comclass = get_comclass_data(actctx, index);
4226 data->ulDataFormatVersion = 1;
4227 data->lpData = comclass;
4228 /* full length includes string length with nulls */
4229 data->ulLength = comclass->size + comclass->clrdata_len;
4230 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4231 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4232 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4233 data->lpSectionBase = actctx->comserver_section;
4234 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4235 data->hActCtx = NULL;
4237 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4238 data->ulAssemblyRosterIndex = index->rosterindex;
4240 return STATUS_SUCCESS;
4243 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4245 unsigned int i;
4247 for (i = 0; i < entities->num; i++)
4249 struct entity *entity = &entities->base[i];
4250 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4252 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4253 if (entity->u.ifaceps.name)
4254 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4255 *count += 1;
4260 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4261 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4263 unsigned int i;
4265 for (i = 0; i < entities->num; i++)
4267 struct entity *entity = &entities->base[i];
4268 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4270 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4271 UNICODE_STRING str;
4272 ULONG name_len;
4274 if (entity->u.ifaceps.name)
4275 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4276 else
4277 name_len = 0;
4279 /* setup index */
4280 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4281 RtlGUIDFromString(&str, &(*index)->guid);
4282 (*index)->data_offset = *data_offset;
4283 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4284 (*index)->rosterindex = rosterindex;
4286 /* setup data record */
4287 data->size = sizeof(*data);
4288 data->mask = entity->u.ifaceps.mask;
4290 /* proxyStubClsid32 value is only stored for external PS,
4291 if set it's used as iid, otherwise 'iid' attribute value is used */
4292 if (entity->u.ifaceps.ps32)
4294 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4295 RtlGUIDFromString(&str, &data->iid);
4297 else
4298 data->iid = (*index)->guid;
4300 data->nummethods = entity->u.ifaceps.nummethods;
4302 if (entity->u.ifaceps.tlib)
4304 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4305 RtlGUIDFromString(&str, &data->tlbid);
4307 else
4308 memset(&data->tlbid, 0, sizeof(data->tlbid));
4310 if (entity->u.ifaceps.base)
4312 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4313 RtlGUIDFromString(&str, &data->base);
4315 else
4316 memset(&data->base, 0, sizeof(data->base));
4318 data->name_len = name_len;
4319 data->name_offset = data->name_len ? sizeof(*data) : 0;
4321 /* name string */
4322 if (data->name_len)
4324 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4325 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4326 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4329 /* move to next record */
4330 (*index) += 1;
4331 *data_offset += sizeof(*data);
4332 if (data->name_len)
4333 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4338 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4340 unsigned int i, j, total_len = 0, count = 0;
4341 struct guidsection_header *header;
4342 struct guid_index *index;
4343 ULONG data_offset;
4345 /* compute section length */
4346 for (i = 0; i < actctx->num_assemblies; i++)
4348 struct assembly *assembly = &actctx->assemblies[i];
4350 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4351 for (j = 0; j < assembly->num_dlls; j++)
4353 struct dll_redirect *dll = &assembly->dlls[j];
4354 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4358 total_len += sizeof(*header);
4360 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4361 if (!header) return STATUS_NO_MEMORY;
4363 memset(header, 0, sizeof(*header));
4364 header->magic = GUIDSECTION_MAGIC;
4365 header->size = sizeof(*header);
4366 header->count = count;
4367 header->index_offset = sizeof(*header);
4368 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4369 data_offset = header->index_offset + count*sizeof(*index);
4371 for (i = 0; i < actctx->num_assemblies; i++)
4373 struct assembly *assembly = &actctx->assemblies[i];
4375 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4376 for (j = 0; j < assembly->num_dlls; j++)
4378 struct dll_redirect *dll = &assembly->dlls[j];
4379 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4383 *section = header;
4385 return STATUS_SUCCESS;
4388 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4390 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4393 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4395 struct ifacepsredirect_data *iface;
4396 struct guid_index *index = NULL;
4398 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4400 if (!actctx->ifaceps_section)
4402 struct guidsection_header *section;
4404 NTSTATUS status = build_ifaceps_section(actctx, &section);
4405 if (status) return status;
4407 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4408 RtlFreeHeap(GetProcessHeap(), 0, section);
4411 index = find_guid_index(actctx->ifaceps_section, guid);
4412 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4414 iface = get_ifaceps_data(actctx, index);
4416 data->ulDataFormatVersion = 1;
4417 data->lpData = iface;
4418 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4419 data->lpSectionGlobalData = NULL;
4420 data->ulSectionGlobalDataLength = 0;
4421 data->lpSectionBase = actctx->ifaceps_section;
4422 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4423 data->hActCtx = NULL;
4425 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4426 data->ulAssemblyRosterIndex = index->rosterindex;
4428 return STATUS_SUCCESS;
4431 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4433 unsigned int i, j, total_len = 0, count = 0;
4434 struct guidsection_header *header;
4435 struct clrsurrogate_data *data;
4436 struct guid_index *index;
4437 ULONG data_offset;
4439 /* compute section length */
4440 for (i = 0; i < actctx->num_assemblies; i++)
4442 struct assembly *assembly = &actctx->assemblies[i];
4443 for (j = 0; j < assembly->entities.num; j++)
4445 struct entity *entity = &assembly->entities.base[j];
4446 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4448 ULONG len;
4450 total_len += sizeof(*index) + sizeof(*data);
4451 len = wcslen(entity->u.clrsurrogate.name) + 1;
4452 if (entity->u.clrsurrogate.version)
4453 len += wcslen(entity->u.clrsurrogate.version) + 1;
4454 total_len += aligned_string_len(len*sizeof(WCHAR));
4456 count++;
4461 total_len += sizeof(*header);
4463 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4464 if (!header) return STATUS_NO_MEMORY;
4466 memset(header, 0, sizeof(*header));
4467 header->magic = GUIDSECTION_MAGIC;
4468 header->size = sizeof(*header);
4469 header->count = count;
4470 header->index_offset = sizeof(*header);
4471 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4472 data_offset = header->index_offset + count*sizeof(*index);
4474 for (i = 0; i < actctx->num_assemblies; i++)
4476 struct assembly *assembly = &actctx->assemblies[i];
4477 for (j = 0; j < assembly->entities.num; j++)
4479 struct entity *entity = &assembly->entities.base[j];
4480 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4482 ULONG version_len, name_len;
4483 UNICODE_STRING str;
4484 WCHAR *ptrW;
4486 if (entity->u.clrsurrogate.version)
4487 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4488 else
4489 version_len = 0;
4490 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4492 /* setup new index entry */
4493 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4494 RtlGUIDFromString(&str, &index->guid);
4496 index->data_offset = data_offset;
4497 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4498 index->rosterindex = i + 1;
4500 /* setup data */
4501 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4502 data->size = sizeof(*data);
4503 data->res = 0;
4504 data->clsid = index->guid;
4505 data->version_offset = version_len ? data->size : 0;
4506 data->version_len = version_len;
4507 data->name_offset = data->size + version_len;
4508 if (version_len)
4509 data->name_offset += sizeof(WCHAR);
4510 data->name_len = name_len;
4512 /* surrogate name */
4513 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4514 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4515 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4517 /* runtime version */
4518 if (data->version_len)
4520 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4521 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4522 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4525 data_offset += index->data_offset;
4526 index++;
4531 *section = header;
4533 return STATUS_SUCCESS;
4536 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4538 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4541 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4543 struct clrsurrogate_data *surrogate;
4544 struct guid_index *index = NULL;
4546 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4548 if (!actctx->clrsurrogate_section)
4550 struct guidsection_header *section;
4552 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4553 if (status) return status;
4555 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4556 RtlFreeHeap(GetProcessHeap(), 0, section);
4559 index = find_guid_index(actctx->clrsurrogate_section, guid);
4560 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4562 surrogate = get_surrogate_data(actctx, index);
4564 data->ulDataFormatVersion = 1;
4565 data->lpData = surrogate;
4566 /* full length includes string length with nulls */
4567 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4568 if (surrogate->version_len)
4569 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4571 data->lpSectionGlobalData = NULL;
4572 data->ulSectionGlobalDataLength = 0;
4573 data->lpSectionBase = actctx->clrsurrogate_section;
4574 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4575 data->hActCtx = NULL;
4577 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4578 data->ulAssemblyRosterIndex = index->rosterindex;
4580 return STATUS_SUCCESS;
4583 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4585 unsigned int i, j, single_len;
4587 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4588 for (i = 0; i < entities->num; i++)
4590 struct entity *entity = &entities->base[i];
4591 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4593 if (entity->u.comclass.progid)
4595 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4596 *count += 1;
4599 for (j = 0; j < entity->u.comclass.progids.num; j++)
4600 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4602 *total_len += single_len*entity->u.comclass.progids.num;
4603 *count += entity->u.comclass.progids.num;
4608 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4609 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4611 struct progidredirect_data *data;
4612 UNICODE_STRING str;
4613 GUID *guid_ptr;
4614 WCHAR *ptrW;
4616 /* setup new index entry */
4618 /* hash progid name */
4619 RtlInitUnicodeString(&str, progid);
4620 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4622 (*index)->name_offset = *data_offset;
4623 (*index)->name_len = str.Length;
4624 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4625 (*index)->data_len = sizeof(*data);
4626 (*index)->rosterindex = rosterindex;
4628 *data_offset += aligned_string_len(str.MaximumLength);
4630 /* setup data structure */
4631 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4632 data->size = sizeof(*data);
4633 data->reserved = 0;
4634 data->clsid_offset = *global_offset;
4636 /* write progid string */
4637 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4638 memcpy(ptrW, progid, (*index)->name_len);
4639 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4641 /* write guid to global area */
4642 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4643 *guid_ptr = *alias;
4645 /* to next entry */
4646 *global_offset += sizeof(GUID);
4647 *data_offset += data->size;
4648 (*index) += 1;
4651 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4652 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4654 unsigned int i, j;
4656 for (i = 0; i < entities->num; i++)
4658 struct entity *entity = &entities->base[i];
4659 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4661 const struct progids *progids = &entity->u.comclass.progids;
4662 struct comclassredirect_data *comclass;
4663 struct guid_index *guid_index;
4664 UNICODE_STRING str;
4665 GUID clsid;
4667 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4668 RtlGUIDFromString(&str, &clsid);
4670 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4671 comclass = get_comclass_data(actctx, guid_index);
4673 if (entity->u.comclass.progid)
4674 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4675 index, data_offset, global_offset, rosterindex);
4677 for (j = 0; j < progids->num; j++)
4678 write_progid_record(section, progids->progids[j], &comclass->alias,
4679 index, data_offset, global_offset, rosterindex);
4684 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4686 unsigned int i, j, total_len = 0, count = 0;
4687 struct strsection_header *header;
4688 ULONG data_offset, global_offset;
4689 struct string_index *index;
4691 /* compute section length */
4692 for (i = 0; i < actctx->num_assemblies; i++)
4694 struct assembly *assembly = &actctx->assemblies[i];
4696 get_progid_datalen(&assembly->entities, &count, &total_len);
4697 for (j = 0; j < assembly->num_dlls; j++)
4699 struct dll_redirect *dll = &assembly->dlls[j];
4700 get_progid_datalen(&dll->entities, &count, &total_len);
4704 total_len += sizeof(*header);
4706 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4707 if (!header) return STATUS_NO_MEMORY;
4709 memset(header, 0, sizeof(*header));
4710 header->magic = STRSECTION_MAGIC;
4711 header->size = sizeof(*header);
4712 header->count = count;
4713 header->global_offset = header->size;
4714 header->global_len = count*sizeof(GUID);
4715 header->index_offset = header->size + header->global_len;
4717 index = (struct string_index*)((BYTE*)header + header->index_offset);
4718 data_offset = header->index_offset + count*sizeof(*index);
4719 global_offset = header->global_offset;
4721 for (i = 0; i < actctx->num_assemblies; i++)
4723 struct assembly *assembly = &actctx->assemblies[i];
4725 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4726 for (j = 0; j < assembly->num_dlls; j++)
4728 struct dll_redirect *dll = &assembly->dlls[j];
4729 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4733 *section = header;
4735 return STATUS_SUCCESS;
4738 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4740 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4743 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4744 PACTCTX_SECTION_KEYED_DATA data)
4746 struct progidredirect_data *progid;
4747 struct string_index *index;
4749 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4751 if (!actctx->comserver_section)
4753 struct guidsection_header *section;
4755 NTSTATUS status = build_comserver_section(actctx, &section);
4756 if (status) return status;
4758 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4759 RtlFreeHeap(GetProcessHeap(), 0, section);
4762 if (!actctx->progid_section)
4764 struct strsection_header *section;
4766 NTSTATUS status = build_progid_section(actctx, &section);
4767 if (status) return status;
4769 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4770 RtlFreeHeap(GetProcessHeap(), 0, section);
4773 index = find_string_index(actctx->progid_section, name);
4774 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4776 if (data)
4778 progid = get_progid_data(actctx, index);
4780 data->ulDataFormatVersion = 1;
4781 data->lpData = progid;
4782 data->ulLength = progid->size;
4783 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4784 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4785 data->lpSectionBase = actctx->progid_section;
4786 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4787 data->hActCtx = NULL;
4789 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4790 data->ulAssemblyRosterIndex = index->rosterindex;
4793 return STATUS_SUCCESS;
4796 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4797 const UNICODE_STRING *section_name,
4798 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4800 NTSTATUS status;
4802 switch (section_kind)
4804 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4805 status = find_dll_redirection(actctx, section_name, data);
4806 break;
4807 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4808 status = find_window_class(actctx, section_name, data);
4809 break;
4810 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4811 status = find_progid_redirection(actctx, section_name, data);
4812 break;
4813 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4814 FIXME("Unsupported yet section_kind %x\n", section_kind);
4815 return STATUS_SXS_SECTION_NOT_FOUND;
4816 default:
4817 WARN("Unknown section_kind %x\n", section_kind);
4818 return STATUS_SXS_SECTION_NOT_FOUND;
4821 if (status != STATUS_SUCCESS) return status;
4823 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4825 actctx_addref(actctx);
4826 data->hActCtx = actctx;
4828 return STATUS_SUCCESS;
4831 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4832 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4834 NTSTATUS status;
4836 switch (section_kind)
4838 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4839 status = find_tlib_redirection(actctx, guid, data);
4840 break;
4841 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4842 status = find_comserver_redirection(actctx, guid, data);
4843 break;
4844 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4845 status = find_cominterface_redirection(actctx, guid, data);
4846 break;
4847 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4848 status = find_clr_surrogate(actctx, guid, data);
4849 break;
4850 default:
4851 WARN("Unknown section_kind %x\n", section_kind);
4852 return STATUS_SXS_SECTION_NOT_FOUND;
4855 if (status != STATUS_SUCCESS) return status;
4857 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4859 actctx_addref(actctx);
4860 data->hActCtx = actctx;
4862 return STATUS_SUCCESS;
4865 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4867 unsigned int i, j;
4869 for (i = 0; i < actctx->num_assemblies; i++)
4871 struct assembly *assembly = &actctx->assemblies[i];
4872 for (j = 0; j < assembly->entities.num; j++)
4874 struct entity *entity = &assembly->entities.base[j];
4875 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4876 !wcscmp( entity->u.settings.name, settings ) &&
4877 !wcscmp( entity->u.settings.ns, ns ))
4878 return entity->u.settings.value;
4881 return NULL;
4884 /* initialize the activation context for the current process */
4885 void actctx_init(void)
4887 ACTCTXW ctx;
4888 HANDLE handle;
4890 ctx.cbSize = sizeof(ctx);
4891 ctx.lpSource = NULL;
4892 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4893 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4894 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4896 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4898 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
4902 /***********************************************************************
4903 * RtlCreateActivationContext (NTDLL.@)
4905 * Create an activation context.
4907 * FIXME: function signature/prototype is wrong
4909 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4911 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4912 const WCHAR *directory = NULL;
4913 ACTIVATION_CONTEXT *actctx;
4914 UNICODE_STRING nameW;
4915 ULONG lang = 0;
4916 NTSTATUS status = STATUS_NO_MEMORY;
4917 HANDLE file = 0;
4918 struct actctx_loader acl;
4920 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4922 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4923 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4924 return STATUS_INVALID_PARAMETER;
4926 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4927 return STATUS_NO_MEMORY;
4929 actctx->magic = ACTCTX_MAGIC;
4930 actctx->ref_count = 1;
4931 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4932 actctx->config.info = NULL;
4933 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4934 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4936 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4938 else
4940 UNICODE_STRING dir;
4941 WCHAR *p;
4942 HMODULE module;
4944 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4945 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4947 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4948 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
4949 actctx->appdir.info = dir.Buffer;
4952 nameW.Buffer = NULL;
4954 /* open file only if it's going to be used */
4955 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4956 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4958 WCHAR *source = NULL;
4959 BOOLEAN ret;
4961 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4962 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4964 DWORD dir_len, source_len;
4966 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
4967 source_len = wcslen(pActCtx->lpSource);
4968 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4970 status = STATUS_NO_MEMORY;
4971 goto error;
4974 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4975 source[dir_len] = '\\';
4976 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4979 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4980 RtlFreeHeap( GetProcessHeap(), 0, source );
4981 if (!ret)
4983 status = STATUS_NO_SUCH_FILE;
4984 goto error;
4986 status = open_nt_file( &file, &nameW );
4987 if (status)
4989 RtlFreeUnicodeString( &nameW );
4990 goto error;
4994 acl.actctx = actctx;
4995 acl.dependencies = NULL;
4996 acl.num_dependencies = 0;
4997 acl.allocated_dependencies = 0;
4999 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5000 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5002 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5004 /* if we have a resource it's a PE file */
5005 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5007 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5008 pActCtx->lpResourceName, lang );
5009 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5010 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5011 pActCtx->hModule, pActCtx->lpResourceName );
5013 else if (pActCtx->lpSource)
5015 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5016 file, pActCtx->lpResourceName, lang );
5017 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5018 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5019 NULL, pActCtx->lpResourceName );
5021 else status = STATUS_INVALID_PARAMETER;
5023 else
5025 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5028 if (file) NtClose( file );
5029 RtlFreeUnicodeString( &nameW );
5031 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5032 free_depend_manifests( &acl );
5034 if (status == STATUS_SUCCESS) *handle = actctx;
5035 else actctx_release( actctx );
5036 return status;
5038 error:
5039 if (file) NtClose( file );
5040 actctx_release( actctx );
5041 return status;
5045 /***********************************************************************
5046 * RtlAddRefActivationContext (NTDLL.@)
5048 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5050 ACTIVATION_CONTEXT *actctx;
5052 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5056 /******************************************************************
5057 * RtlReleaseActivationContext (NTDLL.@)
5059 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5061 ACTIVATION_CONTEXT *actctx;
5063 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5066 /******************************************************************
5067 * RtlZombifyActivationContext (NTDLL.@)
5069 * FIXME: function prototype might be wrong
5071 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5073 FIXME("%p: stub\n", handle);
5074 return STATUS_NOT_IMPLEMENTED;
5077 /******************************************************************
5078 * RtlActivateActivationContext (NTDLL.@)
5080 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5082 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5086 /******************************************************************
5087 * RtlActivateActivationContextEx (NTDLL.@)
5089 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5091 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5093 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5094 return STATUS_NO_MEMORY;
5096 frame->Previous = teb->ActivationContextStack.ActiveFrame;
5097 frame->ActivationContext = handle;
5098 frame->Flags = 0;
5099 teb->ActivationContextStack.ActiveFrame = frame;
5100 RtlAddRefActivationContext( handle );
5102 *cookie = (ULONG_PTR)frame;
5103 TRACE( "%p cookie=%lx\n", handle, *cookie );
5104 return STATUS_SUCCESS;
5108 /***********************************************************************
5109 * RtlDeactivateActivationContext (NTDLL.@)
5111 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5113 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5115 TRACE( "%x cookie=%lx\n", flags, cookie );
5117 /* find the right frame */
5118 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5119 for (frame = top; frame; frame = frame->Previous)
5120 if ((ULONG_PTR)frame == cookie) break;
5122 if (!frame)
5123 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5125 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5126 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5128 /* pop everything up to and including frame */
5129 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5131 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5133 frame = top->Previous;
5134 RtlReleaseActivationContext( top->ActivationContext );
5135 RtlFreeHeap( GetProcessHeap(), 0, top );
5136 top = frame;
5141 /******************************************************************
5142 * RtlFreeThreadActivationContextStack (NTDLL.@)
5144 void WINAPI RtlFreeThreadActivationContextStack(void)
5146 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5148 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5149 while (frame)
5151 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5152 RtlReleaseActivationContext( frame->ActivationContext );
5153 RtlFreeHeap( GetProcessHeap(), 0, frame );
5154 frame = prev;
5156 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5160 /******************************************************************
5161 * RtlGetActiveActivationContext (NTDLL.@)
5163 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5165 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5167 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5168 RtlAddRefActivationContext( *handle );
5170 else
5171 *handle = 0;
5173 return STATUS_SUCCESS;
5177 /******************************************************************
5178 * RtlIsActivationContextActive (NTDLL.@)
5180 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5182 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5184 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5185 if (frame->ActivationContext == handle) return TRUE;
5186 return FALSE;
5190 /***********************************************************************
5191 * RtlQueryInformationActivationContext (NTDLL.@)
5193 * Get information about an activation context.
5194 * FIXME: function signature/prototype may be wrong
5196 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5197 ULONG class, PVOID buffer,
5198 SIZE_T bufsize, SIZE_T *retlen )
5200 ACTIVATION_CONTEXT *actctx;
5201 NTSTATUS status;
5203 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5204 subinst, class, buffer, bufsize, retlen);
5206 if (retlen) *retlen = 0;
5207 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5209 switch (class)
5211 case ActivationContextBasicInformation:
5213 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5215 if (retlen) *retlen = sizeof(*info);
5216 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5218 info->hActCtx = handle;
5219 info->dwFlags = 0; /* FIXME */
5220 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5222 break;
5224 case ActivationContextDetailedInformation:
5226 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5227 struct assembly *assembly = NULL;
5228 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5229 LPWSTR ptr;
5231 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5233 if (actctx->num_assemblies) assembly = actctx->assemblies;
5235 if (assembly && assembly->manifest.info)
5236 manifest_len = wcslen(assembly->manifest.info) + 1;
5237 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5238 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5239 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5241 if (retlen) *retlen = len;
5242 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5244 acdi->dwFlags = 0;
5245 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5246 acdi->ulAssemblyCount = actctx->num_assemblies;
5247 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5248 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5249 acdi->ulRootConfigurationPathType = actctx->config.type;
5250 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5251 acdi->ulAppDirPathType = actctx->appdir.type;
5252 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5253 ptr = (LPWSTR)(acdi + 1);
5254 if (manifest_len)
5256 acdi->lpRootManifestPath = ptr;
5257 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5258 ptr += manifest_len;
5260 else acdi->lpRootManifestPath = NULL;
5261 if (config_len)
5263 acdi->lpRootConfigurationPath = ptr;
5264 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5265 ptr += config_len;
5267 else acdi->lpRootConfigurationPath = NULL;
5268 if (appdir_len)
5270 acdi->lpAppDirPath = ptr;
5271 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5273 else acdi->lpAppDirPath = NULL;
5275 break;
5277 case AssemblyDetailedInformationInActivationContext:
5279 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5280 struct assembly *assembly;
5281 WCHAR *assembly_id;
5282 DWORD index;
5283 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5284 LPWSTR ptr;
5286 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5287 if (!subinst) return STATUS_INVALID_PARAMETER;
5289 index = *(DWORD*)subinst;
5290 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5292 assembly = &actctx->assemblies[index - 1];
5294 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5295 id_len = wcslen(assembly_id) + 1;
5296 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5298 if (assembly->manifest.info &&
5299 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5300 path_len = wcslen(assembly->manifest.info) + 1;
5302 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5304 if (retlen) *retlen = len;
5305 if (!buffer || bufsize < len)
5307 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5308 return STATUS_BUFFER_TOO_SMALL;
5311 afdi->ulFlags = 0; /* FIXME */
5312 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5313 afdi->ulManifestPathType = assembly->manifest.type;
5314 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5315 /* FIXME afdi->liManifestLastWriteTime = 0; */
5316 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5317 afdi->ulPolicyPathLength = 0;
5318 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5319 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5320 afdi->ulManifestVersionMajor = 1;
5321 afdi->ulManifestVersionMinor = 0;
5322 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5323 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5324 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5325 ptr = (LPWSTR)(afdi + 1);
5326 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5327 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5328 ptr += id_len;
5329 if (path_len)
5331 afdi->lpAssemblyManifestPath = ptr;
5332 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5333 ptr += path_len;
5334 } else afdi->lpAssemblyManifestPath = NULL;
5335 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5336 if (ad_len)
5338 afdi->lpAssemblyDirectoryName = ptr;
5339 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5341 else afdi->lpAssemblyDirectoryName = NULL;
5342 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5344 break;
5346 case FileInformationInAssemblyOfAssemblyInActivationContext:
5348 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5349 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5350 struct assembly *assembly;
5351 struct dll_redirect *dll;
5352 SIZE_T len, dll_len = 0;
5353 LPWSTR ptr;
5355 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5356 if (!acqi) return STATUS_INVALID_PARAMETER;
5358 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5359 return STATUS_INVALID_PARAMETER;
5360 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5362 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5363 return STATUS_INVALID_PARAMETER;
5364 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5366 if (dll->name) dll_len = wcslen(dll->name) + 1;
5367 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5369 if (!buffer || bufsize < len)
5371 if (retlen) *retlen = len;
5372 return STATUS_BUFFER_TOO_SMALL;
5374 if (retlen) *retlen = 0; /* yes that's what native does !! */
5375 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5376 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5377 afdi->ulPathLength = 0; /* FIXME */
5378 ptr = (LPWSTR)(afdi + 1);
5379 if (dll_len)
5381 afdi->lpFileName = ptr;
5382 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5383 } else afdi->lpFileName = NULL;
5384 afdi->lpFilePath = NULL; /* FIXME */
5386 break;
5388 case CompatibilityInformationInActivationContext:
5390 struct acci
5392 DWORD ElementCount;
5393 COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
5394 } *acci = buffer;
5395 struct assembly *assembly = NULL;
5396 ULONG num_compat_contexts = 0, n;
5397 SIZE_T len;
5399 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5401 if (actctx->num_assemblies) assembly = actctx->assemblies;
5403 if (assembly)
5404 num_compat_contexts = assembly->num_compat_contexts;
5405 len = offsetof( struct acci, Elements[num_compat_contexts] );
5407 if (retlen) *retlen = len;
5408 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5410 acci->ElementCount = num_compat_contexts;
5411 for (n = 0; n < num_compat_contexts; ++n)
5413 acci->Elements[n] = assembly->compat_contexts[n];
5416 break;
5418 case RunlevelInformationInActivationContext:
5420 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5421 struct assembly *assembly;
5422 SIZE_T len;
5424 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5426 len = sizeof(*acrli);
5427 if (retlen) *retlen = len;
5428 if (!buffer || bufsize < len)
5429 return STATUS_BUFFER_TOO_SMALL;
5431 assembly = actctx->assemblies;
5433 acrli->ulFlags = 0;
5434 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5435 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5437 break;
5439 default:
5440 FIXME( "class %u not implemented\n", class );
5441 return STATUS_NOT_IMPLEMENTED;
5443 return STATUS_SUCCESS;
5446 /***********************************************************************
5447 * RtlFindActivationContextSectionString (NTDLL.@)
5449 * Find information about a string in an activation context.
5450 * FIXME: function signature/prototype may be wrong
5452 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5453 const UNICODE_STRING *section_name, PVOID ptr )
5455 PACTCTX_SECTION_KEYED_DATA data = ptr;
5456 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5458 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5459 debugstr_us(section_name), data);
5461 if (guid)
5463 FIXME("expected guid == NULL\n");
5464 return STATUS_INVALID_PARAMETER;
5466 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5468 FIXME("unknown flags %08x\n", flags);
5469 return STATUS_INVALID_PARAMETER;
5471 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5472 !section_name || !section_name->Buffer)
5474 WARN("invalid parameter\n");
5475 return STATUS_INVALID_PARAMETER;
5478 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5480 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5481 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5484 if (status != STATUS_SUCCESS)
5485 status = find_string( process_actctx, section_kind, section_name, flags, data );
5487 return status;
5490 /***********************************************************************
5491 * RtlFindActivationContextSectionGuid (NTDLL.@)
5493 * Find information about a GUID in an activation context.
5494 * FIXME: function signature/prototype may be wrong
5496 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5497 const GUID *guid, void *ptr )
5499 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5500 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5502 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5504 if (extguid)
5506 FIXME("expected extguid == NULL\n");
5507 return STATUS_INVALID_PARAMETER;
5510 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5512 FIXME("unknown flags %08x\n", flags);
5513 return STATUS_INVALID_PARAMETER;
5516 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5517 return STATUS_INVALID_PARAMETER;
5519 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5521 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5522 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5525 if (status != STATUS_SUCCESS)
5526 status = find_guid( process_actctx, section_kind, guid, flags, data );
5528 return status;
5532 /***********************************************************************
5533 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5535 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5536 const WCHAR *settings, WCHAR *buffer,
5537 SIZE_T size, SIZE_T *written )
5539 ACTIVATION_CONTEXT *actctx;
5540 const WCHAR *res;
5542 if (flags)
5544 WARN( "unknown flags %08x\n", flags );
5545 return STATUS_INVALID_PARAMETER;
5548 if (ns)
5550 if (wcscmp( ns, windowsSettings2005NSW ) &&
5551 wcscmp( ns, windowsSettings2011NSW ) &&
5552 wcscmp( ns, windowsSettings2016NSW ) &&
5553 wcscmp( ns, windowsSettings2017NSW ))
5554 return STATUS_INVALID_PARAMETER;
5556 else ns = windowsSettings2005NSW;
5558 if (!handle) handle = process_actctx;
5559 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5561 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5563 if (written) *written = wcslen(res) + 1;
5564 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5565 wcscpy( buffer, res );
5566 return STATUS_SUCCESS;