dmime/tests: Add more GetTrack() tests.
[wine.git] / dlls / ntdll / actctx.c
blob9e7782c1ee093bf98e7eb39b24891c9d37d3e18e
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 struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
823 struct assembly *assembly;
825 if (actctx->num_assemblies == actctx->allocated_assemblies)
827 void *ptr;
828 unsigned int new_count;
829 if (actctx->assemblies)
831 new_count = actctx->allocated_assemblies * 2;
832 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
833 actctx->assemblies, new_count * sizeof(*assembly) );
835 else
837 new_count = 4;
838 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
840 if (!ptr) return NULL;
841 actctx->assemblies = ptr;
842 actctx->allocated_assemblies = new_count;
845 assembly = &actctx->assemblies[actctx->num_assemblies++];
846 assembly->type = at;
847 return assembly;
850 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
852 if (assembly->num_dlls == assembly->allocated_dlls)
854 void *ptr;
855 unsigned int new_count;
856 if (assembly->dlls)
858 new_count = assembly->allocated_dlls * 2;
859 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
860 assembly->dlls, new_count * sizeof(*assembly->dlls) );
862 else
864 new_count = 4;
865 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
867 if (!ptr) return NULL;
868 assembly->dlls = ptr;
869 assembly->allocated_dlls = new_count;
871 return &assembly->dlls[assembly->num_dlls++];
874 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
876 void *ptr;
877 if (assembly->num_compat_contexts)
879 unsigned int new_count = assembly->num_compat_contexts + 1;
880 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
881 assembly->compat_contexts,
882 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
884 else
886 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
888 if (!ptr) return NULL;
889 assembly->compat_contexts = ptr;
890 return &assembly->compat_contexts[assembly->num_compat_contexts++];
893 static void free_assembly_identity(struct assembly_identity *ai)
895 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
896 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
897 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
898 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
899 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
902 static struct entity* add_entity(struct entity_array *array, DWORD kind)
904 struct entity* entity;
906 if (array->num == array->allocated)
908 void *ptr;
909 unsigned int new_count;
910 if (array->base)
912 new_count = array->allocated * 2;
913 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
914 array->base, new_count * sizeof(*array->base) );
916 else
918 new_count = 4;
919 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
921 if (!ptr) return NULL;
922 array->base = ptr;
923 array->allocated = new_count;
925 entity = &array->base[array->num++];
926 entity->kind = kind;
927 return entity;
930 static void free_entity_array(struct entity_array *array)
932 unsigned int i, j;
933 for (i = 0; i < array->num; i++)
935 struct entity *entity = &array->base[i];
936 switch (entity->kind)
938 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
939 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
940 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
941 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
942 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
943 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
944 for (j = 0; j < entity->u.comclass.progids.num; j++)
945 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
946 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
947 break;
948 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
949 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
950 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
951 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
952 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
953 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
954 break;
955 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
956 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
957 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
958 break;
959 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
960 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
961 break;
962 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
963 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
964 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
965 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
966 break;
967 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
968 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
969 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
970 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
971 break;
972 default:
973 FIXME("Unknown entity kind %d\n", entity->kind);
976 RtlFreeHeap( GetProcessHeap(), 0, array->base );
979 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
981 if (!str1) return !str2;
982 return str2 && !strcmpiW( str1, str2 );
985 static BOOL is_matching_identity( const struct assembly_identity *id1,
986 const struct assembly_identity *id2 )
988 if (!is_matching_string( id1->name, id2->name )) return FALSE;
989 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
990 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
992 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
994 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
995 return FALSE;
997 if (id1->version.major != id2->version.major) return FALSE;
998 if (id1->version.minor != id2->version.minor) return FALSE;
999 if (id1->version.build > id2->version.build) return FALSE;
1000 if (id1->version.build == id2->version.build &&
1001 id1->version.revision > id2->version.revision) return FALSE;
1002 return TRUE;
1005 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
1006 struct assembly_identity* ai)
1008 unsigned int i;
1010 /* check if we already have that assembly */
1012 for (i = 0; i < acl->actctx->num_assemblies; i++)
1013 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1015 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1016 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1017 ai->version.build, ai->version.revision );
1018 return TRUE;
1021 for (i = 0; i < acl->num_dependencies; i++)
1022 if (is_matching_identity( ai, &acl->dependencies[i] ))
1024 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1025 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1026 ai->version.build, ai->version.revision );
1027 return TRUE;
1030 if (acl->num_dependencies == acl->allocated_dependencies)
1032 void *ptr;
1033 unsigned int new_count;
1034 if (acl->dependencies)
1036 new_count = acl->allocated_dependencies * 2;
1037 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
1038 new_count * sizeof(acl->dependencies[0]));
1040 else
1042 new_count = 4;
1043 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1045 if (!ptr) return FALSE;
1046 acl->dependencies = ptr;
1047 acl->allocated_dependencies = new_count;
1049 acl->dependencies[acl->num_dependencies++] = *ai;
1051 return TRUE;
1054 static void free_depend_manifests(struct actctx_loader* acl)
1056 unsigned int i;
1057 for (i = 0; i < acl->num_dependencies; i++)
1058 free_assembly_identity(&acl->dependencies[i]);
1059 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1062 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1064 static const WCHAR undW[] = {'_',0};
1065 static const WCHAR noneW[] = {'n','o','n','e',0};
1066 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1068 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1069 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1070 const WCHAR *lang = ai->language ? ai->language : noneW;
1071 const WCHAR *name = ai->name ? ai->name : noneW;
1072 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1073 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1074 WCHAR *ret;
1076 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1078 strcpyW( ret, arch );
1079 strcatW( ret, undW );
1080 strcatW( ret, name );
1081 strcatW( ret, undW );
1082 strcatW( ret, key );
1083 strcatW( ret, undW );
1084 sprintfW( ret + strlenW(ret), version_formatW,
1085 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1086 strcatW( ret, undW );
1087 strcatW( ret, lang );
1088 strcatW( ret, undW );
1089 strcatW( ret, mskeyW );
1090 return ret;
1093 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1095 WCHAR *p = buffer;
1097 if (!str) return;
1098 strcatW( buffer, prefix );
1099 p += strlenW(p);
1100 *p++ = '"';
1101 strcpyW( p, str );
1102 p += strlenW(p);
1103 *p++ = '"';
1104 *p = 0;
1107 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1109 static const WCHAR archW[] =
1110 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1111 static const WCHAR public_keyW[] =
1112 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1113 static const WCHAR typeW[] =
1114 {',','t','y','p','e','=',0};
1115 static const WCHAR versionW[] =
1116 {',','v','e','r','s','i','o','n','=',0};
1118 WCHAR version[64], *ret;
1119 SIZE_T size = 0;
1121 sprintfW( version, version_formatW,
1122 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1123 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1124 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1125 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1126 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1127 size += strlenW(versionW) + strlenW(version) + 2;
1129 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1130 return NULL;
1132 if (ai->name) strcpyW( ret, ai->name );
1133 else *ret = 0;
1134 append_string( ret, archW, ai->arch );
1135 append_string( ret, public_keyW, ai->public_key );
1136 append_string( ret, typeW, ai->type );
1137 append_string( ret, versionW, version );
1138 return ret;
1141 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1143 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1145 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1146 __TRY
1148 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1150 __EXCEPT_PAGE_FAULT
1153 __ENDTRY
1154 return ret;
1157 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1159 interlocked_xchg_add( &actctx->ref_count, 1 );
1162 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1164 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1166 unsigned int i, j;
1168 for (i = 0; i < actctx->num_assemblies; i++)
1170 struct assembly *assembly = &actctx->assemblies[i];
1171 for (j = 0; j < assembly->num_dlls; j++)
1173 struct dll_redirect *dll = &assembly->dlls[j];
1174 free_entity_array( &dll->entities );
1175 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1176 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1178 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1179 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1180 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1181 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1182 free_entity_array( &assembly->entities );
1183 free_assembly_identity(&assembly->id);
1185 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1186 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1187 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1188 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1189 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1190 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1191 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1192 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1193 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1194 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1195 actctx->magic = 0;
1196 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1200 static BOOL set_error( xmlbuf_t *xmlbuf )
1202 xmlbuf->error = TRUE;
1203 return FALSE;
1206 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1208 const int len = strlenW( xmlnsW );
1209 if (attr->name.len < len) return FALSE;
1210 if (strncmpW( attr->name.ptr, xmlnsW, len )) return FALSE;
1211 return (attr->name.len == len || attr->name.ptr[len] == ':');
1214 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1216 const int len = strlenW( xmlnsW );
1217 struct xml_attr *ns;
1219 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1221 FIXME( "too many namespaces in manifest\n" );
1222 set_error( xmlbuf );
1223 return;
1225 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1226 ns->value = attr->value;
1227 if (attr->name.len > len)
1229 ns->name.ptr = attr->name.ptr + len + 1;
1230 ns->name.len = attr->name.len - len - 1;
1232 else ns->name = empty_xmlstr;
1235 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1237 int i;
1239 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1241 if (xmlbuf->namespaces[i].name.len == name->len &&
1242 !strncmpW( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1243 return xmlbuf->namespaces[i].value;
1245 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1246 return empty_xmlstr;
1249 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1251 const WCHAR* ptr;
1253 if (xmlbuf->error) return FALSE;
1255 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1256 xmlbuf->ptr++;
1258 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1260 if (*xmlbuf->ptr == '/')
1262 xmlbuf->ptr++;
1263 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1264 return set_error( xmlbuf );
1266 xmlbuf->ptr++;
1267 *end = TRUE;
1268 return FALSE;
1271 if (*xmlbuf->ptr == '>')
1273 xmlbuf->ptr++;
1274 return FALSE;
1277 ptr = xmlbuf->ptr;
1278 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1280 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1282 attr->name.ptr = xmlbuf->ptr;
1283 attr->name.len = ptr-xmlbuf->ptr;
1284 xmlbuf->ptr = ptr;
1286 /* skip spaces before '=' */
1287 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1288 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1290 /* skip '=' itself */
1291 ptr++;
1292 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1294 /* skip spaces after '=' */
1295 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1297 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1299 attr->value.ptr = ++ptr;
1300 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1302 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1303 if (!ptr)
1305 xmlbuf->ptr = xmlbuf->end;
1306 return set_error( xmlbuf );
1309 attr->value.len = ptr - attr->value.ptr;
1310 xmlbuf->ptr = ptr + 1;
1311 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1313 return set_error( xmlbuf );
1316 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1318 const WCHAR* ptr = xmlbuf->ptr;
1320 elem->ns = empty_xmlstr;
1321 elem->name.ptr = ptr;
1322 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1324 if (*ptr == ':')
1326 elem->ns.ptr = elem->name.ptr;
1327 elem->ns.len = ptr - elem->ns.ptr;
1328 elem->name.ptr = ptr + 1;
1330 ptr++;
1332 elem->name.len = ptr - elem->name.ptr;
1333 xmlbuf->ptr = ptr;
1336 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1338 const WCHAR* ptr;
1339 struct xml_attr attr;
1340 xmlbuf_t attr_buf;
1341 BOOL end = FALSE;
1343 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1345 if (xmlbuf->error) return FALSE;
1347 for (;;)
1349 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1350 if (!ptr)
1352 xmlbuf->ptr = xmlbuf->end;
1353 return set_error( xmlbuf );
1355 ptr++;
1356 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1358 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1359 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1361 if (ptr + 3 > xmlbuf->end)
1363 xmlbuf->ptr = xmlbuf->end;
1364 return set_error( xmlbuf );
1366 xmlbuf->ptr = ptr + 3;
1368 else break;
1371 xmlbuf->ptr = ptr;
1372 /* check for element terminating the parent element */
1373 if (ptr < xmlbuf->end && *ptr == '/')
1375 xmlbuf->ptr++;
1376 read_xml_elem( xmlbuf, elem );
1377 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1378 if (!xml_name_cmp( elem, parent ))
1380 ERR( "wrong closing element %s for %s\n",
1381 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1382 return set_error( xmlbuf );
1384 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1385 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1386 return FALSE;
1389 read_xml_elem( xmlbuf, elem );
1391 /* parse namespace attributes */
1392 attr_buf = *xmlbuf;
1393 while (next_xml_attr( &attr_buf, &attr, &end ))
1395 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1397 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1398 elem->ns_pos = xmlbuf->ns_pos;
1400 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1402 return set_error( xmlbuf );
1405 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1407 /* FIXME: parse attributes */
1408 const WCHAR *ptr;
1410 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1412 if (ptr[0] == '?' && ptr[1] == '>')
1414 xmlbuf->ptr = ptr + 2;
1415 return TRUE;
1418 return FALSE;
1421 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1423 const WCHAR *ptr;
1425 if (xmlbuf->error) return FALSE;
1427 if (!(ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr))) return set_error( xmlbuf );
1429 content->ptr = xmlbuf->ptr;
1430 content->len = ptr - xmlbuf->ptr;
1431 xmlbuf->ptr = ptr;
1433 return TRUE;
1436 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1438 unsigned int ver[4];
1439 unsigned int pos;
1440 const WCHAR *curr;
1442 /* major.minor.build.revision */
1443 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1444 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1446 if (*curr >= '0' && *curr <= '9')
1448 ver[pos] = ver[pos] * 10 + *curr - '0';
1449 if (ver[pos] >= 0x10000) goto error;
1451 else if (*curr == '.')
1453 if (++pos >= 4) goto error;
1455 else goto error;
1457 version->major = ver[0];
1458 version->minor = ver[1];
1459 version->build = ver[2];
1460 version->revision = ver[3];
1461 return TRUE;
1463 error:
1464 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1465 return FALSE;
1468 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1470 struct xml_attr attr;
1472 while (next_xml_attr(xmlbuf, &attr, end))
1474 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1478 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1480 struct xml_elem elem;
1482 if (next_xml_elem(xmlbuf, &elem, parent))
1484 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1485 set_error( xmlbuf );
1489 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1491 struct xml_elem elem;
1492 struct xml_attr attr;
1493 BOOL end = FALSE;
1495 while (next_xml_attr(xmlbuf, &attr, &end));
1496 if (end) return;
1498 while (next_xml_elem(xmlbuf, &elem, parent))
1499 parse_unknown_elem(xmlbuf, &elem);
1502 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1503 struct assembly_identity* ai, const struct xml_elem *parent)
1505 struct xml_attr attr;
1506 BOOL end = FALSE;
1508 while (next_xml_attr(xmlbuf, &attr, &end))
1510 if (xml_attr_cmp(&attr, nameW))
1512 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1514 else if (xml_attr_cmp(&attr, typeW))
1516 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1518 else if (xml_attr_cmp(&attr, versionW))
1520 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1522 else if (xml_attr_cmp(&attr, processorArchitectureW))
1524 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1526 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1528 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1530 else if (xml_attr_cmp(&attr, languageW))
1532 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1534 else if (!is_xmlns_attr( &attr ))
1536 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1540 TRACE( "name=%s version=%s arch=%s\n",
1541 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1543 if (!end) parse_expect_end_elem(xmlbuf, parent);
1546 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1548 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1549 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1550 static const WCHAR freeW[] = {'F','r','e','e',0};
1551 static const WCHAR bothW[] = {'B','o','t','h',0};
1553 if (value->len == 0) return ThreadingModel_No;
1554 if (xmlstr_cmp(value, apartW))
1555 return ThreadingModel_Apartment;
1556 else if (xmlstr_cmp(value, freeW))
1557 return ThreadingModel_Free;
1558 else if (xmlstr_cmp(value, bothW))
1559 return ThreadingModel_Both;
1560 else if (xmlstr_cmp(value, neutralW))
1561 return ThreadingModel_Neutral;
1562 else
1563 return ThreadingModel_No;
1566 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1568 int min, max;
1570 min = 0;
1571 max = ARRAY_SIZE(olemisc_values) - 1;
1573 while (min <= max)
1575 int n, c;
1577 n = (min+max)/2;
1579 c = strncmpW(olemisc_values[n].name, str, len);
1580 if (!c && !olemisc_values[n].name[len])
1581 return olemisc_values[n].value;
1583 if (c >= 0)
1584 max = n-1;
1585 else
1586 min = n+1;
1589 WARN("unknown flag %s\n", debugstr_wn(str, len));
1590 return 0;
1593 static DWORD parse_com_class_misc(const xmlstr_t *value)
1595 const WCHAR *str = value->ptr, *start;
1596 DWORD flags = 0;
1597 int i = 0;
1599 /* it's comma separated list of flags */
1600 while (i < value->len)
1602 start = str;
1603 while (*str != ',' && (i++ < value->len)) str++;
1605 flags |= get_olemisc_value(start, str-start);
1607 /* skip separator */
1608 str++;
1609 i++;
1612 return flags;
1615 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1617 struct progids *progids = &entity->u.comclass.progids;
1619 if (progids->allocated == 0)
1621 progids->allocated = 4;
1622 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1625 if (progids->allocated == progids->num)
1627 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1628 2 * progids->allocated * sizeof(WCHAR*));
1629 if (!new_progids) return FALSE;
1630 progids->allocated *= 2;
1631 progids->progids = new_progids;
1634 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1635 progids->num++;
1637 return TRUE;
1640 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1642 xmlstr_t content;
1643 BOOL end = FALSE;
1645 parse_expect_no_attr(xmlbuf, &end);
1646 if (end) set_error( xmlbuf );
1647 if (!parse_text_content(xmlbuf, &content)) return;
1649 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1650 parse_expect_end_elem(xmlbuf, parent);
1653 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1654 const struct xml_elem *parent )
1656 struct xml_elem elem;
1657 struct xml_attr attr;
1658 BOOL end = FALSE;
1659 struct entity* entity;
1661 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1663 set_error( xmlbuf );
1664 return;
1667 while (next_xml_attr(xmlbuf, &attr, &end))
1669 if (xml_attr_cmp(&attr, clsidW))
1671 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1673 else if (xml_attr_cmp(&attr, progidW))
1675 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1677 else if (xml_attr_cmp(&attr, tlbidW))
1679 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1681 else if (xml_attr_cmp(&attr, threadingmodelW))
1683 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1685 else if (xml_attr_cmp(&attr, miscstatusW))
1687 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1689 else if (xml_attr_cmp(&attr, miscstatuscontentW))
1691 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1693 else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1695 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1697 else if (xml_attr_cmp(&attr, miscstatusiconW))
1699 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1701 else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1703 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1705 else if (xml_attr_cmp(&attr, descriptionW))
1707 /* not stored */
1709 else if (!is_xmlns_attr( &attr ))
1711 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1715 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1716 if (entity->u.comclass.progid)
1717 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1719 if (end) return;
1721 while (next_xml_elem(xmlbuf, &elem, parent))
1723 if (xml_elem_cmp(&elem, progidW, asmv1W))
1725 parse_com_class_progid(xmlbuf, entity, &elem);
1727 else
1729 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1730 parse_unknown_elem(xmlbuf, &elem);
1734 if (entity->u.comclass.progids.num)
1735 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1738 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1740 const WCHAR *curr;
1741 ULONG num = 0;
1743 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1745 if (*curr >= '0' && *curr <= '9')
1746 num = num * 10 + *curr - '0';
1747 else
1749 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1750 return FALSE;
1753 entity->u.ifaceps.nummethods = num;
1755 return TRUE;
1758 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1759 struct actctx_loader *acl, const struct xml_elem *parent )
1761 struct xml_attr attr;
1762 BOOL end = FALSE;
1763 struct entity* entity;
1765 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1767 set_error( xmlbuf );
1768 return;
1771 while (next_xml_attr(xmlbuf, &attr, &end))
1773 if (xml_attr_cmp(&attr, iidW))
1775 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1777 else if (xml_attr_cmp(&attr, nameW))
1779 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1781 else if (xml_attr_cmp(&attr, baseInterfaceW))
1783 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1784 entity->u.ifaceps.mask |= BaseIface;
1786 else if (xml_attr_cmp(&attr, nummethodsW))
1788 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1789 entity->u.ifaceps.mask |= NumMethods;
1791 else if (xml_attr_cmp(&attr, tlbidW))
1793 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1795 /* not used */
1796 else if (xml_attr_cmp(&attr, proxyStubClsid32W) || xml_attr_cmp(&attr, threadingmodelW))
1799 else if (!is_xmlns_attr( &attr ))
1801 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1805 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1806 if (!end) parse_expect_end_elem(xmlbuf, parent);
1809 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1811 WORD *flags = &entity->u.typelib.flags;
1812 const WCHAR *str = value->ptr, *start;
1813 int i = 0;
1815 *flags = 0;
1817 /* it's comma separated list of flags */
1818 while (i < value->len)
1820 start = str;
1821 while (*str != ',' && (i++ < value->len)) str++;
1823 if (!strncmpiW(start, restrictedW, str-start))
1824 *flags |= LIBFLAG_FRESTRICTED;
1825 else if (!strncmpiW(start, controlW, str-start))
1826 *flags |= LIBFLAG_FCONTROL;
1827 else if (!strncmpiW(start, hiddenW, str-start))
1828 *flags |= LIBFLAG_FHIDDEN;
1829 else if (!strncmpiW(start, hasdiskimageW, str-start))
1830 *flags |= LIBFLAG_FHASDISKIMAGE;
1831 else
1833 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1834 return FALSE;
1837 /* skip separator */
1838 str++;
1839 i++;
1842 return TRUE;
1845 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1847 unsigned int ver[2];
1848 unsigned int pos;
1849 const WCHAR *curr;
1851 /* major.minor */
1852 ver[0] = ver[1] = pos = 0;
1853 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1855 if (*curr >= '0' && *curr <= '9')
1857 ver[pos] = ver[pos] * 10 + *curr - '0';
1858 if (ver[pos] >= 0x10000) goto error;
1860 else if (*curr == '.')
1862 if (++pos >= 2) goto error;
1864 else goto error;
1866 entity->u.typelib.major = ver[0];
1867 entity->u.typelib.minor = ver[1];
1868 return TRUE;
1870 error:
1871 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1872 return FALSE;
1875 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1876 struct actctx_loader *acl, const struct xml_elem *parent )
1878 struct xml_attr attr;
1879 BOOL end = FALSE;
1880 struct entity* entity;
1882 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1884 set_error( xmlbuf );
1885 return;
1888 while (next_xml_attr(xmlbuf, &attr, &end))
1890 if (xml_attr_cmp(&attr, tlbidW))
1892 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1894 else if (xml_attr_cmp(&attr, versionW))
1896 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1898 else if (xml_attr_cmp(&attr, helpdirW))
1900 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1902 else if (xml_attr_cmp(&attr, flagsW))
1904 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1906 else if (!is_xmlns_attr( &attr ))
1908 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1912 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1913 if (!end) parse_expect_end_elem(xmlbuf, parent);
1916 static inline int aligned_string_len(int len)
1918 return (len + 3) & ~3;
1921 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1923 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1924 struct assembly_version *ver = &assembly->id.version;
1925 WCHAR buff[25];
1927 if (!ret) ret = buff;
1928 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1931 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1932 struct actctx_loader *acl, const struct xml_elem *parent )
1934 struct xml_elem elem;
1935 struct xml_attr attr;
1936 xmlstr_t content;
1937 BOOL end = FALSE;
1938 struct entity* entity;
1940 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1942 set_error( xmlbuf );
1943 return;
1945 entity->u.class.versioned = TRUE;
1946 while (next_xml_attr(xmlbuf, &attr, &end))
1948 if (xml_attr_cmp(&attr, versionedW))
1950 if (xmlstr_cmpi(&attr.value, noW))
1951 entity->u.class.versioned = FALSE;
1952 else if (!xmlstr_cmpi(&attr.value, yesW))
1953 set_error( xmlbuf );
1955 else if (!is_xmlns_attr( &attr ))
1957 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1961 if (end) return;
1963 if (!parse_text_content(xmlbuf, &content)) return;
1964 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1966 acl->actctx->sections |= WINDOWCLASS_SECTION;
1968 while (next_xml_elem(xmlbuf, &elem, parent))
1970 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1971 parse_unknown_elem(xmlbuf, &elem);
1975 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1977 struct xml_attr attr;
1978 BOOL end = FALSE;
1980 while (next_xml_attr(xmlbuf, &attr, &end))
1982 if (xml_attr_cmp(&attr, oldVersionW))
1984 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1986 else if (xml_attr_cmp(&attr, newVersionW))
1988 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1990 else if (!is_xmlns_attr( &attr ))
1992 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1996 if (!end) parse_expect_end_elem(xmlbuf, parent);
1999 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2001 struct xml_elem elem;
2002 struct xml_attr attr;
2003 xmlstr_t content;
2004 BOOL end = FALSE;
2006 while (next_xml_attr(xmlbuf, &attr, &end))
2008 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2011 if (end) return;
2012 if (!parse_text_content(xmlbuf, &content)) return;
2014 TRACE("Got description %s\n", debugstr_xmlstr(&content));
2016 while (next_xml_elem(xmlbuf, &elem, parent))
2018 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2019 parse_unknown_elem(xmlbuf, &elem);
2023 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2024 struct assembly* assembly,
2025 struct actctx_loader* acl,
2026 const struct xml_elem *parent)
2028 struct xml_attr attr;
2029 BOOL end = FALSE;
2030 struct entity* entity;
2032 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2034 set_error( xmlbuf );
2035 return;
2038 while (next_xml_attr(xmlbuf, &attr, &end))
2040 if (xml_attr_cmp(&attr, iidW))
2042 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2044 else if (xml_attr_cmp(&attr, nameW))
2046 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2048 else if (xml_attr_cmp(&attr, baseInterfaceW))
2050 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2051 entity->u.ifaceps.mask |= BaseIface;
2053 else if (xml_attr_cmp(&attr, nummethodsW))
2055 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2056 entity->u.ifaceps.mask |= NumMethods;
2058 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2060 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2062 else if (xml_attr_cmp(&attr, tlbidW))
2064 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2066 else if (!is_xmlns_attr( &attr ))
2068 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2072 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2073 if (!end) parse_expect_end_elem(xmlbuf, parent);
2076 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2077 struct actctx_loader *acl, const struct xml_elem *parent )
2080 struct xml_elem elem;
2081 struct xml_attr attr;
2082 BOOL end = FALSE;
2083 struct entity* entity;
2085 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2087 set_error( xmlbuf );
2088 return;
2091 while (next_xml_attr(xmlbuf, &attr, &end))
2093 if (xml_attr_cmp(&attr, nameW))
2095 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2097 else if (xml_attr_cmp(&attr, clsidW))
2099 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2101 else if (xml_attr_cmp(&attr, progidW))
2103 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2105 else if (xml_attr_cmp(&attr, tlbidW))
2107 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2109 else if (xml_attr_cmp(&attr, threadingmodelW))
2111 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2113 else if (xml_attr_cmp(&attr, runtimeVersionW))
2115 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2117 else if (!is_xmlns_attr( &attr ))
2119 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2123 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2124 if (entity->u.comclass.progid)
2125 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2126 if (end) return;
2128 while (next_xml_elem(xmlbuf, &elem, parent))
2130 if (xml_elem_cmp(&elem, progidW, asmv1W))
2132 parse_com_class_progid(xmlbuf, entity, &elem);
2134 else
2136 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2137 parse_unknown_elem(xmlbuf, &elem);
2141 if (entity->u.comclass.progids.num)
2142 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2145 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2146 struct actctx_loader *acl, const struct xml_elem *parent )
2148 struct xml_attr attr;
2149 BOOL end = FALSE;
2150 struct entity* entity;
2152 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2154 set_error( xmlbuf );
2155 return;
2158 while (next_xml_attr(xmlbuf, &attr, &end))
2160 if (xml_attr_cmp(&attr, nameW))
2162 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2164 else if (xml_attr_cmp(&attr, clsidW))
2166 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2168 else if (xml_attr_cmp(&attr, runtimeVersionW))
2170 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2172 else if (!is_xmlns_attr( &attr ))
2174 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2178 acl->actctx->sections |= CLRSURROGATES_SECTION;
2179 if (!end) parse_expect_end_elem(xmlbuf, parent);
2182 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2183 const struct xml_elem *parent, BOOL optional )
2185 struct xml_elem elem;
2186 struct xml_attr attr;
2187 struct assembly_identity ai;
2188 BOOL end = FALSE;
2190 memset(&ai, 0, sizeof(ai));
2191 ai.optional = optional;
2193 while (next_xml_attr(xmlbuf, &attr, &end))
2195 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2196 static const WCHAR trueW[] = {'t','r','u','e',0};
2198 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2199 ai.delayed = xmlstr_cmp(&attr.value, trueW);
2200 else if (!is_xmlns_attr( &attr ))
2201 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2204 if (end) return;
2206 while (next_xml_elem(xmlbuf, &elem, parent))
2208 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2210 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2211 /* store the newly found identity for later loading */
2212 if (ai.arch && !strcmpW(ai.arch, wildcardW)) ai.arch = strdupW( current_archW );
2213 TRACE( "adding name=%s version=%s arch=%s\n",
2214 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2215 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2217 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2219 parse_binding_redirect_elem(xmlbuf, &elem);
2221 else
2223 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2224 parse_unknown_elem(xmlbuf, &elem);
2229 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2230 const struct xml_elem *parent )
2233 struct xml_elem elem;
2234 struct xml_attr attr;
2235 BOOL end = FALSE, optional = FALSE;
2237 while (next_xml_attr(xmlbuf, &attr, &end))
2239 if (xml_attr_cmp(&attr, optionalW))
2241 optional = xmlstr_cmpi( &attr.value, yesW );
2242 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2244 else if (!is_xmlns_attr( &attr ))
2246 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2250 while (next_xml_elem(xmlbuf, &elem, parent))
2252 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2254 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2256 else
2258 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2259 parse_unknown_elem(xmlbuf, &elem);
2264 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2266 BOOL end = FALSE;
2268 parse_expect_no_attr(xmlbuf, &end);
2269 if (!end) parse_expect_end_elem(xmlbuf, parent);
2272 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2274 BOOL end = FALSE;
2276 parse_expect_no_attr(xmlbuf, &end);
2277 if (!end) parse_expect_end_elem(xmlbuf, parent);
2280 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2281 struct actctx_loader* acl, const struct xml_elem *parent )
2283 struct xml_elem elem;
2284 struct xml_attr attr;
2285 BOOL end = FALSE;
2286 struct dll_redirect* dll;
2288 if (!(dll = add_dll_redirect(assembly)))
2290 set_error( xmlbuf );
2291 return;
2294 while (next_xml_attr(xmlbuf, &attr, &end))
2296 if (xml_attr_cmp(&attr, nameW))
2298 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2299 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2301 else if (xml_attr_cmp(&attr, hashW))
2303 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2305 else if (xml_attr_cmp(&attr, hashalgW))
2307 static const WCHAR sha1W[] = {'S','H','A','1',0};
2308 if (!xmlstr_cmpi(&attr.value, sha1W))
2309 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2311 else if (!is_xmlns_attr( &attr ))
2313 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2317 if (!dll->name) set_error( xmlbuf );
2319 acl->actctx->sections |= DLLREDIRECT_SECTION;
2321 if (end) return;
2323 while (next_xml_elem(xmlbuf, &elem, parent))
2325 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2327 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2329 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2331 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2333 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2335 WARN("asmv2:hash (undocumented) not supported\n");
2336 parse_unknown_elem(xmlbuf, &elem);
2338 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2340 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2342 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2344 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2346 else
2348 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2349 parse_unknown_elem( xmlbuf, &elem );
2354 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2355 struct actctx_loader *acl, const struct xml_elem *parent )
2357 struct xml_attr attr;
2358 BOOL end = FALSE;
2360 while (next_xml_attr(xmlbuf, &attr, &end))
2362 if (xml_attr_cmp(&attr, IdW))
2364 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2365 UNICODE_STRING str;
2366 GUID compat_id;
2368 str.Buffer = (PWSTR)attr.value.ptr;
2369 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2370 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2372 if (!(compat = add_compat_context(assembly)))
2374 set_error( xmlbuf );
2375 return;
2377 compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2378 compat->Id = compat_id;
2380 else
2382 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2385 else if (!is_xmlns_attr( &attr ))
2387 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2391 if (!end) parse_expect_end_elem(xmlbuf, parent);
2394 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2395 struct actctx_loader* acl, const struct xml_elem *parent)
2397 struct xml_elem elem;
2399 while (next_xml_elem(xmlbuf, &elem, parent))
2401 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2403 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2405 else
2407 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2408 parse_unknown_elem(xmlbuf, &elem);
2413 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2414 struct actctx_loader* acl, const struct xml_elem *parent)
2416 struct xml_elem elem;
2418 while (next_xml_elem(xmlbuf, &elem, parent))
2420 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2422 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2424 else
2426 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2427 parse_unknown_elem(xmlbuf, &elem);
2432 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2433 struct xml_elem *parent )
2435 struct xml_elem elem;
2436 struct xml_attr attr;
2437 xmlstr_t content;
2438 BOOL end = FALSE;
2439 struct entity *entity;
2441 while (next_xml_attr( xmlbuf, &attr, &end ))
2443 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2446 if (end) return;
2448 if (!parse_text_content( xmlbuf, &content )) return;
2449 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2451 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2452 if (!entity)
2454 set_error( xmlbuf );
2455 return;
2457 entity->u.settings.name = xmlstrdupW( &parent->name );
2458 entity->u.settings.value = xmlstrdupW( &content );
2459 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2461 while (next_xml_elem(xmlbuf, &elem, parent))
2463 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2464 parse_unknown_elem( xmlbuf, &elem );
2468 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2469 struct actctx_loader *acl, const struct xml_elem *parent )
2471 struct xml_elem elem;
2473 while (next_xml_elem( xmlbuf, &elem, parent ))
2475 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2476 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2477 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2478 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2479 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2480 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2481 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2482 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2483 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2484 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2485 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2487 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2489 else
2491 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2492 parse_unknown_elem( xmlbuf, &elem );
2497 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2498 struct actctx_loader *acl, const struct xml_elem *parent )
2500 struct xml_elem elem;
2502 while (next_xml_elem( xmlbuf, &elem, parent ))
2504 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2506 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2508 else
2510 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2511 parse_unknown_elem( xmlbuf, &elem );
2516 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2517 struct actctx_loader *acl, const struct xml_elem *parent )
2519 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2520 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2521 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};
2522 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2523 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2524 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2525 static const WCHAR trueW[] = {'t','r','u','e',0};
2527 struct xml_elem elem;
2528 struct xml_attr attr;
2529 BOOL end = FALSE;
2531 /* Multiple requestedExecutionLevel elements are not supported. */
2532 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2534 while (next_xml_attr(xmlbuf, &attr, &end))
2536 if (xml_attr_cmp(&attr, levelW))
2538 if (xmlstr_cmpi(&attr.value, asInvokerW))
2539 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2540 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2541 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2542 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2543 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2544 else
2545 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2547 else if (xml_attr_cmp(&attr, uiAccessW))
2549 if (xmlstr_cmpi(&attr.value, falseW))
2550 assembly->ui_access = FALSE;
2551 else if (xmlstr_cmpi(&attr.value, trueW))
2552 assembly->ui_access = TRUE;
2553 else
2554 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2556 else if (!is_xmlns_attr( &attr ))
2557 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2560 if (end) return;
2562 while (next_xml_elem(xmlbuf, &elem, parent))
2564 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2565 parse_unknown_elem(xmlbuf, &elem);
2569 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2570 struct actctx_loader *acl, const struct xml_elem *parent )
2572 struct xml_elem elem;
2574 while (next_xml_elem(xmlbuf, &elem, parent))
2576 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2578 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2580 else
2582 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2583 parse_unknown_elem(xmlbuf, &elem);
2588 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2589 struct actctx_loader *acl, const struct xml_elem *parent )
2591 struct xml_elem elem;
2593 while (next_xml_elem(xmlbuf, &elem, parent))
2595 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2597 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2599 else
2601 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2602 parse_unknown_elem(xmlbuf, &elem);
2607 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2608 struct actctx_loader *acl, const struct xml_elem *parent )
2610 struct xml_elem elem;
2612 while (next_xml_elem(xmlbuf, &elem, parent))
2614 if (xml_elem_cmp(&elem, securityW, asmv1W))
2616 parse_security_elem(xmlbuf, assembly, acl, &elem);
2618 else
2620 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2621 parse_unknown_elem(xmlbuf, &elem);
2626 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2627 struct actctx_loader* acl, const struct xml_elem *parent,
2628 struct assembly_identity* expected_ai)
2630 struct xml_elem elem;
2631 struct xml_attr attr;
2632 BOOL end = FALSE, version = FALSE;
2634 TRACE("(%p)\n", xmlbuf);
2636 while (next_xml_attr(xmlbuf, &attr, &end))
2638 if (xml_attr_cmp(&attr, manifestVersionW))
2640 static const WCHAR v10W[] = {'1','.','0',0};
2641 if (!xmlstr_cmp(&attr.value, v10W))
2643 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2644 break;
2646 version = TRUE;
2648 else if (!is_xmlns_attr( &attr ))
2650 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2654 if (end || !version)
2656 set_error( xmlbuf );
2657 return;
2660 while (next_xml_elem(xmlbuf, &elem, parent))
2662 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2664 parse_noinherit_elem(xmlbuf, &elem);
2665 assembly->no_inherit = TRUE;
2667 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2669 parse_noinheritable_elem(xmlbuf, &elem);
2671 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2673 parse_description_elem(xmlbuf, &elem);
2675 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2677 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2679 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2681 parse_dependency_elem(xmlbuf, acl, &elem);
2683 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2685 parse_file_elem(xmlbuf, assembly, acl, &elem);
2687 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2689 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2691 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2693 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2695 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2697 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2699 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2701 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2703 if (!xmlbuf->error && expected_ai)
2705 /* FIXME: more tests */
2706 if (assembly->type == ASSEMBLY_MANIFEST &&
2707 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2709 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2710 expected_ai->version.major, expected_ai->version.minor,
2711 expected_ai->version.build, expected_ai->version.revision,
2712 assembly->id.version.major, assembly->id.version.minor,
2713 assembly->id.version.build, assembly->id.version.revision);
2714 set_error( xmlbuf );
2716 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2717 (assembly->id.version.major != expected_ai->version.major ||
2718 assembly->id.version.minor != expected_ai->version.minor ||
2719 assembly->id.version.build < expected_ai->version.build ||
2720 (assembly->id.version.build == expected_ai->version.build &&
2721 assembly->id.version.revision < expected_ai->version.revision)))
2723 FIXME("wrong version for shared assembly manifest\n");
2724 set_error( xmlbuf );
2728 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2730 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2732 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2734 parse_application_elem(xmlbuf, assembly, acl, &elem);
2736 else
2738 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2739 parse_unknown_elem(xmlbuf, &elem);
2743 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2744 assembly->no_inherit)
2746 set_error( xmlbuf );
2750 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2751 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2753 struct xml_elem elem;
2754 struct xml_elem parent = {};
2756 xmlbuf->error = FALSE;
2757 xmlbuf->ns_pos = 0;
2759 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2761 if (xmlstr_cmp(&elem.name, xmlW) &&
2762 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2763 return STATUS_SXS_CANT_GEN_ACTCTX;
2765 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2767 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2768 return STATUS_SXS_CANT_GEN_ACTCTX;
2771 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2772 if (xmlbuf->error)
2774 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2775 return STATUS_SXS_CANT_GEN_ACTCTX;
2778 if (next_xml_elem(xmlbuf, &elem, &parent))
2780 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2781 return STATUS_SXS_CANT_GEN_ACTCTX;
2784 if (xmlbuf->ptr != xmlbuf->end)
2786 FIXME("parse error\n");
2787 return STATUS_SXS_CANT_GEN_ACTCTX;
2789 return STATUS_SUCCESS;
2792 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2793 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2794 const void *buffer, SIZE_T size )
2796 xmlbuf_t xmlbuf;
2797 NTSTATUS status;
2798 struct assembly *assembly;
2799 int unicode_tests;
2801 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2803 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2804 return STATUS_SXS_CANT_GEN_ACTCTX;
2806 if (directory && !(assembly->directory = strdupW(directory)))
2807 return STATUS_NO_MEMORY;
2809 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2810 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2811 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2813 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2814 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2816 xmlbuf.ptr = buffer;
2817 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2818 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2820 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2822 const WCHAR *buf = buffer;
2823 WCHAR *new_buff;
2824 unsigned int i;
2826 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2827 return STATUS_NO_MEMORY;
2828 for (i = 0; i < size / sizeof(WCHAR); i++)
2829 new_buff[i] = RtlUshortByteSwap( buf[i] );
2830 xmlbuf.ptr = new_buff;
2831 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2832 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2833 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2835 else
2837 DWORD len;
2838 WCHAR *new_buff;
2840 /* let's assume utf-8 for now */
2841 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2842 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2843 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2844 xmlbuf.ptr = new_buff;
2845 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2846 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2847 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2849 return status;
2852 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2854 OBJECT_ATTRIBUTES attr;
2855 IO_STATUS_BLOCK io;
2857 attr.Length = sizeof(attr);
2858 attr.RootDirectory = 0;
2859 attr.Attributes = OBJ_CASE_INSENSITIVE;
2860 attr.ObjectName = name;
2861 attr.SecurityDescriptor = NULL;
2862 attr.SecurityQualityOfService = NULL;
2863 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2866 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2868 NTSTATUS status;
2869 ULONG_PTR magic;
2870 LDR_MODULE *pldr;
2872 LdrLockLoaderLock(0, NULL, &magic);
2873 status = LdrFindEntryForAddress( module, &pldr );
2874 if (status == STATUS_SUCCESS)
2876 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2877 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2879 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2880 str->Length = pldr->FullDllName.Length;
2881 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2883 else status = STATUS_NO_MEMORY;
2885 LdrUnlockLoaderLock(0, magic);
2886 return status;
2889 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2890 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2891 HANDLE hModule, LPCWSTR resname, ULONG lang )
2893 NTSTATUS status;
2894 UNICODE_STRING nameW;
2895 LDR_RESOURCE_INFO info;
2896 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2897 void *ptr;
2899 if (TRACE_ON(actctx))
2901 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2903 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2904 hModule, debugstr_w(nameW.Buffer) );
2905 RtlFreeUnicodeString( &nameW );
2907 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2908 hModule, debugstr_w(filename) );
2911 if (!resname) return STATUS_INVALID_PARAMETER;
2913 info.Type = RT_MANIFEST;
2914 info.Language = lang;
2915 if (!((ULONG_PTR)resname >> 16))
2917 info.Name = (ULONG_PTR)resname;
2918 status = LdrFindResource_U(hModule, &info, 3, &entry);
2920 else if (resname[0] == '#')
2922 ULONG value;
2923 RtlInitUnicodeString(&nameW, resname + 1);
2924 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2925 return STATUS_INVALID_PARAMETER;
2926 info.Name = value;
2927 status = LdrFindResource_U(hModule, &info, 3, &entry);
2929 else
2931 RtlCreateUnicodeString(&nameW, resname);
2932 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2933 info.Name = (ULONG_PTR)nameW.Buffer;
2934 status = LdrFindResource_U(hModule, &info, 3, &entry);
2935 RtlFreeUnicodeString(&nameW);
2937 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2939 if (status == STATUS_SUCCESS)
2940 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2942 return status;
2945 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2946 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2947 HANDLE file, LPCWSTR resname, ULONG lang )
2949 HANDLE mapping;
2950 OBJECT_ATTRIBUTES attr;
2951 LARGE_INTEGER size;
2952 LARGE_INTEGER offset;
2953 NTSTATUS status;
2954 SIZE_T count;
2955 void *base;
2957 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2959 attr.Length = sizeof(attr);
2960 attr.RootDirectory = 0;
2961 attr.ObjectName = NULL;
2962 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2963 attr.SecurityDescriptor = NULL;
2964 attr.SecurityQualityOfService = NULL;
2966 size.QuadPart = 0;
2967 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2968 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2969 if (status != STATUS_SUCCESS) return status;
2971 offset.QuadPart = 0;
2972 count = 0;
2973 base = NULL;
2974 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2975 &count, ViewShare, 0, PAGE_READONLY );
2976 NtClose( mapping );
2977 if (status != STATUS_SUCCESS) return status;
2979 if (RtlImageNtHeader(base)) /* we got a PE file */
2981 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2982 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2984 else status = STATUS_INVALID_IMAGE_FORMAT;
2986 NtUnmapViewOfSection( GetCurrentProcess(), base );
2987 return status;
2990 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2991 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2993 FILE_END_OF_FILE_INFORMATION info;
2994 IO_STATUS_BLOCK io;
2995 HANDLE mapping;
2996 OBJECT_ATTRIBUTES attr;
2997 LARGE_INTEGER size;
2998 LARGE_INTEGER offset;
2999 NTSTATUS status;
3000 SIZE_T count;
3001 void *base;
3003 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3005 attr.Length = sizeof(attr);
3006 attr.RootDirectory = 0;
3007 attr.ObjectName = NULL;
3008 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3009 attr.SecurityDescriptor = NULL;
3010 attr.SecurityQualityOfService = NULL;
3012 size.QuadPart = 0;
3013 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3014 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3015 if (status != STATUS_SUCCESS) return status;
3017 offset.QuadPart = 0;
3018 count = 0;
3019 base = NULL;
3020 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3021 &count, ViewShare, 0, PAGE_READONLY );
3022 NtClose( mapping );
3023 if (status != STATUS_SUCCESS) return status;
3025 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3026 if (status == STATUS_SUCCESS)
3027 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
3029 NtUnmapViewOfSection( GetCurrentProcess(), base );
3030 return status;
3033 /* try to load the .manifest file associated to the file */
3034 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3035 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3037 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3038 WCHAR *buffer;
3039 NTSTATUS status;
3040 UNICODE_STRING nameW;
3041 HANDLE file;
3042 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3044 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3046 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3048 if (module) /* use the module filename */
3050 UNICODE_STRING name;
3052 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3054 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3055 strcatW( name.Buffer, dotManifestW );
3056 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3057 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3058 RtlFreeUnicodeString( &name );
3060 if (status) return status;
3062 else
3064 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3065 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3066 return STATUS_NO_MEMORY;
3067 strcpyW( buffer, filename );
3068 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3069 strcatW( buffer, dotManifestW );
3070 RtlInitUnicodeString( &nameW, buffer );
3073 if (!open_nt_file( &file, &nameW ))
3075 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3076 NtClose( file );
3078 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3079 RtlFreeUnicodeString( &nameW );
3080 return status;
3083 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3085 static const WCHAR lookup_fmtW[] =
3086 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3087 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3088 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3090 WCHAR *lookup, *ret = NULL;
3091 UNICODE_STRING lookup_us;
3092 IO_STATUS_BLOCK io;
3093 const WCHAR *lang = ai->language;
3094 unsigned int data_pos = 0, data_len;
3095 char buffer[8192];
3097 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3099 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3100 (strlenW(ai->arch) + strlenW(ai->name)
3101 + strlenW(ai->public_key) + strlenW(lang) + 20) * sizeof(WCHAR)
3102 + sizeof(lookup_fmtW) )))
3103 return NULL;
3104 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3105 ai->version.major, ai->version.minor, lang );
3106 RtlInitUnicodeString( &lookup_us, lookup );
3108 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3109 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3111 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3112 FILE_BOTH_DIR_INFORMATION *dir_info;
3113 WCHAR *tmp;
3114 ULONG build, revision;
3116 data_len = io.Information;
3118 for (;;)
3120 if (data_pos >= data_len)
3122 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3123 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3124 break;
3125 data_len = io.Information;
3126 data_pos = 0;
3128 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3130 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3131 else data_pos = data_len;
3133 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
3134 build = atoiW(tmp);
3135 if (build < min_build) continue;
3136 tmp = strchrW(tmp, '.') + 1;
3137 revision = atoiW(tmp);
3138 if (build == min_build && revision < min_revision) continue;
3139 tmp = strchrW(tmp, '_') + 1;
3140 tmp = strchrW(tmp, '_') + 1;
3141 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3142 !strncmpiW( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3144 /* prefer a non-Wine manifest if we already have one */
3145 /* we'll still load the builtin dll if specified through DllOverrides */
3146 if (ret) continue;
3148 else
3150 min_build = build;
3151 min_revision = revision;
3153 ai->version.build = build;
3154 ai->version.revision = revision;
3155 RtlFreeHeap( GetProcessHeap(), 0, ret );
3156 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3158 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3159 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3163 else WARN("no matching file for %s\n", debugstr_w(lookup));
3164 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3165 return ret;
3168 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3170 struct assembly_identity sxs_ai;
3171 UNICODE_STRING path_us;
3172 OBJECT_ATTRIBUTES attr;
3173 IO_STATUS_BLOCK io;
3174 WCHAR *path, *file = NULL;
3175 HANDLE handle;
3177 static const WCHAR manifest_dirW[] =
3178 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3180 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3182 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3183 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3184 return STATUS_NO_MEMORY;
3186 strcpyW( path, user_shared_data->NtSystemRoot );
3187 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3189 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3191 RtlFreeHeap( GetProcessHeap(), 0, path );
3192 return STATUS_NO_SUCH_FILE;
3194 RtlFreeHeap( GetProcessHeap(), 0, path );
3196 attr.Length = sizeof(attr);
3197 attr.RootDirectory = 0;
3198 attr.Attributes = OBJ_CASE_INSENSITIVE;
3199 attr.ObjectName = &path_us;
3200 attr.SecurityDescriptor = NULL;
3201 attr.SecurityQualityOfService = NULL;
3203 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3204 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3206 sxs_ai = *ai;
3207 file = lookup_manifest_file( handle, &sxs_ai );
3208 NtClose( handle );
3210 if (!file)
3212 RtlFreeUnicodeString( &path_us );
3213 return STATUS_NO_SUCH_FILE;
3216 /* append file name to directory path */
3217 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3218 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3220 RtlFreeHeap( GetProcessHeap(), 0, file );
3221 RtlFreeUnicodeString( &path_us );
3222 return STATUS_NO_MEMORY;
3225 path[path_us.Length/sizeof(WCHAR)] = '\\';
3226 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3227 RtlInitUnicodeString( &path_us, path );
3228 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3230 if (!open_nt_file( &handle, &path_us ))
3232 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3233 NtClose( handle );
3235 else io.u.Status = STATUS_NO_SUCH_FILE;
3237 RtlFreeHeap( GetProcessHeap(), 0, file );
3238 RtlFreeUnicodeString( &path_us );
3239 return io.u.Status;
3242 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3243 struct assembly_identity* ai)
3245 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3246 unsigned int i;
3247 WCHAR *buffer, *p, *directory;
3248 NTSTATUS status;
3249 UNICODE_STRING nameW;
3250 HANDLE file;
3251 DWORD len;
3253 TRACE( "looking for name=%s version=%s arch=%s\n",
3254 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3256 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3258 /* FIXME: add support for language specific lookup */
3260 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3261 strlenW(acl->actctx->appdir.info));
3263 nameW.Buffer = NULL;
3264 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3265 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3266 return STATUS_NO_MEMORY;
3268 if (!(directory = build_assembly_dir( ai )))
3270 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3271 return STATUS_NO_MEMORY;
3274 /* Lookup in <dir>\name.dll
3275 * <dir>\name.manifest
3276 * <dir>\name\name.dll
3277 * <dir>\name\name.manifest
3279 * First 'appdir' is used as <dir>, if that failed
3280 * it tries application manifest file path.
3282 strcpyW( buffer, acl->actctx->appdir.info );
3283 p = buffer + strlenW(buffer);
3284 for (i = 0; i < 4; i++)
3286 if (i == 2)
3288 struct assembly *assembly = acl->actctx->assemblies;
3289 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3291 else *p++ = '\\';
3293 strcpyW( p, ai->name );
3294 p += strlenW(p);
3296 strcpyW( p, dotDllW );
3297 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3299 status = open_nt_file( &file, &nameW );
3300 if (!status)
3302 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3303 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3304 NtClose( file );
3305 if (status == STATUS_SUCCESS)
3306 break;
3308 RtlFreeUnicodeString( &nameW );
3311 strcpyW( p, dotManifestW );
3312 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3314 status = open_nt_file( &file, &nameW );
3315 if (!status)
3317 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3318 NtClose( file );
3319 break;
3321 RtlFreeUnicodeString( &nameW );
3323 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3325 RtlFreeUnicodeString( &nameW );
3326 RtlFreeHeap( GetProcessHeap(), 0, directory );
3327 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3328 return status;
3331 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3333 NTSTATUS status = STATUS_SUCCESS;
3334 unsigned int i;
3336 for (i = 0; i < acl->num_dependencies; i++)
3338 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3340 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3342 FIXME( "Could not find dependent assembly %s (%s)\n",
3343 debugstr_w(acl->dependencies[i].name),
3344 debugstr_version(&acl->dependencies[i].version) );
3345 status = STATUS_SXS_CANT_GEN_ACTCTX;
3346 break;
3350 /* FIXME should now iterate through all refs */
3351 return status;
3354 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3355 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3357 NTSTATUS status = STATUS_SUCCESS;
3359 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3361 if (*handle) return STATUS_INVALID_PARAMETER;
3363 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3364 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3366 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3368 ULONG_PTR magic;
3369 LDR_MODULE *pldr;
3371 if (!*handle) return STATUS_INVALID_PARAMETER;
3373 LdrLockLoaderLock( 0, NULL, &magic );
3374 if (!LdrFindEntryForAddress( *handle, &pldr ))
3376 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3377 status = STATUS_DLL_NOT_FOUND;
3378 else
3379 *handle = pldr->ActivationContext;
3381 else status = STATUS_DLL_NOT_FOUND;
3382 LdrUnlockLoaderLock( 0, magic );
3384 else if (!*handle && (class != ActivationContextBasicInformation))
3385 *handle = process_actctx;
3387 return status;
3390 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3392 unsigned int i, j, total_len = 0, dll_count = 0;
3393 struct strsection_header *header;
3394 struct dllredirect_data *data;
3395 struct string_index *index;
3396 ULONG name_offset;
3398 /* compute section length */
3399 for (i = 0; i < actctx->num_assemblies; i++)
3401 struct assembly *assembly = &actctx->assemblies[i];
3402 for (j = 0; j < assembly->num_dlls; j++)
3404 struct dll_redirect *dll = &assembly->dlls[j];
3406 /* each entry needs index, data and string data */
3407 total_len += sizeof(*index);
3408 total_len += sizeof(*data);
3409 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3412 dll_count += assembly->num_dlls;
3415 total_len += sizeof(*header);
3417 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3418 if (!header) return STATUS_NO_MEMORY;
3420 memset(header, 0, sizeof(*header));
3421 header->magic = STRSECTION_MAGIC;
3422 header->size = sizeof(*header);
3423 header->count = dll_count;
3424 header->index_offset = sizeof(*header);
3425 index = (struct string_index*)((BYTE*)header + header->index_offset);
3426 name_offset = header->index_offset + header->count*sizeof(*index);
3428 for (i = 0; i < actctx->num_assemblies; i++)
3430 struct assembly *assembly = &actctx->assemblies[i];
3431 for (j = 0; j < assembly->num_dlls; j++)
3433 struct dll_redirect *dll = &assembly->dlls[j];
3434 UNICODE_STRING str;
3435 WCHAR *ptrW;
3437 /* setup new index entry */
3438 str.Buffer = dll->name;
3439 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3440 str.MaximumLength = str.Length + sizeof(WCHAR);
3441 /* hash original class name */
3442 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3444 index->name_offset = name_offset;
3445 index->name_len = str.Length;
3446 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3447 index->data_len = sizeof(*data);
3448 index->rosterindex = i + 1;
3450 /* setup data */
3451 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3452 data->size = sizeof(*data);
3453 data->unk = 2; /* FIXME: seems to be constant */
3454 memset(data->res, 0, sizeof(data->res));
3456 /* dll name */
3457 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3458 memcpy(ptrW, dll->name, index->name_len);
3459 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3461 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3463 index++;
3467 *section = header;
3469 return STATUS_SUCCESS;
3472 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3474 struct string_index *iter, *index = NULL;
3475 ULONG hash = 0, i;
3477 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3478 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3480 for (i = 0; i < section->count; i++)
3482 if (iter->hash == hash)
3484 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3486 if (!strcmpiW(nameW, name->Buffer))
3488 index = iter;
3489 break;
3491 else
3492 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3494 iter++;
3497 return index;
3500 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3502 struct guid_index *iter, *index = NULL;
3503 ULONG i;
3505 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3507 for (i = 0; i < section->count; i++)
3509 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3511 index = iter;
3512 break;
3514 iter++;
3517 return index;
3520 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3522 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3525 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3526 PACTCTX_SECTION_KEYED_DATA data)
3528 struct dllredirect_data *dll;
3529 struct string_index *index;
3531 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3533 if (!actctx->dllredirect_section)
3535 struct strsection_header *section;
3537 NTSTATUS status = build_dllredirect_section(actctx, &section);
3538 if (status) return status;
3540 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3541 RtlFreeHeap(GetProcessHeap(), 0, section);
3544 index = find_string_index(actctx->dllredirect_section, name);
3545 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3547 if (data)
3549 dll = get_dllredirect_data(actctx, index);
3551 data->ulDataFormatVersion = 1;
3552 data->lpData = dll;
3553 data->ulLength = dll->size;
3554 data->lpSectionGlobalData = NULL;
3555 data->ulSectionGlobalDataLength = 0;
3556 data->lpSectionBase = actctx->dllredirect_section;
3557 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3558 data->hActCtx = NULL;
3560 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3561 data->ulAssemblyRosterIndex = index->rosterindex;
3564 return STATUS_SUCCESS;
3567 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3569 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3572 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3574 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3577 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3579 unsigned int i, j, k, total_len = 0, class_count = 0;
3580 struct wndclass_redirect_data *data;
3581 struct strsection_header *header;
3582 struct string_index *index;
3583 ULONG name_offset;
3585 /* compute section length */
3586 for (i = 0; i < actctx->num_assemblies; i++)
3588 struct assembly *assembly = &actctx->assemblies[i];
3589 for (j = 0; j < assembly->num_dlls; j++)
3591 struct dll_redirect *dll = &assembly->dlls[j];
3592 for (k = 0; k < dll->entities.num; k++)
3594 struct entity *entity = &dll->entities.base[k];
3595 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3597 int class_len = strlenW(entity->u.class.name) + 1;
3598 int len;
3600 /* each class entry needs index, data and string data */
3601 total_len += sizeof(*index);
3602 total_len += sizeof(*data);
3603 /* original name is stored separately */
3604 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3605 /* versioned name and module name are stored one after another */
3606 if (entity->u.class.versioned)
3607 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3608 else
3609 len = class_len;
3610 len += strlenW(dll->name) + 1;
3611 total_len += aligned_string_len(len*sizeof(WCHAR));
3613 class_count++;
3619 total_len += sizeof(*header);
3621 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3622 if (!header) return STATUS_NO_MEMORY;
3624 memset(header, 0, sizeof(*header));
3625 header->magic = STRSECTION_MAGIC;
3626 header->size = sizeof(*header);
3627 header->count = class_count;
3628 header->index_offset = sizeof(*header);
3629 index = (struct string_index*)((BYTE*)header + header->index_offset);
3630 name_offset = header->index_offset + header->count*sizeof(*index);
3632 for (i = 0; i < actctx->num_assemblies; i++)
3634 struct assembly *assembly = &actctx->assemblies[i];
3635 for (j = 0; j < assembly->num_dlls; j++)
3637 struct dll_redirect *dll = &assembly->dlls[j];
3638 for (k = 0; k < dll->entities.num; k++)
3640 struct entity *entity = &dll->entities.base[k];
3641 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3643 static const WCHAR exclW[] = {'!',0};
3644 ULONG versioned_len, module_len;
3645 UNICODE_STRING str;
3646 WCHAR *ptrW;
3648 /* setup new index entry */
3649 str.Buffer = entity->u.class.name;
3650 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3651 str.MaximumLength = str.Length + sizeof(WCHAR);
3652 /* hash original class name */
3653 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3655 /* include '!' separator too */
3656 if (entity->u.class.versioned)
3657 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3658 else
3659 versioned_len = str.Length;
3660 module_len = strlenW(dll->name)*sizeof(WCHAR);
3662 index->name_offset = name_offset;
3663 index->name_len = str.Length;
3664 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3665 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3666 index->rosterindex = i + 1;
3668 /* setup data */
3669 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3670 data->size = sizeof(*data);
3671 data->res = 0;
3672 data->name_len = versioned_len;
3673 data->name_offset = sizeof(*data);
3674 data->module_len = module_len;
3675 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3677 /* original class name */
3678 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3679 memcpy(ptrW, entity->u.class.name, index->name_len);
3680 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3682 /* module name */
3683 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3684 memcpy(ptrW, dll->name, data->module_len);
3685 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3687 /* versioned name */
3688 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3689 if (entity->u.class.versioned)
3691 get_assembly_version(assembly, ptrW);
3692 strcatW(ptrW, exclW);
3693 strcatW(ptrW, entity->u.class.name);
3695 else
3697 memcpy(ptrW, entity->u.class.name, index->name_len);
3698 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3701 name_offset += sizeof(*data);
3702 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3704 index++;
3710 *section = header;
3712 return STATUS_SUCCESS;
3715 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3716 PACTCTX_SECTION_KEYED_DATA data)
3718 struct string_index *iter, *index = NULL;
3719 struct wndclass_redirect_data *class;
3720 ULONG hash;
3721 int i;
3723 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3725 if (!actctx->wndclass_section)
3727 struct strsection_header *section;
3729 NTSTATUS status = build_wndclass_section(actctx, &section);
3730 if (status) return status;
3732 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3733 RtlFreeHeap(GetProcessHeap(), 0, section);
3736 hash = 0;
3737 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3738 iter = get_wndclass_first_index(actctx);
3740 for (i = 0; i < actctx->wndclass_section->count; i++)
3742 if (iter->hash == hash)
3744 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3746 if (!strcmpiW(nameW, name->Buffer))
3748 index = iter;
3749 break;
3751 else
3752 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3754 iter++;
3757 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3759 if (data)
3761 class = get_wndclass_data(actctx, index);
3763 data->ulDataFormatVersion = 1;
3764 data->lpData = class;
3765 /* full length includes string length with nulls */
3766 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3767 data->lpSectionGlobalData = NULL;
3768 data->ulSectionGlobalDataLength = 0;
3769 data->lpSectionBase = actctx->wndclass_section;
3770 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3771 data->hActCtx = NULL;
3773 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3774 data->ulAssemblyRosterIndex = index->rosterindex;
3777 return STATUS_SUCCESS;
3780 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3782 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3783 struct guidsection_header *header;
3784 ULONG module_offset, data_offset;
3785 struct tlibredirect_data *data;
3786 struct guid_index *index;
3788 /* compute section length */
3789 for (i = 0; i < actctx->num_assemblies; i++)
3791 struct assembly *assembly = &actctx->assemblies[i];
3792 for (j = 0; j < assembly->num_dlls; j++)
3794 struct dll_redirect *dll = &assembly->dlls[j];
3795 for (k = 0; k < dll->entities.num; k++)
3797 struct entity *entity = &dll->entities.base[k];
3798 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3800 /* each entry needs index, data and string data for module name and help string */
3801 total_len += sizeof(*index);
3802 total_len += sizeof(*data);
3803 /* help string is stored separately */
3804 if (*entity->u.typelib.helpdir)
3805 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3807 /* module names are packed one after another */
3808 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3810 tlib_count++;
3816 total_len += aligned_string_len(names_len);
3817 total_len += sizeof(*header);
3819 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3820 if (!header) return STATUS_NO_MEMORY;
3822 memset(header, 0, sizeof(*header));
3823 header->magic = GUIDSECTION_MAGIC;
3824 header->size = sizeof(*header);
3825 header->count = tlib_count;
3826 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3827 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3828 module_offset = sizeof(*header);
3829 data_offset = header->index_offset + tlib_count*sizeof(*index);
3831 for (i = 0; i < actctx->num_assemblies; i++)
3833 struct assembly *assembly = &actctx->assemblies[i];
3834 for (j = 0; j < assembly->num_dlls; j++)
3836 struct dll_redirect *dll = &assembly->dlls[j];
3837 for (k = 0; k < dll->entities.num; k++)
3839 struct entity *entity = &dll->entities.base[k];
3840 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3842 ULONG module_len, help_len;
3843 UNICODE_STRING str;
3844 WCHAR *ptrW;
3846 if (*entity->u.typelib.helpdir)
3847 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3848 else
3849 help_len = 0;
3851 module_len = strlenW(dll->name)*sizeof(WCHAR);
3853 /* setup new index entry */
3854 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3855 RtlGUIDFromString(&str, &index->guid);
3856 index->data_offset = data_offset;
3857 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3858 index->rosterindex = i + 1;
3860 /* setup data */
3861 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3862 data->size = sizeof(*data);
3863 data->res = 0;
3864 data->name_len = module_len;
3865 data->name_offset = module_offset;
3866 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3867 data->langid = 0;
3868 data->flags = entity->u.typelib.flags;
3869 data->help_len = help_len;
3870 data->help_offset = sizeof(*data);
3871 data->major_version = entity->u.typelib.major;
3872 data->minor_version = entity->u.typelib.minor;
3874 /* module name */
3875 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3876 memcpy(ptrW, dll->name, data->name_len);
3877 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3879 /* help string */
3880 if (data->help_len)
3882 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3883 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3884 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3887 data_offset += sizeof(*data);
3888 if (help_len)
3889 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3891 module_offset += module_len + sizeof(WCHAR);
3893 index++;
3899 *section = header;
3901 return STATUS_SUCCESS;
3904 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3906 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3909 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3911 struct guid_index *index = NULL;
3912 struct tlibredirect_data *tlib;
3914 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3916 if (!actctx->tlib_section)
3918 struct guidsection_header *section;
3920 NTSTATUS status = build_tlib_section(actctx, &section);
3921 if (status) return status;
3923 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3924 RtlFreeHeap(GetProcessHeap(), 0, section);
3927 index = find_guid_index(actctx->tlib_section, guid);
3928 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3930 tlib = get_tlib_data(actctx, index);
3932 data->ulDataFormatVersion = 1;
3933 data->lpData = tlib;
3934 /* full length includes string length with nulls */
3935 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3936 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3937 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3938 data->lpSectionBase = actctx->tlib_section;
3939 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3940 data->hActCtx = NULL;
3942 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3943 data->ulAssemblyRosterIndex = index->rosterindex;
3945 return STATUS_SUCCESS;
3948 static void generate_uuid(ULONG *seed, GUID *guid)
3950 ULONG *ptr = (ULONG*)guid;
3951 int i;
3953 /* GUID is 16 bytes long */
3954 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3955 *ptr = RtlUniform(seed);
3957 guid->Data3 &= 0x0fff;
3958 guid->Data3 |= (4 << 12);
3959 guid->Data4[0] &= 0x3f;
3960 guid->Data4[0] |= 0x80;
3963 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3964 unsigned int *count, unsigned int *len, unsigned int *module_len)
3966 unsigned int i;
3968 for (i = 0; i < entities->num; i++)
3970 struct entity *entity = &entities->base[i];
3971 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3973 /* each entry needs two index entries, extra one goes for alias GUID */
3974 *len += 2*sizeof(struct guid_index);
3975 /* To save some memory we don't allocated two data structures,
3976 instead alias index and normal index point to the same data structure. */
3977 *len += sizeof(struct comclassredirect_data);
3979 /* for clrClass store some more */
3980 if (entity->u.comclass.name)
3982 unsigned int str_len;
3984 /* all string data is stored together in aligned block */
3985 str_len = strlenW(entity->u.comclass.name)+1;
3986 if (entity->u.comclass.progid)
3987 str_len += strlenW(entity->u.comclass.progid)+1;
3988 if (entity->u.comclass.version)
3989 str_len += strlenW(entity->u.comclass.version)+1;
3991 *len += sizeof(struct clrclass_data);
3992 *len += aligned_string_len(str_len*sizeof(WCHAR));
3994 /* module name is forced to mscoree.dll, and stored two times with different case */
3995 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3997 else
3999 /* progid string is stored separately */
4000 if (entity->u.comclass.progid)
4001 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4003 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
4006 *count += 1;
4011 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4012 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4013 ULONG *seed, ULONG rosterindex)
4015 unsigned int i;
4017 for (i = 0; i < entities->num; i++)
4019 struct entity *entity = &entities->base[i];
4020 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4022 ULONG module_len, progid_len, str_len = 0;
4023 struct comclassredirect_data *data;
4024 struct guid_index *alias_index;
4025 struct clrclass_data *clrdata;
4026 UNICODE_STRING str;
4027 WCHAR *ptrW;
4029 if (entity->u.comclass.progid)
4030 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4031 else
4032 progid_len = 0;
4034 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4036 /* setup new index entry */
4037 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4038 RtlGUIDFromString(&str, &(*index)->guid);
4040 (*index)->data_offset = *data_offset;
4041 (*index)->data_len = sizeof(*data); /* additional length added later */
4042 (*index)->rosterindex = rosterindex;
4044 /* Setup new index entry for alias guid. Alias index records are placed after
4045 normal records, so normal guids are hit first on search. Note that class count
4046 is doubled. */
4047 alias_index = (*index) + section->count/2;
4048 generate_uuid(seed, &alias_index->guid);
4049 alias_index->data_offset = (*index)->data_offset;
4050 alias_index->data_len = 0;
4051 alias_index->rosterindex = (*index)->rosterindex;
4053 /* setup data */
4054 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4055 data->size = sizeof(*data);
4056 data->res = 0;
4057 data->res1[0] = 0;
4058 data->res1[1] = 0;
4059 data->model = entity->u.comclass.model;
4060 data->clsid = (*index)->guid;
4061 data->alias = alias_index->guid;
4062 data->clsid2 = data->clsid;
4063 if (entity->u.comclass.tlbid)
4065 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4066 RtlGUIDFromString(&str, &data->tlbid);
4068 else
4069 memset(&data->tlbid, 0, sizeof(data->tlbid));
4070 data->name_len = module_len;
4071 data->name_offset = *module_offset;
4072 data->progid_len = progid_len;
4073 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4074 data->clrdata_len = 0; /* will be set later */
4075 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4076 data->miscstatus = entity->u.comclass.miscstatus;
4077 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4078 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4079 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4080 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4082 /* mask describes which misc* data is available */
4083 data->miscmask = 0;
4084 if (data->miscstatus)
4085 data->miscmask |= MiscStatus;
4086 if (data->miscstatuscontent)
4087 data->miscmask |= MiscStatusContent;
4088 if (data->miscstatusthumbnail)
4089 data->miscmask |= MiscStatusThumbnail;
4090 if (data->miscstatusicon)
4091 data->miscmask |= MiscStatusIcon;
4092 if (data->miscstatusdocprint)
4093 data->miscmask |= MiscStatusDocPrint;
4095 if (data->clrdata_offset)
4097 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4099 clrdata->size = sizeof(*clrdata);
4100 clrdata->res[0] = 0;
4101 clrdata->res[1] = 2; /* FIXME: unknown field */
4102 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4103 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4104 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4105 clrdata->name_offset = clrdata->size;
4106 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4107 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4108 clrdata->res2[0] = 0;
4109 clrdata->res2[1] = 0;
4111 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4113 /* module name */
4114 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4115 memcpy(ptrW, mscoree2W, clrdata->module_len);
4116 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4118 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4119 memcpy(ptrW, mscoreeW, data->name_len);
4120 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4122 /* class name */
4123 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4124 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4125 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4127 /* runtime version, optional */
4128 if (clrdata->version_len)
4130 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4132 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4133 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4134 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4137 if (data->progid_len)
4138 data->progid_offset += data->clrdata_len;
4139 (*index)->data_len += sizeof(*clrdata);
4141 else
4143 clrdata = NULL;
4145 /* module name */
4146 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4147 memcpy(ptrW, dll->name, data->name_len);
4148 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4151 /* progid string */
4152 if (data->progid_len)
4154 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4155 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4156 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4159 /* string block length */
4160 str_len = 0;
4161 if (clrdata)
4163 str_len += clrdata->name_len + sizeof(WCHAR);
4164 if (clrdata->version_len)
4165 str_len += clrdata->version_len + sizeof(WCHAR);
4167 if (progid_len)
4168 str_len += progid_len + sizeof(WCHAR);
4170 (*index)->data_len += aligned_string_len(str_len);
4171 alias_index->data_len = (*index)->data_len;
4173 /* move to next data record */
4174 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4175 (*module_offset) += module_len + sizeof(WCHAR);
4177 if (clrdata)
4179 (*data_offset) += sizeof(*clrdata);
4180 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4182 (*index) += 1;
4187 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4189 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4190 struct guidsection_header *header;
4191 ULONG module_offset, data_offset;
4192 struct guid_index *index;
4193 ULONG seed;
4195 /* compute section length */
4196 for (i = 0; i < actctx->num_assemblies; i++)
4198 struct assembly *assembly = &actctx->assemblies[i];
4199 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4200 for (j = 0; j < assembly->num_dlls; j++)
4202 struct dll_redirect *dll = &assembly->dlls[j];
4203 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4207 total_len += aligned_string_len(names_len);
4208 total_len += sizeof(*header);
4210 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4211 if (!header) return STATUS_NO_MEMORY;
4213 memset(header, 0, sizeof(*header));
4214 header->magic = GUIDSECTION_MAGIC;
4215 header->size = sizeof(*header);
4216 header->count = 2*class_count;
4217 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4218 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4219 module_offset = sizeof(*header);
4220 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4222 seed = NtGetTickCount();
4223 for (i = 0; i < actctx->num_assemblies; i++)
4225 struct assembly *assembly = &actctx->assemblies[i];
4226 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4227 for (j = 0; j < assembly->num_dlls; j++)
4229 struct dll_redirect *dll = &assembly->dlls[j];
4230 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4234 *section = header;
4236 return STATUS_SUCCESS;
4239 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4241 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4244 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4246 struct comclassredirect_data *comclass;
4247 struct guid_index *index = NULL;
4249 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4251 if (!actctx->comserver_section)
4253 struct guidsection_header *section;
4255 NTSTATUS status = build_comserver_section(actctx, &section);
4256 if (status) return status;
4258 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4259 RtlFreeHeap(GetProcessHeap(), 0, section);
4262 index = find_guid_index(actctx->comserver_section, guid);
4263 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4265 comclass = get_comclass_data(actctx, index);
4267 data->ulDataFormatVersion = 1;
4268 data->lpData = comclass;
4269 /* full length includes string length with nulls */
4270 data->ulLength = comclass->size + comclass->clrdata_len;
4271 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4272 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4273 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4274 data->lpSectionBase = actctx->comserver_section;
4275 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4276 data->hActCtx = NULL;
4278 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4279 data->ulAssemblyRosterIndex = index->rosterindex;
4281 return STATUS_SUCCESS;
4284 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4286 unsigned int i;
4288 for (i = 0; i < entities->num; i++)
4290 struct entity *entity = &entities->base[i];
4291 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4293 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4294 if (entity->u.ifaceps.name)
4295 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4296 *count += 1;
4301 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4302 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4304 unsigned int i;
4306 for (i = 0; i < entities->num; i++)
4308 struct entity *entity = &entities->base[i];
4309 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4311 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4312 UNICODE_STRING str;
4313 ULONG name_len;
4315 if (entity->u.ifaceps.name)
4316 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4317 else
4318 name_len = 0;
4320 /* setup index */
4321 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4322 RtlGUIDFromString(&str, &(*index)->guid);
4323 (*index)->data_offset = *data_offset;
4324 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4325 (*index)->rosterindex = rosterindex;
4327 /* setup data record */
4328 data->size = sizeof(*data);
4329 data->mask = entity->u.ifaceps.mask;
4331 /* proxyStubClsid32 value is only stored for external PS,
4332 if set it's used as iid, otherwise 'iid' attribute value is used */
4333 if (entity->u.ifaceps.ps32)
4335 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4336 RtlGUIDFromString(&str, &data->iid);
4338 else
4339 data->iid = (*index)->guid;
4341 data->nummethods = entity->u.ifaceps.nummethods;
4343 if (entity->u.ifaceps.tlib)
4345 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4346 RtlGUIDFromString(&str, &data->tlbid);
4348 else
4349 memset(&data->tlbid, 0, sizeof(data->tlbid));
4351 if (entity->u.ifaceps.base)
4353 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4354 RtlGUIDFromString(&str, &data->base);
4356 else
4357 memset(&data->base, 0, sizeof(data->base));
4359 data->name_len = name_len;
4360 data->name_offset = data->name_len ? sizeof(*data) : 0;
4362 /* name string */
4363 if (data->name_len)
4365 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4366 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4367 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4370 /* move to next record */
4371 (*index) += 1;
4372 *data_offset += sizeof(*data);
4373 if (data->name_len)
4374 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4379 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4381 unsigned int i, j, total_len = 0, count = 0;
4382 struct guidsection_header *header;
4383 struct guid_index *index;
4384 ULONG data_offset;
4386 /* compute section length */
4387 for (i = 0; i < actctx->num_assemblies; i++)
4389 struct assembly *assembly = &actctx->assemblies[i];
4391 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4392 for (j = 0; j < assembly->num_dlls; j++)
4394 struct dll_redirect *dll = &assembly->dlls[j];
4395 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4399 total_len += sizeof(*header);
4401 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4402 if (!header) return STATUS_NO_MEMORY;
4404 memset(header, 0, sizeof(*header));
4405 header->magic = GUIDSECTION_MAGIC;
4406 header->size = sizeof(*header);
4407 header->count = count;
4408 header->index_offset = sizeof(*header);
4409 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4410 data_offset = header->index_offset + count*sizeof(*index);
4412 for (i = 0; i < actctx->num_assemblies; i++)
4414 struct assembly *assembly = &actctx->assemblies[i];
4416 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4417 for (j = 0; j < assembly->num_dlls; j++)
4419 struct dll_redirect *dll = &assembly->dlls[j];
4420 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4424 *section = header;
4426 return STATUS_SUCCESS;
4429 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4431 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4434 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4436 struct ifacepsredirect_data *iface;
4437 struct guid_index *index = NULL;
4439 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4441 if (!actctx->ifaceps_section)
4443 struct guidsection_header *section;
4445 NTSTATUS status = build_ifaceps_section(actctx, &section);
4446 if (status) return status;
4448 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4449 RtlFreeHeap(GetProcessHeap(), 0, section);
4452 index = find_guid_index(actctx->ifaceps_section, guid);
4453 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4455 iface = get_ifaceps_data(actctx, index);
4457 data->ulDataFormatVersion = 1;
4458 data->lpData = iface;
4459 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4460 data->lpSectionGlobalData = NULL;
4461 data->ulSectionGlobalDataLength = 0;
4462 data->lpSectionBase = actctx->ifaceps_section;
4463 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4464 data->hActCtx = NULL;
4466 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4467 data->ulAssemblyRosterIndex = index->rosterindex;
4469 return STATUS_SUCCESS;
4472 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4474 unsigned int i, j, total_len = 0, count = 0;
4475 struct guidsection_header *header;
4476 struct clrsurrogate_data *data;
4477 struct guid_index *index;
4478 ULONG data_offset;
4480 /* compute section length */
4481 for (i = 0; i < actctx->num_assemblies; i++)
4483 struct assembly *assembly = &actctx->assemblies[i];
4484 for (j = 0; j < assembly->entities.num; j++)
4486 struct entity *entity = &assembly->entities.base[j];
4487 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4489 ULONG len;
4491 total_len += sizeof(*index) + sizeof(*data);
4492 len = strlenW(entity->u.clrsurrogate.name) + 1;
4493 if (entity->u.clrsurrogate.version)
4494 len += strlenW(entity->u.clrsurrogate.version) + 1;
4495 total_len += aligned_string_len(len*sizeof(WCHAR));
4497 count++;
4502 total_len += sizeof(*header);
4504 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4505 if (!header) return STATUS_NO_MEMORY;
4507 memset(header, 0, sizeof(*header));
4508 header->magic = GUIDSECTION_MAGIC;
4509 header->size = sizeof(*header);
4510 header->count = count;
4511 header->index_offset = sizeof(*header);
4512 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4513 data_offset = header->index_offset + count*sizeof(*index);
4515 for (i = 0; i < actctx->num_assemblies; i++)
4517 struct assembly *assembly = &actctx->assemblies[i];
4518 for (j = 0; j < assembly->entities.num; j++)
4520 struct entity *entity = &assembly->entities.base[j];
4521 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4523 ULONG version_len, name_len;
4524 UNICODE_STRING str;
4525 WCHAR *ptrW;
4527 if (entity->u.clrsurrogate.version)
4528 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4529 else
4530 version_len = 0;
4531 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4533 /* setup new index entry */
4534 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4535 RtlGUIDFromString(&str, &index->guid);
4537 index->data_offset = data_offset;
4538 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4539 index->rosterindex = i + 1;
4541 /* setup data */
4542 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4543 data->size = sizeof(*data);
4544 data->res = 0;
4545 data->clsid = index->guid;
4546 data->version_offset = version_len ? data->size : 0;
4547 data->version_len = version_len;
4548 data->name_offset = data->size + version_len;
4549 if (version_len)
4550 data->name_offset += sizeof(WCHAR);
4551 data->name_len = name_len;
4553 /* surrogate name */
4554 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4555 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4556 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4558 /* runtime version */
4559 if (data->version_len)
4561 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4562 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4563 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4566 data_offset += index->data_offset;
4567 index++;
4572 *section = header;
4574 return STATUS_SUCCESS;
4577 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4579 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4582 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4584 struct clrsurrogate_data *surrogate;
4585 struct guid_index *index = NULL;
4587 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4589 if (!actctx->clrsurrogate_section)
4591 struct guidsection_header *section;
4593 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4594 if (status) return status;
4596 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4597 RtlFreeHeap(GetProcessHeap(), 0, section);
4600 index = find_guid_index(actctx->clrsurrogate_section, guid);
4601 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4603 surrogate = get_surrogate_data(actctx, index);
4605 data->ulDataFormatVersion = 1;
4606 data->lpData = surrogate;
4607 /* full length includes string length with nulls */
4608 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4609 if (surrogate->version_len)
4610 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4612 data->lpSectionGlobalData = NULL;
4613 data->ulSectionGlobalDataLength = 0;
4614 data->lpSectionBase = actctx->clrsurrogate_section;
4615 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4616 data->hActCtx = NULL;
4618 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4619 data->ulAssemblyRosterIndex = index->rosterindex;
4621 return STATUS_SUCCESS;
4624 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4626 unsigned int i, j, single_len;
4628 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4629 for (i = 0; i < entities->num; i++)
4631 struct entity *entity = &entities->base[i];
4632 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4634 if (entity->u.comclass.progid)
4636 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4637 *count += 1;
4640 for (j = 0; j < entity->u.comclass.progids.num; j++)
4641 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4643 *total_len += single_len*entity->u.comclass.progids.num;
4644 *count += entity->u.comclass.progids.num;
4649 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4650 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4652 struct progidredirect_data *data;
4653 UNICODE_STRING str;
4654 GUID *guid_ptr;
4655 WCHAR *ptrW;
4657 /* setup new index entry */
4659 /* hash progid name */
4660 RtlInitUnicodeString(&str, progid);
4661 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4663 (*index)->name_offset = *data_offset;
4664 (*index)->name_len = str.Length;
4665 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4666 (*index)->data_len = sizeof(*data);
4667 (*index)->rosterindex = rosterindex;
4669 *data_offset += aligned_string_len(str.MaximumLength);
4671 /* setup data structure */
4672 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4673 data->size = sizeof(*data);
4674 data->reserved = 0;
4675 data->clsid_offset = *global_offset;
4677 /* write progid string */
4678 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4679 memcpy(ptrW, progid, (*index)->name_len);
4680 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4682 /* write guid to global area */
4683 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4684 *guid_ptr = *alias;
4686 /* to next entry */
4687 *global_offset += sizeof(GUID);
4688 *data_offset += data->size;
4689 (*index) += 1;
4692 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4693 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4695 unsigned int i, j;
4697 for (i = 0; i < entities->num; i++)
4699 struct entity *entity = &entities->base[i];
4700 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4702 const struct progids *progids = &entity->u.comclass.progids;
4703 struct comclassredirect_data *comclass;
4704 struct guid_index *guid_index;
4705 UNICODE_STRING str;
4706 GUID clsid;
4708 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4709 RtlGUIDFromString(&str, &clsid);
4711 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4712 comclass = get_comclass_data(actctx, guid_index);
4714 if (entity->u.comclass.progid)
4715 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4716 index, data_offset, global_offset, rosterindex);
4718 for (j = 0; j < progids->num; j++)
4719 write_progid_record(section, progids->progids[j], &comclass->alias,
4720 index, data_offset, global_offset, rosterindex);
4725 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4727 unsigned int i, j, total_len = 0, count = 0;
4728 struct strsection_header *header;
4729 ULONG data_offset, global_offset;
4730 struct string_index *index;
4732 /* compute section length */
4733 for (i = 0; i < actctx->num_assemblies; i++)
4735 struct assembly *assembly = &actctx->assemblies[i];
4737 get_progid_datalen(&assembly->entities, &count, &total_len);
4738 for (j = 0; j < assembly->num_dlls; j++)
4740 struct dll_redirect *dll = &assembly->dlls[j];
4741 get_progid_datalen(&dll->entities, &count, &total_len);
4745 total_len += sizeof(*header);
4747 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4748 if (!header) return STATUS_NO_MEMORY;
4750 memset(header, 0, sizeof(*header));
4751 header->magic = STRSECTION_MAGIC;
4752 header->size = sizeof(*header);
4753 header->count = count;
4754 header->global_offset = header->size;
4755 header->global_len = count*sizeof(GUID);
4756 header->index_offset = header->size + header->global_len;
4758 index = (struct string_index*)((BYTE*)header + header->index_offset);
4759 data_offset = header->index_offset + count*sizeof(*index);
4760 global_offset = header->global_offset;
4762 for (i = 0; i < actctx->num_assemblies; i++)
4764 struct assembly *assembly = &actctx->assemblies[i];
4766 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4767 for (j = 0; j < assembly->num_dlls; j++)
4769 struct dll_redirect *dll = &assembly->dlls[j];
4770 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4774 *section = header;
4776 return STATUS_SUCCESS;
4779 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4781 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4784 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4785 PACTCTX_SECTION_KEYED_DATA data)
4787 struct progidredirect_data *progid;
4788 struct string_index *index;
4790 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4792 if (!actctx->comserver_section)
4794 struct guidsection_header *section;
4796 NTSTATUS status = build_comserver_section(actctx, &section);
4797 if (status) return status;
4799 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4800 RtlFreeHeap(GetProcessHeap(), 0, section);
4803 if (!actctx->progid_section)
4805 struct strsection_header *section;
4807 NTSTATUS status = build_progid_section(actctx, &section);
4808 if (status) return status;
4810 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4811 RtlFreeHeap(GetProcessHeap(), 0, section);
4814 index = find_string_index(actctx->progid_section, name);
4815 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4817 if (data)
4819 progid = get_progid_data(actctx, index);
4821 data->ulDataFormatVersion = 1;
4822 data->lpData = progid;
4823 data->ulLength = progid->size;
4824 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4825 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4826 data->lpSectionBase = actctx->progid_section;
4827 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4828 data->hActCtx = NULL;
4830 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4831 data->ulAssemblyRosterIndex = index->rosterindex;
4834 return STATUS_SUCCESS;
4837 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4838 const UNICODE_STRING *section_name,
4839 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4841 NTSTATUS status;
4843 switch (section_kind)
4845 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4846 status = find_dll_redirection(actctx, section_name, data);
4847 break;
4848 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4849 status = find_window_class(actctx, section_name, data);
4850 break;
4851 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4852 status = find_progid_redirection(actctx, section_name, data);
4853 break;
4854 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4855 FIXME("Unsupported yet section_kind %x\n", section_kind);
4856 return STATUS_SXS_SECTION_NOT_FOUND;
4857 default:
4858 WARN("Unknown section_kind %x\n", section_kind);
4859 return STATUS_SXS_SECTION_NOT_FOUND;
4862 if (status != STATUS_SUCCESS) return status;
4864 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4866 actctx_addref(actctx);
4867 data->hActCtx = actctx;
4869 return STATUS_SUCCESS;
4872 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4873 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4875 NTSTATUS status;
4877 switch (section_kind)
4879 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4880 status = find_tlib_redirection(actctx, guid, data);
4881 break;
4882 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4883 status = find_comserver_redirection(actctx, guid, data);
4884 break;
4885 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4886 status = find_cominterface_redirection(actctx, guid, data);
4887 break;
4888 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4889 status = find_clr_surrogate(actctx, guid, data);
4890 break;
4891 default:
4892 WARN("Unknown section_kind %x\n", section_kind);
4893 return STATUS_SXS_SECTION_NOT_FOUND;
4896 if (status != STATUS_SUCCESS) return status;
4898 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4900 actctx_addref(actctx);
4901 data->hActCtx = actctx;
4903 return STATUS_SUCCESS;
4906 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4908 unsigned int i, j;
4910 for (i = 0; i < actctx->num_assemblies; i++)
4912 struct assembly *assembly = &actctx->assemblies[i];
4913 for (j = 0; j < assembly->entities.num; j++)
4915 struct entity *entity = &assembly->entities.base[j];
4916 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4917 !strcmpW( entity->u.settings.name, settings ) &&
4918 !strcmpW( entity->u.settings.ns, ns ))
4919 return entity->u.settings.value;
4922 return NULL;
4925 /* initialize the activation context for the current process */
4926 void actctx_init(void)
4928 ACTCTXW ctx;
4929 HANDLE handle;
4931 ctx.cbSize = sizeof(ctx);
4932 ctx.lpSource = NULL;
4933 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4934 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4935 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4937 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4941 /***********************************************************************
4942 * RtlCreateActivationContext (NTDLL.@)
4944 * Create an activation context.
4946 * FIXME: function signature/prototype is wrong
4948 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4950 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4951 const WCHAR *directory = NULL;
4952 ACTIVATION_CONTEXT *actctx;
4953 UNICODE_STRING nameW;
4954 ULONG lang = 0;
4955 NTSTATUS status = STATUS_NO_MEMORY;
4956 HANDLE file = 0;
4957 struct actctx_loader acl;
4959 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4961 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4962 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4963 return STATUS_INVALID_PARAMETER;
4965 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4966 return STATUS_NO_MEMORY;
4968 actctx->magic = ACTCTX_MAGIC;
4969 actctx->ref_count = 1;
4970 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4971 actctx->config.info = NULL;
4972 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4973 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4975 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4977 else
4979 UNICODE_STRING dir;
4980 WCHAR *p;
4981 HMODULE module;
4983 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4984 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4986 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4987 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4988 actctx->appdir.info = dir.Buffer;
4991 nameW.Buffer = NULL;
4993 /* open file only if it's going to be used */
4994 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4995 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4997 WCHAR *source = NULL;
4998 BOOLEAN ret;
5000 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5001 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5003 DWORD dir_len, source_len;
5005 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
5006 source_len = strlenW(pActCtx->lpSource);
5007 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5009 status = STATUS_NO_MEMORY;
5010 goto error;
5013 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5014 source[dir_len] = '\\';
5015 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5018 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5019 RtlFreeHeap( GetProcessHeap(), 0, source );
5020 if (!ret)
5022 status = STATUS_NO_SUCH_FILE;
5023 goto error;
5025 status = open_nt_file( &file, &nameW );
5026 if (status)
5028 RtlFreeUnicodeString( &nameW );
5029 goto error;
5033 acl.actctx = actctx;
5034 acl.dependencies = NULL;
5035 acl.num_dependencies = 0;
5036 acl.allocated_dependencies = 0;
5038 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5039 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5041 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5043 /* if we have a resource it's a PE file */
5044 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5046 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5047 pActCtx->lpResourceName, lang );
5048 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5049 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5050 pActCtx->hModule, pActCtx->lpResourceName );
5052 else if (pActCtx->lpSource)
5054 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5055 file, pActCtx->lpResourceName, lang );
5056 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5057 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5058 NULL, pActCtx->lpResourceName );
5060 else status = STATUS_INVALID_PARAMETER;
5062 else
5064 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5067 if (file) NtClose( file );
5068 RtlFreeUnicodeString( &nameW );
5070 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5071 free_depend_manifests( &acl );
5073 if (status == STATUS_SUCCESS) *handle = actctx;
5074 else actctx_release( actctx );
5075 return status;
5077 error:
5078 if (file) NtClose( file );
5079 actctx_release( actctx );
5080 return status;
5084 /***********************************************************************
5085 * RtlAddRefActivationContext (NTDLL.@)
5087 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5089 ACTIVATION_CONTEXT *actctx;
5091 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5095 /******************************************************************
5096 * RtlReleaseActivationContext (NTDLL.@)
5098 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5100 ACTIVATION_CONTEXT *actctx;
5102 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5105 /******************************************************************
5106 * RtlZombifyActivationContext (NTDLL.@)
5108 * FIXME: function prototype might be wrong
5110 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5112 FIXME("%p: stub\n", handle);
5113 return STATUS_NOT_IMPLEMENTED;
5116 /******************************************************************
5117 * RtlActivateActivationContext (NTDLL.@)
5119 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5121 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5123 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5124 return STATUS_NO_MEMORY;
5126 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5127 frame->ActivationContext = handle;
5128 frame->Flags = 0;
5129 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5130 RtlAddRefActivationContext( handle );
5132 *cookie = (ULONG_PTR)frame;
5133 TRACE( "%p cookie=%lx\n", handle, *cookie );
5134 return STATUS_SUCCESS;
5138 /***********************************************************************
5139 * RtlDeactivateActivationContext (NTDLL.@)
5141 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5143 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5145 TRACE( "%x cookie=%lx\n", flags, cookie );
5147 /* find the right frame */
5148 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5149 for (frame = top; frame; frame = frame->Previous)
5150 if ((ULONG_PTR)frame == cookie) break;
5152 if (!frame)
5153 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5155 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5156 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5158 /* pop everything up to and including frame */
5159 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5161 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5163 frame = top->Previous;
5164 RtlReleaseActivationContext( top->ActivationContext );
5165 RtlFreeHeap( GetProcessHeap(), 0, top );
5166 top = frame;
5171 /******************************************************************
5172 * RtlFreeThreadActivationContextStack (NTDLL.@)
5174 void WINAPI RtlFreeThreadActivationContextStack(void)
5176 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5178 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5179 while (frame)
5181 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5182 RtlReleaseActivationContext( frame->ActivationContext );
5183 RtlFreeHeap( GetProcessHeap(), 0, frame );
5184 frame = prev;
5186 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5190 /******************************************************************
5191 * RtlGetActiveActivationContext (NTDLL.@)
5193 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5195 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5197 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5198 RtlAddRefActivationContext( *handle );
5200 else
5201 *handle = 0;
5203 return STATUS_SUCCESS;
5207 /******************************************************************
5208 * RtlIsActivationContextActive (NTDLL.@)
5210 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5212 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5214 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5215 if (frame->ActivationContext == handle) return TRUE;
5216 return FALSE;
5220 /***********************************************************************
5221 * RtlQueryInformationActivationContext (NTDLL.@)
5223 * Get information about an activation context.
5224 * FIXME: function signature/prototype may be wrong
5226 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5227 ULONG class, PVOID buffer,
5228 SIZE_T bufsize, SIZE_T *retlen )
5230 ACTIVATION_CONTEXT *actctx;
5231 NTSTATUS status;
5233 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5234 subinst, class, buffer, bufsize, retlen);
5236 if (retlen) *retlen = 0;
5237 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5239 switch (class)
5241 case ActivationContextBasicInformation:
5243 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5245 if (retlen) *retlen = sizeof(*info);
5246 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5248 info->hActCtx = handle;
5249 info->dwFlags = 0; /* FIXME */
5250 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5252 break;
5254 case ActivationContextDetailedInformation:
5256 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5257 struct assembly *assembly = NULL;
5258 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5259 LPWSTR ptr;
5261 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5263 if (actctx->num_assemblies) assembly = actctx->assemblies;
5265 if (assembly && assembly->manifest.info)
5266 manifest_len = strlenW(assembly->manifest.info) + 1;
5267 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5268 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5269 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5271 if (retlen) *retlen = len;
5272 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5274 acdi->dwFlags = 0;
5275 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5276 acdi->ulAssemblyCount = actctx->num_assemblies;
5277 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5278 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5279 acdi->ulRootConfigurationPathType = actctx->config.type;
5280 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5281 acdi->ulAppDirPathType = actctx->appdir.type;
5282 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5283 ptr = (LPWSTR)(acdi + 1);
5284 if (manifest_len)
5286 acdi->lpRootManifestPath = ptr;
5287 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5288 ptr += manifest_len;
5290 else acdi->lpRootManifestPath = NULL;
5291 if (config_len)
5293 acdi->lpRootConfigurationPath = ptr;
5294 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5295 ptr += config_len;
5297 else acdi->lpRootConfigurationPath = NULL;
5298 if (appdir_len)
5300 acdi->lpAppDirPath = ptr;
5301 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5303 else acdi->lpAppDirPath = NULL;
5305 break;
5307 case AssemblyDetailedInformationInActivationContext:
5309 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5310 struct assembly *assembly;
5311 WCHAR *assembly_id;
5312 DWORD index;
5313 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5314 LPWSTR ptr;
5316 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5317 if (!subinst) return STATUS_INVALID_PARAMETER;
5319 index = *(DWORD*)subinst;
5320 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5322 assembly = &actctx->assemblies[index - 1];
5324 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5325 id_len = strlenW(assembly_id) + 1;
5326 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5328 if (assembly->manifest.info &&
5329 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5330 path_len = strlenW(assembly->manifest.info) + 1;
5332 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5334 if (retlen) *retlen = len;
5335 if (!buffer || bufsize < len)
5337 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5338 return STATUS_BUFFER_TOO_SMALL;
5341 afdi->ulFlags = 0; /* FIXME */
5342 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5343 afdi->ulManifestPathType = assembly->manifest.type;
5344 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5345 /* FIXME afdi->liManifestLastWriteTime = 0; */
5346 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5347 afdi->ulPolicyPathLength = 0;
5348 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5349 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5350 afdi->ulManifestVersionMajor = 1;
5351 afdi->ulManifestVersionMinor = 0;
5352 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5353 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5354 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5355 ptr = (LPWSTR)(afdi + 1);
5356 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5357 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5358 ptr += id_len;
5359 if (path_len)
5361 afdi->lpAssemblyManifestPath = ptr;
5362 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5363 ptr += path_len;
5364 } else afdi->lpAssemblyManifestPath = NULL;
5365 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5366 if (ad_len)
5368 afdi->lpAssemblyDirectoryName = ptr;
5369 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5371 else afdi->lpAssemblyDirectoryName = NULL;
5372 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5374 break;
5376 case FileInformationInAssemblyOfAssemblyInActivationContext:
5378 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5379 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5380 struct assembly *assembly;
5381 struct dll_redirect *dll;
5382 SIZE_T len, dll_len = 0;
5383 LPWSTR ptr;
5385 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5386 if (!acqi) return STATUS_INVALID_PARAMETER;
5388 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5389 return STATUS_INVALID_PARAMETER;
5390 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5392 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5393 return STATUS_INVALID_PARAMETER;
5394 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5396 if (dll->name) dll_len = strlenW(dll->name) + 1;
5397 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5399 if (!buffer || bufsize < len)
5401 if (retlen) *retlen = len;
5402 return STATUS_BUFFER_TOO_SMALL;
5404 if (retlen) *retlen = 0; /* yes that's what native does !! */
5405 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5406 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5407 afdi->ulPathLength = 0; /* FIXME */
5408 ptr = (LPWSTR)(afdi + 1);
5409 if (dll_len)
5411 afdi->lpFileName = ptr;
5412 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5413 } else afdi->lpFileName = NULL;
5414 afdi->lpFilePath = NULL; /* FIXME */
5416 break;
5418 case CompatibilityInformationInActivationContext:
5420 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5421 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5422 struct assembly *assembly = NULL;
5423 ULONG num_compat_contexts = 0, n;
5424 SIZE_T len;
5426 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5428 if (actctx->num_assemblies) assembly = actctx->assemblies;
5430 if (assembly)
5431 num_compat_contexts = assembly->num_compat_contexts;
5432 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5434 if (retlen) *retlen = len;
5435 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5437 *acci = num_compat_contexts;
5438 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5439 for (n = 0; n < num_compat_contexts; ++n)
5441 elements[n] = assembly->compat_contexts[n];
5444 break;
5446 case RunlevelInformationInActivationContext:
5448 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5449 struct assembly *assembly;
5450 SIZE_T len;
5452 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5454 len = sizeof(*acrli);
5455 if (retlen) *retlen = len;
5456 if (!buffer || bufsize < len)
5457 return STATUS_BUFFER_TOO_SMALL;
5459 assembly = actctx->assemblies;
5461 acrli->ulFlags = 0;
5462 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5463 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5465 break;
5467 default:
5468 FIXME( "class %u not implemented\n", class );
5469 return STATUS_NOT_IMPLEMENTED;
5471 return STATUS_SUCCESS;
5474 /***********************************************************************
5475 * RtlFindActivationContextSectionString (NTDLL.@)
5477 * Find information about a string in an activation context.
5478 * FIXME: function signature/prototype may be wrong
5480 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5481 const UNICODE_STRING *section_name, PVOID ptr )
5483 PACTCTX_SECTION_KEYED_DATA data = ptr;
5484 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5486 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5487 debugstr_us(section_name), data);
5489 if (guid)
5491 FIXME("expected guid == NULL\n");
5492 return STATUS_INVALID_PARAMETER;
5494 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5496 FIXME("unknown flags %08x\n", flags);
5497 return STATUS_INVALID_PARAMETER;
5499 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5500 !section_name || !section_name->Buffer)
5502 WARN("invalid parameter\n");
5503 return STATUS_INVALID_PARAMETER;
5506 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5508 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5509 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5512 if (status != STATUS_SUCCESS)
5513 status = find_string( process_actctx, section_kind, section_name, flags, data );
5515 return status;
5518 /***********************************************************************
5519 * RtlFindActivationContextSectionGuid (NTDLL.@)
5521 * Find information about a GUID in an activation context.
5522 * FIXME: function signature/prototype may be wrong
5524 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5525 const GUID *guid, void *ptr )
5527 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5528 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5530 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5532 if (extguid)
5534 FIXME("expected extguid == NULL\n");
5535 return STATUS_INVALID_PARAMETER;
5538 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5540 FIXME("unknown flags %08x\n", flags);
5541 return STATUS_INVALID_PARAMETER;
5544 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5545 return STATUS_INVALID_PARAMETER;
5547 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5549 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5550 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5553 if (status != STATUS_SUCCESS)
5554 status = find_guid( process_actctx, section_kind, guid, flags, data );
5556 return status;
5560 /***********************************************************************
5561 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5563 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5564 const WCHAR *settings, WCHAR *buffer,
5565 SIZE_T size, SIZE_T *written )
5567 ACTIVATION_CONTEXT *actctx;
5568 const WCHAR *res;
5570 if (flags)
5572 WARN( "unknown flags %08x\n", flags );
5573 return STATUS_INVALID_PARAMETER;
5576 if (ns)
5578 if (strcmpW( ns, windowsSettings2005NSW ) &&
5579 strcmpW( ns, windowsSettings2011NSW ) &&
5580 strcmpW( ns, windowsSettings2016NSW ) &&
5581 strcmpW( ns, windowsSettings2017NSW ))
5582 return STATUS_INVALID_PARAMETER;
5584 else ns = windowsSettings2005NSW;
5586 if (!handle) handle = process_actctx;
5587 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5589 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5591 if (written) *written = strlenW(res) + 1;
5592 if (size < strlenW(res)) return STATUS_BUFFER_TOO_SMALL;
5593 strcpyW( buffer, res );
5594 return STATUS_SUCCESS;