combase: Add stub for CleanupTlsOleState.
[wine.git] / dlls / ntdll / actctx.c
blob7e3aec4d1e75755fc4a21d1af2ababd1af7ebcac
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 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};
574 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};
575 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};
576 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
577 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
578 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
579 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
580 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
581 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
582 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};
583 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};
584 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
585 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
586 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
587 static const WCHAR fileW[] = {'f','i','l','e',0};
588 static const WCHAR hashW[] = {'h','a','s','h',0};
589 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
590 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
591 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
592 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
594 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
595 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
596 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
597 static const WCHAR iidW[] = {'i','i','d',0};
598 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
599 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
600 static const WCHAR nameW[] = {'n','a','m','e',0};
601 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
602 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
603 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
604 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
605 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};
606 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
607 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
608 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
609 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
610 static const WCHAR typeW[] = {'t','y','p','e',0};
611 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
612 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
613 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
614 static const WCHAR yesW[] = {'y','e','s',0};
615 static const WCHAR noW[] = {'n','o',0};
616 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
617 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
618 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
619 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
620 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
621 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
622 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
623 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
624 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
625 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
626 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
627 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
628 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
629 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
630 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
631 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
633 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
634 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
635 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
636 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
637 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
638 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
639 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
640 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};
641 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
642 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
643 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
644 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
645 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
646 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
647 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
648 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
649 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};
650 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
651 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
652 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
653 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};
654 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
656 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
657 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};
658 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
659 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
660 static const WCHAR IdW[] = {'I','d',0};
661 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};
662 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
663 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
664 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
665 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
666 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
667 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
668 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};
669 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};
670 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};
671 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};
672 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};
673 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
674 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
675 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
676 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};
677 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
678 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
679 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};
680 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};
682 struct olemisc_entry
684 const WCHAR *name;
685 OLEMISC value;
688 static const struct olemisc_entry olemisc_values[] =
690 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
691 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
692 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
693 { alignableW, OLEMISC_ALIGNABLE },
694 { alwaysrunW, OLEMISC_ALWAYSRUN },
695 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
696 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
697 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
698 { imemodeW, OLEMISC_IMEMODE },
699 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
700 { insideoutW, OLEMISC_INSIDEOUT },
701 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
702 { islinkobjectW, OLEMISC_ISLINKOBJECT },
703 { nouiactivateW, OLEMISC_NOUIACTIVATE },
704 { onlyiconicW, OLEMISC_ONLYICONIC },
705 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
706 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
707 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
708 { simpleframeW, OLEMISC_SIMPLEFRAME },
709 { staticW, OLEMISC_STATIC },
710 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
711 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
714 static const WCHAR xmlW[] = {'?','x','m','l',0};
715 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
716 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
717 static const WCHAR wildcardW[] = {'*',0};
719 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
720 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
722 static WCHAR *strdupW(const WCHAR* str)
724 WCHAR* ptr;
726 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
727 return NULL;
728 return strcpyW(ptr, str);
731 static WCHAR *xmlstrdupW(const xmlstr_t* str)
733 WCHAR *strW;
735 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
737 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
738 strW[str->len] = 0;
740 return strW;
743 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
745 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
748 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
750 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
753 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
755 return xmlstr_cmp( &attr->name, str );
758 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
760 return (elem1->name.len == elem2->name.len &&
761 elem1->ns.len == elem2->ns.len &&
762 !strncmpW( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
763 !strncmpW( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
766 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
768 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
769 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
770 if (!strcmpW( namespace, asmv1W ))
772 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
773 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
775 else if (!strcmpW( namespace, asmv2W ))
777 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
779 return FALSE;
782 static inline BOOL isxmlspace( WCHAR ch )
784 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
787 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
789 return debugstr_wn(str->ptr, str->len);
792 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
794 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
795 debugstr_wn( elem->ns.ptr, elem->ns.len ));
798 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
800 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
801 debugstr_wn( attr->value.ptr, attr->value.len ));
804 static inline const char* debugstr_version(const struct assembly_version *ver)
806 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
809 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
811 struct assembly *assembly;
813 if (actctx->num_assemblies == actctx->allocated_assemblies)
815 void *ptr;
816 unsigned int new_count;
817 if (actctx->assemblies)
819 new_count = actctx->allocated_assemblies * 2;
820 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
821 actctx->assemblies, new_count * sizeof(*assembly) );
823 else
825 new_count = 4;
826 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
828 if (!ptr) return NULL;
829 actctx->assemblies = ptr;
830 actctx->allocated_assemblies = new_count;
833 assembly = &actctx->assemblies[actctx->num_assemblies++];
834 assembly->type = at;
835 return assembly;
838 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
840 if (assembly->num_dlls == assembly->allocated_dlls)
842 void *ptr;
843 unsigned int new_count;
844 if (assembly->dlls)
846 new_count = assembly->allocated_dlls * 2;
847 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
848 assembly->dlls, new_count * sizeof(*assembly->dlls) );
850 else
852 new_count = 4;
853 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
855 if (!ptr) return NULL;
856 assembly->dlls = ptr;
857 assembly->allocated_dlls = new_count;
859 return &assembly->dlls[assembly->num_dlls++];
862 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
864 void *ptr;
865 if (assembly->num_compat_contexts)
867 unsigned int new_count = assembly->num_compat_contexts + 1;
868 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
869 assembly->compat_contexts,
870 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
872 else
874 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
876 if (!ptr) return NULL;
877 assembly->compat_contexts = ptr;
878 return &assembly->compat_contexts[assembly->num_compat_contexts++];
881 static void free_assembly_identity(struct assembly_identity *ai)
883 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
884 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
885 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
886 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
887 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
890 static struct entity* add_entity(struct entity_array *array, DWORD kind)
892 struct entity* entity;
894 if (array->num == array->allocated)
896 void *ptr;
897 unsigned int new_count;
898 if (array->base)
900 new_count = array->allocated * 2;
901 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
902 array->base, new_count * sizeof(*array->base) );
904 else
906 new_count = 4;
907 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
909 if (!ptr) return NULL;
910 array->base = ptr;
911 array->allocated = new_count;
913 entity = &array->base[array->num++];
914 entity->kind = kind;
915 return entity;
918 static void free_entity_array(struct entity_array *array)
920 unsigned int i, j;
921 for (i = 0; i < array->num; i++)
923 struct entity *entity = &array->base[i];
924 switch (entity->kind)
926 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
927 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
928 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
929 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
930 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
931 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
932 for (j = 0; j < entity->u.comclass.progids.num; j++)
933 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
934 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
935 break;
936 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
937 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
938 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
939 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
940 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
941 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
942 break;
943 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
944 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
945 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
946 break;
947 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
948 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
949 break;
950 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
951 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
952 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
953 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
954 break;
955 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
956 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
957 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
958 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
959 break;
960 default:
961 FIXME("Unknown entity kind %d\n", entity->kind);
964 RtlFreeHeap( GetProcessHeap(), 0, array->base );
967 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
969 if (!str1) return !str2;
970 return str2 && !strcmpiW( str1, str2 );
973 static BOOL is_matching_identity( const struct assembly_identity *id1,
974 const struct assembly_identity *id2 )
976 if (!is_matching_string( id1->name, id2->name )) return FALSE;
977 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
978 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
980 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
982 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
983 return FALSE;
985 if (id1->version.major != id2->version.major) return FALSE;
986 if (id1->version.minor != id2->version.minor) return FALSE;
987 if (id1->version.build > id2->version.build) return FALSE;
988 if (id1->version.build == id2->version.build &&
989 id1->version.revision > id2->version.revision) return FALSE;
990 return TRUE;
993 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
994 struct assembly_identity* ai)
996 unsigned int i;
998 /* check if we already have that assembly */
1000 for (i = 0; i < acl->actctx->num_assemblies; i++)
1001 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1003 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1004 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1005 ai->version.build, ai->version.revision );
1006 return TRUE;
1009 for (i = 0; i < acl->num_dependencies; i++)
1010 if (is_matching_identity( ai, &acl->dependencies[i] ))
1012 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1013 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1014 ai->version.build, ai->version.revision );
1015 return TRUE;
1018 if (acl->num_dependencies == acl->allocated_dependencies)
1020 void *ptr;
1021 unsigned int new_count;
1022 if (acl->dependencies)
1024 new_count = acl->allocated_dependencies * 2;
1025 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
1026 new_count * sizeof(acl->dependencies[0]));
1028 else
1030 new_count = 4;
1031 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1033 if (!ptr) return FALSE;
1034 acl->dependencies = ptr;
1035 acl->allocated_dependencies = new_count;
1037 acl->dependencies[acl->num_dependencies++] = *ai;
1039 return TRUE;
1042 static void free_depend_manifests(struct actctx_loader* acl)
1044 unsigned int i;
1045 for (i = 0; i < acl->num_dependencies; i++)
1046 free_assembly_identity(&acl->dependencies[i]);
1047 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1050 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1052 static const WCHAR undW[] = {'_',0};
1053 static const WCHAR noneW[] = {'n','o','n','e',0};
1054 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1056 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1057 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1058 const WCHAR *lang = ai->language ? ai->language : noneW;
1059 const WCHAR *name = ai->name ? ai->name : noneW;
1060 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1061 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1062 WCHAR *ret;
1064 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1066 strcpyW( ret, arch );
1067 strcatW( ret, undW );
1068 strcatW( ret, name );
1069 strcatW( ret, undW );
1070 strcatW( ret, key );
1071 strcatW( ret, undW );
1072 sprintfW( ret + strlenW(ret), version_formatW,
1073 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1074 strcatW( ret, undW );
1075 strcatW( ret, lang );
1076 strcatW( ret, undW );
1077 strcatW( ret, mskeyW );
1078 return ret;
1081 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1083 WCHAR *p = buffer;
1085 if (!str) return;
1086 strcatW( buffer, prefix );
1087 p += strlenW(p);
1088 *p++ = '"';
1089 strcpyW( p, str );
1090 p += strlenW(p);
1091 *p++ = '"';
1092 *p = 0;
1095 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1097 static const WCHAR archW[] =
1098 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1099 static const WCHAR public_keyW[] =
1100 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1101 static const WCHAR typeW[] =
1102 {',','t','y','p','e','=',0};
1103 static const WCHAR versionW[] =
1104 {',','v','e','r','s','i','o','n','=',0};
1106 WCHAR version[64], *ret;
1107 SIZE_T size = 0;
1109 sprintfW( version, version_formatW,
1110 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1111 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1112 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1113 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1114 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1115 size += strlenW(versionW) + strlenW(version) + 2;
1117 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1118 return NULL;
1120 if (ai->name) strcpyW( ret, ai->name );
1121 else *ret = 0;
1122 append_string( ret, archW, ai->arch );
1123 append_string( ret, public_keyW, ai->public_key );
1124 append_string( ret, typeW, ai->type );
1125 append_string( ret, versionW, version );
1126 return ret;
1129 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1131 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1133 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1134 __TRY
1136 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1138 __EXCEPT_PAGE_FAULT
1141 __ENDTRY
1142 return ret;
1145 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1147 interlocked_xchg_add( &actctx->ref_count, 1 );
1150 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1152 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1154 unsigned int i, j;
1156 for (i = 0; i < actctx->num_assemblies; i++)
1158 struct assembly *assembly = &actctx->assemblies[i];
1159 for (j = 0; j < assembly->num_dlls; j++)
1161 struct dll_redirect *dll = &assembly->dlls[j];
1162 free_entity_array( &dll->entities );
1163 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1164 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1166 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1167 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1168 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1169 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1170 free_entity_array( &assembly->entities );
1171 free_assembly_identity(&assembly->id);
1173 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1174 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1175 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1176 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1177 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1178 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1179 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1180 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1181 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1182 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1183 actctx->magic = 0;
1184 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1188 static BOOL set_error( xmlbuf_t *xmlbuf )
1190 xmlbuf->error = TRUE;
1191 return FALSE;
1194 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1196 const int len = strlenW( xmlnsW );
1197 if (attr->name.len < len) return FALSE;
1198 if (strncmpW( attr->name.ptr, xmlnsW, len )) return FALSE;
1199 return (attr->name.len == len || attr->name.ptr[len] == ':');
1202 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1204 const int len = strlenW( xmlnsW );
1205 struct xml_attr *ns;
1207 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1209 FIXME( "too many namespaces in manifest\n" );
1210 set_error( xmlbuf );
1211 return;
1213 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1214 ns->value = attr->value;
1215 if (attr->name.len > len)
1217 ns->name.ptr = attr->name.ptr + len + 1;
1218 ns->name.len = attr->name.len - len - 1;
1220 else ns->name = empty_xmlstr;
1223 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1225 int i;
1227 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1229 if (xmlbuf->namespaces[i].name.len == name->len &&
1230 !strncmpW( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1231 return xmlbuf->namespaces[i].value;
1233 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1234 return empty_xmlstr;
1237 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1239 const WCHAR* ptr;
1241 if (xmlbuf->error) return FALSE;
1243 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1244 xmlbuf->ptr++;
1246 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1248 if (*xmlbuf->ptr == '/')
1250 xmlbuf->ptr++;
1251 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1252 return set_error( xmlbuf );
1254 xmlbuf->ptr++;
1255 *end = TRUE;
1256 return FALSE;
1259 if (*xmlbuf->ptr == '>')
1261 xmlbuf->ptr++;
1262 return FALSE;
1265 ptr = xmlbuf->ptr;
1266 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1268 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1270 attr->name.ptr = xmlbuf->ptr;
1271 attr->name.len = ptr-xmlbuf->ptr;
1272 xmlbuf->ptr = ptr;
1274 /* skip spaces before '=' */
1275 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1276 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1278 /* skip '=' itself */
1279 ptr++;
1280 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1282 /* skip spaces after '=' */
1283 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1285 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1287 attr->value.ptr = ++ptr;
1288 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1290 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1291 if (!ptr)
1293 xmlbuf->ptr = xmlbuf->end;
1294 return set_error( xmlbuf );
1297 attr->value.len = ptr - attr->value.ptr;
1298 xmlbuf->ptr = ptr + 1;
1299 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1301 return set_error( xmlbuf );
1304 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1306 const WCHAR* ptr = xmlbuf->ptr;
1308 elem->ns = empty_xmlstr;
1309 elem->name.ptr = ptr;
1310 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1312 if (*ptr == ':')
1314 elem->ns.ptr = elem->name.ptr;
1315 elem->ns.len = ptr - elem->ns.ptr;
1316 elem->name.ptr = ptr + 1;
1318 ptr++;
1320 elem->name.len = ptr - elem->name.ptr;
1321 xmlbuf->ptr = ptr;
1324 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1326 const WCHAR* ptr;
1327 struct xml_attr attr;
1328 xmlbuf_t attr_buf;
1329 BOOL end = FALSE;
1331 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1333 if (xmlbuf->error) return FALSE;
1335 for (;;)
1337 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1338 if (!ptr)
1340 xmlbuf->ptr = xmlbuf->end;
1341 return set_error( xmlbuf );
1343 ptr++;
1344 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1346 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1347 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1349 if (ptr + 3 > xmlbuf->end)
1351 xmlbuf->ptr = xmlbuf->end;
1352 return set_error( xmlbuf );
1354 xmlbuf->ptr = ptr + 3;
1356 else break;
1359 xmlbuf->ptr = ptr;
1360 /* check for element terminating the parent element */
1361 if (ptr < xmlbuf->end && *ptr == '/')
1363 xmlbuf->ptr++;
1364 read_xml_elem( xmlbuf, elem );
1365 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1366 if (!xml_name_cmp( elem, parent ))
1368 ERR( "wrong closing element %s for %s\n",
1369 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1370 return set_error( xmlbuf );
1372 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1373 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1374 return FALSE;
1377 read_xml_elem( xmlbuf, elem );
1379 /* parse namespace attributes */
1380 attr_buf = *xmlbuf;
1381 while (next_xml_attr( &attr_buf, &attr, &end ))
1383 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1385 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1386 elem->ns_pos = xmlbuf->ns_pos;
1388 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1390 return set_error( xmlbuf );
1393 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1395 /* FIXME: parse attributes */
1396 const WCHAR *ptr;
1398 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1400 if (ptr[0] == '?' && ptr[1] == '>')
1402 xmlbuf->ptr = ptr + 2;
1403 return TRUE;
1406 return FALSE;
1409 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1411 const WCHAR *ptr;
1413 if (xmlbuf->error) return FALSE;
1415 if (!(ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr))) return set_error( xmlbuf );
1417 content->ptr = xmlbuf->ptr;
1418 content->len = ptr - xmlbuf->ptr;
1419 xmlbuf->ptr = ptr;
1421 return TRUE;
1424 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1426 unsigned int ver[4];
1427 unsigned int pos;
1428 const WCHAR *curr;
1430 /* major.minor.build.revision */
1431 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1432 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1434 if (*curr >= '0' && *curr <= '9')
1436 ver[pos] = ver[pos] * 10 + *curr - '0';
1437 if (ver[pos] >= 0x10000) goto error;
1439 else if (*curr == '.')
1441 if (++pos >= 4) goto error;
1443 else goto error;
1445 version->major = ver[0];
1446 version->minor = ver[1];
1447 version->build = ver[2];
1448 version->revision = ver[3];
1449 return TRUE;
1451 error:
1452 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1453 return FALSE;
1456 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1458 struct xml_attr attr;
1460 while (next_xml_attr(xmlbuf, &attr, end))
1462 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1466 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1468 struct xml_elem elem;
1470 if (next_xml_elem(xmlbuf, &elem, parent))
1472 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1473 set_error( xmlbuf );
1477 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1479 struct xml_elem elem;
1480 struct xml_attr attr;
1481 BOOL end = FALSE;
1483 while (next_xml_attr(xmlbuf, &attr, &end));
1484 if (end) return;
1486 while (next_xml_elem(xmlbuf, &elem, parent))
1487 parse_unknown_elem(xmlbuf, &elem);
1490 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1491 struct assembly_identity* ai, const struct xml_elem *parent)
1493 struct xml_attr attr;
1494 BOOL end = FALSE;
1496 while (next_xml_attr(xmlbuf, &attr, &end))
1498 if (xml_attr_cmp(&attr, nameW))
1500 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1502 else if (xml_attr_cmp(&attr, typeW))
1504 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1506 else if (xml_attr_cmp(&attr, versionW))
1508 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1510 else if (xml_attr_cmp(&attr, processorArchitectureW))
1512 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1514 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1516 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1518 else if (xml_attr_cmp(&attr, languageW))
1520 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1522 else if (!is_xmlns_attr( &attr ))
1524 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1528 TRACE( "name=%s version=%s arch=%s\n",
1529 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1531 if (!end) parse_expect_end_elem(xmlbuf, parent);
1534 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1536 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1537 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1538 static const WCHAR freeW[] = {'F','r','e','e',0};
1539 static const WCHAR bothW[] = {'B','o','t','h',0};
1541 if (value->len == 0) return ThreadingModel_No;
1542 if (xmlstr_cmp(value, apartW))
1543 return ThreadingModel_Apartment;
1544 else if (xmlstr_cmp(value, freeW))
1545 return ThreadingModel_Free;
1546 else if (xmlstr_cmp(value, bothW))
1547 return ThreadingModel_Both;
1548 else if (xmlstr_cmp(value, neutralW))
1549 return ThreadingModel_Neutral;
1550 else
1551 return ThreadingModel_No;
1554 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1556 int min, max;
1558 min = 0;
1559 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1561 while (min <= max)
1563 int n, c;
1565 n = (min+max)/2;
1567 c = strncmpW(olemisc_values[n].name, str, len);
1568 if (!c && !olemisc_values[n].name[len])
1569 return olemisc_values[n].value;
1571 if (c >= 0)
1572 max = n-1;
1573 else
1574 min = n+1;
1577 WARN("unknown flag %s\n", debugstr_wn(str, len));
1578 return 0;
1581 static DWORD parse_com_class_misc(const xmlstr_t *value)
1583 const WCHAR *str = value->ptr, *start;
1584 DWORD flags = 0;
1585 int i = 0;
1587 /* it's comma separated list of flags */
1588 while (i < value->len)
1590 start = str;
1591 while (*str != ',' && (i++ < value->len)) str++;
1593 flags |= get_olemisc_value(start, str-start);
1595 /* skip separator */
1596 str++;
1597 i++;
1600 return flags;
1603 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1605 struct progids *progids = &entity->u.comclass.progids;
1607 if (progids->allocated == 0)
1609 progids->allocated = 4;
1610 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1613 if (progids->allocated == progids->num)
1615 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1616 2 * progids->allocated * sizeof(WCHAR*));
1617 if (!new_progids) return FALSE;
1618 progids->allocated *= 2;
1619 progids->progids = new_progids;
1622 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1623 progids->num++;
1625 return TRUE;
1628 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1630 xmlstr_t content;
1631 BOOL end = FALSE;
1633 parse_expect_no_attr(xmlbuf, &end);
1634 if (end) set_error( xmlbuf );
1635 if (!parse_text_content(xmlbuf, &content)) return;
1637 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1638 parse_expect_end_elem(xmlbuf, parent);
1641 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1642 const struct xml_elem *parent )
1644 struct xml_elem elem;
1645 struct xml_attr attr;
1646 BOOL end = FALSE;
1647 struct entity* entity;
1649 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1651 set_error( xmlbuf );
1652 return;
1655 while (next_xml_attr(xmlbuf, &attr, &end))
1657 if (xml_attr_cmp(&attr, clsidW))
1659 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1661 else if (xml_attr_cmp(&attr, progidW))
1663 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1665 else if (xml_attr_cmp(&attr, tlbidW))
1667 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1669 else if (xml_attr_cmp(&attr, threadingmodelW))
1671 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1673 else if (xml_attr_cmp(&attr, miscstatusW))
1675 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1677 else if (xml_attr_cmp(&attr, miscstatuscontentW))
1679 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1681 else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1683 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1685 else if (xml_attr_cmp(&attr, miscstatusiconW))
1687 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1689 else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1691 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1693 else if (xml_attr_cmp(&attr, descriptionW))
1695 /* not stored */
1697 else if (!is_xmlns_attr( &attr ))
1699 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1703 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1704 if (entity->u.comclass.progid)
1705 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1707 if (end) return;
1709 while (next_xml_elem(xmlbuf, &elem, parent))
1711 if (xml_elem_cmp(&elem, progidW, asmv1W))
1713 parse_com_class_progid(xmlbuf, entity, &elem);
1715 else
1717 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1718 parse_unknown_elem(xmlbuf, &elem);
1722 if (entity->u.comclass.progids.num)
1723 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1726 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1728 const WCHAR *curr;
1729 ULONG num = 0;
1731 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1733 if (*curr >= '0' && *curr <= '9')
1734 num = num * 10 + *curr - '0';
1735 else
1737 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1738 return FALSE;
1741 entity->u.ifaceps.nummethods = num;
1743 return TRUE;
1746 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1747 struct actctx_loader *acl, const struct xml_elem *parent )
1749 struct xml_attr attr;
1750 BOOL end = FALSE;
1751 struct entity* entity;
1753 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1755 set_error( xmlbuf );
1756 return;
1759 while (next_xml_attr(xmlbuf, &attr, &end))
1761 if (xml_attr_cmp(&attr, iidW))
1763 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1765 else if (xml_attr_cmp(&attr, nameW))
1767 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1769 else if (xml_attr_cmp(&attr, baseInterfaceW))
1771 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1772 entity->u.ifaceps.mask |= BaseIface;
1774 else if (xml_attr_cmp(&attr, nummethodsW))
1776 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1777 entity->u.ifaceps.mask |= NumMethods;
1779 else if (xml_attr_cmp(&attr, tlbidW))
1781 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1783 /* not used */
1784 else if (xml_attr_cmp(&attr, proxyStubClsid32W) || xml_attr_cmp(&attr, threadingmodelW))
1787 else if (!is_xmlns_attr( &attr ))
1789 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1793 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1794 if (!end) parse_expect_end_elem(xmlbuf, parent);
1797 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1799 WORD *flags = &entity->u.typelib.flags;
1800 const WCHAR *str = value->ptr, *start;
1801 int i = 0;
1803 *flags = 0;
1805 /* it's comma separated list of flags */
1806 while (i < value->len)
1808 start = str;
1809 while (*str != ',' && (i++ < value->len)) str++;
1811 if (!strncmpiW(start, restrictedW, str-start))
1812 *flags |= LIBFLAG_FRESTRICTED;
1813 else if (!strncmpiW(start, controlW, str-start))
1814 *flags |= LIBFLAG_FCONTROL;
1815 else if (!strncmpiW(start, hiddenW, str-start))
1816 *flags |= LIBFLAG_FHIDDEN;
1817 else if (!strncmpiW(start, hasdiskimageW, str-start))
1818 *flags |= LIBFLAG_FHASDISKIMAGE;
1819 else
1821 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1822 return FALSE;
1825 /* skip separator */
1826 str++;
1827 i++;
1830 return TRUE;
1833 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1835 unsigned int ver[2];
1836 unsigned int pos;
1837 const WCHAR *curr;
1839 /* major.minor */
1840 ver[0] = ver[1] = pos = 0;
1841 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1843 if (*curr >= '0' && *curr <= '9')
1845 ver[pos] = ver[pos] * 10 + *curr - '0';
1846 if (ver[pos] >= 0x10000) goto error;
1848 else if (*curr == '.')
1850 if (++pos >= 2) goto error;
1852 else goto error;
1854 entity->u.typelib.major = ver[0];
1855 entity->u.typelib.minor = ver[1];
1856 return TRUE;
1858 error:
1859 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1860 return FALSE;
1863 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1864 struct actctx_loader *acl, const struct xml_elem *parent )
1866 struct xml_attr attr;
1867 BOOL end = FALSE;
1868 struct entity* entity;
1870 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1872 set_error( xmlbuf );
1873 return;
1876 while (next_xml_attr(xmlbuf, &attr, &end))
1878 if (xml_attr_cmp(&attr, tlbidW))
1880 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1882 else if (xml_attr_cmp(&attr, versionW))
1884 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1886 else if (xml_attr_cmp(&attr, helpdirW))
1888 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1890 else if (xml_attr_cmp(&attr, flagsW))
1892 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1894 else if (!is_xmlns_attr( &attr ))
1896 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1900 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1901 if (!end) parse_expect_end_elem(xmlbuf, parent);
1904 static inline int aligned_string_len(int len)
1906 return (len + 3) & ~3;
1909 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1911 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1912 struct assembly_version *ver = &assembly->id.version;
1913 WCHAR buff[25];
1915 if (!ret) ret = buff;
1916 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1919 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1920 struct actctx_loader *acl, const struct xml_elem *parent )
1922 struct xml_elem elem;
1923 struct xml_attr attr;
1924 xmlstr_t content;
1925 BOOL end = FALSE;
1926 struct entity* entity;
1928 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1930 set_error( xmlbuf );
1931 return;
1933 entity->u.class.versioned = TRUE;
1934 while (next_xml_attr(xmlbuf, &attr, &end))
1936 if (xml_attr_cmp(&attr, versionedW))
1938 if (xmlstr_cmpi(&attr.value, noW))
1939 entity->u.class.versioned = FALSE;
1940 else if (!xmlstr_cmpi(&attr.value, yesW))
1941 set_error( xmlbuf );
1943 else if (!is_xmlns_attr( &attr ))
1945 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1949 if (end) return;
1951 if (!parse_text_content(xmlbuf, &content)) return;
1952 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
1954 acl->actctx->sections |= WINDOWCLASS_SECTION;
1956 while (next_xml_elem(xmlbuf, &elem, parent))
1958 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1959 parse_unknown_elem(xmlbuf, &elem);
1963 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1965 struct xml_attr attr;
1966 BOOL end = FALSE;
1968 while (next_xml_attr(xmlbuf, &attr, &end))
1970 if (xml_attr_cmp(&attr, oldVersionW))
1972 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1974 else if (xml_attr_cmp(&attr, newVersionW))
1976 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
1978 else if (!is_xmlns_attr( &attr ))
1980 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1984 if (!end) parse_expect_end_elem(xmlbuf, parent);
1987 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1989 struct xml_elem elem;
1990 struct xml_attr attr;
1991 xmlstr_t content;
1992 BOOL end = FALSE;
1994 while (next_xml_attr(xmlbuf, &attr, &end))
1996 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1999 if (end) return;
2000 if (!parse_text_content(xmlbuf, &content)) return;
2002 TRACE("Got description %s\n", debugstr_xmlstr(&content));
2004 while (next_xml_elem(xmlbuf, &elem, parent))
2006 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2007 parse_unknown_elem(xmlbuf, &elem);
2011 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2012 struct assembly* assembly,
2013 struct actctx_loader* acl,
2014 const struct xml_elem *parent)
2016 struct xml_attr attr;
2017 BOOL end = FALSE;
2018 struct entity* entity;
2020 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2022 set_error( xmlbuf );
2023 return;
2026 while (next_xml_attr(xmlbuf, &attr, &end))
2028 if (xml_attr_cmp(&attr, iidW))
2030 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2032 else if (xml_attr_cmp(&attr, nameW))
2034 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2036 else if (xml_attr_cmp(&attr, baseInterfaceW))
2038 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2039 entity->u.ifaceps.mask |= BaseIface;
2041 else if (xml_attr_cmp(&attr, nummethodsW))
2043 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2044 entity->u.ifaceps.mask |= NumMethods;
2046 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2048 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2050 else if (xml_attr_cmp(&attr, tlbidW))
2052 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2054 else if (!is_xmlns_attr( &attr ))
2056 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2060 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2061 if (!end) parse_expect_end_elem(xmlbuf, parent);
2064 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2065 struct actctx_loader *acl, const struct xml_elem *parent )
2068 struct xml_elem elem;
2069 struct xml_attr attr;
2070 BOOL end = FALSE;
2071 struct entity* entity;
2073 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2075 set_error( xmlbuf );
2076 return;
2079 while (next_xml_attr(xmlbuf, &attr, &end))
2081 if (xml_attr_cmp(&attr, nameW))
2083 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2085 else if (xml_attr_cmp(&attr, clsidW))
2087 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2089 else if (xml_attr_cmp(&attr, progidW))
2091 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2093 else if (xml_attr_cmp(&attr, tlbidW))
2095 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2097 else if (xml_attr_cmp(&attr, threadingmodelW))
2099 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2101 else if (xml_attr_cmp(&attr, runtimeVersionW))
2103 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2105 else if (!is_xmlns_attr( &attr ))
2107 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2111 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2112 if (entity->u.comclass.progid)
2113 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2114 if (end) return;
2116 while (next_xml_elem(xmlbuf, &elem, parent))
2118 if (xml_elem_cmp(&elem, progidW, asmv1W))
2120 parse_com_class_progid(xmlbuf, entity, &elem);
2122 else
2124 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2125 parse_unknown_elem(xmlbuf, &elem);
2129 if (entity->u.comclass.progids.num)
2130 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2133 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2134 struct actctx_loader *acl, const struct xml_elem *parent )
2136 struct xml_attr attr;
2137 BOOL end = FALSE;
2138 struct entity* entity;
2140 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2142 set_error( xmlbuf );
2143 return;
2146 while (next_xml_attr(xmlbuf, &attr, &end))
2148 if (xml_attr_cmp(&attr, nameW))
2150 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2152 else if (xml_attr_cmp(&attr, clsidW))
2154 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2156 else if (xml_attr_cmp(&attr, runtimeVersionW))
2158 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2160 else if (!is_xmlns_attr( &attr ))
2162 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2166 acl->actctx->sections |= CLRSURROGATES_SECTION;
2167 if (!end) parse_expect_end_elem(xmlbuf, parent);
2170 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2171 const struct xml_elem *parent, BOOL optional )
2173 struct xml_elem elem;
2174 struct xml_attr attr;
2175 struct assembly_identity ai;
2176 BOOL end = FALSE;
2178 memset(&ai, 0, sizeof(ai));
2179 ai.optional = optional;
2181 while (next_xml_attr(xmlbuf, &attr, &end))
2183 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2184 static const WCHAR trueW[] = {'t','r','u','e',0};
2186 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2187 ai.delayed = xmlstr_cmp(&attr.value, trueW);
2188 else if (!is_xmlns_attr( &attr ))
2189 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2192 if (end) return;
2194 while (next_xml_elem(xmlbuf, &elem, parent))
2196 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2198 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2199 /* store the newly found identity for later loading */
2200 TRACE( "adding name=%s version=%s arch=%s\n",
2201 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2202 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2204 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2206 parse_binding_redirect_elem(xmlbuf, &elem);
2208 else
2210 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2211 parse_unknown_elem(xmlbuf, &elem);
2216 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2217 const struct xml_elem *parent )
2220 struct xml_elem elem;
2221 struct xml_attr attr;
2222 BOOL end = FALSE, optional = FALSE;
2224 while (next_xml_attr(xmlbuf, &attr, &end))
2226 if (xml_attr_cmp(&attr, optionalW))
2228 optional = xmlstr_cmpi( &attr.value, yesW );
2229 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2231 else if (!is_xmlns_attr( &attr ))
2233 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2237 while (next_xml_elem(xmlbuf, &elem, parent))
2239 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2241 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2243 else
2245 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2246 parse_unknown_elem(xmlbuf, &elem);
2251 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2253 BOOL end = FALSE;
2255 parse_expect_no_attr(xmlbuf, &end);
2256 if (!end) parse_expect_end_elem(xmlbuf, parent);
2259 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2261 BOOL end = FALSE;
2263 parse_expect_no_attr(xmlbuf, &end);
2264 if (!end) parse_expect_end_elem(xmlbuf, parent);
2267 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2268 struct actctx_loader* acl, const struct xml_elem *parent )
2270 struct xml_elem elem;
2271 struct xml_attr attr;
2272 BOOL end = FALSE;
2273 struct dll_redirect* dll;
2275 if (!(dll = add_dll_redirect(assembly)))
2277 set_error( xmlbuf );
2278 return;
2281 while (next_xml_attr(xmlbuf, &attr, &end))
2283 if (xml_attr_cmp(&attr, nameW))
2285 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2286 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2288 else if (xml_attr_cmp(&attr, hashW))
2290 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2292 else if (xml_attr_cmp(&attr, hashalgW))
2294 static const WCHAR sha1W[] = {'S','H','A','1',0};
2295 if (!xmlstr_cmpi(&attr.value, sha1W))
2296 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2298 else if (!is_xmlns_attr( &attr ))
2300 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2304 if (!dll->name) set_error( xmlbuf );
2306 acl->actctx->sections |= DLLREDIRECT_SECTION;
2308 if (end) return;
2310 while (next_xml_elem(xmlbuf, &elem, parent))
2312 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2314 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2316 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2318 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2320 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2322 WARN("asmv2:hash (undocumented) not supported\n");
2323 parse_unknown_elem(xmlbuf, &elem);
2325 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2327 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2329 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2331 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2333 else
2335 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2336 parse_unknown_elem( xmlbuf, &elem );
2341 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2342 struct actctx_loader *acl, const struct xml_elem *parent )
2344 struct xml_attr attr;
2345 BOOL end = FALSE;
2347 while (next_xml_attr(xmlbuf, &attr, &end))
2349 if (xml_attr_cmp(&attr, IdW))
2351 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2352 UNICODE_STRING str;
2353 GUID compat_id;
2355 str.Buffer = (PWSTR)attr.value.ptr;
2356 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2357 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2359 if (!(compat = add_compat_context(assembly)))
2361 set_error( xmlbuf );
2362 return;
2364 compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2365 compat->Id = compat_id;
2367 else
2369 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2372 else if (!is_xmlns_attr( &attr ))
2374 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2378 if (!end) parse_expect_end_elem(xmlbuf, parent);
2381 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2382 struct actctx_loader* acl, const struct xml_elem *parent)
2384 struct xml_elem elem;
2386 while (next_xml_elem(xmlbuf, &elem, parent))
2388 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2390 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2392 else
2394 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2395 parse_unknown_elem(xmlbuf, &elem);
2400 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2401 struct actctx_loader* acl, const struct xml_elem *parent)
2403 struct xml_elem elem;
2405 while (next_xml_elem(xmlbuf, &elem, parent))
2407 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2409 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2411 else
2413 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2414 parse_unknown_elem(xmlbuf, &elem);
2419 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2420 struct xml_elem *parent )
2422 struct xml_elem elem;
2423 struct xml_attr attr;
2424 xmlstr_t content;
2425 BOOL end = FALSE;
2426 struct entity *entity;
2428 while (next_xml_attr( xmlbuf, &attr, &end ))
2430 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2433 if (end) return;
2435 if (!parse_text_content( xmlbuf, &content )) return;
2436 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2438 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2439 if (!entity)
2441 set_error( xmlbuf );
2442 return;
2444 entity->u.settings.name = xmlstrdupW( &parent->name );
2445 entity->u.settings.value = xmlstrdupW( &content );
2446 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2448 while (next_xml_elem(xmlbuf, &elem, parent))
2450 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2451 parse_unknown_elem( xmlbuf, &elem );
2455 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2456 struct actctx_loader *acl, const struct xml_elem *parent )
2458 struct xml_elem elem;
2460 while (next_xml_elem( xmlbuf, &elem, parent ))
2462 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2463 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2464 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2465 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2466 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2467 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2468 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2469 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2470 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2471 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2472 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2474 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2476 else
2478 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2479 parse_unknown_elem( xmlbuf, &elem );
2484 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2485 struct actctx_loader *acl, const struct xml_elem *parent )
2487 struct xml_elem elem;
2489 while (next_xml_elem( xmlbuf, &elem, parent ))
2491 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2493 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2495 else
2497 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2498 parse_unknown_elem( xmlbuf, &elem );
2503 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2504 struct actctx_loader *acl, const struct xml_elem *parent )
2506 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2507 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2508 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};
2509 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2510 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2511 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2512 static const WCHAR trueW[] = {'t','r','u','e',0};
2514 struct xml_elem elem;
2515 struct xml_attr attr;
2516 BOOL end = FALSE;
2518 /* Multiple requestedExecutionLevel elements are not supported. */
2519 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2521 while (next_xml_attr(xmlbuf, &attr, &end))
2523 if (xml_attr_cmp(&attr, levelW))
2525 if (xmlstr_cmpi(&attr.value, asInvokerW))
2526 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2527 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2528 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2529 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2530 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2531 else
2532 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2534 else if (xml_attr_cmp(&attr, uiAccessW))
2536 if (xmlstr_cmpi(&attr.value, falseW))
2537 assembly->ui_access = FALSE;
2538 else if (xmlstr_cmpi(&attr.value, trueW))
2539 assembly->ui_access = TRUE;
2540 else
2541 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2543 else if (!is_xmlns_attr( &attr ))
2544 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2547 if (end) return;
2549 while (next_xml_elem(xmlbuf, &elem, parent))
2551 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2552 parse_unknown_elem(xmlbuf, &elem);
2556 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2557 struct actctx_loader *acl, const struct xml_elem *parent )
2559 struct xml_elem elem;
2561 while (next_xml_elem(xmlbuf, &elem, parent))
2563 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2565 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2567 else
2569 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2570 parse_unknown_elem(xmlbuf, &elem);
2575 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2576 struct actctx_loader *acl, const struct xml_elem *parent )
2578 struct xml_elem elem;
2580 while (next_xml_elem(xmlbuf, &elem, parent))
2582 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2584 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2586 else
2588 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2589 parse_unknown_elem(xmlbuf, &elem);
2594 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2595 struct actctx_loader *acl, const struct xml_elem *parent )
2597 struct xml_elem elem;
2599 while (next_xml_elem(xmlbuf, &elem, parent))
2601 if (xml_elem_cmp(&elem, securityW, asmv1W))
2603 parse_security_elem(xmlbuf, assembly, acl, &elem);
2605 else
2607 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2608 parse_unknown_elem(xmlbuf, &elem);
2613 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2614 struct actctx_loader* acl, const struct xml_elem *parent,
2615 struct assembly_identity* expected_ai)
2617 struct xml_elem elem;
2618 struct xml_attr attr;
2619 BOOL end = FALSE, version = FALSE;
2621 TRACE("(%p)\n", xmlbuf);
2623 while (next_xml_attr(xmlbuf, &attr, &end))
2625 if (xml_attr_cmp(&attr, manifestVersionW))
2627 static const WCHAR v10W[] = {'1','.','0',0};
2628 if (!xmlstr_cmp(&attr.value, v10W))
2630 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2631 break;
2633 version = TRUE;
2635 else if (!is_xmlns_attr( &attr ))
2637 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2641 if (end || !version)
2643 set_error( xmlbuf );
2644 return;
2647 while (next_xml_elem(xmlbuf, &elem, parent))
2649 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2651 parse_noinherit_elem(xmlbuf, &elem);
2652 assembly->no_inherit = TRUE;
2654 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2656 parse_noinheritable_elem(xmlbuf, &elem);
2658 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2660 parse_description_elem(xmlbuf, &elem);
2662 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2664 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2666 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2668 parse_dependency_elem(xmlbuf, acl, &elem);
2670 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2672 parse_file_elem(xmlbuf, assembly, acl, &elem);
2674 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2676 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2678 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2680 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2682 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2684 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2686 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2688 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2690 if (!xmlbuf->error && expected_ai)
2692 /* FIXME: more tests */
2693 if (assembly->type == ASSEMBLY_MANIFEST &&
2694 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2696 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2697 expected_ai->version.major, expected_ai->version.minor,
2698 expected_ai->version.build, expected_ai->version.revision,
2699 assembly->id.version.major, assembly->id.version.minor,
2700 assembly->id.version.build, assembly->id.version.revision);
2701 set_error( xmlbuf );
2703 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2704 (assembly->id.version.major != expected_ai->version.major ||
2705 assembly->id.version.minor != expected_ai->version.minor ||
2706 assembly->id.version.build < expected_ai->version.build ||
2707 (assembly->id.version.build == expected_ai->version.build &&
2708 assembly->id.version.revision < expected_ai->version.revision)))
2710 FIXME("wrong version for shared assembly manifest\n");
2711 set_error( xmlbuf );
2715 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2717 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2719 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2721 parse_application_elem(xmlbuf, assembly, acl, &elem);
2723 else
2725 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2726 parse_unknown_elem(xmlbuf, &elem);
2730 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2731 assembly->no_inherit)
2733 set_error( xmlbuf );
2737 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2738 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2740 struct xml_elem elem;
2741 struct xml_elem parent = {};
2743 xmlbuf->error = FALSE;
2744 xmlbuf->ns_pos = 0;
2746 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2748 if (xmlstr_cmp(&elem.name, xmlW) &&
2749 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2750 return STATUS_SXS_CANT_GEN_ACTCTX;
2752 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2754 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2755 return STATUS_SXS_CANT_GEN_ACTCTX;
2758 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2759 if (xmlbuf->error)
2761 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2762 return STATUS_SXS_CANT_GEN_ACTCTX;
2765 if (next_xml_elem(xmlbuf, &elem, &parent))
2767 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2768 return STATUS_SXS_CANT_GEN_ACTCTX;
2771 if (xmlbuf->ptr != xmlbuf->end)
2773 FIXME("parse error\n");
2774 return STATUS_SXS_CANT_GEN_ACTCTX;
2776 return STATUS_SUCCESS;
2779 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2780 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2781 const void *buffer, SIZE_T size )
2783 xmlbuf_t xmlbuf;
2784 NTSTATUS status;
2785 struct assembly *assembly;
2786 int unicode_tests;
2788 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2790 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2791 return STATUS_SXS_CANT_GEN_ACTCTX;
2793 if (directory && !(assembly->directory = strdupW(directory)))
2794 return STATUS_NO_MEMORY;
2796 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2797 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2798 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2800 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2801 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2803 xmlbuf.ptr = buffer;
2804 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2805 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2807 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2809 const WCHAR *buf = buffer;
2810 WCHAR *new_buff;
2811 unsigned int i;
2813 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2814 return STATUS_NO_MEMORY;
2815 for (i = 0; i < size / sizeof(WCHAR); i++)
2816 new_buff[i] = RtlUshortByteSwap( buf[i] );
2817 xmlbuf.ptr = new_buff;
2818 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2819 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2820 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2822 else
2824 /* let's assume utf-8 for now */
2825 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2826 WCHAR *new_buff;
2828 if (len == -1)
2830 FIXME( "utf-8 conversion failed\n" );
2831 return STATUS_SXS_CANT_GEN_ACTCTX;
2833 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2834 return STATUS_NO_MEMORY;
2835 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2836 xmlbuf.ptr = new_buff;
2837 xmlbuf.end = xmlbuf.ptr + len;
2838 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2839 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2841 return status;
2844 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2846 OBJECT_ATTRIBUTES attr;
2847 IO_STATUS_BLOCK io;
2849 attr.Length = sizeof(attr);
2850 attr.RootDirectory = 0;
2851 attr.Attributes = OBJ_CASE_INSENSITIVE;
2852 attr.ObjectName = name;
2853 attr.SecurityDescriptor = NULL;
2854 attr.SecurityQualityOfService = NULL;
2855 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2858 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2860 NTSTATUS status;
2861 ULONG_PTR magic;
2862 LDR_MODULE *pldr;
2864 LdrLockLoaderLock(0, NULL, &magic);
2865 status = LdrFindEntryForAddress( module, &pldr );
2866 if (status == STATUS_SUCCESS)
2868 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2869 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2871 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2872 str->Length = pldr->FullDllName.Length;
2873 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2875 else status = STATUS_NO_MEMORY;
2877 LdrUnlockLoaderLock(0, magic);
2878 return status;
2881 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2882 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2883 HANDLE hModule, LPCWSTR resname, ULONG lang )
2885 NTSTATUS status;
2886 UNICODE_STRING nameW;
2887 LDR_RESOURCE_INFO info;
2888 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2889 void *ptr;
2891 if (TRACE_ON(actctx))
2893 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2895 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2896 hModule, debugstr_w(nameW.Buffer) );
2897 RtlFreeUnicodeString( &nameW );
2899 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2900 hModule, debugstr_w(filename) );
2903 if (!resname) return STATUS_INVALID_PARAMETER;
2905 info.Type = RT_MANIFEST;
2906 info.Language = lang;
2907 if (!((ULONG_PTR)resname >> 16))
2909 info.Name = (ULONG_PTR)resname;
2910 status = LdrFindResource_U(hModule, &info, 3, &entry);
2912 else if (resname[0] == '#')
2914 ULONG value;
2915 RtlInitUnicodeString(&nameW, resname + 1);
2916 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2917 return STATUS_INVALID_PARAMETER;
2918 info.Name = value;
2919 status = LdrFindResource_U(hModule, &info, 3, &entry);
2921 else
2923 RtlCreateUnicodeString(&nameW, resname);
2924 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2925 info.Name = (ULONG_PTR)nameW.Buffer;
2926 status = LdrFindResource_U(hModule, &info, 3, &entry);
2927 RtlFreeUnicodeString(&nameW);
2929 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2931 if (status == STATUS_SUCCESS)
2932 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2934 return status;
2937 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2938 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2939 HANDLE file, LPCWSTR resname, ULONG lang )
2941 HANDLE mapping;
2942 OBJECT_ATTRIBUTES attr;
2943 LARGE_INTEGER size;
2944 LARGE_INTEGER offset;
2945 NTSTATUS status;
2946 SIZE_T count;
2947 void *base;
2949 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2951 attr.Length = sizeof(attr);
2952 attr.RootDirectory = 0;
2953 attr.ObjectName = NULL;
2954 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2955 attr.SecurityDescriptor = NULL;
2956 attr.SecurityQualityOfService = NULL;
2958 size.QuadPart = 0;
2959 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2960 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2961 if (status != STATUS_SUCCESS) return status;
2963 offset.QuadPart = 0;
2964 count = 0;
2965 base = NULL;
2966 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2967 &count, ViewShare, 0, PAGE_READONLY );
2968 NtClose( mapping );
2969 if (status != STATUS_SUCCESS) return status;
2971 if (RtlImageNtHeader(base)) /* we got a PE file */
2973 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2974 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2976 else status = STATUS_INVALID_IMAGE_FORMAT;
2978 NtUnmapViewOfSection( GetCurrentProcess(), base );
2979 return status;
2982 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2983 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2985 FILE_END_OF_FILE_INFORMATION info;
2986 IO_STATUS_BLOCK io;
2987 HANDLE mapping;
2988 OBJECT_ATTRIBUTES attr;
2989 LARGE_INTEGER size;
2990 LARGE_INTEGER offset;
2991 NTSTATUS status;
2992 SIZE_T count;
2993 void *base;
2995 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2997 attr.Length = sizeof(attr);
2998 attr.RootDirectory = 0;
2999 attr.ObjectName = NULL;
3000 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3001 attr.SecurityDescriptor = NULL;
3002 attr.SecurityQualityOfService = NULL;
3004 size.QuadPart = 0;
3005 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3006 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3007 if (status != STATUS_SUCCESS) return status;
3009 offset.QuadPart = 0;
3010 count = 0;
3011 base = NULL;
3012 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3013 &count, ViewShare, 0, PAGE_READONLY );
3014 NtClose( mapping );
3015 if (status != STATUS_SUCCESS) return status;
3017 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3018 if (status == STATUS_SUCCESS)
3019 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
3021 NtUnmapViewOfSection( GetCurrentProcess(), base );
3022 return status;
3025 /* try to load the .manifest file associated to the file */
3026 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3027 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3029 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3030 WCHAR *buffer;
3031 NTSTATUS status;
3032 UNICODE_STRING nameW;
3033 HANDLE file;
3034 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3036 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3038 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3040 if (module) /* use the module filename */
3042 UNICODE_STRING name;
3044 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3046 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3047 strcatW( name.Buffer, dotManifestW );
3048 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3049 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3050 RtlFreeUnicodeString( &name );
3052 if (status) return status;
3054 else
3056 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3057 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3058 return STATUS_NO_MEMORY;
3059 strcpyW( buffer, filename );
3060 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3061 strcatW( buffer, dotManifestW );
3062 RtlInitUnicodeString( &nameW, buffer );
3065 if (!open_nt_file( &file, &nameW ))
3067 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3068 NtClose( file );
3070 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3071 RtlFreeUnicodeString( &nameW );
3072 return status;
3075 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3077 static const WCHAR lookup_fmtW[] =
3078 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3079 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3080 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3082 WCHAR *lookup, *ret = NULL;
3083 UNICODE_STRING lookup_us;
3084 IO_STATUS_BLOCK io;
3085 const WCHAR *lang = ai->language;
3086 unsigned int data_pos = 0, data_len;
3087 char buffer[8192];
3089 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3090 (strlenW(ai->arch) + strlenW(ai->name)
3091 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
3092 + sizeof(lookup_fmtW) )))
3093 return NULL;
3095 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3096 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3097 ai->version.major, ai->version.minor, lang );
3098 RtlInitUnicodeString( &lookup_us, lookup );
3100 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3101 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3103 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3104 FILE_BOTH_DIR_INFORMATION *dir_info;
3105 WCHAR *tmp;
3106 ULONG build, revision;
3108 data_len = io.Information;
3110 for (;;)
3112 if (data_pos >= data_len)
3114 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3115 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3116 break;
3117 data_len = io.Information;
3118 data_pos = 0;
3120 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3122 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3123 else data_pos = data_len;
3125 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
3126 build = atoiW(tmp);
3127 if (build < min_build) continue;
3128 tmp = strchrW(tmp, '.') + 1;
3129 revision = atoiW(tmp);
3130 if (build == min_build && revision < min_revision) continue;
3131 tmp = strchrW(tmp, '_') + 1;
3132 tmp = strchrW(tmp, '_') + 1;
3133 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3134 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3136 /* prefer a non-Wine manifest if we already have one */
3137 /* we'll still load the builtin dll if specified through DllOverrides */
3138 if (ret) continue;
3140 else
3142 min_build = build;
3143 min_revision = revision;
3145 ai->version.build = build;
3146 ai->version.revision = revision;
3147 RtlFreeHeap( GetProcessHeap(), 0, ret );
3148 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3150 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3151 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3155 else WARN("no matching file for %s\n", debugstr_w(lookup));
3156 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3157 return ret;
3160 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3162 struct assembly_identity sxs_ai;
3163 UNICODE_STRING path_us;
3164 OBJECT_ATTRIBUTES attr;
3165 IO_STATUS_BLOCK io;
3166 WCHAR *path, *file = NULL;
3167 HANDLE handle;
3169 static const WCHAR manifest_dirW[] =
3170 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3172 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3174 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3175 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3176 return STATUS_NO_MEMORY;
3178 strcpyW( path, user_shared_data->NtSystemRoot );
3179 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3181 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3183 RtlFreeHeap( GetProcessHeap(), 0, path );
3184 return STATUS_NO_SUCH_FILE;
3186 RtlFreeHeap( GetProcessHeap(), 0, path );
3188 attr.Length = sizeof(attr);
3189 attr.RootDirectory = 0;
3190 attr.Attributes = OBJ_CASE_INSENSITIVE;
3191 attr.ObjectName = &path_us;
3192 attr.SecurityDescriptor = NULL;
3193 attr.SecurityQualityOfService = NULL;
3195 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3196 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3198 sxs_ai = *ai;
3199 file = lookup_manifest_file( handle, &sxs_ai );
3200 NtClose( handle );
3202 if (!file)
3204 RtlFreeUnicodeString( &path_us );
3205 return STATUS_NO_SUCH_FILE;
3208 /* append file name to directory path */
3209 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3210 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3212 RtlFreeHeap( GetProcessHeap(), 0, file );
3213 RtlFreeUnicodeString( &path_us );
3214 return STATUS_NO_MEMORY;
3217 path[path_us.Length/sizeof(WCHAR)] = '\\';
3218 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3219 RtlInitUnicodeString( &path_us, path );
3220 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3222 if (!open_nt_file( &handle, &path_us ))
3224 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3225 NtClose( handle );
3227 else io.u.Status = STATUS_NO_SUCH_FILE;
3229 RtlFreeHeap( GetProcessHeap(), 0, file );
3230 RtlFreeUnicodeString( &path_us );
3231 return io.u.Status;
3234 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3235 struct assembly_identity* ai)
3237 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3238 unsigned int i;
3239 WCHAR *buffer, *p, *directory;
3240 NTSTATUS status;
3241 UNICODE_STRING nameW;
3242 HANDLE file;
3243 DWORD len;
3245 TRACE( "looking for name=%s version=%s arch=%s\n",
3246 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3248 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3250 /* FIXME: add support for language specific lookup */
3252 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3253 strlenW(acl->actctx->appdir.info));
3255 nameW.Buffer = NULL;
3256 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3257 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3258 return STATUS_NO_MEMORY;
3260 if (!(directory = build_assembly_dir( ai )))
3262 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3263 return STATUS_NO_MEMORY;
3266 /* Lookup in <dir>\name.dll
3267 * <dir>\name.manifest
3268 * <dir>\name\name.dll
3269 * <dir>\name\name.manifest
3271 * First 'appdir' is used as <dir>, if that failed
3272 * it tries application manifest file path.
3274 strcpyW( buffer, acl->actctx->appdir.info );
3275 p = buffer + strlenW(buffer);
3276 for (i = 0; i < 4; i++)
3278 if (i == 2)
3280 struct assembly *assembly = acl->actctx->assemblies;
3281 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3283 else *p++ = '\\';
3285 strcpyW( p, ai->name );
3286 p += strlenW(p);
3288 strcpyW( p, dotDllW );
3289 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3291 status = open_nt_file( &file, &nameW );
3292 if (!status)
3294 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3295 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3296 NtClose( file );
3297 break;
3299 RtlFreeUnicodeString( &nameW );
3302 strcpyW( p, dotManifestW );
3303 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3305 status = open_nt_file( &file, &nameW );
3306 if (!status)
3308 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3309 NtClose( file );
3310 break;
3312 RtlFreeUnicodeString( &nameW );
3314 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3316 RtlFreeUnicodeString( &nameW );
3317 RtlFreeHeap( GetProcessHeap(), 0, directory );
3318 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3319 return status;
3322 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3324 NTSTATUS status = STATUS_SUCCESS;
3325 unsigned int i;
3327 for (i = 0; i < acl->num_dependencies; i++)
3329 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3331 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3333 FIXME( "Could not find dependent assembly %s (%s)\n",
3334 debugstr_w(acl->dependencies[i].name),
3335 debugstr_version(&acl->dependencies[i].version) );
3336 status = STATUS_SXS_CANT_GEN_ACTCTX;
3337 break;
3341 /* FIXME should now iterate through all refs */
3342 return status;
3345 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3346 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3348 NTSTATUS status = STATUS_SUCCESS;
3350 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3352 if (*handle) return STATUS_INVALID_PARAMETER;
3354 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3355 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3357 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3359 ULONG_PTR magic;
3360 LDR_MODULE *pldr;
3362 if (!*handle) return STATUS_INVALID_PARAMETER;
3364 LdrLockLoaderLock( 0, NULL, &magic );
3365 if (!LdrFindEntryForAddress( *handle, &pldr ))
3367 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3368 status = STATUS_DLL_NOT_FOUND;
3369 else
3370 *handle = pldr->ActivationContext;
3372 else status = STATUS_DLL_NOT_FOUND;
3373 LdrUnlockLoaderLock( 0, magic );
3375 else if (!*handle && (class != ActivationContextBasicInformation))
3376 *handle = process_actctx;
3378 return status;
3381 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3383 unsigned int i, j, total_len = 0, dll_count = 0;
3384 struct strsection_header *header;
3385 struct dllredirect_data *data;
3386 struct string_index *index;
3387 ULONG name_offset;
3389 /* compute section length */
3390 for (i = 0; i < actctx->num_assemblies; i++)
3392 struct assembly *assembly = &actctx->assemblies[i];
3393 for (j = 0; j < assembly->num_dlls; j++)
3395 struct dll_redirect *dll = &assembly->dlls[j];
3397 /* each entry needs index, data and string data */
3398 total_len += sizeof(*index);
3399 total_len += sizeof(*data);
3400 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3403 dll_count += assembly->num_dlls;
3406 total_len += sizeof(*header);
3408 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3409 if (!header) return STATUS_NO_MEMORY;
3411 memset(header, 0, sizeof(*header));
3412 header->magic = STRSECTION_MAGIC;
3413 header->size = sizeof(*header);
3414 header->count = dll_count;
3415 header->index_offset = sizeof(*header);
3416 index = (struct string_index*)((BYTE*)header + header->index_offset);
3417 name_offset = header->index_offset + header->count*sizeof(*index);
3419 for (i = 0; i < actctx->num_assemblies; i++)
3421 struct assembly *assembly = &actctx->assemblies[i];
3422 for (j = 0; j < assembly->num_dlls; j++)
3424 struct dll_redirect *dll = &assembly->dlls[j];
3425 UNICODE_STRING str;
3426 WCHAR *ptrW;
3428 /* setup new index entry */
3429 str.Buffer = dll->name;
3430 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3431 str.MaximumLength = str.Length + sizeof(WCHAR);
3432 /* hash original class name */
3433 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3435 index->name_offset = name_offset;
3436 index->name_len = str.Length;
3437 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3438 index->data_len = sizeof(*data);
3439 index->rosterindex = i + 1;
3441 /* setup data */
3442 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3443 data->size = sizeof(*data);
3444 data->unk = 2; /* FIXME: seems to be constant */
3445 memset(data->res, 0, sizeof(data->res));
3447 /* dll name */
3448 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3449 memcpy(ptrW, dll->name, index->name_len);
3450 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3452 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3454 index++;
3458 *section = header;
3460 return STATUS_SUCCESS;
3463 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3465 struct string_index *iter, *index = NULL;
3466 ULONG hash = 0, i;
3468 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3469 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3471 for (i = 0; i < section->count; i++)
3473 if (iter->hash == hash)
3475 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3477 if (!strcmpiW(nameW, name->Buffer))
3479 index = iter;
3480 break;
3482 else
3483 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3485 iter++;
3488 return index;
3491 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3493 struct guid_index *iter, *index = NULL;
3494 ULONG i;
3496 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3498 for (i = 0; i < section->count; i++)
3500 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3502 index = iter;
3503 break;
3505 iter++;
3508 return index;
3511 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3513 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3516 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3517 PACTCTX_SECTION_KEYED_DATA data)
3519 struct dllredirect_data *dll;
3520 struct string_index *index;
3522 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3524 if (!actctx->dllredirect_section)
3526 struct strsection_header *section;
3528 NTSTATUS status = build_dllredirect_section(actctx, &section);
3529 if (status) return status;
3531 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3532 RtlFreeHeap(GetProcessHeap(), 0, section);
3535 index = find_string_index(actctx->dllredirect_section, name);
3536 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3538 if (data)
3540 dll = get_dllredirect_data(actctx, index);
3542 data->ulDataFormatVersion = 1;
3543 data->lpData = dll;
3544 data->ulLength = dll->size;
3545 data->lpSectionGlobalData = NULL;
3546 data->ulSectionGlobalDataLength = 0;
3547 data->lpSectionBase = actctx->dllredirect_section;
3548 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3549 data->hActCtx = NULL;
3551 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3552 data->ulAssemblyRosterIndex = index->rosterindex;
3555 return STATUS_SUCCESS;
3558 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3560 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3563 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3565 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3568 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3570 unsigned int i, j, k, total_len = 0, class_count = 0;
3571 struct wndclass_redirect_data *data;
3572 struct strsection_header *header;
3573 struct string_index *index;
3574 ULONG name_offset;
3576 /* compute section length */
3577 for (i = 0; i < actctx->num_assemblies; i++)
3579 struct assembly *assembly = &actctx->assemblies[i];
3580 for (j = 0; j < assembly->num_dlls; j++)
3582 struct dll_redirect *dll = &assembly->dlls[j];
3583 for (k = 0; k < dll->entities.num; k++)
3585 struct entity *entity = &dll->entities.base[k];
3586 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3588 int class_len = strlenW(entity->u.class.name) + 1;
3589 int len;
3591 /* each class entry needs index, data and string data */
3592 total_len += sizeof(*index);
3593 total_len += sizeof(*data);
3594 /* original name is stored separately */
3595 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3596 /* versioned name and module name are stored one after another */
3597 if (entity->u.class.versioned)
3598 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3599 else
3600 len = class_len;
3601 len += strlenW(dll->name) + 1;
3602 total_len += aligned_string_len(len*sizeof(WCHAR));
3604 class_count++;
3610 total_len += sizeof(*header);
3612 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3613 if (!header) return STATUS_NO_MEMORY;
3615 memset(header, 0, sizeof(*header));
3616 header->magic = STRSECTION_MAGIC;
3617 header->size = sizeof(*header);
3618 header->count = class_count;
3619 header->index_offset = sizeof(*header);
3620 index = (struct string_index*)((BYTE*)header + header->index_offset);
3621 name_offset = header->index_offset + header->count*sizeof(*index);
3623 for (i = 0; i < actctx->num_assemblies; i++)
3625 struct assembly *assembly = &actctx->assemblies[i];
3626 for (j = 0; j < assembly->num_dlls; j++)
3628 struct dll_redirect *dll = &assembly->dlls[j];
3629 for (k = 0; k < dll->entities.num; k++)
3631 struct entity *entity = &dll->entities.base[k];
3632 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3634 static const WCHAR exclW[] = {'!',0};
3635 ULONG versioned_len, module_len;
3636 UNICODE_STRING str;
3637 WCHAR *ptrW;
3639 /* setup new index entry */
3640 str.Buffer = entity->u.class.name;
3641 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3642 str.MaximumLength = str.Length + sizeof(WCHAR);
3643 /* hash original class name */
3644 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3646 /* include '!' separator too */
3647 if (entity->u.class.versioned)
3648 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3649 else
3650 versioned_len = str.Length;
3651 module_len = strlenW(dll->name)*sizeof(WCHAR);
3653 index->name_offset = name_offset;
3654 index->name_len = str.Length;
3655 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3656 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3657 index->rosterindex = i + 1;
3659 /* setup data */
3660 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3661 data->size = sizeof(*data);
3662 data->res = 0;
3663 data->name_len = versioned_len;
3664 data->name_offset = sizeof(*data);
3665 data->module_len = module_len;
3666 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3668 /* original class name */
3669 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3670 memcpy(ptrW, entity->u.class.name, index->name_len);
3671 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3673 /* module name */
3674 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3675 memcpy(ptrW, dll->name, data->module_len);
3676 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3678 /* versioned name */
3679 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3680 if (entity->u.class.versioned)
3682 get_assembly_version(assembly, ptrW);
3683 strcatW(ptrW, exclW);
3684 strcatW(ptrW, entity->u.class.name);
3686 else
3688 memcpy(ptrW, entity->u.class.name, index->name_len);
3689 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3692 name_offset += sizeof(*data);
3693 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3695 index++;
3701 *section = header;
3703 return STATUS_SUCCESS;
3706 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3707 PACTCTX_SECTION_KEYED_DATA data)
3709 struct string_index *iter, *index = NULL;
3710 struct wndclass_redirect_data *class;
3711 ULONG hash;
3712 int i;
3714 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3716 if (!actctx->wndclass_section)
3718 struct strsection_header *section;
3720 NTSTATUS status = build_wndclass_section(actctx, &section);
3721 if (status) return status;
3723 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3724 RtlFreeHeap(GetProcessHeap(), 0, section);
3727 hash = 0;
3728 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3729 iter = get_wndclass_first_index(actctx);
3731 for (i = 0; i < actctx->wndclass_section->count; i++)
3733 if (iter->hash == hash)
3735 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3737 if (!strcmpiW(nameW, name->Buffer))
3739 index = iter;
3740 break;
3742 else
3743 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3745 iter++;
3748 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3750 if (data)
3752 class = get_wndclass_data(actctx, index);
3754 data->ulDataFormatVersion = 1;
3755 data->lpData = class;
3756 /* full length includes string length with nulls */
3757 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3758 data->lpSectionGlobalData = NULL;
3759 data->ulSectionGlobalDataLength = 0;
3760 data->lpSectionBase = actctx->wndclass_section;
3761 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3762 data->hActCtx = NULL;
3764 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3765 data->ulAssemblyRosterIndex = index->rosterindex;
3768 return STATUS_SUCCESS;
3771 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3773 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3774 struct guidsection_header *header;
3775 ULONG module_offset, data_offset;
3776 struct tlibredirect_data *data;
3777 struct guid_index *index;
3779 /* compute section length */
3780 for (i = 0; i < actctx->num_assemblies; i++)
3782 struct assembly *assembly = &actctx->assemblies[i];
3783 for (j = 0; j < assembly->num_dlls; j++)
3785 struct dll_redirect *dll = &assembly->dlls[j];
3786 for (k = 0; k < dll->entities.num; k++)
3788 struct entity *entity = &dll->entities.base[k];
3789 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3791 /* each entry needs index, data and string data for module name and help string */
3792 total_len += sizeof(*index);
3793 total_len += sizeof(*data);
3794 /* help string is stored separately */
3795 if (*entity->u.typelib.helpdir)
3796 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3798 /* module names are packed one after another */
3799 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3801 tlib_count++;
3807 total_len += aligned_string_len(names_len);
3808 total_len += sizeof(*header);
3810 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3811 if (!header) return STATUS_NO_MEMORY;
3813 memset(header, 0, sizeof(*header));
3814 header->magic = GUIDSECTION_MAGIC;
3815 header->size = sizeof(*header);
3816 header->count = tlib_count;
3817 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3818 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3819 module_offset = sizeof(*header);
3820 data_offset = header->index_offset + tlib_count*sizeof(*index);
3822 for (i = 0; i < actctx->num_assemblies; i++)
3824 struct assembly *assembly = &actctx->assemblies[i];
3825 for (j = 0; j < assembly->num_dlls; j++)
3827 struct dll_redirect *dll = &assembly->dlls[j];
3828 for (k = 0; k < dll->entities.num; k++)
3830 struct entity *entity = &dll->entities.base[k];
3831 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3833 ULONG module_len, help_len;
3834 UNICODE_STRING str;
3835 WCHAR *ptrW;
3837 if (*entity->u.typelib.helpdir)
3838 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3839 else
3840 help_len = 0;
3842 module_len = strlenW(dll->name)*sizeof(WCHAR);
3844 /* setup new index entry */
3845 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3846 RtlGUIDFromString(&str, &index->guid);
3847 index->data_offset = data_offset;
3848 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3849 index->rosterindex = i + 1;
3851 /* setup data */
3852 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3853 data->size = sizeof(*data);
3854 data->res = 0;
3855 data->name_len = module_len;
3856 data->name_offset = module_offset;
3857 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3858 data->langid = 0;
3859 data->flags = entity->u.typelib.flags;
3860 data->help_len = help_len;
3861 data->help_offset = sizeof(*data);
3862 data->major_version = entity->u.typelib.major;
3863 data->minor_version = entity->u.typelib.minor;
3865 /* module name */
3866 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3867 memcpy(ptrW, dll->name, data->name_len);
3868 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3870 /* help string */
3871 if (data->help_len)
3873 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3874 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3875 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3878 data_offset += sizeof(*data);
3879 if (help_len)
3880 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3882 module_offset += module_len + sizeof(WCHAR);
3884 index++;
3890 *section = header;
3892 return STATUS_SUCCESS;
3895 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3897 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3900 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3902 struct guid_index *index = NULL;
3903 struct tlibredirect_data *tlib;
3905 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3907 if (!actctx->tlib_section)
3909 struct guidsection_header *section;
3911 NTSTATUS status = build_tlib_section(actctx, &section);
3912 if (status) return status;
3914 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3915 RtlFreeHeap(GetProcessHeap(), 0, section);
3918 index = find_guid_index(actctx->tlib_section, guid);
3919 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3921 tlib = get_tlib_data(actctx, index);
3923 data->ulDataFormatVersion = 1;
3924 data->lpData = tlib;
3925 /* full length includes string length with nulls */
3926 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3927 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3928 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3929 data->lpSectionBase = actctx->tlib_section;
3930 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3931 data->hActCtx = NULL;
3933 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3934 data->ulAssemblyRosterIndex = index->rosterindex;
3936 return STATUS_SUCCESS;
3939 static void generate_uuid(ULONG *seed, GUID *guid)
3941 ULONG *ptr = (ULONG*)guid;
3942 int i;
3944 /* GUID is 16 bytes long */
3945 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3946 *ptr = RtlUniform(seed);
3948 guid->Data3 &= 0x0fff;
3949 guid->Data3 |= (4 << 12);
3950 guid->Data4[0] &= 0x3f;
3951 guid->Data4[0] |= 0x80;
3954 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3955 unsigned int *count, unsigned int *len, unsigned int *module_len)
3957 unsigned int i;
3959 for (i = 0; i < entities->num; i++)
3961 struct entity *entity = &entities->base[i];
3962 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3964 /* each entry needs two index entries, extra one goes for alias GUID */
3965 *len += 2*sizeof(struct guid_index);
3966 /* To save some memory we don't allocated two data structures,
3967 instead alias index and normal index point to the same data structure. */
3968 *len += sizeof(struct comclassredirect_data);
3970 /* for clrClass store some more */
3971 if (entity->u.comclass.name)
3973 unsigned int str_len;
3975 /* all string data is stored together in aligned block */
3976 str_len = strlenW(entity->u.comclass.name)+1;
3977 if (entity->u.comclass.progid)
3978 str_len += strlenW(entity->u.comclass.progid)+1;
3979 if (entity->u.comclass.version)
3980 str_len += strlenW(entity->u.comclass.version)+1;
3982 *len += sizeof(struct clrclass_data);
3983 *len += aligned_string_len(str_len*sizeof(WCHAR));
3985 /* module name is forced to mscoree.dll, and stored two times with different case */
3986 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3988 else
3990 /* progid string is stored separately */
3991 if (entity->u.comclass.progid)
3992 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3994 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3997 *count += 1;
4002 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4003 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4004 ULONG *seed, ULONG rosterindex)
4006 unsigned int i;
4008 for (i = 0; i < entities->num; i++)
4010 struct entity *entity = &entities->base[i];
4011 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4013 ULONG module_len, progid_len, str_len = 0;
4014 struct comclassredirect_data *data;
4015 struct guid_index *alias_index;
4016 struct clrclass_data *clrdata;
4017 UNICODE_STRING str;
4018 WCHAR *ptrW;
4020 if (entity->u.comclass.progid)
4021 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4022 else
4023 progid_len = 0;
4025 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4027 /* setup new index entry */
4028 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4029 RtlGUIDFromString(&str, &(*index)->guid);
4031 (*index)->data_offset = *data_offset;
4032 (*index)->data_len = sizeof(*data); /* additional length added later */
4033 (*index)->rosterindex = rosterindex;
4035 /* Setup new index entry for alias guid. Alias index records are placed after
4036 normal records, so normal guids are hit first on search. Note that class count
4037 is doubled. */
4038 alias_index = (*index) + section->count/2;
4039 generate_uuid(seed, &alias_index->guid);
4040 alias_index->data_offset = (*index)->data_offset;
4041 alias_index->data_len = 0;
4042 alias_index->rosterindex = (*index)->rosterindex;
4044 /* setup data */
4045 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4046 data->size = sizeof(*data);
4047 data->res = 0;
4048 data->res1[0] = 0;
4049 data->res1[1] = 0;
4050 data->model = entity->u.comclass.model;
4051 data->clsid = (*index)->guid;
4052 data->alias = alias_index->guid;
4053 data->clsid2 = data->clsid;
4054 if (entity->u.comclass.tlbid)
4056 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4057 RtlGUIDFromString(&str, &data->tlbid);
4059 else
4060 memset(&data->tlbid, 0, sizeof(data->tlbid));
4061 data->name_len = module_len;
4062 data->name_offset = *module_offset;
4063 data->progid_len = progid_len;
4064 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4065 data->clrdata_len = 0; /* will be set later */
4066 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4067 data->miscstatus = entity->u.comclass.miscstatus;
4068 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4069 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4070 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4071 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4073 /* mask describes which misc* data is available */
4074 data->miscmask = 0;
4075 if (data->miscstatus)
4076 data->miscmask |= MiscStatus;
4077 if (data->miscstatuscontent)
4078 data->miscmask |= MiscStatusContent;
4079 if (data->miscstatusthumbnail)
4080 data->miscmask |= MiscStatusThumbnail;
4081 if (data->miscstatusicon)
4082 data->miscmask |= MiscStatusIcon;
4083 if (data->miscstatusdocprint)
4084 data->miscmask |= MiscStatusDocPrint;
4086 if (data->clrdata_offset)
4088 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4090 clrdata->size = sizeof(*clrdata);
4091 clrdata->res[0] = 0;
4092 clrdata->res[1] = 2; /* FIXME: unknown field */
4093 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4094 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4095 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4096 clrdata->name_offset = clrdata->size;
4097 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4098 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4099 clrdata->res2[0] = 0;
4100 clrdata->res2[1] = 0;
4102 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4104 /* module name */
4105 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4106 memcpy(ptrW, mscoree2W, clrdata->module_len);
4107 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4109 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4110 memcpy(ptrW, mscoreeW, data->name_len);
4111 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4113 /* class name */
4114 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4115 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4116 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4118 /* runtime version, optional */
4119 if (clrdata->version_len)
4121 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4123 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4124 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4125 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4128 if (data->progid_len)
4129 data->progid_offset += data->clrdata_len;
4130 (*index)->data_len += sizeof(*clrdata);
4132 else
4134 clrdata = NULL;
4136 /* module name */
4137 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4138 memcpy(ptrW, dll->name, data->name_len);
4139 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4142 /* progid string */
4143 if (data->progid_len)
4145 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4146 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4147 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4150 /* string block length */
4151 str_len = 0;
4152 if (clrdata)
4154 str_len += clrdata->name_len + sizeof(WCHAR);
4155 if (clrdata->version_len)
4156 str_len += clrdata->version_len + sizeof(WCHAR);
4158 if (progid_len)
4159 str_len += progid_len + sizeof(WCHAR);
4161 (*index)->data_len += aligned_string_len(str_len);
4162 alias_index->data_len = (*index)->data_len;
4164 /* move to next data record */
4165 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4166 (*module_offset) += module_len + sizeof(WCHAR);
4168 if (clrdata)
4170 (*data_offset) += sizeof(*clrdata);
4171 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4173 (*index) += 1;
4178 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4180 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4181 struct guidsection_header *header;
4182 ULONG module_offset, data_offset;
4183 struct guid_index *index;
4184 ULONG seed;
4186 /* compute section length */
4187 for (i = 0; i < actctx->num_assemblies; i++)
4189 struct assembly *assembly = &actctx->assemblies[i];
4190 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4191 for (j = 0; j < assembly->num_dlls; j++)
4193 struct dll_redirect *dll = &assembly->dlls[j];
4194 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4198 total_len += aligned_string_len(names_len);
4199 total_len += sizeof(*header);
4201 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4202 if (!header) return STATUS_NO_MEMORY;
4204 memset(header, 0, sizeof(*header));
4205 header->magic = GUIDSECTION_MAGIC;
4206 header->size = sizeof(*header);
4207 header->count = 2*class_count;
4208 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4209 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4210 module_offset = sizeof(*header);
4211 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4213 seed = NtGetTickCount();
4214 for (i = 0; i < actctx->num_assemblies; i++)
4216 struct assembly *assembly = &actctx->assemblies[i];
4217 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4218 for (j = 0; j < assembly->num_dlls; j++)
4220 struct dll_redirect *dll = &assembly->dlls[j];
4221 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4225 *section = header;
4227 return STATUS_SUCCESS;
4230 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4232 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4235 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4237 struct comclassredirect_data *comclass;
4238 struct guid_index *index = NULL;
4240 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4242 if (!actctx->comserver_section)
4244 struct guidsection_header *section;
4246 NTSTATUS status = build_comserver_section(actctx, &section);
4247 if (status) return status;
4249 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4250 RtlFreeHeap(GetProcessHeap(), 0, section);
4253 index = find_guid_index(actctx->comserver_section, guid);
4254 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4256 comclass = get_comclass_data(actctx, index);
4258 data->ulDataFormatVersion = 1;
4259 data->lpData = comclass;
4260 /* full length includes string length with nulls */
4261 data->ulLength = comclass->size + comclass->clrdata_len;
4262 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4263 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4264 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4265 data->lpSectionBase = actctx->comserver_section;
4266 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4267 data->hActCtx = NULL;
4269 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4270 data->ulAssemblyRosterIndex = index->rosterindex;
4272 return STATUS_SUCCESS;
4275 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4277 unsigned int i;
4279 for (i = 0; i < entities->num; i++)
4281 struct entity *entity = &entities->base[i];
4282 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4284 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4285 if (entity->u.ifaceps.name)
4286 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4287 *count += 1;
4292 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4293 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4295 unsigned int i;
4297 for (i = 0; i < entities->num; i++)
4299 struct entity *entity = &entities->base[i];
4300 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4302 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4303 UNICODE_STRING str;
4304 ULONG name_len;
4306 if (entity->u.ifaceps.name)
4307 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4308 else
4309 name_len = 0;
4311 /* setup index */
4312 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4313 RtlGUIDFromString(&str, &(*index)->guid);
4314 (*index)->data_offset = *data_offset;
4315 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4316 (*index)->rosterindex = rosterindex;
4318 /* setup data record */
4319 data->size = sizeof(*data);
4320 data->mask = entity->u.ifaceps.mask;
4322 /* proxyStubClsid32 value is only stored for external PS,
4323 if set it's used as iid, otherwise 'iid' attribute value is used */
4324 if (entity->u.ifaceps.ps32)
4326 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4327 RtlGUIDFromString(&str, &data->iid);
4329 else
4330 data->iid = (*index)->guid;
4332 data->nummethods = entity->u.ifaceps.nummethods;
4334 if (entity->u.ifaceps.tlib)
4336 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4337 RtlGUIDFromString(&str, &data->tlbid);
4339 else
4340 memset(&data->tlbid, 0, sizeof(data->tlbid));
4342 if (entity->u.ifaceps.base)
4344 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4345 RtlGUIDFromString(&str, &data->base);
4347 else
4348 memset(&data->base, 0, sizeof(data->base));
4350 data->name_len = name_len;
4351 data->name_offset = data->name_len ? sizeof(*data) : 0;
4353 /* name string */
4354 if (data->name_len)
4356 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4357 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4358 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4361 /* move to next record */
4362 (*index) += 1;
4363 *data_offset += sizeof(*data);
4364 if (data->name_len)
4365 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4370 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4372 unsigned int i, j, total_len = 0, count = 0;
4373 struct guidsection_header *header;
4374 struct guid_index *index;
4375 ULONG data_offset;
4377 /* compute section length */
4378 for (i = 0; i < actctx->num_assemblies; i++)
4380 struct assembly *assembly = &actctx->assemblies[i];
4382 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4383 for (j = 0; j < assembly->num_dlls; j++)
4385 struct dll_redirect *dll = &assembly->dlls[j];
4386 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4390 total_len += sizeof(*header);
4392 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4393 if (!header) return STATUS_NO_MEMORY;
4395 memset(header, 0, sizeof(*header));
4396 header->magic = GUIDSECTION_MAGIC;
4397 header->size = sizeof(*header);
4398 header->count = count;
4399 header->index_offset = sizeof(*header);
4400 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4401 data_offset = header->index_offset + count*sizeof(*index);
4403 for (i = 0; i < actctx->num_assemblies; i++)
4405 struct assembly *assembly = &actctx->assemblies[i];
4407 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4408 for (j = 0; j < assembly->num_dlls; j++)
4410 struct dll_redirect *dll = &assembly->dlls[j];
4411 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4415 *section = header;
4417 return STATUS_SUCCESS;
4420 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4422 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4425 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4427 struct ifacepsredirect_data *iface;
4428 struct guid_index *index = NULL;
4430 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4432 if (!actctx->ifaceps_section)
4434 struct guidsection_header *section;
4436 NTSTATUS status = build_ifaceps_section(actctx, &section);
4437 if (status) return status;
4439 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4440 RtlFreeHeap(GetProcessHeap(), 0, section);
4443 index = find_guid_index(actctx->ifaceps_section, guid);
4444 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4446 iface = get_ifaceps_data(actctx, index);
4448 data->ulDataFormatVersion = 1;
4449 data->lpData = iface;
4450 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4451 data->lpSectionGlobalData = NULL;
4452 data->ulSectionGlobalDataLength = 0;
4453 data->lpSectionBase = actctx->ifaceps_section;
4454 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4455 data->hActCtx = NULL;
4457 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4458 data->ulAssemblyRosterIndex = index->rosterindex;
4460 return STATUS_SUCCESS;
4463 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4465 unsigned int i, j, total_len = 0, count = 0;
4466 struct guidsection_header *header;
4467 struct clrsurrogate_data *data;
4468 struct guid_index *index;
4469 ULONG data_offset;
4471 /* compute section length */
4472 for (i = 0; i < actctx->num_assemblies; i++)
4474 struct assembly *assembly = &actctx->assemblies[i];
4475 for (j = 0; j < assembly->entities.num; j++)
4477 struct entity *entity = &assembly->entities.base[j];
4478 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4480 ULONG len;
4482 total_len += sizeof(*index) + sizeof(*data);
4483 len = strlenW(entity->u.clrsurrogate.name) + 1;
4484 if (entity->u.clrsurrogate.version)
4485 len += strlenW(entity->u.clrsurrogate.version) + 1;
4486 total_len += aligned_string_len(len*sizeof(WCHAR));
4488 count++;
4493 total_len += sizeof(*header);
4495 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4496 if (!header) return STATUS_NO_MEMORY;
4498 memset(header, 0, sizeof(*header));
4499 header->magic = GUIDSECTION_MAGIC;
4500 header->size = sizeof(*header);
4501 header->count = count;
4502 header->index_offset = sizeof(*header);
4503 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4504 data_offset = header->index_offset + count*sizeof(*index);
4506 for (i = 0; i < actctx->num_assemblies; i++)
4508 struct assembly *assembly = &actctx->assemblies[i];
4509 for (j = 0; j < assembly->entities.num; j++)
4511 struct entity *entity = &assembly->entities.base[j];
4512 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4514 ULONG version_len, name_len;
4515 UNICODE_STRING str;
4516 WCHAR *ptrW;
4518 if (entity->u.clrsurrogate.version)
4519 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4520 else
4521 version_len = 0;
4522 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4524 /* setup new index entry */
4525 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4526 RtlGUIDFromString(&str, &index->guid);
4528 index->data_offset = data_offset;
4529 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4530 index->rosterindex = i + 1;
4532 /* setup data */
4533 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4534 data->size = sizeof(*data);
4535 data->res = 0;
4536 data->clsid = index->guid;
4537 data->version_offset = version_len ? data->size : 0;
4538 data->version_len = version_len;
4539 data->name_offset = data->size + version_len;
4540 if (version_len)
4541 data->name_offset += sizeof(WCHAR);
4542 data->name_len = name_len;
4544 /* surrogate name */
4545 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4546 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4547 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4549 /* runtime version */
4550 if (data->version_len)
4552 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4553 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4554 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4557 data_offset += index->data_offset;
4558 index++;
4563 *section = header;
4565 return STATUS_SUCCESS;
4568 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4570 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4573 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4575 struct clrsurrogate_data *surrogate;
4576 struct guid_index *index = NULL;
4578 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4580 if (!actctx->clrsurrogate_section)
4582 struct guidsection_header *section;
4584 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4585 if (status) return status;
4587 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4588 RtlFreeHeap(GetProcessHeap(), 0, section);
4591 index = find_guid_index(actctx->clrsurrogate_section, guid);
4592 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4594 surrogate = get_surrogate_data(actctx, index);
4596 data->ulDataFormatVersion = 1;
4597 data->lpData = surrogate;
4598 /* full length includes string length with nulls */
4599 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4600 if (surrogate->version_len)
4601 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4603 data->lpSectionGlobalData = NULL;
4604 data->ulSectionGlobalDataLength = 0;
4605 data->lpSectionBase = actctx->clrsurrogate_section;
4606 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4607 data->hActCtx = NULL;
4609 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4610 data->ulAssemblyRosterIndex = index->rosterindex;
4612 return STATUS_SUCCESS;
4615 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4617 unsigned int i, j, single_len;
4619 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4620 for (i = 0; i < entities->num; i++)
4622 struct entity *entity = &entities->base[i];
4623 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4625 if (entity->u.comclass.progid)
4627 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4628 *count += 1;
4631 for (j = 0; j < entity->u.comclass.progids.num; j++)
4632 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4634 *total_len += single_len*entity->u.comclass.progids.num;
4635 *count += entity->u.comclass.progids.num;
4640 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4641 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4643 struct progidredirect_data *data;
4644 UNICODE_STRING str;
4645 GUID *guid_ptr;
4646 WCHAR *ptrW;
4648 /* setup new index entry */
4650 /* hash progid name */
4651 RtlInitUnicodeString(&str, progid);
4652 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4654 (*index)->name_offset = *data_offset;
4655 (*index)->name_len = str.Length;
4656 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4657 (*index)->data_len = sizeof(*data);
4658 (*index)->rosterindex = rosterindex;
4660 *data_offset += aligned_string_len(str.MaximumLength);
4662 /* setup data structure */
4663 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4664 data->size = sizeof(*data);
4665 data->reserved = 0;
4666 data->clsid_offset = *global_offset;
4668 /* write progid string */
4669 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4670 memcpy(ptrW, progid, (*index)->name_len);
4671 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4673 /* write guid to global area */
4674 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4675 *guid_ptr = *alias;
4677 /* to next entry */
4678 *global_offset += sizeof(GUID);
4679 *data_offset += data->size;
4680 (*index) += 1;
4683 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4684 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4686 unsigned int i, j;
4688 for (i = 0; i < entities->num; i++)
4690 struct entity *entity = &entities->base[i];
4691 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4693 const struct progids *progids = &entity->u.comclass.progids;
4694 struct comclassredirect_data *comclass;
4695 struct guid_index *guid_index;
4696 UNICODE_STRING str;
4697 GUID clsid;
4699 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4700 RtlGUIDFromString(&str, &clsid);
4702 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4703 comclass = get_comclass_data(actctx, guid_index);
4705 if (entity->u.comclass.progid)
4706 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4707 index, data_offset, global_offset, rosterindex);
4709 for (j = 0; j < progids->num; j++)
4710 write_progid_record(section, progids->progids[j], &comclass->alias,
4711 index, data_offset, global_offset, rosterindex);
4716 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4718 unsigned int i, j, total_len = 0, count = 0;
4719 struct strsection_header *header;
4720 ULONG data_offset, global_offset;
4721 struct string_index *index;
4723 /* compute section length */
4724 for (i = 0; i < actctx->num_assemblies; i++)
4726 struct assembly *assembly = &actctx->assemblies[i];
4728 get_progid_datalen(&assembly->entities, &count, &total_len);
4729 for (j = 0; j < assembly->num_dlls; j++)
4731 struct dll_redirect *dll = &assembly->dlls[j];
4732 get_progid_datalen(&dll->entities, &count, &total_len);
4736 total_len += sizeof(*header);
4738 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4739 if (!header) return STATUS_NO_MEMORY;
4741 memset(header, 0, sizeof(*header));
4742 header->magic = STRSECTION_MAGIC;
4743 header->size = sizeof(*header);
4744 header->count = count;
4745 header->global_offset = header->size;
4746 header->global_len = count*sizeof(GUID);
4747 header->index_offset = header->size + header->global_len;
4749 index = (struct string_index*)((BYTE*)header + header->index_offset);
4750 data_offset = header->index_offset + count*sizeof(*index);
4751 global_offset = header->global_offset;
4753 for (i = 0; i < actctx->num_assemblies; i++)
4755 struct assembly *assembly = &actctx->assemblies[i];
4757 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4758 for (j = 0; j < assembly->num_dlls; j++)
4760 struct dll_redirect *dll = &assembly->dlls[j];
4761 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4765 *section = header;
4767 return STATUS_SUCCESS;
4770 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4772 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4775 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4776 PACTCTX_SECTION_KEYED_DATA data)
4778 struct progidredirect_data *progid;
4779 struct string_index *index;
4781 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4783 if (!actctx->comserver_section)
4785 struct guidsection_header *section;
4787 NTSTATUS status = build_comserver_section(actctx, &section);
4788 if (status) return status;
4790 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4791 RtlFreeHeap(GetProcessHeap(), 0, section);
4794 if (!actctx->progid_section)
4796 struct strsection_header *section;
4798 NTSTATUS status = build_progid_section(actctx, &section);
4799 if (status) return status;
4801 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4802 RtlFreeHeap(GetProcessHeap(), 0, section);
4805 index = find_string_index(actctx->progid_section, name);
4806 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4808 if (data)
4810 progid = get_progid_data(actctx, index);
4812 data->ulDataFormatVersion = 1;
4813 data->lpData = progid;
4814 data->ulLength = progid->size;
4815 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4816 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4817 data->lpSectionBase = actctx->progid_section;
4818 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4819 data->hActCtx = NULL;
4821 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4822 data->ulAssemblyRosterIndex = index->rosterindex;
4825 return STATUS_SUCCESS;
4828 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4829 const UNICODE_STRING *section_name,
4830 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4832 NTSTATUS status;
4834 switch (section_kind)
4836 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4837 status = find_dll_redirection(actctx, section_name, data);
4838 break;
4839 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4840 status = find_window_class(actctx, section_name, data);
4841 break;
4842 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4843 status = find_progid_redirection(actctx, section_name, data);
4844 break;
4845 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4846 FIXME("Unsupported yet section_kind %x\n", section_kind);
4847 return STATUS_SXS_SECTION_NOT_FOUND;
4848 default:
4849 WARN("Unknown section_kind %x\n", section_kind);
4850 return STATUS_SXS_SECTION_NOT_FOUND;
4853 if (status != STATUS_SUCCESS) return status;
4855 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4857 actctx_addref(actctx);
4858 data->hActCtx = actctx;
4860 return STATUS_SUCCESS;
4863 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4864 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4866 NTSTATUS status;
4868 switch (section_kind)
4870 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4871 status = find_tlib_redirection(actctx, guid, data);
4872 break;
4873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4874 status = find_comserver_redirection(actctx, guid, data);
4875 break;
4876 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4877 status = find_cominterface_redirection(actctx, guid, data);
4878 break;
4879 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4880 status = find_clr_surrogate(actctx, guid, data);
4881 break;
4882 default:
4883 WARN("Unknown section_kind %x\n", section_kind);
4884 return STATUS_SXS_SECTION_NOT_FOUND;
4887 if (status != STATUS_SUCCESS) return status;
4889 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4891 actctx_addref(actctx);
4892 data->hActCtx = actctx;
4894 return STATUS_SUCCESS;
4897 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4899 unsigned int i, j;
4901 for (i = 0; i < actctx->num_assemblies; i++)
4903 struct assembly *assembly = &actctx->assemblies[i];
4904 for (j = 0; j < assembly->entities.num; j++)
4906 struct entity *entity = &assembly->entities.base[j];
4907 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4908 !strcmpW( entity->u.settings.name, settings ) &&
4909 !strcmpW( entity->u.settings.ns, ns ))
4910 return entity->u.settings.value;
4913 return NULL;
4916 /* initialize the activation context for the current process */
4917 void actctx_init(void)
4919 ACTCTXW ctx;
4920 HANDLE handle;
4922 ctx.cbSize = sizeof(ctx);
4923 ctx.lpSource = NULL;
4924 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4925 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4926 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4928 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4932 /***********************************************************************
4933 * RtlCreateActivationContext (NTDLL.@)
4935 * Create an activation context.
4937 * FIXME: function signature/prototype is wrong
4939 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4941 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4942 const WCHAR *directory = NULL;
4943 ACTIVATION_CONTEXT *actctx;
4944 UNICODE_STRING nameW;
4945 ULONG lang = 0;
4946 NTSTATUS status = STATUS_NO_MEMORY;
4947 HANDLE file = 0;
4948 struct actctx_loader acl;
4950 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4952 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4953 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4954 return STATUS_INVALID_PARAMETER;
4956 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4957 return STATUS_NO_MEMORY;
4959 actctx->magic = ACTCTX_MAGIC;
4960 actctx->ref_count = 1;
4961 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4962 actctx->config.info = NULL;
4963 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4964 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4966 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4968 else
4970 UNICODE_STRING dir;
4971 WCHAR *p;
4972 HMODULE module;
4974 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4975 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4977 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4978 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4979 actctx->appdir.info = dir.Buffer;
4982 nameW.Buffer = NULL;
4984 /* open file only if it's going to be used */
4985 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4986 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4988 WCHAR *source = NULL;
4989 BOOLEAN ret;
4991 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4992 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4994 DWORD dir_len, source_len;
4996 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4997 source_len = strlenW(pActCtx->lpSource);
4998 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5000 status = STATUS_NO_MEMORY;
5001 goto error;
5004 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5005 source[dir_len] = '\\';
5006 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5009 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5010 RtlFreeHeap( GetProcessHeap(), 0, source );
5011 if (!ret)
5013 status = STATUS_NO_SUCH_FILE;
5014 goto error;
5016 status = open_nt_file( &file, &nameW );
5017 if (status)
5019 RtlFreeUnicodeString( &nameW );
5020 goto error;
5024 acl.actctx = actctx;
5025 acl.dependencies = NULL;
5026 acl.num_dependencies = 0;
5027 acl.allocated_dependencies = 0;
5029 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5030 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5032 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5034 /* if we have a resource it's a PE file */
5035 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5037 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5038 pActCtx->lpResourceName, lang );
5039 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5040 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5041 pActCtx->hModule, pActCtx->lpResourceName );
5043 else if (pActCtx->lpSource)
5045 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5046 file, pActCtx->lpResourceName, lang );
5047 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5048 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5049 NULL, pActCtx->lpResourceName );
5051 else status = STATUS_INVALID_PARAMETER;
5053 else
5055 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5058 if (file) NtClose( file );
5059 RtlFreeUnicodeString( &nameW );
5061 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5062 free_depend_manifests( &acl );
5064 if (status == STATUS_SUCCESS) *handle = actctx;
5065 else actctx_release( actctx );
5066 return status;
5068 error:
5069 if (file) NtClose( file );
5070 actctx_release( actctx );
5071 return status;
5075 /***********************************************************************
5076 * RtlAddRefActivationContext (NTDLL.@)
5078 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5080 ACTIVATION_CONTEXT *actctx;
5082 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5086 /******************************************************************
5087 * RtlReleaseActivationContext (NTDLL.@)
5089 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5091 ACTIVATION_CONTEXT *actctx;
5093 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5096 /******************************************************************
5097 * RtlZombifyActivationContext (NTDLL.@)
5099 * FIXME: function prototype might be wrong
5101 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5103 FIXME("%p: stub\n", handle);
5104 return STATUS_NOT_IMPLEMENTED;
5107 /******************************************************************
5108 * RtlActivateActivationContext (NTDLL.@)
5110 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5112 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5114 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5115 return STATUS_NO_MEMORY;
5117 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5118 frame->ActivationContext = handle;
5119 frame->Flags = 0;
5120 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5121 RtlAddRefActivationContext( handle );
5123 *cookie = (ULONG_PTR)frame;
5124 TRACE( "%p cookie=%lx\n", handle, *cookie );
5125 return STATUS_SUCCESS;
5129 /***********************************************************************
5130 * RtlDeactivateActivationContext (NTDLL.@)
5132 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5134 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5136 TRACE( "%x cookie=%lx\n", flags, cookie );
5138 /* find the right frame */
5139 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5140 for (frame = top; frame; frame = frame->Previous)
5141 if ((ULONG_PTR)frame == cookie) break;
5143 if (!frame)
5144 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5146 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5147 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5149 /* pop everything up to and including frame */
5150 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5152 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5154 frame = top->Previous;
5155 RtlReleaseActivationContext( top->ActivationContext );
5156 RtlFreeHeap( GetProcessHeap(), 0, top );
5157 top = frame;
5162 /******************************************************************
5163 * RtlFreeThreadActivationContextStack (NTDLL.@)
5165 void WINAPI RtlFreeThreadActivationContextStack(void)
5167 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5169 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5170 while (frame)
5172 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5173 RtlReleaseActivationContext( frame->ActivationContext );
5174 RtlFreeHeap( GetProcessHeap(), 0, frame );
5175 frame = prev;
5177 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5181 /******************************************************************
5182 * RtlGetActiveActivationContext (NTDLL.@)
5184 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5186 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5188 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5189 RtlAddRefActivationContext( *handle );
5191 else
5192 *handle = 0;
5194 return STATUS_SUCCESS;
5198 /******************************************************************
5199 * RtlIsActivationContextActive (NTDLL.@)
5201 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5203 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5205 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5206 if (frame->ActivationContext == handle) return TRUE;
5207 return FALSE;
5211 /***********************************************************************
5212 * RtlQueryInformationActivationContext (NTDLL.@)
5214 * Get information about an activation context.
5215 * FIXME: function signature/prototype may be wrong
5217 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5218 ULONG class, PVOID buffer,
5219 SIZE_T bufsize, SIZE_T *retlen )
5221 ACTIVATION_CONTEXT *actctx;
5222 NTSTATUS status;
5224 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5225 subinst, class, buffer, bufsize, retlen);
5227 if (retlen) *retlen = 0;
5228 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5230 switch (class)
5232 case ActivationContextBasicInformation:
5234 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5236 if (retlen) *retlen = sizeof(*info);
5237 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5239 info->hActCtx = handle;
5240 info->dwFlags = 0; /* FIXME */
5241 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5243 break;
5245 case ActivationContextDetailedInformation:
5247 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5248 struct assembly *assembly = NULL;
5249 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5250 LPWSTR ptr;
5252 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5254 if (actctx->num_assemblies) assembly = actctx->assemblies;
5256 if (assembly && assembly->manifest.info)
5257 manifest_len = strlenW(assembly->manifest.info) + 1;
5258 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5259 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5260 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5262 if (retlen) *retlen = len;
5263 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5265 acdi->dwFlags = 0;
5266 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5267 acdi->ulAssemblyCount = actctx->num_assemblies;
5268 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5269 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5270 acdi->ulRootConfigurationPathType = actctx->config.type;
5271 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5272 acdi->ulAppDirPathType = actctx->appdir.type;
5273 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5274 ptr = (LPWSTR)(acdi + 1);
5275 if (manifest_len)
5277 acdi->lpRootManifestPath = ptr;
5278 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5279 ptr += manifest_len;
5281 else acdi->lpRootManifestPath = NULL;
5282 if (config_len)
5284 acdi->lpRootConfigurationPath = ptr;
5285 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5286 ptr += config_len;
5288 else acdi->lpRootConfigurationPath = NULL;
5289 if (appdir_len)
5291 acdi->lpAppDirPath = ptr;
5292 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5294 else acdi->lpAppDirPath = NULL;
5296 break;
5298 case AssemblyDetailedInformationInActivationContext:
5300 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5301 struct assembly *assembly;
5302 WCHAR *assembly_id;
5303 DWORD index;
5304 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5305 LPWSTR ptr;
5307 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5308 if (!subinst) return STATUS_INVALID_PARAMETER;
5310 index = *(DWORD*)subinst;
5311 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5313 assembly = &actctx->assemblies[index - 1];
5315 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5316 id_len = strlenW(assembly_id) + 1;
5317 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5319 if (assembly->manifest.info &&
5320 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5321 path_len = strlenW(assembly->manifest.info) + 1;
5323 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5325 if (retlen) *retlen = len;
5326 if (!buffer || bufsize < len)
5328 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5329 return STATUS_BUFFER_TOO_SMALL;
5332 afdi->ulFlags = 0; /* FIXME */
5333 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5334 afdi->ulManifestPathType = assembly->manifest.type;
5335 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5336 /* FIXME afdi->liManifestLastWriteTime = 0; */
5337 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5338 afdi->ulPolicyPathLength = 0;
5339 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5340 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5341 afdi->ulManifestVersionMajor = 1;
5342 afdi->ulManifestVersionMinor = 0;
5343 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5344 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5345 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5346 ptr = (LPWSTR)(afdi + 1);
5347 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5348 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5349 ptr += id_len;
5350 if (path_len)
5352 afdi->lpAssemblyManifestPath = ptr;
5353 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5354 ptr += path_len;
5355 } else afdi->lpAssemblyManifestPath = NULL;
5356 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5357 if (ad_len)
5359 afdi->lpAssemblyDirectoryName = ptr;
5360 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5362 else afdi->lpAssemblyDirectoryName = NULL;
5363 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5365 break;
5367 case FileInformationInAssemblyOfAssemblyInActivationContext:
5369 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5370 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5371 struct assembly *assembly;
5372 struct dll_redirect *dll;
5373 SIZE_T len, dll_len = 0;
5374 LPWSTR ptr;
5376 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5377 if (!acqi) return STATUS_INVALID_PARAMETER;
5379 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5380 return STATUS_INVALID_PARAMETER;
5381 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5383 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5384 return STATUS_INVALID_PARAMETER;
5385 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5387 if (dll->name) dll_len = strlenW(dll->name) + 1;
5388 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5390 if (!buffer || bufsize < len)
5392 if (retlen) *retlen = len;
5393 return STATUS_BUFFER_TOO_SMALL;
5395 if (retlen) *retlen = 0; /* yes that's what native does !! */
5396 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5397 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5398 afdi->ulPathLength = 0; /* FIXME */
5399 ptr = (LPWSTR)(afdi + 1);
5400 if (dll_len)
5402 afdi->lpFileName = ptr;
5403 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5404 } else afdi->lpFileName = NULL;
5405 afdi->lpFilePath = NULL; /* FIXME */
5407 break;
5409 case CompatibilityInformationInActivationContext:
5411 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5412 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5413 struct assembly *assembly = NULL;
5414 ULONG num_compat_contexts = 0, n;
5415 SIZE_T len;
5417 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5419 if (actctx->num_assemblies) assembly = actctx->assemblies;
5421 if (assembly)
5422 num_compat_contexts = assembly->num_compat_contexts;
5423 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5425 if (retlen) *retlen = len;
5426 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5428 *acci = num_compat_contexts;
5429 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5430 for (n = 0; n < num_compat_contexts; ++n)
5432 elements[n] = assembly->compat_contexts[n];
5435 break;
5437 case RunlevelInformationInActivationContext:
5439 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5440 struct assembly *assembly;
5441 SIZE_T len;
5443 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5445 len = sizeof(*acrli);
5446 if (retlen) *retlen = len;
5447 if (!buffer || bufsize < len)
5448 return STATUS_BUFFER_TOO_SMALL;
5450 assembly = actctx->assemblies;
5452 acrli->ulFlags = 0;
5453 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5454 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5456 break;
5458 default:
5459 FIXME( "class %u not implemented\n", class );
5460 return STATUS_NOT_IMPLEMENTED;
5462 return STATUS_SUCCESS;
5465 /***********************************************************************
5466 * RtlFindActivationContextSectionString (NTDLL.@)
5468 * Find information about a string in an activation context.
5469 * FIXME: function signature/prototype may be wrong
5471 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5472 const UNICODE_STRING *section_name, PVOID ptr )
5474 PACTCTX_SECTION_KEYED_DATA data = ptr;
5475 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5477 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5478 debugstr_us(section_name), data);
5480 if (guid)
5482 FIXME("expected guid == NULL\n");
5483 return STATUS_INVALID_PARAMETER;
5485 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5487 FIXME("unknown flags %08x\n", flags);
5488 return STATUS_INVALID_PARAMETER;
5490 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5491 !section_name || !section_name->Buffer)
5493 WARN("invalid parameter\n");
5494 return STATUS_INVALID_PARAMETER;
5497 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5499 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5500 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5503 if (status != STATUS_SUCCESS)
5504 status = find_string( process_actctx, section_kind, section_name, flags, data );
5506 return status;
5509 /***********************************************************************
5510 * RtlFindActivationContextSectionGuid (NTDLL.@)
5512 * Find information about a GUID in an activation context.
5513 * FIXME: function signature/prototype may be wrong
5515 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5516 const GUID *guid, void *ptr )
5518 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5519 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5521 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5523 if (extguid)
5525 FIXME("expected extguid == NULL\n");
5526 return STATUS_INVALID_PARAMETER;
5529 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5531 FIXME("unknown flags %08x\n", flags);
5532 return STATUS_INVALID_PARAMETER;
5535 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5536 return STATUS_INVALID_PARAMETER;
5538 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5540 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5541 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5544 if (status != STATUS_SUCCESS)
5545 status = find_guid( process_actctx, section_kind, guid, flags, data );
5547 return status;
5551 /***********************************************************************
5552 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5554 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5555 const WCHAR *settings, WCHAR *buffer,
5556 SIZE_T size, SIZE_T *written )
5558 ACTIVATION_CONTEXT *actctx = check_actctx( handle );
5559 const WCHAR *res;
5561 if (flags)
5563 WARN( "unknown flags %08x\n", flags );
5564 return STATUS_INVALID_PARAMETER;
5567 if (ns)
5569 if (strcmpW( ns, windowsSettings2005NSW ) &&
5570 strcmpW( ns, windowsSettings2011NSW ) &&
5571 strcmpW( ns, windowsSettings2016NSW ) &&
5572 strcmpW( ns, windowsSettings2017NSW ))
5573 return STATUS_INVALID_PARAMETER;
5575 else ns = windowsSettings2005NSW;
5577 if (!handle) handle = process_actctx;
5578 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5580 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5582 if (written) *written = strlenW(res) + 1;
5583 if (size < strlenW(res)) return STATUS_BUFFER_TOO_SMALL;
5584 strcpyW( buffer, res );
5585 return STATUS_SUCCESS;