dbghelp: Use local declarations of r_debug and link_map structs.
[wine.git] / dlls / ntdll / actctx.c
blob1ca14827a7913deb5b732eb75067a88218b1e7a9
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 "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
34 #include "winternl.h"
35 #include "ddk/wdm.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
42 #define ACTCTX_FLAGS_ALL (\
43 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
44 ACTCTX_FLAG_LANGID_VALID |\
45 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
46 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
47 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
48 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
49 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
50 ACTCTX_FLAG_HMODULE_VALID )
52 #define ACTCTX_MAGIC 0xC07E3E11
53 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
54 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
56 /* we don't want to include winuser.h */
57 #define RT_MANIFEST ((ULONG_PTR)24)
58 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
60 /* from oaidl.h */
61 typedef enum tagLIBFLAGS {
62 LIBFLAG_FRESTRICTED = 0x1,
63 LIBFLAG_FCONTROL = 0x2,
64 LIBFLAG_FHIDDEN = 0x4,
65 LIBFLAG_FHASDISKIMAGE = 0x8
66 } LIBFLAGS;
68 /* from oleidl.idl */
69 typedef enum tagOLEMISC
71 OLEMISC_RECOMPOSEONRESIZE = 0x1,
72 OLEMISC_ONLYICONIC = 0x2,
73 OLEMISC_INSERTNOTREPLACE = 0x4,
74 OLEMISC_STATIC = 0x8,
75 OLEMISC_CANTLINKINSIDE = 0x10,
76 OLEMISC_CANLINKBYOLE1 = 0x20,
77 OLEMISC_ISLINKOBJECT = 0x40,
78 OLEMISC_INSIDEOUT = 0x80,
79 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
80 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
81 OLEMISC_INVISIBLEATRUNTIME = 0x400,
82 OLEMISC_ALWAYSRUN = 0x800,
83 OLEMISC_ACTSLIKEBUTTON = 0x1000,
84 OLEMISC_ACTSLIKELABEL = 0x2000,
85 OLEMISC_NOUIACTIVATE = 0x4000,
86 OLEMISC_ALIGNABLE = 0x8000,
87 OLEMISC_SIMPLEFRAME = 0x10000,
88 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
89 OLEMISC_IMEMODE = 0x40000,
90 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
91 OLEMISC_WANTSTOMENUMERGE = 0x100000,
92 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
93 } OLEMISC;
95 #define MAX_NAMESPACES 64
97 typedef struct
99 const WCHAR *ptr;
100 unsigned int len;
101 } xmlstr_t;
103 struct xml_elem
105 xmlstr_t name;
106 xmlstr_t ns;
107 int ns_pos;
110 struct xml_attr
112 xmlstr_t name;
113 xmlstr_t value;
116 typedef struct
118 const WCHAR *ptr;
119 const WCHAR *end;
120 struct xml_attr namespaces[MAX_NAMESPACES];
121 int ns_pos;
122 BOOL error;
123 } xmlbuf_t;
125 struct file_info
127 ULONG type;
128 WCHAR *info;
131 struct assembly_version
133 USHORT major;
134 USHORT minor;
135 USHORT build;
136 USHORT revision;
139 struct assembly_identity
141 WCHAR *name;
142 WCHAR *arch;
143 WCHAR *public_key;
144 WCHAR *language;
145 WCHAR *type;
146 struct assembly_version version;
147 BOOL optional;
148 BOOL delayed;
151 struct strsection_header
153 DWORD magic;
154 ULONG size;
155 DWORD unk1[3];
156 ULONG count;
157 ULONG index_offset;
158 DWORD unk2[2];
159 ULONG global_offset;
160 ULONG global_len;
163 struct string_index
165 ULONG hash; /* key string hash */
166 ULONG name_offset;
167 ULONG name_len;
168 ULONG data_offset; /* redirect data offset */
169 ULONG data_len;
170 ULONG rosterindex;
173 struct guidsection_header
175 DWORD magic;
176 ULONG size;
177 DWORD unk[3];
178 ULONG count;
179 ULONG index_offset;
180 DWORD unk2;
181 ULONG names_offset;
182 ULONG names_len;
185 struct guid_index
187 GUID guid;
188 ULONG data_offset;
189 ULONG data_len;
190 ULONG rosterindex;
193 struct wndclass_redirect_data
195 ULONG size;
196 DWORD res;
197 ULONG name_len;
198 ULONG name_offset; /* versioned name offset */
199 ULONG module_len;
200 ULONG module_offset;/* container name offset */
203 struct dllredirect_data
205 ULONG size;
206 ULONG unk;
207 DWORD res[3];
210 struct tlibredirect_data
212 ULONG size;
213 DWORD res;
214 ULONG name_len;
215 ULONG name_offset;
216 LANGID langid;
217 WORD flags;
218 ULONG help_len;
219 ULONG help_offset;
220 WORD major_version;
221 WORD minor_version;
224 enum comclass_threadingmodel
226 ThreadingModel_Apartment = 1,
227 ThreadingModel_Free = 2,
228 ThreadingModel_No = 3,
229 ThreadingModel_Both = 4,
230 ThreadingModel_Neutral = 5
233 enum comclass_miscfields
235 MiscStatus = 1,
236 MiscStatusIcon = 2,
237 MiscStatusContent = 4,
238 MiscStatusThumbnail = 8,
239 MiscStatusDocPrint = 16
242 struct comclassredirect_data
244 ULONG size;
245 BYTE res;
246 BYTE miscmask;
247 BYTE res1[2];
248 DWORD model;
249 GUID clsid;
250 GUID alias;
251 GUID clsid2;
252 GUID tlbid;
253 ULONG name_len;
254 ULONG name_offset;
255 ULONG progid_len;
256 ULONG progid_offset;
257 ULONG clrdata_len;
258 ULONG clrdata_offset;
259 DWORD miscstatus;
260 DWORD miscstatuscontent;
261 DWORD miscstatusthumbnail;
262 DWORD miscstatusicon;
263 DWORD miscstatusdocprint;
266 enum ifaceps_mask
268 NumMethods = 1,
269 BaseIface = 2
272 struct ifacepsredirect_data
274 ULONG size;
275 DWORD mask;
276 GUID iid;
277 ULONG nummethods;
278 GUID tlbid;
279 GUID base;
280 ULONG name_len;
281 ULONG name_offset;
284 struct clrsurrogate_data
286 ULONG size;
287 DWORD res;
288 GUID clsid;
289 ULONG version_offset;
290 ULONG version_len;
291 ULONG name_offset;
292 ULONG name_len;
295 struct clrclass_data
297 ULONG size;
298 DWORD res[2];
299 ULONG module_len;
300 ULONG module_offset;
301 ULONG name_len;
302 ULONG name_offset;
303 ULONG version_len;
304 ULONG version_offset;
305 DWORD res2[2];
308 struct progidredirect_data
310 ULONG size;
311 DWORD reserved;
312 ULONG clsid_offset;
317 Sections structure.
319 Sections are accessible by string or guid key, that defines two types of sections.
320 All sections of each type have same magic value and header structure, index
321 data could be of two possible types too. So every string based section uses
322 the same index format, same applies to guid sections - they share same guid index
323 format.
325 - window class redirection section is a plain buffer with following format:
327 <section header>
328 <index[]>
329 <data[]> --- <original name>
330 <redirect data>
331 <versioned name>
332 <module name>
334 Header is fixed length structure - struct strsection_header,
335 contains redirected classes count;
337 Index is an array of fixed length index records, each record is
338 struct string_index.
340 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
342 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
343 others are relative to section itself.
345 - dll redirect section format:
347 <section header>
348 <index[]>
349 <data[]> --- <dll name>
350 <data>
352 This section doesn't seem to carry any payload data except dll names.
354 - typelib section format:
356 <section header>
357 <module names[]>
358 <index[]>
359 <data[]> --- <data>
360 <helpstring>
362 Header is fixed length, index is an array of fixed length 'struct guid_index'.
363 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
364 4-bytes aligned as a whole.
366 Module name offsets are relative to section, helpstring offset is relative to data
367 structure itself.
369 - comclass section format:
371 <section header>
372 <module names[]>
373 <index[]>
374 <data[]> --- <data> --- <data>
375 <progid> <clrdata>
376 <name>
377 <version>
378 <progid>
380 This section uses two index records per comclass, one entry contains original guid
381 as specified by context, another one has a generated guid. Index and strings handling
382 is similar to typelib sections.
384 For CLR classes additional data is stored after main COM class data, it contains
385 class name and runtime version string, see 'struct clrclass_data'.
387 Module name offsets are relative to section, progid offset is relative to data
388 structure itself.
390 - COM interface section format:
392 <section header>
393 <index[]>
394 <data[]> --- <data>
395 <name>
397 Interface section contains data for proxy/stubs and external proxy/stubs. External
398 ones are defined at assembly level, so this section has no module information.
399 All records are indexed with 'iid' value from manifest. There an exception for
400 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
401 redirect data, but index is still 'iid' from manifest.
403 Interface name offset is relative to data structure itself.
405 - CLR surrogates section format:
407 <section header>
408 <index[]>
409 <data[]> --- <data>
410 <name>
411 <version>
413 There's nothing special about this section, same way to store strings is used,
414 no modules part as it belongs to assembly level, not a file.
416 - ProgID section format:
418 <section header>
419 <guids[]>
420 <index[]>
421 <data[]> --- <progid>
422 <data>
424 This sections uses generated alias guids from COM server section. This way
425 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
426 is stored too, aligned.
429 struct progids
431 WCHAR **progids;
432 unsigned int num;
433 unsigned int allocated;
436 struct entity
438 DWORD kind;
439 union
441 struct
443 WCHAR *tlbid;
444 WCHAR *helpdir;
445 WORD flags;
446 WORD major;
447 WORD minor;
448 } typelib;
449 struct
451 WCHAR *clsid;
452 WCHAR *tlbid;
453 WCHAR *progid;
454 WCHAR *name; /* clrClass: class name */
455 WCHAR *version; /* clrClass: CLR runtime version */
456 DWORD model;
457 DWORD miscstatus;
458 DWORD miscstatuscontent;
459 DWORD miscstatusthumbnail;
460 DWORD miscstatusicon;
461 DWORD miscstatusdocprint;
462 struct progids progids;
463 } comclass;
464 struct {
465 WCHAR *iid;
466 WCHAR *base;
467 WCHAR *tlib;
468 WCHAR *name;
469 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
470 DWORD mask;
471 ULONG nummethods;
472 } ifaceps;
473 struct
475 WCHAR *name;
476 BOOL versioned;
477 } class;
478 struct
480 WCHAR *name;
481 WCHAR *clsid;
482 WCHAR *version;
483 } clrsurrogate;
484 struct
486 WCHAR *name;
487 WCHAR *value;
488 WCHAR *ns;
489 } settings;
490 } u;
493 struct entity_array
495 struct entity *base;
496 unsigned int num;
497 unsigned int allocated;
500 struct dll_redirect
502 WCHAR *name;
503 WCHAR *hash;
504 struct entity_array entities;
507 enum assembly_type
509 APPLICATION_MANIFEST,
510 ASSEMBLY_MANIFEST,
511 ASSEMBLY_SHARED_MANIFEST,
514 struct assembly
516 enum assembly_type type;
517 struct assembly_identity id;
518 struct file_info manifest;
519 WCHAR *directory;
520 BOOL no_inherit;
521 struct dll_redirect *dlls;
522 unsigned int num_dlls;
523 unsigned int allocated_dlls;
524 struct entity_array entities;
525 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
526 ULONG num_compat_contexts;
527 ACTCTX_REQUESTED_RUN_LEVEL run_level;
528 ULONG ui_access;
531 enum context_sections
533 WINDOWCLASS_SECTION = 1,
534 DLLREDIRECT_SECTION = 2,
535 TLIBREDIRECT_SECTION = 4,
536 SERVERREDIRECT_SECTION = 8,
537 IFACEREDIRECT_SECTION = 16,
538 CLRSURROGATES_SECTION = 32,
539 PROGIDREDIRECT_SECTION = 64
542 typedef struct _ACTIVATION_CONTEXT
544 ULONG magic;
545 int ref_count;
546 struct file_info config;
547 struct file_info appdir;
548 struct assembly *assemblies;
549 unsigned int num_assemblies;
550 unsigned int allocated_assemblies;
551 /* section data */
552 DWORD sections;
553 struct strsection_header *wndclass_section;
554 struct strsection_header *dllredirect_section;
555 struct strsection_header *progid_section;
556 struct guidsection_header *tlib_section;
557 struct guidsection_header *comserver_section;
558 struct guidsection_header *ifaceps_section;
559 struct guidsection_header *clrsurrogate_section;
560 } ACTIVATION_CONTEXT;
562 struct actctx_loader
564 ACTIVATION_CONTEXT *actctx;
565 struct assembly_identity *dependencies;
566 unsigned int num_dependencies;
567 unsigned int allocated_dependencies;
570 static const xmlstr_t empty_xmlstr;
572 #ifdef __i386__
573 static const WCHAR current_archW[] = {'x','8','6',0};
574 #elif defined __x86_64__
575 static const WCHAR current_archW[] = {'a','m','d','6','4',0};
576 #elif defined __arm__
577 static const WCHAR current_archW[] = {'a','r','m',0};
578 #elif defined __aarch64__
579 static const WCHAR current_archW[] = {'a','r','m','6','4',0};
580 #else
581 static const WCHAR current_archW[] = {'n','o','n','e',0};
582 #endif
584 static const WCHAR asmv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
585 static const WCHAR asmv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
586 static const WCHAR asmv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
587 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
588 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
589 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
590 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
591 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
592 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
593 static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
594 static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
595 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
596 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
597 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
598 static const WCHAR fileW[] = {'f','i','l','e',0};
599 static const WCHAR hashW[] = {'h','a','s','h',0};
600 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
601 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
602 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
603 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
605 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
606 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
607 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
608 static const WCHAR iidW[] = {'i','i','d',0};
609 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
610 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
611 static const WCHAR nameW[] = {'n','a','m','e',0};
612 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
613 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
614 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
615 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
616 static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
617 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
618 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
619 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
620 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
621 static const WCHAR typeW[] = {'t','y','p','e',0};
622 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
623 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
624 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
625 static const WCHAR yesW[] = {'y','e','s',0};
626 static const WCHAR noW[] = {'n','o',0};
627 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
628 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
629 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
630 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
631 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
632 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
633 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
634 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
635 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
636 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
637 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
638 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
639 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
640 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
641 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
642 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
644 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
645 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
646 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
647 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
648 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
649 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
650 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
651 static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
652 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
653 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
654 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
655 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
656 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
657 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
658 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
659 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
660 static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
661 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
662 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
663 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
664 static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
665 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
667 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
668 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
669 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
670 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
671 static const WCHAR IdW[] = {'I','d',0};
672 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
673 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
674 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
675 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
676 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
677 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
678 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
679 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0};
680 static const WCHAR windowsSettings2005NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
681 static const WCHAR windowsSettings2011NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
682 static const WCHAR windowsSettings2016NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
683 static const WCHAR windowsSettings2017NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
684 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
685 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
686 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
687 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
688 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
689 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
690 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0};
691 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
693 struct olemisc_entry
695 const WCHAR *name;
696 OLEMISC value;
699 static const struct olemisc_entry olemisc_values[] =
701 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
702 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
703 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
704 { alignableW, OLEMISC_ALIGNABLE },
705 { alwaysrunW, OLEMISC_ALWAYSRUN },
706 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
707 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
708 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
709 { imemodeW, OLEMISC_IMEMODE },
710 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
711 { insideoutW, OLEMISC_INSIDEOUT },
712 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
713 { islinkobjectW, OLEMISC_ISLINKOBJECT },
714 { nouiactivateW, OLEMISC_NOUIACTIVATE },
715 { onlyiconicW, OLEMISC_ONLYICONIC },
716 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
717 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
718 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
719 { simpleframeW, OLEMISC_SIMPLEFRAME },
720 { staticW, OLEMISC_STATIC },
721 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
722 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
725 static const WCHAR xmlW[] = {'?','x','m','l',0};
726 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
727 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
728 static const WCHAR wildcardW[] = {'*',0};
730 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
731 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
733 static WCHAR *strdupW(const WCHAR* str)
735 WCHAR* ptr;
737 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR))))
738 return NULL;
739 return wcscpy(ptr, str);
742 static WCHAR *xmlstrdupW(const xmlstr_t* str)
744 WCHAR *strW;
746 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
748 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
749 strW[str->len] = 0;
751 return strW;
754 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
756 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
759 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
761 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
764 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
766 return xmlstr_cmp( &attr->name, str );
769 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
771 return (elem1->name.len == elem2->name.len &&
772 elem1->ns.len == elem2->ns.len &&
773 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
774 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
777 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
779 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
780 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
781 if (!wcscmp( namespace, asmv1W ))
783 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
784 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
786 else if (!wcscmp( namespace, asmv2W ))
788 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
790 return FALSE;
793 static inline BOOL isxmlspace( WCHAR ch )
795 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
798 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
800 return debugstr_wn(str->ptr, str->len);
803 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
805 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
806 debugstr_wn( elem->ns.ptr, elem->ns.len ));
809 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
811 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
812 debugstr_wn( attr->value.ptr, attr->value.len ));
815 static inline const char* debugstr_version(const struct assembly_version *ver)
817 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
820 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
822 NTSTATUS status;
823 ULONG_PTR magic;
824 LDR_MODULE *pldr;
826 LdrLockLoaderLock(0, NULL, &magic);
827 status = LdrFindEntryForAddress( module, &pldr );
828 if (status == STATUS_SUCCESS)
830 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
831 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
833 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
834 str->Length = pldr->FullDllName.Length;
835 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
837 else status = STATUS_NO_MEMORY;
839 LdrUnlockLoaderLock(0, magic);
840 return status;
843 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
845 struct assembly *assembly;
847 if (actctx->num_assemblies == actctx->allocated_assemblies)
849 void *ptr;
850 unsigned int new_count;
851 if (actctx->assemblies)
853 new_count = actctx->allocated_assemblies * 2;
854 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
855 actctx->assemblies, new_count * sizeof(*assembly) );
857 else
859 new_count = 4;
860 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
862 if (!ptr) return NULL;
863 actctx->assemblies = ptr;
864 actctx->allocated_assemblies = new_count;
867 assembly = &actctx->assemblies[actctx->num_assemblies++];
868 assembly->type = at;
869 return assembly;
872 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
874 if (assembly->num_dlls == assembly->allocated_dlls)
876 void *ptr;
877 unsigned int new_count;
878 if (assembly->dlls)
880 new_count = assembly->allocated_dlls * 2;
881 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
882 assembly->dlls, new_count * sizeof(*assembly->dlls) );
884 else
886 new_count = 4;
887 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
889 if (!ptr) return NULL;
890 assembly->dlls = ptr;
891 assembly->allocated_dlls = new_count;
893 return &assembly->dlls[assembly->num_dlls++];
896 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
898 void *ptr;
899 if (assembly->num_compat_contexts)
901 unsigned int new_count = assembly->num_compat_contexts + 1;
902 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
903 assembly->compat_contexts,
904 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
906 else
908 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
910 if (!ptr) return NULL;
911 assembly->compat_contexts = ptr;
912 return &assembly->compat_contexts[assembly->num_compat_contexts++];
915 static void free_assembly_identity(struct assembly_identity *ai)
917 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
918 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
919 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
920 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
921 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
924 static struct entity* add_entity(struct entity_array *array, DWORD kind)
926 struct entity* entity;
928 if (array->num == array->allocated)
930 void *ptr;
931 unsigned int new_count;
932 if (array->base)
934 new_count = array->allocated * 2;
935 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
936 array->base, new_count * sizeof(*array->base) );
938 else
940 new_count = 4;
941 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
943 if (!ptr) return NULL;
944 array->base = ptr;
945 array->allocated = new_count;
947 entity = &array->base[array->num++];
948 entity->kind = kind;
949 return entity;
952 static void free_entity_array(struct entity_array *array)
954 unsigned int i, j;
955 for (i = 0; i < array->num; i++)
957 struct entity *entity = &array->base[i];
958 switch (entity->kind)
960 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
961 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
962 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
963 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
964 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
965 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
966 for (j = 0; j < entity->u.comclass.progids.num; j++)
967 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
968 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
969 break;
970 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
971 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
972 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
973 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
974 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
975 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
976 break;
977 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
978 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
979 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
980 break;
981 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
982 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
983 break;
984 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
985 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
986 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
987 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
988 break;
989 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
990 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
991 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
992 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
993 break;
994 default:
995 FIXME("Unknown entity kind %d\n", entity->kind);
998 RtlFreeHeap( GetProcessHeap(), 0, array->base );
1001 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
1003 if (!str1) return !str2;
1004 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE );
1007 static BOOL is_matching_identity( const struct assembly_identity *id1,
1008 const struct assembly_identity *id2 )
1010 if (!is_matching_string( id1->name, id2->name )) return FALSE;
1011 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1012 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1014 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language ))
1016 if (wcscmp( wildcardW, id1->language ) && wcscmp( wildcardW, id2->language ))
1017 return FALSE;
1019 if (id1->version.major != id2->version.major) return FALSE;
1020 if (id1->version.minor != id2->version.minor) return FALSE;
1021 if (id1->version.build > id2->version.build) return FALSE;
1022 if (id1->version.build == id2->version.build &&
1023 id1->version.revision > id2->version.revision) return FALSE;
1024 return TRUE;
1027 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
1028 struct assembly_identity* ai)
1030 unsigned int i;
1032 /* check if we already have that assembly */
1034 for (i = 0; i < acl->actctx->num_assemblies; i++)
1035 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1037 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1038 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1039 ai->version.build, ai->version.revision );
1040 return TRUE;
1043 for (i = 0; i < acl->num_dependencies; i++)
1044 if (is_matching_identity( ai, &acl->dependencies[i] ))
1046 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1047 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1048 ai->version.build, ai->version.revision );
1049 return TRUE;
1052 if (acl->num_dependencies == acl->allocated_dependencies)
1054 void *ptr;
1055 unsigned int new_count;
1056 if (acl->dependencies)
1058 new_count = acl->allocated_dependencies * 2;
1059 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
1060 new_count * sizeof(acl->dependencies[0]));
1062 else
1064 new_count = 4;
1065 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1067 if (!ptr) return FALSE;
1068 acl->dependencies = ptr;
1069 acl->allocated_dependencies = new_count;
1071 acl->dependencies[acl->num_dependencies++] = *ai;
1073 return TRUE;
1076 static void free_depend_manifests(struct actctx_loader* acl)
1078 unsigned int i;
1079 for (i = 0; i < acl->num_dependencies; i++)
1080 free_assembly_identity(&acl->dependencies[i]);
1081 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1084 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1086 static const WCHAR undW[] = {'_',0};
1087 static const WCHAR noneW[] = {'n','o','n','e',0};
1088 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1090 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1091 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1092 const WCHAR *lang = ai->language ? ai->language : noneW;
1093 const WCHAR *name = ai->name ? ai->name : noneW;
1094 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 +
1095 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1096 WCHAR *ret;
1098 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1100 wcscpy( ret, arch );
1101 wcscat( ret, undW );
1102 wcscat( ret, name );
1103 wcscat( ret, undW );
1104 wcscat( ret, key );
1105 wcscat( ret, undW );
1106 NTDLL_swprintf( ret + wcslen(ret), version_formatW,
1107 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1108 wcscat( ret, undW );
1109 wcscat( ret, lang );
1110 wcscat( ret, undW );
1111 wcscat( ret, mskeyW );
1112 return ret;
1115 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1117 WCHAR *p = buffer;
1119 if (!str) return;
1120 wcscat( buffer, prefix );
1121 p += wcslen(p);
1122 *p++ = '"';
1123 wcscpy( p, str );
1124 p += wcslen(p);
1125 *p++ = '"';
1126 *p = 0;
1129 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1131 static const WCHAR archW[] =
1132 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1133 static const WCHAR public_keyW[] =
1134 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1135 static const WCHAR typeW[] =
1136 {',','t','y','p','e','=',0};
1137 static const WCHAR versionW[] =
1138 {',','v','e','r','s','i','o','n','=',0};
1140 WCHAR version[64], *ret;
1141 SIZE_T size = 0;
1143 NTDLL_swprintf( version, version_formatW,
1144 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1145 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR);
1146 if (ai->arch) size += wcslen(archW) + wcslen(ai->arch) + 2;
1147 if (ai->public_key) size += wcslen(public_keyW) + wcslen(ai->public_key) + 2;
1148 if (ai->type) size += wcslen(typeW) + wcslen(ai->type) + 2;
1149 size += wcslen(versionW) + wcslen(version) + 2;
1151 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1152 return NULL;
1154 if (ai->name) wcscpy( ret, ai->name );
1155 else *ret = 0;
1156 append_string( ret, archW, ai->arch );
1157 append_string( ret, public_keyW, ai->public_key );
1158 append_string( ret, typeW, ai->type );
1159 append_string( ret, versionW, version );
1160 return ret;
1163 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1165 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1167 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1168 __TRY
1170 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1172 __EXCEPT_PAGE_FAULT
1175 __ENDTRY
1176 return ret;
1179 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1181 interlocked_xchg_add( &actctx->ref_count, 1 );
1184 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1186 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1188 unsigned int i, j;
1190 for (i = 0; i < actctx->num_assemblies; i++)
1192 struct assembly *assembly = &actctx->assemblies[i];
1193 for (j = 0; j < assembly->num_dlls; j++)
1195 struct dll_redirect *dll = &assembly->dlls[j];
1196 free_entity_array( &dll->entities );
1197 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1198 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1200 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1201 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1202 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1203 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1204 free_entity_array( &assembly->entities );
1205 free_assembly_identity(&assembly->id);
1207 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1208 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1209 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1210 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1211 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1212 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1213 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1214 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1215 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1216 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1217 actctx->magic = 0;
1218 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1222 static BOOL set_error( xmlbuf_t *xmlbuf )
1224 xmlbuf->error = TRUE;
1225 return FALSE;
1228 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1230 const int len = wcslen( xmlnsW );
1231 if (attr->name.len < len) return FALSE;
1232 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1233 return (attr->name.len == len || attr->name.ptr[len] == ':');
1236 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1238 const int len = wcslen( xmlnsW );
1239 struct xml_attr *ns;
1241 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1243 FIXME( "too many namespaces in manifest\n" );
1244 set_error( xmlbuf );
1245 return;
1247 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1248 ns->value = attr->value;
1249 if (attr->name.len > len)
1251 ns->name.ptr = attr->name.ptr + len + 1;
1252 ns->name.len = attr->name.len - len - 1;
1254 else ns->name = empty_xmlstr;
1257 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1259 int i;
1261 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1263 if (xmlbuf->namespaces[i].name.len == name->len &&
1264 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1265 return xmlbuf->namespaces[i].value;
1267 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1268 return empty_xmlstr;
1271 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1273 const WCHAR* ptr;
1274 WCHAR quote;
1276 if (xmlbuf->error) return FALSE;
1278 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1279 xmlbuf->ptr++;
1281 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1283 if (*xmlbuf->ptr == '/')
1285 xmlbuf->ptr++;
1286 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1287 return set_error( xmlbuf );
1289 xmlbuf->ptr++;
1290 *end = TRUE;
1291 return FALSE;
1294 if (*xmlbuf->ptr == '>')
1296 xmlbuf->ptr++;
1297 return FALSE;
1300 ptr = xmlbuf->ptr;
1301 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1303 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1305 attr->name.ptr = xmlbuf->ptr;
1306 attr->name.len = ptr-xmlbuf->ptr;
1307 xmlbuf->ptr = ptr;
1309 /* skip spaces before '=' */
1310 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1311 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1313 /* skip '=' itself */
1314 ptr++;
1315 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1317 /* skip spaces after '=' */
1318 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1320 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1322 quote = *ptr++;
1323 attr->value.ptr = ptr;
1324 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1326 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1327 if (ptr == xmlbuf->end)
1329 xmlbuf->ptr = xmlbuf->end;
1330 return set_error( xmlbuf );
1333 attr->value.len = ptr - attr->value.ptr;
1334 xmlbuf->ptr = ptr + 1;
1335 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1337 return set_error( xmlbuf );
1340 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1342 const WCHAR* ptr = xmlbuf->ptr;
1344 elem->ns = empty_xmlstr;
1345 elem->name.ptr = ptr;
1346 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1348 if (*ptr == ':')
1350 elem->ns.ptr = elem->name.ptr;
1351 elem->ns.len = ptr - elem->ns.ptr;
1352 elem->name.ptr = ptr + 1;
1354 ptr++;
1356 elem->name.len = ptr - elem->name.ptr;
1357 xmlbuf->ptr = ptr;
1360 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1362 const WCHAR* ptr;
1363 struct xml_attr attr;
1364 xmlbuf_t attr_buf;
1365 BOOL end = FALSE;
1367 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1369 if (xmlbuf->error) return FALSE;
1371 for (;;)
1373 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1374 if (ptr == xmlbuf->end)
1376 xmlbuf->ptr = xmlbuf->end;
1377 return set_error( xmlbuf );
1379 ptr++;
1380 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1382 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1383 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1385 if (ptr + 3 > xmlbuf->end)
1387 xmlbuf->ptr = xmlbuf->end;
1388 return set_error( xmlbuf );
1390 xmlbuf->ptr = ptr + 3;
1392 else break;
1395 xmlbuf->ptr = ptr;
1396 /* check for element terminating the parent element */
1397 if (ptr < xmlbuf->end && *ptr == '/')
1399 xmlbuf->ptr++;
1400 read_xml_elem( xmlbuf, elem );
1401 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1402 if (!xml_name_cmp( elem, parent ))
1404 ERR( "wrong closing element %s for %s\n",
1405 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1406 return set_error( xmlbuf );
1408 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1409 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1410 return FALSE;
1413 read_xml_elem( xmlbuf, elem );
1415 /* parse namespace attributes */
1416 attr_buf = *xmlbuf;
1417 while (next_xml_attr( &attr_buf, &attr, &end ))
1419 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1421 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1422 elem->ns_pos = xmlbuf->ns_pos;
1424 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1426 return set_error( xmlbuf );
1429 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1431 /* FIXME: parse attributes */
1432 const WCHAR *ptr;
1434 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1436 if (ptr[0] == '?' && ptr[1] == '>')
1438 xmlbuf->ptr = ptr + 2;
1439 return TRUE;
1442 return FALSE;
1445 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1447 const WCHAR *ptr;
1449 if (xmlbuf->error) return FALSE;
1451 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1452 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1454 content->ptr = xmlbuf->ptr;
1455 content->len = ptr - xmlbuf->ptr;
1456 xmlbuf->ptr = ptr;
1458 return TRUE;
1461 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1463 unsigned int ver[4];
1464 unsigned int pos;
1465 const WCHAR *curr;
1467 /* major.minor.build.revision */
1468 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1469 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1471 if (*curr >= '0' && *curr <= '9')
1473 ver[pos] = ver[pos] * 10 + *curr - '0';
1474 if (ver[pos] >= 0x10000) goto error;
1476 else if (*curr == '.')
1478 if (++pos >= 4) goto error;
1480 else goto error;
1482 version->major = ver[0];
1483 version->minor = ver[1];
1484 version->build = ver[2];
1485 version->revision = ver[3];
1486 return TRUE;
1488 error:
1489 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1490 return FALSE;
1493 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1495 struct xml_attr attr;
1497 while (next_xml_attr(xmlbuf, &attr, end))
1499 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1503 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1505 struct xml_elem elem;
1507 if (next_xml_elem(xmlbuf, &elem, parent))
1509 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1510 set_error( xmlbuf );
1514 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1516 struct xml_elem elem;
1517 struct xml_attr attr;
1518 BOOL end = FALSE;
1520 while (next_xml_attr(xmlbuf, &attr, &end));
1521 if (end) return;
1523 while (next_xml_elem(xmlbuf, &elem, parent))
1524 parse_unknown_elem(xmlbuf, &elem);
1527 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1528 struct assembly_identity* ai, const struct xml_elem *parent)
1530 struct xml_attr attr;
1531 BOOL end = FALSE;
1533 while (next_xml_attr(xmlbuf, &attr, &end))
1535 if (xml_attr_cmp(&attr, nameW))
1537 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1539 else if (xml_attr_cmp(&attr, typeW))
1541 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1543 else if (xml_attr_cmp(&attr, versionW))
1545 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1547 else if (xml_attr_cmp(&attr, processorArchitectureW))
1549 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1551 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1553 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1555 else if (xml_attr_cmp(&attr, languageW))
1557 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1559 else if (!is_xmlns_attr( &attr ))
1561 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1565 TRACE( "name=%s version=%s arch=%s\n",
1566 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1568 if (!end) parse_expect_end_elem(xmlbuf, parent);
1571 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1573 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1574 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1575 static const WCHAR freeW[] = {'F','r','e','e',0};
1576 static const WCHAR bothW[] = {'B','o','t','h',0};
1578 if (value->len == 0) return ThreadingModel_No;
1579 if (xmlstr_cmp(value, apartW))
1580 return ThreadingModel_Apartment;
1581 else if (xmlstr_cmp(value, freeW))
1582 return ThreadingModel_Free;
1583 else if (xmlstr_cmp(value, bothW))
1584 return ThreadingModel_Both;
1585 else if (xmlstr_cmp(value, neutralW))
1586 return ThreadingModel_Neutral;
1587 else
1588 return ThreadingModel_No;
1591 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1593 int min, max;
1595 min = 0;
1596 max = ARRAY_SIZE(olemisc_values) - 1;
1598 while (min <= max)
1600 int n, c;
1602 n = (min+max)/2;
1604 c = wcsncmp(olemisc_values[n].name, str, len);
1605 if (!c && !olemisc_values[n].name[len])
1606 return olemisc_values[n].value;
1608 if (c >= 0)
1609 max = n-1;
1610 else
1611 min = n+1;
1614 WARN("unknown flag %s\n", debugstr_wn(str, len));
1615 return 0;
1618 static DWORD parse_com_class_misc(const xmlstr_t *value)
1620 const WCHAR *str = value->ptr, *start;
1621 DWORD flags = 0;
1622 int i = 0;
1624 /* it's comma separated list of flags */
1625 while (i < value->len)
1627 start = str;
1628 while (*str != ',' && (i++ < value->len)) str++;
1630 flags |= get_olemisc_value(start, str-start);
1632 /* skip separator */
1633 str++;
1634 i++;
1637 return flags;
1640 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1642 struct progids *progids = &entity->u.comclass.progids;
1644 if (progids->allocated == 0)
1646 progids->allocated = 4;
1647 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1650 if (progids->allocated == progids->num)
1652 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1653 2 * progids->allocated * sizeof(WCHAR*));
1654 if (!new_progids) return FALSE;
1655 progids->allocated *= 2;
1656 progids->progids = new_progids;
1659 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1660 progids->num++;
1662 return TRUE;
1665 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1667 xmlstr_t content;
1668 BOOL end = FALSE;
1670 parse_expect_no_attr(xmlbuf, &end);
1671 if (end) set_error( xmlbuf );
1672 if (!parse_text_content(xmlbuf, &content)) return;
1674 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1675 parse_expect_end_elem(xmlbuf, parent);
1678 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1679 const struct xml_elem *parent )
1681 struct xml_elem elem;
1682 struct xml_attr attr;
1683 BOOL end = FALSE;
1684 struct entity* entity;
1686 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1688 set_error( xmlbuf );
1689 return;
1692 while (next_xml_attr(xmlbuf, &attr, &end))
1694 if (xml_attr_cmp(&attr, clsidW))
1696 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1698 else if (xml_attr_cmp(&attr, progidW))
1700 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1702 else if (xml_attr_cmp(&attr, tlbidW))
1704 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1706 else if (xml_attr_cmp(&attr, threadingmodelW))
1708 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1710 else if (xml_attr_cmp(&attr, miscstatusW))
1712 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1714 else if (xml_attr_cmp(&attr, miscstatuscontentW))
1716 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1718 else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1720 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1722 else if (xml_attr_cmp(&attr, miscstatusiconW))
1724 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1726 else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1728 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1730 else if (xml_attr_cmp(&attr, descriptionW))
1732 /* not stored */
1734 else if (!is_xmlns_attr( &attr ))
1736 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1740 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1741 if (entity->u.comclass.progid)
1742 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1744 if (end) return;
1746 while (next_xml_elem(xmlbuf, &elem, parent))
1748 if (xml_elem_cmp(&elem, progidW, asmv1W))
1750 parse_com_class_progid(xmlbuf, entity, &elem);
1752 else
1754 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1755 parse_unknown_elem(xmlbuf, &elem);
1759 if (entity->u.comclass.progids.num)
1760 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1763 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1765 const WCHAR *curr;
1766 ULONG num = 0;
1768 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1770 if (*curr >= '0' && *curr <= '9')
1771 num = num * 10 + *curr - '0';
1772 else
1774 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1775 return FALSE;
1778 entity->u.ifaceps.nummethods = num;
1780 return TRUE;
1783 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1784 struct actctx_loader *acl, const struct xml_elem *parent )
1786 struct xml_attr attr;
1787 BOOL end = FALSE;
1788 struct entity* entity;
1790 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1792 set_error( xmlbuf );
1793 return;
1796 while (next_xml_attr(xmlbuf, &attr, &end))
1798 if (xml_attr_cmp(&attr, iidW))
1800 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1802 else if (xml_attr_cmp(&attr, nameW))
1804 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1806 else if (xml_attr_cmp(&attr, baseInterfaceW))
1808 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1809 entity->u.ifaceps.mask |= BaseIface;
1811 else if (xml_attr_cmp(&attr, nummethodsW))
1813 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1814 entity->u.ifaceps.mask |= NumMethods;
1816 else if (xml_attr_cmp(&attr, tlbidW))
1818 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1820 /* not used */
1821 else if (xml_attr_cmp(&attr, proxyStubClsid32W) || xml_attr_cmp(&attr, threadingmodelW))
1824 else if (!is_xmlns_attr( &attr ))
1826 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1830 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1831 if (!end) parse_expect_end_elem(xmlbuf, parent);
1834 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1836 WORD *flags = &entity->u.typelib.flags;
1837 const WCHAR *str = value->ptr, *start;
1838 int i = 0;
1840 *flags = 0;
1842 /* it's comma separated list of flags */
1843 while (i < value->len)
1845 start = str;
1846 while (*str != ',' && (i++ < value->len)) str++;
1848 if (!wcsnicmp(start, restrictedW, str-start))
1849 *flags |= LIBFLAG_FRESTRICTED;
1850 else if (!wcsnicmp(start, controlW, str-start))
1851 *flags |= LIBFLAG_FCONTROL;
1852 else if (!wcsnicmp(start, hiddenW, str-start))
1853 *flags |= LIBFLAG_FHIDDEN;
1854 else if (!wcsnicmp(start, hasdiskimageW, str-start))
1855 *flags |= LIBFLAG_FHASDISKIMAGE;
1856 else
1858 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1859 return FALSE;
1862 /* skip separator */
1863 str++;
1864 i++;
1867 return TRUE;
1870 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1872 unsigned int ver[2];
1873 unsigned int pos;
1874 const WCHAR *curr;
1876 /* major.minor */
1877 ver[0] = ver[1] = pos = 0;
1878 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1880 if (*curr >= '0' && *curr <= '9')
1882 ver[pos] = ver[pos] * 10 + *curr - '0';
1883 if (ver[pos] >= 0x10000) goto error;
1885 else if (*curr == '.')
1887 if (++pos >= 2) goto error;
1889 else goto error;
1891 entity->u.typelib.major = ver[0];
1892 entity->u.typelib.minor = ver[1];
1893 return TRUE;
1895 error:
1896 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1897 return FALSE;
1900 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1901 struct actctx_loader *acl, const struct xml_elem *parent )
1903 struct xml_attr attr;
1904 BOOL end = FALSE;
1905 struct entity* entity;
1907 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1909 set_error( xmlbuf );
1910 return;
1913 while (next_xml_attr(xmlbuf, &attr, &end))
1915 if (xml_attr_cmp(&attr, tlbidW))
1917 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1919 else if (xml_attr_cmp(&attr, versionW))
1921 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1923 else if (xml_attr_cmp(&attr, helpdirW))
1925 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1927 else if (xml_attr_cmp(&attr, flagsW))
1929 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1931 else if (!is_xmlns_attr( &attr ))
1933 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1937 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1938 if (!end) parse_expect_end_elem(xmlbuf, parent);
1941 static inline int aligned_string_len(int len)
1943 return (len + 3) & ~3;
1946 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1948 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1949 struct assembly_version *ver = &assembly->id.version;
1950 WCHAR buff[25];
1952 if (!ret) ret = buff;
1953 return NTDLL_swprintf(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1956 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1957 struct actctx_loader *acl, const struct xml_elem *parent )
1959 struct xml_elem elem;
1960 struct xml_attr attr;
1961 xmlstr_t content;
1962 BOOL end = FALSE;
1963 struct entity* entity;
1965 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1967 set_error( xmlbuf );
1968 return;
1970 entity->u.class.versioned = TRUE;
1971 while (next_xml_attr(xmlbuf, &attr, &end))
1973 if (xml_attr_cmp(&attr, versionedW))
1975 if (xmlstr_cmpi(&attr.value, noW))
1976 entity->u.class.versioned = FALSE;
1977 else if (!xmlstr_cmpi(&attr.value, yesW))
1978 set_error( xmlbuf );
1980 else if (!is_xmlns_attr( &attr ))
1982 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1986 if (end) return;
1988 if (!parse_text_content(xmlbuf, &content)) return;
1989 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1991 acl->actctx->sections |= WINDOWCLASS_SECTION;
1993 while (next_xml_elem(xmlbuf, &elem, parent))
1995 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1996 parse_unknown_elem(xmlbuf, &elem);
2000 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2002 struct xml_attr attr;
2003 BOOL end = FALSE;
2005 while (next_xml_attr(xmlbuf, &attr, &end))
2007 if (xml_attr_cmp(&attr, oldVersionW))
2009 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2011 else if (xml_attr_cmp(&attr, newVersionW))
2013 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2015 else if (!is_xmlns_attr( &attr ))
2017 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2021 if (!end) parse_expect_end_elem(xmlbuf, parent);
2024 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2026 struct xml_elem elem;
2027 struct xml_attr attr;
2028 xmlstr_t content;
2029 BOOL end = FALSE;
2031 while (next_xml_attr(xmlbuf, &attr, &end))
2033 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2036 if (end) return;
2037 if (!parse_text_content(xmlbuf, &content)) return;
2039 TRACE("Got description %s\n", debugstr_xmlstr(&content));
2041 while (next_xml_elem(xmlbuf, &elem, parent))
2043 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2044 parse_unknown_elem(xmlbuf, &elem);
2048 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2049 struct assembly* assembly,
2050 struct actctx_loader* acl,
2051 const struct xml_elem *parent)
2053 struct xml_attr attr;
2054 BOOL end = FALSE;
2055 struct entity* entity;
2057 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2059 set_error( xmlbuf );
2060 return;
2063 while (next_xml_attr(xmlbuf, &attr, &end))
2065 if (xml_attr_cmp(&attr, iidW))
2067 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2069 else if (xml_attr_cmp(&attr, nameW))
2071 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2073 else if (xml_attr_cmp(&attr, baseInterfaceW))
2075 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2076 entity->u.ifaceps.mask |= BaseIface;
2078 else if (xml_attr_cmp(&attr, nummethodsW))
2080 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2081 entity->u.ifaceps.mask |= NumMethods;
2083 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2085 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2087 else if (xml_attr_cmp(&attr, tlbidW))
2089 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2091 else if (!is_xmlns_attr( &attr ))
2093 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2097 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2098 if (!end) parse_expect_end_elem(xmlbuf, parent);
2101 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2102 struct actctx_loader *acl, const struct xml_elem *parent )
2105 struct xml_elem elem;
2106 struct xml_attr attr;
2107 BOOL end = FALSE;
2108 struct entity* entity;
2110 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2112 set_error( xmlbuf );
2113 return;
2116 while (next_xml_attr(xmlbuf, &attr, &end))
2118 if (xml_attr_cmp(&attr, nameW))
2120 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2122 else if (xml_attr_cmp(&attr, clsidW))
2124 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2126 else if (xml_attr_cmp(&attr, progidW))
2128 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2130 else if (xml_attr_cmp(&attr, tlbidW))
2132 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2134 else if (xml_attr_cmp(&attr, threadingmodelW))
2136 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2138 else if (xml_attr_cmp(&attr, runtimeVersionW))
2140 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2142 else if (!is_xmlns_attr( &attr ))
2144 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2148 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2149 if (entity->u.comclass.progid)
2150 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2151 if (end) return;
2153 while (next_xml_elem(xmlbuf, &elem, parent))
2155 if (xml_elem_cmp(&elem, progidW, asmv1W))
2157 parse_com_class_progid(xmlbuf, entity, &elem);
2159 else
2161 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2162 parse_unknown_elem(xmlbuf, &elem);
2166 if (entity->u.comclass.progids.num)
2167 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2170 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2171 struct actctx_loader *acl, const struct xml_elem *parent )
2173 struct xml_attr attr;
2174 BOOL end = FALSE;
2175 struct entity* entity;
2177 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2179 set_error( xmlbuf );
2180 return;
2183 while (next_xml_attr(xmlbuf, &attr, &end))
2185 if (xml_attr_cmp(&attr, nameW))
2187 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2189 else if (xml_attr_cmp(&attr, clsidW))
2191 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2193 else if (xml_attr_cmp(&attr, runtimeVersionW))
2195 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2197 else if (!is_xmlns_attr( &attr ))
2199 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2203 acl->actctx->sections |= CLRSURROGATES_SECTION;
2204 if (!end) parse_expect_end_elem(xmlbuf, parent);
2207 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2208 const struct xml_elem *parent, BOOL optional )
2210 struct xml_elem elem;
2211 struct xml_attr attr;
2212 struct assembly_identity ai;
2213 BOOL end = FALSE;
2215 memset(&ai, 0, sizeof(ai));
2216 ai.optional = optional;
2218 while (next_xml_attr(xmlbuf, &attr, &end))
2220 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2221 static const WCHAR trueW[] = {'t','r','u','e',0};
2223 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2224 ai.delayed = xmlstr_cmp(&attr.value, trueW);
2225 else if (!is_xmlns_attr( &attr ))
2226 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2229 if (end) return;
2231 while (next_xml_elem(xmlbuf, &elem, parent))
2233 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2235 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2236 /* store the newly found identity for later loading */
2237 if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2238 TRACE( "adding name=%s version=%s arch=%s\n",
2239 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2240 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2242 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2244 parse_binding_redirect_elem(xmlbuf, &elem);
2246 else
2248 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2249 parse_unknown_elem(xmlbuf, &elem);
2254 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2255 const struct xml_elem *parent )
2258 struct xml_elem elem;
2259 struct xml_attr attr;
2260 BOOL end = FALSE, optional = FALSE;
2262 while (next_xml_attr(xmlbuf, &attr, &end))
2264 if (xml_attr_cmp(&attr, optionalW))
2266 optional = xmlstr_cmpi( &attr.value, yesW );
2267 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2269 else if (!is_xmlns_attr( &attr ))
2271 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2275 while (next_xml_elem(xmlbuf, &elem, parent))
2277 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2279 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2281 else
2283 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2284 parse_unknown_elem(xmlbuf, &elem);
2289 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2291 BOOL end = FALSE;
2293 parse_expect_no_attr(xmlbuf, &end);
2294 if (!end) parse_expect_end_elem(xmlbuf, parent);
2297 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2299 BOOL end = FALSE;
2301 parse_expect_no_attr(xmlbuf, &end);
2302 if (!end) parse_expect_end_elem(xmlbuf, parent);
2305 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2306 struct actctx_loader* acl, const struct xml_elem *parent )
2308 struct xml_elem elem;
2309 struct xml_attr attr;
2310 BOOL end = FALSE;
2311 struct dll_redirect* dll;
2313 if (!(dll = add_dll_redirect(assembly)))
2315 set_error( xmlbuf );
2316 return;
2319 while (next_xml_attr(xmlbuf, &attr, &end))
2321 if (xml_attr_cmp(&attr, nameW))
2323 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2324 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2326 else if (xml_attr_cmp(&attr, hashW))
2328 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2330 else if (xml_attr_cmp(&attr, hashalgW))
2332 static const WCHAR sha1W[] = {'S','H','A','1',0};
2333 if (!xmlstr_cmpi(&attr.value, sha1W))
2334 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2336 else if (!is_xmlns_attr( &attr ))
2338 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2342 if (!dll->name) set_error( xmlbuf );
2344 acl->actctx->sections |= DLLREDIRECT_SECTION;
2346 if (end) return;
2348 while (next_xml_elem(xmlbuf, &elem, parent))
2350 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2352 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2354 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2356 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2358 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2360 WARN("asmv2:hash (undocumented) not supported\n");
2361 parse_unknown_elem(xmlbuf, &elem);
2363 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2365 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2367 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2369 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2371 else
2373 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2374 parse_unknown_elem( xmlbuf, &elem );
2379 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2380 struct actctx_loader *acl, const struct xml_elem *parent )
2382 struct xml_attr attr;
2383 BOOL end = FALSE;
2385 while (next_xml_attr(xmlbuf, &attr, &end))
2387 if (xml_attr_cmp(&attr, IdW))
2389 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2390 UNICODE_STRING str;
2391 GUID compat_id;
2393 str.Buffer = (PWSTR)attr.value.ptr;
2394 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2395 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2397 if (!(compat = add_compat_context(assembly)))
2399 set_error( xmlbuf );
2400 return;
2402 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2403 compat->Id = compat_id;
2405 else
2407 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2410 else if (!is_xmlns_attr( &attr ))
2412 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2416 if (!end) parse_expect_end_elem(xmlbuf, parent);
2419 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2420 struct actctx_loader* acl, const struct xml_elem *parent)
2422 struct xml_elem elem;
2424 while (next_xml_elem(xmlbuf, &elem, parent))
2426 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2428 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2430 else
2432 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2433 parse_unknown_elem(xmlbuf, &elem);
2438 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2439 struct actctx_loader* acl, const struct xml_elem *parent)
2441 struct xml_elem elem;
2443 while (next_xml_elem(xmlbuf, &elem, parent))
2445 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2447 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2449 else
2451 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2452 parse_unknown_elem(xmlbuf, &elem);
2457 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2458 struct xml_elem *parent )
2460 struct xml_elem elem;
2461 struct xml_attr attr;
2462 xmlstr_t content;
2463 BOOL end = FALSE;
2464 struct entity *entity;
2466 while (next_xml_attr( xmlbuf, &attr, &end ))
2468 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2471 if (end) return;
2473 if (!parse_text_content( xmlbuf, &content )) return;
2474 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2476 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2477 if (!entity)
2479 set_error( xmlbuf );
2480 return;
2482 entity->u.settings.name = xmlstrdupW( &parent->name );
2483 entity->u.settings.value = xmlstrdupW( &content );
2484 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2486 while (next_xml_elem(xmlbuf, &elem, parent))
2488 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2489 parse_unknown_elem( xmlbuf, &elem );
2493 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2494 struct actctx_loader *acl, const struct xml_elem *parent )
2496 struct xml_elem elem;
2498 while (next_xml_elem( xmlbuf, &elem, parent ))
2500 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2501 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2502 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2503 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2504 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2505 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2506 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2507 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2508 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2509 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2510 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2512 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2514 else
2516 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2517 parse_unknown_elem( xmlbuf, &elem );
2522 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2523 struct actctx_loader *acl, const struct xml_elem *parent )
2525 struct xml_elem elem;
2527 while (next_xml_elem( xmlbuf, &elem, parent ))
2529 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2531 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2533 else
2535 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2536 parse_unknown_elem( xmlbuf, &elem );
2541 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2542 struct actctx_loader *acl, const struct xml_elem *parent )
2544 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2545 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2546 static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2547 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2548 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2549 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2550 static const WCHAR trueW[] = {'t','r','u','e',0};
2552 struct xml_elem elem;
2553 struct xml_attr attr;
2554 BOOL end = FALSE;
2556 /* Multiple requestedExecutionLevel elements are not supported. */
2557 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2559 while (next_xml_attr(xmlbuf, &attr, &end))
2561 if (xml_attr_cmp(&attr, levelW))
2563 if (xmlstr_cmpi(&attr.value, asInvokerW))
2564 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2565 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2566 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2567 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2568 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2569 else
2570 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2572 else if (xml_attr_cmp(&attr, uiAccessW))
2574 if (xmlstr_cmpi(&attr.value, falseW))
2575 assembly->ui_access = FALSE;
2576 else if (xmlstr_cmpi(&attr.value, trueW))
2577 assembly->ui_access = TRUE;
2578 else
2579 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2581 else if (!is_xmlns_attr( &attr ))
2582 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2585 if (end) return;
2587 while (next_xml_elem(xmlbuf, &elem, parent))
2589 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2590 parse_unknown_elem(xmlbuf, &elem);
2594 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2595 struct actctx_loader *acl, const struct xml_elem *parent )
2597 struct xml_elem elem;
2599 while (next_xml_elem(xmlbuf, &elem, parent))
2601 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2603 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2605 else
2607 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2608 parse_unknown_elem(xmlbuf, &elem);
2613 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2614 struct actctx_loader *acl, const struct xml_elem *parent )
2616 struct xml_elem elem;
2618 while (next_xml_elem(xmlbuf, &elem, parent))
2620 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2622 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2624 else
2626 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2627 parse_unknown_elem(xmlbuf, &elem);
2632 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2633 struct actctx_loader *acl, const struct xml_elem *parent )
2635 struct xml_elem elem;
2637 while (next_xml_elem(xmlbuf, &elem, parent))
2639 if (xml_elem_cmp(&elem, securityW, asmv1W))
2641 parse_security_elem(xmlbuf, assembly, acl, &elem);
2643 else
2645 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2646 parse_unknown_elem(xmlbuf, &elem);
2651 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2652 struct actctx_loader* acl, const struct xml_elem *parent,
2653 struct assembly_identity* expected_ai)
2655 struct xml_elem elem;
2656 struct xml_attr attr;
2657 BOOL end = FALSE, version = FALSE;
2659 TRACE("(%p)\n", xmlbuf);
2661 while (next_xml_attr(xmlbuf, &attr, &end))
2663 if (xml_attr_cmp(&attr, manifestVersionW))
2665 static const WCHAR v10W[] = {'1','.','0',0};
2666 if (!xmlstr_cmp(&attr.value, v10W))
2668 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2669 break;
2671 version = TRUE;
2673 else if (!is_xmlns_attr( &attr ))
2675 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2679 if (end || !version)
2681 set_error( xmlbuf );
2682 return;
2685 while (next_xml_elem(xmlbuf, &elem, parent))
2687 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2689 parse_noinherit_elem(xmlbuf, &elem);
2690 assembly->no_inherit = TRUE;
2692 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2694 parse_noinheritable_elem(xmlbuf, &elem);
2696 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2698 parse_description_elem(xmlbuf, &elem);
2700 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2702 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2704 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2706 parse_dependency_elem(xmlbuf, acl, &elem);
2708 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2710 parse_file_elem(xmlbuf, assembly, acl, &elem);
2712 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2714 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2716 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2718 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2720 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2722 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2724 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2726 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2728 if (!xmlbuf->error && expected_ai)
2730 /* FIXME: more tests */
2731 if (assembly->type == ASSEMBLY_MANIFEST &&
2732 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2734 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2735 expected_ai->version.major, expected_ai->version.minor,
2736 expected_ai->version.build, expected_ai->version.revision,
2737 assembly->id.version.major, assembly->id.version.minor,
2738 assembly->id.version.build, assembly->id.version.revision);
2739 set_error( xmlbuf );
2741 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2742 (assembly->id.version.major != expected_ai->version.major ||
2743 assembly->id.version.minor != expected_ai->version.minor ||
2744 assembly->id.version.build < expected_ai->version.build ||
2745 (assembly->id.version.build == expected_ai->version.build &&
2746 assembly->id.version.revision < expected_ai->version.revision)))
2748 FIXME("wrong version for shared assembly manifest\n");
2749 set_error( xmlbuf );
2753 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2755 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2757 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2759 parse_application_elem(xmlbuf, assembly, acl, &elem);
2761 else
2763 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2764 parse_unknown_elem(xmlbuf, &elem);
2768 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2769 assembly->no_inherit)
2771 set_error( xmlbuf );
2775 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2776 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2778 struct xml_elem elem;
2779 struct xml_elem parent = {};
2781 xmlbuf->error = FALSE;
2782 xmlbuf->ns_pos = 0;
2784 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2786 if (xmlstr_cmp(&elem.name, xmlW) &&
2787 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2788 return STATUS_SXS_CANT_GEN_ACTCTX;
2790 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2792 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2793 return STATUS_SXS_CANT_GEN_ACTCTX;
2796 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2797 if (xmlbuf->error)
2799 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2800 return STATUS_SXS_CANT_GEN_ACTCTX;
2803 if (next_xml_elem(xmlbuf, &elem, &parent))
2805 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2806 return STATUS_SXS_CANT_GEN_ACTCTX;
2809 if (xmlbuf->ptr != xmlbuf->end)
2811 FIXME("parse error\n");
2812 return STATUS_SXS_CANT_GEN_ACTCTX;
2814 return STATUS_SUCCESS;
2817 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2818 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2819 const void *buffer, SIZE_T size )
2821 xmlbuf_t xmlbuf;
2822 NTSTATUS status;
2823 struct assembly *assembly;
2824 int unicode_tests;
2826 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2828 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2829 return STATUS_SXS_CANT_GEN_ACTCTX;
2831 if (directory && !(assembly->directory = strdupW(directory)))
2832 return STATUS_NO_MEMORY;
2834 if (!filename)
2836 UNICODE_STRING module_path;
2837 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2838 assembly->manifest.info = module_path.Buffer;
2840 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2842 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2843 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2845 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2846 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2848 xmlbuf.ptr = buffer;
2849 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2850 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2852 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2854 const WCHAR *buf = buffer;
2855 WCHAR *new_buff;
2856 unsigned int i;
2858 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2859 return STATUS_NO_MEMORY;
2860 for (i = 0; i < size / sizeof(WCHAR); i++)
2861 new_buff[i] = RtlUshortByteSwap( buf[i] );
2862 xmlbuf.ptr = new_buff;
2863 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2864 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2865 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2867 else
2869 DWORD len;
2870 WCHAR *new_buff;
2872 /* let's assume utf-8 for now */
2873 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2874 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2875 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2876 xmlbuf.ptr = new_buff;
2877 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2878 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2879 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2881 return status;
2884 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2886 OBJECT_ATTRIBUTES attr;
2887 IO_STATUS_BLOCK io;
2889 attr.Length = sizeof(attr);
2890 attr.RootDirectory = 0;
2891 attr.Attributes = OBJ_CASE_INSENSITIVE;
2892 attr.ObjectName = name;
2893 attr.SecurityDescriptor = NULL;
2894 attr.SecurityQualityOfService = NULL;
2895 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2898 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2899 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2900 HANDLE hModule, LPCWSTR resname, ULONG lang )
2902 NTSTATUS status;
2903 UNICODE_STRING nameW;
2904 LDR_RESOURCE_INFO info;
2905 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2906 void *ptr;
2908 if (TRACE_ON(actctx))
2910 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2912 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2913 hModule, debugstr_w(nameW.Buffer) );
2914 RtlFreeUnicodeString( &nameW );
2916 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2917 hModule, debugstr_w(filename) );
2920 if (!resname) return STATUS_INVALID_PARAMETER;
2922 info.Type = RT_MANIFEST;
2923 info.Language = lang;
2924 if (!((ULONG_PTR)resname >> 16))
2926 info.Name = (ULONG_PTR)resname;
2927 status = LdrFindResource_U(hModule, &info, 3, &entry);
2929 else if (resname[0] == '#')
2931 ULONG value;
2932 RtlInitUnicodeString(&nameW, resname + 1);
2933 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2934 return STATUS_INVALID_PARAMETER;
2935 info.Name = value;
2936 status = LdrFindResource_U(hModule, &info, 3, &entry);
2938 else
2940 RtlCreateUnicodeString(&nameW, resname);
2941 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2942 info.Name = (ULONG_PTR)nameW.Buffer;
2943 status = LdrFindResource_U(hModule, &info, 3, &entry);
2944 RtlFreeUnicodeString(&nameW);
2946 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2948 if (status == STATUS_SUCCESS)
2949 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2951 return status;
2954 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2955 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2956 HANDLE file, LPCWSTR resname, ULONG lang )
2958 HANDLE mapping;
2959 OBJECT_ATTRIBUTES attr;
2960 LARGE_INTEGER size;
2961 LARGE_INTEGER offset;
2962 NTSTATUS status;
2963 SIZE_T count;
2964 void *base;
2966 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2968 attr.Length = sizeof(attr);
2969 attr.RootDirectory = 0;
2970 attr.ObjectName = NULL;
2971 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2972 attr.SecurityDescriptor = NULL;
2973 attr.SecurityQualityOfService = NULL;
2975 size.QuadPart = 0;
2976 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2977 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2978 if (status != STATUS_SUCCESS) return status;
2980 offset.QuadPart = 0;
2981 count = 0;
2982 base = NULL;
2983 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2984 &count, ViewShare, 0, PAGE_READONLY );
2985 NtClose( mapping );
2986 if (status != STATUS_SUCCESS) return status;
2988 if (RtlImageNtHeader(base)) /* we got a PE file */
2990 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2991 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2993 else status = STATUS_INVALID_IMAGE_FORMAT;
2995 NtUnmapViewOfSection( GetCurrentProcess(), base );
2996 return status;
2999 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3000 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3002 FILE_END_OF_FILE_INFORMATION info;
3003 IO_STATUS_BLOCK io;
3004 HANDLE mapping;
3005 OBJECT_ATTRIBUTES attr;
3006 LARGE_INTEGER size;
3007 LARGE_INTEGER offset;
3008 NTSTATUS status;
3009 SIZE_T count;
3010 void *base;
3012 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3014 attr.Length = sizeof(attr);
3015 attr.RootDirectory = 0;
3016 attr.ObjectName = NULL;
3017 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3018 attr.SecurityDescriptor = NULL;
3019 attr.SecurityQualityOfService = NULL;
3021 size.QuadPart = 0;
3022 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3023 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3024 if (status != STATUS_SUCCESS) return status;
3026 offset.QuadPart = 0;
3027 count = 0;
3028 base = NULL;
3029 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3030 &count, ViewShare, 0, PAGE_READONLY );
3031 NtClose( mapping );
3032 if (status != STATUS_SUCCESS) return status;
3034 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3035 if (status == STATUS_SUCCESS)
3036 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3038 NtUnmapViewOfSection( GetCurrentProcess(), base );
3039 return status;
3042 /* try to load the .manifest file associated to the file */
3043 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3044 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3046 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3047 WCHAR *buffer;
3048 NTSTATUS status;
3049 UNICODE_STRING nameW;
3050 HANDLE file;
3051 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3053 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3055 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3057 if (module) /* use the module filename */
3059 UNICODE_STRING name;
3061 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3063 if (resid != 1) NTDLL_swprintf( name.Buffer + wcslen(name.Buffer), fmtW, resid );
3064 wcscat( name.Buffer, dotManifestW );
3065 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3066 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3067 RtlFreeUnicodeString( &name );
3069 if (status) return status;
3071 else
3073 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3074 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3075 return STATUS_NO_MEMORY;
3076 wcscpy( buffer, filename );
3077 if (resid != 1) NTDLL_swprintf( buffer + wcslen(buffer), fmtW, resid );
3078 wcscat( buffer, dotManifestW );
3079 RtlInitUnicodeString( &nameW, buffer );
3082 if (!open_nt_file( &file, &nameW ))
3084 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3085 NtClose( file );
3087 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3088 RtlFreeUnicodeString( &nameW );
3089 return status;
3092 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3094 static const WCHAR lookup_fmtW[] =
3095 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3096 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3097 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3099 WCHAR *lookup, *ret = NULL;
3100 UNICODE_STRING lookup_us;
3101 IO_STATUS_BLOCK io;
3102 const WCHAR *lang = ai->language;
3103 unsigned int data_pos = 0, data_len;
3104 char buffer[8192];
3106 if (!lang || !wcsicmp( lang, neutralW )) lang = wildcardW;
3108 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3109 (wcslen(ai->arch) + wcslen(ai->name)
3110 + wcslen(ai->public_key) + wcslen(lang) + 20) * sizeof(WCHAR)
3111 + sizeof(lookup_fmtW) )))
3112 return NULL;
3113 NTDLL_swprintf( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3114 ai->version.major, ai->version.minor, lang );
3115 RtlInitUnicodeString( &lookup_us, lookup );
3117 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3118 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3120 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3121 FILE_BOTH_DIR_INFORMATION *dir_info;
3122 WCHAR *tmp;
3123 ULONG build, revision;
3125 data_len = io.Information;
3127 for (;;)
3129 if (data_pos >= data_len)
3131 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3132 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3133 break;
3134 data_len = io.Information;
3135 data_pos = 0;
3137 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3139 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3140 else data_pos = data_len;
3142 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3143 build = wcstoul( tmp, NULL, 10 );
3144 if (build < min_build) continue;
3145 tmp = wcschr(tmp, '.') + 1;
3146 revision = wcstoul( tmp, NULL, 10 );
3147 if (build == min_build && revision < min_revision) continue;
3148 tmp = wcschr(tmp, '_') + 1;
3149 tmp = wcschr(tmp, '_') + 1;
3150 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3151 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3153 /* prefer a non-Wine manifest if we already have one */
3154 /* we'll still load the builtin dll if specified through DllOverrides */
3155 if (ret) continue;
3157 else
3159 min_build = build;
3160 min_revision = revision;
3162 ai->version.build = build;
3163 ai->version.revision = revision;
3164 RtlFreeHeap( GetProcessHeap(), 0, ret );
3165 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3167 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3168 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3172 else WARN("no matching file for %s\n", debugstr_w(lookup));
3173 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3174 return ret;
3177 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3179 struct assembly_identity sxs_ai;
3180 UNICODE_STRING path_us;
3181 OBJECT_ATTRIBUTES attr;
3182 IO_STATUS_BLOCK io;
3183 WCHAR *path, *file = NULL;
3184 HANDLE handle;
3186 static const WCHAR manifest_dirW[] =
3187 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3189 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3191 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3192 wcslen(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3193 return STATUS_NO_MEMORY;
3195 wcscpy( path, user_shared_data->NtSystemRoot );
3196 memcpy( path + wcslen(path), manifest_dirW, sizeof(manifest_dirW) );
3198 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3200 RtlFreeHeap( GetProcessHeap(), 0, path );
3201 return STATUS_NO_SUCH_FILE;
3203 RtlFreeHeap( GetProcessHeap(), 0, path );
3205 attr.Length = sizeof(attr);
3206 attr.RootDirectory = 0;
3207 attr.Attributes = OBJ_CASE_INSENSITIVE;
3208 attr.ObjectName = &path_us;
3209 attr.SecurityDescriptor = NULL;
3210 attr.SecurityQualityOfService = NULL;
3212 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3213 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3215 sxs_ai = *ai;
3216 file = lookup_manifest_file( handle, &sxs_ai );
3217 NtClose( handle );
3219 if (!file)
3221 RtlFreeUnicodeString( &path_us );
3222 return STATUS_NO_SUCH_FILE;
3225 /* append file name to directory path */
3226 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3227 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3229 RtlFreeHeap( GetProcessHeap(), 0, file );
3230 RtlFreeUnicodeString( &path_us );
3231 return STATUS_NO_MEMORY;
3234 path[path_us.Length/sizeof(WCHAR)] = '\\';
3235 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3236 RtlInitUnicodeString( &path_us, path );
3237 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3239 if (!open_nt_file( &handle, &path_us ))
3241 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3242 NtClose( handle );
3244 else io.u.Status = STATUS_NO_SUCH_FILE;
3246 RtlFreeHeap( GetProcessHeap(), 0, file );
3247 RtlFreeUnicodeString( &path_us );
3248 return io.u.Status;
3251 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3252 struct assembly_identity* ai)
3254 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3255 unsigned int i;
3256 WCHAR *buffer, *p, *directory;
3257 NTSTATUS status;
3258 UNICODE_STRING nameW;
3259 HANDLE file;
3260 DWORD len;
3262 TRACE( "looking for name=%s version=%s arch=%s\n",
3263 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3265 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3267 /* FIXME: add support for language specific lookup */
3269 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3270 wcslen(acl->actctx->appdir.info));
3272 nameW.Buffer = NULL;
3273 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3274 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3275 return STATUS_NO_MEMORY;
3277 if (!(directory = build_assembly_dir( ai )))
3279 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3280 return STATUS_NO_MEMORY;
3283 /* Lookup in <dir>\name.dll
3284 * <dir>\name.manifest
3285 * <dir>\name\name.dll
3286 * <dir>\name\name.manifest
3288 * First 'appdir' is used as <dir>, if that failed
3289 * it tries application manifest file path.
3291 wcscpy( buffer, acl->actctx->appdir.info );
3292 p = buffer + wcslen(buffer);
3293 for (i = 0; i < 4; i++)
3295 if (i == 2)
3297 struct assembly *assembly = acl->actctx->assemblies;
3298 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3300 else *p++ = '\\';
3302 wcscpy( p, ai->name );
3303 p += wcslen(p);
3305 wcscpy( p, dotDllW );
3306 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3308 status = open_nt_file( &file, &nameW );
3309 if (!status)
3311 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3312 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3313 NtClose( file );
3314 if (status == STATUS_SUCCESS)
3315 break;
3317 RtlFreeUnicodeString( &nameW );
3320 wcscpy( p, dotManifestW );
3321 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3323 status = open_nt_file( &file, &nameW );
3324 if (!status)
3326 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3327 NtClose( file );
3328 break;
3330 RtlFreeUnicodeString( &nameW );
3332 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3334 RtlFreeUnicodeString( &nameW );
3335 RtlFreeHeap( GetProcessHeap(), 0, directory );
3336 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3337 return status;
3340 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3342 NTSTATUS status = STATUS_SUCCESS;
3343 unsigned int i;
3345 for (i = 0; i < acl->num_dependencies; i++)
3347 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3349 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3351 FIXME( "Could not find dependent assembly %s (%s)\n",
3352 debugstr_w(acl->dependencies[i].name),
3353 debugstr_version(&acl->dependencies[i].version) );
3354 status = STATUS_SXS_CANT_GEN_ACTCTX;
3355 break;
3359 /* FIXME should now iterate through all refs */
3360 return status;
3363 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3364 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3366 NTSTATUS status = STATUS_SUCCESS;
3368 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3370 if (*handle) return STATUS_INVALID_PARAMETER;
3372 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3373 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3375 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3377 ULONG_PTR magic;
3378 LDR_MODULE *pldr;
3380 if (!*handle) return STATUS_INVALID_PARAMETER;
3382 LdrLockLoaderLock( 0, NULL, &magic );
3383 if (!LdrFindEntryForAddress( *handle, &pldr ))
3385 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3386 status = STATUS_DLL_NOT_FOUND;
3387 else
3388 *handle = pldr->ActivationContext;
3390 else status = STATUS_DLL_NOT_FOUND;
3391 LdrUnlockLoaderLock( 0, magic );
3393 else if (!*handle && (class != ActivationContextBasicInformation))
3394 *handle = process_actctx;
3396 return status;
3399 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3401 unsigned int i, j, total_len = 0, dll_count = 0;
3402 struct strsection_header *header;
3403 struct dllredirect_data *data;
3404 struct string_index *index;
3405 ULONG name_offset;
3407 /* compute section length */
3408 for (i = 0; i < actctx->num_assemblies; i++)
3410 struct assembly *assembly = &actctx->assemblies[i];
3411 for (j = 0; j < assembly->num_dlls; j++)
3413 struct dll_redirect *dll = &assembly->dlls[j];
3415 /* each entry needs index, data and string data */
3416 total_len += sizeof(*index);
3417 total_len += sizeof(*data);
3418 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3421 dll_count += assembly->num_dlls;
3424 total_len += sizeof(*header);
3426 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3427 if (!header) return STATUS_NO_MEMORY;
3429 memset(header, 0, sizeof(*header));
3430 header->magic = STRSECTION_MAGIC;
3431 header->size = sizeof(*header);
3432 header->count = dll_count;
3433 header->index_offset = sizeof(*header);
3434 index = (struct string_index*)((BYTE*)header + header->index_offset);
3435 name_offset = header->index_offset + header->count*sizeof(*index);
3437 for (i = 0; i < actctx->num_assemblies; i++)
3439 struct assembly *assembly = &actctx->assemblies[i];
3440 for (j = 0; j < assembly->num_dlls; j++)
3442 struct dll_redirect *dll = &assembly->dlls[j];
3443 UNICODE_STRING str;
3444 WCHAR *ptrW;
3446 /* setup new index entry */
3447 str.Buffer = dll->name;
3448 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3449 str.MaximumLength = str.Length + sizeof(WCHAR);
3450 /* hash original class name */
3451 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3453 index->name_offset = name_offset;
3454 index->name_len = str.Length;
3455 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3456 index->data_len = sizeof(*data);
3457 index->rosterindex = i + 1;
3459 /* setup data */
3460 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3461 data->size = sizeof(*data);
3462 data->unk = 2; /* FIXME: seems to be constant */
3463 memset(data->res, 0, sizeof(data->res));
3465 /* dll name */
3466 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3467 memcpy(ptrW, dll->name, index->name_len);
3468 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3470 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3472 index++;
3476 *section = header;
3478 return STATUS_SUCCESS;
3481 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3483 struct string_index *iter, *index = NULL;
3484 UNICODE_STRING str;
3485 ULONG hash = 0, i;
3487 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3488 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3490 for (i = 0; i < section->count; i++)
3492 if (iter->hash == hash)
3494 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3495 str.Length = iter->name_len;
3496 if (RtlEqualUnicodeString( &str, name, TRUE ))
3498 index = iter;
3499 break;
3501 else
3502 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3504 iter++;
3507 return index;
3510 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3512 struct guid_index *iter, *index = NULL;
3513 ULONG i;
3515 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3517 for (i = 0; i < section->count; i++)
3519 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3521 index = iter;
3522 break;
3524 iter++;
3527 return index;
3530 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3532 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3535 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3536 PACTCTX_SECTION_KEYED_DATA data)
3538 struct dllredirect_data *dll;
3539 struct string_index *index;
3541 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3543 if (!actctx->dllredirect_section)
3545 struct strsection_header *section;
3547 NTSTATUS status = build_dllredirect_section(actctx, &section);
3548 if (status) return status;
3550 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3551 RtlFreeHeap(GetProcessHeap(), 0, section);
3554 index = find_string_index(actctx->dllredirect_section, name);
3555 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3557 if (data)
3559 dll = get_dllredirect_data(actctx, index);
3561 data->ulDataFormatVersion = 1;
3562 data->lpData = dll;
3563 data->ulLength = dll->size;
3564 data->lpSectionGlobalData = NULL;
3565 data->ulSectionGlobalDataLength = 0;
3566 data->lpSectionBase = actctx->dllredirect_section;
3567 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3568 data->hActCtx = NULL;
3570 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3571 data->ulAssemblyRosterIndex = index->rosterindex;
3574 return STATUS_SUCCESS;
3577 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3579 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3582 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3584 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3587 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3589 unsigned int i, j, k, total_len = 0, class_count = 0;
3590 struct wndclass_redirect_data *data;
3591 struct strsection_header *header;
3592 struct string_index *index;
3593 ULONG name_offset;
3595 /* compute section length */
3596 for (i = 0; i < actctx->num_assemblies; i++)
3598 struct assembly *assembly = &actctx->assemblies[i];
3599 for (j = 0; j < assembly->num_dlls; j++)
3601 struct dll_redirect *dll = &assembly->dlls[j];
3602 for (k = 0; k < dll->entities.num; k++)
3604 struct entity *entity = &dll->entities.base[k];
3605 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3607 int class_len = wcslen(entity->u.class.name) + 1;
3608 int len;
3610 /* each class entry needs index, data and string data */
3611 total_len += sizeof(*index);
3612 total_len += sizeof(*data);
3613 /* original name is stored separately */
3614 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3615 /* versioned name and module name are stored one after another */
3616 if (entity->u.class.versioned)
3617 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3618 else
3619 len = class_len;
3620 len += wcslen(dll->name) + 1;
3621 total_len += aligned_string_len(len*sizeof(WCHAR));
3623 class_count++;
3629 total_len += sizeof(*header);
3631 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3632 if (!header) return STATUS_NO_MEMORY;
3634 memset(header, 0, sizeof(*header));
3635 header->magic = STRSECTION_MAGIC;
3636 header->size = sizeof(*header);
3637 header->count = class_count;
3638 header->index_offset = sizeof(*header);
3639 index = (struct string_index*)((BYTE*)header + header->index_offset);
3640 name_offset = header->index_offset + header->count*sizeof(*index);
3642 for (i = 0; i < actctx->num_assemblies; i++)
3644 struct assembly *assembly = &actctx->assemblies[i];
3645 for (j = 0; j < assembly->num_dlls; j++)
3647 struct dll_redirect *dll = &assembly->dlls[j];
3648 for (k = 0; k < dll->entities.num; k++)
3650 struct entity *entity = &dll->entities.base[k];
3651 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3653 static const WCHAR exclW[] = {'!',0};
3654 ULONG versioned_len, module_len;
3655 UNICODE_STRING str;
3656 WCHAR *ptrW;
3658 /* setup new index entry */
3659 str.Buffer = entity->u.class.name;
3660 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3661 str.MaximumLength = str.Length + sizeof(WCHAR);
3662 /* hash original class name */
3663 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3665 /* include '!' separator too */
3666 if (entity->u.class.versioned)
3667 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3668 else
3669 versioned_len = str.Length;
3670 module_len = wcslen(dll->name)*sizeof(WCHAR);
3672 index->name_offset = name_offset;
3673 index->name_len = str.Length;
3674 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3675 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3676 index->rosterindex = i + 1;
3678 /* setup data */
3679 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3680 data->size = sizeof(*data);
3681 data->res = 0;
3682 data->name_len = versioned_len;
3683 data->name_offset = sizeof(*data);
3684 data->module_len = module_len;
3685 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3687 /* original class name */
3688 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3689 memcpy(ptrW, entity->u.class.name, index->name_len);
3690 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3692 /* module name */
3693 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3694 memcpy(ptrW, dll->name, data->module_len);
3695 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3697 /* versioned name */
3698 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3699 if (entity->u.class.versioned)
3701 get_assembly_version(assembly, ptrW);
3702 wcscat(ptrW, exclW);
3703 wcscat(ptrW, entity->u.class.name);
3705 else
3707 memcpy(ptrW, entity->u.class.name, index->name_len);
3708 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3711 name_offset += sizeof(*data);
3712 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3714 index++;
3720 *section = header;
3722 return STATUS_SUCCESS;
3725 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3726 PACTCTX_SECTION_KEYED_DATA data)
3728 struct string_index *iter, *index = NULL;
3729 struct wndclass_redirect_data *class;
3730 UNICODE_STRING str;
3731 ULONG hash;
3732 int i;
3734 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3736 if (!actctx->wndclass_section)
3738 struct strsection_header *section;
3740 NTSTATUS status = build_wndclass_section(actctx, &section);
3741 if (status) return status;
3743 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3744 RtlFreeHeap(GetProcessHeap(), 0, section);
3747 hash = 0;
3748 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3749 iter = get_wndclass_first_index(actctx);
3751 for (i = 0; i < actctx->wndclass_section->count; i++)
3753 if (iter->hash == hash)
3755 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3756 str.Length = iter->name_len;
3757 if (RtlEqualUnicodeString( &str, name, TRUE ))
3759 index = iter;
3760 break;
3762 else
3763 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3765 iter++;
3768 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3770 if (data)
3772 class = get_wndclass_data(actctx, index);
3774 data->ulDataFormatVersion = 1;
3775 data->lpData = class;
3776 /* full length includes string length with nulls */
3777 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3778 data->lpSectionGlobalData = NULL;
3779 data->ulSectionGlobalDataLength = 0;
3780 data->lpSectionBase = actctx->wndclass_section;
3781 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3782 data->hActCtx = NULL;
3784 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3785 data->ulAssemblyRosterIndex = index->rosterindex;
3788 return STATUS_SUCCESS;
3791 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3793 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3794 struct guidsection_header *header;
3795 ULONG module_offset, data_offset;
3796 struct tlibredirect_data *data;
3797 struct guid_index *index;
3799 /* compute section length */
3800 for (i = 0; i < actctx->num_assemblies; i++)
3802 struct assembly *assembly = &actctx->assemblies[i];
3803 for (j = 0; j < assembly->num_dlls; j++)
3805 struct dll_redirect *dll = &assembly->dlls[j];
3806 for (k = 0; k < dll->entities.num; k++)
3808 struct entity *entity = &dll->entities.base[k];
3809 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3811 /* each entry needs index, data and string data for module name and help string */
3812 total_len += sizeof(*index);
3813 total_len += sizeof(*data);
3814 /* help string is stored separately */
3815 if (*entity->u.typelib.helpdir)
3816 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3818 /* module names are packed one after another */
3819 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
3821 tlib_count++;
3827 total_len += aligned_string_len(names_len);
3828 total_len += sizeof(*header);
3830 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3831 if (!header) return STATUS_NO_MEMORY;
3833 memset(header, 0, sizeof(*header));
3834 header->magic = GUIDSECTION_MAGIC;
3835 header->size = sizeof(*header);
3836 header->count = tlib_count;
3837 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3838 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3839 module_offset = sizeof(*header);
3840 data_offset = header->index_offset + tlib_count*sizeof(*index);
3842 for (i = 0; i < actctx->num_assemblies; i++)
3844 struct assembly *assembly = &actctx->assemblies[i];
3845 for (j = 0; j < assembly->num_dlls; j++)
3847 struct dll_redirect *dll = &assembly->dlls[j];
3848 for (k = 0; k < dll->entities.num; k++)
3850 struct entity *entity = &dll->entities.base[k];
3851 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3853 ULONG module_len, help_len;
3854 UNICODE_STRING str;
3855 WCHAR *ptrW;
3857 if (*entity->u.typelib.helpdir)
3858 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
3859 else
3860 help_len = 0;
3862 module_len = wcslen(dll->name)*sizeof(WCHAR);
3864 /* setup new index entry */
3865 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3866 RtlGUIDFromString(&str, &index->guid);
3867 index->data_offset = data_offset;
3868 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3869 index->rosterindex = i + 1;
3871 /* setup data */
3872 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3873 data->size = sizeof(*data);
3874 data->res = 0;
3875 data->name_len = module_len;
3876 data->name_offset = module_offset;
3877 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3878 data->langid = 0;
3879 data->flags = entity->u.typelib.flags;
3880 data->help_len = help_len;
3881 data->help_offset = sizeof(*data);
3882 data->major_version = entity->u.typelib.major;
3883 data->minor_version = entity->u.typelib.minor;
3885 /* module name */
3886 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3887 memcpy(ptrW, dll->name, data->name_len);
3888 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3890 /* help string */
3891 if (data->help_len)
3893 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3894 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3895 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3898 data_offset += sizeof(*data);
3899 if (help_len)
3900 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3902 module_offset += module_len + sizeof(WCHAR);
3904 index++;
3910 *section = header;
3912 return STATUS_SUCCESS;
3915 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3917 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3920 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3922 struct guid_index *index = NULL;
3923 struct tlibredirect_data *tlib;
3925 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3927 if (!actctx->tlib_section)
3929 struct guidsection_header *section;
3931 NTSTATUS status = build_tlib_section(actctx, &section);
3932 if (status) return status;
3934 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3935 RtlFreeHeap(GetProcessHeap(), 0, section);
3938 index = find_guid_index(actctx->tlib_section, guid);
3939 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3941 tlib = get_tlib_data(actctx, index);
3943 data->ulDataFormatVersion = 1;
3944 data->lpData = tlib;
3945 /* full length includes string length with nulls */
3946 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3947 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3948 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3949 data->lpSectionBase = actctx->tlib_section;
3950 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3951 data->hActCtx = NULL;
3953 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3954 data->ulAssemblyRosterIndex = index->rosterindex;
3956 return STATUS_SUCCESS;
3959 static void generate_uuid(ULONG *seed, GUID *guid)
3961 ULONG *ptr = (ULONG*)guid;
3962 int i;
3964 /* GUID is 16 bytes long */
3965 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3966 *ptr = RtlUniform(seed);
3968 guid->Data3 &= 0x0fff;
3969 guid->Data3 |= (4 << 12);
3970 guid->Data4[0] &= 0x3f;
3971 guid->Data4[0] |= 0x80;
3974 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3975 unsigned int *count, unsigned int *len, unsigned int *module_len)
3977 unsigned int i;
3979 for (i = 0; i < entities->num; i++)
3981 struct entity *entity = &entities->base[i];
3982 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3984 /* each entry needs two index entries, extra one goes for alias GUID */
3985 *len += 2*sizeof(struct guid_index);
3986 /* To save some memory we don't allocated two data structures,
3987 instead alias index and normal index point to the same data structure. */
3988 *len += sizeof(struct comclassredirect_data);
3990 /* for clrClass store some more */
3991 if (entity->u.comclass.name)
3993 unsigned int str_len;
3995 /* all string data is stored together in aligned block */
3996 str_len = wcslen(entity->u.comclass.name)+1;
3997 if (entity->u.comclass.progid)
3998 str_len += wcslen(entity->u.comclass.progid)+1;
3999 if (entity->u.comclass.version)
4000 str_len += wcslen(entity->u.comclass.version)+1;
4002 *len += sizeof(struct clrclass_data);
4003 *len += aligned_string_len(str_len*sizeof(WCHAR));
4005 /* module name is forced to mscoree.dll, and stored two times with different case */
4006 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4008 else
4010 /* progid string is stored separately */
4011 if (entity->u.comclass.progid)
4012 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4014 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4017 *count += 1;
4022 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4023 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4024 ULONG *seed, ULONG rosterindex)
4026 unsigned int i;
4028 for (i = 0; i < entities->num; i++)
4030 struct entity *entity = &entities->base[i];
4031 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4033 ULONG module_len, progid_len, str_len = 0;
4034 struct comclassredirect_data *data;
4035 struct guid_index *alias_index;
4036 struct clrclass_data *clrdata;
4037 UNICODE_STRING str;
4038 WCHAR *ptrW;
4040 if (entity->u.comclass.progid)
4041 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4042 else
4043 progid_len = 0;
4045 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(mscoreeW)*sizeof(WCHAR);
4047 /* setup new index entry */
4048 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4049 RtlGUIDFromString(&str, &(*index)->guid);
4051 (*index)->data_offset = *data_offset;
4052 (*index)->data_len = sizeof(*data); /* additional length added later */
4053 (*index)->rosterindex = rosterindex;
4055 /* Setup new index entry for alias guid. Alias index records are placed after
4056 normal records, so normal guids are hit first on search. Note that class count
4057 is doubled. */
4058 alias_index = (*index) + section->count/2;
4059 generate_uuid(seed, &alias_index->guid);
4060 alias_index->data_offset = (*index)->data_offset;
4061 alias_index->data_len = 0;
4062 alias_index->rosterindex = (*index)->rosterindex;
4064 /* setup data */
4065 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4066 data->size = sizeof(*data);
4067 data->res = 0;
4068 data->res1[0] = 0;
4069 data->res1[1] = 0;
4070 data->model = entity->u.comclass.model;
4071 data->clsid = (*index)->guid;
4072 data->alias = alias_index->guid;
4073 data->clsid2 = data->clsid;
4074 if (entity->u.comclass.tlbid)
4076 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4077 RtlGUIDFromString(&str, &data->tlbid);
4079 else
4080 memset(&data->tlbid, 0, sizeof(data->tlbid));
4081 data->name_len = module_len;
4082 data->name_offset = *module_offset;
4083 data->progid_len = progid_len;
4084 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4085 data->clrdata_len = 0; /* will be set later */
4086 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4087 data->miscstatus = entity->u.comclass.miscstatus;
4088 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4089 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4090 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4091 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4093 /* mask describes which misc* data is available */
4094 data->miscmask = 0;
4095 if (data->miscstatus)
4096 data->miscmask |= MiscStatus;
4097 if (data->miscstatuscontent)
4098 data->miscmask |= MiscStatusContent;
4099 if (data->miscstatusthumbnail)
4100 data->miscmask |= MiscStatusThumbnail;
4101 if (data->miscstatusicon)
4102 data->miscmask |= MiscStatusIcon;
4103 if (data->miscstatusdocprint)
4104 data->miscmask |= MiscStatusDocPrint;
4106 if (data->clrdata_offset)
4108 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4110 clrdata->size = sizeof(*clrdata);
4111 clrdata->res[0] = 0;
4112 clrdata->res[1] = 2; /* FIXME: unknown field */
4113 clrdata->module_len = wcslen(mscoreeW)*sizeof(WCHAR);
4114 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4115 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4116 clrdata->name_offset = clrdata->size;
4117 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4118 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4119 clrdata->res2[0] = 0;
4120 clrdata->res2[1] = 0;
4122 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4124 /* module name */
4125 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4126 memcpy(ptrW, mscoree2W, clrdata->module_len);
4127 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4129 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4130 memcpy(ptrW, mscoreeW, data->name_len);
4131 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4133 /* class name */
4134 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4135 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4136 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4138 /* runtime version, optional */
4139 if (clrdata->version_len)
4141 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4143 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4144 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4145 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4148 if (data->progid_len)
4149 data->progid_offset += data->clrdata_len;
4150 (*index)->data_len += sizeof(*clrdata);
4152 else
4154 clrdata = NULL;
4156 /* module name */
4157 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4158 memcpy(ptrW, dll->name, data->name_len);
4159 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4162 /* progid string */
4163 if (data->progid_len)
4165 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4166 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4167 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4170 /* string block length */
4171 str_len = 0;
4172 if (clrdata)
4174 str_len += clrdata->name_len + sizeof(WCHAR);
4175 if (clrdata->version_len)
4176 str_len += clrdata->version_len + sizeof(WCHAR);
4178 if (progid_len)
4179 str_len += progid_len + sizeof(WCHAR);
4181 (*index)->data_len += aligned_string_len(str_len);
4182 alias_index->data_len = (*index)->data_len;
4184 /* move to next data record */
4185 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4186 (*module_offset) += module_len + sizeof(WCHAR);
4188 if (clrdata)
4190 (*data_offset) += sizeof(*clrdata);
4191 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4193 (*index) += 1;
4198 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4200 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4201 struct guidsection_header *header;
4202 ULONG module_offset, data_offset;
4203 struct guid_index *index;
4204 ULONG seed;
4206 /* compute section length */
4207 for (i = 0; i < actctx->num_assemblies; i++)
4209 struct assembly *assembly = &actctx->assemblies[i];
4210 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4211 for (j = 0; j < assembly->num_dlls; j++)
4213 struct dll_redirect *dll = &assembly->dlls[j];
4214 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4218 total_len += aligned_string_len(names_len);
4219 total_len += sizeof(*header);
4221 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4222 if (!header) return STATUS_NO_MEMORY;
4224 memset(header, 0, sizeof(*header));
4225 header->magic = GUIDSECTION_MAGIC;
4226 header->size = sizeof(*header);
4227 header->count = 2*class_count;
4228 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4229 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4230 module_offset = sizeof(*header);
4231 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4233 seed = NtGetTickCount();
4234 for (i = 0; i < actctx->num_assemblies; i++)
4236 struct assembly *assembly = &actctx->assemblies[i];
4237 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4238 for (j = 0; j < assembly->num_dlls; j++)
4240 struct dll_redirect *dll = &assembly->dlls[j];
4241 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4245 *section = header;
4247 return STATUS_SUCCESS;
4250 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4252 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4255 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4257 struct comclassredirect_data *comclass;
4258 struct guid_index *index = NULL;
4260 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4262 if (!actctx->comserver_section)
4264 struct guidsection_header *section;
4266 NTSTATUS status = build_comserver_section(actctx, &section);
4267 if (status) return status;
4269 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4270 RtlFreeHeap(GetProcessHeap(), 0, section);
4273 index = find_guid_index(actctx->comserver_section, guid);
4274 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4276 comclass = get_comclass_data(actctx, index);
4278 data->ulDataFormatVersion = 1;
4279 data->lpData = comclass;
4280 /* full length includes string length with nulls */
4281 data->ulLength = comclass->size + comclass->clrdata_len;
4282 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4283 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4284 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4285 data->lpSectionBase = actctx->comserver_section;
4286 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4287 data->hActCtx = NULL;
4289 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4290 data->ulAssemblyRosterIndex = index->rosterindex;
4292 return STATUS_SUCCESS;
4295 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4297 unsigned int i;
4299 for (i = 0; i < entities->num; i++)
4301 struct entity *entity = &entities->base[i];
4302 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4304 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4305 if (entity->u.ifaceps.name)
4306 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4307 *count += 1;
4312 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4313 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4315 unsigned int i;
4317 for (i = 0; i < entities->num; i++)
4319 struct entity *entity = &entities->base[i];
4320 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4322 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4323 UNICODE_STRING str;
4324 ULONG name_len;
4326 if (entity->u.ifaceps.name)
4327 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4328 else
4329 name_len = 0;
4331 /* setup index */
4332 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4333 RtlGUIDFromString(&str, &(*index)->guid);
4334 (*index)->data_offset = *data_offset;
4335 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4336 (*index)->rosterindex = rosterindex;
4338 /* setup data record */
4339 data->size = sizeof(*data);
4340 data->mask = entity->u.ifaceps.mask;
4342 /* proxyStubClsid32 value is only stored for external PS,
4343 if set it's used as iid, otherwise 'iid' attribute value is used */
4344 if (entity->u.ifaceps.ps32)
4346 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4347 RtlGUIDFromString(&str, &data->iid);
4349 else
4350 data->iid = (*index)->guid;
4352 data->nummethods = entity->u.ifaceps.nummethods;
4354 if (entity->u.ifaceps.tlib)
4356 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4357 RtlGUIDFromString(&str, &data->tlbid);
4359 else
4360 memset(&data->tlbid, 0, sizeof(data->tlbid));
4362 if (entity->u.ifaceps.base)
4364 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4365 RtlGUIDFromString(&str, &data->base);
4367 else
4368 memset(&data->base, 0, sizeof(data->base));
4370 data->name_len = name_len;
4371 data->name_offset = data->name_len ? sizeof(*data) : 0;
4373 /* name string */
4374 if (data->name_len)
4376 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4377 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4378 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4381 /* move to next record */
4382 (*index) += 1;
4383 *data_offset += sizeof(*data);
4384 if (data->name_len)
4385 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4390 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4392 unsigned int i, j, total_len = 0, count = 0;
4393 struct guidsection_header *header;
4394 struct guid_index *index;
4395 ULONG data_offset;
4397 /* compute section length */
4398 for (i = 0; i < actctx->num_assemblies; i++)
4400 struct assembly *assembly = &actctx->assemblies[i];
4402 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4403 for (j = 0; j < assembly->num_dlls; j++)
4405 struct dll_redirect *dll = &assembly->dlls[j];
4406 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4410 total_len += sizeof(*header);
4412 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4413 if (!header) return STATUS_NO_MEMORY;
4415 memset(header, 0, sizeof(*header));
4416 header->magic = GUIDSECTION_MAGIC;
4417 header->size = sizeof(*header);
4418 header->count = count;
4419 header->index_offset = sizeof(*header);
4420 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4421 data_offset = header->index_offset + count*sizeof(*index);
4423 for (i = 0; i < actctx->num_assemblies; i++)
4425 struct assembly *assembly = &actctx->assemblies[i];
4427 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4428 for (j = 0; j < assembly->num_dlls; j++)
4430 struct dll_redirect *dll = &assembly->dlls[j];
4431 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4435 *section = header;
4437 return STATUS_SUCCESS;
4440 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4442 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4445 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4447 struct ifacepsredirect_data *iface;
4448 struct guid_index *index = NULL;
4450 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4452 if (!actctx->ifaceps_section)
4454 struct guidsection_header *section;
4456 NTSTATUS status = build_ifaceps_section(actctx, &section);
4457 if (status) return status;
4459 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4460 RtlFreeHeap(GetProcessHeap(), 0, section);
4463 index = find_guid_index(actctx->ifaceps_section, guid);
4464 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4466 iface = get_ifaceps_data(actctx, index);
4468 data->ulDataFormatVersion = 1;
4469 data->lpData = iface;
4470 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4471 data->lpSectionGlobalData = NULL;
4472 data->ulSectionGlobalDataLength = 0;
4473 data->lpSectionBase = actctx->ifaceps_section;
4474 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4475 data->hActCtx = NULL;
4477 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4478 data->ulAssemblyRosterIndex = index->rosterindex;
4480 return STATUS_SUCCESS;
4483 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4485 unsigned int i, j, total_len = 0, count = 0;
4486 struct guidsection_header *header;
4487 struct clrsurrogate_data *data;
4488 struct guid_index *index;
4489 ULONG data_offset;
4491 /* compute section length */
4492 for (i = 0; i < actctx->num_assemblies; i++)
4494 struct assembly *assembly = &actctx->assemblies[i];
4495 for (j = 0; j < assembly->entities.num; j++)
4497 struct entity *entity = &assembly->entities.base[j];
4498 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4500 ULONG len;
4502 total_len += sizeof(*index) + sizeof(*data);
4503 len = wcslen(entity->u.clrsurrogate.name) + 1;
4504 if (entity->u.clrsurrogate.version)
4505 len += wcslen(entity->u.clrsurrogate.version) + 1;
4506 total_len += aligned_string_len(len*sizeof(WCHAR));
4508 count++;
4513 total_len += sizeof(*header);
4515 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4516 if (!header) return STATUS_NO_MEMORY;
4518 memset(header, 0, sizeof(*header));
4519 header->magic = GUIDSECTION_MAGIC;
4520 header->size = sizeof(*header);
4521 header->count = count;
4522 header->index_offset = sizeof(*header);
4523 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4524 data_offset = header->index_offset + count*sizeof(*index);
4526 for (i = 0; i < actctx->num_assemblies; i++)
4528 struct assembly *assembly = &actctx->assemblies[i];
4529 for (j = 0; j < assembly->entities.num; j++)
4531 struct entity *entity = &assembly->entities.base[j];
4532 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4534 ULONG version_len, name_len;
4535 UNICODE_STRING str;
4536 WCHAR *ptrW;
4538 if (entity->u.clrsurrogate.version)
4539 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4540 else
4541 version_len = 0;
4542 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4544 /* setup new index entry */
4545 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4546 RtlGUIDFromString(&str, &index->guid);
4548 index->data_offset = data_offset;
4549 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4550 index->rosterindex = i + 1;
4552 /* setup data */
4553 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4554 data->size = sizeof(*data);
4555 data->res = 0;
4556 data->clsid = index->guid;
4557 data->version_offset = version_len ? data->size : 0;
4558 data->version_len = version_len;
4559 data->name_offset = data->size + version_len;
4560 if (version_len)
4561 data->name_offset += sizeof(WCHAR);
4562 data->name_len = name_len;
4564 /* surrogate name */
4565 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4566 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4567 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4569 /* runtime version */
4570 if (data->version_len)
4572 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4573 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4574 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4577 data_offset += index->data_offset;
4578 index++;
4583 *section = header;
4585 return STATUS_SUCCESS;
4588 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4590 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4593 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4595 struct clrsurrogate_data *surrogate;
4596 struct guid_index *index = NULL;
4598 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4600 if (!actctx->clrsurrogate_section)
4602 struct guidsection_header *section;
4604 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4605 if (status) return status;
4607 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4608 RtlFreeHeap(GetProcessHeap(), 0, section);
4611 index = find_guid_index(actctx->clrsurrogate_section, guid);
4612 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4614 surrogate = get_surrogate_data(actctx, index);
4616 data->ulDataFormatVersion = 1;
4617 data->lpData = surrogate;
4618 /* full length includes string length with nulls */
4619 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4620 if (surrogate->version_len)
4621 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4623 data->lpSectionGlobalData = NULL;
4624 data->ulSectionGlobalDataLength = 0;
4625 data->lpSectionBase = actctx->clrsurrogate_section;
4626 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4627 data->hActCtx = NULL;
4629 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4630 data->ulAssemblyRosterIndex = index->rosterindex;
4632 return STATUS_SUCCESS;
4635 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4637 unsigned int i, j, single_len;
4639 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4640 for (i = 0; i < entities->num; i++)
4642 struct entity *entity = &entities->base[i];
4643 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4645 if (entity->u.comclass.progid)
4647 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4648 *count += 1;
4651 for (j = 0; j < entity->u.comclass.progids.num; j++)
4652 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4654 *total_len += single_len*entity->u.comclass.progids.num;
4655 *count += entity->u.comclass.progids.num;
4660 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4661 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4663 struct progidredirect_data *data;
4664 UNICODE_STRING str;
4665 GUID *guid_ptr;
4666 WCHAR *ptrW;
4668 /* setup new index entry */
4670 /* hash progid name */
4671 RtlInitUnicodeString(&str, progid);
4672 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4674 (*index)->name_offset = *data_offset;
4675 (*index)->name_len = str.Length;
4676 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4677 (*index)->data_len = sizeof(*data);
4678 (*index)->rosterindex = rosterindex;
4680 *data_offset += aligned_string_len(str.MaximumLength);
4682 /* setup data structure */
4683 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4684 data->size = sizeof(*data);
4685 data->reserved = 0;
4686 data->clsid_offset = *global_offset;
4688 /* write progid string */
4689 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4690 memcpy(ptrW, progid, (*index)->name_len);
4691 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4693 /* write guid to global area */
4694 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4695 *guid_ptr = *alias;
4697 /* to next entry */
4698 *global_offset += sizeof(GUID);
4699 *data_offset += data->size;
4700 (*index) += 1;
4703 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4704 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4706 unsigned int i, j;
4708 for (i = 0; i < entities->num; i++)
4710 struct entity *entity = &entities->base[i];
4711 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4713 const struct progids *progids = &entity->u.comclass.progids;
4714 struct comclassredirect_data *comclass;
4715 struct guid_index *guid_index;
4716 UNICODE_STRING str;
4717 GUID clsid;
4719 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4720 RtlGUIDFromString(&str, &clsid);
4722 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4723 comclass = get_comclass_data(actctx, guid_index);
4725 if (entity->u.comclass.progid)
4726 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4727 index, data_offset, global_offset, rosterindex);
4729 for (j = 0; j < progids->num; j++)
4730 write_progid_record(section, progids->progids[j], &comclass->alias,
4731 index, data_offset, global_offset, rosterindex);
4736 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4738 unsigned int i, j, total_len = 0, count = 0;
4739 struct strsection_header *header;
4740 ULONG data_offset, global_offset;
4741 struct string_index *index;
4743 /* compute section length */
4744 for (i = 0; i < actctx->num_assemblies; i++)
4746 struct assembly *assembly = &actctx->assemblies[i];
4748 get_progid_datalen(&assembly->entities, &count, &total_len);
4749 for (j = 0; j < assembly->num_dlls; j++)
4751 struct dll_redirect *dll = &assembly->dlls[j];
4752 get_progid_datalen(&dll->entities, &count, &total_len);
4756 total_len += sizeof(*header);
4758 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4759 if (!header) return STATUS_NO_MEMORY;
4761 memset(header, 0, sizeof(*header));
4762 header->magic = STRSECTION_MAGIC;
4763 header->size = sizeof(*header);
4764 header->count = count;
4765 header->global_offset = header->size;
4766 header->global_len = count*sizeof(GUID);
4767 header->index_offset = header->size + header->global_len;
4769 index = (struct string_index*)((BYTE*)header + header->index_offset);
4770 data_offset = header->index_offset + count*sizeof(*index);
4771 global_offset = header->global_offset;
4773 for (i = 0; i < actctx->num_assemblies; i++)
4775 struct assembly *assembly = &actctx->assemblies[i];
4777 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4778 for (j = 0; j < assembly->num_dlls; j++)
4780 struct dll_redirect *dll = &assembly->dlls[j];
4781 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4785 *section = header;
4787 return STATUS_SUCCESS;
4790 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4792 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4795 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4796 PACTCTX_SECTION_KEYED_DATA data)
4798 struct progidredirect_data *progid;
4799 struct string_index *index;
4801 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4803 if (!actctx->comserver_section)
4805 struct guidsection_header *section;
4807 NTSTATUS status = build_comserver_section(actctx, &section);
4808 if (status) return status;
4810 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4811 RtlFreeHeap(GetProcessHeap(), 0, section);
4814 if (!actctx->progid_section)
4816 struct strsection_header *section;
4818 NTSTATUS status = build_progid_section(actctx, &section);
4819 if (status) return status;
4821 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4822 RtlFreeHeap(GetProcessHeap(), 0, section);
4825 index = find_string_index(actctx->progid_section, name);
4826 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4828 if (data)
4830 progid = get_progid_data(actctx, index);
4832 data->ulDataFormatVersion = 1;
4833 data->lpData = progid;
4834 data->ulLength = progid->size;
4835 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4836 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4837 data->lpSectionBase = actctx->progid_section;
4838 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4839 data->hActCtx = NULL;
4841 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4842 data->ulAssemblyRosterIndex = index->rosterindex;
4845 return STATUS_SUCCESS;
4848 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4849 const UNICODE_STRING *section_name,
4850 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4852 NTSTATUS status;
4854 switch (section_kind)
4856 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4857 status = find_dll_redirection(actctx, section_name, data);
4858 break;
4859 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4860 status = find_window_class(actctx, section_name, data);
4861 break;
4862 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4863 status = find_progid_redirection(actctx, section_name, data);
4864 break;
4865 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4866 FIXME("Unsupported yet section_kind %x\n", section_kind);
4867 return STATUS_SXS_SECTION_NOT_FOUND;
4868 default:
4869 WARN("Unknown section_kind %x\n", section_kind);
4870 return STATUS_SXS_SECTION_NOT_FOUND;
4873 if (status != STATUS_SUCCESS) return status;
4875 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4877 actctx_addref(actctx);
4878 data->hActCtx = actctx;
4880 return STATUS_SUCCESS;
4883 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4884 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4886 NTSTATUS status;
4888 switch (section_kind)
4890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4891 status = find_tlib_redirection(actctx, guid, data);
4892 break;
4893 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4894 status = find_comserver_redirection(actctx, guid, data);
4895 break;
4896 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4897 status = find_cominterface_redirection(actctx, guid, data);
4898 break;
4899 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4900 status = find_clr_surrogate(actctx, guid, data);
4901 break;
4902 default:
4903 WARN("Unknown section_kind %x\n", section_kind);
4904 return STATUS_SXS_SECTION_NOT_FOUND;
4907 if (status != STATUS_SUCCESS) return status;
4909 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4911 actctx_addref(actctx);
4912 data->hActCtx = actctx;
4914 return STATUS_SUCCESS;
4917 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4919 unsigned int i, j;
4921 for (i = 0; i < actctx->num_assemblies; i++)
4923 struct assembly *assembly = &actctx->assemblies[i];
4924 for (j = 0; j < assembly->entities.num; j++)
4926 struct entity *entity = &assembly->entities.base[j];
4927 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4928 !wcscmp( entity->u.settings.name, settings ) &&
4929 !wcscmp( entity->u.settings.ns, ns ))
4930 return entity->u.settings.value;
4933 return NULL;
4936 /* initialize the activation context for the current process */
4937 void actctx_init(void)
4939 ACTCTXW ctx;
4940 HANDLE handle;
4942 ctx.cbSize = sizeof(ctx);
4943 ctx.lpSource = NULL;
4944 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4945 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4946 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4948 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4950 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
4954 /***********************************************************************
4955 * RtlCreateActivationContext (NTDLL.@)
4957 * Create an activation context.
4959 * FIXME: function signature/prototype is wrong
4961 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4963 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4964 const WCHAR *directory = NULL;
4965 ACTIVATION_CONTEXT *actctx;
4966 UNICODE_STRING nameW;
4967 ULONG lang = 0;
4968 NTSTATUS status = STATUS_NO_MEMORY;
4969 HANDLE file = 0;
4970 struct actctx_loader acl;
4972 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4974 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4975 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4976 return STATUS_INVALID_PARAMETER;
4978 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4979 return STATUS_NO_MEMORY;
4981 actctx->magic = ACTCTX_MAGIC;
4982 actctx->ref_count = 1;
4983 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4984 actctx->config.info = NULL;
4985 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4986 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4988 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4990 else
4992 UNICODE_STRING dir;
4993 WCHAR *p;
4994 HMODULE module;
4996 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4997 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4999 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5000 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5001 actctx->appdir.info = dir.Buffer;
5004 nameW.Buffer = NULL;
5006 /* open file only if it's going to be used */
5007 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5008 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5010 WCHAR *source = NULL;
5011 BOOLEAN ret;
5013 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5014 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5016 DWORD dir_len, source_len;
5018 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5019 source_len = wcslen(pActCtx->lpSource);
5020 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5022 status = STATUS_NO_MEMORY;
5023 goto error;
5026 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5027 source[dir_len] = '\\';
5028 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5031 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5032 RtlFreeHeap( GetProcessHeap(), 0, source );
5033 if (!ret)
5035 status = STATUS_NO_SUCH_FILE;
5036 goto error;
5038 status = open_nt_file( &file, &nameW );
5039 if (status)
5041 RtlFreeUnicodeString( &nameW );
5042 goto error;
5046 acl.actctx = actctx;
5047 acl.dependencies = NULL;
5048 acl.num_dependencies = 0;
5049 acl.allocated_dependencies = 0;
5051 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5052 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5054 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5056 /* if we have a resource it's a PE file */
5057 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5059 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5060 pActCtx->lpResourceName, lang );
5061 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5062 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5063 pActCtx->hModule, pActCtx->lpResourceName );
5065 else if (pActCtx->lpSource)
5067 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5068 file, pActCtx->lpResourceName, lang );
5069 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5070 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5071 NULL, pActCtx->lpResourceName );
5073 else status = STATUS_INVALID_PARAMETER;
5075 else
5077 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5080 if (file) NtClose( file );
5081 RtlFreeUnicodeString( &nameW );
5083 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5084 free_depend_manifests( &acl );
5086 if (status == STATUS_SUCCESS) *handle = actctx;
5087 else actctx_release( actctx );
5088 return status;
5090 error:
5091 if (file) NtClose( file );
5092 actctx_release( actctx );
5093 return status;
5097 /***********************************************************************
5098 * RtlAddRefActivationContext (NTDLL.@)
5100 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5102 ACTIVATION_CONTEXT *actctx;
5104 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5108 /******************************************************************
5109 * RtlReleaseActivationContext (NTDLL.@)
5111 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5113 ACTIVATION_CONTEXT *actctx;
5115 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5118 /******************************************************************
5119 * RtlZombifyActivationContext (NTDLL.@)
5121 * FIXME: function prototype might be wrong
5123 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5125 FIXME("%p: stub\n", handle);
5126 return STATUS_NOT_IMPLEMENTED;
5129 /******************************************************************
5130 * RtlActivateActivationContext (NTDLL.@)
5132 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5134 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5136 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5137 return STATUS_NO_MEMORY;
5139 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5140 frame->ActivationContext = handle;
5141 frame->Flags = 0;
5142 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5143 RtlAddRefActivationContext( handle );
5145 *cookie = (ULONG_PTR)frame;
5146 TRACE( "%p cookie=%lx\n", handle, *cookie );
5147 return STATUS_SUCCESS;
5151 /***********************************************************************
5152 * RtlDeactivateActivationContext (NTDLL.@)
5154 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5156 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5158 TRACE( "%x cookie=%lx\n", flags, cookie );
5160 /* find the right frame */
5161 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5162 for (frame = top; frame; frame = frame->Previous)
5163 if ((ULONG_PTR)frame == cookie) break;
5165 if (!frame)
5166 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5168 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5169 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5171 /* pop everything up to and including frame */
5172 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5174 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5176 frame = top->Previous;
5177 RtlReleaseActivationContext( top->ActivationContext );
5178 RtlFreeHeap( GetProcessHeap(), 0, top );
5179 top = frame;
5184 /******************************************************************
5185 * RtlFreeThreadActivationContextStack (NTDLL.@)
5187 void WINAPI RtlFreeThreadActivationContextStack(void)
5189 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5191 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5192 while (frame)
5194 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5195 RtlReleaseActivationContext( frame->ActivationContext );
5196 RtlFreeHeap( GetProcessHeap(), 0, frame );
5197 frame = prev;
5199 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5203 /******************************************************************
5204 * RtlGetActiveActivationContext (NTDLL.@)
5206 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5208 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5210 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5211 RtlAddRefActivationContext( *handle );
5213 else
5214 *handle = 0;
5216 return STATUS_SUCCESS;
5220 /******************************************************************
5221 * RtlIsActivationContextActive (NTDLL.@)
5223 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5225 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5227 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5228 if (frame->ActivationContext == handle) return TRUE;
5229 return FALSE;
5233 /***********************************************************************
5234 * RtlQueryInformationActivationContext (NTDLL.@)
5236 * Get information about an activation context.
5237 * FIXME: function signature/prototype may be wrong
5239 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5240 ULONG class, PVOID buffer,
5241 SIZE_T bufsize, SIZE_T *retlen )
5243 ACTIVATION_CONTEXT *actctx;
5244 NTSTATUS status;
5246 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5247 subinst, class, buffer, bufsize, retlen);
5249 if (retlen) *retlen = 0;
5250 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5252 switch (class)
5254 case ActivationContextBasicInformation:
5256 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5258 if (retlen) *retlen = sizeof(*info);
5259 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5261 info->hActCtx = handle;
5262 info->dwFlags = 0; /* FIXME */
5263 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5265 break;
5267 case ActivationContextDetailedInformation:
5269 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5270 struct assembly *assembly = NULL;
5271 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5272 LPWSTR ptr;
5274 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5276 if (actctx->num_assemblies) assembly = actctx->assemblies;
5278 if (assembly && assembly->manifest.info)
5279 manifest_len = wcslen(assembly->manifest.info) + 1;
5280 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5281 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5282 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5284 if (retlen) *retlen = len;
5285 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5287 acdi->dwFlags = 0;
5288 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5289 acdi->ulAssemblyCount = actctx->num_assemblies;
5290 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5291 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5292 acdi->ulRootConfigurationPathType = actctx->config.type;
5293 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5294 acdi->ulAppDirPathType = actctx->appdir.type;
5295 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5296 ptr = (LPWSTR)(acdi + 1);
5297 if (manifest_len)
5299 acdi->lpRootManifestPath = ptr;
5300 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5301 ptr += manifest_len;
5303 else acdi->lpRootManifestPath = NULL;
5304 if (config_len)
5306 acdi->lpRootConfigurationPath = ptr;
5307 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5308 ptr += config_len;
5310 else acdi->lpRootConfigurationPath = NULL;
5311 if (appdir_len)
5313 acdi->lpAppDirPath = ptr;
5314 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5316 else acdi->lpAppDirPath = NULL;
5318 break;
5320 case AssemblyDetailedInformationInActivationContext:
5322 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5323 struct assembly *assembly;
5324 WCHAR *assembly_id;
5325 DWORD index;
5326 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5327 LPWSTR ptr;
5329 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5330 if (!subinst) return STATUS_INVALID_PARAMETER;
5332 index = *(DWORD*)subinst;
5333 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5335 assembly = &actctx->assemblies[index - 1];
5337 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5338 id_len = wcslen(assembly_id) + 1;
5339 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5341 if (assembly->manifest.info &&
5342 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5343 path_len = wcslen(assembly->manifest.info) + 1;
5345 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5347 if (retlen) *retlen = len;
5348 if (!buffer || bufsize < len)
5350 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5351 return STATUS_BUFFER_TOO_SMALL;
5354 afdi->ulFlags = 0; /* FIXME */
5355 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5356 afdi->ulManifestPathType = assembly->manifest.type;
5357 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5358 /* FIXME afdi->liManifestLastWriteTime = 0; */
5359 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5360 afdi->ulPolicyPathLength = 0;
5361 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5362 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5363 afdi->ulManifestVersionMajor = 1;
5364 afdi->ulManifestVersionMinor = 0;
5365 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5366 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5367 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5368 ptr = (LPWSTR)(afdi + 1);
5369 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5370 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5371 ptr += id_len;
5372 if (path_len)
5374 afdi->lpAssemblyManifestPath = ptr;
5375 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5376 ptr += path_len;
5377 } else afdi->lpAssemblyManifestPath = NULL;
5378 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5379 if (ad_len)
5381 afdi->lpAssemblyDirectoryName = ptr;
5382 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5384 else afdi->lpAssemblyDirectoryName = NULL;
5385 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5387 break;
5389 case FileInformationInAssemblyOfAssemblyInActivationContext:
5391 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5392 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5393 struct assembly *assembly;
5394 struct dll_redirect *dll;
5395 SIZE_T len, dll_len = 0;
5396 LPWSTR ptr;
5398 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5399 if (!acqi) return STATUS_INVALID_PARAMETER;
5401 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5402 return STATUS_INVALID_PARAMETER;
5403 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5405 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5406 return STATUS_INVALID_PARAMETER;
5407 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5409 if (dll->name) dll_len = wcslen(dll->name) + 1;
5410 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5412 if (!buffer || bufsize < len)
5414 if (retlen) *retlen = len;
5415 return STATUS_BUFFER_TOO_SMALL;
5417 if (retlen) *retlen = 0; /* yes that's what native does !! */
5418 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5419 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5420 afdi->ulPathLength = 0; /* FIXME */
5421 ptr = (LPWSTR)(afdi + 1);
5422 if (dll_len)
5424 afdi->lpFileName = ptr;
5425 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5426 } else afdi->lpFileName = NULL;
5427 afdi->lpFilePath = NULL; /* FIXME */
5429 break;
5431 case CompatibilityInformationInActivationContext:
5433 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5434 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5435 struct assembly *assembly = NULL;
5436 ULONG num_compat_contexts = 0, n;
5437 SIZE_T len;
5439 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5441 if (actctx->num_assemblies) assembly = actctx->assemblies;
5443 if (assembly)
5444 num_compat_contexts = assembly->num_compat_contexts;
5445 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5447 if (retlen) *retlen = len;
5448 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5450 *acci = num_compat_contexts;
5451 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5452 for (n = 0; n < num_compat_contexts; ++n)
5454 elements[n] = assembly->compat_contexts[n];
5457 break;
5459 case RunlevelInformationInActivationContext:
5461 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5462 struct assembly *assembly;
5463 SIZE_T len;
5465 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5467 len = sizeof(*acrli);
5468 if (retlen) *retlen = len;
5469 if (!buffer || bufsize < len)
5470 return STATUS_BUFFER_TOO_SMALL;
5472 assembly = actctx->assemblies;
5474 acrli->ulFlags = 0;
5475 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5476 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5478 break;
5480 default:
5481 FIXME( "class %u not implemented\n", class );
5482 return STATUS_NOT_IMPLEMENTED;
5484 return STATUS_SUCCESS;
5487 /***********************************************************************
5488 * RtlFindActivationContextSectionString (NTDLL.@)
5490 * Find information about a string in an activation context.
5491 * FIXME: function signature/prototype may be wrong
5493 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5494 const UNICODE_STRING *section_name, PVOID ptr )
5496 PACTCTX_SECTION_KEYED_DATA data = ptr;
5497 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5499 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5500 debugstr_us(section_name), data);
5502 if (guid)
5504 FIXME("expected guid == NULL\n");
5505 return STATUS_INVALID_PARAMETER;
5507 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5509 FIXME("unknown flags %08x\n", flags);
5510 return STATUS_INVALID_PARAMETER;
5512 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5513 !section_name || !section_name->Buffer)
5515 WARN("invalid parameter\n");
5516 return STATUS_INVALID_PARAMETER;
5519 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5521 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5522 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5525 if (status != STATUS_SUCCESS)
5526 status = find_string( process_actctx, section_kind, section_name, flags, data );
5528 return status;
5531 /***********************************************************************
5532 * RtlFindActivationContextSectionGuid (NTDLL.@)
5534 * Find information about a GUID in an activation context.
5535 * FIXME: function signature/prototype may be wrong
5537 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5538 const GUID *guid, void *ptr )
5540 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5541 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5543 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5545 if (extguid)
5547 FIXME("expected extguid == NULL\n");
5548 return STATUS_INVALID_PARAMETER;
5551 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5553 FIXME("unknown flags %08x\n", flags);
5554 return STATUS_INVALID_PARAMETER;
5557 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5558 return STATUS_INVALID_PARAMETER;
5560 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5562 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5563 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5566 if (status != STATUS_SUCCESS)
5567 status = find_guid( process_actctx, section_kind, guid, flags, data );
5569 return status;
5573 /***********************************************************************
5574 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5576 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5577 const WCHAR *settings, WCHAR *buffer,
5578 SIZE_T size, SIZE_T *written )
5580 ACTIVATION_CONTEXT *actctx;
5581 const WCHAR *res;
5583 if (flags)
5585 WARN( "unknown flags %08x\n", flags );
5586 return STATUS_INVALID_PARAMETER;
5589 if (ns)
5591 if (wcscmp( ns, windowsSettings2005NSW ) &&
5592 wcscmp( ns, windowsSettings2011NSW ) &&
5593 wcscmp( ns, windowsSettings2016NSW ) &&
5594 wcscmp( ns, windowsSettings2017NSW ))
5595 return STATUS_INVALID_PARAMETER;
5597 else ns = windowsSettings2005NSW;
5599 if (!handle) handle = process_actctx;
5600 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5602 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5604 if (written) *written = wcslen(res) + 1;
5605 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5606 wcscpy( buffer, res );
5607 return STATUS_SUCCESS;