ntdll: Store the default process activation context into the PEB.
[wine.git] / dlls / ntdll / actctx.c
blob17f9cad0846c47ff478a9626010c82e174e1a676
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"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 /* from oaidl.h */
62 typedef enum tagLIBFLAGS {
63 LIBFLAG_FRESTRICTED = 0x1,
64 LIBFLAG_FCONTROL = 0x2,
65 LIBFLAG_FHIDDEN = 0x4,
66 LIBFLAG_FHASDISKIMAGE = 0x8
67 } LIBFLAGS;
69 /* from oleidl.idl */
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE = 0x1,
73 OLEMISC_ONLYICONIC = 0x2,
74 OLEMISC_INSERTNOTREPLACE = 0x4,
75 OLEMISC_STATIC = 0x8,
76 OLEMISC_CANTLINKINSIDE = 0x10,
77 OLEMISC_CANLINKBYOLE1 = 0x20,
78 OLEMISC_ISLINKOBJECT = 0x40,
79 OLEMISC_INSIDEOUT = 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
82 OLEMISC_INVISIBLEATRUNTIME = 0x400,
83 OLEMISC_ALWAYSRUN = 0x800,
84 OLEMISC_ACTSLIKEBUTTON = 0x1000,
85 OLEMISC_ACTSLIKELABEL = 0x2000,
86 OLEMISC_NOUIACTIVATE = 0x4000,
87 OLEMISC_ALIGNABLE = 0x8000,
88 OLEMISC_SIMPLEFRAME = 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
90 OLEMISC_IMEMODE = 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
92 OLEMISC_WANTSTOMENUMERGE = 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
94 } OLEMISC;
96 #define MAX_NAMESPACES 64
98 typedef struct
100 const WCHAR *ptr;
101 unsigned int len;
102 } xmlstr_t;
104 struct xml_elem
106 xmlstr_t name;
107 xmlstr_t ns;
108 int ns_pos;
111 struct xml_attr
113 xmlstr_t name;
114 xmlstr_t value;
117 typedef struct
119 const WCHAR *ptr;
120 const WCHAR *end;
121 struct xml_attr namespaces[MAX_NAMESPACES];
122 int ns_pos;
123 BOOL error;
124 } xmlbuf_t;
126 struct file_info
128 ULONG type;
129 WCHAR *info;
132 struct assembly_version
134 USHORT major;
135 USHORT minor;
136 USHORT build;
137 USHORT revision;
140 struct assembly_identity
142 WCHAR *name;
143 WCHAR *arch;
144 WCHAR *public_key;
145 WCHAR *language;
146 WCHAR *type;
147 struct assembly_version version;
148 BOOL optional;
149 BOOL delayed;
152 struct strsection_header
154 DWORD magic;
155 ULONG size;
156 DWORD unk1[3];
157 ULONG count;
158 ULONG index_offset;
159 DWORD unk2[2];
160 ULONG global_offset;
161 ULONG global_len;
164 struct string_index
166 ULONG hash; /* key string hash */
167 ULONG name_offset;
168 ULONG name_len;
169 ULONG data_offset; /* redirect data offset */
170 ULONG data_len;
171 ULONG rosterindex;
174 struct guidsection_header
176 DWORD magic;
177 ULONG size;
178 DWORD unk[3];
179 ULONG count;
180 ULONG index_offset;
181 DWORD unk2;
182 ULONG names_offset;
183 ULONG names_len;
186 struct guid_index
188 GUID guid;
189 ULONG data_offset;
190 ULONG data_len;
191 ULONG rosterindex;
194 struct wndclass_redirect_data
196 ULONG size;
197 DWORD res;
198 ULONG name_len;
199 ULONG name_offset; /* versioned name offset */
200 ULONG module_len;
201 ULONG module_offset;/* container name offset */
204 struct dllredirect_data
206 ULONG size;
207 ULONG unk;
208 DWORD res[3];
211 struct tlibredirect_data
213 ULONG size;
214 DWORD res;
215 ULONG name_len;
216 ULONG name_offset;
217 LANGID langid;
218 WORD flags;
219 ULONG help_len;
220 ULONG help_offset;
221 WORD major_version;
222 WORD minor_version;
225 enum comclass_threadingmodel
227 ThreadingModel_Apartment = 1,
228 ThreadingModel_Free = 2,
229 ThreadingModel_No = 3,
230 ThreadingModel_Both = 4,
231 ThreadingModel_Neutral = 5
234 enum comclass_miscfields
236 MiscStatus = 1,
237 MiscStatusIcon = 2,
238 MiscStatusContent = 4,
239 MiscStatusThumbnail = 8,
240 MiscStatusDocPrint = 16
243 struct comclassredirect_data
245 ULONG size;
246 BYTE res;
247 BYTE miscmask;
248 BYTE res1[2];
249 DWORD model;
250 GUID clsid;
251 GUID alias;
252 GUID clsid2;
253 GUID tlbid;
254 ULONG name_len;
255 ULONG name_offset;
256 ULONG progid_len;
257 ULONG progid_offset;
258 ULONG clrdata_len;
259 ULONG clrdata_offset;
260 DWORD miscstatus;
261 DWORD miscstatuscontent;
262 DWORD miscstatusthumbnail;
263 DWORD miscstatusicon;
264 DWORD miscstatusdocprint;
267 enum ifaceps_mask
269 NumMethods = 1,
270 BaseIface = 2
273 struct ifacepsredirect_data
275 ULONG size;
276 DWORD mask;
277 GUID iid;
278 ULONG nummethods;
279 GUID tlbid;
280 GUID base;
281 ULONG name_len;
282 ULONG name_offset;
285 struct clrsurrogate_data
287 ULONG size;
288 DWORD res;
289 GUID clsid;
290 ULONG version_offset;
291 ULONG version_len;
292 ULONG name_offset;
293 ULONG name_len;
296 struct clrclass_data
298 ULONG size;
299 DWORD res[2];
300 ULONG module_len;
301 ULONG module_offset;
302 ULONG name_len;
303 ULONG name_offset;
304 ULONG version_len;
305 ULONG version_offset;
306 DWORD res2[2];
309 struct progidredirect_data
311 ULONG size;
312 DWORD reserved;
313 ULONG clsid_offset;
318 Sections structure.
320 Sections are accessible by string or guid key, that defines two types of sections.
321 All sections of each type have same magic value and header structure, index
322 data could be of two possible types too. So every string based section uses
323 the same index format, same applies to guid sections - they share same guid index
324 format.
326 - window class redirection section is a plain buffer with following format:
328 <section header>
329 <index[]>
330 <data[]> --- <original name>
331 <redirect data>
332 <versioned name>
333 <module name>
335 Header is fixed length structure - struct strsection_header,
336 contains redirected classes count;
338 Index is an array of fixed length index records, each record is
339 struct string_index.
341 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
343 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
344 others are relative to section itself.
346 - dll redirect section format:
348 <section header>
349 <index[]>
350 <data[]> --- <dll name>
351 <data>
353 This section doesn't seem to carry any payload data except dll names.
355 - typelib section format:
357 <section header>
358 <module names[]>
359 <index[]>
360 <data[]> --- <data>
361 <helpstring>
363 Header is fixed length, index is an array of fixed length 'struct guid_index'.
364 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
365 4-bytes aligned as a whole.
367 Module name offsets are relative to section, helpstring offset is relative to data
368 structure itself.
370 - comclass section format:
372 <section header>
373 <module names[]>
374 <index[]>
375 <data[]> --- <data> --- <data>
376 <progid> <clrdata>
377 <name>
378 <version>
379 <progid>
381 This section uses two index records per comclass, one entry contains original guid
382 as specified by context, another one has a generated guid. Index and strings handling
383 is similar to typelib sections.
385 For CLR classes additional data is stored after main COM class data, it contains
386 class name and runtime version string, see 'struct clrclass_data'.
388 Module name offsets are relative to section, progid offset is relative to data
389 structure itself.
391 - COM interface section format:
393 <section header>
394 <index[]>
395 <data[]> --- <data>
396 <name>
398 Interface section contains data for proxy/stubs and external proxy/stubs. External
399 ones are defined at assembly level, so this section has no module information.
400 All records are indexed with 'iid' value from manifest. There an exception for
401 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
402 redirect data, but index is still 'iid' from manifest.
404 Interface name offset is relative to data structure itself.
406 - CLR surrogates section format:
408 <section header>
409 <index[]>
410 <data[]> --- <data>
411 <name>
412 <version>
414 There's nothing special about this section, same way to store strings is used,
415 no modules part as it belongs to assembly level, not a file.
417 - ProgID section format:
419 <section header>
420 <guids[]>
421 <index[]>
422 <data[]> --- <progid>
423 <data>
425 This sections uses generated alias guids from COM server section. This way
426 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
427 is stored too, aligned.
430 struct progids
432 WCHAR **progids;
433 unsigned int num;
434 unsigned int allocated;
437 struct entity
439 DWORD kind;
440 union
442 struct
444 WCHAR *tlbid;
445 WCHAR *helpdir;
446 WORD flags;
447 WORD major;
448 WORD minor;
449 } typelib;
450 struct
452 WCHAR *clsid;
453 WCHAR *tlbid;
454 WCHAR *progid;
455 WCHAR *name; /* clrClass: class name */
456 WCHAR *version; /* clrClass: CLR runtime version */
457 DWORD model;
458 DWORD miscstatus;
459 DWORD miscstatuscontent;
460 DWORD miscstatusthumbnail;
461 DWORD miscstatusicon;
462 DWORD miscstatusdocprint;
463 struct progids progids;
464 } comclass;
465 struct {
466 WCHAR *iid;
467 WCHAR *base;
468 WCHAR *tlib;
469 WCHAR *name;
470 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
471 DWORD mask;
472 ULONG nummethods;
473 } ifaceps;
474 struct
476 WCHAR *name;
477 BOOL versioned;
478 } class;
479 struct
481 WCHAR *name;
482 WCHAR *clsid;
483 WCHAR *version;
484 } clrsurrogate;
485 struct
487 WCHAR *name;
488 WCHAR *value;
489 WCHAR *ns;
490 } settings;
491 } u;
494 struct entity_array
496 struct entity *base;
497 unsigned int num;
498 unsigned int allocated;
501 struct dll_redirect
503 WCHAR *name;
504 WCHAR *hash;
505 struct entity_array entities;
508 enum assembly_type
510 APPLICATION_MANIFEST,
511 ASSEMBLY_MANIFEST,
512 ASSEMBLY_SHARED_MANIFEST,
515 struct assembly
517 enum assembly_type type;
518 struct assembly_identity id;
519 struct file_info manifest;
520 WCHAR *directory;
521 BOOL no_inherit;
522 struct dll_redirect *dlls;
523 unsigned int num_dlls;
524 unsigned int allocated_dlls;
525 struct entity_array entities;
526 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
527 ULONG num_compat_contexts;
528 ACTCTX_REQUESTED_RUN_LEVEL run_level;
529 ULONG ui_access;
532 enum context_sections
534 WINDOWCLASS_SECTION = 1,
535 DLLREDIRECT_SECTION = 2,
536 TLIBREDIRECT_SECTION = 4,
537 SERVERREDIRECT_SECTION = 8,
538 IFACEREDIRECT_SECTION = 16,
539 CLRSURROGATES_SECTION = 32,
540 PROGIDREDIRECT_SECTION = 64
543 typedef struct _ACTIVATION_CONTEXT
545 ULONG magic;
546 int ref_count;
547 struct file_info config;
548 struct file_info appdir;
549 struct assembly *assemblies;
550 unsigned int num_assemblies;
551 unsigned int allocated_assemblies;
552 /* section data */
553 DWORD sections;
554 struct strsection_header *wndclass_section;
555 struct strsection_header *dllredirect_section;
556 struct strsection_header *progid_section;
557 struct guidsection_header *tlib_section;
558 struct guidsection_header *comserver_section;
559 struct guidsection_header *ifaceps_section;
560 struct guidsection_header *clrsurrogate_section;
561 } ACTIVATION_CONTEXT;
563 struct actctx_loader
565 ACTIVATION_CONTEXT *actctx;
566 struct assembly_identity *dependencies;
567 unsigned int num_dependencies;
568 unsigned int allocated_dependencies;
571 static const xmlstr_t empty_xmlstr;
573 #ifdef __i386__
574 static const WCHAR current_archW[] = {'x','8','6',0};
575 #elif defined __x86_64__
576 static const WCHAR current_archW[] = {'a','m','d','6','4',0};
577 #elif defined __arm__
578 static const WCHAR current_archW[] = {'a','r','m',0};
579 #elif defined __aarch64__
580 static const WCHAR current_archW[] = {'a','r','m','6','4',0};
581 #else
582 static const WCHAR current_archW[] = {'n','o','n','e',0};
583 #endif
585 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};
586 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};
587 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};
588 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
589 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
590 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
591 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
592 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
593 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
594 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};
595 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};
596 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
597 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
598 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
599 static const WCHAR fileW[] = {'f','i','l','e',0};
600 static const WCHAR hashW[] = {'h','a','s','h',0};
601 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
602 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
603 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
604 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
606 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
607 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
608 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
609 static const WCHAR iidW[] = {'i','i','d',0};
610 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
611 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
612 static const WCHAR nameW[] = {'n','a','m','e',0};
613 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
614 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
615 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
616 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
617 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};
618 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
619 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
620 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
621 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
622 static const WCHAR typeW[] = {'t','y','p','e',0};
623 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
624 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
625 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
626 static const WCHAR yesW[] = {'y','e','s',0};
627 static const WCHAR noW[] = {'n','o',0};
628 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
629 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
630 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
631 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
632 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
633 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
634 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
635 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
636 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
637 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
638 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
639 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
640 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
641 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
642 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
643 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
645 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
646 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
647 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
648 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
649 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
650 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
651 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
652 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};
653 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
654 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
655 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
656 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
657 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
658 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
659 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
660 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
661 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};
662 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
663 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
664 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
665 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};
666 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
668 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
669 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};
670 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
671 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
672 static const WCHAR IdW[] = {'I','d',0};
673 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};
674 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
675 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
676 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
677 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
678 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
679 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
680 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};
681 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};
682 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};
683 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};
684 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};
685 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
686 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
687 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
688 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};
689 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
690 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
691 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};
692 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};
694 struct olemisc_entry
696 const WCHAR *name;
697 OLEMISC value;
700 static const struct olemisc_entry olemisc_values[] =
702 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
703 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
704 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
705 { alignableW, OLEMISC_ALIGNABLE },
706 { alwaysrunW, OLEMISC_ALWAYSRUN },
707 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
708 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
709 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
710 { imemodeW, OLEMISC_IMEMODE },
711 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
712 { insideoutW, OLEMISC_INSIDEOUT },
713 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
714 { islinkobjectW, OLEMISC_ISLINKOBJECT },
715 { nouiactivateW, OLEMISC_NOUIACTIVATE },
716 { onlyiconicW, OLEMISC_ONLYICONIC },
717 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
718 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
719 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
720 { simpleframeW, OLEMISC_SIMPLEFRAME },
721 { staticW, OLEMISC_STATIC },
722 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
723 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
726 static const WCHAR xmlW[] = {'?','x','m','l',0};
727 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
728 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
729 static const WCHAR wildcardW[] = {'*',0};
731 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
732 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
734 static WCHAR *strdupW(const WCHAR* str)
736 WCHAR* ptr;
738 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
739 return NULL;
740 return strcpyW(ptr, str);
743 static WCHAR *xmlstrdupW(const xmlstr_t* str)
745 WCHAR *strW;
747 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
749 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
750 strW[str->len] = 0;
752 return strW;
755 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
757 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
760 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
762 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
765 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
767 return xmlstr_cmp( &attr->name, str );
770 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
772 return (elem1->name.len == elem2->name.len &&
773 elem1->ns.len == elem2->ns.len &&
774 !strncmpW( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
775 !strncmpW( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
778 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
780 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
781 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
782 if (!strcmpW( namespace, asmv1W ))
784 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
785 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
787 else if (!strcmpW( namespace, asmv2W ))
789 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
791 return FALSE;
794 static inline BOOL isxmlspace( WCHAR ch )
796 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
799 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
801 return debugstr_wn(str->ptr, str->len);
804 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
806 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
807 debugstr_wn( elem->ns.ptr, elem->ns.len ));
810 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
812 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
813 debugstr_wn( attr->value.ptr, attr->value.len ));
816 static inline const char* debugstr_version(const struct assembly_version *ver)
818 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
821 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
823 NTSTATUS status;
824 ULONG_PTR magic;
825 LDR_MODULE *pldr;
827 LdrLockLoaderLock(0, NULL, &magic);
828 status = LdrFindEntryForAddress( module, &pldr );
829 if (status == STATUS_SUCCESS)
831 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
832 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
834 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
835 str->Length = pldr->FullDllName.Length;
836 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
838 else status = STATUS_NO_MEMORY;
840 LdrUnlockLoaderLock(0, magic);
841 return status;
844 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
846 struct assembly *assembly;
848 if (actctx->num_assemblies == actctx->allocated_assemblies)
850 void *ptr;
851 unsigned int new_count;
852 if (actctx->assemblies)
854 new_count = actctx->allocated_assemblies * 2;
855 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
856 actctx->assemblies, new_count * sizeof(*assembly) );
858 else
860 new_count = 4;
861 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
863 if (!ptr) return NULL;
864 actctx->assemblies = ptr;
865 actctx->allocated_assemblies = new_count;
868 assembly = &actctx->assemblies[actctx->num_assemblies++];
869 assembly->type = at;
870 return assembly;
873 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
875 if (assembly->num_dlls == assembly->allocated_dlls)
877 void *ptr;
878 unsigned int new_count;
879 if (assembly->dlls)
881 new_count = assembly->allocated_dlls * 2;
882 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
883 assembly->dlls, new_count * sizeof(*assembly->dlls) );
885 else
887 new_count = 4;
888 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
890 if (!ptr) return NULL;
891 assembly->dlls = ptr;
892 assembly->allocated_dlls = new_count;
894 return &assembly->dlls[assembly->num_dlls++];
897 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
899 void *ptr;
900 if (assembly->num_compat_contexts)
902 unsigned int new_count = assembly->num_compat_contexts + 1;
903 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
904 assembly->compat_contexts,
905 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
907 else
909 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
911 if (!ptr) return NULL;
912 assembly->compat_contexts = ptr;
913 return &assembly->compat_contexts[assembly->num_compat_contexts++];
916 static void free_assembly_identity(struct assembly_identity *ai)
918 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
919 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
920 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
921 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
922 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
925 static struct entity* add_entity(struct entity_array *array, DWORD kind)
927 struct entity* entity;
929 if (array->num == array->allocated)
931 void *ptr;
932 unsigned int new_count;
933 if (array->base)
935 new_count = array->allocated * 2;
936 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
937 array->base, new_count * sizeof(*array->base) );
939 else
941 new_count = 4;
942 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
944 if (!ptr) return NULL;
945 array->base = ptr;
946 array->allocated = new_count;
948 entity = &array->base[array->num++];
949 entity->kind = kind;
950 return entity;
953 static void free_entity_array(struct entity_array *array)
955 unsigned int i, j;
956 for (i = 0; i < array->num; i++)
958 struct entity *entity = &array->base[i];
959 switch (entity->kind)
961 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
962 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
963 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
964 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
965 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
966 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
967 for (j = 0; j < entity->u.comclass.progids.num; j++)
968 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
969 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
970 break;
971 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
972 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
973 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
974 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
975 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
976 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
977 break;
978 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
979 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
980 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
981 break;
982 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
983 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
984 break;
985 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
986 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
987 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
988 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
989 break;
990 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
991 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
992 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
993 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
994 break;
995 default:
996 FIXME("Unknown entity kind %d\n", entity->kind);
999 RtlFreeHeap( GetProcessHeap(), 0, array->base );
1002 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
1004 if (!str1) return !str2;
1005 return str2 && !strcmpiW( str1, str2 );
1008 static BOOL is_matching_identity( const struct assembly_identity *id1,
1009 const struct assembly_identity *id2 )
1011 if (!is_matching_string( id1->name, id2->name )) return FALSE;
1012 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1013 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1015 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
1017 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
1018 return FALSE;
1020 if (id1->version.major != id2->version.major) return FALSE;
1021 if (id1->version.minor != id2->version.minor) return FALSE;
1022 if (id1->version.build > id2->version.build) return FALSE;
1023 if (id1->version.build == id2->version.build &&
1024 id1->version.revision > id2->version.revision) return FALSE;
1025 return TRUE;
1028 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
1029 struct assembly_identity* ai)
1031 unsigned int i;
1033 /* check if we already have that assembly */
1035 for (i = 0; i < acl->actctx->num_assemblies; i++)
1036 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1038 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1039 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1040 ai->version.build, ai->version.revision );
1041 return TRUE;
1044 for (i = 0; i < acl->num_dependencies; i++)
1045 if (is_matching_identity( ai, &acl->dependencies[i] ))
1047 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1048 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1049 ai->version.build, ai->version.revision );
1050 return TRUE;
1053 if (acl->num_dependencies == acl->allocated_dependencies)
1055 void *ptr;
1056 unsigned int new_count;
1057 if (acl->dependencies)
1059 new_count = acl->allocated_dependencies * 2;
1060 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
1061 new_count * sizeof(acl->dependencies[0]));
1063 else
1065 new_count = 4;
1066 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1068 if (!ptr) return FALSE;
1069 acl->dependencies = ptr;
1070 acl->allocated_dependencies = new_count;
1072 acl->dependencies[acl->num_dependencies++] = *ai;
1074 return TRUE;
1077 static void free_depend_manifests(struct actctx_loader* acl)
1079 unsigned int i;
1080 for (i = 0; i < acl->num_dependencies; i++)
1081 free_assembly_identity(&acl->dependencies[i]);
1082 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1085 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1087 static const WCHAR undW[] = {'_',0};
1088 static const WCHAR noneW[] = {'n','o','n','e',0};
1089 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1091 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1092 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1093 const WCHAR *lang = ai->language ? ai->language : noneW;
1094 const WCHAR *name = ai->name ? ai->name : noneW;
1095 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1096 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1097 WCHAR *ret;
1099 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1101 strcpyW( ret, arch );
1102 strcatW( ret, undW );
1103 strcatW( ret, name );
1104 strcatW( ret, undW );
1105 strcatW( ret, key );
1106 strcatW( ret, undW );
1107 sprintfW( ret + strlenW(ret), version_formatW,
1108 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1109 strcatW( ret, undW );
1110 strcatW( ret, lang );
1111 strcatW( ret, undW );
1112 strcatW( ret, mskeyW );
1113 return ret;
1116 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1118 WCHAR *p = buffer;
1120 if (!str) return;
1121 strcatW( buffer, prefix );
1122 p += strlenW(p);
1123 *p++ = '"';
1124 strcpyW( p, str );
1125 p += strlenW(p);
1126 *p++ = '"';
1127 *p = 0;
1130 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1132 static const WCHAR archW[] =
1133 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1134 static const WCHAR public_keyW[] =
1135 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1136 static const WCHAR typeW[] =
1137 {',','t','y','p','e','=',0};
1138 static const WCHAR versionW[] =
1139 {',','v','e','r','s','i','o','n','=',0};
1141 WCHAR version[64], *ret;
1142 SIZE_T size = 0;
1144 sprintfW( version, version_formatW,
1145 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1146 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1147 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1148 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1149 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1150 size += strlenW(versionW) + strlenW(version) + 2;
1152 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1153 return NULL;
1155 if (ai->name) strcpyW( ret, ai->name );
1156 else *ret = 0;
1157 append_string( ret, archW, ai->arch );
1158 append_string( ret, public_keyW, ai->public_key );
1159 append_string( ret, typeW, ai->type );
1160 append_string( ret, versionW, version );
1161 return ret;
1164 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1166 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1168 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1169 __TRY
1171 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1173 __EXCEPT_PAGE_FAULT
1176 __ENDTRY
1177 return ret;
1180 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1182 interlocked_xchg_add( &actctx->ref_count, 1 );
1185 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1187 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1189 unsigned int i, j;
1191 for (i = 0; i < actctx->num_assemblies; i++)
1193 struct assembly *assembly = &actctx->assemblies[i];
1194 for (j = 0; j < assembly->num_dlls; j++)
1196 struct dll_redirect *dll = &assembly->dlls[j];
1197 free_entity_array( &dll->entities );
1198 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1199 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1201 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1202 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1203 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1204 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1205 free_entity_array( &assembly->entities );
1206 free_assembly_identity(&assembly->id);
1208 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1209 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1210 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1211 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1212 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1213 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1214 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1215 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1216 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1217 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1218 actctx->magic = 0;
1219 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1223 static BOOL set_error( xmlbuf_t *xmlbuf )
1225 xmlbuf->error = TRUE;
1226 return FALSE;
1229 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1231 const int len = strlenW( xmlnsW );
1232 if (attr->name.len < len) return FALSE;
1233 if (strncmpW( attr->name.ptr, xmlnsW, len )) return FALSE;
1234 return (attr->name.len == len || attr->name.ptr[len] == ':');
1237 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1239 const int len = strlenW( xmlnsW );
1240 struct xml_attr *ns;
1242 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1244 FIXME( "too many namespaces in manifest\n" );
1245 set_error( xmlbuf );
1246 return;
1248 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1249 ns->value = attr->value;
1250 if (attr->name.len > len)
1252 ns->name.ptr = attr->name.ptr + len + 1;
1253 ns->name.len = attr->name.len - len - 1;
1255 else ns->name = empty_xmlstr;
1258 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1260 int i;
1262 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1264 if (xmlbuf->namespaces[i].name.len == name->len &&
1265 !strncmpW( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1266 return xmlbuf->namespaces[i].value;
1268 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1269 return empty_xmlstr;
1272 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1274 const WCHAR* ptr;
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 attr->value.ptr = ++ptr;
1323 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1325 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1326 if (!ptr)
1328 xmlbuf->ptr = xmlbuf->end;
1329 return set_error( xmlbuf );
1332 attr->value.len = ptr - attr->value.ptr;
1333 xmlbuf->ptr = ptr + 1;
1334 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1336 return set_error( xmlbuf );
1339 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1341 const WCHAR* ptr = xmlbuf->ptr;
1343 elem->ns = empty_xmlstr;
1344 elem->name.ptr = ptr;
1345 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1347 if (*ptr == ':')
1349 elem->ns.ptr = elem->name.ptr;
1350 elem->ns.len = ptr - elem->ns.ptr;
1351 elem->name.ptr = ptr + 1;
1353 ptr++;
1355 elem->name.len = ptr - elem->name.ptr;
1356 xmlbuf->ptr = ptr;
1359 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1361 const WCHAR* ptr;
1362 struct xml_attr attr;
1363 xmlbuf_t attr_buf;
1364 BOOL end = FALSE;
1366 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1368 if (xmlbuf->error) return FALSE;
1370 for (;;)
1372 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1373 if (!ptr)
1375 xmlbuf->ptr = xmlbuf->end;
1376 return set_error( xmlbuf );
1378 ptr++;
1379 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1381 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1382 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1384 if (ptr + 3 > xmlbuf->end)
1386 xmlbuf->ptr = xmlbuf->end;
1387 return set_error( xmlbuf );
1389 xmlbuf->ptr = ptr + 3;
1391 else break;
1394 xmlbuf->ptr = ptr;
1395 /* check for element terminating the parent element */
1396 if (ptr < xmlbuf->end && *ptr == '/')
1398 xmlbuf->ptr++;
1399 read_xml_elem( xmlbuf, elem );
1400 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1401 if (!xml_name_cmp( elem, parent ))
1403 ERR( "wrong closing element %s for %s\n",
1404 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1405 return set_error( xmlbuf );
1407 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1408 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1409 return FALSE;
1412 read_xml_elem( xmlbuf, elem );
1414 /* parse namespace attributes */
1415 attr_buf = *xmlbuf;
1416 while (next_xml_attr( &attr_buf, &attr, &end ))
1418 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1420 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1421 elem->ns_pos = xmlbuf->ns_pos;
1423 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1425 return set_error( xmlbuf );
1428 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1430 /* FIXME: parse attributes */
1431 const WCHAR *ptr;
1433 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1435 if (ptr[0] == '?' && ptr[1] == '>')
1437 xmlbuf->ptr = ptr + 2;
1438 return TRUE;
1441 return FALSE;
1444 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1446 const WCHAR *ptr;
1448 if (xmlbuf->error) return FALSE;
1450 if (!(ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr))) return set_error( xmlbuf );
1452 content->ptr = xmlbuf->ptr;
1453 content->len = ptr - xmlbuf->ptr;
1454 xmlbuf->ptr = ptr;
1456 return TRUE;
1459 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1461 unsigned int ver[4];
1462 unsigned int pos;
1463 const WCHAR *curr;
1465 /* major.minor.build.revision */
1466 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1467 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1469 if (*curr >= '0' && *curr <= '9')
1471 ver[pos] = ver[pos] * 10 + *curr - '0';
1472 if (ver[pos] >= 0x10000) goto error;
1474 else if (*curr == '.')
1476 if (++pos >= 4) goto error;
1478 else goto error;
1480 version->major = ver[0];
1481 version->minor = ver[1];
1482 version->build = ver[2];
1483 version->revision = ver[3];
1484 return TRUE;
1486 error:
1487 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1488 return FALSE;
1491 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1493 struct xml_attr attr;
1495 while (next_xml_attr(xmlbuf, &attr, end))
1497 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1501 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1503 struct xml_elem elem;
1505 if (next_xml_elem(xmlbuf, &elem, parent))
1507 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1508 set_error( xmlbuf );
1512 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1514 struct xml_elem elem;
1515 struct xml_attr attr;
1516 BOOL end = FALSE;
1518 while (next_xml_attr(xmlbuf, &attr, &end));
1519 if (end) return;
1521 while (next_xml_elem(xmlbuf, &elem, parent))
1522 parse_unknown_elem(xmlbuf, &elem);
1525 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1526 struct assembly_identity* ai, const struct xml_elem *parent)
1528 struct xml_attr attr;
1529 BOOL end = FALSE;
1531 while (next_xml_attr(xmlbuf, &attr, &end))
1533 if (xml_attr_cmp(&attr, nameW))
1535 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1537 else if (xml_attr_cmp(&attr, typeW))
1539 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1541 else if (xml_attr_cmp(&attr, versionW))
1543 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1545 else if (xml_attr_cmp(&attr, processorArchitectureW))
1547 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1549 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1551 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1553 else if (xml_attr_cmp(&attr, languageW))
1555 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1557 else if (!is_xmlns_attr( &attr ))
1559 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1563 TRACE( "name=%s version=%s arch=%s\n",
1564 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1566 if (!end) parse_expect_end_elem(xmlbuf, parent);
1569 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1571 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1572 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1573 static const WCHAR freeW[] = {'F','r','e','e',0};
1574 static const WCHAR bothW[] = {'B','o','t','h',0};
1576 if (value->len == 0) return ThreadingModel_No;
1577 if (xmlstr_cmp(value, apartW))
1578 return ThreadingModel_Apartment;
1579 else if (xmlstr_cmp(value, freeW))
1580 return ThreadingModel_Free;
1581 else if (xmlstr_cmp(value, bothW))
1582 return ThreadingModel_Both;
1583 else if (xmlstr_cmp(value, neutralW))
1584 return ThreadingModel_Neutral;
1585 else
1586 return ThreadingModel_No;
1589 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1591 int min, max;
1593 min = 0;
1594 max = ARRAY_SIZE(olemisc_values) - 1;
1596 while (min <= max)
1598 int n, c;
1600 n = (min+max)/2;
1602 c = strncmpW(olemisc_values[n].name, str, len);
1603 if (!c && !olemisc_values[n].name[len])
1604 return olemisc_values[n].value;
1606 if (c >= 0)
1607 max = n-1;
1608 else
1609 min = n+1;
1612 WARN("unknown flag %s\n", debugstr_wn(str, len));
1613 return 0;
1616 static DWORD parse_com_class_misc(const xmlstr_t *value)
1618 const WCHAR *str = value->ptr, *start;
1619 DWORD flags = 0;
1620 int i = 0;
1622 /* it's comma separated list of flags */
1623 while (i < value->len)
1625 start = str;
1626 while (*str != ',' && (i++ < value->len)) str++;
1628 flags |= get_olemisc_value(start, str-start);
1630 /* skip separator */
1631 str++;
1632 i++;
1635 return flags;
1638 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1640 struct progids *progids = &entity->u.comclass.progids;
1642 if (progids->allocated == 0)
1644 progids->allocated = 4;
1645 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1648 if (progids->allocated == progids->num)
1650 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1651 2 * progids->allocated * sizeof(WCHAR*));
1652 if (!new_progids) return FALSE;
1653 progids->allocated *= 2;
1654 progids->progids = new_progids;
1657 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1658 progids->num++;
1660 return TRUE;
1663 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1665 xmlstr_t content;
1666 BOOL end = FALSE;
1668 parse_expect_no_attr(xmlbuf, &end);
1669 if (end) set_error( xmlbuf );
1670 if (!parse_text_content(xmlbuf, &content)) return;
1672 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1673 parse_expect_end_elem(xmlbuf, parent);
1676 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1677 const struct xml_elem *parent )
1679 struct xml_elem elem;
1680 struct xml_attr attr;
1681 BOOL end = FALSE;
1682 struct entity* entity;
1684 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1686 set_error( xmlbuf );
1687 return;
1690 while (next_xml_attr(xmlbuf, &attr, &end))
1692 if (xml_attr_cmp(&attr, clsidW))
1694 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1696 else if (xml_attr_cmp(&attr, progidW))
1698 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1700 else if (xml_attr_cmp(&attr, tlbidW))
1702 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1704 else if (xml_attr_cmp(&attr, threadingmodelW))
1706 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1708 else if (xml_attr_cmp(&attr, miscstatusW))
1710 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1712 else if (xml_attr_cmp(&attr, miscstatuscontentW))
1714 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1716 else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1718 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1720 else if (xml_attr_cmp(&attr, miscstatusiconW))
1722 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1724 else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1726 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1728 else if (xml_attr_cmp(&attr, descriptionW))
1730 /* not stored */
1732 else if (!is_xmlns_attr( &attr ))
1734 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1738 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1739 if (entity->u.comclass.progid)
1740 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1742 if (end) return;
1744 while (next_xml_elem(xmlbuf, &elem, parent))
1746 if (xml_elem_cmp(&elem, progidW, asmv1W))
1748 parse_com_class_progid(xmlbuf, entity, &elem);
1750 else
1752 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1753 parse_unknown_elem(xmlbuf, &elem);
1757 if (entity->u.comclass.progids.num)
1758 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1761 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1763 const WCHAR *curr;
1764 ULONG num = 0;
1766 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1768 if (*curr >= '0' && *curr <= '9')
1769 num = num * 10 + *curr - '0';
1770 else
1772 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1773 return FALSE;
1776 entity->u.ifaceps.nummethods = num;
1778 return TRUE;
1781 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1782 struct actctx_loader *acl, const struct xml_elem *parent )
1784 struct xml_attr attr;
1785 BOOL end = FALSE;
1786 struct entity* entity;
1788 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1790 set_error( xmlbuf );
1791 return;
1794 while (next_xml_attr(xmlbuf, &attr, &end))
1796 if (xml_attr_cmp(&attr, iidW))
1798 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1800 else if (xml_attr_cmp(&attr, nameW))
1802 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1804 else if (xml_attr_cmp(&attr, baseInterfaceW))
1806 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1807 entity->u.ifaceps.mask |= BaseIface;
1809 else if (xml_attr_cmp(&attr, nummethodsW))
1811 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1812 entity->u.ifaceps.mask |= NumMethods;
1814 else if (xml_attr_cmp(&attr, tlbidW))
1816 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1818 /* not used */
1819 else if (xml_attr_cmp(&attr, proxyStubClsid32W) || xml_attr_cmp(&attr, threadingmodelW))
1822 else if (!is_xmlns_attr( &attr ))
1824 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1828 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1829 if (!end) parse_expect_end_elem(xmlbuf, parent);
1832 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1834 WORD *flags = &entity->u.typelib.flags;
1835 const WCHAR *str = value->ptr, *start;
1836 int i = 0;
1838 *flags = 0;
1840 /* it's comma separated list of flags */
1841 while (i < value->len)
1843 start = str;
1844 while (*str != ',' && (i++ < value->len)) str++;
1846 if (!strncmpiW(start, restrictedW, str-start))
1847 *flags |= LIBFLAG_FRESTRICTED;
1848 else if (!strncmpiW(start, controlW, str-start))
1849 *flags |= LIBFLAG_FCONTROL;
1850 else if (!strncmpiW(start, hiddenW, str-start))
1851 *flags |= LIBFLAG_FHIDDEN;
1852 else if (!strncmpiW(start, hasdiskimageW, str-start))
1853 *flags |= LIBFLAG_FHASDISKIMAGE;
1854 else
1856 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1857 return FALSE;
1860 /* skip separator */
1861 str++;
1862 i++;
1865 return TRUE;
1868 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1870 unsigned int ver[2];
1871 unsigned int pos;
1872 const WCHAR *curr;
1874 /* major.minor */
1875 ver[0] = ver[1] = pos = 0;
1876 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1878 if (*curr >= '0' && *curr <= '9')
1880 ver[pos] = ver[pos] * 10 + *curr - '0';
1881 if (ver[pos] >= 0x10000) goto error;
1883 else if (*curr == '.')
1885 if (++pos >= 2) goto error;
1887 else goto error;
1889 entity->u.typelib.major = ver[0];
1890 entity->u.typelib.minor = ver[1];
1891 return TRUE;
1893 error:
1894 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1895 return FALSE;
1898 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1899 struct actctx_loader *acl, const struct xml_elem *parent )
1901 struct xml_attr attr;
1902 BOOL end = FALSE;
1903 struct entity* entity;
1905 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1907 set_error( xmlbuf );
1908 return;
1911 while (next_xml_attr(xmlbuf, &attr, &end))
1913 if (xml_attr_cmp(&attr, tlbidW))
1915 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1917 else if (xml_attr_cmp(&attr, versionW))
1919 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1921 else if (xml_attr_cmp(&attr, helpdirW))
1923 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1925 else if (xml_attr_cmp(&attr, flagsW))
1927 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1929 else if (!is_xmlns_attr( &attr ))
1931 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1935 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1936 if (!end) parse_expect_end_elem(xmlbuf, parent);
1939 static inline int aligned_string_len(int len)
1941 return (len + 3) & ~3;
1944 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1946 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1947 struct assembly_version *ver = &assembly->id.version;
1948 WCHAR buff[25];
1950 if (!ret) ret = buff;
1951 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1954 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1955 struct actctx_loader *acl, const struct xml_elem *parent )
1957 struct xml_elem elem;
1958 struct xml_attr attr;
1959 xmlstr_t content;
1960 BOOL end = FALSE;
1961 struct entity* entity;
1963 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1965 set_error( xmlbuf );
1966 return;
1968 entity->u.class.versioned = TRUE;
1969 while (next_xml_attr(xmlbuf, &attr, &end))
1971 if (xml_attr_cmp(&attr, versionedW))
1973 if (xmlstr_cmpi(&attr.value, noW))
1974 entity->u.class.versioned = FALSE;
1975 else if (!xmlstr_cmpi(&attr.value, yesW))
1976 set_error( xmlbuf );
1978 else if (!is_xmlns_attr( &attr ))
1980 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1984 if (end) return;
1986 if (!parse_text_content(xmlbuf, &content)) return;
1987 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1989 acl->actctx->sections |= WINDOWCLASS_SECTION;
1991 while (next_xml_elem(xmlbuf, &elem, parent))
1993 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1994 parse_unknown_elem(xmlbuf, &elem);
1998 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2000 struct xml_attr attr;
2001 BOOL end = FALSE;
2003 while (next_xml_attr(xmlbuf, &attr, &end))
2005 if (xml_attr_cmp(&attr, oldVersionW))
2007 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2009 else if (xml_attr_cmp(&attr, newVersionW))
2011 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2013 else if (!is_xmlns_attr( &attr ))
2015 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2019 if (!end) parse_expect_end_elem(xmlbuf, parent);
2022 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2024 struct xml_elem elem;
2025 struct xml_attr attr;
2026 xmlstr_t content;
2027 BOOL end = FALSE;
2029 while (next_xml_attr(xmlbuf, &attr, &end))
2031 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2034 if (end) return;
2035 if (!parse_text_content(xmlbuf, &content)) return;
2037 TRACE("Got description %s\n", debugstr_xmlstr(&content));
2039 while (next_xml_elem(xmlbuf, &elem, parent))
2041 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2042 parse_unknown_elem(xmlbuf, &elem);
2046 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2047 struct assembly* assembly,
2048 struct actctx_loader* acl,
2049 const struct xml_elem *parent)
2051 struct xml_attr attr;
2052 BOOL end = FALSE;
2053 struct entity* entity;
2055 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2057 set_error( xmlbuf );
2058 return;
2061 while (next_xml_attr(xmlbuf, &attr, &end))
2063 if (xml_attr_cmp(&attr, iidW))
2065 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2067 else if (xml_attr_cmp(&attr, nameW))
2069 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2071 else if (xml_attr_cmp(&attr, baseInterfaceW))
2073 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2074 entity->u.ifaceps.mask |= BaseIface;
2076 else if (xml_attr_cmp(&attr, nummethodsW))
2078 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2079 entity->u.ifaceps.mask |= NumMethods;
2081 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2083 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2085 else if (xml_attr_cmp(&attr, tlbidW))
2087 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2089 else if (!is_xmlns_attr( &attr ))
2091 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2095 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2096 if (!end) parse_expect_end_elem(xmlbuf, parent);
2099 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2100 struct actctx_loader *acl, const struct xml_elem *parent )
2103 struct xml_elem elem;
2104 struct xml_attr attr;
2105 BOOL end = FALSE;
2106 struct entity* entity;
2108 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2110 set_error( xmlbuf );
2111 return;
2114 while (next_xml_attr(xmlbuf, &attr, &end))
2116 if (xml_attr_cmp(&attr, nameW))
2118 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2120 else if (xml_attr_cmp(&attr, clsidW))
2122 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2124 else if (xml_attr_cmp(&attr, progidW))
2126 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2128 else if (xml_attr_cmp(&attr, tlbidW))
2130 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2132 else if (xml_attr_cmp(&attr, threadingmodelW))
2134 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2136 else if (xml_attr_cmp(&attr, runtimeVersionW))
2138 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2140 else if (!is_xmlns_attr( &attr ))
2142 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2146 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2147 if (entity->u.comclass.progid)
2148 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2149 if (end) return;
2151 while (next_xml_elem(xmlbuf, &elem, parent))
2153 if (xml_elem_cmp(&elem, progidW, asmv1W))
2155 parse_com_class_progid(xmlbuf, entity, &elem);
2157 else
2159 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2160 parse_unknown_elem(xmlbuf, &elem);
2164 if (entity->u.comclass.progids.num)
2165 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2168 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2169 struct actctx_loader *acl, const struct xml_elem *parent )
2171 struct xml_attr attr;
2172 BOOL end = FALSE;
2173 struct entity* entity;
2175 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2177 set_error( xmlbuf );
2178 return;
2181 while (next_xml_attr(xmlbuf, &attr, &end))
2183 if (xml_attr_cmp(&attr, nameW))
2185 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2187 else if (xml_attr_cmp(&attr, clsidW))
2189 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2191 else if (xml_attr_cmp(&attr, runtimeVersionW))
2193 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2195 else if (!is_xmlns_attr( &attr ))
2197 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2201 acl->actctx->sections |= CLRSURROGATES_SECTION;
2202 if (!end) parse_expect_end_elem(xmlbuf, parent);
2205 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2206 const struct xml_elem *parent, BOOL optional )
2208 struct xml_elem elem;
2209 struct xml_attr attr;
2210 struct assembly_identity ai;
2211 BOOL end = FALSE;
2213 memset(&ai, 0, sizeof(ai));
2214 ai.optional = optional;
2216 while (next_xml_attr(xmlbuf, &attr, &end))
2218 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2219 static const WCHAR trueW[] = {'t','r','u','e',0};
2221 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2222 ai.delayed = xmlstr_cmp(&attr.value, trueW);
2223 else if (!is_xmlns_attr( &attr ))
2224 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2227 if (end) return;
2229 while (next_xml_elem(xmlbuf, &elem, parent))
2231 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2233 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2234 /* store the newly found identity for later loading */
2235 if (ai.arch && !strcmpW(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2236 TRACE( "adding name=%s version=%s arch=%s\n",
2237 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2238 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2240 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2242 parse_binding_redirect_elem(xmlbuf, &elem);
2244 else
2246 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2247 parse_unknown_elem(xmlbuf, &elem);
2252 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2253 const struct xml_elem *parent )
2256 struct xml_elem elem;
2257 struct xml_attr attr;
2258 BOOL end = FALSE, optional = FALSE;
2260 while (next_xml_attr(xmlbuf, &attr, &end))
2262 if (xml_attr_cmp(&attr, optionalW))
2264 optional = xmlstr_cmpi( &attr.value, yesW );
2265 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2267 else if (!is_xmlns_attr( &attr ))
2269 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2273 while (next_xml_elem(xmlbuf, &elem, parent))
2275 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2277 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2279 else
2281 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2282 parse_unknown_elem(xmlbuf, &elem);
2287 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2289 BOOL end = FALSE;
2291 parse_expect_no_attr(xmlbuf, &end);
2292 if (!end) parse_expect_end_elem(xmlbuf, parent);
2295 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2297 BOOL end = FALSE;
2299 parse_expect_no_attr(xmlbuf, &end);
2300 if (!end) parse_expect_end_elem(xmlbuf, parent);
2303 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2304 struct actctx_loader* acl, const struct xml_elem *parent )
2306 struct xml_elem elem;
2307 struct xml_attr attr;
2308 BOOL end = FALSE;
2309 struct dll_redirect* dll;
2311 if (!(dll = add_dll_redirect(assembly)))
2313 set_error( xmlbuf );
2314 return;
2317 while (next_xml_attr(xmlbuf, &attr, &end))
2319 if (xml_attr_cmp(&attr, nameW))
2321 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2322 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2324 else if (xml_attr_cmp(&attr, hashW))
2326 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2328 else if (xml_attr_cmp(&attr, hashalgW))
2330 static const WCHAR sha1W[] = {'S','H','A','1',0};
2331 if (!xmlstr_cmpi(&attr.value, sha1W))
2332 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2334 else if (!is_xmlns_attr( &attr ))
2336 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2340 if (!dll->name) set_error( xmlbuf );
2342 acl->actctx->sections |= DLLREDIRECT_SECTION;
2344 if (end) return;
2346 while (next_xml_elem(xmlbuf, &elem, parent))
2348 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2350 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2352 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2354 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2356 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2358 WARN("asmv2:hash (undocumented) not supported\n");
2359 parse_unknown_elem(xmlbuf, &elem);
2361 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2363 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2365 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2367 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2369 else
2371 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2372 parse_unknown_elem( xmlbuf, &elem );
2377 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2378 struct actctx_loader *acl, const struct xml_elem *parent )
2380 struct xml_attr attr;
2381 BOOL end = FALSE;
2383 while (next_xml_attr(xmlbuf, &attr, &end))
2385 if (xml_attr_cmp(&attr, IdW))
2387 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2388 UNICODE_STRING str;
2389 GUID compat_id;
2391 str.Buffer = (PWSTR)attr.value.ptr;
2392 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2393 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2395 if (!(compat = add_compat_context(assembly)))
2397 set_error( xmlbuf );
2398 return;
2400 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2401 compat->Id = compat_id;
2403 else
2405 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2408 else if (!is_xmlns_attr( &attr ))
2410 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2414 if (!end) parse_expect_end_elem(xmlbuf, parent);
2417 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2418 struct actctx_loader* acl, const struct xml_elem *parent)
2420 struct xml_elem elem;
2422 while (next_xml_elem(xmlbuf, &elem, parent))
2424 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2426 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2428 else
2430 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2431 parse_unknown_elem(xmlbuf, &elem);
2436 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2437 struct actctx_loader* acl, const struct xml_elem *parent)
2439 struct xml_elem elem;
2441 while (next_xml_elem(xmlbuf, &elem, parent))
2443 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2445 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2447 else
2449 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2450 parse_unknown_elem(xmlbuf, &elem);
2455 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2456 struct xml_elem *parent )
2458 struct xml_elem elem;
2459 struct xml_attr attr;
2460 xmlstr_t content;
2461 BOOL end = FALSE;
2462 struct entity *entity;
2464 while (next_xml_attr( xmlbuf, &attr, &end ))
2466 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2469 if (end) return;
2471 if (!parse_text_content( xmlbuf, &content )) return;
2472 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2474 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2475 if (!entity)
2477 set_error( xmlbuf );
2478 return;
2480 entity->u.settings.name = xmlstrdupW( &parent->name );
2481 entity->u.settings.value = xmlstrdupW( &content );
2482 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2484 while (next_xml_elem(xmlbuf, &elem, parent))
2486 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2487 parse_unknown_elem( xmlbuf, &elem );
2491 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2492 struct actctx_loader *acl, const struct xml_elem *parent )
2494 struct xml_elem elem;
2496 while (next_xml_elem( xmlbuf, &elem, parent ))
2498 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2499 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2500 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2501 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2502 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2503 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2504 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2505 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2506 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2507 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2508 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2510 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2512 else
2514 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2515 parse_unknown_elem( xmlbuf, &elem );
2520 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2521 struct actctx_loader *acl, const struct xml_elem *parent )
2523 struct xml_elem elem;
2525 while (next_xml_elem( xmlbuf, &elem, parent ))
2527 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2529 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2531 else
2533 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2534 parse_unknown_elem( xmlbuf, &elem );
2539 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2540 struct actctx_loader *acl, const struct xml_elem *parent )
2542 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2543 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2544 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};
2545 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2546 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2547 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2548 static const WCHAR trueW[] = {'t','r','u','e',0};
2550 struct xml_elem elem;
2551 struct xml_attr attr;
2552 BOOL end = FALSE;
2554 /* Multiple requestedExecutionLevel elements are not supported. */
2555 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2557 while (next_xml_attr(xmlbuf, &attr, &end))
2559 if (xml_attr_cmp(&attr, levelW))
2561 if (xmlstr_cmpi(&attr.value, asInvokerW))
2562 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2563 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2564 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2565 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2566 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2567 else
2568 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2570 else if (xml_attr_cmp(&attr, uiAccessW))
2572 if (xmlstr_cmpi(&attr.value, falseW))
2573 assembly->ui_access = FALSE;
2574 else if (xmlstr_cmpi(&attr.value, trueW))
2575 assembly->ui_access = TRUE;
2576 else
2577 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2579 else if (!is_xmlns_attr( &attr ))
2580 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2583 if (end) return;
2585 while (next_xml_elem(xmlbuf, &elem, parent))
2587 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2588 parse_unknown_elem(xmlbuf, &elem);
2592 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2593 struct actctx_loader *acl, const struct xml_elem *parent )
2595 struct xml_elem elem;
2597 while (next_xml_elem(xmlbuf, &elem, parent))
2599 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2601 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2603 else
2605 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2606 parse_unknown_elem(xmlbuf, &elem);
2611 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2612 struct actctx_loader *acl, const struct xml_elem *parent )
2614 struct xml_elem elem;
2616 while (next_xml_elem(xmlbuf, &elem, parent))
2618 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2620 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2622 else
2624 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2625 parse_unknown_elem(xmlbuf, &elem);
2630 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2631 struct actctx_loader *acl, const struct xml_elem *parent )
2633 struct xml_elem elem;
2635 while (next_xml_elem(xmlbuf, &elem, parent))
2637 if (xml_elem_cmp(&elem, securityW, asmv1W))
2639 parse_security_elem(xmlbuf, assembly, acl, &elem);
2641 else
2643 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2644 parse_unknown_elem(xmlbuf, &elem);
2649 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2650 struct actctx_loader* acl, const struct xml_elem *parent,
2651 struct assembly_identity* expected_ai)
2653 struct xml_elem elem;
2654 struct xml_attr attr;
2655 BOOL end = FALSE, version = FALSE;
2657 TRACE("(%p)\n", xmlbuf);
2659 while (next_xml_attr(xmlbuf, &attr, &end))
2661 if (xml_attr_cmp(&attr, manifestVersionW))
2663 static const WCHAR v10W[] = {'1','.','0',0};
2664 if (!xmlstr_cmp(&attr.value, v10W))
2666 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2667 break;
2669 version = TRUE;
2671 else if (!is_xmlns_attr( &attr ))
2673 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2677 if (end || !version)
2679 set_error( xmlbuf );
2680 return;
2683 while (next_xml_elem(xmlbuf, &elem, parent))
2685 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2687 parse_noinherit_elem(xmlbuf, &elem);
2688 assembly->no_inherit = TRUE;
2690 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2692 parse_noinheritable_elem(xmlbuf, &elem);
2694 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2696 parse_description_elem(xmlbuf, &elem);
2698 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2700 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2702 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2704 parse_dependency_elem(xmlbuf, acl, &elem);
2706 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2708 parse_file_elem(xmlbuf, assembly, acl, &elem);
2710 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2712 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2714 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2716 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2718 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2720 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2722 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2724 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2726 if (!xmlbuf->error && expected_ai)
2728 /* FIXME: more tests */
2729 if (assembly->type == ASSEMBLY_MANIFEST &&
2730 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2732 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2733 expected_ai->version.major, expected_ai->version.minor,
2734 expected_ai->version.build, expected_ai->version.revision,
2735 assembly->id.version.major, assembly->id.version.minor,
2736 assembly->id.version.build, assembly->id.version.revision);
2737 set_error( xmlbuf );
2739 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2740 (assembly->id.version.major != expected_ai->version.major ||
2741 assembly->id.version.minor != expected_ai->version.minor ||
2742 assembly->id.version.build < expected_ai->version.build ||
2743 (assembly->id.version.build == expected_ai->version.build &&
2744 assembly->id.version.revision < expected_ai->version.revision)))
2746 FIXME("wrong version for shared assembly manifest\n");
2747 set_error( xmlbuf );
2751 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2753 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2755 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2757 parse_application_elem(xmlbuf, assembly, acl, &elem);
2759 else
2761 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2762 parse_unknown_elem(xmlbuf, &elem);
2766 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2767 assembly->no_inherit)
2769 set_error( xmlbuf );
2773 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2774 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2776 struct xml_elem elem;
2777 struct xml_elem parent = {};
2779 xmlbuf->error = FALSE;
2780 xmlbuf->ns_pos = 0;
2782 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2784 if (xmlstr_cmp(&elem.name, xmlW) &&
2785 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2786 return STATUS_SXS_CANT_GEN_ACTCTX;
2788 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2790 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2791 return STATUS_SXS_CANT_GEN_ACTCTX;
2794 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2795 if (xmlbuf->error)
2797 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2798 return STATUS_SXS_CANT_GEN_ACTCTX;
2801 if (next_xml_elem(xmlbuf, &elem, &parent))
2803 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2804 return STATUS_SXS_CANT_GEN_ACTCTX;
2807 if (xmlbuf->ptr != xmlbuf->end)
2809 FIXME("parse error\n");
2810 return STATUS_SXS_CANT_GEN_ACTCTX;
2812 return STATUS_SUCCESS;
2815 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2816 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2817 const void *buffer, SIZE_T size )
2819 xmlbuf_t xmlbuf;
2820 NTSTATUS status;
2821 struct assembly *assembly;
2822 int unicode_tests;
2824 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2826 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2827 return STATUS_SXS_CANT_GEN_ACTCTX;
2829 if (directory && !(assembly->directory = strdupW(directory)))
2830 return STATUS_NO_MEMORY;
2832 if (!filename)
2834 UNICODE_STRING module_path;
2835 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2836 assembly->manifest.info = module_path.Buffer;
2838 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2840 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2841 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2843 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2844 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2846 xmlbuf.ptr = buffer;
2847 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2848 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2850 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2852 const WCHAR *buf = buffer;
2853 WCHAR *new_buff;
2854 unsigned int i;
2856 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2857 return STATUS_NO_MEMORY;
2858 for (i = 0; i < size / sizeof(WCHAR); i++)
2859 new_buff[i] = RtlUshortByteSwap( buf[i] );
2860 xmlbuf.ptr = new_buff;
2861 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2862 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2863 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2865 else
2867 DWORD len;
2868 WCHAR *new_buff;
2870 /* let's assume utf-8 for now */
2871 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2872 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2873 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2874 xmlbuf.ptr = new_buff;
2875 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2876 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2877 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2879 return status;
2882 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2884 OBJECT_ATTRIBUTES attr;
2885 IO_STATUS_BLOCK io;
2887 attr.Length = sizeof(attr);
2888 attr.RootDirectory = 0;
2889 attr.Attributes = OBJ_CASE_INSENSITIVE;
2890 attr.ObjectName = name;
2891 attr.SecurityDescriptor = NULL;
2892 attr.SecurityQualityOfService = NULL;
2893 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2896 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2897 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2898 HANDLE hModule, LPCWSTR resname, ULONG lang )
2900 NTSTATUS status;
2901 UNICODE_STRING nameW;
2902 LDR_RESOURCE_INFO info;
2903 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2904 void *ptr;
2906 if (TRACE_ON(actctx))
2908 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2910 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2911 hModule, debugstr_w(nameW.Buffer) );
2912 RtlFreeUnicodeString( &nameW );
2914 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2915 hModule, debugstr_w(filename) );
2918 if (!resname) return STATUS_INVALID_PARAMETER;
2920 info.Type = RT_MANIFEST;
2921 info.Language = lang;
2922 if (!((ULONG_PTR)resname >> 16))
2924 info.Name = (ULONG_PTR)resname;
2925 status = LdrFindResource_U(hModule, &info, 3, &entry);
2927 else if (resname[0] == '#')
2929 ULONG value;
2930 RtlInitUnicodeString(&nameW, resname + 1);
2931 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2932 return STATUS_INVALID_PARAMETER;
2933 info.Name = value;
2934 status = LdrFindResource_U(hModule, &info, 3, &entry);
2936 else
2938 RtlCreateUnicodeString(&nameW, resname);
2939 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2940 info.Name = (ULONG_PTR)nameW.Buffer;
2941 status = LdrFindResource_U(hModule, &info, 3, &entry);
2942 RtlFreeUnicodeString(&nameW);
2944 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2946 if (status == STATUS_SUCCESS)
2947 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2949 return status;
2952 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2953 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2954 HANDLE file, LPCWSTR resname, ULONG lang )
2956 HANDLE mapping;
2957 OBJECT_ATTRIBUTES attr;
2958 LARGE_INTEGER size;
2959 LARGE_INTEGER offset;
2960 NTSTATUS status;
2961 SIZE_T count;
2962 void *base;
2964 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2966 attr.Length = sizeof(attr);
2967 attr.RootDirectory = 0;
2968 attr.ObjectName = NULL;
2969 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2970 attr.SecurityDescriptor = NULL;
2971 attr.SecurityQualityOfService = NULL;
2973 size.QuadPart = 0;
2974 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2975 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2976 if (status != STATUS_SUCCESS) return status;
2978 offset.QuadPart = 0;
2979 count = 0;
2980 base = NULL;
2981 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2982 &count, ViewShare, 0, PAGE_READONLY );
2983 NtClose( mapping );
2984 if (status != STATUS_SUCCESS) return status;
2986 if (RtlImageNtHeader(base)) /* we got a PE file */
2988 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2989 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2991 else status = STATUS_INVALID_IMAGE_FORMAT;
2993 NtUnmapViewOfSection( GetCurrentProcess(), base );
2994 return status;
2997 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2998 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3000 FILE_END_OF_FILE_INFORMATION info;
3001 IO_STATUS_BLOCK io;
3002 HANDLE mapping;
3003 OBJECT_ATTRIBUTES attr;
3004 LARGE_INTEGER size;
3005 LARGE_INTEGER offset;
3006 NTSTATUS status;
3007 SIZE_T count;
3008 void *base;
3010 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3012 attr.Length = sizeof(attr);
3013 attr.RootDirectory = 0;
3014 attr.ObjectName = NULL;
3015 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3016 attr.SecurityDescriptor = NULL;
3017 attr.SecurityQualityOfService = NULL;
3019 size.QuadPart = 0;
3020 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3021 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3022 if (status != STATUS_SUCCESS) return status;
3024 offset.QuadPart = 0;
3025 count = 0;
3026 base = NULL;
3027 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3028 &count, ViewShare, 0, PAGE_READONLY );
3029 NtClose( mapping );
3030 if (status != STATUS_SUCCESS) return status;
3032 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3033 if (status == STATUS_SUCCESS)
3034 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3036 NtUnmapViewOfSection( GetCurrentProcess(), base );
3037 return status;
3040 /* try to load the .manifest file associated to the file */
3041 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3042 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3044 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3045 WCHAR *buffer;
3046 NTSTATUS status;
3047 UNICODE_STRING nameW;
3048 HANDLE file;
3049 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3051 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3053 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3055 if (module) /* use the module filename */
3057 UNICODE_STRING name;
3059 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3061 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3062 strcatW( name.Buffer, dotManifestW );
3063 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3064 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3065 RtlFreeUnicodeString( &name );
3067 if (status) return status;
3069 else
3071 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3072 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3073 return STATUS_NO_MEMORY;
3074 strcpyW( buffer, filename );
3075 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3076 strcatW( buffer, dotManifestW );
3077 RtlInitUnicodeString( &nameW, buffer );
3080 if (!open_nt_file( &file, &nameW ))
3082 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3083 NtClose( file );
3085 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3086 RtlFreeUnicodeString( &nameW );
3087 return status;
3090 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3092 static const WCHAR lookup_fmtW[] =
3093 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3094 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3095 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3097 WCHAR *lookup, *ret = NULL;
3098 UNICODE_STRING lookup_us;
3099 IO_STATUS_BLOCK io;
3100 const WCHAR *lang = ai->language;
3101 unsigned int data_pos = 0, data_len;
3102 char buffer[8192];
3104 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3106 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3107 (strlenW(ai->arch) + strlenW(ai->name)
3108 + strlenW(ai->public_key) + strlenW(lang) + 20) * sizeof(WCHAR)
3109 + sizeof(lookup_fmtW) )))
3110 return NULL;
3111 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3112 ai->version.major, ai->version.minor, lang );
3113 RtlInitUnicodeString( &lookup_us, lookup );
3115 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3116 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3118 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3119 FILE_BOTH_DIR_INFORMATION *dir_info;
3120 WCHAR *tmp;
3121 ULONG build, revision;
3123 data_len = io.Information;
3125 for (;;)
3127 if (data_pos >= data_len)
3129 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3130 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3131 break;
3132 data_len = io.Information;
3133 data_pos = 0;
3135 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3137 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3138 else data_pos = data_len;
3140 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
3141 build = atoiW(tmp);
3142 if (build < min_build) continue;
3143 tmp = strchrW(tmp, '.') + 1;
3144 revision = atoiW(tmp);
3145 if (build == min_build && revision < min_revision) continue;
3146 tmp = strchrW(tmp, '_') + 1;
3147 tmp = strchrW(tmp, '_') + 1;
3148 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3149 !strncmpiW( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3151 /* prefer a non-Wine manifest if we already have one */
3152 /* we'll still load the builtin dll if specified through DllOverrides */
3153 if (ret) continue;
3155 else
3157 min_build = build;
3158 min_revision = revision;
3160 ai->version.build = build;
3161 ai->version.revision = revision;
3162 RtlFreeHeap( GetProcessHeap(), 0, ret );
3163 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3165 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3166 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3170 else WARN("no matching file for %s\n", debugstr_w(lookup));
3171 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3172 return ret;
3175 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3177 struct assembly_identity sxs_ai;
3178 UNICODE_STRING path_us;
3179 OBJECT_ATTRIBUTES attr;
3180 IO_STATUS_BLOCK io;
3181 WCHAR *path, *file = NULL;
3182 HANDLE handle;
3184 static const WCHAR manifest_dirW[] =
3185 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3187 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3189 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3190 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3191 return STATUS_NO_MEMORY;
3193 strcpyW( path, user_shared_data->NtSystemRoot );
3194 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3196 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3198 RtlFreeHeap( GetProcessHeap(), 0, path );
3199 return STATUS_NO_SUCH_FILE;
3201 RtlFreeHeap( GetProcessHeap(), 0, path );
3203 attr.Length = sizeof(attr);
3204 attr.RootDirectory = 0;
3205 attr.Attributes = OBJ_CASE_INSENSITIVE;
3206 attr.ObjectName = &path_us;
3207 attr.SecurityDescriptor = NULL;
3208 attr.SecurityQualityOfService = NULL;
3210 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3211 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3213 sxs_ai = *ai;
3214 file = lookup_manifest_file( handle, &sxs_ai );
3215 NtClose( handle );
3217 if (!file)
3219 RtlFreeUnicodeString( &path_us );
3220 return STATUS_NO_SUCH_FILE;
3223 /* append file name to directory path */
3224 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3225 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3227 RtlFreeHeap( GetProcessHeap(), 0, file );
3228 RtlFreeUnicodeString( &path_us );
3229 return STATUS_NO_MEMORY;
3232 path[path_us.Length/sizeof(WCHAR)] = '\\';
3233 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3234 RtlInitUnicodeString( &path_us, path );
3235 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3237 if (!open_nt_file( &handle, &path_us ))
3239 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3240 NtClose( handle );
3242 else io.u.Status = STATUS_NO_SUCH_FILE;
3244 RtlFreeHeap( GetProcessHeap(), 0, file );
3245 RtlFreeUnicodeString( &path_us );
3246 return io.u.Status;
3249 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3250 struct assembly_identity* ai)
3252 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3253 unsigned int i;
3254 WCHAR *buffer, *p, *directory;
3255 NTSTATUS status;
3256 UNICODE_STRING nameW;
3257 HANDLE file;
3258 DWORD len;
3260 TRACE( "looking for name=%s version=%s arch=%s\n",
3261 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3263 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3265 /* FIXME: add support for language specific lookup */
3267 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3268 strlenW(acl->actctx->appdir.info));
3270 nameW.Buffer = NULL;
3271 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3272 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3273 return STATUS_NO_MEMORY;
3275 if (!(directory = build_assembly_dir( ai )))
3277 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3278 return STATUS_NO_MEMORY;
3281 /* Lookup in <dir>\name.dll
3282 * <dir>\name.manifest
3283 * <dir>\name\name.dll
3284 * <dir>\name\name.manifest
3286 * First 'appdir' is used as <dir>, if that failed
3287 * it tries application manifest file path.
3289 strcpyW( buffer, acl->actctx->appdir.info );
3290 p = buffer + strlenW(buffer);
3291 for (i = 0; i < 4; i++)
3293 if (i == 2)
3295 struct assembly *assembly = acl->actctx->assemblies;
3296 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3298 else *p++ = '\\';
3300 strcpyW( p, ai->name );
3301 p += strlenW(p);
3303 strcpyW( p, dotDllW );
3304 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3306 status = open_nt_file( &file, &nameW );
3307 if (!status)
3309 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3310 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3311 NtClose( file );
3312 if (status == STATUS_SUCCESS)
3313 break;
3315 RtlFreeUnicodeString( &nameW );
3318 strcpyW( p, dotManifestW );
3319 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3321 status = open_nt_file( &file, &nameW );
3322 if (!status)
3324 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3325 NtClose( file );
3326 break;
3328 RtlFreeUnicodeString( &nameW );
3330 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3332 RtlFreeUnicodeString( &nameW );
3333 RtlFreeHeap( GetProcessHeap(), 0, directory );
3334 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3335 return status;
3338 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3340 NTSTATUS status = STATUS_SUCCESS;
3341 unsigned int i;
3343 for (i = 0; i < acl->num_dependencies; i++)
3345 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3347 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3349 FIXME( "Could not find dependent assembly %s (%s)\n",
3350 debugstr_w(acl->dependencies[i].name),
3351 debugstr_version(&acl->dependencies[i].version) );
3352 status = STATUS_SXS_CANT_GEN_ACTCTX;
3353 break;
3357 /* FIXME should now iterate through all refs */
3358 return status;
3361 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3362 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3364 NTSTATUS status = STATUS_SUCCESS;
3366 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3368 if (*handle) return STATUS_INVALID_PARAMETER;
3370 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3371 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3373 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3375 ULONG_PTR magic;
3376 LDR_MODULE *pldr;
3378 if (!*handle) return STATUS_INVALID_PARAMETER;
3380 LdrLockLoaderLock( 0, NULL, &magic );
3381 if (!LdrFindEntryForAddress( *handle, &pldr ))
3383 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3384 status = STATUS_DLL_NOT_FOUND;
3385 else
3386 *handle = pldr->ActivationContext;
3388 else status = STATUS_DLL_NOT_FOUND;
3389 LdrUnlockLoaderLock( 0, magic );
3391 else if (!*handle && (class != ActivationContextBasicInformation))
3392 *handle = process_actctx;
3394 return status;
3397 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3399 unsigned int i, j, total_len = 0, dll_count = 0;
3400 struct strsection_header *header;
3401 struct dllredirect_data *data;
3402 struct string_index *index;
3403 ULONG name_offset;
3405 /* compute section length */
3406 for (i = 0; i < actctx->num_assemblies; i++)
3408 struct assembly *assembly = &actctx->assemblies[i];
3409 for (j = 0; j < assembly->num_dlls; j++)
3411 struct dll_redirect *dll = &assembly->dlls[j];
3413 /* each entry needs index, data and string data */
3414 total_len += sizeof(*index);
3415 total_len += sizeof(*data);
3416 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3419 dll_count += assembly->num_dlls;
3422 total_len += sizeof(*header);
3424 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3425 if (!header) return STATUS_NO_MEMORY;
3427 memset(header, 0, sizeof(*header));
3428 header->magic = STRSECTION_MAGIC;
3429 header->size = sizeof(*header);
3430 header->count = dll_count;
3431 header->index_offset = sizeof(*header);
3432 index = (struct string_index*)((BYTE*)header + header->index_offset);
3433 name_offset = header->index_offset + header->count*sizeof(*index);
3435 for (i = 0; i < actctx->num_assemblies; i++)
3437 struct assembly *assembly = &actctx->assemblies[i];
3438 for (j = 0; j < assembly->num_dlls; j++)
3440 struct dll_redirect *dll = &assembly->dlls[j];
3441 UNICODE_STRING str;
3442 WCHAR *ptrW;
3444 /* setup new index entry */
3445 str.Buffer = dll->name;
3446 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3447 str.MaximumLength = str.Length + sizeof(WCHAR);
3448 /* hash original class name */
3449 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3451 index->name_offset = name_offset;
3452 index->name_len = str.Length;
3453 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3454 index->data_len = sizeof(*data);
3455 index->rosterindex = i + 1;
3457 /* setup data */
3458 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3459 data->size = sizeof(*data);
3460 data->unk = 2; /* FIXME: seems to be constant */
3461 memset(data->res, 0, sizeof(data->res));
3463 /* dll name */
3464 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3465 memcpy(ptrW, dll->name, index->name_len);
3466 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3468 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3470 index++;
3474 *section = header;
3476 return STATUS_SUCCESS;
3479 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3481 struct string_index *iter, *index = NULL;
3482 ULONG hash = 0, i;
3484 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3485 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3487 for (i = 0; i < section->count; i++)
3489 if (iter->hash == hash)
3491 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3493 if (!strcmpiW(nameW, name->Buffer))
3495 index = iter;
3496 break;
3498 else
3499 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3501 iter++;
3504 return index;
3507 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3509 struct guid_index *iter, *index = NULL;
3510 ULONG i;
3512 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3514 for (i = 0; i < section->count; i++)
3516 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3518 index = iter;
3519 break;
3521 iter++;
3524 return index;
3527 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3529 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3532 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3533 PACTCTX_SECTION_KEYED_DATA data)
3535 struct dllredirect_data *dll;
3536 struct string_index *index;
3538 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3540 if (!actctx->dllredirect_section)
3542 struct strsection_header *section;
3544 NTSTATUS status = build_dllredirect_section(actctx, &section);
3545 if (status) return status;
3547 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3548 RtlFreeHeap(GetProcessHeap(), 0, section);
3551 index = find_string_index(actctx->dllredirect_section, name);
3552 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3554 if (data)
3556 dll = get_dllredirect_data(actctx, index);
3558 data->ulDataFormatVersion = 1;
3559 data->lpData = dll;
3560 data->ulLength = dll->size;
3561 data->lpSectionGlobalData = NULL;
3562 data->ulSectionGlobalDataLength = 0;
3563 data->lpSectionBase = actctx->dllredirect_section;
3564 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3565 data->hActCtx = NULL;
3567 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3568 data->ulAssemblyRosterIndex = index->rosterindex;
3571 return STATUS_SUCCESS;
3574 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3576 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3579 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3581 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3584 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3586 unsigned int i, j, k, total_len = 0, class_count = 0;
3587 struct wndclass_redirect_data *data;
3588 struct strsection_header *header;
3589 struct string_index *index;
3590 ULONG name_offset;
3592 /* compute section length */
3593 for (i = 0; i < actctx->num_assemblies; i++)
3595 struct assembly *assembly = &actctx->assemblies[i];
3596 for (j = 0; j < assembly->num_dlls; j++)
3598 struct dll_redirect *dll = &assembly->dlls[j];
3599 for (k = 0; k < dll->entities.num; k++)
3601 struct entity *entity = &dll->entities.base[k];
3602 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3604 int class_len = strlenW(entity->u.class.name) + 1;
3605 int len;
3607 /* each class entry needs index, data and string data */
3608 total_len += sizeof(*index);
3609 total_len += sizeof(*data);
3610 /* original name is stored separately */
3611 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3612 /* versioned name and module name are stored one after another */
3613 if (entity->u.class.versioned)
3614 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3615 else
3616 len = class_len;
3617 len += strlenW(dll->name) + 1;
3618 total_len += aligned_string_len(len*sizeof(WCHAR));
3620 class_count++;
3626 total_len += sizeof(*header);
3628 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3629 if (!header) return STATUS_NO_MEMORY;
3631 memset(header, 0, sizeof(*header));
3632 header->magic = STRSECTION_MAGIC;
3633 header->size = sizeof(*header);
3634 header->count = class_count;
3635 header->index_offset = sizeof(*header);
3636 index = (struct string_index*)((BYTE*)header + header->index_offset);
3637 name_offset = header->index_offset + header->count*sizeof(*index);
3639 for (i = 0; i < actctx->num_assemblies; i++)
3641 struct assembly *assembly = &actctx->assemblies[i];
3642 for (j = 0; j < assembly->num_dlls; j++)
3644 struct dll_redirect *dll = &assembly->dlls[j];
3645 for (k = 0; k < dll->entities.num; k++)
3647 struct entity *entity = &dll->entities.base[k];
3648 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3650 static const WCHAR exclW[] = {'!',0};
3651 ULONG versioned_len, module_len;
3652 UNICODE_STRING str;
3653 WCHAR *ptrW;
3655 /* setup new index entry */
3656 str.Buffer = entity->u.class.name;
3657 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3658 str.MaximumLength = str.Length + sizeof(WCHAR);
3659 /* hash original class name */
3660 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3662 /* include '!' separator too */
3663 if (entity->u.class.versioned)
3664 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3665 else
3666 versioned_len = str.Length;
3667 module_len = strlenW(dll->name)*sizeof(WCHAR);
3669 index->name_offset = name_offset;
3670 index->name_len = str.Length;
3671 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3672 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3673 index->rosterindex = i + 1;
3675 /* setup data */
3676 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3677 data->size = sizeof(*data);
3678 data->res = 0;
3679 data->name_len = versioned_len;
3680 data->name_offset = sizeof(*data);
3681 data->module_len = module_len;
3682 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3684 /* original class name */
3685 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3686 memcpy(ptrW, entity->u.class.name, index->name_len);
3687 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3689 /* module name */
3690 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3691 memcpy(ptrW, dll->name, data->module_len);
3692 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3694 /* versioned name */
3695 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3696 if (entity->u.class.versioned)
3698 get_assembly_version(assembly, ptrW);
3699 strcatW(ptrW, exclW);
3700 strcatW(ptrW, entity->u.class.name);
3702 else
3704 memcpy(ptrW, entity->u.class.name, index->name_len);
3705 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3708 name_offset += sizeof(*data);
3709 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3711 index++;
3717 *section = header;
3719 return STATUS_SUCCESS;
3722 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3723 PACTCTX_SECTION_KEYED_DATA data)
3725 struct string_index *iter, *index = NULL;
3726 struct wndclass_redirect_data *class;
3727 ULONG hash;
3728 int i;
3730 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3732 if (!actctx->wndclass_section)
3734 struct strsection_header *section;
3736 NTSTATUS status = build_wndclass_section(actctx, &section);
3737 if (status) return status;
3739 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3740 RtlFreeHeap(GetProcessHeap(), 0, section);
3743 hash = 0;
3744 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3745 iter = get_wndclass_first_index(actctx);
3747 for (i = 0; i < actctx->wndclass_section->count; i++)
3749 if (iter->hash == hash)
3751 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3753 if (!strcmpiW(nameW, name->Buffer))
3755 index = iter;
3756 break;
3758 else
3759 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3761 iter++;
3764 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3766 if (data)
3768 class = get_wndclass_data(actctx, index);
3770 data->ulDataFormatVersion = 1;
3771 data->lpData = class;
3772 /* full length includes string length with nulls */
3773 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3774 data->lpSectionGlobalData = NULL;
3775 data->ulSectionGlobalDataLength = 0;
3776 data->lpSectionBase = actctx->wndclass_section;
3777 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3778 data->hActCtx = NULL;
3780 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3781 data->ulAssemblyRosterIndex = index->rosterindex;
3784 return STATUS_SUCCESS;
3787 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3789 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3790 struct guidsection_header *header;
3791 ULONG module_offset, data_offset;
3792 struct tlibredirect_data *data;
3793 struct guid_index *index;
3795 /* compute section length */
3796 for (i = 0; i < actctx->num_assemblies; i++)
3798 struct assembly *assembly = &actctx->assemblies[i];
3799 for (j = 0; j < assembly->num_dlls; j++)
3801 struct dll_redirect *dll = &assembly->dlls[j];
3802 for (k = 0; k < dll->entities.num; k++)
3804 struct entity *entity = &dll->entities.base[k];
3805 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3807 /* each entry needs index, data and string data for module name and help string */
3808 total_len += sizeof(*index);
3809 total_len += sizeof(*data);
3810 /* help string is stored separately */
3811 if (*entity->u.typelib.helpdir)
3812 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3814 /* module names are packed one after another */
3815 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3817 tlib_count++;
3823 total_len += aligned_string_len(names_len);
3824 total_len += sizeof(*header);
3826 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3827 if (!header) return STATUS_NO_MEMORY;
3829 memset(header, 0, sizeof(*header));
3830 header->magic = GUIDSECTION_MAGIC;
3831 header->size = sizeof(*header);
3832 header->count = tlib_count;
3833 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3834 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3835 module_offset = sizeof(*header);
3836 data_offset = header->index_offset + tlib_count*sizeof(*index);
3838 for (i = 0; i < actctx->num_assemblies; i++)
3840 struct assembly *assembly = &actctx->assemblies[i];
3841 for (j = 0; j < assembly->num_dlls; j++)
3843 struct dll_redirect *dll = &assembly->dlls[j];
3844 for (k = 0; k < dll->entities.num; k++)
3846 struct entity *entity = &dll->entities.base[k];
3847 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3849 ULONG module_len, help_len;
3850 UNICODE_STRING str;
3851 WCHAR *ptrW;
3853 if (*entity->u.typelib.helpdir)
3854 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3855 else
3856 help_len = 0;
3858 module_len = strlenW(dll->name)*sizeof(WCHAR);
3860 /* setup new index entry */
3861 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3862 RtlGUIDFromString(&str, &index->guid);
3863 index->data_offset = data_offset;
3864 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3865 index->rosterindex = i + 1;
3867 /* setup data */
3868 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3869 data->size = sizeof(*data);
3870 data->res = 0;
3871 data->name_len = module_len;
3872 data->name_offset = module_offset;
3873 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3874 data->langid = 0;
3875 data->flags = entity->u.typelib.flags;
3876 data->help_len = help_len;
3877 data->help_offset = sizeof(*data);
3878 data->major_version = entity->u.typelib.major;
3879 data->minor_version = entity->u.typelib.minor;
3881 /* module name */
3882 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3883 memcpy(ptrW, dll->name, data->name_len);
3884 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3886 /* help string */
3887 if (data->help_len)
3889 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3890 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3891 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3894 data_offset += sizeof(*data);
3895 if (help_len)
3896 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3898 module_offset += module_len + sizeof(WCHAR);
3900 index++;
3906 *section = header;
3908 return STATUS_SUCCESS;
3911 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3913 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3916 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3918 struct guid_index *index = NULL;
3919 struct tlibredirect_data *tlib;
3921 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3923 if (!actctx->tlib_section)
3925 struct guidsection_header *section;
3927 NTSTATUS status = build_tlib_section(actctx, &section);
3928 if (status) return status;
3930 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3931 RtlFreeHeap(GetProcessHeap(), 0, section);
3934 index = find_guid_index(actctx->tlib_section, guid);
3935 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3937 tlib = get_tlib_data(actctx, index);
3939 data->ulDataFormatVersion = 1;
3940 data->lpData = tlib;
3941 /* full length includes string length with nulls */
3942 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3943 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3944 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3945 data->lpSectionBase = actctx->tlib_section;
3946 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3947 data->hActCtx = NULL;
3949 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3950 data->ulAssemblyRosterIndex = index->rosterindex;
3952 return STATUS_SUCCESS;
3955 static void generate_uuid(ULONG *seed, GUID *guid)
3957 ULONG *ptr = (ULONG*)guid;
3958 int i;
3960 /* GUID is 16 bytes long */
3961 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3962 *ptr = RtlUniform(seed);
3964 guid->Data3 &= 0x0fff;
3965 guid->Data3 |= (4 << 12);
3966 guid->Data4[0] &= 0x3f;
3967 guid->Data4[0] |= 0x80;
3970 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3971 unsigned int *count, unsigned int *len, unsigned int *module_len)
3973 unsigned int i;
3975 for (i = 0; i < entities->num; i++)
3977 struct entity *entity = &entities->base[i];
3978 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3980 /* each entry needs two index entries, extra one goes for alias GUID */
3981 *len += 2*sizeof(struct guid_index);
3982 /* To save some memory we don't allocated two data structures,
3983 instead alias index and normal index point to the same data structure. */
3984 *len += sizeof(struct comclassredirect_data);
3986 /* for clrClass store some more */
3987 if (entity->u.comclass.name)
3989 unsigned int str_len;
3991 /* all string data is stored together in aligned block */
3992 str_len = strlenW(entity->u.comclass.name)+1;
3993 if (entity->u.comclass.progid)
3994 str_len += strlenW(entity->u.comclass.progid)+1;
3995 if (entity->u.comclass.version)
3996 str_len += strlenW(entity->u.comclass.version)+1;
3998 *len += sizeof(struct clrclass_data);
3999 *len += aligned_string_len(str_len*sizeof(WCHAR));
4001 /* module name is forced to mscoree.dll, and stored two times with different case */
4002 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4004 else
4006 /* progid string is stored separately */
4007 if (entity->u.comclass.progid)
4008 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4010 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
4013 *count += 1;
4018 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4019 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4020 ULONG *seed, ULONG rosterindex)
4022 unsigned int i;
4024 for (i = 0; i < entities->num; i++)
4026 struct entity *entity = &entities->base[i];
4027 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4029 ULONG module_len, progid_len, str_len = 0;
4030 struct comclassredirect_data *data;
4031 struct guid_index *alias_index;
4032 struct clrclass_data *clrdata;
4033 UNICODE_STRING str;
4034 WCHAR *ptrW;
4036 if (entity->u.comclass.progid)
4037 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4038 else
4039 progid_len = 0;
4041 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4043 /* setup new index entry */
4044 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4045 RtlGUIDFromString(&str, &(*index)->guid);
4047 (*index)->data_offset = *data_offset;
4048 (*index)->data_len = sizeof(*data); /* additional length added later */
4049 (*index)->rosterindex = rosterindex;
4051 /* Setup new index entry for alias guid. Alias index records are placed after
4052 normal records, so normal guids are hit first on search. Note that class count
4053 is doubled. */
4054 alias_index = (*index) + section->count/2;
4055 generate_uuid(seed, &alias_index->guid);
4056 alias_index->data_offset = (*index)->data_offset;
4057 alias_index->data_len = 0;
4058 alias_index->rosterindex = (*index)->rosterindex;
4060 /* setup data */
4061 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4062 data->size = sizeof(*data);
4063 data->res = 0;
4064 data->res1[0] = 0;
4065 data->res1[1] = 0;
4066 data->model = entity->u.comclass.model;
4067 data->clsid = (*index)->guid;
4068 data->alias = alias_index->guid;
4069 data->clsid2 = data->clsid;
4070 if (entity->u.comclass.tlbid)
4072 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4073 RtlGUIDFromString(&str, &data->tlbid);
4075 else
4076 memset(&data->tlbid, 0, sizeof(data->tlbid));
4077 data->name_len = module_len;
4078 data->name_offset = *module_offset;
4079 data->progid_len = progid_len;
4080 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4081 data->clrdata_len = 0; /* will be set later */
4082 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4083 data->miscstatus = entity->u.comclass.miscstatus;
4084 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4085 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4086 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4087 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4089 /* mask describes which misc* data is available */
4090 data->miscmask = 0;
4091 if (data->miscstatus)
4092 data->miscmask |= MiscStatus;
4093 if (data->miscstatuscontent)
4094 data->miscmask |= MiscStatusContent;
4095 if (data->miscstatusthumbnail)
4096 data->miscmask |= MiscStatusThumbnail;
4097 if (data->miscstatusicon)
4098 data->miscmask |= MiscStatusIcon;
4099 if (data->miscstatusdocprint)
4100 data->miscmask |= MiscStatusDocPrint;
4102 if (data->clrdata_offset)
4104 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4106 clrdata->size = sizeof(*clrdata);
4107 clrdata->res[0] = 0;
4108 clrdata->res[1] = 2; /* FIXME: unknown field */
4109 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4110 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4111 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4112 clrdata->name_offset = clrdata->size;
4113 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4114 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4115 clrdata->res2[0] = 0;
4116 clrdata->res2[1] = 0;
4118 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4120 /* module name */
4121 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4122 memcpy(ptrW, mscoree2W, clrdata->module_len);
4123 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4125 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4126 memcpy(ptrW, mscoreeW, data->name_len);
4127 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4129 /* class name */
4130 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4131 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4132 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4134 /* runtime version, optional */
4135 if (clrdata->version_len)
4137 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4139 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4140 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4141 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4144 if (data->progid_len)
4145 data->progid_offset += data->clrdata_len;
4146 (*index)->data_len += sizeof(*clrdata);
4148 else
4150 clrdata = NULL;
4152 /* module name */
4153 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4154 memcpy(ptrW, dll->name, data->name_len);
4155 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4158 /* progid string */
4159 if (data->progid_len)
4161 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4162 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4163 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4166 /* string block length */
4167 str_len = 0;
4168 if (clrdata)
4170 str_len += clrdata->name_len + sizeof(WCHAR);
4171 if (clrdata->version_len)
4172 str_len += clrdata->version_len + sizeof(WCHAR);
4174 if (progid_len)
4175 str_len += progid_len + sizeof(WCHAR);
4177 (*index)->data_len += aligned_string_len(str_len);
4178 alias_index->data_len = (*index)->data_len;
4180 /* move to next data record */
4181 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4182 (*module_offset) += module_len + sizeof(WCHAR);
4184 if (clrdata)
4186 (*data_offset) += sizeof(*clrdata);
4187 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4189 (*index) += 1;
4194 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4196 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4197 struct guidsection_header *header;
4198 ULONG module_offset, data_offset;
4199 struct guid_index *index;
4200 ULONG seed;
4202 /* compute section length */
4203 for (i = 0; i < actctx->num_assemblies; i++)
4205 struct assembly *assembly = &actctx->assemblies[i];
4206 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4207 for (j = 0; j < assembly->num_dlls; j++)
4209 struct dll_redirect *dll = &assembly->dlls[j];
4210 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4214 total_len += aligned_string_len(names_len);
4215 total_len += sizeof(*header);
4217 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4218 if (!header) return STATUS_NO_MEMORY;
4220 memset(header, 0, sizeof(*header));
4221 header->magic = GUIDSECTION_MAGIC;
4222 header->size = sizeof(*header);
4223 header->count = 2*class_count;
4224 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4225 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4226 module_offset = sizeof(*header);
4227 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4229 seed = NtGetTickCount();
4230 for (i = 0; i < actctx->num_assemblies; i++)
4232 struct assembly *assembly = &actctx->assemblies[i];
4233 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4234 for (j = 0; j < assembly->num_dlls; j++)
4236 struct dll_redirect *dll = &assembly->dlls[j];
4237 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4241 *section = header;
4243 return STATUS_SUCCESS;
4246 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4248 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4251 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4253 struct comclassredirect_data *comclass;
4254 struct guid_index *index = NULL;
4256 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4258 if (!actctx->comserver_section)
4260 struct guidsection_header *section;
4262 NTSTATUS status = build_comserver_section(actctx, &section);
4263 if (status) return status;
4265 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4266 RtlFreeHeap(GetProcessHeap(), 0, section);
4269 index = find_guid_index(actctx->comserver_section, guid);
4270 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4272 comclass = get_comclass_data(actctx, index);
4274 data->ulDataFormatVersion = 1;
4275 data->lpData = comclass;
4276 /* full length includes string length with nulls */
4277 data->ulLength = comclass->size + comclass->clrdata_len;
4278 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4279 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4280 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4281 data->lpSectionBase = actctx->comserver_section;
4282 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4283 data->hActCtx = NULL;
4285 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4286 data->ulAssemblyRosterIndex = index->rosterindex;
4288 return STATUS_SUCCESS;
4291 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4293 unsigned int i;
4295 for (i = 0; i < entities->num; i++)
4297 struct entity *entity = &entities->base[i];
4298 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4300 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4301 if (entity->u.ifaceps.name)
4302 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4303 *count += 1;
4308 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4309 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4311 unsigned int i;
4313 for (i = 0; i < entities->num; i++)
4315 struct entity *entity = &entities->base[i];
4316 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4318 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4319 UNICODE_STRING str;
4320 ULONG name_len;
4322 if (entity->u.ifaceps.name)
4323 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4324 else
4325 name_len = 0;
4327 /* setup index */
4328 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4329 RtlGUIDFromString(&str, &(*index)->guid);
4330 (*index)->data_offset = *data_offset;
4331 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4332 (*index)->rosterindex = rosterindex;
4334 /* setup data record */
4335 data->size = sizeof(*data);
4336 data->mask = entity->u.ifaceps.mask;
4338 /* proxyStubClsid32 value is only stored for external PS,
4339 if set it's used as iid, otherwise 'iid' attribute value is used */
4340 if (entity->u.ifaceps.ps32)
4342 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4343 RtlGUIDFromString(&str, &data->iid);
4345 else
4346 data->iid = (*index)->guid;
4348 data->nummethods = entity->u.ifaceps.nummethods;
4350 if (entity->u.ifaceps.tlib)
4352 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4353 RtlGUIDFromString(&str, &data->tlbid);
4355 else
4356 memset(&data->tlbid, 0, sizeof(data->tlbid));
4358 if (entity->u.ifaceps.base)
4360 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4361 RtlGUIDFromString(&str, &data->base);
4363 else
4364 memset(&data->base, 0, sizeof(data->base));
4366 data->name_len = name_len;
4367 data->name_offset = data->name_len ? sizeof(*data) : 0;
4369 /* name string */
4370 if (data->name_len)
4372 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4373 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4374 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4377 /* move to next record */
4378 (*index) += 1;
4379 *data_offset += sizeof(*data);
4380 if (data->name_len)
4381 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4386 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4388 unsigned int i, j, total_len = 0, count = 0;
4389 struct guidsection_header *header;
4390 struct guid_index *index;
4391 ULONG data_offset;
4393 /* compute section length */
4394 for (i = 0; i < actctx->num_assemblies; i++)
4396 struct assembly *assembly = &actctx->assemblies[i];
4398 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4399 for (j = 0; j < assembly->num_dlls; j++)
4401 struct dll_redirect *dll = &assembly->dlls[j];
4402 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4406 total_len += sizeof(*header);
4408 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4409 if (!header) return STATUS_NO_MEMORY;
4411 memset(header, 0, sizeof(*header));
4412 header->magic = GUIDSECTION_MAGIC;
4413 header->size = sizeof(*header);
4414 header->count = count;
4415 header->index_offset = sizeof(*header);
4416 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4417 data_offset = header->index_offset + count*sizeof(*index);
4419 for (i = 0; i < actctx->num_assemblies; i++)
4421 struct assembly *assembly = &actctx->assemblies[i];
4423 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4424 for (j = 0; j < assembly->num_dlls; j++)
4426 struct dll_redirect *dll = &assembly->dlls[j];
4427 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4431 *section = header;
4433 return STATUS_SUCCESS;
4436 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4438 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4441 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4443 struct ifacepsredirect_data *iface;
4444 struct guid_index *index = NULL;
4446 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4448 if (!actctx->ifaceps_section)
4450 struct guidsection_header *section;
4452 NTSTATUS status = build_ifaceps_section(actctx, &section);
4453 if (status) return status;
4455 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4456 RtlFreeHeap(GetProcessHeap(), 0, section);
4459 index = find_guid_index(actctx->ifaceps_section, guid);
4460 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4462 iface = get_ifaceps_data(actctx, index);
4464 data->ulDataFormatVersion = 1;
4465 data->lpData = iface;
4466 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4467 data->lpSectionGlobalData = NULL;
4468 data->ulSectionGlobalDataLength = 0;
4469 data->lpSectionBase = actctx->ifaceps_section;
4470 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4471 data->hActCtx = NULL;
4473 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4474 data->ulAssemblyRosterIndex = index->rosterindex;
4476 return STATUS_SUCCESS;
4479 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4481 unsigned int i, j, total_len = 0, count = 0;
4482 struct guidsection_header *header;
4483 struct clrsurrogate_data *data;
4484 struct guid_index *index;
4485 ULONG data_offset;
4487 /* compute section length */
4488 for (i = 0; i < actctx->num_assemblies; i++)
4490 struct assembly *assembly = &actctx->assemblies[i];
4491 for (j = 0; j < assembly->entities.num; j++)
4493 struct entity *entity = &assembly->entities.base[j];
4494 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4496 ULONG len;
4498 total_len += sizeof(*index) + sizeof(*data);
4499 len = strlenW(entity->u.clrsurrogate.name) + 1;
4500 if (entity->u.clrsurrogate.version)
4501 len += strlenW(entity->u.clrsurrogate.version) + 1;
4502 total_len += aligned_string_len(len*sizeof(WCHAR));
4504 count++;
4509 total_len += sizeof(*header);
4511 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4512 if (!header) return STATUS_NO_MEMORY;
4514 memset(header, 0, sizeof(*header));
4515 header->magic = GUIDSECTION_MAGIC;
4516 header->size = sizeof(*header);
4517 header->count = count;
4518 header->index_offset = sizeof(*header);
4519 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4520 data_offset = header->index_offset + count*sizeof(*index);
4522 for (i = 0; i < actctx->num_assemblies; i++)
4524 struct assembly *assembly = &actctx->assemblies[i];
4525 for (j = 0; j < assembly->entities.num; j++)
4527 struct entity *entity = &assembly->entities.base[j];
4528 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4530 ULONG version_len, name_len;
4531 UNICODE_STRING str;
4532 WCHAR *ptrW;
4534 if (entity->u.clrsurrogate.version)
4535 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4536 else
4537 version_len = 0;
4538 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4540 /* setup new index entry */
4541 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4542 RtlGUIDFromString(&str, &index->guid);
4544 index->data_offset = data_offset;
4545 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4546 index->rosterindex = i + 1;
4548 /* setup data */
4549 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4550 data->size = sizeof(*data);
4551 data->res = 0;
4552 data->clsid = index->guid;
4553 data->version_offset = version_len ? data->size : 0;
4554 data->version_len = version_len;
4555 data->name_offset = data->size + version_len;
4556 if (version_len)
4557 data->name_offset += sizeof(WCHAR);
4558 data->name_len = name_len;
4560 /* surrogate name */
4561 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4562 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4563 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4565 /* runtime version */
4566 if (data->version_len)
4568 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4569 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4570 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4573 data_offset += index->data_offset;
4574 index++;
4579 *section = header;
4581 return STATUS_SUCCESS;
4584 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4586 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4589 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4591 struct clrsurrogate_data *surrogate;
4592 struct guid_index *index = NULL;
4594 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4596 if (!actctx->clrsurrogate_section)
4598 struct guidsection_header *section;
4600 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4601 if (status) return status;
4603 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4604 RtlFreeHeap(GetProcessHeap(), 0, section);
4607 index = find_guid_index(actctx->clrsurrogate_section, guid);
4608 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4610 surrogate = get_surrogate_data(actctx, index);
4612 data->ulDataFormatVersion = 1;
4613 data->lpData = surrogate;
4614 /* full length includes string length with nulls */
4615 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4616 if (surrogate->version_len)
4617 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4619 data->lpSectionGlobalData = NULL;
4620 data->ulSectionGlobalDataLength = 0;
4621 data->lpSectionBase = actctx->clrsurrogate_section;
4622 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4623 data->hActCtx = NULL;
4625 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4626 data->ulAssemblyRosterIndex = index->rosterindex;
4628 return STATUS_SUCCESS;
4631 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4633 unsigned int i, j, single_len;
4635 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4636 for (i = 0; i < entities->num; i++)
4638 struct entity *entity = &entities->base[i];
4639 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4641 if (entity->u.comclass.progid)
4643 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4644 *count += 1;
4647 for (j = 0; j < entity->u.comclass.progids.num; j++)
4648 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4650 *total_len += single_len*entity->u.comclass.progids.num;
4651 *count += entity->u.comclass.progids.num;
4656 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4657 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4659 struct progidredirect_data *data;
4660 UNICODE_STRING str;
4661 GUID *guid_ptr;
4662 WCHAR *ptrW;
4664 /* setup new index entry */
4666 /* hash progid name */
4667 RtlInitUnicodeString(&str, progid);
4668 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4670 (*index)->name_offset = *data_offset;
4671 (*index)->name_len = str.Length;
4672 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4673 (*index)->data_len = sizeof(*data);
4674 (*index)->rosterindex = rosterindex;
4676 *data_offset += aligned_string_len(str.MaximumLength);
4678 /* setup data structure */
4679 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4680 data->size = sizeof(*data);
4681 data->reserved = 0;
4682 data->clsid_offset = *global_offset;
4684 /* write progid string */
4685 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4686 memcpy(ptrW, progid, (*index)->name_len);
4687 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4689 /* write guid to global area */
4690 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4691 *guid_ptr = *alias;
4693 /* to next entry */
4694 *global_offset += sizeof(GUID);
4695 *data_offset += data->size;
4696 (*index) += 1;
4699 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4700 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4702 unsigned int i, j;
4704 for (i = 0; i < entities->num; i++)
4706 struct entity *entity = &entities->base[i];
4707 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4709 const struct progids *progids = &entity->u.comclass.progids;
4710 struct comclassredirect_data *comclass;
4711 struct guid_index *guid_index;
4712 UNICODE_STRING str;
4713 GUID clsid;
4715 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4716 RtlGUIDFromString(&str, &clsid);
4718 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4719 comclass = get_comclass_data(actctx, guid_index);
4721 if (entity->u.comclass.progid)
4722 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4723 index, data_offset, global_offset, rosterindex);
4725 for (j = 0; j < progids->num; j++)
4726 write_progid_record(section, progids->progids[j], &comclass->alias,
4727 index, data_offset, global_offset, rosterindex);
4732 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4734 unsigned int i, j, total_len = 0, count = 0;
4735 struct strsection_header *header;
4736 ULONG data_offset, global_offset;
4737 struct string_index *index;
4739 /* compute section length */
4740 for (i = 0; i < actctx->num_assemblies; i++)
4742 struct assembly *assembly = &actctx->assemblies[i];
4744 get_progid_datalen(&assembly->entities, &count, &total_len);
4745 for (j = 0; j < assembly->num_dlls; j++)
4747 struct dll_redirect *dll = &assembly->dlls[j];
4748 get_progid_datalen(&dll->entities, &count, &total_len);
4752 total_len += sizeof(*header);
4754 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4755 if (!header) return STATUS_NO_MEMORY;
4757 memset(header, 0, sizeof(*header));
4758 header->magic = STRSECTION_MAGIC;
4759 header->size = sizeof(*header);
4760 header->count = count;
4761 header->global_offset = header->size;
4762 header->global_len = count*sizeof(GUID);
4763 header->index_offset = header->size + header->global_len;
4765 index = (struct string_index*)((BYTE*)header + header->index_offset);
4766 data_offset = header->index_offset + count*sizeof(*index);
4767 global_offset = header->global_offset;
4769 for (i = 0; i < actctx->num_assemblies; i++)
4771 struct assembly *assembly = &actctx->assemblies[i];
4773 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4774 for (j = 0; j < assembly->num_dlls; j++)
4776 struct dll_redirect *dll = &assembly->dlls[j];
4777 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4781 *section = header;
4783 return STATUS_SUCCESS;
4786 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4788 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4791 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4792 PACTCTX_SECTION_KEYED_DATA data)
4794 struct progidredirect_data *progid;
4795 struct string_index *index;
4797 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4799 if (!actctx->comserver_section)
4801 struct guidsection_header *section;
4803 NTSTATUS status = build_comserver_section(actctx, &section);
4804 if (status) return status;
4806 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4807 RtlFreeHeap(GetProcessHeap(), 0, section);
4810 if (!actctx->progid_section)
4812 struct strsection_header *section;
4814 NTSTATUS status = build_progid_section(actctx, &section);
4815 if (status) return status;
4817 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4818 RtlFreeHeap(GetProcessHeap(), 0, section);
4821 index = find_string_index(actctx->progid_section, name);
4822 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4824 if (data)
4826 progid = get_progid_data(actctx, index);
4828 data->ulDataFormatVersion = 1;
4829 data->lpData = progid;
4830 data->ulLength = progid->size;
4831 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4832 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4833 data->lpSectionBase = actctx->progid_section;
4834 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4835 data->hActCtx = NULL;
4837 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4838 data->ulAssemblyRosterIndex = index->rosterindex;
4841 return STATUS_SUCCESS;
4844 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4845 const UNICODE_STRING *section_name,
4846 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4848 NTSTATUS status;
4850 switch (section_kind)
4852 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4853 status = find_dll_redirection(actctx, section_name, data);
4854 break;
4855 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4856 status = find_window_class(actctx, section_name, data);
4857 break;
4858 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4859 status = find_progid_redirection(actctx, section_name, data);
4860 break;
4861 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4862 FIXME("Unsupported yet section_kind %x\n", section_kind);
4863 return STATUS_SXS_SECTION_NOT_FOUND;
4864 default:
4865 WARN("Unknown section_kind %x\n", section_kind);
4866 return STATUS_SXS_SECTION_NOT_FOUND;
4869 if (status != STATUS_SUCCESS) return status;
4871 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4873 actctx_addref(actctx);
4874 data->hActCtx = actctx;
4876 return STATUS_SUCCESS;
4879 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4880 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4882 NTSTATUS status;
4884 switch (section_kind)
4886 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4887 status = find_tlib_redirection(actctx, guid, data);
4888 break;
4889 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4890 status = find_comserver_redirection(actctx, guid, data);
4891 break;
4892 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4893 status = find_cominterface_redirection(actctx, guid, data);
4894 break;
4895 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4896 status = find_clr_surrogate(actctx, guid, data);
4897 break;
4898 default:
4899 WARN("Unknown section_kind %x\n", section_kind);
4900 return STATUS_SXS_SECTION_NOT_FOUND;
4903 if (status != STATUS_SUCCESS) return status;
4905 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4907 actctx_addref(actctx);
4908 data->hActCtx = actctx;
4910 return STATUS_SUCCESS;
4913 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4915 unsigned int i, j;
4917 for (i = 0; i < actctx->num_assemblies; i++)
4919 struct assembly *assembly = &actctx->assemblies[i];
4920 for (j = 0; j < assembly->entities.num; j++)
4922 struct entity *entity = &assembly->entities.base[j];
4923 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4924 !strcmpW( entity->u.settings.name, settings ) &&
4925 !strcmpW( entity->u.settings.ns, ns ))
4926 return entity->u.settings.value;
4929 return NULL;
4932 /* initialize the activation context for the current process */
4933 void actctx_init(void)
4935 ACTCTXW ctx;
4936 HANDLE handle;
4938 ctx.cbSize = sizeof(ctx);
4939 ctx.lpSource = NULL;
4940 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4941 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4942 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4944 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4946 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
4950 /***********************************************************************
4951 * RtlCreateActivationContext (NTDLL.@)
4953 * Create an activation context.
4955 * FIXME: function signature/prototype is wrong
4957 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4959 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4960 const WCHAR *directory = NULL;
4961 ACTIVATION_CONTEXT *actctx;
4962 UNICODE_STRING nameW;
4963 ULONG lang = 0;
4964 NTSTATUS status = STATUS_NO_MEMORY;
4965 HANDLE file = 0;
4966 struct actctx_loader acl;
4968 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4970 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4971 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4972 return STATUS_INVALID_PARAMETER;
4974 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4975 return STATUS_NO_MEMORY;
4977 actctx->magic = ACTCTX_MAGIC;
4978 actctx->ref_count = 1;
4979 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4980 actctx->config.info = NULL;
4981 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4982 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4984 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4986 else
4988 UNICODE_STRING dir;
4989 WCHAR *p;
4990 HMODULE module;
4992 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4993 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4995 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4996 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4997 actctx->appdir.info = dir.Buffer;
5000 nameW.Buffer = NULL;
5002 /* open file only if it's going to be used */
5003 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5004 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5006 WCHAR *source = NULL;
5007 BOOLEAN ret;
5009 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5010 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5012 DWORD dir_len, source_len;
5014 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
5015 source_len = strlenW(pActCtx->lpSource);
5016 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5018 status = STATUS_NO_MEMORY;
5019 goto error;
5022 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5023 source[dir_len] = '\\';
5024 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5027 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5028 RtlFreeHeap( GetProcessHeap(), 0, source );
5029 if (!ret)
5031 status = STATUS_NO_SUCH_FILE;
5032 goto error;
5034 status = open_nt_file( &file, &nameW );
5035 if (status)
5037 RtlFreeUnicodeString( &nameW );
5038 goto error;
5042 acl.actctx = actctx;
5043 acl.dependencies = NULL;
5044 acl.num_dependencies = 0;
5045 acl.allocated_dependencies = 0;
5047 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5048 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5050 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5052 /* if we have a resource it's a PE file */
5053 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5055 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5056 pActCtx->lpResourceName, lang );
5057 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5058 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5059 pActCtx->hModule, pActCtx->lpResourceName );
5061 else if (pActCtx->lpSource)
5063 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5064 file, pActCtx->lpResourceName, lang );
5065 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5066 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5067 NULL, pActCtx->lpResourceName );
5069 else status = STATUS_INVALID_PARAMETER;
5071 else
5073 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5076 if (file) NtClose( file );
5077 RtlFreeUnicodeString( &nameW );
5079 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5080 free_depend_manifests( &acl );
5082 if (status == STATUS_SUCCESS) *handle = actctx;
5083 else actctx_release( actctx );
5084 return status;
5086 error:
5087 if (file) NtClose( file );
5088 actctx_release( actctx );
5089 return status;
5093 /***********************************************************************
5094 * RtlAddRefActivationContext (NTDLL.@)
5096 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5098 ACTIVATION_CONTEXT *actctx;
5100 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5104 /******************************************************************
5105 * RtlReleaseActivationContext (NTDLL.@)
5107 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5109 ACTIVATION_CONTEXT *actctx;
5111 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5114 /******************************************************************
5115 * RtlZombifyActivationContext (NTDLL.@)
5117 * FIXME: function prototype might be wrong
5119 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5121 FIXME("%p: stub\n", handle);
5122 return STATUS_NOT_IMPLEMENTED;
5125 /******************************************************************
5126 * RtlActivateActivationContext (NTDLL.@)
5128 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5130 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5132 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5133 return STATUS_NO_MEMORY;
5135 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5136 frame->ActivationContext = handle;
5137 frame->Flags = 0;
5138 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5139 RtlAddRefActivationContext( handle );
5141 *cookie = (ULONG_PTR)frame;
5142 TRACE( "%p cookie=%lx\n", handle, *cookie );
5143 return STATUS_SUCCESS;
5147 /***********************************************************************
5148 * RtlDeactivateActivationContext (NTDLL.@)
5150 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5152 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5154 TRACE( "%x cookie=%lx\n", flags, cookie );
5156 /* find the right frame */
5157 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5158 for (frame = top; frame; frame = frame->Previous)
5159 if ((ULONG_PTR)frame == cookie) break;
5161 if (!frame)
5162 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5164 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5165 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5167 /* pop everything up to and including frame */
5168 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5170 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5172 frame = top->Previous;
5173 RtlReleaseActivationContext( top->ActivationContext );
5174 RtlFreeHeap( GetProcessHeap(), 0, top );
5175 top = frame;
5180 /******************************************************************
5181 * RtlFreeThreadActivationContextStack (NTDLL.@)
5183 void WINAPI RtlFreeThreadActivationContextStack(void)
5185 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5187 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5188 while (frame)
5190 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5191 RtlReleaseActivationContext( frame->ActivationContext );
5192 RtlFreeHeap( GetProcessHeap(), 0, frame );
5193 frame = prev;
5195 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5199 /******************************************************************
5200 * RtlGetActiveActivationContext (NTDLL.@)
5202 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5204 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5206 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5207 RtlAddRefActivationContext( *handle );
5209 else
5210 *handle = 0;
5212 return STATUS_SUCCESS;
5216 /******************************************************************
5217 * RtlIsActivationContextActive (NTDLL.@)
5219 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5221 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5223 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5224 if (frame->ActivationContext == handle) return TRUE;
5225 return FALSE;
5229 /***********************************************************************
5230 * RtlQueryInformationActivationContext (NTDLL.@)
5232 * Get information about an activation context.
5233 * FIXME: function signature/prototype may be wrong
5235 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5236 ULONG class, PVOID buffer,
5237 SIZE_T bufsize, SIZE_T *retlen )
5239 ACTIVATION_CONTEXT *actctx;
5240 NTSTATUS status;
5242 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5243 subinst, class, buffer, bufsize, retlen);
5245 if (retlen) *retlen = 0;
5246 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5248 switch (class)
5250 case ActivationContextBasicInformation:
5252 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5254 if (retlen) *retlen = sizeof(*info);
5255 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5257 info->hActCtx = handle;
5258 info->dwFlags = 0; /* FIXME */
5259 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5261 break;
5263 case ActivationContextDetailedInformation:
5265 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5266 struct assembly *assembly = NULL;
5267 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5268 LPWSTR ptr;
5270 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5272 if (actctx->num_assemblies) assembly = actctx->assemblies;
5274 if (assembly && assembly->manifest.info)
5275 manifest_len = strlenW(assembly->manifest.info) + 1;
5276 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5277 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5278 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5280 if (retlen) *retlen = len;
5281 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5283 acdi->dwFlags = 0;
5284 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5285 acdi->ulAssemblyCount = actctx->num_assemblies;
5286 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5287 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5288 acdi->ulRootConfigurationPathType = actctx->config.type;
5289 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5290 acdi->ulAppDirPathType = actctx->appdir.type;
5291 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5292 ptr = (LPWSTR)(acdi + 1);
5293 if (manifest_len)
5295 acdi->lpRootManifestPath = ptr;
5296 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5297 ptr += manifest_len;
5299 else acdi->lpRootManifestPath = NULL;
5300 if (config_len)
5302 acdi->lpRootConfigurationPath = ptr;
5303 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5304 ptr += config_len;
5306 else acdi->lpRootConfigurationPath = NULL;
5307 if (appdir_len)
5309 acdi->lpAppDirPath = ptr;
5310 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5312 else acdi->lpAppDirPath = NULL;
5314 break;
5316 case AssemblyDetailedInformationInActivationContext:
5318 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5319 struct assembly *assembly;
5320 WCHAR *assembly_id;
5321 DWORD index;
5322 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5323 LPWSTR ptr;
5325 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5326 if (!subinst) return STATUS_INVALID_PARAMETER;
5328 index = *(DWORD*)subinst;
5329 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5331 assembly = &actctx->assemblies[index - 1];
5333 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5334 id_len = strlenW(assembly_id) + 1;
5335 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5337 if (assembly->manifest.info &&
5338 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5339 path_len = strlenW(assembly->manifest.info) + 1;
5341 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5343 if (retlen) *retlen = len;
5344 if (!buffer || bufsize < len)
5346 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5347 return STATUS_BUFFER_TOO_SMALL;
5350 afdi->ulFlags = 0; /* FIXME */
5351 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5352 afdi->ulManifestPathType = assembly->manifest.type;
5353 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5354 /* FIXME afdi->liManifestLastWriteTime = 0; */
5355 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5356 afdi->ulPolicyPathLength = 0;
5357 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5358 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5359 afdi->ulManifestVersionMajor = 1;
5360 afdi->ulManifestVersionMinor = 0;
5361 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5362 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5363 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5364 ptr = (LPWSTR)(afdi + 1);
5365 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5366 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5367 ptr += id_len;
5368 if (path_len)
5370 afdi->lpAssemblyManifestPath = ptr;
5371 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5372 ptr += path_len;
5373 } else afdi->lpAssemblyManifestPath = NULL;
5374 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5375 if (ad_len)
5377 afdi->lpAssemblyDirectoryName = ptr;
5378 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5380 else afdi->lpAssemblyDirectoryName = NULL;
5381 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5383 break;
5385 case FileInformationInAssemblyOfAssemblyInActivationContext:
5387 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5388 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5389 struct assembly *assembly;
5390 struct dll_redirect *dll;
5391 SIZE_T len, dll_len = 0;
5392 LPWSTR ptr;
5394 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5395 if (!acqi) return STATUS_INVALID_PARAMETER;
5397 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5398 return STATUS_INVALID_PARAMETER;
5399 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5401 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5402 return STATUS_INVALID_PARAMETER;
5403 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5405 if (dll->name) dll_len = strlenW(dll->name) + 1;
5406 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5408 if (!buffer || bufsize < len)
5410 if (retlen) *retlen = len;
5411 return STATUS_BUFFER_TOO_SMALL;
5413 if (retlen) *retlen = 0; /* yes that's what native does !! */
5414 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5415 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5416 afdi->ulPathLength = 0; /* FIXME */
5417 ptr = (LPWSTR)(afdi + 1);
5418 if (dll_len)
5420 afdi->lpFileName = ptr;
5421 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5422 } else afdi->lpFileName = NULL;
5423 afdi->lpFilePath = NULL; /* FIXME */
5425 break;
5427 case CompatibilityInformationInActivationContext:
5429 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5430 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5431 struct assembly *assembly = NULL;
5432 ULONG num_compat_contexts = 0, n;
5433 SIZE_T len;
5435 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5437 if (actctx->num_assemblies) assembly = actctx->assemblies;
5439 if (assembly)
5440 num_compat_contexts = assembly->num_compat_contexts;
5441 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5443 if (retlen) *retlen = len;
5444 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5446 *acci = num_compat_contexts;
5447 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5448 for (n = 0; n < num_compat_contexts; ++n)
5450 elements[n] = assembly->compat_contexts[n];
5453 break;
5455 case RunlevelInformationInActivationContext:
5457 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5458 struct assembly *assembly;
5459 SIZE_T len;
5461 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5463 len = sizeof(*acrli);
5464 if (retlen) *retlen = len;
5465 if (!buffer || bufsize < len)
5466 return STATUS_BUFFER_TOO_SMALL;
5468 assembly = actctx->assemblies;
5470 acrli->ulFlags = 0;
5471 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5472 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5474 break;
5476 default:
5477 FIXME( "class %u not implemented\n", class );
5478 return STATUS_NOT_IMPLEMENTED;
5480 return STATUS_SUCCESS;
5483 /***********************************************************************
5484 * RtlFindActivationContextSectionString (NTDLL.@)
5486 * Find information about a string in an activation context.
5487 * FIXME: function signature/prototype may be wrong
5489 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5490 const UNICODE_STRING *section_name, PVOID ptr )
5492 PACTCTX_SECTION_KEYED_DATA data = ptr;
5493 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5495 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5496 debugstr_us(section_name), data);
5498 if (guid)
5500 FIXME("expected guid == NULL\n");
5501 return STATUS_INVALID_PARAMETER;
5503 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5505 FIXME("unknown flags %08x\n", flags);
5506 return STATUS_INVALID_PARAMETER;
5508 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5509 !section_name || !section_name->Buffer)
5511 WARN("invalid parameter\n");
5512 return STATUS_INVALID_PARAMETER;
5515 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5517 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5518 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5521 if (status != STATUS_SUCCESS)
5522 status = find_string( process_actctx, section_kind, section_name, flags, data );
5524 return status;
5527 /***********************************************************************
5528 * RtlFindActivationContextSectionGuid (NTDLL.@)
5530 * Find information about a GUID in an activation context.
5531 * FIXME: function signature/prototype may be wrong
5533 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5534 const GUID *guid, void *ptr )
5536 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5537 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5539 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5541 if (extguid)
5543 FIXME("expected extguid == NULL\n");
5544 return STATUS_INVALID_PARAMETER;
5547 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5549 FIXME("unknown flags %08x\n", flags);
5550 return STATUS_INVALID_PARAMETER;
5553 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5554 return STATUS_INVALID_PARAMETER;
5556 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5558 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5559 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5562 if (status != STATUS_SUCCESS)
5563 status = find_guid( process_actctx, section_kind, guid, flags, data );
5565 return status;
5569 /***********************************************************************
5570 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5572 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5573 const WCHAR *settings, WCHAR *buffer,
5574 SIZE_T size, SIZE_T *written )
5576 ACTIVATION_CONTEXT *actctx;
5577 const WCHAR *res;
5579 if (flags)
5581 WARN( "unknown flags %08x\n", flags );
5582 return STATUS_INVALID_PARAMETER;
5585 if (ns)
5587 if (strcmpW( ns, windowsSettings2005NSW ) &&
5588 strcmpW( ns, windowsSettings2011NSW ) &&
5589 strcmpW( ns, windowsSettings2016NSW ) &&
5590 strcmpW( ns, windowsSettings2017NSW ))
5591 return STATUS_INVALID_PARAMETER;
5593 else ns = windowsSettings2005NSW;
5595 if (!handle) handle = process_actctx;
5596 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5598 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5600 if (written) *written = strlenW(res) + 1;
5601 if (size < strlenW(res)) return STATUS_BUFFER_TOO_SMALL;
5602 strcpyW( buffer, res );
5603 return STATUS_SUCCESS;