kernel32: Move ReadConsole and WriteConsole to kernelbase.
[wine.git] / dlls / ntdll / actctx.c
blob7e18544cda83d98015c5792f0f5a686ed985ed0c
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 <stdarg.h>
26 #include <stdio.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #define NONAMELESSUNION
31 #include "winternl.h"
32 #include "ddk/wdm.h"
33 #include "ntdll_misc.h"
34 #include "wine/exception.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
39 #define ACTCTX_FLAGS_ALL (\
40 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
41 ACTCTX_FLAG_LANGID_VALID |\
42 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
43 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
44 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
45 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
46 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
47 ACTCTX_FLAG_HMODULE_VALID )
49 #define ACTCTX_MAGIC 0xC07E3E11
50 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
51 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
53 /* we don't want to include winuser.h */
54 #define RT_MANIFEST ((ULONG_PTR)24)
55 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
57 /* from oaidl.h */
58 typedef enum tagLIBFLAGS {
59 LIBFLAG_FRESTRICTED = 0x1,
60 LIBFLAG_FCONTROL = 0x2,
61 LIBFLAG_FHIDDEN = 0x4,
62 LIBFLAG_FHASDISKIMAGE = 0x8
63 } LIBFLAGS;
65 /* from oleidl.idl */
66 typedef enum tagOLEMISC
68 OLEMISC_RECOMPOSEONRESIZE = 0x1,
69 OLEMISC_ONLYICONIC = 0x2,
70 OLEMISC_INSERTNOTREPLACE = 0x4,
71 OLEMISC_STATIC = 0x8,
72 OLEMISC_CANTLINKINSIDE = 0x10,
73 OLEMISC_CANLINKBYOLE1 = 0x20,
74 OLEMISC_ISLINKOBJECT = 0x40,
75 OLEMISC_INSIDEOUT = 0x80,
76 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
77 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
78 OLEMISC_INVISIBLEATRUNTIME = 0x400,
79 OLEMISC_ALWAYSRUN = 0x800,
80 OLEMISC_ACTSLIKEBUTTON = 0x1000,
81 OLEMISC_ACTSLIKELABEL = 0x2000,
82 OLEMISC_NOUIACTIVATE = 0x4000,
83 OLEMISC_ALIGNABLE = 0x8000,
84 OLEMISC_SIMPLEFRAME = 0x10000,
85 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
86 OLEMISC_IMEMODE = 0x40000,
87 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
88 OLEMISC_WANTSTOMENUMERGE = 0x100000,
89 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
90 } OLEMISC;
92 #define MAX_NAMESPACES 64
94 typedef struct
96 const WCHAR *ptr;
97 unsigned int len;
98 } xmlstr_t;
100 struct xml_elem
102 xmlstr_t name;
103 xmlstr_t ns;
104 int ns_pos;
107 struct xml_attr
109 xmlstr_t name;
110 xmlstr_t value;
113 typedef struct
115 const WCHAR *ptr;
116 const WCHAR *end;
117 struct xml_attr namespaces[MAX_NAMESPACES];
118 int ns_pos;
119 BOOL error;
120 } xmlbuf_t;
122 struct file_info
124 ULONG type;
125 WCHAR *info;
128 struct assembly_version
130 USHORT major;
131 USHORT minor;
132 USHORT build;
133 USHORT revision;
136 struct assembly_identity
138 WCHAR *name;
139 WCHAR *arch;
140 WCHAR *public_key;
141 WCHAR *language;
142 WCHAR *type;
143 struct assembly_version version;
144 BOOL optional;
145 BOOL delayed;
148 struct strsection_header
150 DWORD magic;
151 ULONG size;
152 DWORD unk1[3];
153 ULONG count;
154 ULONG index_offset;
155 DWORD unk2[2];
156 ULONG global_offset;
157 ULONG global_len;
160 struct string_index
162 ULONG hash; /* key string hash */
163 ULONG name_offset;
164 ULONG name_len;
165 ULONG data_offset; /* redirect data offset */
166 ULONG data_len;
167 ULONG rosterindex;
170 struct guidsection_header
172 DWORD magic;
173 ULONG size;
174 DWORD unk[3];
175 ULONG count;
176 ULONG index_offset;
177 DWORD unk2;
178 ULONG names_offset;
179 ULONG names_len;
182 struct guid_index
184 GUID guid;
185 ULONG data_offset;
186 ULONG data_len;
187 ULONG rosterindex;
190 struct wndclass_redirect_data
192 ULONG size;
193 DWORD res;
194 ULONG name_len;
195 ULONG name_offset; /* versioned name offset */
196 ULONG module_len;
197 ULONG module_offset;/* container name offset */
200 struct dllredirect_data
202 ULONG size;
203 ULONG unk;
204 DWORD res[3];
207 struct tlibredirect_data
209 ULONG size;
210 DWORD res;
211 ULONG name_len;
212 ULONG name_offset;
213 LANGID langid;
214 WORD flags;
215 ULONG help_len;
216 ULONG help_offset;
217 WORD major_version;
218 WORD minor_version;
221 enum comclass_threadingmodel
223 ThreadingModel_Apartment = 1,
224 ThreadingModel_Free = 2,
225 ThreadingModel_No = 3,
226 ThreadingModel_Both = 4,
227 ThreadingModel_Neutral = 5
230 enum comclass_miscfields
232 MiscStatus = 1,
233 MiscStatusIcon = 2,
234 MiscStatusContent = 4,
235 MiscStatusThumbnail = 8,
236 MiscStatusDocPrint = 16
239 struct comclassredirect_data
241 ULONG size;
242 ULONG flags;
243 DWORD model;
244 GUID clsid;
245 GUID alias;
246 GUID clsid2;
247 GUID tlbid;
248 ULONG name_len;
249 ULONG name_offset;
250 ULONG progid_len;
251 ULONG progid_offset;
252 ULONG clrdata_len;
253 ULONG clrdata_offset;
254 DWORD miscstatus;
255 DWORD miscstatuscontent;
256 DWORD miscstatusthumbnail;
257 DWORD miscstatusicon;
258 DWORD miscstatusdocprint;
261 enum ifaceps_mask
263 NumMethods = 1,
264 BaseIface = 2
267 struct ifacepsredirect_data
269 ULONG size;
270 DWORD mask;
271 GUID iid;
272 ULONG nummethods;
273 GUID tlbid;
274 GUID base;
275 ULONG name_len;
276 ULONG name_offset;
279 struct clrsurrogate_data
281 ULONG size;
282 DWORD res;
283 GUID clsid;
284 ULONG version_offset;
285 ULONG version_len;
286 ULONG name_offset;
287 ULONG name_len;
290 struct clrclass_data
292 ULONG size;
293 DWORD res[2];
294 ULONG module_len;
295 ULONG module_offset;
296 ULONG name_len;
297 ULONG name_offset;
298 ULONG version_len;
299 ULONG version_offset;
300 DWORD res2[2];
303 struct progidredirect_data
305 ULONG size;
306 DWORD reserved;
307 ULONG clsid_offset;
312 Sections structure.
314 Sections are accessible by string or guid key, that defines two types of sections.
315 All sections of each type have same magic value and header structure, index
316 data could be of two possible types too. So every string based section uses
317 the same index format, same applies to guid sections - they share same guid index
318 format.
320 - window class redirection section is a plain buffer with following format:
322 <section header>
323 <index[]>
324 <data[]> --- <original name>
325 <redirect data>
326 <versioned name>
327 <module name>
329 Header is fixed length structure - struct strsection_header,
330 contains redirected classes count;
332 Index is an array of fixed length index records, each record is
333 struct string_index.
335 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
337 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
338 others are relative to section itself.
340 - dll redirect section format:
342 <section header>
343 <index[]>
344 <data[]> --- <dll name>
345 <data>
347 This section doesn't seem to carry any payload data except dll names.
349 - typelib section format:
351 <section header>
352 <module names[]>
353 <index[]>
354 <data[]> --- <data>
355 <helpstring>
357 Header is fixed length, index is an array of fixed length 'struct guid_index'.
358 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
359 4-bytes aligned as a whole.
361 Module name offsets are relative to section, helpstring offset is relative to data
362 structure itself.
364 - comclass section format:
366 <section header>
367 <module names[]>
368 <index[]>
369 <data[]> --- <data> --- <data>
370 <progid> <clrdata>
371 <name>
372 <version>
373 <progid>
375 This section uses two index records per comclass, one entry contains original guid
376 as specified by context, another one has a generated guid. Index and strings handling
377 is similar to typelib sections.
379 For CLR classes additional data is stored after main COM class data, it contains
380 class name and runtime version string, see 'struct clrclass_data'.
382 Module name offsets are relative to section, progid offset is relative to data
383 structure itself.
385 - COM interface section format:
387 <section header>
388 <index[]>
389 <data[]> --- <data>
390 <name>
392 Interface section contains data for proxy/stubs and external proxy/stubs. External
393 ones are defined at assembly level, so this section has no module information.
394 All records are indexed with 'iid' value from manifest. There an exception for
395 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
396 redirect data, but index is still 'iid' from manifest.
398 Interface name offset is relative to data structure itself.
400 - CLR surrogates section format:
402 <section header>
403 <index[]>
404 <data[]> --- <data>
405 <name>
406 <version>
408 There's nothing special about this section, same way to store strings is used,
409 no modules part as it belongs to assembly level, not a file.
411 - ProgID section format:
413 <section header>
414 <guids[]>
415 <index[]>
416 <data[]> --- <progid>
417 <data>
419 This sections uses generated alias guids from COM server section. This way
420 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
421 is stored too, aligned.
424 struct progids
426 WCHAR **progids;
427 unsigned int num;
428 unsigned int allocated;
431 struct entity
433 DWORD kind;
434 union
436 struct
438 WCHAR *tlbid;
439 WCHAR *helpdir;
440 WORD flags;
441 WORD major;
442 WORD minor;
443 } typelib;
444 struct
446 WCHAR *clsid;
447 WCHAR *tlbid;
448 WCHAR *progid;
449 WCHAR *name; /* clrClass: class name */
450 WCHAR *version; /* clrClass: CLR runtime version */
451 DWORD model;
452 DWORD miscstatus;
453 DWORD miscstatuscontent;
454 DWORD miscstatusthumbnail;
455 DWORD miscstatusicon;
456 DWORD miscstatusdocprint;
457 struct progids progids;
458 } comclass;
459 struct {
460 WCHAR *iid;
461 WCHAR *base;
462 WCHAR *tlib;
463 WCHAR *name;
464 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
465 DWORD mask;
466 ULONG nummethods;
467 } ifaceps;
468 struct
470 WCHAR *name;
471 BOOL versioned;
472 } class;
473 struct
475 WCHAR *name;
476 WCHAR *clsid;
477 WCHAR *version;
478 } clrsurrogate;
479 struct
481 WCHAR *name;
482 WCHAR *value;
483 WCHAR *ns;
484 } settings;
485 } u;
488 struct entity_array
490 struct entity *base;
491 unsigned int num;
492 unsigned int allocated;
495 struct dll_redirect
497 WCHAR *name;
498 WCHAR *hash;
499 struct entity_array entities;
502 enum assembly_type
504 APPLICATION_MANIFEST,
505 ASSEMBLY_MANIFEST,
506 ASSEMBLY_SHARED_MANIFEST,
509 struct assembly
511 enum assembly_type type;
512 struct assembly_identity id;
513 struct file_info manifest;
514 WCHAR *directory;
515 BOOL no_inherit;
516 struct dll_redirect *dlls;
517 unsigned int num_dlls;
518 unsigned int allocated_dlls;
519 struct entity_array entities;
520 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
521 ULONG num_compat_contexts;
522 ACTCTX_REQUESTED_RUN_LEVEL run_level;
523 ULONG ui_access;
526 enum context_sections
528 WINDOWCLASS_SECTION = 1,
529 DLLREDIRECT_SECTION = 2,
530 TLIBREDIRECT_SECTION = 4,
531 SERVERREDIRECT_SECTION = 8,
532 IFACEREDIRECT_SECTION = 16,
533 CLRSURROGATES_SECTION = 32,
534 PROGIDREDIRECT_SECTION = 64
537 typedef struct _ACTIVATION_CONTEXT
539 ULONG magic;
540 int ref_count;
541 struct file_info config;
542 struct file_info appdir;
543 struct assembly *assemblies;
544 unsigned int num_assemblies;
545 unsigned int allocated_assemblies;
546 /* section data */
547 DWORD sections;
548 struct strsection_header *wndclass_section;
549 struct strsection_header *dllredirect_section;
550 struct strsection_header *progid_section;
551 struct guidsection_header *tlib_section;
552 struct guidsection_header *comserver_section;
553 struct guidsection_header *ifaceps_section;
554 struct guidsection_header *clrsurrogate_section;
555 } ACTIVATION_CONTEXT;
557 struct actctx_loader
559 ACTIVATION_CONTEXT *actctx;
560 struct assembly_identity *dependencies;
561 unsigned int num_dependencies;
562 unsigned int allocated_dependencies;
565 static const xmlstr_t empty_xmlstr;
567 #ifdef __i386__
568 static const WCHAR current_archW[] = {'x','8','6',0};
569 #elif defined __x86_64__
570 static const WCHAR current_archW[] = {'a','m','d','6','4',0};
571 #elif defined __arm__
572 static const WCHAR current_archW[] = {'a','r','m',0};
573 #elif defined __aarch64__
574 static const WCHAR current_archW[] = {'a','r','m','6','4',0};
575 #else
576 static const WCHAR current_archW[] = {'n','o','n','e',0};
577 #endif
579 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};
580 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};
581 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};
582 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
583 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
584 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
585 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
586 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
587 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
588 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};
589 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};
590 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
591 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
592 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
593 static const WCHAR fileW[] = {'f','i','l','e',0};
594 static const WCHAR hashW[] = {'h','a','s','h',0};
595 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
596 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
597 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
598 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
600 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
601 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
602 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
603 static const WCHAR iidW[] = {'i','i','d',0};
604 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
605 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
606 static const WCHAR nameW[] = {'n','a','m','e',0};
607 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
608 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
609 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
610 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
611 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};
612 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
613 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
614 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
615 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
616 static const WCHAR typeW[] = {'t','y','p','e',0};
617 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
618 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
619 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
620 static const WCHAR yesW[] = {'y','e','s',0};
621 static const WCHAR noW[] = {'n','o',0};
622 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
623 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
624 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
625 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
626 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
627 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
628 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
629 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
630 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
631 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
632 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
633 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
634 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
635 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
636 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
637 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
639 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
640 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
641 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
642 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
643 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
644 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
645 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
646 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};
647 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
648 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
649 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
650 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
651 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
652 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
653 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
654 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
655 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};
656 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
657 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
658 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
659 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};
660 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
662 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
663 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};
664 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
665 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
666 static const WCHAR IdW[] = {'I','d',0};
667 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};
668 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
669 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
670 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
671 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
672 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
673 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
674 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};
675 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};
676 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};
677 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};
678 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};
679 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
680 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
681 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
682 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};
683 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
684 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
685 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};
686 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};
688 struct olemisc_entry
690 const WCHAR *name;
691 OLEMISC value;
694 static const struct olemisc_entry olemisc_values[] =
696 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
697 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
698 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
699 { alignableW, OLEMISC_ALIGNABLE },
700 { alwaysrunW, OLEMISC_ALWAYSRUN },
701 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
702 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
703 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
704 { imemodeW, OLEMISC_IMEMODE },
705 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
706 { insideoutW, OLEMISC_INSIDEOUT },
707 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
708 { islinkobjectW, OLEMISC_ISLINKOBJECT },
709 { nouiactivateW, OLEMISC_NOUIACTIVATE },
710 { onlyiconicW, OLEMISC_ONLYICONIC },
711 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
712 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
713 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
714 { simpleframeW, OLEMISC_SIMPLEFRAME },
715 { staticW, OLEMISC_STATIC },
716 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
717 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
720 static const WCHAR xmlW[] = {'?','x','m','l',0};
721 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
722 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
723 static const WCHAR wildcardW[] = {'*',0};
725 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
726 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
728 static WCHAR *strdupW(const WCHAR* str)
730 WCHAR* ptr;
732 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR))))
733 return NULL;
734 return wcscpy(ptr, str);
737 static WCHAR *xmlstrdupW(const xmlstr_t* str)
739 WCHAR *strW;
741 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
743 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
744 strW[str->len] = 0;
746 return strW;
749 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
751 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
754 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
756 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
759 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str )
761 return xmlstr_cmp( &attr->name, str );
764 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 )
766 return (elem1->name.len == elem2->name.len &&
767 elem1->ns.len == elem2->ns.len &&
768 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) &&
769 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len ));
772 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace)
774 if (!xmlstr_cmp( &elem->name, str )) return FALSE;
775 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE;
776 if (!wcscmp( namespace, asmv1W ))
778 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE;
779 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
781 else if (!wcscmp( namespace, asmv2W ))
783 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE;
785 return FALSE;
788 static inline BOOL isxmlspace( WCHAR ch )
790 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
793 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
795 return debugstr_wn(str->ptr, str->len);
798 static inline const char *debugstr_xml_elem( const struct xml_elem *elem )
800 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ),
801 debugstr_wn( elem->ns.ptr, elem->ns.len ));
804 static inline const char *debugstr_xml_attr( const struct xml_attr *attr )
806 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ),
807 debugstr_wn( attr->value.ptr, attr->value.len ));
810 static inline const char* debugstr_version(const struct assembly_version *ver)
812 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
815 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
817 NTSTATUS status;
818 ULONG_PTR magic;
819 LDR_DATA_TABLE_ENTRY *pldr;
821 LdrLockLoaderLock(0, NULL, &magic);
822 status = LdrFindEntryForAddress( module, &pldr );
823 if (status == STATUS_SUCCESS)
825 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
826 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
828 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
829 str->Length = pldr->FullDllName.Length;
830 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
832 else status = STATUS_NO_MEMORY;
834 LdrUnlockLoaderLock(0, magic);
835 return status;
838 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
840 struct assembly *assembly;
842 if (actctx->num_assemblies == actctx->allocated_assemblies)
844 void *ptr;
845 unsigned int new_count;
846 if (actctx->assemblies)
848 new_count = actctx->allocated_assemblies * 2;
849 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
850 actctx->assemblies, new_count * sizeof(*assembly) );
852 else
854 new_count = 4;
855 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
857 if (!ptr) return NULL;
858 actctx->assemblies = ptr;
859 actctx->allocated_assemblies = new_count;
862 assembly = &actctx->assemblies[actctx->num_assemblies++];
863 assembly->type = at;
864 return assembly;
867 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
869 if (assembly->num_dlls == assembly->allocated_dlls)
871 void *ptr;
872 unsigned int new_count;
873 if (assembly->dlls)
875 new_count = assembly->allocated_dlls * 2;
876 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
877 assembly->dlls, new_count * sizeof(*assembly->dlls) );
879 else
881 new_count = 4;
882 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
884 if (!ptr) return NULL;
885 assembly->dlls = ptr;
886 assembly->allocated_dlls = new_count;
888 return &assembly->dlls[assembly->num_dlls++];
891 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
893 void *ptr;
894 if (assembly->num_compat_contexts)
896 unsigned int new_count = assembly->num_compat_contexts + 1;
897 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
898 assembly->compat_contexts,
899 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
901 else
903 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
905 if (!ptr) return NULL;
906 assembly->compat_contexts = ptr;
907 return &assembly->compat_contexts[assembly->num_compat_contexts++];
910 static void free_assembly_identity(struct assembly_identity *ai)
912 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
913 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
914 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
915 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
916 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
919 static struct entity* add_entity(struct entity_array *array, DWORD kind)
921 struct entity* entity;
923 if (array->num == array->allocated)
925 void *ptr;
926 unsigned int new_count;
927 if (array->base)
929 new_count = array->allocated * 2;
930 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
931 array->base, new_count * sizeof(*array->base) );
933 else
935 new_count = 4;
936 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
938 if (!ptr) return NULL;
939 array->base = ptr;
940 array->allocated = new_count;
942 entity = &array->base[array->num++];
943 entity->kind = kind;
944 return entity;
947 static void free_entity_array(struct entity_array *array)
949 unsigned int i, j;
950 for (i = 0; i < array->num; i++)
952 struct entity *entity = &array->base[i];
953 switch (entity->kind)
955 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
956 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
957 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
958 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
959 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
960 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
961 for (j = 0; j < entity->u.comclass.progids.num; j++)
962 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
963 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
964 break;
965 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
966 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
967 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
968 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
969 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
970 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
971 break;
972 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
973 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
974 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
975 break;
976 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
977 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
978 break;
979 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
980 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
981 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
982 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
983 break;
984 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
985 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
986 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
987 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns);
988 break;
989 default:
990 FIXME("Unknown entity kind %d\n", entity->kind);
993 RtlFreeHeap( GetProcessHeap(), 0, array->base );
996 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
998 if (!str1) return !str2;
999 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE );
1002 static BOOL is_matching_identity( const struct assembly_identity *id1,
1003 const struct assembly_identity *id2 )
1005 if (!is_matching_string( id1->name, id2->name )) return FALSE;
1006 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
1007 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
1009 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language ))
1011 if (wcscmp( wildcardW, id1->language ) && wcscmp( wildcardW, id2->language ))
1012 return FALSE;
1014 if (id1->version.major != id2->version.major) return FALSE;
1015 if (id1->version.minor != id2->version.minor) return FALSE;
1016 if (id1->version.build > id2->version.build) return FALSE;
1017 if (id1->version.build == id2->version.build &&
1018 id1->version.revision > id2->version.revision) return FALSE;
1019 return TRUE;
1022 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
1023 struct assembly_identity* ai)
1025 unsigned int i;
1027 /* check if we already have that assembly */
1029 for (i = 0; i < acl->actctx->num_assemblies; i++)
1030 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
1032 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
1033 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1034 ai->version.build, ai->version.revision );
1035 return TRUE;
1038 for (i = 0; i < acl->num_dependencies; i++)
1039 if (is_matching_identity( ai, &acl->dependencies[i] ))
1041 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
1042 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
1043 ai->version.build, ai->version.revision );
1044 return TRUE;
1047 if (acl->num_dependencies == acl->allocated_dependencies)
1049 void *ptr;
1050 unsigned int new_count;
1051 if (acl->dependencies)
1053 new_count = acl->allocated_dependencies * 2;
1054 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
1055 new_count * sizeof(acl->dependencies[0]));
1057 else
1059 new_count = 4;
1060 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
1062 if (!ptr) return FALSE;
1063 acl->dependencies = ptr;
1064 acl->allocated_dependencies = new_count;
1066 acl->dependencies[acl->num_dependencies++] = *ai;
1068 return TRUE;
1071 static void free_depend_manifests(struct actctx_loader* acl)
1073 unsigned int i;
1074 for (i = 0; i < acl->num_dependencies; i++)
1075 free_assembly_identity(&acl->dependencies[i]);
1076 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1079 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1081 static const WCHAR undW[] = {'_',0};
1082 static const WCHAR noneW[] = {'n','o','n','e',0};
1083 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1085 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1086 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1087 const WCHAR *lang = ai->language ? ai->language : noneW;
1088 const WCHAR *name = ai->name ? ai->name : noneW;
1089 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 +
1090 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1091 WCHAR *ret;
1093 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1095 wcscpy( ret, arch );
1096 wcscat( ret, undW );
1097 wcscat( ret, name );
1098 wcscat( ret, undW );
1099 wcscat( ret, key );
1100 wcscat( ret, undW );
1101 swprintf( ret + wcslen(ret), size - wcslen(ret), version_formatW,
1102 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1103 wcscat( ret, undW );
1104 wcscat( ret, lang );
1105 wcscat( ret, undW );
1106 wcscat( ret, mskeyW );
1107 return ret;
1110 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1112 WCHAR *p = buffer;
1114 if (!str) return;
1115 wcscat( buffer, prefix );
1116 p += wcslen(p);
1117 *p++ = '"';
1118 wcscpy( p, str );
1119 p += wcslen(p);
1120 *p++ = '"';
1121 *p = 0;
1124 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1126 static const WCHAR archW[] =
1127 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1128 static const WCHAR public_keyW[] =
1129 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1130 static const WCHAR typeW[] =
1131 {',','t','y','p','e','=',0};
1132 static const WCHAR versionW[] =
1133 {',','v','e','r','s','i','o','n','=',0};
1135 WCHAR version[64], *ret;
1136 SIZE_T size = 0;
1138 swprintf( version, ARRAY_SIZE(version), version_formatW,
1139 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1140 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR);
1141 if (ai->arch) size += wcslen(archW) + wcslen(ai->arch) + 2;
1142 if (ai->public_key) size += wcslen(public_keyW) + wcslen(ai->public_key) + 2;
1143 if (ai->type) size += wcslen(typeW) + wcslen(ai->type) + 2;
1144 size += wcslen(versionW) + wcslen(version) + 2;
1146 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1147 return NULL;
1149 if (ai->name) wcscpy( ret, ai->name );
1150 else *ret = 0;
1151 append_string( ret, archW, ai->arch );
1152 append_string( ret, public_keyW, ai->public_key );
1153 append_string( ret, typeW, ai->type );
1154 append_string( ret, versionW, version );
1155 return ret;
1158 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1160 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1162 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1163 __TRY
1165 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1167 __EXCEPT_PAGE_FAULT
1170 __ENDTRY
1171 return ret;
1174 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1176 InterlockedIncrement( &actctx->ref_count );
1179 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1181 if (!InterlockedDecrement( &actctx->ref_count ))
1183 unsigned int i, j;
1185 for (i = 0; i < actctx->num_assemblies; i++)
1187 struct assembly *assembly = &actctx->assemblies[i];
1188 for (j = 0; j < assembly->num_dlls; j++)
1190 struct dll_redirect *dll = &assembly->dlls[j];
1191 free_entity_array( &dll->entities );
1192 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1193 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1195 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1196 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1197 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1198 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1199 free_entity_array( &assembly->entities );
1200 free_assembly_identity(&assembly->id);
1202 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1203 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1204 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1205 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1206 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1207 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1208 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1209 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1210 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1211 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1212 actctx->magic = 0;
1213 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1217 static BOOL set_error( xmlbuf_t *xmlbuf )
1219 xmlbuf->error = TRUE;
1220 return FALSE;
1223 static BOOL is_xmlns_attr( const struct xml_attr *attr )
1225 const int len = wcslen( xmlnsW );
1226 if (attr->name.len < len) return FALSE;
1227 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE;
1228 return (attr->name.len == len || attr->name.ptr[len] == ':');
1231 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr )
1233 const int len = wcslen( xmlnsW );
1234 struct xml_attr *ns;
1236 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1)
1238 FIXME( "too many namespaces in manifest\n" );
1239 set_error( xmlbuf );
1240 return;
1242 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++];
1243 ns->value = attr->value;
1244 if (attr->name.len > len)
1246 ns->name.ptr = attr->name.ptr + len + 1;
1247 ns->name.len = attr->name.len - len - 1;
1249 else ns->name = empty_xmlstr;
1252 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name )
1254 int i;
1256 for (i = xmlbuf->ns_pos - 1; i >= 0; i--)
1258 if (xmlbuf->namespaces[i].name.len == name->len &&
1259 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len ))
1260 return xmlbuf->namespaces[i].value;
1262 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name ));
1263 return empty_xmlstr;
1266 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end)
1268 const WCHAR* ptr;
1269 WCHAR quote;
1271 if (xmlbuf->error) return FALSE;
1273 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1274 xmlbuf->ptr++;
1276 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf );
1278 if (*xmlbuf->ptr == '/')
1280 xmlbuf->ptr++;
1281 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1282 return set_error( xmlbuf );
1284 xmlbuf->ptr++;
1285 *end = TRUE;
1286 return FALSE;
1289 if (*xmlbuf->ptr == '>')
1291 xmlbuf->ptr++;
1292 return FALSE;
1295 ptr = xmlbuf->ptr;
1296 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1298 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1300 attr->name.ptr = xmlbuf->ptr;
1301 attr->name.len = ptr-xmlbuf->ptr;
1302 xmlbuf->ptr = ptr;
1304 /* skip spaces before '=' */
1305 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1306 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf );
1308 /* skip '=' itself */
1309 ptr++;
1310 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1312 /* skip spaces after '=' */
1313 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1315 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf );
1317 quote = *ptr++;
1318 attr->value.ptr = ptr;
1319 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1321 while (ptr < xmlbuf->end && *ptr != quote) ptr++;
1322 if (ptr == xmlbuf->end)
1324 xmlbuf->ptr = xmlbuf->end;
1325 return set_error( xmlbuf );
1328 attr->value.len = ptr - attr->value.ptr;
1329 xmlbuf->ptr = ptr + 1;
1330 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1332 return set_error( xmlbuf );
1335 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem )
1337 const WCHAR* ptr = xmlbuf->ptr;
1339 elem->ns = empty_xmlstr;
1340 elem->name.ptr = ptr;
1341 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/')
1343 if (*ptr == ':')
1345 elem->ns.ptr = elem->name.ptr;
1346 elem->ns.len = ptr - elem->ns.ptr;
1347 elem->name.ptr = ptr + 1;
1349 ptr++;
1351 elem->name.len = ptr - elem->name.ptr;
1352 xmlbuf->ptr = ptr;
1355 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent )
1357 const WCHAR* ptr;
1358 struct xml_attr attr;
1359 xmlbuf_t attr_buf;
1360 BOOL end = FALSE;
1362 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */
1364 if (xmlbuf->error) return FALSE;
1366 for (;;)
1368 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1369 if (ptr == xmlbuf->end)
1371 xmlbuf->ptr = xmlbuf->end;
1372 return set_error( xmlbuf );
1374 ptr++;
1375 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1377 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1378 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1380 if (ptr + 3 > xmlbuf->end)
1382 xmlbuf->ptr = xmlbuf->end;
1383 return set_error( xmlbuf );
1385 xmlbuf->ptr = ptr + 3;
1387 else break;
1390 xmlbuf->ptr = ptr;
1391 /* check for element terminating the parent element */
1392 if (ptr < xmlbuf->end && *ptr == '/')
1394 xmlbuf->ptr++;
1395 read_xml_elem( xmlbuf, elem );
1396 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1397 if (!xml_name_cmp( elem, parent ))
1399 ERR( "wrong closing element %s for %s\n",
1400 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));
1401 return set_error( xmlbuf );
1403 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++;
1404 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf );
1405 return FALSE;
1408 read_xml_elem( xmlbuf, elem );
1410 /* parse namespace attributes */
1411 attr_buf = *xmlbuf;
1412 while (next_xml_attr( &attr_buf, &attr, &end ))
1414 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr );
1416 elem->ns = find_xmlns( xmlbuf, &elem->ns );
1417 elem->ns_pos = xmlbuf->ns_pos;
1419 if (xmlbuf->ptr != xmlbuf->end) return TRUE;
1421 return set_error( xmlbuf );
1424 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1426 /* FIXME: parse attributes */
1427 const WCHAR *ptr;
1429 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1431 if (ptr[0] == '?' && ptr[1] == '>')
1433 xmlbuf->ptr = ptr + 2;
1434 return TRUE;
1437 return FALSE;
1440 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1442 const WCHAR *ptr;
1444 if (xmlbuf->error) return FALSE;
1446 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break;
1447 if (ptr == xmlbuf->end) return set_error( xmlbuf );
1449 content->ptr = xmlbuf->ptr;
1450 content->len = ptr - xmlbuf->ptr;
1451 xmlbuf->ptr = ptr;
1453 return TRUE;
1456 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1458 unsigned int ver[4];
1459 unsigned int pos;
1460 const WCHAR *curr;
1462 /* major.minor.build.revision */
1463 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1464 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1466 if (*curr >= '0' && *curr <= '9')
1468 ver[pos] = ver[pos] * 10 + *curr - '0';
1469 if (ver[pos] >= 0x10000) goto error;
1471 else if (*curr == '.')
1473 if (++pos >= 4) goto error;
1475 else goto error;
1477 version->major = ver[0];
1478 version->minor = ver[1];
1479 version->build = ver[2];
1480 version->revision = ver[3];
1481 return TRUE;
1483 error:
1484 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1485 return FALSE;
1488 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1490 struct xml_attr attr;
1492 while (next_xml_attr(xmlbuf, &attr, end))
1494 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr));
1498 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
1500 struct xml_elem elem;
1502 if (next_xml_elem(xmlbuf, &elem, parent))
1504 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) );
1505 set_error( xmlbuf );
1509 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent)
1511 struct xml_elem elem;
1512 struct xml_attr attr;
1513 BOOL end = FALSE;
1515 while (next_xml_attr(xmlbuf, &attr, &end));
1516 if (end) return;
1518 while (next_xml_elem(xmlbuf, &elem, parent))
1519 parse_unknown_elem(xmlbuf, &elem);
1522 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx,
1523 struct assembly_identity* ai, const struct xml_elem *parent)
1525 struct xml_attr attr;
1526 BOOL end = FALSE;
1528 while (next_xml_attr(xmlbuf, &attr, &end))
1530 if (xml_attr_cmp(&attr, nameW))
1532 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1534 else if (xml_attr_cmp(&attr, typeW))
1536 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1538 else if (xml_attr_cmp(&attr, versionW))
1540 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf );
1542 else if (xml_attr_cmp(&attr, processorArchitectureW))
1544 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1546 else if (xml_attr_cmp(&attr, publicKeyTokenW))
1548 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1550 else if (xml_attr_cmp(&attr, languageW))
1552 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1554 else if (!is_xmlns_attr( &attr ))
1556 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1560 TRACE( "name=%s version=%s arch=%s\n",
1561 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1563 if (!end) parse_expect_end_elem(xmlbuf, parent);
1566 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1568 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1569 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1570 static const WCHAR freeW[] = {'F','r','e','e',0};
1571 static const WCHAR bothW[] = {'B','o','t','h',0};
1573 if (value->len == 0) return ThreadingModel_No;
1574 if (xmlstr_cmp(value, apartW))
1575 return ThreadingModel_Apartment;
1576 else if (xmlstr_cmp(value, freeW))
1577 return ThreadingModel_Free;
1578 else if (xmlstr_cmp(value, bothW))
1579 return ThreadingModel_Both;
1580 else if (xmlstr_cmp(value, neutralW))
1581 return ThreadingModel_Neutral;
1582 else
1583 return ThreadingModel_No;
1586 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1588 int min, max;
1590 min = 0;
1591 max = ARRAY_SIZE(olemisc_values) - 1;
1593 while (min <= max)
1595 int n, c;
1597 n = (min+max)/2;
1599 c = wcsncmp(olemisc_values[n].name, str, len);
1600 if (!c && !olemisc_values[n].name[len])
1601 return olemisc_values[n].value;
1603 if (c >= 0)
1604 max = n-1;
1605 else
1606 min = n+1;
1609 WARN("unknown flag %s\n", debugstr_wn(str, len));
1610 return 0;
1613 static DWORD parse_com_class_misc(const xmlstr_t *value)
1615 const WCHAR *str = value->ptr, *start;
1616 DWORD flags = 0;
1617 int i = 0;
1619 /* it's comma separated list of flags */
1620 while (i < value->len)
1622 start = str;
1623 while (*str != ',' && (i++ < value->len)) str++;
1625 flags |= get_olemisc_value(start, str-start);
1627 /* skip separator */
1628 str++;
1629 i++;
1632 return flags;
1635 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1637 struct progids *progids = &entity->u.comclass.progids;
1639 if (progids->allocated == 0)
1641 progids->allocated = 4;
1642 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1645 if (progids->allocated == progids->num)
1647 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1648 2 * progids->allocated * sizeof(WCHAR*));
1649 if (!new_progids) return FALSE;
1650 progids->allocated *= 2;
1651 progids->progids = new_progids;
1654 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1655 progids->num++;
1657 return TRUE;
1660 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent)
1662 xmlstr_t content;
1663 BOOL end = FALSE;
1665 parse_expect_no_attr(xmlbuf, &end);
1666 if (end) set_error( xmlbuf );
1667 if (!parse_text_content(xmlbuf, &content)) return;
1669 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf );
1670 parse_expect_end_elem(xmlbuf, parent);
1673 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl,
1674 const struct xml_elem *parent )
1676 struct xml_elem elem;
1677 struct xml_attr attr;
1678 BOOL end = FALSE;
1679 struct entity* entity;
1681 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1683 set_error( xmlbuf );
1684 return;
1687 while (next_xml_attr(xmlbuf, &attr, &end))
1689 if (xml_attr_cmp(&attr, clsidW))
1691 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1693 else if (xml_attr_cmp(&attr, progidW))
1695 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1697 else if (xml_attr_cmp(&attr, tlbidW))
1699 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1701 else if (xml_attr_cmp(&attr, threadingmodelW))
1703 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
1705 else if (xml_attr_cmp(&attr, miscstatusW))
1707 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value);
1709 else if (xml_attr_cmp(&attr, miscstatuscontentW))
1711 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value);
1713 else if (xml_attr_cmp(&attr, miscstatusthumbnailW))
1715 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value);
1717 else if (xml_attr_cmp(&attr, miscstatusiconW))
1719 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value);
1721 else if (xml_attr_cmp(&attr, miscstatusdocprintW))
1723 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value);
1725 else if (xml_attr_cmp(&attr, descriptionW))
1727 /* not stored */
1729 else if (!is_xmlns_attr( &attr ))
1731 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1735 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1736 if (entity->u.comclass.progid)
1737 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1739 if (end) return;
1741 while (next_xml_elem(xmlbuf, &elem, parent))
1743 if (xml_elem_cmp(&elem, progidW, asmv1W))
1745 parse_com_class_progid(xmlbuf, entity, &elem);
1747 else
1749 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
1750 parse_unknown_elem(xmlbuf, &elem);
1754 if (entity->u.comclass.progids.num)
1755 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1758 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1760 const WCHAR *curr;
1761 ULONG num = 0;
1763 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1765 if (*curr >= '0' && *curr <= '9')
1766 num = num * 10 + *curr - '0';
1767 else
1769 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1770 return FALSE;
1773 entity->u.ifaceps.nummethods = num;
1775 return TRUE;
1778 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities,
1779 struct actctx_loader *acl, WCHAR *clsid )
1781 struct entity *entity;
1782 WCHAR *str;
1784 if (!clsid) return;
1786 if (!(str = strdupW(clsid)))
1788 set_error( xmlbuf );
1789 return;
1792 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1794 RtlFreeHeap(GetProcessHeap(), 0, str);
1795 set_error( xmlbuf );
1796 return;
1799 entity->u.comclass.clsid = str;
1800 entity->u.comclass.model = ThreadingModel_Both;
1802 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1805 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1806 struct actctx_loader *acl, const struct xml_elem *parent )
1808 WCHAR *psclsid = NULL;
1809 struct entity *entity;
1810 struct xml_attr attr;
1811 BOOL end = FALSE;
1813 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1815 set_error( xmlbuf );
1816 return;
1819 while (next_xml_attr(xmlbuf, &attr, &end))
1821 if (xml_attr_cmp(&attr, iidW))
1823 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1825 else if (xml_attr_cmp(&attr, nameW))
1827 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1829 else if (xml_attr_cmp(&attr, baseInterfaceW))
1831 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1832 entity->u.ifaceps.mask |= BaseIface;
1834 else if (xml_attr_cmp(&attr, nummethodsW))
1836 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
1837 entity->u.ifaceps.mask |= NumMethods;
1839 else if (xml_attr_cmp(&attr, tlbidW))
1841 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1843 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
1845 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1847 /* not used */
1848 else if (xml_attr_cmp(&attr, threadingmodelW))
1851 else if (!is_xmlns_attr( &attr ))
1853 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1857 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1858 if (!end) parse_expect_end_elem(xmlbuf, parent);
1860 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid);
1862 RtlFreeHeap(GetProcessHeap(), 0, psclsid);
1865 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1867 WORD *flags = &entity->u.typelib.flags;
1868 const WCHAR *str = value->ptr, *start;
1869 int i = 0;
1871 *flags = 0;
1873 /* it's comma separated list of flags */
1874 while (i < value->len)
1876 start = str;
1877 while (*str != ',' && (i++ < value->len)) str++;
1879 if (!wcsnicmp(start, restrictedW, str-start))
1880 *flags |= LIBFLAG_FRESTRICTED;
1881 else if (!wcsnicmp(start, controlW, str-start))
1882 *flags |= LIBFLAG_FCONTROL;
1883 else if (!wcsnicmp(start, hiddenW, str-start))
1884 *flags |= LIBFLAG_FHIDDEN;
1885 else if (!wcsnicmp(start, hasdiskimageW, str-start))
1886 *flags |= LIBFLAG_FHASDISKIMAGE;
1887 else
1889 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1890 return FALSE;
1893 /* skip separator */
1894 str++;
1895 i++;
1898 return TRUE;
1901 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1903 unsigned int ver[2];
1904 unsigned int pos;
1905 const WCHAR *curr;
1907 /* major.minor */
1908 ver[0] = ver[1] = pos = 0;
1909 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1911 if (*curr >= '0' && *curr <= '9')
1913 ver[pos] = ver[pos] * 10 + *curr - '0';
1914 if (ver[pos] >= 0x10000) goto error;
1916 else if (*curr == '.')
1918 if (++pos >= 2) goto error;
1920 else goto error;
1922 entity->u.typelib.major = ver[0];
1923 entity->u.typelib.minor = ver[1];
1924 return TRUE;
1926 error:
1927 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1928 return FALSE;
1931 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1932 struct actctx_loader *acl, const struct xml_elem *parent )
1934 struct xml_attr attr;
1935 BOOL end = FALSE;
1936 struct entity* entity;
1938 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1940 set_error( xmlbuf );
1941 return;
1944 while (next_xml_attr(xmlbuf, &attr, &end))
1946 if (xml_attr_cmp(&attr, tlbidW))
1948 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1950 else if (xml_attr_cmp(&attr, versionW))
1952 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf );
1954 else if (xml_attr_cmp(&attr, helpdirW))
1956 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf );
1958 else if (xml_attr_cmp(&attr, flagsW))
1960 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf );
1962 else if (!is_xmlns_attr( &attr ))
1964 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
1968 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1969 if (!end) parse_expect_end_elem(xmlbuf, parent);
1972 static inline int aligned_string_len(int len)
1974 return (len + 3) & ~3;
1977 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1979 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1980 struct assembly_version *ver = &assembly->id.version;
1981 WCHAR buff[25];
1983 if (!ret) ret = buff;
1984 return swprintf(ret, ARRAY_SIZE(buff), fmtW, ver->major, ver->minor, ver->build, ver->revision);
1987 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll,
1988 struct actctx_loader *acl, const struct xml_elem *parent )
1990 struct xml_elem elem;
1991 struct xml_attr attr;
1992 xmlstr_t content;
1993 BOOL end = FALSE;
1994 struct entity* entity;
1996 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1998 set_error( xmlbuf );
1999 return;
2001 entity->u.class.versioned = TRUE;
2002 while (next_xml_attr(xmlbuf, &attr, &end))
2004 if (xml_attr_cmp(&attr, versionedW))
2006 if (xmlstr_cmpi(&attr.value, noW))
2007 entity->u.class.versioned = FALSE;
2008 else if (!xmlstr_cmpi(&attr.value, yesW))
2009 set_error( xmlbuf );
2011 else if (!is_xmlns_attr( &attr ))
2013 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2017 if (end) return;
2019 if (!parse_text_content(xmlbuf, &content)) return;
2020 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf );
2022 acl->actctx->sections |= WINDOWCLASS_SECTION;
2024 while (next_xml_elem(xmlbuf, &elem, parent))
2026 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2027 parse_unknown_elem(xmlbuf, &elem);
2031 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2033 struct xml_attr attr;
2034 BOOL end = FALSE;
2036 while (next_xml_attr(xmlbuf, &attr, &end))
2038 if (xml_attr_cmp(&attr, oldVersionW))
2040 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2042 else if (xml_attr_cmp(&attr, newVersionW))
2044 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr));
2046 else if (!is_xmlns_attr( &attr ))
2048 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2052 if (!end) parse_expect_end_elem(xmlbuf, parent);
2055 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2057 struct xml_elem elem;
2058 struct xml_attr attr;
2059 xmlstr_t content;
2060 BOOL end = FALSE;
2062 while (next_xml_attr(xmlbuf, &attr, &end))
2064 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2067 if (end) return;
2068 if (!parse_text_content(xmlbuf, &content)) return;
2070 TRACE("Got description %s\n", debugstr_xmlstr(&content));
2072 while (next_xml_elem(xmlbuf, &elem, parent))
2074 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2075 parse_unknown_elem(xmlbuf, &elem);
2079 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf,
2080 struct assembly* assembly,
2081 struct actctx_loader* acl,
2082 const struct xml_elem *parent)
2084 struct xml_attr attr;
2085 BOOL end = FALSE;
2086 struct entity* entity;
2088 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
2090 set_error( xmlbuf );
2091 return;
2094 while (next_xml_attr(xmlbuf, &attr, &end))
2096 if (xml_attr_cmp(&attr, iidW))
2098 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2100 else if (xml_attr_cmp(&attr, nameW))
2102 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2104 else if (xml_attr_cmp(&attr, baseInterfaceW))
2106 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2107 entity->u.ifaceps.mask |= BaseIface;
2109 else if (xml_attr_cmp(&attr, nummethodsW))
2111 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf );
2112 entity->u.ifaceps.mask |= NumMethods;
2114 else if (xml_attr_cmp(&attr, proxyStubClsid32W))
2116 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2118 else if (xml_attr_cmp(&attr, tlbidW))
2120 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2122 else if (!is_xmlns_attr( &attr ))
2124 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2128 acl->actctx->sections |= IFACEREDIRECT_SECTION;
2129 if (!end) parse_expect_end_elem(xmlbuf, parent);
2132 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2133 struct actctx_loader *acl, const struct xml_elem *parent )
2136 struct xml_elem elem;
2137 struct xml_attr attr;
2138 BOOL end = FALSE;
2139 struct entity* entity;
2141 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
2143 set_error( xmlbuf );
2144 return;
2147 while (next_xml_attr(xmlbuf, &attr, &end))
2149 if (xml_attr_cmp(&attr, nameW))
2151 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2153 else if (xml_attr_cmp(&attr, clsidW))
2155 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2157 else if (xml_attr_cmp(&attr, progidW))
2159 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2161 else if (xml_attr_cmp(&attr, tlbidW))
2163 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2165 else if (xml_attr_cmp(&attr, threadingmodelW))
2167 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value);
2169 else if (xml_attr_cmp(&attr, runtimeVersionW))
2171 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2173 else if (!is_xmlns_attr( &attr ))
2175 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2179 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2180 if (entity->u.comclass.progid)
2181 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2182 if (end) return;
2184 while (next_xml_elem(xmlbuf, &elem, parent))
2186 if (xml_elem_cmp(&elem, progidW, asmv1W))
2188 parse_com_class_progid(xmlbuf, entity, &elem);
2190 else
2192 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2193 parse_unknown_elem(xmlbuf, &elem);
2197 if (entity->u.comclass.progids.num)
2198 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2201 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2202 struct actctx_loader *acl, const struct xml_elem *parent )
2204 struct xml_attr attr;
2205 BOOL end = FALSE;
2206 struct entity* entity;
2208 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)))
2210 set_error( xmlbuf );
2211 return;
2214 while (next_xml_attr(xmlbuf, &attr, &end))
2216 if (xml_attr_cmp(&attr, nameW))
2218 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2220 else if (xml_attr_cmp(&attr, clsidW))
2222 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2224 else if (xml_attr_cmp(&attr, runtimeVersionW))
2226 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2228 else if (!is_xmlns_attr( &attr ))
2230 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2234 acl->actctx->sections |= CLRSURROGATES_SECTION;
2235 if (!end) parse_expect_end_elem(xmlbuf, parent);
2238 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2239 const struct xml_elem *parent, BOOL optional )
2241 struct xml_elem elem;
2242 struct xml_attr attr;
2243 struct assembly_identity ai;
2244 BOOL end = FALSE;
2246 memset(&ai, 0, sizeof(ai));
2247 ai.optional = optional;
2249 while (next_xml_attr(xmlbuf, &attr, &end))
2251 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2252 static const WCHAR trueW[] = {'t','r','u','e',0};
2254 if (xml_attr_cmp(&attr, allowDelayedBindingW))
2255 ai.delayed = xmlstr_cmp(&attr.value, trueW);
2256 else if (!is_xmlns_attr( &attr ))
2257 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2260 if (end) return;
2262 while (next_xml_elem(xmlbuf, &elem, parent))
2264 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2266 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem);
2267 /* store the newly found identity for later loading */
2268 if (ai.arch && !wcscmp(ai.arch, wildcardW))
2270 RtlFreeHeap( GetProcessHeap(), 0, ai.arch );
2271 ai.arch = strdupW( current_archW );
2273 TRACE( "adding name=%s version=%s arch=%s\n",
2274 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2275 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf );
2277 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W))
2279 parse_binding_redirect_elem(xmlbuf, &elem);
2281 else
2283 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2284 parse_unknown_elem(xmlbuf, &elem);
2289 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl,
2290 const struct xml_elem *parent )
2293 struct xml_elem elem;
2294 struct xml_attr attr;
2295 BOOL end = FALSE, optional = FALSE;
2297 while (next_xml_attr(xmlbuf, &attr, &end))
2299 if (xml_attr_cmp(&attr, optionalW))
2301 optional = xmlstr_cmpi( &attr.value, yesW );
2302 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value));
2304 else if (!is_xmlns_attr( &attr ))
2306 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2310 while (next_xml_elem(xmlbuf, &elem, parent))
2312 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2314 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2316 else
2318 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2319 parse_unknown_elem(xmlbuf, &elem);
2324 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2326 BOOL end = FALSE;
2328 parse_expect_no_attr(xmlbuf, &end);
2329 if (!end) parse_expect_end_elem(xmlbuf, parent);
2332 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2334 BOOL end = FALSE;
2336 parse_expect_no_attr(xmlbuf, &end);
2337 if (!end) parse_expect_end_elem(xmlbuf, parent);
2340 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2341 struct actctx_loader* acl, const struct xml_elem *parent )
2343 struct xml_elem elem;
2344 struct xml_attr attr;
2345 BOOL end = FALSE;
2346 struct dll_redirect* dll;
2348 if (!(dll = add_dll_redirect(assembly)))
2350 set_error( xmlbuf );
2351 return;
2354 while (next_xml_attr(xmlbuf, &attr, &end))
2356 if (xml_attr_cmp(&attr, nameW))
2358 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2359 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2361 else if (xml_attr_cmp(&attr, hashW))
2363 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2365 else if (xml_attr_cmp(&attr, hashalgW))
2367 static const WCHAR sha1W[] = {'S','H','A','1',0};
2368 if (!xmlstr_cmpi(&attr.value, sha1W))
2369 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2371 else if (!is_xmlns_attr( &attr ))
2373 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2377 if (!dll->name) set_error( xmlbuf );
2379 acl->actctx->sections |= DLLREDIRECT_SECTION;
2381 if (end) return;
2383 while (next_xml_elem(xmlbuf, &elem, parent))
2385 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2387 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2389 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2391 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2393 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2395 WARN("asmv2:hash (undocumented) not supported\n");
2396 parse_unknown_elem(xmlbuf, &elem);
2398 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2400 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2402 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2404 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2406 else
2408 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2409 parse_unknown_elem( xmlbuf, &elem );
2414 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2415 struct actctx_loader *acl, const struct xml_elem *parent )
2417 struct xml_attr attr;
2418 BOOL end = FALSE;
2420 while (next_xml_attr(xmlbuf, &attr, &end))
2422 if (xml_attr_cmp(&attr, IdW))
2424 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2425 UNICODE_STRING str;
2426 GUID compat_id;
2428 str.Buffer = (PWSTR)attr.value.ptr;
2429 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2430 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2432 if (!(compat = add_compat_context(assembly)))
2434 set_error( xmlbuf );
2435 return;
2437 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2438 compat->Id = compat_id;
2440 else
2442 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2445 else if (!is_xmlns_attr( &attr ))
2447 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2451 if (!end) parse_expect_end_elem(xmlbuf, parent);
2454 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2455 struct actctx_loader* acl, const struct xml_elem *parent)
2457 struct xml_elem elem;
2459 while (next_xml_elem(xmlbuf, &elem, parent))
2461 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2463 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2465 else
2467 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2468 parse_unknown_elem(xmlbuf, &elem);
2473 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2474 struct actctx_loader* acl, const struct xml_elem *parent)
2476 struct xml_elem elem;
2478 while (next_xml_elem(xmlbuf, &elem, parent))
2480 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2482 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2484 else
2486 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2487 parse_unknown_elem(xmlbuf, &elem);
2492 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2493 struct xml_elem *parent )
2495 struct xml_elem elem;
2496 struct xml_attr attr;
2497 xmlstr_t content;
2498 BOOL end = FALSE;
2499 struct entity *entity;
2501 while (next_xml_attr( xmlbuf, &attr, &end ))
2503 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2506 if (end) return;
2508 if (!parse_text_content( xmlbuf, &content )) return;
2509 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2511 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2512 if (!entity)
2514 set_error( xmlbuf );
2515 return;
2517 entity->u.settings.name = xmlstrdupW( &parent->name );
2518 entity->u.settings.value = xmlstrdupW( &content );
2519 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2521 while (next_xml_elem(xmlbuf, &elem, parent))
2523 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2524 parse_unknown_elem( xmlbuf, &elem );
2528 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2529 struct actctx_loader *acl, const struct xml_elem *parent )
2531 struct xml_elem elem;
2533 while (next_xml_elem( xmlbuf, &elem, parent ))
2535 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2536 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2537 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2538 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2539 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2540 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2541 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2542 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2543 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2544 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2545 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2547 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2549 else
2551 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2552 parse_unknown_elem( xmlbuf, &elem );
2557 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2558 struct actctx_loader *acl, const struct xml_elem *parent )
2560 struct xml_elem elem;
2562 while (next_xml_elem( xmlbuf, &elem, parent ))
2564 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2566 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2568 else
2570 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2571 parse_unknown_elem( xmlbuf, &elem );
2576 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2577 struct actctx_loader *acl, const struct xml_elem *parent )
2579 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2580 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2581 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};
2582 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2583 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2584 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2585 static const WCHAR trueW[] = {'t','r','u','e',0};
2587 struct xml_elem elem;
2588 struct xml_attr attr;
2589 BOOL end = FALSE;
2591 /* Multiple requestedExecutionLevel elements are not supported. */
2592 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2594 while (next_xml_attr(xmlbuf, &attr, &end))
2596 if (xml_attr_cmp(&attr, levelW))
2598 if (xmlstr_cmpi(&attr.value, asInvokerW))
2599 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2600 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2601 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2602 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2603 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2604 else
2605 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2607 else if (xml_attr_cmp(&attr, uiAccessW))
2609 if (xmlstr_cmpi(&attr.value, falseW))
2610 assembly->ui_access = FALSE;
2611 else if (xmlstr_cmpi(&attr.value, trueW))
2612 assembly->ui_access = TRUE;
2613 else
2614 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2616 else if (!is_xmlns_attr( &attr ))
2617 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2620 if (end) return;
2622 while (next_xml_elem(xmlbuf, &elem, parent))
2624 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2625 parse_unknown_elem(xmlbuf, &elem);
2629 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2630 struct actctx_loader *acl, const struct xml_elem *parent )
2632 struct xml_elem elem;
2634 while (next_xml_elem(xmlbuf, &elem, parent))
2636 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2638 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2640 else
2642 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2643 parse_unknown_elem(xmlbuf, &elem);
2648 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2649 struct actctx_loader *acl, const struct xml_elem *parent )
2651 struct xml_elem elem;
2653 while (next_xml_elem(xmlbuf, &elem, parent))
2655 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2657 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2659 else
2661 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2662 parse_unknown_elem(xmlbuf, &elem);
2667 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2668 struct actctx_loader *acl, const struct xml_elem *parent )
2670 struct xml_elem elem;
2672 while (next_xml_elem(xmlbuf, &elem, parent))
2674 if (xml_elem_cmp(&elem, securityW, asmv1W))
2676 parse_security_elem(xmlbuf, assembly, acl, &elem);
2678 else
2680 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2681 parse_unknown_elem(xmlbuf, &elem);
2686 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2687 struct actctx_loader* acl, const struct xml_elem *parent,
2688 struct assembly_identity* expected_ai)
2690 struct xml_elem elem;
2691 struct xml_attr attr;
2692 BOOL end = FALSE, version = FALSE;
2694 TRACE("(%p)\n", xmlbuf);
2696 while (next_xml_attr(xmlbuf, &attr, &end))
2698 if (xml_attr_cmp(&attr, manifestVersionW))
2700 static const WCHAR v10W[] = {'1','.','0',0};
2701 if (!xmlstr_cmp(&attr.value, v10W))
2703 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2704 break;
2706 version = TRUE;
2708 else if (!is_xmlns_attr( &attr ))
2710 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2714 if (end || !version)
2716 set_error( xmlbuf );
2717 return;
2720 while (next_xml_elem(xmlbuf, &elem, parent))
2722 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2724 parse_noinherit_elem(xmlbuf, &elem);
2725 assembly->no_inherit = TRUE;
2727 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2729 parse_noinheritable_elem(xmlbuf, &elem);
2731 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2733 parse_description_elem(xmlbuf, &elem);
2735 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2737 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2739 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2741 parse_dependency_elem(xmlbuf, acl, &elem);
2743 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2745 parse_file_elem(xmlbuf, assembly, acl, &elem);
2747 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2749 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2751 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2753 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2755 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2757 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2759 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2761 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2763 if (!xmlbuf->error && expected_ai)
2765 /* FIXME: more tests */
2766 if (assembly->type == ASSEMBLY_MANIFEST &&
2767 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2769 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2770 expected_ai->version.major, expected_ai->version.minor,
2771 expected_ai->version.build, expected_ai->version.revision,
2772 assembly->id.version.major, assembly->id.version.minor,
2773 assembly->id.version.build, assembly->id.version.revision);
2774 set_error( xmlbuf );
2776 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2777 (assembly->id.version.major != expected_ai->version.major ||
2778 assembly->id.version.minor != expected_ai->version.minor ||
2779 assembly->id.version.build < expected_ai->version.build ||
2780 (assembly->id.version.build == expected_ai->version.build &&
2781 assembly->id.version.revision < expected_ai->version.revision)))
2783 FIXME("wrong version for shared assembly manifest\n");
2784 set_error( xmlbuf );
2788 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2790 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2792 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2794 parse_application_elem(xmlbuf, assembly, acl, &elem);
2796 else
2798 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2799 parse_unknown_elem(xmlbuf, &elem);
2803 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2804 assembly->no_inherit)
2806 set_error( xmlbuf );
2810 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2811 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2813 struct xml_elem elem;
2814 struct xml_elem parent = {};
2816 xmlbuf->error = FALSE;
2817 xmlbuf->ns_pos = 0;
2819 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2821 if (xmlstr_cmp(&elem.name, xmlW) &&
2822 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2823 return STATUS_SXS_CANT_GEN_ACTCTX;
2825 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2827 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2828 return STATUS_SXS_CANT_GEN_ACTCTX;
2831 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2832 if (xmlbuf->error)
2834 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2835 return STATUS_SXS_CANT_GEN_ACTCTX;
2838 if (next_xml_elem(xmlbuf, &elem, &parent))
2840 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2841 return STATUS_SXS_CANT_GEN_ACTCTX;
2844 if (xmlbuf->ptr != xmlbuf->end)
2846 FIXME("parse error\n");
2847 return STATUS_SXS_CANT_GEN_ACTCTX;
2849 return STATUS_SUCCESS;
2852 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2853 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2854 const void *buffer, SIZE_T size )
2856 xmlbuf_t xmlbuf;
2857 NTSTATUS status;
2858 struct assembly *assembly;
2859 int unicode_tests;
2861 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2863 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2864 return STATUS_SXS_CANT_GEN_ACTCTX;
2866 if (directory && !(assembly->directory = strdupW(directory)))
2867 return STATUS_NO_MEMORY;
2869 if (!filename)
2871 UNICODE_STRING module_path;
2872 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2873 assembly->manifest.info = module_path.Buffer;
2875 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2877 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2878 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2880 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2881 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2883 xmlbuf.ptr = buffer;
2884 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2885 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2887 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2889 const WCHAR *buf = buffer;
2890 WCHAR *new_buff;
2891 unsigned int i;
2893 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2894 return STATUS_NO_MEMORY;
2895 for (i = 0; i < size / sizeof(WCHAR); i++)
2896 new_buff[i] = RtlUshortByteSwap( buf[i] );
2897 xmlbuf.ptr = new_buff;
2898 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2899 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2900 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2902 else
2904 DWORD len;
2905 WCHAR *new_buff;
2907 /* let's assume utf-8 for now */
2908 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2909 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2910 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2911 xmlbuf.ptr = new_buff;
2912 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2913 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2914 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2916 return status;
2919 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2921 OBJECT_ATTRIBUTES attr;
2922 IO_STATUS_BLOCK io;
2924 attr.Length = sizeof(attr);
2925 attr.RootDirectory = 0;
2926 attr.Attributes = OBJ_CASE_INSENSITIVE;
2927 attr.ObjectName = name;
2928 attr.SecurityDescriptor = NULL;
2929 attr.SecurityQualityOfService = NULL;
2930 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2933 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2934 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2935 HANDLE hModule, LPCWSTR resname, ULONG lang )
2937 NTSTATUS status;
2938 UNICODE_STRING nameW;
2939 LDR_RESOURCE_INFO info;
2940 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2941 void *ptr;
2943 if (TRACE_ON(actctx))
2945 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2947 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2948 hModule, debugstr_w(nameW.Buffer) );
2949 RtlFreeUnicodeString( &nameW );
2951 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2952 hModule, debugstr_w(filename) );
2955 if (!resname) return STATUS_INVALID_PARAMETER;
2957 info.Type = RT_MANIFEST;
2958 info.Language = lang;
2959 if (!((ULONG_PTR)resname >> 16))
2961 info.Name = (ULONG_PTR)resname;
2962 status = LdrFindResource_U(hModule, &info, 3, &entry);
2964 else if (resname[0] == '#')
2966 ULONG value;
2967 RtlInitUnicodeString(&nameW, resname + 1);
2968 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2969 return STATUS_INVALID_PARAMETER;
2970 info.Name = value;
2971 status = LdrFindResource_U(hModule, &info, 3, &entry);
2973 else
2975 RtlCreateUnicodeString(&nameW, resname);
2976 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2977 info.Name = (ULONG_PTR)nameW.Buffer;
2978 status = LdrFindResource_U(hModule, &info, 3, &entry);
2979 RtlFreeUnicodeString(&nameW);
2981 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2983 if (status == STATUS_SUCCESS)
2984 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2986 return status;
2989 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2990 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2991 HANDLE file, LPCWSTR resname, ULONG lang )
2993 HANDLE mapping;
2994 OBJECT_ATTRIBUTES attr;
2995 LARGE_INTEGER size;
2996 LARGE_INTEGER offset;
2997 NTSTATUS status;
2998 SIZE_T count;
2999 void *base;
3001 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
3003 attr.Length = sizeof(attr);
3004 attr.RootDirectory = 0;
3005 attr.ObjectName = NULL;
3006 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3007 attr.SecurityDescriptor = NULL;
3008 attr.SecurityQualityOfService = NULL;
3010 size.QuadPart = 0;
3011 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3012 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3013 if (status != STATUS_SUCCESS) return status;
3015 offset.QuadPart = 0;
3016 count = 0;
3017 base = NULL;
3018 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3019 &count, ViewShare, 0, PAGE_READONLY );
3020 NtClose( mapping );
3021 if (status != STATUS_SUCCESS) return status;
3023 if (RtlImageNtHeader(base)) /* we got a PE file */
3025 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3026 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3028 else status = STATUS_INVALID_IMAGE_FORMAT;
3030 NtUnmapViewOfSection( GetCurrentProcess(), base );
3031 return status;
3034 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3035 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3037 FILE_END_OF_FILE_INFORMATION info;
3038 IO_STATUS_BLOCK io;
3039 HANDLE mapping;
3040 OBJECT_ATTRIBUTES attr;
3041 LARGE_INTEGER size;
3042 LARGE_INTEGER offset;
3043 NTSTATUS status;
3044 SIZE_T count;
3045 void *base;
3047 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3049 attr.Length = sizeof(attr);
3050 attr.RootDirectory = 0;
3051 attr.ObjectName = NULL;
3052 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3053 attr.SecurityDescriptor = NULL;
3054 attr.SecurityQualityOfService = NULL;
3056 size.QuadPart = 0;
3057 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3058 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3059 if (status != STATUS_SUCCESS) return status;
3061 offset.QuadPart = 0;
3062 count = 0;
3063 base = NULL;
3064 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3065 &count, ViewShare, 0, PAGE_READONLY );
3066 NtClose( mapping );
3067 if (status != STATUS_SUCCESS) return status;
3069 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3070 if (status == STATUS_SUCCESS)
3071 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3073 NtUnmapViewOfSection( GetCurrentProcess(), base );
3074 return status;
3077 /* try to load the .manifest file associated to the file */
3078 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3079 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3081 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3082 WCHAR *buffer;
3083 NTSTATUS status;
3084 UNICODE_STRING nameW;
3085 HANDLE file;
3086 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3088 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3090 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3092 if (module) /* use the module filename */
3094 UNICODE_STRING name;
3096 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3098 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, fmtW, resid );
3099 wcscat( name.Buffer, dotManifestW );
3100 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3101 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3102 RtlFreeUnicodeString( &name );
3104 if (status) return status;
3106 else
3108 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3109 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3110 return STATUS_NO_MEMORY;
3111 wcscpy( buffer, filename );
3112 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, fmtW, resid );
3113 wcscat( buffer, dotManifestW );
3114 RtlInitUnicodeString( &nameW, buffer );
3117 if (!open_nt_file( &file, &nameW ))
3119 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3120 NtClose( file );
3122 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3123 RtlFreeUnicodeString( &nameW );
3124 return status;
3127 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3129 static const WCHAR lookup_fmtW[] =
3130 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3131 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3132 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3134 WCHAR *lookup, *ret = NULL;
3135 UNICODE_STRING lookup_us;
3136 IO_STATUS_BLOCK io;
3137 const WCHAR *lang = ai->language;
3138 unsigned int data_pos = 0, data_len, len;
3139 char buffer[8192];
3141 if (!lang || !wcsicmp( lang, neutralW )) lang = wildcardW;
3143 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3144 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3145 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3146 ai->version.major, ai->version.minor, lang );
3147 RtlInitUnicodeString( &lookup_us, lookup );
3149 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3150 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3152 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3153 FILE_BOTH_DIR_INFORMATION *dir_info;
3154 WCHAR *tmp;
3155 ULONG build, revision;
3157 data_len = io.Information;
3159 for (;;)
3161 if (data_pos >= data_len)
3163 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3164 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3165 break;
3166 data_len = io.Information;
3167 data_pos = 0;
3169 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3171 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3172 else data_pos = data_len;
3174 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3175 build = wcstoul( tmp, NULL, 10 );
3176 if (build < min_build) continue;
3177 tmp = wcschr(tmp, '.') + 1;
3178 revision = wcstoul( tmp, NULL, 10 );
3179 if (build == min_build && revision < min_revision) continue;
3180 tmp = wcschr(tmp, '_') + 1;
3181 tmp = wcschr(tmp, '_') + 1;
3182 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3183 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3185 /* prefer a non-Wine manifest if we already have one */
3186 /* we'll still load the builtin dll if specified through DllOverrides */
3187 if (ret) continue;
3189 else
3191 min_build = build;
3192 min_revision = revision;
3194 ai->version.build = build;
3195 ai->version.revision = revision;
3196 RtlFreeHeap( GetProcessHeap(), 0, ret );
3197 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3199 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3200 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3204 else WARN("no matching file for %s\n", debugstr_w(lookup));
3205 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3206 return ret;
3209 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3211 struct assembly_identity sxs_ai;
3212 UNICODE_STRING path_us;
3213 OBJECT_ATTRIBUTES attr;
3214 IO_STATUS_BLOCK io;
3215 WCHAR *path, *file = NULL;
3216 HANDLE handle;
3218 static const WCHAR manifest_dirW[] =
3219 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3221 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3223 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3224 wcslen(windows_dir) * sizeof(WCHAR) )))
3225 return STATUS_NO_MEMORY;
3227 wcscpy( path, windows_dir );
3228 wcscat( path, manifest_dirW );
3230 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3232 RtlFreeHeap( GetProcessHeap(), 0, path );
3233 return STATUS_NO_SUCH_FILE;
3235 RtlFreeHeap( GetProcessHeap(), 0, path );
3237 attr.Length = sizeof(attr);
3238 attr.RootDirectory = 0;
3239 attr.Attributes = OBJ_CASE_INSENSITIVE;
3240 attr.ObjectName = &path_us;
3241 attr.SecurityDescriptor = NULL;
3242 attr.SecurityQualityOfService = NULL;
3244 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3245 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3247 sxs_ai = *ai;
3248 file = lookup_manifest_file( handle, &sxs_ai );
3249 NtClose( handle );
3251 if (!file)
3253 RtlFreeUnicodeString( &path_us );
3254 return STATUS_NO_SUCH_FILE;
3257 /* append file name to directory path */
3258 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3259 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3261 RtlFreeHeap( GetProcessHeap(), 0, file );
3262 RtlFreeUnicodeString( &path_us );
3263 return STATUS_NO_MEMORY;
3266 path[path_us.Length/sizeof(WCHAR)] = '\\';
3267 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3268 RtlInitUnicodeString( &path_us, path );
3269 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3271 if (!open_nt_file( &handle, &path_us ))
3273 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3274 NtClose( handle );
3276 else io.u.Status = STATUS_NO_SUCH_FILE;
3278 RtlFreeHeap( GetProcessHeap(), 0, file );
3279 RtlFreeUnicodeString( &path_us );
3280 return io.u.Status;
3283 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3284 struct assembly_identity* ai)
3286 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3287 unsigned int i;
3288 WCHAR *buffer, *p, *directory;
3289 NTSTATUS status;
3290 UNICODE_STRING nameW;
3291 HANDLE file;
3292 DWORD len;
3294 TRACE( "looking for name=%s version=%s arch=%s\n",
3295 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3297 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3299 /* FIXME: add support for language specific lookup */
3301 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3302 wcslen(acl->actctx->appdir.info));
3304 nameW.Buffer = NULL;
3305 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3306 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3307 return STATUS_NO_MEMORY;
3309 if (!(directory = build_assembly_dir( ai )))
3311 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3312 return STATUS_NO_MEMORY;
3315 /* Lookup in <dir>\name.dll
3316 * <dir>\name.manifest
3317 * <dir>\name\name.dll
3318 * <dir>\name\name.manifest
3320 * First 'appdir' is used as <dir>, if that failed
3321 * it tries application manifest file path.
3323 wcscpy( buffer, acl->actctx->appdir.info );
3324 p = buffer + wcslen(buffer);
3325 for (i = 0; i < 4; i++)
3327 if (i == 2)
3329 struct assembly *assembly = acl->actctx->assemblies;
3330 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3332 else *p++ = '\\';
3334 wcscpy( p, ai->name );
3335 p += wcslen(p);
3337 wcscpy( p, dotDllW );
3338 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3340 status = open_nt_file( &file, &nameW );
3341 if (!status)
3343 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3344 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3345 NtClose( file );
3346 if (status == STATUS_SUCCESS)
3347 break;
3349 RtlFreeUnicodeString( &nameW );
3352 wcscpy( p, dotManifestW );
3353 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3355 status = open_nt_file( &file, &nameW );
3356 if (!status)
3358 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3359 NtClose( file );
3360 break;
3362 RtlFreeUnicodeString( &nameW );
3364 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3366 RtlFreeUnicodeString( &nameW );
3367 RtlFreeHeap( GetProcessHeap(), 0, directory );
3368 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3369 return status;
3372 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3374 NTSTATUS status = STATUS_SUCCESS;
3375 unsigned int i;
3377 for (i = 0; i < acl->num_dependencies; i++)
3379 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3381 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3383 FIXME( "Could not find dependent assembly %s (%s)\n",
3384 debugstr_w(acl->dependencies[i].name),
3385 debugstr_version(&acl->dependencies[i].version) );
3386 status = STATUS_SXS_CANT_GEN_ACTCTX;
3387 break;
3391 /* FIXME should now iterate through all refs */
3392 return status;
3395 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3396 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3398 NTSTATUS status = STATUS_SUCCESS;
3400 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3402 if (*handle) return STATUS_INVALID_PARAMETER;
3404 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3405 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3407 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3409 ULONG_PTR magic;
3410 LDR_DATA_TABLE_ENTRY *pldr;
3412 if (!*handle) return STATUS_INVALID_PARAMETER;
3414 LdrLockLoaderLock( 0, NULL, &magic );
3415 if (!LdrFindEntryForAddress( *handle, &pldr ))
3417 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3418 status = STATUS_DLL_NOT_FOUND;
3419 else
3420 *handle = pldr->ActivationContext;
3422 else status = STATUS_DLL_NOT_FOUND;
3423 LdrUnlockLoaderLock( 0, magic );
3425 else if (!*handle && (class != ActivationContextBasicInformation))
3426 *handle = process_actctx;
3428 return status;
3431 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3433 unsigned int i, j, total_len = 0, dll_count = 0;
3434 struct strsection_header *header;
3435 struct dllredirect_data *data;
3436 struct string_index *index;
3437 ULONG name_offset;
3439 /* compute section length */
3440 for (i = 0; i < actctx->num_assemblies; i++)
3442 struct assembly *assembly = &actctx->assemblies[i];
3443 for (j = 0; j < assembly->num_dlls; j++)
3445 struct dll_redirect *dll = &assembly->dlls[j];
3447 /* each entry needs index, data and string data */
3448 total_len += sizeof(*index);
3449 total_len += sizeof(*data);
3450 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3453 dll_count += assembly->num_dlls;
3456 total_len += sizeof(*header);
3458 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3459 if (!header) return STATUS_NO_MEMORY;
3461 memset(header, 0, sizeof(*header));
3462 header->magic = STRSECTION_MAGIC;
3463 header->size = sizeof(*header);
3464 header->count = dll_count;
3465 header->index_offset = sizeof(*header);
3466 index = (struct string_index*)((BYTE*)header + header->index_offset);
3467 name_offset = header->index_offset + header->count*sizeof(*index);
3469 for (i = 0; i < actctx->num_assemblies; i++)
3471 struct assembly *assembly = &actctx->assemblies[i];
3472 for (j = 0; j < assembly->num_dlls; j++)
3474 struct dll_redirect *dll = &assembly->dlls[j];
3475 UNICODE_STRING str;
3476 WCHAR *ptrW;
3478 /* setup new index entry */
3479 str.Buffer = dll->name;
3480 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3481 str.MaximumLength = str.Length + sizeof(WCHAR);
3482 /* hash original class name */
3483 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3485 index->name_offset = name_offset;
3486 index->name_len = str.Length;
3487 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3488 index->data_len = sizeof(*data);
3489 index->rosterindex = i + 1;
3491 /* setup data */
3492 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3493 data->size = sizeof(*data);
3494 data->unk = 2; /* FIXME: seems to be constant */
3495 memset(data->res, 0, sizeof(data->res));
3497 /* dll name */
3498 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3499 memcpy(ptrW, dll->name, index->name_len);
3500 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3502 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3504 index++;
3508 *section = header;
3510 return STATUS_SUCCESS;
3513 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3515 struct string_index *iter, *index = NULL;
3516 UNICODE_STRING str;
3517 ULONG hash = 0, i;
3519 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3520 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3522 for (i = 0; i < section->count; i++)
3524 if (iter->hash == hash)
3526 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3527 str.Length = iter->name_len;
3528 if (RtlEqualUnicodeString( &str, name, TRUE ))
3530 index = iter;
3531 break;
3533 else
3534 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3536 iter++;
3539 return index;
3542 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3544 struct guid_index *iter, *index = NULL;
3545 ULONG i;
3547 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3549 for (i = 0; i < section->count; i++)
3551 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3553 index = iter;
3554 break;
3556 iter++;
3559 return index;
3562 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3564 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3567 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3568 PACTCTX_SECTION_KEYED_DATA data)
3570 struct dllredirect_data *dll;
3571 struct string_index *index;
3573 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3575 if (!actctx->dllredirect_section)
3577 struct strsection_header *section;
3579 NTSTATUS status = build_dllredirect_section(actctx, &section);
3580 if (status) return status;
3582 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3583 RtlFreeHeap(GetProcessHeap(), 0, section);
3586 index = find_string_index(actctx->dllredirect_section, name);
3587 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3589 if (data)
3591 dll = get_dllredirect_data(actctx, index);
3593 data->ulDataFormatVersion = 1;
3594 data->lpData = dll;
3595 data->ulLength = dll->size;
3596 data->lpSectionGlobalData = NULL;
3597 data->ulSectionGlobalDataLength = 0;
3598 data->lpSectionBase = actctx->dllredirect_section;
3599 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3600 data->hActCtx = NULL;
3602 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3603 data->ulAssemblyRosterIndex = index->rosterindex;
3606 return STATUS_SUCCESS;
3609 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3611 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3614 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3616 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3619 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3621 unsigned int i, j, k, total_len = 0, class_count = 0;
3622 struct wndclass_redirect_data *data;
3623 struct strsection_header *header;
3624 struct string_index *index;
3625 ULONG name_offset;
3627 /* compute section length */
3628 for (i = 0; i < actctx->num_assemblies; i++)
3630 struct assembly *assembly = &actctx->assemblies[i];
3631 for (j = 0; j < assembly->num_dlls; j++)
3633 struct dll_redirect *dll = &assembly->dlls[j];
3634 for (k = 0; k < dll->entities.num; k++)
3636 struct entity *entity = &dll->entities.base[k];
3637 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3639 int class_len = wcslen(entity->u.class.name) + 1;
3640 int len;
3642 /* each class entry needs index, data and string data */
3643 total_len += sizeof(*index);
3644 total_len += sizeof(*data);
3645 /* original name is stored separately */
3646 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3647 /* versioned name and module name are stored one after another */
3648 if (entity->u.class.versioned)
3649 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3650 else
3651 len = class_len;
3652 len += wcslen(dll->name) + 1;
3653 total_len += aligned_string_len(len*sizeof(WCHAR));
3655 class_count++;
3661 total_len += sizeof(*header);
3663 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3664 if (!header) return STATUS_NO_MEMORY;
3666 memset(header, 0, sizeof(*header));
3667 header->magic = STRSECTION_MAGIC;
3668 header->size = sizeof(*header);
3669 header->count = class_count;
3670 header->index_offset = sizeof(*header);
3671 index = (struct string_index*)((BYTE*)header + header->index_offset);
3672 name_offset = header->index_offset + header->count*sizeof(*index);
3674 for (i = 0; i < actctx->num_assemblies; i++)
3676 struct assembly *assembly = &actctx->assemblies[i];
3677 for (j = 0; j < assembly->num_dlls; j++)
3679 struct dll_redirect *dll = &assembly->dlls[j];
3680 for (k = 0; k < dll->entities.num; k++)
3682 struct entity *entity = &dll->entities.base[k];
3683 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3685 static const WCHAR exclW[] = {'!',0};
3686 ULONG versioned_len, module_len;
3687 UNICODE_STRING str;
3688 WCHAR *ptrW;
3690 /* setup new index entry */
3691 str.Buffer = entity->u.class.name;
3692 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3693 str.MaximumLength = str.Length + sizeof(WCHAR);
3694 /* hash original class name */
3695 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3697 /* include '!' separator too */
3698 if (entity->u.class.versioned)
3699 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3700 else
3701 versioned_len = str.Length;
3702 module_len = wcslen(dll->name)*sizeof(WCHAR);
3704 index->name_offset = name_offset;
3705 index->name_len = str.Length;
3706 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3707 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3708 index->rosterindex = i + 1;
3710 /* setup data */
3711 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3712 data->size = sizeof(*data);
3713 data->res = 0;
3714 data->name_len = versioned_len;
3715 data->name_offset = sizeof(*data);
3716 data->module_len = module_len;
3717 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3719 /* original class name */
3720 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3721 memcpy(ptrW, entity->u.class.name, index->name_len);
3722 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3724 /* module name */
3725 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3726 memcpy(ptrW, dll->name, data->module_len);
3727 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3729 /* versioned name */
3730 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3731 if (entity->u.class.versioned)
3733 get_assembly_version(assembly, ptrW);
3734 wcscat(ptrW, exclW);
3735 wcscat(ptrW, entity->u.class.name);
3737 else
3739 memcpy(ptrW, entity->u.class.name, index->name_len);
3740 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3743 name_offset += sizeof(*data);
3744 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3746 index++;
3752 *section = header;
3754 return STATUS_SUCCESS;
3757 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3758 PACTCTX_SECTION_KEYED_DATA data)
3760 struct string_index *iter, *index = NULL;
3761 struct wndclass_redirect_data *class;
3762 UNICODE_STRING str;
3763 ULONG hash;
3764 int i;
3766 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3768 if (!actctx->wndclass_section)
3770 struct strsection_header *section;
3772 NTSTATUS status = build_wndclass_section(actctx, &section);
3773 if (status) return status;
3775 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3776 RtlFreeHeap(GetProcessHeap(), 0, section);
3779 hash = 0;
3780 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3781 iter = get_wndclass_first_index(actctx);
3783 for (i = 0; i < actctx->wndclass_section->count; i++)
3785 if (iter->hash == hash)
3787 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3788 str.Length = iter->name_len;
3789 if (RtlEqualUnicodeString( &str, name, TRUE ))
3791 index = iter;
3792 break;
3794 else
3795 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3797 iter++;
3800 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3802 if (data)
3804 class = get_wndclass_data(actctx, index);
3806 data->ulDataFormatVersion = 1;
3807 data->lpData = class;
3808 /* full length includes string length with nulls */
3809 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3810 data->lpSectionGlobalData = NULL;
3811 data->ulSectionGlobalDataLength = 0;
3812 data->lpSectionBase = actctx->wndclass_section;
3813 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3814 data->hActCtx = NULL;
3816 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3817 data->ulAssemblyRosterIndex = index->rosterindex;
3820 return STATUS_SUCCESS;
3823 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3825 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3826 struct guidsection_header *header;
3827 ULONG module_offset, data_offset;
3828 struct tlibredirect_data *data;
3829 struct guid_index *index;
3831 /* compute section length */
3832 for (i = 0; i < actctx->num_assemblies; i++)
3834 struct assembly *assembly = &actctx->assemblies[i];
3835 for (j = 0; j < assembly->num_dlls; j++)
3837 struct dll_redirect *dll = &assembly->dlls[j];
3838 for (k = 0; k < dll->entities.num; k++)
3840 struct entity *entity = &dll->entities.base[k];
3841 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3843 /* each entry needs index, data and string data for module name and help string */
3844 total_len += sizeof(*index);
3845 total_len += sizeof(*data);
3846 /* help string is stored separately */
3847 if (*entity->u.typelib.helpdir)
3848 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3850 /* module names are packed one after another */
3851 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
3853 tlib_count++;
3859 total_len += aligned_string_len(names_len);
3860 total_len += sizeof(*header);
3862 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3863 if (!header) return STATUS_NO_MEMORY;
3865 memset(header, 0, sizeof(*header));
3866 header->magic = GUIDSECTION_MAGIC;
3867 header->size = sizeof(*header);
3868 header->count = tlib_count;
3869 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3870 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3871 module_offset = sizeof(*header);
3872 data_offset = header->index_offset + tlib_count*sizeof(*index);
3874 for (i = 0; i < actctx->num_assemblies; i++)
3876 struct assembly *assembly = &actctx->assemblies[i];
3877 for (j = 0; j < assembly->num_dlls; j++)
3879 struct dll_redirect *dll = &assembly->dlls[j];
3880 for (k = 0; k < dll->entities.num; k++)
3882 struct entity *entity = &dll->entities.base[k];
3883 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3885 ULONG module_len, help_len;
3886 UNICODE_STRING str;
3887 WCHAR *ptrW;
3889 if (*entity->u.typelib.helpdir)
3890 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
3891 else
3892 help_len = 0;
3894 module_len = wcslen(dll->name)*sizeof(WCHAR);
3896 /* setup new index entry */
3897 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3898 RtlGUIDFromString(&str, &index->guid);
3899 index->data_offset = data_offset;
3900 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3901 index->rosterindex = i + 1;
3903 /* setup data */
3904 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3905 data->size = sizeof(*data);
3906 data->res = 0;
3907 data->name_len = module_len;
3908 data->name_offset = module_offset;
3909 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3910 data->langid = 0;
3911 data->flags = entity->u.typelib.flags;
3912 data->help_len = help_len;
3913 data->help_offset = sizeof(*data);
3914 data->major_version = entity->u.typelib.major;
3915 data->minor_version = entity->u.typelib.minor;
3917 /* module name */
3918 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3919 memcpy(ptrW, dll->name, data->name_len);
3920 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3922 /* help string */
3923 if (data->help_len)
3925 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3926 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3927 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3930 data_offset += sizeof(*data);
3931 if (help_len)
3932 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3934 module_offset += module_len + sizeof(WCHAR);
3936 index++;
3942 *section = header;
3944 return STATUS_SUCCESS;
3947 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3949 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3952 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3954 struct guid_index *index = NULL;
3955 struct tlibredirect_data *tlib;
3957 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3959 if (!actctx->tlib_section)
3961 struct guidsection_header *section;
3963 NTSTATUS status = build_tlib_section(actctx, &section);
3964 if (status) return status;
3966 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3967 RtlFreeHeap(GetProcessHeap(), 0, section);
3970 index = find_guid_index(actctx->tlib_section, guid);
3971 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3973 tlib = get_tlib_data(actctx, index);
3975 data->ulDataFormatVersion = 1;
3976 data->lpData = tlib;
3977 /* full length includes string length with nulls */
3978 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3979 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3980 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3981 data->lpSectionBase = actctx->tlib_section;
3982 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3983 data->hActCtx = NULL;
3985 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3986 data->ulAssemblyRosterIndex = index->rosterindex;
3988 return STATUS_SUCCESS;
3991 static void generate_uuid(ULONG *seed, GUID *guid)
3993 ULONG *ptr = (ULONG*)guid;
3994 int i;
3996 /* GUID is 16 bytes long */
3997 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3998 *ptr = RtlUniform(seed);
4000 guid->Data3 &= 0x0fff;
4001 guid->Data3 |= (4 << 12);
4002 guid->Data4[0] &= 0x3f;
4003 guid->Data4[0] |= 0x80;
4006 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4007 unsigned int *count, unsigned int *len, unsigned int *module_len)
4009 unsigned int i;
4011 for (i = 0; i < entities->num; i++)
4013 struct entity *entity = &entities->base[i];
4014 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4016 /* each entry needs two index entries, extra one goes for alias GUID */
4017 *len += 2*sizeof(struct guid_index);
4018 /* To save some memory we don't allocated two data structures,
4019 instead alias index and normal index point to the same data structure. */
4020 *len += sizeof(struct comclassredirect_data);
4022 /* for clrClass store some more */
4023 if (entity->u.comclass.name)
4025 unsigned int str_len;
4027 /* all string data is stored together in aligned block */
4028 str_len = wcslen(entity->u.comclass.name)+1;
4029 if (entity->u.comclass.progid)
4030 str_len += wcslen(entity->u.comclass.progid)+1;
4031 if (entity->u.comclass.version)
4032 str_len += wcslen(entity->u.comclass.version)+1;
4034 *len += sizeof(struct clrclass_data);
4035 *len += aligned_string_len(str_len*sizeof(WCHAR));
4037 /* module name is forced to mscoree.dll, and stored two times with different case */
4038 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4040 else
4042 /* progid string is stored separately */
4043 if (entity->u.comclass.progid)
4044 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4046 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4049 *count += 1;
4054 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4055 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4056 ULONG *seed, ULONG rosterindex)
4058 unsigned int i;
4060 for (i = 0; i < entities->num; i++)
4062 struct entity *entity = &entities->base[i];
4063 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4065 ULONG module_len, progid_len, str_len = 0, miscmask;
4066 struct comclassredirect_data *data;
4067 struct guid_index *alias_index;
4068 struct clrclass_data *clrdata;
4069 UNICODE_STRING str;
4070 WCHAR *ptrW;
4072 if (entity->u.comclass.progid)
4073 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4074 else
4075 progid_len = 0;
4077 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(mscoreeW)*sizeof(WCHAR);
4079 /* setup new index entry */
4080 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4081 RtlGUIDFromString(&str, &(*index)->guid);
4083 (*index)->data_offset = *data_offset;
4084 (*index)->data_len = sizeof(*data); /* additional length added later */
4085 (*index)->rosterindex = rosterindex;
4087 /* Setup new index entry for alias guid. Alias index records are placed after
4088 normal records, so normal guids are hit first on search. Note that class count
4089 is doubled. */
4090 alias_index = (*index) + section->count/2;
4091 generate_uuid(seed, &alias_index->guid);
4092 alias_index->data_offset = (*index)->data_offset;
4093 alias_index->data_len = 0;
4094 alias_index->rosterindex = (*index)->rosterindex;
4096 /* setup data */
4097 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4098 data->size = sizeof(*data);
4099 data->model = entity->u.comclass.model;
4100 data->clsid = (*index)->guid;
4101 data->alias = alias_index->guid;
4102 data->clsid2 = data->clsid;
4103 if (entity->u.comclass.tlbid)
4105 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4106 RtlGUIDFromString(&str, &data->tlbid);
4108 else
4109 memset(&data->tlbid, 0, sizeof(data->tlbid));
4110 data->name_len = module_len;
4111 data->name_offset = *module_offset;
4112 data->progid_len = progid_len;
4113 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4114 data->clrdata_len = 0; /* will be set later */
4115 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4116 data->miscstatus = entity->u.comclass.miscstatus;
4117 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4118 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4119 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4120 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4122 /* mask describes which misc* data is available */
4123 miscmask = 0;
4124 if (data->miscstatus)
4125 miscmask |= MiscStatus;
4126 if (data->miscstatuscontent)
4127 miscmask |= MiscStatusContent;
4128 if (data->miscstatusthumbnail)
4129 miscmask |= MiscStatusThumbnail;
4130 if (data->miscstatusicon)
4131 miscmask |= MiscStatusIcon;
4132 if (data->miscstatusdocprint)
4133 miscmask |= MiscStatusDocPrint;
4134 data->flags = miscmask << 8;
4136 if (data->clrdata_offset)
4138 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4140 clrdata->size = sizeof(*clrdata);
4141 clrdata->res[0] = 0;
4142 clrdata->res[1] = 2; /* FIXME: unknown field */
4143 clrdata->module_len = wcslen(mscoreeW)*sizeof(WCHAR);
4144 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4145 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4146 clrdata->name_offset = clrdata->size;
4147 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4148 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4149 clrdata->res2[0] = 0;
4150 clrdata->res2[1] = 0;
4152 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4154 /* module name */
4155 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4156 memcpy(ptrW, mscoree2W, clrdata->module_len);
4157 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4159 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4160 memcpy(ptrW, mscoreeW, data->name_len);
4161 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4163 /* class name */
4164 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4165 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4166 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4168 /* runtime version, optional */
4169 if (clrdata->version_len)
4171 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4173 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4174 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4175 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4178 if (data->progid_len)
4179 data->progid_offset += data->clrdata_len;
4180 (*index)->data_len += sizeof(*clrdata);
4182 else
4184 clrdata = NULL;
4186 /* module name */
4187 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4188 memcpy(ptrW, dll->name, data->name_len);
4189 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4192 /* progid string */
4193 if (data->progid_len)
4195 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4196 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4197 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4200 /* string block length */
4201 str_len = 0;
4202 if (clrdata)
4204 str_len += clrdata->name_len + sizeof(WCHAR);
4205 if (clrdata->version_len)
4206 str_len += clrdata->version_len + sizeof(WCHAR);
4208 if (progid_len)
4209 str_len += progid_len + sizeof(WCHAR);
4211 (*index)->data_len += aligned_string_len(str_len);
4212 alias_index->data_len = (*index)->data_len;
4214 /* move to next data record */
4215 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4216 (*module_offset) += module_len + sizeof(WCHAR);
4218 if (clrdata)
4220 (*data_offset) += sizeof(*clrdata);
4221 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4223 (*index) += 1;
4228 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4230 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4231 struct guidsection_header *header;
4232 ULONG module_offset, data_offset;
4233 struct guid_index *index;
4234 ULONG seed;
4236 /* compute section length */
4237 for (i = 0; i < actctx->num_assemblies; i++)
4239 struct assembly *assembly = &actctx->assemblies[i];
4240 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4241 for (j = 0; j < assembly->num_dlls; j++)
4243 struct dll_redirect *dll = &assembly->dlls[j];
4244 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4248 total_len += aligned_string_len(names_len);
4249 total_len += sizeof(*header);
4251 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4252 if (!header) return STATUS_NO_MEMORY;
4254 memset(header, 0, sizeof(*header));
4255 header->magic = GUIDSECTION_MAGIC;
4256 header->size = sizeof(*header);
4257 header->count = 2*class_count;
4258 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4259 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4260 module_offset = sizeof(*header);
4261 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4263 seed = NtGetTickCount();
4264 for (i = 0; i < actctx->num_assemblies; i++)
4266 struct assembly *assembly = &actctx->assemblies[i];
4267 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4268 for (j = 0; j < assembly->num_dlls; j++)
4270 struct dll_redirect *dll = &assembly->dlls[j];
4271 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4275 *section = header;
4277 return STATUS_SUCCESS;
4280 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4282 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4285 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4287 struct comclassredirect_data *comclass;
4288 struct guid_index *index = NULL;
4290 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4292 if (!actctx->comserver_section)
4294 struct guidsection_header *section;
4296 NTSTATUS status = build_comserver_section(actctx, &section);
4297 if (status) return status;
4299 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4300 RtlFreeHeap(GetProcessHeap(), 0, section);
4303 index = find_guid_index(actctx->comserver_section, guid);
4304 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4306 comclass = get_comclass_data(actctx, index);
4308 data->ulDataFormatVersion = 1;
4309 data->lpData = comclass;
4310 /* full length includes string length with nulls */
4311 data->ulLength = comclass->size + comclass->clrdata_len;
4312 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4313 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4314 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4315 data->lpSectionBase = actctx->comserver_section;
4316 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4317 data->hActCtx = NULL;
4319 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4320 data->ulAssemblyRosterIndex = index->rosterindex;
4322 return STATUS_SUCCESS;
4325 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4327 unsigned int i;
4329 for (i = 0; i < entities->num; i++)
4331 struct entity *entity = &entities->base[i];
4332 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4334 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4335 if (entity->u.ifaceps.name)
4336 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4337 *count += 1;
4342 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4343 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4345 unsigned int i;
4347 for (i = 0; i < entities->num; i++)
4349 struct entity *entity = &entities->base[i];
4350 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4352 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4353 UNICODE_STRING str;
4354 ULONG name_len;
4356 if (entity->u.ifaceps.name)
4357 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4358 else
4359 name_len = 0;
4361 /* setup index */
4362 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4363 RtlGUIDFromString(&str, &(*index)->guid);
4364 (*index)->data_offset = *data_offset;
4365 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4366 (*index)->rosterindex = rosterindex;
4368 /* setup data record */
4369 data->size = sizeof(*data);
4370 data->mask = entity->u.ifaceps.mask;
4372 /* proxyStubClsid32 value is only stored for external PS,
4373 if set it's used as iid, otherwise 'iid' attribute value is used */
4374 if (entity->u.ifaceps.ps32)
4376 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4377 RtlGUIDFromString(&str, &data->iid);
4379 else
4380 data->iid = (*index)->guid;
4382 data->nummethods = entity->u.ifaceps.nummethods;
4384 if (entity->u.ifaceps.tlib)
4386 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4387 RtlGUIDFromString(&str, &data->tlbid);
4389 else
4390 memset(&data->tlbid, 0, sizeof(data->tlbid));
4392 if (entity->u.ifaceps.base)
4394 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4395 RtlGUIDFromString(&str, &data->base);
4397 else
4398 memset(&data->base, 0, sizeof(data->base));
4400 data->name_len = name_len;
4401 data->name_offset = data->name_len ? sizeof(*data) : 0;
4403 /* name string */
4404 if (data->name_len)
4406 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4407 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4408 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4411 /* move to next record */
4412 (*index) += 1;
4413 *data_offset += sizeof(*data);
4414 if (data->name_len)
4415 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4420 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4422 unsigned int i, j, total_len = 0, count = 0;
4423 struct guidsection_header *header;
4424 struct guid_index *index;
4425 ULONG data_offset;
4427 /* compute section length */
4428 for (i = 0; i < actctx->num_assemblies; i++)
4430 struct assembly *assembly = &actctx->assemblies[i];
4432 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4433 for (j = 0; j < assembly->num_dlls; j++)
4435 struct dll_redirect *dll = &assembly->dlls[j];
4436 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4440 total_len += sizeof(*header);
4442 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4443 if (!header) return STATUS_NO_MEMORY;
4445 memset(header, 0, sizeof(*header));
4446 header->magic = GUIDSECTION_MAGIC;
4447 header->size = sizeof(*header);
4448 header->count = count;
4449 header->index_offset = sizeof(*header);
4450 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4451 data_offset = header->index_offset + count*sizeof(*index);
4453 for (i = 0; i < actctx->num_assemblies; i++)
4455 struct assembly *assembly = &actctx->assemblies[i];
4457 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4458 for (j = 0; j < assembly->num_dlls; j++)
4460 struct dll_redirect *dll = &assembly->dlls[j];
4461 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4465 *section = header;
4467 return STATUS_SUCCESS;
4470 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4472 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4475 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4477 struct ifacepsredirect_data *iface;
4478 struct guid_index *index = NULL;
4480 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4482 if (!actctx->ifaceps_section)
4484 struct guidsection_header *section;
4486 NTSTATUS status = build_ifaceps_section(actctx, &section);
4487 if (status) return status;
4489 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4490 RtlFreeHeap(GetProcessHeap(), 0, section);
4493 index = find_guid_index(actctx->ifaceps_section, guid);
4494 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4496 iface = get_ifaceps_data(actctx, index);
4498 data->ulDataFormatVersion = 1;
4499 data->lpData = iface;
4500 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4501 data->lpSectionGlobalData = NULL;
4502 data->ulSectionGlobalDataLength = 0;
4503 data->lpSectionBase = actctx->ifaceps_section;
4504 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4505 data->hActCtx = NULL;
4507 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4508 data->ulAssemblyRosterIndex = index->rosterindex;
4510 return STATUS_SUCCESS;
4513 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4515 unsigned int i, j, total_len = 0, count = 0;
4516 struct guidsection_header *header;
4517 struct clrsurrogate_data *data;
4518 struct guid_index *index;
4519 ULONG data_offset;
4521 /* compute section length */
4522 for (i = 0; i < actctx->num_assemblies; i++)
4524 struct assembly *assembly = &actctx->assemblies[i];
4525 for (j = 0; j < assembly->entities.num; j++)
4527 struct entity *entity = &assembly->entities.base[j];
4528 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4530 ULONG len;
4532 total_len += sizeof(*index) + sizeof(*data);
4533 len = wcslen(entity->u.clrsurrogate.name) + 1;
4534 if (entity->u.clrsurrogate.version)
4535 len += wcslen(entity->u.clrsurrogate.version) + 1;
4536 total_len += aligned_string_len(len*sizeof(WCHAR));
4538 count++;
4543 total_len += sizeof(*header);
4545 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4546 if (!header) return STATUS_NO_MEMORY;
4548 memset(header, 0, sizeof(*header));
4549 header->magic = GUIDSECTION_MAGIC;
4550 header->size = sizeof(*header);
4551 header->count = count;
4552 header->index_offset = sizeof(*header);
4553 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4554 data_offset = header->index_offset + count*sizeof(*index);
4556 for (i = 0; i < actctx->num_assemblies; i++)
4558 struct assembly *assembly = &actctx->assemblies[i];
4559 for (j = 0; j < assembly->entities.num; j++)
4561 struct entity *entity = &assembly->entities.base[j];
4562 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4564 ULONG version_len, name_len;
4565 UNICODE_STRING str;
4566 WCHAR *ptrW;
4568 if (entity->u.clrsurrogate.version)
4569 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4570 else
4571 version_len = 0;
4572 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4574 /* setup new index entry */
4575 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4576 RtlGUIDFromString(&str, &index->guid);
4578 index->data_offset = data_offset;
4579 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4580 index->rosterindex = i + 1;
4582 /* setup data */
4583 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4584 data->size = sizeof(*data);
4585 data->res = 0;
4586 data->clsid = index->guid;
4587 data->version_offset = version_len ? data->size : 0;
4588 data->version_len = version_len;
4589 data->name_offset = data->size + version_len;
4590 if (version_len)
4591 data->name_offset += sizeof(WCHAR);
4592 data->name_len = name_len;
4594 /* surrogate name */
4595 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4596 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4597 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4599 /* runtime version */
4600 if (data->version_len)
4602 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4603 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4604 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4607 data_offset += index->data_offset;
4608 index++;
4613 *section = header;
4615 return STATUS_SUCCESS;
4618 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4620 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4623 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4625 struct clrsurrogate_data *surrogate;
4626 struct guid_index *index = NULL;
4628 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4630 if (!actctx->clrsurrogate_section)
4632 struct guidsection_header *section;
4634 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4635 if (status) return status;
4637 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4638 RtlFreeHeap(GetProcessHeap(), 0, section);
4641 index = find_guid_index(actctx->clrsurrogate_section, guid);
4642 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4644 surrogate = get_surrogate_data(actctx, index);
4646 data->ulDataFormatVersion = 1;
4647 data->lpData = surrogate;
4648 /* full length includes string length with nulls */
4649 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4650 if (surrogate->version_len)
4651 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4653 data->lpSectionGlobalData = NULL;
4654 data->ulSectionGlobalDataLength = 0;
4655 data->lpSectionBase = actctx->clrsurrogate_section;
4656 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4657 data->hActCtx = NULL;
4659 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4660 data->ulAssemblyRosterIndex = index->rosterindex;
4662 return STATUS_SUCCESS;
4665 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4667 unsigned int i, j, single_len;
4669 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4670 for (i = 0; i < entities->num; i++)
4672 struct entity *entity = &entities->base[i];
4673 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4675 if (entity->u.comclass.progid)
4677 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4678 *count += 1;
4681 for (j = 0; j < entity->u.comclass.progids.num; j++)
4682 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4684 *total_len += single_len*entity->u.comclass.progids.num;
4685 *count += entity->u.comclass.progids.num;
4690 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4691 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4693 struct progidredirect_data *data;
4694 UNICODE_STRING str;
4695 GUID *guid_ptr;
4696 WCHAR *ptrW;
4698 /* setup new index entry */
4700 /* hash progid name */
4701 RtlInitUnicodeString(&str, progid);
4702 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4704 (*index)->name_offset = *data_offset;
4705 (*index)->name_len = str.Length;
4706 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4707 (*index)->data_len = sizeof(*data);
4708 (*index)->rosterindex = rosterindex;
4710 *data_offset += aligned_string_len(str.MaximumLength);
4712 /* setup data structure */
4713 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4714 data->size = sizeof(*data);
4715 data->reserved = 0;
4716 data->clsid_offset = *global_offset;
4718 /* write progid string */
4719 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4720 memcpy(ptrW, progid, (*index)->name_len);
4721 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4723 /* write guid to global area */
4724 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4725 *guid_ptr = *alias;
4727 /* to next entry */
4728 *global_offset += sizeof(GUID);
4729 *data_offset += data->size;
4730 (*index) += 1;
4733 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4734 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4736 unsigned int i, j;
4738 for (i = 0; i < entities->num; i++)
4740 struct entity *entity = &entities->base[i];
4741 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4743 const struct progids *progids = &entity->u.comclass.progids;
4744 struct comclassredirect_data *comclass;
4745 struct guid_index *guid_index;
4746 UNICODE_STRING str;
4747 GUID clsid;
4749 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4750 RtlGUIDFromString(&str, &clsid);
4752 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4753 comclass = get_comclass_data(actctx, guid_index);
4755 if (entity->u.comclass.progid)
4756 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4757 index, data_offset, global_offset, rosterindex);
4759 for (j = 0; j < progids->num; j++)
4760 write_progid_record(section, progids->progids[j], &comclass->alias,
4761 index, data_offset, global_offset, rosterindex);
4766 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4768 unsigned int i, j, total_len = 0, count = 0;
4769 struct strsection_header *header;
4770 ULONG data_offset, global_offset;
4771 struct string_index *index;
4773 /* compute section length */
4774 for (i = 0; i < actctx->num_assemblies; i++)
4776 struct assembly *assembly = &actctx->assemblies[i];
4778 get_progid_datalen(&assembly->entities, &count, &total_len);
4779 for (j = 0; j < assembly->num_dlls; j++)
4781 struct dll_redirect *dll = &assembly->dlls[j];
4782 get_progid_datalen(&dll->entities, &count, &total_len);
4786 total_len += sizeof(*header);
4788 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4789 if (!header) return STATUS_NO_MEMORY;
4791 memset(header, 0, sizeof(*header));
4792 header->magic = STRSECTION_MAGIC;
4793 header->size = sizeof(*header);
4794 header->count = count;
4795 header->global_offset = header->size;
4796 header->global_len = count*sizeof(GUID);
4797 header->index_offset = header->size + header->global_len;
4799 index = (struct string_index*)((BYTE*)header + header->index_offset);
4800 data_offset = header->index_offset + count*sizeof(*index);
4801 global_offset = header->global_offset;
4803 for (i = 0; i < actctx->num_assemblies; i++)
4805 struct assembly *assembly = &actctx->assemblies[i];
4807 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4808 for (j = 0; j < assembly->num_dlls; j++)
4810 struct dll_redirect *dll = &assembly->dlls[j];
4811 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4815 *section = header;
4817 return STATUS_SUCCESS;
4820 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4822 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4825 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4826 PACTCTX_SECTION_KEYED_DATA data)
4828 struct progidredirect_data *progid;
4829 struct string_index *index;
4831 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4833 if (!actctx->comserver_section)
4835 struct guidsection_header *section;
4837 NTSTATUS status = build_comserver_section(actctx, &section);
4838 if (status) return status;
4840 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4841 RtlFreeHeap(GetProcessHeap(), 0, section);
4844 if (!actctx->progid_section)
4846 struct strsection_header *section;
4848 NTSTATUS status = build_progid_section(actctx, &section);
4849 if (status) return status;
4851 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4852 RtlFreeHeap(GetProcessHeap(), 0, section);
4855 index = find_string_index(actctx->progid_section, name);
4856 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4858 if (data)
4860 progid = get_progid_data(actctx, index);
4862 data->ulDataFormatVersion = 1;
4863 data->lpData = progid;
4864 data->ulLength = progid->size;
4865 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4866 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4867 data->lpSectionBase = actctx->progid_section;
4868 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4869 data->hActCtx = NULL;
4871 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4872 data->ulAssemblyRosterIndex = index->rosterindex;
4875 return STATUS_SUCCESS;
4878 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4879 const UNICODE_STRING *section_name,
4880 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4882 NTSTATUS status;
4884 switch (section_kind)
4886 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4887 status = find_dll_redirection(actctx, section_name, data);
4888 break;
4889 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4890 status = find_window_class(actctx, section_name, data);
4891 break;
4892 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4893 status = find_progid_redirection(actctx, section_name, data);
4894 break;
4895 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4896 FIXME("Unsupported yet section_kind %x\n", section_kind);
4897 return STATUS_SXS_SECTION_NOT_FOUND;
4898 default:
4899 WARN("Unknown section_kind %x\n", section_kind);
4900 return STATUS_SXS_SECTION_NOT_FOUND;
4903 if (status != STATUS_SUCCESS) return status;
4905 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4907 actctx_addref(actctx);
4908 data->hActCtx = actctx;
4910 return STATUS_SUCCESS;
4913 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4914 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4916 NTSTATUS status;
4918 switch (section_kind)
4920 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4921 status = find_tlib_redirection(actctx, guid, data);
4922 break;
4923 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4924 status = find_comserver_redirection(actctx, guid, data);
4925 break;
4926 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4927 status = find_cominterface_redirection(actctx, guid, data);
4928 break;
4929 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4930 status = find_clr_surrogate(actctx, guid, data);
4931 break;
4932 default:
4933 WARN("Unknown section_kind %x\n", section_kind);
4934 return STATUS_SXS_SECTION_NOT_FOUND;
4937 if (status != STATUS_SUCCESS) return status;
4939 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4941 actctx_addref(actctx);
4942 data->hActCtx = actctx;
4944 return STATUS_SUCCESS;
4947 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4949 unsigned int i, j;
4951 for (i = 0; i < actctx->num_assemblies; i++)
4953 struct assembly *assembly = &actctx->assemblies[i];
4954 for (j = 0; j < assembly->entities.num; j++)
4956 struct entity *entity = &assembly->entities.base[j];
4957 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4958 !wcscmp( entity->u.settings.name, settings ) &&
4959 !wcscmp( entity->u.settings.ns, ns ))
4960 return entity->u.settings.value;
4963 return NULL;
4966 /* initialize the activation context for the current process */
4967 void actctx_init(void)
4969 ACTCTXW ctx;
4970 HANDLE handle;
4972 ctx.cbSize = sizeof(ctx);
4973 ctx.lpSource = NULL;
4974 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4975 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4976 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4978 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4980 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
4984 /***********************************************************************
4985 * RtlCreateActivationContext (NTDLL.@)
4987 * Create an activation context.
4989 * FIXME: function signature/prototype is wrong
4991 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4993 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4994 const WCHAR *directory = NULL;
4995 ACTIVATION_CONTEXT *actctx;
4996 UNICODE_STRING nameW;
4997 ULONG lang = 0;
4998 NTSTATUS status = STATUS_NO_MEMORY;
4999 HANDLE file = 0;
5000 struct actctx_loader acl;
5002 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
5004 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5005 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5006 return STATUS_INVALID_PARAMETER;
5008 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
5009 return STATUS_NO_MEMORY;
5011 actctx->magic = ACTCTX_MAGIC;
5012 actctx->ref_count = 1;
5013 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5014 actctx->config.info = NULL;
5015 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5016 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5018 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5020 else
5022 UNICODE_STRING dir;
5023 WCHAR *p;
5024 HMODULE module;
5026 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5027 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
5029 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5030 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5031 actctx->appdir.info = dir.Buffer;
5034 nameW.Buffer = NULL;
5036 /* open file only if it's going to be used */
5037 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5038 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5040 WCHAR *source = NULL;
5041 BOOLEAN ret;
5043 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5044 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5046 DWORD dir_len, source_len;
5048 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5049 source_len = wcslen(pActCtx->lpSource);
5050 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5052 status = STATUS_NO_MEMORY;
5053 goto error;
5056 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5057 source[dir_len] = '\\';
5058 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5061 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5062 RtlFreeHeap( GetProcessHeap(), 0, source );
5063 if (!ret)
5065 status = STATUS_NO_SUCH_FILE;
5066 goto error;
5068 status = open_nt_file( &file, &nameW );
5069 if (status)
5071 RtlFreeUnicodeString( &nameW );
5072 goto error;
5076 acl.actctx = actctx;
5077 acl.dependencies = NULL;
5078 acl.num_dependencies = 0;
5079 acl.allocated_dependencies = 0;
5081 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5082 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5084 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5086 /* if we have a resource it's a PE file */
5087 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5089 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5090 pActCtx->lpResourceName, lang );
5091 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5092 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5093 pActCtx->hModule, pActCtx->lpResourceName );
5095 else if (pActCtx->lpSource)
5097 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5098 file, pActCtx->lpResourceName, lang );
5099 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5100 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5101 NULL, pActCtx->lpResourceName );
5103 else status = STATUS_INVALID_PARAMETER;
5105 else
5107 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5110 if (file) NtClose( file );
5111 RtlFreeUnicodeString( &nameW );
5113 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5114 free_depend_manifests( &acl );
5116 if (status == STATUS_SUCCESS) *handle = actctx;
5117 else actctx_release( actctx );
5118 return status;
5120 error:
5121 if (file) NtClose( file );
5122 actctx_release( actctx );
5123 return status;
5127 /***********************************************************************
5128 * RtlAddRefActivationContext (NTDLL.@)
5130 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5132 ACTIVATION_CONTEXT *actctx;
5134 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5138 /******************************************************************
5139 * RtlReleaseActivationContext (NTDLL.@)
5141 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5143 ACTIVATION_CONTEXT *actctx;
5145 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5148 /******************************************************************
5149 * RtlZombifyActivationContext (NTDLL.@)
5151 * FIXME: function prototype might be wrong
5153 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5155 FIXME("%p: stub\n", handle);
5156 return STATUS_NOT_IMPLEMENTED;
5159 /******************************************************************
5160 * RtlActivateActivationContext (NTDLL.@)
5162 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5164 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5168 /******************************************************************
5169 * RtlActivateActivationContextEx (NTDLL.@)
5171 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5173 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5175 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5176 return STATUS_NO_MEMORY;
5178 frame->Previous = teb->ActivationContextStack.ActiveFrame;
5179 frame->ActivationContext = handle;
5180 frame->Flags = 0;
5181 teb->ActivationContextStack.ActiveFrame = frame;
5182 RtlAddRefActivationContext( handle );
5184 *cookie = (ULONG_PTR)frame;
5185 TRACE( "%p cookie=%lx\n", handle, *cookie );
5186 return STATUS_SUCCESS;
5190 /***********************************************************************
5191 * RtlDeactivateActivationContext (NTDLL.@)
5193 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5195 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5197 TRACE( "%x cookie=%lx\n", flags, cookie );
5199 /* find the right frame */
5200 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5201 for (frame = top; frame; frame = frame->Previous)
5202 if ((ULONG_PTR)frame == cookie) break;
5204 if (!frame)
5205 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5207 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5208 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5210 /* pop everything up to and including frame */
5211 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5213 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5215 frame = top->Previous;
5216 RtlReleaseActivationContext( top->ActivationContext );
5217 RtlFreeHeap( GetProcessHeap(), 0, top );
5218 top = frame;
5223 /******************************************************************
5224 * RtlFreeThreadActivationContextStack (NTDLL.@)
5226 void WINAPI RtlFreeThreadActivationContextStack(void)
5228 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5230 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5231 while (frame)
5233 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5234 RtlReleaseActivationContext( frame->ActivationContext );
5235 RtlFreeHeap( GetProcessHeap(), 0, frame );
5236 frame = prev;
5238 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5242 /******************************************************************
5243 * RtlGetActiveActivationContext (NTDLL.@)
5245 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5247 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5249 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5250 RtlAddRefActivationContext( *handle );
5252 else
5253 *handle = 0;
5255 return STATUS_SUCCESS;
5259 /******************************************************************
5260 * RtlIsActivationContextActive (NTDLL.@)
5262 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5264 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5266 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5267 if (frame->ActivationContext == handle) return TRUE;
5268 return FALSE;
5272 /***********************************************************************
5273 * RtlQueryInformationActivationContext (NTDLL.@)
5275 * Get information about an activation context.
5276 * FIXME: function signature/prototype may be wrong
5278 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5279 ULONG class, PVOID buffer,
5280 SIZE_T bufsize, SIZE_T *retlen )
5282 ACTIVATION_CONTEXT *actctx;
5283 NTSTATUS status;
5285 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5286 subinst, class, buffer, bufsize, retlen);
5288 if (retlen) *retlen = 0;
5289 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5291 switch (class)
5293 case ActivationContextBasicInformation:
5295 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5297 if (retlen) *retlen = sizeof(*info);
5298 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5300 info->hActCtx = handle;
5301 info->dwFlags = 0; /* FIXME */
5302 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5304 break;
5306 case ActivationContextDetailedInformation:
5308 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5309 struct assembly *assembly = NULL;
5310 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5311 LPWSTR ptr;
5313 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5315 if (actctx->num_assemblies) assembly = actctx->assemblies;
5317 if (assembly && assembly->manifest.info)
5318 manifest_len = wcslen(assembly->manifest.info) + 1;
5319 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5320 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5321 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5323 if (retlen) *retlen = len;
5324 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5326 acdi->dwFlags = 0;
5327 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5328 acdi->ulAssemblyCount = actctx->num_assemblies;
5329 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5330 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5331 acdi->ulRootConfigurationPathType = actctx->config.type;
5332 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5333 acdi->ulAppDirPathType = actctx->appdir.type;
5334 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5335 ptr = (LPWSTR)(acdi + 1);
5336 if (manifest_len)
5338 acdi->lpRootManifestPath = ptr;
5339 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5340 ptr += manifest_len;
5342 else acdi->lpRootManifestPath = NULL;
5343 if (config_len)
5345 acdi->lpRootConfigurationPath = ptr;
5346 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5347 ptr += config_len;
5349 else acdi->lpRootConfigurationPath = NULL;
5350 if (appdir_len)
5352 acdi->lpAppDirPath = ptr;
5353 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5355 else acdi->lpAppDirPath = NULL;
5357 break;
5359 case AssemblyDetailedInformationInActivationContext:
5361 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5362 struct assembly *assembly;
5363 WCHAR *assembly_id;
5364 DWORD index;
5365 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5366 LPWSTR ptr;
5368 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5369 if (!subinst) return STATUS_INVALID_PARAMETER;
5371 index = *(DWORD*)subinst;
5372 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5374 assembly = &actctx->assemblies[index - 1];
5376 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5377 id_len = wcslen(assembly_id) + 1;
5378 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5380 if (assembly->manifest.info &&
5381 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5382 path_len = wcslen(assembly->manifest.info) + 1;
5384 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5386 if (retlen) *retlen = len;
5387 if (!buffer || bufsize < len)
5389 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5390 return STATUS_BUFFER_TOO_SMALL;
5393 afdi->ulFlags = 0; /* FIXME */
5394 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5395 afdi->ulManifestPathType = assembly->manifest.type;
5396 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5397 /* FIXME afdi->liManifestLastWriteTime = 0; */
5398 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5399 afdi->ulPolicyPathLength = 0;
5400 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5401 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5402 afdi->ulManifestVersionMajor = 1;
5403 afdi->ulManifestVersionMinor = 0;
5404 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5405 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5406 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5407 ptr = (LPWSTR)(afdi + 1);
5408 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5409 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5410 ptr += id_len;
5411 if (path_len)
5413 afdi->lpAssemblyManifestPath = ptr;
5414 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5415 ptr += path_len;
5416 } else afdi->lpAssemblyManifestPath = NULL;
5417 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5418 if (ad_len)
5420 afdi->lpAssemblyDirectoryName = ptr;
5421 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5423 else afdi->lpAssemblyDirectoryName = NULL;
5424 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5426 break;
5428 case FileInformationInAssemblyOfAssemblyInActivationContext:
5430 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5431 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5432 struct assembly *assembly;
5433 struct dll_redirect *dll;
5434 SIZE_T len, dll_len = 0;
5435 LPWSTR ptr;
5437 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5438 if (!acqi) return STATUS_INVALID_PARAMETER;
5440 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5441 return STATUS_INVALID_PARAMETER;
5442 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5444 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5445 return STATUS_INVALID_PARAMETER;
5446 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5448 if (dll->name) dll_len = wcslen(dll->name) + 1;
5449 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5451 if (!buffer || bufsize < len)
5453 if (retlen) *retlen = len;
5454 return STATUS_BUFFER_TOO_SMALL;
5456 if (retlen) *retlen = 0; /* yes that's what native does !! */
5457 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5458 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5459 afdi->ulPathLength = 0; /* FIXME */
5460 ptr = (LPWSTR)(afdi + 1);
5461 if (dll_len)
5463 afdi->lpFileName = ptr;
5464 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5465 } else afdi->lpFileName = NULL;
5466 afdi->lpFilePath = NULL; /* FIXME */
5468 break;
5470 case CompatibilityInformationInActivationContext:
5472 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5473 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5474 struct assembly *assembly = NULL;
5475 ULONG num_compat_contexts = 0, n;
5476 SIZE_T len;
5478 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5480 if (actctx->num_assemblies) assembly = actctx->assemblies;
5482 if (assembly)
5483 num_compat_contexts = assembly->num_compat_contexts;
5484 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5486 if (retlen) *retlen = len;
5487 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5489 *acci = num_compat_contexts;
5490 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5491 for (n = 0; n < num_compat_contexts; ++n)
5493 elements[n] = assembly->compat_contexts[n];
5496 break;
5498 case RunlevelInformationInActivationContext:
5500 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5501 struct assembly *assembly;
5502 SIZE_T len;
5504 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5506 len = sizeof(*acrli);
5507 if (retlen) *retlen = len;
5508 if (!buffer || bufsize < len)
5509 return STATUS_BUFFER_TOO_SMALL;
5511 assembly = actctx->assemblies;
5513 acrli->ulFlags = 0;
5514 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5515 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5517 break;
5519 default:
5520 FIXME( "class %u not implemented\n", class );
5521 return STATUS_NOT_IMPLEMENTED;
5523 return STATUS_SUCCESS;
5526 /***********************************************************************
5527 * RtlFindActivationContextSectionString (NTDLL.@)
5529 * Find information about a string in an activation context.
5530 * FIXME: function signature/prototype may be wrong
5532 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5533 const UNICODE_STRING *section_name, PVOID ptr )
5535 PACTCTX_SECTION_KEYED_DATA data = ptr;
5536 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5538 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5539 debugstr_us(section_name), data);
5541 if (guid)
5543 FIXME("expected guid == NULL\n");
5544 return STATUS_INVALID_PARAMETER;
5546 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5548 FIXME("unknown flags %08x\n", flags);
5549 return STATUS_INVALID_PARAMETER;
5551 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5552 !section_name || !section_name->Buffer)
5554 WARN("invalid parameter\n");
5555 return STATUS_INVALID_PARAMETER;
5558 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5560 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5561 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5564 if (status != STATUS_SUCCESS)
5565 status = find_string( process_actctx, section_kind, section_name, flags, data );
5567 return status;
5570 /***********************************************************************
5571 * RtlFindActivationContextSectionGuid (NTDLL.@)
5573 * Find information about a GUID in an activation context.
5574 * FIXME: function signature/prototype may be wrong
5576 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5577 const GUID *guid, void *ptr )
5579 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5580 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5582 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5584 if (extguid)
5586 FIXME("expected extguid == NULL\n");
5587 return STATUS_INVALID_PARAMETER;
5590 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5592 FIXME("unknown flags %08x\n", flags);
5593 return STATUS_INVALID_PARAMETER;
5596 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5597 return STATUS_INVALID_PARAMETER;
5599 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5601 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5602 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5605 if (status != STATUS_SUCCESS)
5606 status = find_guid( process_actctx, section_kind, guid, flags, data );
5608 return status;
5612 /***********************************************************************
5613 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5615 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5616 const WCHAR *settings, WCHAR *buffer,
5617 SIZE_T size, SIZE_T *written )
5619 ACTIVATION_CONTEXT *actctx;
5620 const WCHAR *res;
5622 if (flags)
5624 WARN( "unknown flags %08x\n", flags );
5625 return STATUS_INVALID_PARAMETER;
5628 if (ns)
5630 if (wcscmp( ns, windowsSettings2005NSW ) &&
5631 wcscmp( ns, windowsSettings2011NSW ) &&
5632 wcscmp( ns, windowsSettings2016NSW ) &&
5633 wcscmp( ns, windowsSettings2017NSW ))
5634 return STATUS_INVALID_PARAMETER;
5636 else ns = windowsSettings2005NSW;
5638 if (!handle) handle = process_actctx;
5639 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5641 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5643 if (written) *written = wcslen(res) + 1;
5644 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5645 wcscpy( buffer, res );
5646 return STATUS_SUCCESS;