ntoskrnl.exe: Implement ExAcquireFastMutex and ExReleaseFastMutex.
[wine.git] / dlls / ntdll / actctx.c
blob106fea80a3f8cc5663baf331bc1b7c78dd48d1bc
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 /* let's assume utf-8 for now */
2838 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2839 WCHAR *new_buff;
2841 if (len == -1)
2843 FIXME( "utf-8 conversion failed\n" );
2844 return STATUS_SXS_CANT_GEN_ACTCTX;
2846 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2847 return STATUS_NO_MEMORY;
2848 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2849 xmlbuf.ptr = new_buff;
2850 xmlbuf.end = xmlbuf.ptr + len;
2851 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2852 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2854 return status;
2857 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2859 OBJECT_ATTRIBUTES attr;
2860 IO_STATUS_BLOCK io;
2862 attr.Length = sizeof(attr);
2863 attr.RootDirectory = 0;
2864 attr.Attributes = OBJ_CASE_INSENSITIVE;
2865 attr.ObjectName = name;
2866 attr.SecurityDescriptor = NULL;
2867 attr.SecurityQualityOfService = NULL;
2868 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2871 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2873 NTSTATUS status;
2874 ULONG_PTR magic;
2875 LDR_MODULE *pldr;
2877 LdrLockLoaderLock(0, NULL, &magic);
2878 status = LdrFindEntryForAddress( module, &pldr );
2879 if (status == STATUS_SUCCESS)
2881 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2882 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2884 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2885 str->Length = pldr->FullDllName.Length;
2886 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2888 else status = STATUS_NO_MEMORY;
2890 LdrUnlockLoaderLock(0, magic);
2891 return status;
2894 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2895 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2896 HANDLE hModule, LPCWSTR resname, ULONG lang )
2898 NTSTATUS status;
2899 UNICODE_STRING nameW;
2900 LDR_RESOURCE_INFO info;
2901 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2902 void *ptr;
2904 if (TRACE_ON(actctx))
2906 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2908 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2909 hModule, debugstr_w(nameW.Buffer) );
2910 RtlFreeUnicodeString( &nameW );
2912 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2913 hModule, debugstr_w(filename) );
2916 if (!resname) return STATUS_INVALID_PARAMETER;
2918 info.Type = RT_MANIFEST;
2919 info.Language = lang;
2920 if (!((ULONG_PTR)resname >> 16))
2922 info.Name = (ULONG_PTR)resname;
2923 status = LdrFindResource_U(hModule, &info, 3, &entry);
2925 else if (resname[0] == '#')
2927 ULONG value;
2928 RtlInitUnicodeString(&nameW, resname + 1);
2929 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2930 return STATUS_INVALID_PARAMETER;
2931 info.Name = value;
2932 status = LdrFindResource_U(hModule, &info, 3, &entry);
2934 else
2936 RtlCreateUnicodeString(&nameW, resname);
2937 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2938 info.Name = (ULONG_PTR)nameW.Buffer;
2939 status = LdrFindResource_U(hModule, &info, 3, &entry);
2940 RtlFreeUnicodeString(&nameW);
2942 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2944 if (status == STATUS_SUCCESS)
2945 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2947 return status;
2950 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2951 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2952 HANDLE file, LPCWSTR resname, ULONG lang )
2954 HANDLE mapping;
2955 OBJECT_ATTRIBUTES attr;
2956 LARGE_INTEGER size;
2957 LARGE_INTEGER offset;
2958 NTSTATUS status;
2959 SIZE_T count;
2960 void *base;
2962 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2964 attr.Length = sizeof(attr);
2965 attr.RootDirectory = 0;
2966 attr.ObjectName = NULL;
2967 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2968 attr.SecurityDescriptor = NULL;
2969 attr.SecurityQualityOfService = NULL;
2971 size.QuadPart = 0;
2972 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2973 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2974 if (status != STATUS_SUCCESS) return status;
2976 offset.QuadPart = 0;
2977 count = 0;
2978 base = NULL;
2979 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2980 &count, ViewShare, 0, PAGE_READONLY );
2981 NtClose( mapping );
2982 if (status != STATUS_SUCCESS) return status;
2984 if (RtlImageNtHeader(base)) /* we got a PE file */
2986 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2987 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2989 else status = STATUS_INVALID_IMAGE_FORMAT;
2991 NtUnmapViewOfSection( GetCurrentProcess(), base );
2992 return status;
2995 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2996 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2998 FILE_END_OF_FILE_INFORMATION info;
2999 IO_STATUS_BLOCK io;
3000 HANDLE mapping;
3001 OBJECT_ATTRIBUTES attr;
3002 LARGE_INTEGER size;
3003 LARGE_INTEGER offset;
3004 NTSTATUS status;
3005 SIZE_T count;
3006 void *base;
3008 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3010 attr.Length = sizeof(attr);
3011 attr.RootDirectory = 0;
3012 attr.ObjectName = NULL;
3013 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3014 attr.SecurityDescriptor = NULL;
3015 attr.SecurityQualityOfService = NULL;
3017 size.QuadPart = 0;
3018 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3019 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3020 if (status != STATUS_SUCCESS) return status;
3022 offset.QuadPart = 0;
3023 count = 0;
3024 base = NULL;
3025 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3026 &count, ViewShare, 0, PAGE_READONLY );
3027 NtClose( mapping );
3028 if (status != STATUS_SUCCESS) return status;
3030 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3031 if (status == STATUS_SUCCESS)
3032 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
3034 NtUnmapViewOfSection( GetCurrentProcess(), base );
3035 return status;
3038 /* try to load the .manifest file associated to the file */
3039 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3040 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3042 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3043 WCHAR *buffer;
3044 NTSTATUS status;
3045 UNICODE_STRING nameW;
3046 HANDLE file;
3047 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3049 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3051 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3053 if (module) /* use the module filename */
3055 UNICODE_STRING name;
3057 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3059 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3060 strcatW( name.Buffer, dotManifestW );
3061 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3062 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3063 RtlFreeUnicodeString( &name );
3065 if (status) return status;
3067 else
3069 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3070 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3071 return STATUS_NO_MEMORY;
3072 strcpyW( buffer, filename );
3073 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3074 strcatW( buffer, dotManifestW );
3075 RtlInitUnicodeString( &nameW, buffer );
3078 if (!open_nt_file( &file, &nameW ))
3080 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3081 NtClose( file );
3083 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3084 RtlFreeUnicodeString( &nameW );
3085 return status;
3088 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3090 static const WCHAR lookup_fmtW[] =
3091 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3092 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3093 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3095 WCHAR *lookup, *ret = NULL;
3096 UNICODE_STRING lookup_us;
3097 IO_STATUS_BLOCK io;
3098 const WCHAR *lang = ai->language;
3099 unsigned int data_pos = 0, data_len;
3100 char buffer[8192];
3102 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3104 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3105 (strlenW(ai->arch) + strlenW(ai->name)
3106 + strlenW(ai->public_key) + strlenW(lang) + 20) * sizeof(WCHAR)
3107 + sizeof(lookup_fmtW) )))
3108 return NULL;
3109 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3110 ai->version.major, ai->version.minor, lang );
3111 RtlInitUnicodeString( &lookup_us, lookup );
3113 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3114 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3116 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3117 FILE_BOTH_DIR_INFORMATION *dir_info;
3118 WCHAR *tmp;
3119 ULONG build, revision;
3121 data_len = io.Information;
3123 for (;;)
3125 if (data_pos >= data_len)
3127 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3128 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3129 break;
3130 data_len = io.Information;
3131 data_pos = 0;
3133 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3135 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3136 else data_pos = data_len;
3138 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
3139 build = atoiW(tmp);
3140 if (build < min_build) continue;
3141 tmp = strchrW(tmp, '.') + 1;
3142 revision = atoiW(tmp);
3143 if (build == min_build && revision < min_revision) continue;
3144 tmp = strchrW(tmp, '_') + 1;
3145 tmp = strchrW(tmp, '_') + 1;
3146 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3147 !strncmpiW( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3149 /* prefer a non-Wine manifest if we already have one */
3150 /* we'll still load the builtin dll if specified through DllOverrides */
3151 if (ret) continue;
3153 else
3155 min_build = build;
3156 min_revision = revision;
3158 ai->version.build = build;
3159 ai->version.revision = revision;
3160 RtlFreeHeap( GetProcessHeap(), 0, ret );
3161 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3163 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3164 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3168 else WARN("no matching file for %s\n", debugstr_w(lookup));
3169 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3170 return ret;
3173 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3175 struct assembly_identity sxs_ai;
3176 UNICODE_STRING path_us;
3177 OBJECT_ATTRIBUTES attr;
3178 IO_STATUS_BLOCK io;
3179 WCHAR *path, *file = NULL;
3180 HANDLE handle;
3182 static const WCHAR manifest_dirW[] =
3183 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3185 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3187 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3188 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3189 return STATUS_NO_MEMORY;
3191 strcpyW( path, user_shared_data->NtSystemRoot );
3192 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3194 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3196 RtlFreeHeap( GetProcessHeap(), 0, path );
3197 return STATUS_NO_SUCH_FILE;
3199 RtlFreeHeap( GetProcessHeap(), 0, path );
3201 attr.Length = sizeof(attr);
3202 attr.RootDirectory = 0;
3203 attr.Attributes = OBJ_CASE_INSENSITIVE;
3204 attr.ObjectName = &path_us;
3205 attr.SecurityDescriptor = NULL;
3206 attr.SecurityQualityOfService = NULL;
3208 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3209 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3211 sxs_ai = *ai;
3212 file = lookup_manifest_file( handle, &sxs_ai );
3213 NtClose( handle );
3215 if (!file)
3217 RtlFreeUnicodeString( &path_us );
3218 return STATUS_NO_SUCH_FILE;
3221 /* append file name to directory path */
3222 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3223 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3225 RtlFreeHeap( GetProcessHeap(), 0, file );
3226 RtlFreeUnicodeString( &path_us );
3227 return STATUS_NO_MEMORY;
3230 path[path_us.Length/sizeof(WCHAR)] = '\\';
3231 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3232 RtlInitUnicodeString( &path_us, path );
3233 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3235 if (!open_nt_file( &handle, &path_us ))
3237 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3238 NtClose( handle );
3240 else io.u.Status = STATUS_NO_SUCH_FILE;
3242 RtlFreeHeap( GetProcessHeap(), 0, file );
3243 RtlFreeUnicodeString( &path_us );
3244 return io.u.Status;
3247 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3248 struct assembly_identity* ai)
3250 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3251 unsigned int i;
3252 WCHAR *buffer, *p, *directory;
3253 NTSTATUS status;
3254 UNICODE_STRING nameW;
3255 HANDLE file;
3256 DWORD len;
3258 TRACE( "looking for name=%s version=%s arch=%s\n",
3259 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3261 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3263 /* FIXME: add support for language specific lookup */
3265 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3266 strlenW(acl->actctx->appdir.info));
3268 nameW.Buffer = NULL;
3269 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3270 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3271 return STATUS_NO_MEMORY;
3273 if (!(directory = build_assembly_dir( ai )))
3275 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3276 return STATUS_NO_MEMORY;
3279 /* Lookup in <dir>\name.dll
3280 * <dir>\name.manifest
3281 * <dir>\name\name.dll
3282 * <dir>\name\name.manifest
3284 * First 'appdir' is used as <dir>, if that failed
3285 * it tries application manifest file path.
3287 strcpyW( buffer, acl->actctx->appdir.info );
3288 p = buffer + strlenW(buffer);
3289 for (i = 0; i < 4; i++)
3291 if (i == 2)
3293 struct assembly *assembly = acl->actctx->assemblies;
3294 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3296 else *p++ = '\\';
3298 strcpyW( p, ai->name );
3299 p += strlenW(p);
3301 strcpyW( p, dotDllW );
3302 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3304 status = open_nt_file( &file, &nameW );
3305 if (!status)
3307 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3308 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3309 NtClose( file );
3310 if (status == STATUS_SUCCESS)
3311 break;
3313 RtlFreeUnicodeString( &nameW );
3316 strcpyW( p, dotManifestW );
3317 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3319 status = open_nt_file( &file, &nameW );
3320 if (!status)
3322 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3323 NtClose( file );
3324 break;
3326 RtlFreeUnicodeString( &nameW );
3328 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3330 RtlFreeUnicodeString( &nameW );
3331 RtlFreeHeap( GetProcessHeap(), 0, directory );
3332 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3333 return status;
3336 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3338 NTSTATUS status = STATUS_SUCCESS;
3339 unsigned int i;
3341 for (i = 0; i < acl->num_dependencies; i++)
3343 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3345 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3347 FIXME( "Could not find dependent assembly %s (%s)\n",
3348 debugstr_w(acl->dependencies[i].name),
3349 debugstr_version(&acl->dependencies[i].version) );
3350 status = STATUS_SXS_CANT_GEN_ACTCTX;
3351 break;
3355 /* FIXME should now iterate through all refs */
3356 return status;
3359 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3360 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3362 NTSTATUS status = STATUS_SUCCESS;
3364 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3366 if (*handle) return STATUS_INVALID_PARAMETER;
3368 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3369 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3371 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3373 ULONG_PTR magic;
3374 LDR_MODULE *pldr;
3376 if (!*handle) return STATUS_INVALID_PARAMETER;
3378 LdrLockLoaderLock( 0, NULL, &magic );
3379 if (!LdrFindEntryForAddress( *handle, &pldr ))
3381 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3382 status = STATUS_DLL_NOT_FOUND;
3383 else
3384 *handle = pldr->ActivationContext;
3386 else status = STATUS_DLL_NOT_FOUND;
3387 LdrUnlockLoaderLock( 0, magic );
3389 else if (!*handle && (class != ActivationContextBasicInformation))
3390 *handle = process_actctx;
3392 return status;
3395 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3397 unsigned int i, j, total_len = 0, dll_count = 0;
3398 struct strsection_header *header;
3399 struct dllredirect_data *data;
3400 struct string_index *index;
3401 ULONG name_offset;
3403 /* compute section length */
3404 for (i = 0; i < actctx->num_assemblies; i++)
3406 struct assembly *assembly = &actctx->assemblies[i];
3407 for (j = 0; j < assembly->num_dlls; j++)
3409 struct dll_redirect *dll = &assembly->dlls[j];
3411 /* each entry needs index, data and string data */
3412 total_len += sizeof(*index);
3413 total_len += sizeof(*data);
3414 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3417 dll_count += assembly->num_dlls;
3420 total_len += sizeof(*header);
3422 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3423 if (!header) return STATUS_NO_MEMORY;
3425 memset(header, 0, sizeof(*header));
3426 header->magic = STRSECTION_MAGIC;
3427 header->size = sizeof(*header);
3428 header->count = dll_count;
3429 header->index_offset = sizeof(*header);
3430 index = (struct string_index*)((BYTE*)header + header->index_offset);
3431 name_offset = header->index_offset + header->count*sizeof(*index);
3433 for (i = 0; i < actctx->num_assemblies; i++)
3435 struct assembly *assembly = &actctx->assemblies[i];
3436 for (j = 0; j < assembly->num_dlls; j++)
3438 struct dll_redirect *dll = &assembly->dlls[j];
3439 UNICODE_STRING str;
3440 WCHAR *ptrW;
3442 /* setup new index entry */
3443 str.Buffer = dll->name;
3444 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3445 str.MaximumLength = str.Length + sizeof(WCHAR);
3446 /* hash original class name */
3447 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3449 index->name_offset = name_offset;
3450 index->name_len = str.Length;
3451 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3452 index->data_len = sizeof(*data);
3453 index->rosterindex = i + 1;
3455 /* setup data */
3456 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3457 data->size = sizeof(*data);
3458 data->unk = 2; /* FIXME: seems to be constant */
3459 memset(data->res, 0, sizeof(data->res));
3461 /* dll name */
3462 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3463 memcpy(ptrW, dll->name, index->name_len);
3464 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3466 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3468 index++;
3472 *section = header;
3474 return STATUS_SUCCESS;
3477 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3479 struct string_index *iter, *index = NULL;
3480 ULONG hash = 0, i;
3482 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3483 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3485 for (i = 0; i < section->count; i++)
3487 if (iter->hash == hash)
3489 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3491 if (!strcmpiW(nameW, name->Buffer))
3493 index = iter;
3494 break;
3496 else
3497 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3499 iter++;
3502 return index;
3505 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3507 struct guid_index *iter, *index = NULL;
3508 ULONG i;
3510 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3512 for (i = 0; i < section->count; i++)
3514 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3516 index = iter;
3517 break;
3519 iter++;
3522 return index;
3525 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3527 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3530 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3531 PACTCTX_SECTION_KEYED_DATA data)
3533 struct dllredirect_data *dll;
3534 struct string_index *index;
3536 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3538 if (!actctx->dllredirect_section)
3540 struct strsection_header *section;
3542 NTSTATUS status = build_dllredirect_section(actctx, &section);
3543 if (status) return status;
3545 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3546 RtlFreeHeap(GetProcessHeap(), 0, section);
3549 index = find_string_index(actctx->dllredirect_section, name);
3550 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3552 if (data)
3554 dll = get_dllredirect_data(actctx, index);
3556 data->ulDataFormatVersion = 1;
3557 data->lpData = dll;
3558 data->ulLength = dll->size;
3559 data->lpSectionGlobalData = NULL;
3560 data->ulSectionGlobalDataLength = 0;
3561 data->lpSectionBase = actctx->dllredirect_section;
3562 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3563 data->hActCtx = NULL;
3565 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3566 data->ulAssemblyRosterIndex = index->rosterindex;
3569 return STATUS_SUCCESS;
3572 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3574 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3577 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3579 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3582 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3584 unsigned int i, j, k, total_len = 0, class_count = 0;
3585 struct wndclass_redirect_data *data;
3586 struct strsection_header *header;
3587 struct string_index *index;
3588 ULONG name_offset;
3590 /* compute section length */
3591 for (i = 0; i < actctx->num_assemblies; i++)
3593 struct assembly *assembly = &actctx->assemblies[i];
3594 for (j = 0; j < assembly->num_dlls; j++)
3596 struct dll_redirect *dll = &assembly->dlls[j];
3597 for (k = 0; k < dll->entities.num; k++)
3599 struct entity *entity = &dll->entities.base[k];
3600 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3602 int class_len = strlenW(entity->u.class.name) + 1;
3603 int len;
3605 /* each class entry needs index, data and string data */
3606 total_len += sizeof(*index);
3607 total_len += sizeof(*data);
3608 /* original name is stored separately */
3609 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3610 /* versioned name and module name are stored one after another */
3611 if (entity->u.class.versioned)
3612 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3613 else
3614 len = class_len;
3615 len += strlenW(dll->name) + 1;
3616 total_len += aligned_string_len(len*sizeof(WCHAR));
3618 class_count++;
3624 total_len += sizeof(*header);
3626 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3627 if (!header) return STATUS_NO_MEMORY;
3629 memset(header, 0, sizeof(*header));
3630 header->magic = STRSECTION_MAGIC;
3631 header->size = sizeof(*header);
3632 header->count = class_count;
3633 header->index_offset = sizeof(*header);
3634 index = (struct string_index*)((BYTE*)header + header->index_offset);
3635 name_offset = header->index_offset + header->count*sizeof(*index);
3637 for (i = 0; i < actctx->num_assemblies; i++)
3639 struct assembly *assembly = &actctx->assemblies[i];
3640 for (j = 0; j < assembly->num_dlls; j++)
3642 struct dll_redirect *dll = &assembly->dlls[j];
3643 for (k = 0; k < dll->entities.num; k++)
3645 struct entity *entity = &dll->entities.base[k];
3646 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3648 static const WCHAR exclW[] = {'!',0};
3649 ULONG versioned_len, module_len;
3650 UNICODE_STRING str;
3651 WCHAR *ptrW;
3653 /* setup new index entry */
3654 str.Buffer = entity->u.class.name;
3655 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3656 str.MaximumLength = str.Length + sizeof(WCHAR);
3657 /* hash original class name */
3658 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3660 /* include '!' separator too */
3661 if (entity->u.class.versioned)
3662 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3663 else
3664 versioned_len = str.Length;
3665 module_len = strlenW(dll->name)*sizeof(WCHAR);
3667 index->name_offset = name_offset;
3668 index->name_len = str.Length;
3669 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3670 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3671 index->rosterindex = i + 1;
3673 /* setup data */
3674 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3675 data->size = sizeof(*data);
3676 data->res = 0;
3677 data->name_len = versioned_len;
3678 data->name_offset = sizeof(*data);
3679 data->module_len = module_len;
3680 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3682 /* original class name */
3683 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3684 memcpy(ptrW, entity->u.class.name, index->name_len);
3685 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3687 /* module name */
3688 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3689 memcpy(ptrW, dll->name, data->module_len);
3690 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3692 /* versioned name */
3693 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3694 if (entity->u.class.versioned)
3696 get_assembly_version(assembly, ptrW);
3697 strcatW(ptrW, exclW);
3698 strcatW(ptrW, entity->u.class.name);
3700 else
3702 memcpy(ptrW, entity->u.class.name, index->name_len);
3703 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3706 name_offset += sizeof(*data);
3707 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3709 index++;
3715 *section = header;
3717 return STATUS_SUCCESS;
3720 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3721 PACTCTX_SECTION_KEYED_DATA data)
3723 struct string_index *iter, *index = NULL;
3724 struct wndclass_redirect_data *class;
3725 ULONG hash;
3726 int i;
3728 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3730 if (!actctx->wndclass_section)
3732 struct strsection_header *section;
3734 NTSTATUS status = build_wndclass_section(actctx, &section);
3735 if (status) return status;
3737 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3738 RtlFreeHeap(GetProcessHeap(), 0, section);
3741 hash = 0;
3742 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3743 iter = get_wndclass_first_index(actctx);
3745 for (i = 0; i < actctx->wndclass_section->count; i++)
3747 if (iter->hash == hash)
3749 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3751 if (!strcmpiW(nameW, name->Buffer))
3753 index = iter;
3754 break;
3756 else
3757 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3759 iter++;
3762 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3764 if (data)
3766 class = get_wndclass_data(actctx, index);
3768 data->ulDataFormatVersion = 1;
3769 data->lpData = class;
3770 /* full length includes string length with nulls */
3771 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3772 data->lpSectionGlobalData = NULL;
3773 data->ulSectionGlobalDataLength = 0;
3774 data->lpSectionBase = actctx->wndclass_section;
3775 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3776 data->hActCtx = NULL;
3778 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3779 data->ulAssemblyRosterIndex = index->rosterindex;
3782 return STATUS_SUCCESS;
3785 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3787 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3788 struct guidsection_header *header;
3789 ULONG module_offset, data_offset;
3790 struct tlibredirect_data *data;
3791 struct guid_index *index;
3793 /* compute section length */
3794 for (i = 0; i < actctx->num_assemblies; i++)
3796 struct assembly *assembly = &actctx->assemblies[i];
3797 for (j = 0; j < assembly->num_dlls; j++)
3799 struct dll_redirect *dll = &assembly->dlls[j];
3800 for (k = 0; k < dll->entities.num; k++)
3802 struct entity *entity = &dll->entities.base[k];
3803 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3805 /* each entry needs index, data and string data for module name and help string */
3806 total_len += sizeof(*index);
3807 total_len += sizeof(*data);
3808 /* help string is stored separately */
3809 if (*entity->u.typelib.helpdir)
3810 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3812 /* module names are packed one after another */
3813 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3815 tlib_count++;
3821 total_len += aligned_string_len(names_len);
3822 total_len += sizeof(*header);
3824 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3825 if (!header) return STATUS_NO_MEMORY;
3827 memset(header, 0, sizeof(*header));
3828 header->magic = GUIDSECTION_MAGIC;
3829 header->size = sizeof(*header);
3830 header->count = tlib_count;
3831 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3832 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3833 module_offset = sizeof(*header);
3834 data_offset = header->index_offset + tlib_count*sizeof(*index);
3836 for (i = 0; i < actctx->num_assemblies; i++)
3838 struct assembly *assembly = &actctx->assemblies[i];
3839 for (j = 0; j < assembly->num_dlls; j++)
3841 struct dll_redirect *dll = &assembly->dlls[j];
3842 for (k = 0; k < dll->entities.num; k++)
3844 struct entity *entity = &dll->entities.base[k];
3845 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3847 ULONG module_len, help_len;
3848 UNICODE_STRING str;
3849 WCHAR *ptrW;
3851 if (*entity->u.typelib.helpdir)
3852 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3853 else
3854 help_len = 0;
3856 module_len = strlenW(dll->name)*sizeof(WCHAR);
3858 /* setup new index entry */
3859 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3860 RtlGUIDFromString(&str, &index->guid);
3861 index->data_offset = data_offset;
3862 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3863 index->rosterindex = i + 1;
3865 /* setup data */
3866 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3867 data->size = sizeof(*data);
3868 data->res = 0;
3869 data->name_len = module_len;
3870 data->name_offset = module_offset;
3871 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3872 data->langid = 0;
3873 data->flags = entity->u.typelib.flags;
3874 data->help_len = help_len;
3875 data->help_offset = sizeof(*data);
3876 data->major_version = entity->u.typelib.major;
3877 data->minor_version = entity->u.typelib.minor;
3879 /* module name */
3880 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3881 memcpy(ptrW, dll->name, data->name_len);
3882 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3884 /* help string */
3885 if (data->help_len)
3887 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3888 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3889 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3892 data_offset += sizeof(*data);
3893 if (help_len)
3894 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3896 module_offset += module_len + sizeof(WCHAR);
3898 index++;
3904 *section = header;
3906 return STATUS_SUCCESS;
3909 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3911 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3914 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3916 struct guid_index *index = NULL;
3917 struct tlibredirect_data *tlib;
3919 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3921 if (!actctx->tlib_section)
3923 struct guidsection_header *section;
3925 NTSTATUS status = build_tlib_section(actctx, &section);
3926 if (status) return status;
3928 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3929 RtlFreeHeap(GetProcessHeap(), 0, section);
3932 index = find_guid_index(actctx->tlib_section, guid);
3933 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3935 tlib = get_tlib_data(actctx, index);
3937 data->ulDataFormatVersion = 1;
3938 data->lpData = tlib;
3939 /* full length includes string length with nulls */
3940 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3941 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3942 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3943 data->lpSectionBase = actctx->tlib_section;
3944 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3945 data->hActCtx = NULL;
3947 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3948 data->ulAssemblyRosterIndex = index->rosterindex;
3950 return STATUS_SUCCESS;
3953 static void generate_uuid(ULONG *seed, GUID *guid)
3955 ULONG *ptr = (ULONG*)guid;
3956 int i;
3958 /* GUID is 16 bytes long */
3959 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3960 *ptr = RtlUniform(seed);
3962 guid->Data3 &= 0x0fff;
3963 guid->Data3 |= (4 << 12);
3964 guid->Data4[0] &= 0x3f;
3965 guid->Data4[0] |= 0x80;
3968 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3969 unsigned int *count, unsigned int *len, unsigned int *module_len)
3971 unsigned int i;
3973 for (i = 0; i < entities->num; i++)
3975 struct entity *entity = &entities->base[i];
3976 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3978 /* each entry needs two index entries, extra one goes for alias GUID */
3979 *len += 2*sizeof(struct guid_index);
3980 /* To save some memory we don't allocated two data structures,
3981 instead alias index and normal index point to the same data structure. */
3982 *len += sizeof(struct comclassredirect_data);
3984 /* for clrClass store some more */
3985 if (entity->u.comclass.name)
3987 unsigned int str_len;
3989 /* all string data is stored together in aligned block */
3990 str_len = strlenW(entity->u.comclass.name)+1;
3991 if (entity->u.comclass.progid)
3992 str_len += strlenW(entity->u.comclass.progid)+1;
3993 if (entity->u.comclass.version)
3994 str_len += strlenW(entity->u.comclass.version)+1;
3996 *len += sizeof(struct clrclass_data);
3997 *len += aligned_string_len(str_len*sizeof(WCHAR));
3999 /* module name is forced to mscoree.dll, and stored two times with different case */
4000 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4002 else
4004 /* progid string is stored separately */
4005 if (entity->u.comclass.progid)
4006 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4008 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
4011 *count += 1;
4016 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4017 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4018 ULONG *seed, ULONG rosterindex)
4020 unsigned int i;
4022 for (i = 0; i < entities->num; i++)
4024 struct entity *entity = &entities->base[i];
4025 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4027 ULONG module_len, progid_len, str_len = 0;
4028 struct comclassredirect_data *data;
4029 struct guid_index *alias_index;
4030 struct clrclass_data *clrdata;
4031 UNICODE_STRING str;
4032 WCHAR *ptrW;
4034 if (entity->u.comclass.progid)
4035 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4036 else
4037 progid_len = 0;
4039 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4041 /* setup new index entry */
4042 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4043 RtlGUIDFromString(&str, &(*index)->guid);
4045 (*index)->data_offset = *data_offset;
4046 (*index)->data_len = sizeof(*data); /* additional length added later */
4047 (*index)->rosterindex = rosterindex;
4049 /* Setup new index entry for alias guid. Alias index records are placed after
4050 normal records, so normal guids are hit first on search. Note that class count
4051 is doubled. */
4052 alias_index = (*index) + section->count/2;
4053 generate_uuid(seed, &alias_index->guid);
4054 alias_index->data_offset = (*index)->data_offset;
4055 alias_index->data_len = 0;
4056 alias_index->rosterindex = (*index)->rosterindex;
4058 /* setup data */
4059 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4060 data->size = sizeof(*data);
4061 data->res = 0;
4062 data->res1[0] = 0;
4063 data->res1[1] = 0;
4064 data->model = entity->u.comclass.model;
4065 data->clsid = (*index)->guid;
4066 data->alias = alias_index->guid;
4067 data->clsid2 = data->clsid;
4068 if (entity->u.comclass.tlbid)
4070 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4071 RtlGUIDFromString(&str, &data->tlbid);
4073 else
4074 memset(&data->tlbid, 0, sizeof(data->tlbid));
4075 data->name_len = module_len;
4076 data->name_offset = *module_offset;
4077 data->progid_len = progid_len;
4078 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4079 data->clrdata_len = 0; /* will be set later */
4080 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4081 data->miscstatus = entity->u.comclass.miscstatus;
4082 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4083 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4084 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4085 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4087 /* mask describes which misc* data is available */
4088 data->miscmask = 0;
4089 if (data->miscstatus)
4090 data->miscmask |= MiscStatus;
4091 if (data->miscstatuscontent)
4092 data->miscmask |= MiscStatusContent;
4093 if (data->miscstatusthumbnail)
4094 data->miscmask |= MiscStatusThumbnail;
4095 if (data->miscstatusicon)
4096 data->miscmask |= MiscStatusIcon;
4097 if (data->miscstatusdocprint)
4098 data->miscmask |= MiscStatusDocPrint;
4100 if (data->clrdata_offset)
4102 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4104 clrdata->size = sizeof(*clrdata);
4105 clrdata->res[0] = 0;
4106 clrdata->res[1] = 2; /* FIXME: unknown field */
4107 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4108 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4109 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4110 clrdata->name_offset = clrdata->size;
4111 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4112 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4113 clrdata->res2[0] = 0;
4114 clrdata->res2[1] = 0;
4116 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4118 /* module name */
4119 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4120 memcpy(ptrW, mscoree2W, clrdata->module_len);
4121 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4123 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4124 memcpy(ptrW, mscoreeW, data->name_len);
4125 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4127 /* class name */
4128 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4129 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4130 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4132 /* runtime version, optional */
4133 if (clrdata->version_len)
4135 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4137 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4138 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4139 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4142 if (data->progid_len)
4143 data->progid_offset += data->clrdata_len;
4144 (*index)->data_len += sizeof(*clrdata);
4146 else
4148 clrdata = NULL;
4150 /* module name */
4151 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4152 memcpy(ptrW, dll->name, data->name_len);
4153 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4156 /* progid string */
4157 if (data->progid_len)
4159 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4160 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4161 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4164 /* string block length */
4165 str_len = 0;
4166 if (clrdata)
4168 str_len += clrdata->name_len + sizeof(WCHAR);
4169 if (clrdata->version_len)
4170 str_len += clrdata->version_len + sizeof(WCHAR);
4172 if (progid_len)
4173 str_len += progid_len + sizeof(WCHAR);
4175 (*index)->data_len += aligned_string_len(str_len);
4176 alias_index->data_len = (*index)->data_len;
4178 /* move to next data record */
4179 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4180 (*module_offset) += module_len + sizeof(WCHAR);
4182 if (clrdata)
4184 (*data_offset) += sizeof(*clrdata);
4185 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4187 (*index) += 1;
4192 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4194 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4195 struct guidsection_header *header;
4196 ULONG module_offset, data_offset;
4197 struct guid_index *index;
4198 ULONG seed;
4200 /* compute section length */
4201 for (i = 0; i < actctx->num_assemblies; i++)
4203 struct assembly *assembly = &actctx->assemblies[i];
4204 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4205 for (j = 0; j < assembly->num_dlls; j++)
4207 struct dll_redirect *dll = &assembly->dlls[j];
4208 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4212 total_len += aligned_string_len(names_len);
4213 total_len += sizeof(*header);
4215 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4216 if (!header) return STATUS_NO_MEMORY;
4218 memset(header, 0, sizeof(*header));
4219 header->magic = GUIDSECTION_MAGIC;
4220 header->size = sizeof(*header);
4221 header->count = 2*class_count;
4222 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4223 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4224 module_offset = sizeof(*header);
4225 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4227 seed = NtGetTickCount();
4228 for (i = 0; i < actctx->num_assemblies; i++)
4230 struct assembly *assembly = &actctx->assemblies[i];
4231 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4232 for (j = 0; j < assembly->num_dlls; j++)
4234 struct dll_redirect *dll = &assembly->dlls[j];
4235 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4239 *section = header;
4241 return STATUS_SUCCESS;
4244 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4246 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4249 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4251 struct comclassredirect_data *comclass;
4252 struct guid_index *index = NULL;
4254 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4256 if (!actctx->comserver_section)
4258 struct guidsection_header *section;
4260 NTSTATUS status = build_comserver_section(actctx, &section);
4261 if (status) return status;
4263 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4264 RtlFreeHeap(GetProcessHeap(), 0, section);
4267 index = find_guid_index(actctx->comserver_section, guid);
4268 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4270 comclass = get_comclass_data(actctx, index);
4272 data->ulDataFormatVersion = 1;
4273 data->lpData = comclass;
4274 /* full length includes string length with nulls */
4275 data->ulLength = comclass->size + comclass->clrdata_len;
4276 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4277 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4278 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4279 data->lpSectionBase = actctx->comserver_section;
4280 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4281 data->hActCtx = NULL;
4283 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4284 data->ulAssemblyRosterIndex = index->rosterindex;
4286 return STATUS_SUCCESS;
4289 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4291 unsigned int i;
4293 for (i = 0; i < entities->num; i++)
4295 struct entity *entity = &entities->base[i];
4296 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4298 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4299 if (entity->u.ifaceps.name)
4300 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4301 *count += 1;
4306 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4307 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4309 unsigned int i;
4311 for (i = 0; i < entities->num; i++)
4313 struct entity *entity = &entities->base[i];
4314 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4316 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4317 UNICODE_STRING str;
4318 ULONG name_len;
4320 if (entity->u.ifaceps.name)
4321 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4322 else
4323 name_len = 0;
4325 /* setup index */
4326 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4327 RtlGUIDFromString(&str, &(*index)->guid);
4328 (*index)->data_offset = *data_offset;
4329 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4330 (*index)->rosterindex = rosterindex;
4332 /* setup data record */
4333 data->size = sizeof(*data);
4334 data->mask = entity->u.ifaceps.mask;
4336 /* proxyStubClsid32 value is only stored for external PS,
4337 if set it's used as iid, otherwise 'iid' attribute value is used */
4338 if (entity->u.ifaceps.ps32)
4340 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4341 RtlGUIDFromString(&str, &data->iid);
4343 else
4344 data->iid = (*index)->guid;
4346 data->nummethods = entity->u.ifaceps.nummethods;
4348 if (entity->u.ifaceps.tlib)
4350 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4351 RtlGUIDFromString(&str, &data->tlbid);
4353 else
4354 memset(&data->tlbid, 0, sizeof(data->tlbid));
4356 if (entity->u.ifaceps.base)
4358 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4359 RtlGUIDFromString(&str, &data->base);
4361 else
4362 memset(&data->base, 0, sizeof(data->base));
4364 data->name_len = name_len;
4365 data->name_offset = data->name_len ? sizeof(*data) : 0;
4367 /* name string */
4368 if (data->name_len)
4370 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4371 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4372 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4375 /* move to next record */
4376 (*index) += 1;
4377 *data_offset += sizeof(*data);
4378 if (data->name_len)
4379 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4384 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4386 unsigned int i, j, total_len = 0, count = 0;
4387 struct guidsection_header *header;
4388 struct guid_index *index;
4389 ULONG data_offset;
4391 /* compute section length */
4392 for (i = 0; i < actctx->num_assemblies; i++)
4394 struct assembly *assembly = &actctx->assemblies[i];
4396 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4397 for (j = 0; j < assembly->num_dlls; j++)
4399 struct dll_redirect *dll = &assembly->dlls[j];
4400 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4404 total_len += sizeof(*header);
4406 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4407 if (!header) return STATUS_NO_MEMORY;
4409 memset(header, 0, sizeof(*header));
4410 header->magic = GUIDSECTION_MAGIC;
4411 header->size = sizeof(*header);
4412 header->count = count;
4413 header->index_offset = sizeof(*header);
4414 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4415 data_offset = header->index_offset + count*sizeof(*index);
4417 for (i = 0; i < actctx->num_assemblies; i++)
4419 struct assembly *assembly = &actctx->assemblies[i];
4421 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4422 for (j = 0; j < assembly->num_dlls; j++)
4424 struct dll_redirect *dll = &assembly->dlls[j];
4425 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4429 *section = header;
4431 return STATUS_SUCCESS;
4434 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4436 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4439 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4441 struct ifacepsredirect_data *iface;
4442 struct guid_index *index = NULL;
4444 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4446 if (!actctx->ifaceps_section)
4448 struct guidsection_header *section;
4450 NTSTATUS status = build_ifaceps_section(actctx, &section);
4451 if (status) return status;
4453 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4454 RtlFreeHeap(GetProcessHeap(), 0, section);
4457 index = find_guid_index(actctx->ifaceps_section, guid);
4458 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4460 iface = get_ifaceps_data(actctx, index);
4462 data->ulDataFormatVersion = 1;
4463 data->lpData = iface;
4464 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4465 data->lpSectionGlobalData = NULL;
4466 data->ulSectionGlobalDataLength = 0;
4467 data->lpSectionBase = actctx->ifaceps_section;
4468 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4469 data->hActCtx = NULL;
4471 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4472 data->ulAssemblyRosterIndex = index->rosterindex;
4474 return STATUS_SUCCESS;
4477 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4479 unsigned int i, j, total_len = 0, count = 0;
4480 struct guidsection_header *header;
4481 struct clrsurrogate_data *data;
4482 struct guid_index *index;
4483 ULONG data_offset;
4485 /* compute section length */
4486 for (i = 0; i < actctx->num_assemblies; i++)
4488 struct assembly *assembly = &actctx->assemblies[i];
4489 for (j = 0; j < assembly->entities.num; j++)
4491 struct entity *entity = &assembly->entities.base[j];
4492 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4494 ULONG len;
4496 total_len += sizeof(*index) + sizeof(*data);
4497 len = strlenW(entity->u.clrsurrogate.name) + 1;
4498 if (entity->u.clrsurrogate.version)
4499 len += strlenW(entity->u.clrsurrogate.version) + 1;
4500 total_len += aligned_string_len(len*sizeof(WCHAR));
4502 count++;
4507 total_len += sizeof(*header);
4509 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4510 if (!header) return STATUS_NO_MEMORY;
4512 memset(header, 0, sizeof(*header));
4513 header->magic = GUIDSECTION_MAGIC;
4514 header->size = sizeof(*header);
4515 header->count = count;
4516 header->index_offset = sizeof(*header);
4517 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4518 data_offset = header->index_offset + count*sizeof(*index);
4520 for (i = 0; i < actctx->num_assemblies; i++)
4522 struct assembly *assembly = &actctx->assemblies[i];
4523 for (j = 0; j < assembly->entities.num; j++)
4525 struct entity *entity = &assembly->entities.base[j];
4526 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4528 ULONG version_len, name_len;
4529 UNICODE_STRING str;
4530 WCHAR *ptrW;
4532 if (entity->u.clrsurrogate.version)
4533 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4534 else
4535 version_len = 0;
4536 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4538 /* setup new index entry */
4539 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4540 RtlGUIDFromString(&str, &index->guid);
4542 index->data_offset = data_offset;
4543 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4544 index->rosterindex = i + 1;
4546 /* setup data */
4547 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4548 data->size = sizeof(*data);
4549 data->res = 0;
4550 data->clsid = index->guid;
4551 data->version_offset = version_len ? data->size : 0;
4552 data->version_len = version_len;
4553 data->name_offset = data->size + version_len;
4554 if (version_len)
4555 data->name_offset += sizeof(WCHAR);
4556 data->name_len = name_len;
4558 /* surrogate name */
4559 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4560 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4561 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4563 /* runtime version */
4564 if (data->version_len)
4566 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4567 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4568 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4571 data_offset += index->data_offset;
4572 index++;
4577 *section = header;
4579 return STATUS_SUCCESS;
4582 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4584 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4587 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4589 struct clrsurrogate_data *surrogate;
4590 struct guid_index *index = NULL;
4592 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4594 if (!actctx->clrsurrogate_section)
4596 struct guidsection_header *section;
4598 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4599 if (status) return status;
4601 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4602 RtlFreeHeap(GetProcessHeap(), 0, section);
4605 index = find_guid_index(actctx->clrsurrogate_section, guid);
4606 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4608 surrogate = get_surrogate_data(actctx, index);
4610 data->ulDataFormatVersion = 1;
4611 data->lpData = surrogate;
4612 /* full length includes string length with nulls */
4613 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4614 if (surrogate->version_len)
4615 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4617 data->lpSectionGlobalData = NULL;
4618 data->ulSectionGlobalDataLength = 0;
4619 data->lpSectionBase = actctx->clrsurrogate_section;
4620 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4621 data->hActCtx = NULL;
4623 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4624 data->ulAssemblyRosterIndex = index->rosterindex;
4626 return STATUS_SUCCESS;
4629 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4631 unsigned int i, j, single_len;
4633 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4634 for (i = 0; i < entities->num; i++)
4636 struct entity *entity = &entities->base[i];
4637 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4639 if (entity->u.comclass.progid)
4641 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4642 *count += 1;
4645 for (j = 0; j < entity->u.comclass.progids.num; j++)
4646 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4648 *total_len += single_len*entity->u.comclass.progids.num;
4649 *count += entity->u.comclass.progids.num;
4654 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4655 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4657 struct progidredirect_data *data;
4658 UNICODE_STRING str;
4659 GUID *guid_ptr;
4660 WCHAR *ptrW;
4662 /* setup new index entry */
4664 /* hash progid name */
4665 RtlInitUnicodeString(&str, progid);
4666 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4668 (*index)->name_offset = *data_offset;
4669 (*index)->name_len = str.Length;
4670 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4671 (*index)->data_len = sizeof(*data);
4672 (*index)->rosterindex = rosterindex;
4674 *data_offset += aligned_string_len(str.MaximumLength);
4676 /* setup data structure */
4677 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4678 data->size = sizeof(*data);
4679 data->reserved = 0;
4680 data->clsid_offset = *global_offset;
4682 /* write progid string */
4683 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4684 memcpy(ptrW, progid, (*index)->name_len);
4685 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4687 /* write guid to global area */
4688 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4689 *guid_ptr = *alias;
4691 /* to next entry */
4692 *global_offset += sizeof(GUID);
4693 *data_offset += data->size;
4694 (*index) += 1;
4697 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4698 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4700 unsigned int i, j;
4702 for (i = 0; i < entities->num; i++)
4704 struct entity *entity = &entities->base[i];
4705 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4707 const struct progids *progids = &entity->u.comclass.progids;
4708 struct comclassredirect_data *comclass;
4709 struct guid_index *guid_index;
4710 UNICODE_STRING str;
4711 GUID clsid;
4713 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4714 RtlGUIDFromString(&str, &clsid);
4716 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4717 comclass = get_comclass_data(actctx, guid_index);
4719 if (entity->u.comclass.progid)
4720 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4721 index, data_offset, global_offset, rosterindex);
4723 for (j = 0; j < progids->num; j++)
4724 write_progid_record(section, progids->progids[j], &comclass->alias,
4725 index, data_offset, global_offset, rosterindex);
4730 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4732 unsigned int i, j, total_len = 0, count = 0;
4733 struct strsection_header *header;
4734 ULONG data_offset, global_offset;
4735 struct string_index *index;
4737 /* compute section length */
4738 for (i = 0; i < actctx->num_assemblies; i++)
4740 struct assembly *assembly = &actctx->assemblies[i];
4742 get_progid_datalen(&assembly->entities, &count, &total_len);
4743 for (j = 0; j < assembly->num_dlls; j++)
4745 struct dll_redirect *dll = &assembly->dlls[j];
4746 get_progid_datalen(&dll->entities, &count, &total_len);
4750 total_len += sizeof(*header);
4752 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4753 if (!header) return STATUS_NO_MEMORY;
4755 memset(header, 0, sizeof(*header));
4756 header->magic = STRSECTION_MAGIC;
4757 header->size = sizeof(*header);
4758 header->count = count;
4759 header->global_offset = header->size;
4760 header->global_len = count*sizeof(GUID);
4761 header->index_offset = header->size + header->global_len;
4763 index = (struct string_index*)((BYTE*)header + header->index_offset);
4764 data_offset = header->index_offset + count*sizeof(*index);
4765 global_offset = header->global_offset;
4767 for (i = 0; i < actctx->num_assemblies; i++)
4769 struct assembly *assembly = &actctx->assemblies[i];
4771 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4772 for (j = 0; j < assembly->num_dlls; j++)
4774 struct dll_redirect *dll = &assembly->dlls[j];
4775 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4779 *section = header;
4781 return STATUS_SUCCESS;
4784 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4786 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4789 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4790 PACTCTX_SECTION_KEYED_DATA data)
4792 struct progidredirect_data *progid;
4793 struct string_index *index;
4795 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4797 if (!actctx->comserver_section)
4799 struct guidsection_header *section;
4801 NTSTATUS status = build_comserver_section(actctx, &section);
4802 if (status) return status;
4804 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4805 RtlFreeHeap(GetProcessHeap(), 0, section);
4808 if (!actctx->progid_section)
4810 struct strsection_header *section;
4812 NTSTATUS status = build_progid_section(actctx, &section);
4813 if (status) return status;
4815 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4816 RtlFreeHeap(GetProcessHeap(), 0, section);
4819 index = find_string_index(actctx->progid_section, name);
4820 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4822 if (data)
4824 progid = get_progid_data(actctx, index);
4826 data->ulDataFormatVersion = 1;
4827 data->lpData = progid;
4828 data->ulLength = progid->size;
4829 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4830 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4831 data->lpSectionBase = actctx->progid_section;
4832 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4833 data->hActCtx = NULL;
4835 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4836 data->ulAssemblyRosterIndex = index->rosterindex;
4839 return STATUS_SUCCESS;
4842 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4843 const UNICODE_STRING *section_name,
4844 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4846 NTSTATUS status;
4848 switch (section_kind)
4850 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4851 status = find_dll_redirection(actctx, section_name, data);
4852 break;
4853 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4854 status = find_window_class(actctx, section_name, data);
4855 break;
4856 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4857 status = find_progid_redirection(actctx, section_name, data);
4858 break;
4859 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4860 FIXME("Unsupported yet section_kind %x\n", section_kind);
4861 return STATUS_SXS_SECTION_NOT_FOUND;
4862 default:
4863 WARN("Unknown section_kind %x\n", section_kind);
4864 return STATUS_SXS_SECTION_NOT_FOUND;
4867 if (status != STATUS_SUCCESS) return status;
4869 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4871 actctx_addref(actctx);
4872 data->hActCtx = actctx;
4874 return STATUS_SUCCESS;
4877 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4878 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4880 NTSTATUS status;
4882 switch (section_kind)
4884 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4885 status = find_tlib_redirection(actctx, guid, data);
4886 break;
4887 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4888 status = find_comserver_redirection(actctx, guid, data);
4889 break;
4890 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4891 status = find_cominterface_redirection(actctx, guid, data);
4892 break;
4893 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4894 status = find_clr_surrogate(actctx, guid, data);
4895 break;
4896 default:
4897 WARN("Unknown section_kind %x\n", section_kind);
4898 return STATUS_SXS_SECTION_NOT_FOUND;
4901 if (status != STATUS_SUCCESS) return status;
4903 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4905 actctx_addref(actctx);
4906 data->hActCtx = actctx;
4908 return STATUS_SUCCESS;
4911 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4913 unsigned int i, j;
4915 for (i = 0; i < actctx->num_assemblies; i++)
4917 struct assembly *assembly = &actctx->assemblies[i];
4918 for (j = 0; j < assembly->entities.num; j++)
4920 struct entity *entity = &assembly->entities.base[j];
4921 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4922 !strcmpW( entity->u.settings.name, settings ) &&
4923 !strcmpW( entity->u.settings.ns, ns ))
4924 return entity->u.settings.value;
4927 return NULL;
4930 /* initialize the activation context for the current process */
4931 void actctx_init(void)
4933 ACTCTXW ctx;
4934 HANDLE handle;
4936 ctx.cbSize = sizeof(ctx);
4937 ctx.lpSource = NULL;
4938 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4939 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4940 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4942 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4946 /***********************************************************************
4947 * RtlCreateActivationContext (NTDLL.@)
4949 * Create an activation context.
4951 * FIXME: function signature/prototype is wrong
4953 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4955 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4956 const WCHAR *directory = NULL;
4957 ACTIVATION_CONTEXT *actctx;
4958 UNICODE_STRING nameW;
4959 ULONG lang = 0;
4960 NTSTATUS status = STATUS_NO_MEMORY;
4961 HANDLE file = 0;
4962 struct actctx_loader acl;
4964 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4966 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4967 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4968 return STATUS_INVALID_PARAMETER;
4970 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4971 return STATUS_NO_MEMORY;
4973 actctx->magic = ACTCTX_MAGIC;
4974 actctx->ref_count = 1;
4975 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4976 actctx->config.info = NULL;
4977 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4978 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4980 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4982 else
4984 UNICODE_STRING dir;
4985 WCHAR *p;
4986 HMODULE module;
4988 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4989 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4991 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4992 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4993 actctx->appdir.info = dir.Buffer;
4996 nameW.Buffer = NULL;
4998 /* open file only if it's going to be used */
4999 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5000 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5002 WCHAR *source = NULL;
5003 BOOLEAN ret;
5005 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5006 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5008 DWORD dir_len, source_len;
5010 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
5011 source_len = strlenW(pActCtx->lpSource);
5012 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5014 status = STATUS_NO_MEMORY;
5015 goto error;
5018 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5019 source[dir_len] = '\\';
5020 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5023 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5024 RtlFreeHeap( GetProcessHeap(), 0, source );
5025 if (!ret)
5027 status = STATUS_NO_SUCH_FILE;
5028 goto error;
5030 status = open_nt_file( &file, &nameW );
5031 if (status)
5033 RtlFreeUnicodeString( &nameW );
5034 goto error;
5038 acl.actctx = actctx;
5039 acl.dependencies = NULL;
5040 acl.num_dependencies = 0;
5041 acl.allocated_dependencies = 0;
5043 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5044 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5046 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5048 /* if we have a resource it's a PE file */
5049 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5051 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5052 pActCtx->lpResourceName, lang );
5053 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5054 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5055 pActCtx->hModule, pActCtx->lpResourceName );
5057 else if (pActCtx->lpSource)
5059 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5060 file, pActCtx->lpResourceName, lang );
5061 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5062 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5063 NULL, pActCtx->lpResourceName );
5065 else status = STATUS_INVALID_PARAMETER;
5067 else
5069 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5072 if (file) NtClose( file );
5073 RtlFreeUnicodeString( &nameW );
5075 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5076 free_depend_manifests( &acl );
5078 if (status == STATUS_SUCCESS) *handle = actctx;
5079 else actctx_release( actctx );
5080 return status;
5082 error:
5083 if (file) NtClose( file );
5084 actctx_release( actctx );
5085 return status;
5089 /***********************************************************************
5090 * RtlAddRefActivationContext (NTDLL.@)
5092 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5094 ACTIVATION_CONTEXT *actctx;
5096 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5100 /******************************************************************
5101 * RtlReleaseActivationContext (NTDLL.@)
5103 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5105 ACTIVATION_CONTEXT *actctx;
5107 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5110 /******************************************************************
5111 * RtlZombifyActivationContext (NTDLL.@)
5113 * FIXME: function prototype might be wrong
5115 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5117 FIXME("%p: stub\n", handle);
5118 return STATUS_NOT_IMPLEMENTED;
5121 /******************************************************************
5122 * RtlActivateActivationContext (NTDLL.@)
5124 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5126 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5128 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5129 return STATUS_NO_MEMORY;
5131 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5132 frame->ActivationContext = handle;
5133 frame->Flags = 0;
5134 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5135 RtlAddRefActivationContext( handle );
5137 *cookie = (ULONG_PTR)frame;
5138 TRACE( "%p cookie=%lx\n", handle, *cookie );
5139 return STATUS_SUCCESS;
5143 /***********************************************************************
5144 * RtlDeactivateActivationContext (NTDLL.@)
5146 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5148 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5150 TRACE( "%x cookie=%lx\n", flags, cookie );
5152 /* find the right frame */
5153 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5154 for (frame = top; frame; frame = frame->Previous)
5155 if ((ULONG_PTR)frame == cookie) break;
5157 if (!frame)
5158 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5160 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5161 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5163 /* pop everything up to and including frame */
5164 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5166 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5168 frame = top->Previous;
5169 RtlReleaseActivationContext( top->ActivationContext );
5170 RtlFreeHeap( GetProcessHeap(), 0, top );
5171 top = frame;
5176 /******************************************************************
5177 * RtlFreeThreadActivationContextStack (NTDLL.@)
5179 void WINAPI RtlFreeThreadActivationContextStack(void)
5181 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5183 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5184 while (frame)
5186 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5187 RtlReleaseActivationContext( frame->ActivationContext );
5188 RtlFreeHeap( GetProcessHeap(), 0, frame );
5189 frame = prev;
5191 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5195 /******************************************************************
5196 * RtlGetActiveActivationContext (NTDLL.@)
5198 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5200 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5202 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5203 RtlAddRefActivationContext( *handle );
5205 else
5206 *handle = 0;
5208 return STATUS_SUCCESS;
5212 /******************************************************************
5213 * RtlIsActivationContextActive (NTDLL.@)
5215 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5217 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5219 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5220 if (frame->ActivationContext == handle) return TRUE;
5221 return FALSE;
5225 /***********************************************************************
5226 * RtlQueryInformationActivationContext (NTDLL.@)
5228 * Get information about an activation context.
5229 * FIXME: function signature/prototype may be wrong
5231 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5232 ULONG class, PVOID buffer,
5233 SIZE_T bufsize, SIZE_T *retlen )
5235 ACTIVATION_CONTEXT *actctx;
5236 NTSTATUS status;
5238 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5239 subinst, class, buffer, bufsize, retlen);
5241 if (retlen) *retlen = 0;
5242 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5244 switch (class)
5246 case ActivationContextBasicInformation:
5248 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5250 if (retlen) *retlen = sizeof(*info);
5251 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5253 info->hActCtx = handle;
5254 info->dwFlags = 0; /* FIXME */
5255 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5257 break;
5259 case ActivationContextDetailedInformation:
5261 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5262 struct assembly *assembly = NULL;
5263 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5264 LPWSTR ptr;
5266 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5268 if (actctx->num_assemblies) assembly = actctx->assemblies;
5270 if (assembly && assembly->manifest.info)
5271 manifest_len = strlenW(assembly->manifest.info) + 1;
5272 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5273 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5274 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5276 if (retlen) *retlen = len;
5277 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5279 acdi->dwFlags = 0;
5280 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5281 acdi->ulAssemblyCount = actctx->num_assemblies;
5282 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5283 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5284 acdi->ulRootConfigurationPathType = actctx->config.type;
5285 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5286 acdi->ulAppDirPathType = actctx->appdir.type;
5287 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5288 ptr = (LPWSTR)(acdi + 1);
5289 if (manifest_len)
5291 acdi->lpRootManifestPath = ptr;
5292 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5293 ptr += manifest_len;
5295 else acdi->lpRootManifestPath = NULL;
5296 if (config_len)
5298 acdi->lpRootConfigurationPath = ptr;
5299 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5300 ptr += config_len;
5302 else acdi->lpRootConfigurationPath = NULL;
5303 if (appdir_len)
5305 acdi->lpAppDirPath = ptr;
5306 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5308 else acdi->lpAppDirPath = NULL;
5310 break;
5312 case AssemblyDetailedInformationInActivationContext:
5314 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5315 struct assembly *assembly;
5316 WCHAR *assembly_id;
5317 DWORD index;
5318 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5319 LPWSTR ptr;
5321 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5322 if (!subinst) return STATUS_INVALID_PARAMETER;
5324 index = *(DWORD*)subinst;
5325 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5327 assembly = &actctx->assemblies[index - 1];
5329 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5330 id_len = strlenW(assembly_id) + 1;
5331 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5333 if (assembly->manifest.info &&
5334 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5335 path_len = strlenW(assembly->manifest.info) + 1;
5337 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5339 if (retlen) *retlen = len;
5340 if (!buffer || bufsize < len)
5342 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5343 return STATUS_BUFFER_TOO_SMALL;
5346 afdi->ulFlags = 0; /* FIXME */
5347 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5348 afdi->ulManifestPathType = assembly->manifest.type;
5349 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5350 /* FIXME afdi->liManifestLastWriteTime = 0; */
5351 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5352 afdi->ulPolicyPathLength = 0;
5353 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5354 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5355 afdi->ulManifestVersionMajor = 1;
5356 afdi->ulManifestVersionMinor = 0;
5357 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5358 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5359 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5360 ptr = (LPWSTR)(afdi + 1);
5361 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5362 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5363 ptr += id_len;
5364 if (path_len)
5366 afdi->lpAssemblyManifestPath = ptr;
5367 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5368 ptr += path_len;
5369 } else afdi->lpAssemblyManifestPath = NULL;
5370 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5371 if (ad_len)
5373 afdi->lpAssemblyDirectoryName = ptr;
5374 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5376 else afdi->lpAssemblyDirectoryName = NULL;
5377 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5379 break;
5381 case FileInformationInAssemblyOfAssemblyInActivationContext:
5383 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5384 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5385 struct assembly *assembly;
5386 struct dll_redirect *dll;
5387 SIZE_T len, dll_len = 0;
5388 LPWSTR ptr;
5390 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5391 if (!acqi) return STATUS_INVALID_PARAMETER;
5393 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5394 return STATUS_INVALID_PARAMETER;
5395 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5397 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5398 return STATUS_INVALID_PARAMETER;
5399 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5401 if (dll->name) dll_len = strlenW(dll->name) + 1;
5402 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5404 if (!buffer || bufsize < len)
5406 if (retlen) *retlen = len;
5407 return STATUS_BUFFER_TOO_SMALL;
5409 if (retlen) *retlen = 0; /* yes that's what native does !! */
5410 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5411 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5412 afdi->ulPathLength = 0; /* FIXME */
5413 ptr = (LPWSTR)(afdi + 1);
5414 if (dll_len)
5416 afdi->lpFileName = ptr;
5417 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5418 } else afdi->lpFileName = NULL;
5419 afdi->lpFilePath = NULL; /* FIXME */
5421 break;
5423 case CompatibilityInformationInActivationContext:
5425 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5426 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5427 struct assembly *assembly = NULL;
5428 ULONG num_compat_contexts = 0, n;
5429 SIZE_T len;
5431 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5433 if (actctx->num_assemblies) assembly = actctx->assemblies;
5435 if (assembly)
5436 num_compat_contexts = assembly->num_compat_contexts;
5437 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5439 if (retlen) *retlen = len;
5440 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5442 *acci = num_compat_contexts;
5443 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5444 for (n = 0; n < num_compat_contexts; ++n)
5446 elements[n] = assembly->compat_contexts[n];
5449 break;
5451 case RunlevelInformationInActivationContext:
5453 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5454 struct assembly *assembly;
5455 SIZE_T len;
5457 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5459 len = sizeof(*acrli);
5460 if (retlen) *retlen = len;
5461 if (!buffer || bufsize < len)
5462 return STATUS_BUFFER_TOO_SMALL;
5464 assembly = actctx->assemblies;
5466 acrli->ulFlags = 0;
5467 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5468 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5470 break;
5472 default:
5473 FIXME( "class %u not implemented\n", class );
5474 return STATUS_NOT_IMPLEMENTED;
5476 return STATUS_SUCCESS;
5479 /***********************************************************************
5480 * RtlFindActivationContextSectionString (NTDLL.@)
5482 * Find information about a string in an activation context.
5483 * FIXME: function signature/prototype may be wrong
5485 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5486 const UNICODE_STRING *section_name, PVOID ptr )
5488 PACTCTX_SECTION_KEYED_DATA data = ptr;
5489 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5491 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5492 debugstr_us(section_name), data);
5494 if (guid)
5496 FIXME("expected guid == NULL\n");
5497 return STATUS_INVALID_PARAMETER;
5499 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5501 FIXME("unknown flags %08x\n", flags);
5502 return STATUS_INVALID_PARAMETER;
5504 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5505 !section_name || !section_name->Buffer)
5507 WARN("invalid parameter\n");
5508 return STATUS_INVALID_PARAMETER;
5511 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5513 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5514 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5517 if (status != STATUS_SUCCESS)
5518 status = find_string( process_actctx, section_kind, section_name, flags, data );
5520 return status;
5523 /***********************************************************************
5524 * RtlFindActivationContextSectionGuid (NTDLL.@)
5526 * Find information about a GUID in an activation context.
5527 * FIXME: function signature/prototype may be wrong
5529 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5530 const GUID *guid, void *ptr )
5532 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5533 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5535 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5537 if (extguid)
5539 FIXME("expected extguid == NULL\n");
5540 return STATUS_INVALID_PARAMETER;
5543 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5545 FIXME("unknown flags %08x\n", flags);
5546 return STATUS_INVALID_PARAMETER;
5549 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5550 return STATUS_INVALID_PARAMETER;
5552 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5554 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5555 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5558 if (status != STATUS_SUCCESS)
5559 status = find_guid( process_actctx, section_kind, guid, flags, data );
5561 return status;
5565 /***********************************************************************
5566 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5568 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5569 const WCHAR *settings, WCHAR *buffer,
5570 SIZE_T size, SIZE_T *written )
5572 ACTIVATION_CONTEXT *actctx = check_actctx( handle );
5573 const WCHAR *res;
5575 if (flags)
5577 WARN( "unknown flags %08x\n", flags );
5578 return STATUS_INVALID_PARAMETER;
5581 if (ns)
5583 if (strcmpW( ns, windowsSettings2005NSW ) &&
5584 strcmpW( ns, windowsSettings2011NSW ) &&
5585 strcmpW( ns, windowsSettings2016NSW ) &&
5586 strcmpW( ns, windowsSettings2017NSW ))
5587 return STATUS_INVALID_PARAMETER;
5589 else ns = windowsSettings2005NSW;
5591 if (!handle) handle = process_actctx;
5592 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5594 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5596 if (written) *written = strlenW(res) + 1;
5597 if (size < strlenW(res)) return STATUS_BUFFER_TOO_SMALL;
5598 strcpyW( buffer, res );
5599 return STATUS_SUCCESS;