ncrypt: Add NCryptIsKeyHandle stub.
[wine.git] / dlls / ntdll / actctx.c
blobb99d1655d22f4674d3353a050d99ee0c5fcebde2
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 if (end) return;
2312 while (next_xml_elem(xmlbuf, &elem, parent))
2314 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W))
2316 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional);
2318 else
2320 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2321 parse_unknown_elem(xmlbuf, &elem);
2326 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2328 BOOL end = FALSE;
2330 parse_expect_no_attr(xmlbuf, &end);
2331 if (!end) parse_expect_end_elem(xmlbuf, parent);
2334 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent )
2336 BOOL end = FALSE;
2338 parse_expect_no_attr(xmlbuf, &end);
2339 if (!end) parse_expect_end_elem(xmlbuf, parent);
2342 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly,
2343 struct actctx_loader* acl, const struct xml_elem *parent )
2345 struct xml_elem elem;
2346 struct xml_attr attr;
2347 BOOL end = FALSE;
2348 struct dll_redirect* dll;
2350 if (!(dll = add_dll_redirect(assembly)))
2352 set_error( xmlbuf );
2353 return;
2356 while (next_xml_attr(xmlbuf, &attr, &end))
2358 if (xml_attr_cmp(&attr, nameW))
2360 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2361 TRACE("name=%s\n", debugstr_xmlstr(&attr.value));
2363 else if (xml_attr_cmp(&attr, hashW))
2365 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf );
2367 else if (xml_attr_cmp(&attr, hashalgW))
2369 static const WCHAR sha1W[] = {'S','H','A','1',0};
2370 if (!xmlstr_cmpi(&attr.value, sha1W))
2371 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value));
2373 else if (!is_xmlns_attr( &attr ))
2375 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2379 if (!dll->name) set_error( xmlbuf );
2381 acl->actctx->sections |= DLLREDIRECT_SECTION;
2383 if (end) return;
2385 while (next_xml_elem(xmlbuf, &elem, parent))
2387 if (xml_elem_cmp(&elem, comClassW, asmv1W))
2389 parse_com_class_elem(xmlbuf, dll, acl, &elem);
2391 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W))
2393 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem);
2395 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2397 WARN("asmv2:hash (undocumented) not supported\n");
2398 parse_unknown_elem(xmlbuf, &elem);
2400 else if (xml_elem_cmp(&elem, typelibW, asmv1W))
2402 parse_typelib_elem(xmlbuf, dll, acl, &elem);
2404 else if (xml_elem_cmp(&elem, windowClassW, asmv1W))
2406 parse_window_class_elem(xmlbuf, dll, acl, &elem);
2408 else
2410 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2411 parse_unknown_elem( xmlbuf, &elem );
2416 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2417 struct actctx_loader *acl, const struct xml_elem *parent )
2419 struct xml_attr attr;
2420 BOOL end = FALSE;
2422 while (next_xml_attr(xmlbuf, &attr, &end))
2424 if (xml_attr_cmp(&attr, IdW))
2426 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2427 UNICODE_STRING str;
2428 GUID compat_id;
2430 str.Buffer = (PWSTR)attr.value.ptr;
2431 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR);
2432 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2434 if (!(compat = add_compat_context(assembly)))
2436 set_error( xmlbuf );
2437 return;
2439 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS;
2440 compat->Id = compat_id;
2442 else
2444 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value));
2447 else if (!is_xmlns_attr( &attr ))
2449 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2453 if (!end) parse_expect_end_elem(xmlbuf, parent);
2456 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2457 struct actctx_loader* acl, const struct xml_elem *parent)
2459 struct xml_elem elem;
2461 while (next_xml_elem(xmlbuf, &elem, parent))
2463 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW))
2465 parse_supportedos_elem(xmlbuf, assembly, acl, &elem);
2467 else
2469 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2470 parse_unknown_elem(xmlbuf, &elem);
2475 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly,
2476 struct actctx_loader* acl, const struct xml_elem *parent)
2478 struct xml_elem elem;
2480 while (next_xml_elem(xmlbuf, &elem, parent))
2482 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW))
2484 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem);
2486 else
2488 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2489 parse_unknown_elem(xmlbuf, &elem);
2494 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2495 struct xml_elem *parent )
2497 struct xml_elem elem;
2498 struct xml_attr attr;
2499 xmlstr_t content;
2500 BOOL end = FALSE;
2501 struct entity *entity;
2503 while (next_xml_attr( xmlbuf, &attr, &end ))
2505 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) );
2508 if (end) return;
2510 if (!parse_text_content( xmlbuf, &content )) return;
2511 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) );
2513 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2514 if (!entity)
2516 set_error( xmlbuf );
2517 return;
2519 entity->u.settings.name = xmlstrdupW( &parent->name );
2520 entity->u.settings.value = xmlstrdupW( &content );
2521 entity->u.settings.ns = xmlstrdupW( &parent->ns );
2523 while (next_xml_elem(xmlbuf, &elem, parent))
2525 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2526 parse_unknown_elem( xmlbuf, &elem );
2530 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2531 struct actctx_loader *acl, const struct xml_elem *parent )
2533 struct xml_elem elem;
2535 while (next_xml_elem( xmlbuf, &elem, parent ))
2537 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) ||
2538 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) ||
2539 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) ||
2540 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) ||
2541 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) ||
2542 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) ||
2543 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) ||
2544 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) ||
2545 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) ||
2546 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) ||
2547 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW ))
2549 parse_settings_elem( xmlbuf, assembly, acl, &elem );
2551 else
2553 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2554 parse_unknown_elem( xmlbuf, &elem );
2559 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2560 struct actctx_loader *acl, const struct xml_elem *parent )
2562 struct xml_elem elem;
2564 while (next_xml_elem( xmlbuf, &elem, parent ))
2566 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W ))
2568 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem );
2570 else
2572 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) );
2573 parse_unknown_elem( xmlbuf, &elem );
2578 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2579 struct actctx_loader *acl, const struct xml_elem *parent )
2581 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2582 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2583 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};
2584 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2585 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2586 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2587 static const WCHAR trueW[] = {'t','r','u','e',0};
2589 struct xml_elem elem;
2590 struct xml_attr attr;
2591 BOOL end = FALSE;
2593 /* Multiple requestedExecutionLevel elements are not supported. */
2594 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf );
2596 while (next_xml_attr(xmlbuf, &attr, &end))
2598 if (xml_attr_cmp(&attr, levelW))
2600 if (xmlstr_cmpi(&attr.value, asInvokerW))
2601 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2602 else if (xmlstr_cmpi(&attr.value, highestAvailableW))
2603 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2604 else if (xmlstr_cmpi(&attr.value, requireAdministratorW))
2605 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2606 else
2607 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value));
2609 else if (xml_attr_cmp(&attr, uiAccessW))
2611 if (xmlstr_cmpi(&attr.value, falseW))
2612 assembly->ui_access = FALSE;
2613 else if (xmlstr_cmpi(&attr.value, trueW))
2614 assembly->ui_access = TRUE;
2615 else
2616 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value));
2618 else if (!is_xmlns_attr( &attr ))
2619 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2622 if (end) return;
2624 while (next_xml_elem(xmlbuf, &elem, parent))
2626 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2627 parse_unknown_elem(xmlbuf, &elem);
2631 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2632 struct actctx_loader *acl, const struct xml_elem *parent )
2634 struct xml_elem elem;
2636 while (next_xml_elem(xmlbuf, &elem, parent))
2638 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W))
2640 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem);
2642 else
2644 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2645 parse_unknown_elem(xmlbuf, &elem);
2650 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2651 struct actctx_loader *acl, const struct xml_elem *parent )
2653 struct xml_elem elem;
2655 while (next_xml_elem(xmlbuf, &elem, parent))
2657 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W))
2659 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem);
2661 else
2663 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2664 parse_unknown_elem(xmlbuf, &elem);
2669 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2670 struct actctx_loader *acl, const struct xml_elem *parent )
2672 struct xml_elem elem;
2674 while (next_xml_elem(xmlbuf, &elem, parent))
2676 if (xml_elem_cmp(&elem, securityW, asmv1W))
2678 parse_security_elem(xmlbuf, assembly, acl, &elem);
2680 else
2682 WARN("unknown elem %s\n", debugstr_xml_elem(&elem));
2683 parse_unknown_elem(xmlbuf, &elem);
2688 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly,
2689 struct actctx_loader* acl, const struct xml_elem *parent,
2690 struct assembly_identity* expected_ai)
2692 struct xml_elem elem;
2693 struct xml_attr attr;
2694 BOOL end = FALSE, version = FALSE;
2696 TRACE("(%p)\n", xmlbuf);
2698 while (next_xml_attr(xmlbuf, &attr, &end))
2700 if (xml_attr_cmp(&attr, manifestVersionW))
2702 static const WCHAR v10W[] = {'1','.','0',0};
2703 if (!xmlstr_cmp(&attr.value, v10W))
2705 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value));
2706 break;
2708 version = TRUE;
2710 else if (!is_xmlns_attr( &attr ))
2712 WARN("unknown attr %s\n", debugstr_xml_attr(&attr));
2716 if (end || !version)
2718 set_error( xmlbuf );
2719 return;
2722 while (next_xml_elem(xmlbuf, &elem, parent))
2724 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W))
2726 parse_noinherit_elem(xmlbuf, &elem);
2727 assembly->no_inherit = TRUE;
2729 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2731 parse_noinheritable_elem(xmlbuf, &elem);
2733 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2735 parse_description_elem(xmlbuf, &elem);
2737 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2739 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem);
2741 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2743 parse_dependency_elem(xmlbuf, acl, &elem);
2745 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2747 parse_file_elem(xmlbuf, assembly, acl, &elem);
2749 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2751 parse_clr_class_elem(xmlbuf, assembly, acl, &elem);
2753 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2755 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem);
2757 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W))
2759 parse_trust_info_elem(xmlbuf, assembly, acl, &elem);
2761 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2763 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem);
2765 if (!xmlbuf->error && expected_ai)
2767 /* FIXME: more tests */
2768 if (assembly->type == ASSEMBLY_MANIFEST &&
2769 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2771 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2772 expected_ai->version.major, expected_ai->version.minor,
2773 expected_ai->version.build, expected_ai->version.revision,
2774 assembly->id.version.major, assembly->id.version.minor,
2775 assembly->id.version.build, assembly->id.version.revision);
2776 set_error( xmlbuf );
2778 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2779 (assembly->id.version.major != expected_ai->version.major ||
2780 assembly->id.version.minor != expected_ai->version.minor ||
2781 assembly->id.version.build < expected_ai->version.build ||
2782 (assembly->id.version.build == expected_ai->version.build &&
2783 assembly->id.version.revision < expected_ai->version.revision)))
2785 FIXME("wrong version for shared assembly manifest\n");
2786 set_error( xmlbuf );
2790 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2792 parse_compatibility_elem(xmlbuf, assembly, acl, &elem);
2794 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2796 parse_application_elem(xmlbuf, assembly, acl, &elem);
2798 else
2800 WARN("unknown element %s\n", debugstr_xml_elem(&elem));
2801 parse_unknown_elem(xmlbuf, &elem);
2805 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2806 assembly->no_inherit)
2808 set_error( xmlbuf );
2812 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2813 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2815 struct xml_elem elem;
2816 struct xml_elem parent = {};
2818 xmlbuf->error = FALSE;
2819 xmlbuf->ns_pos = 0;
2821 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX;
2823 if (xmlstr_cmp(&elem.name, xmlW) &&
2824 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent)))
2825 return STATUS_SXS_CANT_GEN_ACTCTX;
2827 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2829 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem));
2830 return STATUS_SXS_CANT_GEN_ACTCTX;
2833 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai);
2834 if (xmlbuf->error)
2836 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2837 return STATUS_SXS_CANT_GEN_ACTCTX;
2840 if (next_xml_elem(xmlbuf, &elem, &parent))
2842 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem));
2843 return STATUS_SXS_CANT_GEN_ACTCTX;
2846 if (xmlbuf->ptr != xmlbuf->end)
2848 FIXME("parse error\n");
2849 return STATUS_SXS_CANT_GEN_ACTCTX;
2851 return STATUS_SUCCESS;
2854 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2855 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared,
2856 const void *buffer, SIZE_T size )
2858 xmlbuf_t xmlbuf;
2859 NTSTATUS status;
2860 struct assembly *assembly;
2861 int unicode_tests;
2863 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2865 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2866 return STATUS_SXS_CANT_GEN_ACTCTX;
2868 if (directory && !(assembly->directory = strdupW(directory)))
2869 return STATUS_NO_MEMORY;
2871 if (!filename)
2873 UNICODE_STRING module_path;
2874 if ((status = get_module_filename( module, &module_path, 0 ))) return status;
2875 assembly->manifest.info = module_path.Buffer;
2877 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY;
2879 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2880 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2882 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2883 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2885 xmlbuf.ptr = buffer;
2886 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2887 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2889 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2891 const WCHAR *buf = buffer;
2892 WCHAR *new_buff;
2893 unsigned int i;
2895 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2896 return STATUS_NO_MEMORY;
2897 for (i = 0; i < size / sizeof(WCHAR); i++)
2898 new_buff[i] = RtlUshortByteSwap( buf[i] );
2899 xmlbuf.ptr = new_buff;
2900 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2901 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2902 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2904 else
2906 DWORD len;
2907 WCHAR *new_buff;
2909 /* let's assume utf-8 for now */
2910 RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size );
2911 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY;
2912 RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size );
2913 xmlbuf.ptr = new_buff;
2914 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
2915 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2916 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2918 return status;
2921 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2923 OBJECT_ATTRIBUTES attr;
2924 IO_STATUS_BLOCK io;
2926 attr.Length = sizeof(attr);
2927 attr.RootDirectory = 0;
2928 attr.Attributes = OBJ_CASE_INSENSITIVE;
2929 attr.ObjectName = name;
2930 attr.SecurityDescriptor = NULL;
2931 attr.SecurityQualityOfService = NULL;
2932 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2935 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2936 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2937 HANDLE hModule, LPCWSTR resname, ULONG lang )
2939 NTSTATUS status;
2940 UNICODE_STRING nameW;
2941 LDR_RESOURCE_INFO info;
2942 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2943 void *ptr;
2945 if (TRACE_ON(actctx))
2947 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2949 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2950 hModule, debugstr_w(nameW.Buffer) );
2951 RtlFreeUnicodeString( &nameW );
2953 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2954 hModule, debugstr_w(filename) );
2957 if (!resname) return STATUS_INVALID_PARAMETER;
2959 info.Type = RT_MANIFEST;
2960 info.Language = lang;
2961 if (!((ULONG_PTR)resname >> 16))
2963 info.Name = (ULONG_PTR)resname;
2964 status = LdrFindResource_U(hModule, &info, 3, &entry);
2966 else if (resname[0] == '#')
2968 ULONG value;
2969 RtlInitUnicodeString(&nameW, resname + 1);
2970 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2971 return STATUS_INVALID_PARAMETER;
2972 info.Name = value;
2973 status = LdrFindResource_U(hModule, &info, 3, &entry);
2975 else
2977 RtlCreateUnicodeString(&nameW, resname);
2978 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2979 info.Name = (ULONG_PTR)nameW.Buffer;
2980 status = LdrFindResource_U(hModule, &info, 3, &entry);
2981 RtlFreeUnicodeString(&nameW);
2983 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2985 if (status == STATUS_SUCCESS)
2986 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size);
2988 return status;
2991 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2992 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2993 HANDLE file, LPCWSTR resname, ULONG lang )
2995 HANDLE mapping;
2996 OBJECT_ATTRIBUTES attr;
2997 LARGE_INTEGER size;
2998 LARGE_INTEGER offset;
2999 NTSTATUS status;
3000 SIZE_T count;
3001 void *base;
3003 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
3005 attr.Length = sizeof(attr);
3006 attr.RootDirectory = 0;
3007 attr.ObjectName = NULL;
3008 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3009 attr.SecurityDescriptor = NULL;
3010 attr.SecurityQualityOfService = NULL;
3012 size.QuadPart = 0;
3013 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3014 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3015 if (status != STATUS_SUCCESS) return status;
3017 offset.QuadPart = 0;
3018 count = 0;
3019 base = NULL;
3020 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3021 &count, ViewShare, 0, PAGE_READONLY );
3022 NtClose( mapping );
3023 if (status != STATUS_SUCCESS) return status;
3025 if (RtlImageNtHeader(base)) /* we got a PE file */
3027 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
3028 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
3030 else status = STATUS_INVALID_IMAGE_FORMAT;
3032 NtUnmapViewOfSection( GetCurrentProcess(), base );
3033 return status;
3036 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
3037 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
3039 FILE_END_OF_FILE_INFORMATION info;
3040 IO_STATUS_BLOCK io;
3041 HANDLE mapping;
3042 OBJECT_ATTRIBUTES attr;
3043 LARGE_INTEGER size;
3044 LARGE_INTEGER offset;
3045 NTSTATUS status;
3046 SIZE_T count;
3047 void *base;
3049 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
3051 attr.Length = sizeof(attr);
3052 attr.RootDirectory = 0;
3053 attr.ObjectName = NULL;
3054 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
3055 attr.SecurityDescriptor = NULL;
3056 attr.SecurityQualityOfService = NULL;
3058 size.QuadPart = 0;
3059 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3060 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3061 if (status != STATUS_SUCCESS) return status;
3063 offset.QuadPart = 0;
3064 count = 0;
3065 base = NULL;
3066 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3067 &count, ViewShare, 0, PAGE_READONLY );
3068 NtClose( mapping );
3069 if (status != STATUS_SUCCESS) return status;
3071 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3072 if (status == STATUS_SUCCESS)
3073 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart);
3075 NtUnmapViewOfSection( GetCurrentProcess(), base );
3076 return status;
3079 /* try to load the .manifest file associated to the file */
3080 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3081 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3083 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3084 WCHAR *buffer;
3085 NTSTATUS status;
3086 UNICODE_STRING nameW;
3087 HANDLE file;
3088 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3090 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3092 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3094 if (module) /* use the module filename */
3096 UNICODE_STRING name;
3098 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3100 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, fmtW, resid );
3101 wcscat( name.Buffer, dotManifestW );
3102 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3103 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3104 RtlFreeUnicodeString( &name );
3106 if (status) return status;
3108 else
3110 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3111 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3112 return STATUS_NO_MEMORY;
3113 wcscpy( buffer, filename );
3114 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, fmtW, resid );
3115 wcscat( buffer, dotManifestW );
3116 RtlInitUnicodeString( &nameW, buffer );
3119 if (!open_nt_file( &file, &nameW ))
3121 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3122 NtClose( file );
3124 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3125 RtlFreeUnicodeString( &nameW );
3126 return status;
3129 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3131 static const WCHAR lookup_fmtW[] =
3132 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3133 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3134 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3136 WCHAR *lookup, *ret = NULL;
3137 UNICODE_STRING lookup_us;
3138 IO_STATUS_BLOCK io;
3139 const WCHAR *lang = ai->language;
3140 unsigned int data_pos = 0, data_len, len;
3141 char buffer[8192];
3143 if (!lang || !wcsicmp( lang, neutralW )) lang = wildcardW;
3145 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW);
3146 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL;
3147 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3148 ai->version.major, ai->version.minor, lang );
3149 RtlInitUnicodeString( &lookup_us, lookup );
3151 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3152 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3154 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3155 FILE_BOTH_DIR_INFORMATION *dir_info;
3156 WCHAR *tmp;
3157 ULONG build, revision;
3159 data_len = io.Information;
3161 for (;;)
3163 if (data_pos >= data_len)
3165 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3166 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3167 break;
3168 data_len = io.Information;
3169 data_pos = 0;
3171 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3173 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3174 else data_pos = data_len;
3176 tmp = dir_info->FileName + (wcschr(lookup, '*') - lookup);
3177 build = wcstoul( tmp, NULL, 10 );
3178 if (build < min_build) continue;
3179 tmp = wcschr(tmp, '.') + 1;
3180 revision = wcstoul( tmp, NULL, 10 );
3181 if (build == min_build && revision < min_revision) continue;
3182 tmp = wcschr(tmp, '_') + 1;
3183 tmp = wcschr(tmp, '_') + 1;
3184 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3185 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW )))
3187 /* prefer a non-Wine manifest if we already have one */
3188 /* we'll still load the builtin dll if specified through DllOverrides */
3189 if (ret) continue;
3191 else
3193 min_build = build;
3194 min_revision = revision;
3196 ai->version.build = build;
3197 ai->version.revision = revision;
3198 RtlFreeHeap( GetProcessHeap(), 0, ret );
3199 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3201 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3202 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3206 else WARN("no matching file for %s\n", debugstr_w(lookup));
3207 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3208 return ret;
3211 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3213 struct assembly_identity sxs_ai;
3214 UNICODE_STRING path_us;
3215 OBJECT_ATTRIBUTES attr;
3216 IO_STATUS_BLOCK io;
3217 WCHAR *path, *file = NULL;
3218 HANDLE handle;
3220 static const WCHAR manifest_dirW[] =
3221 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3223 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3225 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3226 wcslen(windows_dir) * sizeof(WCHAR) )))
3227 return STATUS_NO_MEMORY;
3229 wcscpy( path, windows_dir );
3230 wcscat( path, manifest_dirW );
3232 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3234 RtlFreeHeap( GetProcessHeap(), 0, path );
3235 return STATUS_NO_SUCH_FILE;
3237 RtlFreeHeap( GetProcessHeap(), 0, path );
3239 attr.Length = sizeof(attr);
3240 attr.RootDirectory = 0;
3241 attr.Attributes = OBJ_CASE_INSENSITIVE;
3242 attr.ObjectName = &path_us;
3243 attr.SecurityDescriptor = NULL;
3244 attr.SecurityQualityOfService = NULL;
3246 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3247 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3249 sxs_ai = *ai;
3250 file = lookup_manifest_file( handle, &sxs_ai );
3251 NtClose( handle );
3253 if (!file)
3255 RtlFreeUnicodeString( &path_us );
3256 return STATUS_NO_SUCH_FILE;
3259 /* append file name to directory path */
3260 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3261 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) )))
3263 RtlFreeHeap( GetProcessHeap(), 0, file );
3264 RtlFreeUnicodeString( &path_us );
3265 return STATUS_NO_MEMORY;
3268 path[path_us.Length/sizeof(WCHAR)] = '\\';
3269 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file );
3270 RtlInitUnicodeString( &path_us, path );
3271 *wcsrchr(file, '.') = 0; /* remove .manifest extension */
3273 if (!open_nt_file( &handle, &path_us ))
3275 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3276 NtClose( handle );
3278 else io.u.Status = STATUS_NO_SUCH_FILE;
3280 RtlFreeHeap( GetProcessHeap(), 0, file );
3281 RtlFreeUnicodeString( &path_us );
3282 return io.u.Status;
3285 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3286 struct assembly_identity* ai)
3288 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3289 unsigned int i;
3290 WCHAR *buffer, *p, *directory;
3291 NTSTATUS status;
3292 UNICODE_STRING nameW;
3293 HANDLE file;
3294 DWORD len;
3296 TRACE( "looking for name=%s version=%s arch=%s\n",
3297 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3299 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3301 /* FIXME: add support for language specific lookup */
3303 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3304 wcslen(acl->actctx->appdir.info));
3306 nameW.Buffer = NULL;
3307 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3308 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3309 return STATUS_NO_MEMORY;
3311 if (!(directory = build_assembly_dir( ai )))
3313 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3314 return STATUS_NO_MEMORY;
3317 /* Lookup in <dir>\name.dll
3318 * <dir>\name.manifest
3319 * <dir>\name\name.dll
3320 * <dir>\name\name.manifest
3322 * First 'appdir' is used as <dir>, if that failed
3323 * it tries application manifest file path.
3325 wcscpy( buffer, acl->actctx->appdir.info );
3326 p = buffer + wcslen(buffer);
3327 for (i = 0; i < 4; i++)
3329 if (i == 2)
3331 struct assembly *assembly = acl->actctx->assemblies;
3332 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3334 else *p++ = '\\';
3336 wcscpy( p, ai->name );
3337 p += wcslen(p);
3339 wcscpy( p, dotDllW );
3340 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3342 status = open_nt_file( &file, &nameW );
3343 if (!status)
3345 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3346 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3347 NtClose( file );
3348 if (status == STATUS_SUCCESS)
3349 break;
3351 RtlFreeUnicodeString( &nameW );
3354 wcscpy( p, dotManifestW );
3355 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3357 status = open_nt_file( &file, &nameW );
3358 if (!status)
3360 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3361 NtClose( file );
3362 break;
3364 RtlFreeUnicodeString( &nameW );
3366 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3368 RtlFreeUnicodeString( &nameW );
3369 RtlFreeHeap( GetProcessHeap(), 0, directory );
3370 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3371 return status;
3374 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3376 NTSTATUS status = STATUS_SUCCESS;
3377 unsigned int i;
3379 for (i = 0; i < acl->num_dependencies; i++)
3381 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3383 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3385 FIXME( "Could not find dependent assembly %s (%s)\n",
3386 debugstr_w(acl->dependencies[i].name),
3387 debugstr_version(&acl->dependencies[i].version) );
3388 status = STATUS_SXS_CANT_GEN_ACTCTX;
3389 break;
3393 /* FIXME should now iterate through all refs */
3394 return status;
3397 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3398 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3400 NTSTATUS status = STATUS_SUCCESS;
3402 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3404 if (*handle) return STATUS_INVALID_PARAMETER;
3406 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3407 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3409 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3411 ULONG_PTR magic;
3412 LDR_DATA_TABLE_ENTRY *pldr;
3414 if (!*handle) return STATUS_INVALID_PARAMETER;
3416 LdrLockLoaderLock( 0, NULL, &magic );
3417 if (!LdrFindEntryForAddress( *handle, &pldr ))
3419 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
3420 status = STATUS_DLL_NOT_FOUND;
3421 else
3422 *handle = pldr->ActivationContext;
3424 else status = STATUS_DLL_NOT_FOUND;
3425 LdrUnlockLoaderLock( 0, magic );
3427 else if (!*handle && (class != ActivationContextBasicInformation))
3428 *handle = process_actctx;
3430 return status;
3433 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3435 unsigned int i, j, total_len = 0, dll_count = 0;
3436 struct strsection_header *header;
3437 struct dllredirect_data *data;
3438 struct string_index *index;
3439 ULONG name_offset;
3441 /* compute section length */
3442 for (i = 0; i < actctx->num_assemblies; i++)
3444 struct assembly *assembly = &actctx->assemblies[i];
3445 for (j = 0; j < assembly->num_dlls; j++)
3447 struct dll_redirect *dll = &assembly->dlls[j];
3449 /* each entry needs index, data and string data */
3450 total_len += sizeof(*index);
3451 total_len += sizeof(*data);
3452 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR));
3455 dll_count += assembly->num_dlls;
3458 total_len += sizeof(*header);
3460 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3461 if (!header) return STATUS_NO_MEMORY;
3463 memset(header, 0, sizeof(*header));
3464 header->magic = STRSECTION_MAGIC;
3465 header->size = sizeof(*header);
3466 header->count = dll_count;
3467 header->index_offset = sizeof(*header);
3468 index = (struct string_index*)((BYTE*)header + header->index_offset);
3469 name_offset = header->index_offset + header->count*sizeof(*index);
3471 for (i = 0; i < actctx->num_assemblies; i++)
3473 struct assembly *assembly = &actctx->assemblies[i];
3474 for (j = 0; j < assembly->num_dlls; j++)
3476 struct dll_redirect *dll = &assembly->dlls[j];
3477 UNICODE_STRING str;
3478 WCHAR *ptrW;
3480 /* setup new index entry */
3481 str.Buffer = dll->name;
3482 str.Length = wcslen(dll->name)*sizeof(WCHAR);
3483 str.MaximumLength = str.Length + sizeof(WCHAR);
3484 /* hash original class name */
3485 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3487 index->name_offset = name_offset;
3488 index->name_len = str.Length;
3489 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3490 index->data_len = sizeof(*data);
3491 index->rosterindex = i + 1;
3493 /* setup data */
3494 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3495 data->size = sizeof(*data);
3496 data->unk = 2; /* FIXME: seems to be constant */
3497 memset(data->res, 0, sizeof(data->res));
3499 /* dll name */
3500 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3501 memcpy(ptrW, dll->name, index->name_len);
3502 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3504 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3506 index++;
3510 *section = header;
3512 return STATUS_SUCCESS;
3515 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3517 struct string_index *iter, *index = NULL;
3518 UNICODE_STRING str;
3519 ULONG hash = 0, i;
3521 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3522 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3524 for (i = 0; i < section->count; i++)
3526 if (iter->hash == hash)
3528 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset);
3529 str.Length = iter->name_len;
3530 if (RtlEqualUnicodeString( &str, name, TRUE ))
3532 index = iter;
3533 break;
3535 else
3536 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3538 iter++;
3541 return index;
3544 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3546 struct guid_index *iter, *index = NULL;
3547 ULONG i;
3549 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3551 for (i = 0; i < section->count; i++)
3553 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3555 index = iter;
3556 break;
3558 iter++;
3561 return index;
3564 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3566 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3569 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3570 PACTCTX_SECTION_KEYED_DATA data)
3572 struct dllredirect_data *dll;
3573 struct string_index *index;
3575 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3577 if (!actctx->dllredirect_section)
3579 struct strsection_header *section;
3581 NTSTATUS status = build_dllredirect_section(actctx, &section);
3582 if (status) return status;
3584 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
3585 RtlFreeHeap(GetProcessHeap(), 0, section);
3588 index = find_string_index(actctx->dllredirect_section, name);
3589 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3591 if (data)
3593 dll = get_dllredirect_data(actctx, index);
3595 data->ulDataFormatVersion = 1;
3596 data->lpData = dll;
3597 data->ulLength = dll->size;
3598 data->lpSectionGlobalData = NULL;
3599 data->ulSectionGlobalDataLength = 0;
3600 data->lpSectionBase = actctx->dllredirect_section;
3601 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3602 data->hActCtx = NULL;
3604 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3605 data->ulAssemblyRosterIndex = index->rosterindex;
3608 return STATUS_SUCCESS;
3611 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3613 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3616 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3618 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3621 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3623 unsigned int i, j, k, total_len = 0, class_count = 0;
3624 struct wndclass_redirect_data *data;
3625 struct strsection_header *header;
3626 struct string_index *index;
3627 ULONG name_offset;
3629 /* compute section length */
3630 for (i = 0; i < actctx->num_assemblies; i++)
3632 struct assembly *assembly = &actctx->assemblies[i];
3633 for (j = 0; j < assembly->num_dlls; j++)
3635 struct dll_redirect *dll = &assembly->dlls[j];
3636 for (k = 0; k < dll->entities.num; k++)
3638 struct entity *entity = &dll->entities.base[k];
3639 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3641 int class_len = wcslen(entity->u.class.name) + 1;
3642 int len;
3644 /* each class entry needs index, data and string data */
3645 total_len += sizeof(*index);
3646 total_len += sizeof(*data);
3647 /* original name is stored separately */
3648 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3649 /* versioned name and module name are stored one after another */
3650 if (entity->u.class.versioned)
3651 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3652 else
3653 len = class_len;
3654 len += wcslen(dll->name) + 1;
3655 total_len += aligned_string_len(len*sizeof(WCHAR));
3657 class_count++;
3663 total_len += sizeof(*header);
3665 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3666 if (!header) return STATUS_NO_MEMORY;
3668 memset(header, 0, sizeof(*header));
3669 header->magic = STRSECTION_MAGIC;
3670 header->size = sizeof(*header);
3671 header->count = class_count;
3672 header->index_offset = sizeof(*header);
3673 index = (struct string_index*)((BYTE*)header + header->index_offset);
3674 name_offset = header->index_offset + header->count*sizeof(*index);
3676 for (i = 0; i < actctx->num_assemblies; i++)
3678 struct assembly *assembly = &actctx->assemblies[i];
3679 for (j = 0; j < assembly->num_dlls; j++)
3681 struct dll_redirect *dll = &assembly->dlls[j];
3682 for (k = 0; k < dll->entities.num; k++)
3684 struct entity *entity = &dll->entities.base[k];
3685 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3687 static const WCHAR exclW[] = {'!',0};
3688 ULONG versioned_len, module_len;
3689 UNICODE_STRING str;
3690 WCHAR *ptrW;
3692 /* setup new index entry */
3693 str.Buffer = entity->u.class.name;
3694 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR);
3695 str.MaximumLength = str.Length + sizeof(WCHAR);
3696 /* hash original class name */
3697 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3699 /* include '!' separator too */
3700 if (entity->u.class.versioned)
3701 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3702 else
3703 versioned_len = str.Length;
3704 module_len = wcslen(dll->name)*sizeof(WCHAR);
3706 index->name_offset = name_offset;
3707 index->name_len = str.Length;
3708 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3709 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3710 index->rosterindex = i + 1;
3712 /* setup data */
3713 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3714 data->size = sizeof(*data);
3715 data->res = 0;
3716 data->name_len = versioned_len;
3717 data->name_offset = sizeof(*data);
3718 data->module_len = module_len;
3719 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3721 /* original class name */
3722 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3723 memcpy(ptrW, entity->u.class.name, index->name_len);
3724 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3726 /* module name */
3727 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3728 memcpy(ptrW, dll->name, data->module_len);
3729 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3731 /* versioned name */
3732 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3733 if (entity->u.class.versioned)
3735 get_assembly_version(assembly, ptrW);
3736 wcscat(ptrW, exclW);
3737 wcscat(ptrW, entity->u.class.name);
3739 else
3741 memcpy(ptrW, entity->u.class.name, index->name_len);
3742 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3745 name_offset += sizeof(*data);
3746 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3748 index++;
3754 *section = header;
3756 return STATUS_SUCCESS;
3759 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3760 PACTCTX_SECTION_KEYED_DATA data)
3762 struct string_index *iter, *index = NULL;
3763 struct wndclass_redirect_data *class;
3764 UNICODE_STRING str;
3765 ULONG hash;
3766 int i;
3768 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3770 if (!actctx->wndclass_section)
3772 struct strsection_header *section;
3774 NTSTATUS status = build_wndclass_section(actctx, &section);
3775 if (status) return status;
3777 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
3778 RtlFreeHeap(GetProcessHeap(), 0, section);
3781 hash = 0;
3782 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3783 iter = get_wndclass_first_index(actctx);
3785 for (i = 0; i < actctx->wndclass_section->count; i++)
3787 if (iter->hash == hash)
3789 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset);
3790 str.Length = iter->name_len;
3791 if (RtlEqualUnicodeString( &str, name, TRUE ))
3793 index = iter;
3794 break;
3796 else
3797 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3799 iter++;
3802 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3804 if (data)
3806 class = get_wndclass_data(actctx, index);
3808 data->ulDataFormatVersion = 1;
3809 data->lpData = class;
3810 /* full length includes string length with nulls */
3811 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3812 data->lpSectionGlobalData = NULL;
3813 data->ulSectionGlobalDataLength = 0;
3814 data->lpSectionBase = actctx->wndclass_section;
3815 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3816 data->hActCtx = NULL;
3818 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3819 data->ulAssemblyRosterIndex = index->rosterindex;
3822 return STATUS_SUCCESS;
3825 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3827 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3828 struct guidsection_header *header;
3829 ULONG module_offset, data_offset;
3830 struct tlibredirect_data *data;
3831 struct guid_index *index;
3833 /* compute section length */
3834 for (i = 0; i < actctx->num_assemblies; i++)
3836 struct assembly *assembly = &actctx->assemblies[i];
3837 for (j = 0; j < assembly->num_dlls; j++)
3839 struct dll_redirect *dll = &assembly->dlls[j];
3840 for (k = 0; k < dll->entities.num; k++)
3842 struct entity *entity = &dll->entities.base[k];
3843 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3845 /* each entry needs index, data and string data for module name and help string */
3846 total_len += sizeof(*index);
3847 total_len += sizeof(*data);
3848 /* help string is stored separately */
3849 if (*entity->u.typelib.helpdir)
3850 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3852 /* module names are packed one after another */
3853 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
3855 tlib_count++;
3861 total_len += aligned_string_len(names_len);
3862 total_len += sizeof(*header);
3864 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3865 if (!header) return STATUS_NO_MEMORY;
3867 memset(header, 0, sizeof(*header));
3868 header->magic = GUIDSECTION_MAGIC;
3869 header->size = sizeof(*header);
3870 header->count = tlib_count;
3871 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3872 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3873 module_offset = sizeof(*header);
3874 data_offset = header->index_offset + tlib_count*sizeof(*index);
3876 for (i = 0; i < actctx->num_assemblies; i++)
3878 struct assembly *assembly = &actctx->assemblies[i];
3879 for (j = 0; j < assembly->num_dlls; j++)
3881 struct dll_redirect *dll = &assembly->dlls[j];
3882 for (k = 0; k < dll->entities.num; k++)
3884 struct entity *entity = &dll->entities.base[k];
3885 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3887 ULONG module_len, help_len;
3888 UNICODE_STRING str;
3889 WCHAR *ptrW;
3891 if (*entity->u.typelib.helpdir)
3892 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR);
3893 else
3894 help_len = 0;
3896 module_len = wcslen(dll->name)*sizeof(WCHAR);
3898 /* setup new index entry */
3899 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3900 RtlGUIDFromString(&str, &index->guid);
3901 index->data_offset = data_offset;
3902 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3903 index->rosterindex = i + 1;
3905 /* setup data */
3906 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3907 data->size = sizeof(*data);
3908 data->res = 0;
3909 data->name_len = module_len;
3910 data->name_offset = module_offset;
3911 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3912 data->langid = 0;
3913 data->flags = entity->u.typelib.flags;
3914 data->help_len = help_len;
3915 data->help_offset = sizeof(*data);
3916 data->major_version = entity->u.typelib.major;
3917 data->minor_version = entity->u.typelib.minor;
3919 /* module name */
3920 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3921 memcpy(ptrW, dll->name, data->name_len);
3922 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3924 /* help string */
3925 if (data->help_len)
3927 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3928 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3929 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3932 data_offset += sizeof(*data);
3933 if (help_len)
3934 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3936 module_offset += module_len + sizeof(WCHAR);
3938 index++;
3944 *section = header;
3946 return STATUS_SUCCESS;
3949 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3951 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3954 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3956 struct guid_index *index = NULL;
3957 struct tlibredirect_data *tlib;
3959 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3961 if (!actctx->tlib_section)
3963 struct guidsection_header *section;
3965 NTSTATUS status = build_tlib_section(actctx, &section);
3966 if (status) return status;
3968 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
3969 RtlFreeHeap(GetProcessHeap(), 0, section);
3972 index = find_guid_index(actctx->tlib_section, guid);
3973 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3975 tlib = get_tlib_data(actctx, index);
3977 data->ulDataFormatVersion = 1;
3978 data->lpData = tlib;
3979 /* full length includes string length with nulls */
3980 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3981 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3982 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3983 data->lpSectionBase = actctx->tlib_section;
3984 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3985 data->hActCtx = NULL;
3987 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3988 data->ulAssemblyRosterIndex = index->rosterindex;
3990 return STATUS_SUCCESS;
3993 static void generate_uuid(ULONG *seed, GUID *guid)
3995 ULONG *ptr = (ULONG*)guid;
3996 int i;
3998 /* GUID is 16 bytes long */
3999 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
4000 *ptr = RtlUniform(seed);
4002 guid->Data3 &= 0x0fff;
4003 guid->Data3 |= (4 << 12);
4004 guid->Data4[0] &= 0x3f;
4005 guid->Data4[0] |= 0x80;
4008 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
4009 unsigned int *count, unsigned int *len, unsigned int *module_len)
4011 unsigned int i;
4013 for (i = 0; i < entities->num; i++)
4015 struct entity *entity = &entities->base[i];
4016 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4018 /* each entry needs two index entries, extra one goes for alias GUID */
4019 *len += 2*sizeof(struct guid_index);
4020 /* To save some memory we don't allocated two data structures,
4021 instead alias index and normal index point to the same data structure. */
4022 *len += sizeof(struct comclassredirect_data);
4024 /* for clrClass store some more */
4025 if (entity->u.comclass.name)
4027 unsigned int str_len;
4029 /* all string data is stored together in aligned block */
4030 str_len = wcslen(entity->u.comclass.name)+1;
4031 if (entity->u.comclass.progid)
4032 str_len += wcslen(entity->u.comclass.progid)+1;
4033 if (entity->u.comclass.version)
4034 str_len += wcslen(entity->u.comclass.version)+1;
4036 *len += sizeof(struct clrclass_data);
4037 *len += aligned_string_len(str_len*sizeof(WCHAR));
4039 /* module name is forced to mscoree.dll, and stored two times with different case */
4040 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
4042 else
4044 /* progid string is stored separately */
4045 if (entity->u.comclass.progid)
4046 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4048 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR);
4051 *count += 1;
4056 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4057 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4058 ULONG *seed, ULONG rosterindex)
4060 unsigned int i;
4062 for (i = 0; i < entities->num; i++)
4064 struct entity *entity = &entities->base[i];
4065 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4067 ULONG module_len, progid_len, str_len = 0, miscmask;
4068 struct comclassredirect_data *data;
4069 struct guid_index *alias_index;
4070 struct clrclass_data *clrdata;
4071 UNICODE_STRING str;
4072 WCHAR *ptrW;
4074 if (entity->u.comclass.progid)
4075 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR);
4076 else
4077 progid_len = 0;
4079 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(mscoreeW)*sizeof(WCHAR);
4081 /* setup new index entry */
4082 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4083 RtlGUIDFromString(&str, &(*index)->guid);
4085 (*index)->data_offset = *data_offset;
4086 (*index)->data_len = sizeof(*data); /* additional length added later */
4087 (*index)->rosterindex = rosterindex;
4089 /* Setup new index entry for alias guid. Alias index records are placed after
4090 normal records, so normal guids are hit first on search. Note that class count
4091 is doubled. */
4092 alias_index = (*index) + section->count/2;
4093 generate_uuid(seed, &alias_index->guid);
4094 alias_index->data_offset = (*index)->data_offset;
4095 alias_index->data_len = 0;
4096 alias_index->rosterindex = (*index)->rosterindex;
4098 /* setup data */
4099 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4100 data->size = sizeof(*data);
4101 data->model = entity->u.comclass.model;
4102 data->clsid = (*index)->guid;
4103 data->alias = alias_index->guid;
4104 data->clsid2 = data->clsid;
4105 if (entity->u.comclass.tlbid)
4107 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4108 RtlGUIDFromString(&str, &data->tlbid);
4110 else
4111 memset(&data->tlbid, 0, sizeof(data->tlbid));
4112 data->name_len = module_len;
4113 data->name_offset = *module_offset;
4114 data->progid_len = progid_len;
4115 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4116 data->clrdata_len = 0; /* will be set later */
4117 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4118 data->miscstatus = entity->u.comclass.miscstatus;
4119 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4120 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4121 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4122 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4124 /* mask describes which misc* data is available */
4125 miscmask = 0;
4126 if (data->miscstatus)
4127 miscmask |= MiscStatus;
4128 if (data->miscstatuscontent)
4129 miscmask |= MiscStatusContent;
4130 if (data->miscstatusthumbnail)
4131 miscmask |= MiscStatusThumbnail;
4132 if (data->miscstatusicon)
4133 miscmask |= MiscStatusIcon;
4134 if (data->miscstatusdocprint)
4135 miscmask |= MiscStatusDocPrint;
4136 data->flags = miscmask << 8;
4138 if (data->clrdata_offset)
4140 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4142 clrdata->size = sizeof(*clrdata);
4143 clrdata->res[0] = 0;
4144 clrdata->res[1] = 2; /* FIXME: unknown field */
4145 clrdata->module_len = wcslen(mscoreeW)*sizeof(WCHAR);
4146 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4147 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR);
4148 clrdata->name_offset = clrdata->size;
4149 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4150 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4151 clrdata->res2[0] = 0;
4152 clrdata->res2[1] = 0;
4154 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4156 /* module name */
4157 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4158 memcpy(ptrW, mscoree2W, clrdata->module_len);
4159 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4161 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4162 memcpy(ptrW, mscoreeW, data->name_len);
4163 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4165 /* class name */
4166 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4167 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4168 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4170 /* runtime version, optional */
4171 if (clrdata->version_len)
4173 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4175 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4176 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4177 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4180 if (data->progid_len)
4181 data->progid_offset += data->clrdata_len;
4182 (*index)->data_len += sizeof(*clrdata);
4184 else
4186 clrdata = NULL;
4188 /* module name */
4189 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4190 memcpy(ptrW, dll->name, data->name_len);
4191 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4194 /* progid string */
4195 if (data->progid_len)
4197 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4198 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4199 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4202 /* string block length */
4203 str_len = 0;
4204 if (clrdata)
4206 str_len += clrdata->name_len + sizeof(WCHAR);
4207 if (clrdata->version_len)
4208 str_len += clrdata->version_len + sizeof(WCHAR);
4210 if (progid_len)
4211 str_len += progid_len + sizeof(WCHAR);
4213 (*index)->data_len += aligned_string_len(str_len);
4214 alias_index->data_len = (*index)->data_len;
4216 /* move to next data record */
4217 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4218 (*module_offset) += module_len + sizeof(WCHAR);
4220 if (clrdata)
4222 (*data_offset) += sizeof(*clrdata);
4223 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4225 (*index) += 1;
4230 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4232 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4233 struct guidsection_header *header;
4234 ULONG module_offset, data_offset;
4235 struct guid_index *index;
4236 ULONG seed;
4238 /* compute section length */
4239 for (i = 0; i < actctx->num_assemblies; i++)
4241 struct assembly *assembly = &actctx->assemblies[i];
4242 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4243 for (j = 0; j < assembly->num_dlls; j++)
4245 struct dll_redirect *dll = &assembly->dlls[j];
4246 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4250 total_len += aligned_string_len(names_len);
4251 total_len += sizeof(*header);
4253 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4254 if (!header) return STATUS_NO_MEMORY;
4256 memset(header, 0, sizeof(*header));
4257 header->magic = GUIDSECTION_MAGIC;
4258 header->size = sizeof(*header);
4259 header->count = 2*class_count;
4260 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4261 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4262 module_offset = sizeof(*header);
4263 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4265 seed = NtGetTickCount();
4266 for (i = 0; i < actctx->num_assemblies; i++)
4268 struct assembly *assembly = &actctx->assemblies[i];
4269 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4270 for (j = 0; j < assembly->num_dlls; j++)
4272 struct dll_redirect *dll = &assembly->dlls[j];
4273 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4277 *section = header;
4279 return STATUS_SUCCESS;
4282 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4284 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4287 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4289 struct comclassredirect_data *comclass;
4290 struct guid_index *index = NULL;
4292 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4294 if (!actctx->comserver_section)
4296 struct guidsection_header *section;
4298 NTSTATUS status = build_comserver_section(actctx, &section);
4299 if (status) return status;
4301 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4302 RtlFreeHeap(GetProcessHeap(), 0, section);
4305 index = find_guid_index(actctx->comserver_section, guid);
4306 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4308 comclass = get_comclass_data(actctx, index);
4310 data->ulDataFormatVersion = 1;
4311 data->lpData = comclass;
4312 /* full length includes string length with nulls */
4313 data->ulLength = comclass->size + comclass->clrdata_len;
4314 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4315 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4316 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4317 data->lpSectionBase = actctx->comserver_section;
4318 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4319 data->hActCtx = NULL;
4321 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4322 data->ulAssemblyRosterIndex = index->rosterindex;
4324 return STATUS_SUCCESS;
4327 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4329 unsigned int i;
4331 for (i = 0; i < entities->num; i++)
4333 struct entity *entity = &entities->base[i];
4334 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4336 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4337 if (entity->u.ifaceps.name)
4338 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4339 *count += 1;
4344 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4345 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4347 unsigned int i;
4349 for (i = 0; i < entities->num; i++)
4351 struct entity *entity = &entities->base[i];
4352 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4354 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4355 UNICODE_STRING str;
4356 ULONG name_len;
4358 if (entity->u.ifaceps.name)
4359 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR);
4360 else
4361 name_len = 0;
4363 /* setup index */
4364 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4365 RtlGUIDFromString(&str, &(*index)->guid);
4366 (*index)->data_offset = *data_offset;
4367 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4368 (*index)->rosterindex = rosterindex;
4370 /* setup data record */
4371 data->size = sizeof(*data);
4372 data->mask = entity->u.ifaceps.mask;
4374 /* proxyStubClsid32 value is only stored for external PS,
4375 if set it's used as iid, otherwise 'iid' attribute value is used */
4376 if (entity->u.ifaceps.ps32)
4378 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4379 RtlGUIDFromString(&str, &data->iid);
4381 else
4382 data->iid = (*index)->guid;
4384 data->nummethods = entity->u.ifaceps.nummethods;
4386 if (entity->u.ifaceps.tlib)
4388 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4389 RtlGUIDFromString(&str, &data->tlbid);
4391 else
4392 memset(&data->tlbid, 0, sizeof(data->tlbid));
4394 if (entity->u.ifaceps.base)
4396 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4397 RtlGUIDFromString(&str, &data->base);
4399 else
4400 memset(&data->base, 0, sizeof(data->base));
4402 data->name_len = name_len;
4403 data->name_offset = data->name_len ? sizeof(*data) : 0;
4405 /* name string */
4406 if (data->name_len)
4408 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4409 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4410 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4413 /* move to next record */
4414 (*index) += 1;
4415 *data_offset += sizeof(*data);
4416 if (data->name_len)
4417 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4422 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4424 unsigned int i, j, total_len = 0, count = 0;
4425 struct guidsection_header *header;
4426 struct guid_index *index;
4427 ULONG data_offset;
4429 /* compute section length */
4430 for (i = 0; i < actctx->num_assemblies; i++)
4432 struct assembly *assembly = &actctx->assemblies[i];
4434 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4435 for (j = 0; j < assembly->num_dlls; j++)
4437 struct dll_redirect *dll = &assembly->dlls[j];
4438 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4442 total_len += sizeof(*header);
4444 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4445 if (!header) return STATUS_NO_MEMORY;
4447 memset(header, 0, sizeof(*header));
4448 header->magic = GUIDSECTION_MAGIC;
4449 header->size = sizeof(*header);
4450 header->count = count;
4451 header->index_offset = sizeof(*header);
4452 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4453 data_offset = header->index_offset + count*sizeof(*index);
4455 for (i = 0; i < actctx->num_assemblies; i++)
4457 struct assembly *assembly = &actctx->assemblies[i];
4459 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4460 for (j = 0; j < assembly->num_dlls; j++)
4462 struct dll_redirect *dll = &assembly->dlls[j];
4463 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4467 *section = header;
4469 return STATUS_SUCCESS;
4472 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4474 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4477 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4479 struct ifacepsredirect_data *iface;
4480 struct guid_index *index = NULL;
4482 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4484 if (!actctx->ifaceps_section)
4486 struct guidsection_header *section;
4488 NTSTATUS status = build_ifaceps_section(actctx, &section);
4489 if (status) return status;
4491 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
4492 RtlFreeHeap(GetProcessHeap(), 0, section);
4495 index = find_guid_index(actctx->ifaceps_section, guid);
4496 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4498 iface = get_ifaceps_data(actctx, index);
4500 data->ulDataFormatVersion = 1;
4501 data->lpData = iface;
4502 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4503 data->lpSectionGlobalData = NULL;
4504 data->ulSectionGlobalDataLength = 0;
4505 data->lpSectionBase = actctx->ifaceps_section;
4506 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4507 data->hActCtx = NULL;
4509 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4510 data->ulAssemblyRosterIndex = index->rosterindex;
4512 return STATUS_SUCCESS;
4515 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4517 unsigned int i, j, total_len = 0, count = 0;
4518 struct guidsection_header *header;
4519 struct clrsurrogate_data *data;
4520 struct guid_index *index;
4521 ULONG data_offset;
4523 /* compute section length */
4524 for (i = 0; i < actctx->num_assemblies; i++)
4526 struct assembly *assembly = &actctx->assemblies[i];
4527 for (j = 0; j < assembly->entities.num; j++)
4529 struct entity *entity = &assembly->entities.base[j];
4530 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4532 ULONG len;
4534 total_len += sizeof(*index) + sizeof(*data);
4535 len = wcslen(entity->u.clrsurrogate.name) + 1;
4536 if (entity->u.clrsurrogate.version)
4537 len += wcslen(entity->u.clrsurrogate.version) + 1;
4538 total_len += aligned_string_len(len*sizeof(WCHAR));
4540 count++;
4545 total_len += sizeof(*header);
4547 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4548 if (!header) return STATUS_NO_MEMORY;
4550 memset(header, 0, sizeof(*header));
4551 header->magic = GUIDSECTION_MAGIC;
4552 header->size = sizeof(*header);
4553 header->count = count;
4554 header->index_offset = sizeof(*header);
4555 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4556 data_offset = header->index_offset + count*sizeof(*index);
4558 for (i = 0; i < actctx->num_assemblies; i++)
4560 struct assembly *assembly = &actctx->assemblies[i];
4561 for (j = 0; j < assembly->entities.num; j++)
4563 struct entity *entity = &assembly->entities.base[j];
4564 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4566 ULONG version_len, name_len;
4567 UNICODE_STRING str;
4568 WCHAR *ptrW;
4570 if (entity->u.clrsurrogate.version)
4571 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4572 else
4573 version_len = 0;
4574 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4576 /* setup new index entry */
4577 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4578 RtlGUIDFromString(&str, &index->guid);
4580 index->data_offset = data_offset;
4581 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4582 index->rosterindex = i + 1;
4584 /* setup data */
4585 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4586 data->size = sizeof(*data);
4587 data->res = 0;
4588 data->clsid = index->guid;
4589 data->version_offset = version_len ? data->size : 0;
4590 data->version_len = version_len;
4591 data->name_offset = data->size + version_len;
4592 if (version_len)
4593 data->name_offset += sizeof(WCHAR);
4594 data->name_len = name_len;
4596 /* surrogate name */
4597 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4598 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4599 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4601 /* runtime version */
4602 if (data->version_len)
4604 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4605 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4606 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4609 data_offset += index->data_offset;
4610 index++;
4615 *section = header;
4617 return STATUS_SUCCESS;
4620 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4622 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4625 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4627 struct clrsurrogate_data *surrogate;
4628 struct guid_index *index = NULL;
4630 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4632 if (!actctx->clrsurrogate_section)
4634 struct guidsection_header *section;
4636 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4637 if (status) return status;
4639 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
4640 RtlFreeHeap(GetProcessHeap(), 0, section);
4643 index = find_guid_index(actctx->clrsurrogate_section, guid);
4644 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4646 surrogate = get_surrogate_data(actctx, index);
4648 data->ulDataFormatVersion = 1;
4649 data->lpData = surrogate;
4650 /* full length includes string length with nulls */
4651 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4652 if (surrogate->version_len)
4653 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4655 data->lpSectionGlobalData = NULL;
4656 data->ulSectionGlobalDataLength = 0;
4657 data->lpSectionBase = actctx->clrsurrogate_section;
4658 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4659 data->hActCtx = NULL;
4661 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4662 data->ulAssemblyRosterIndex = index->rosterindex;
4664 return STATUS_SUCCESS;
4667 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4669 unsigned int i, j, single_len;
4671 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4672 for (i = 0; i < entities->num; i++)
4674 struct entity *entity = &entities->base[i];
4675 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4677 if (entity->u.comclass.progid)
4679 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4680 *count += 1;
4683 for (j = 0; j < entity->u.comclass.progids.num; j++)
4684 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4686 *total_len += single_len*entity->u.comclass.progids.num;
4687 *count += entity->u.comclass.progids.num;
4692 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4693 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4695 struct progidredirect_data *data;
4696 UNICODE_STRING str;
4697 GUID *guid_ptr;
4698 WCHAR *ptrW;
4700 /* setup new index entry */
4702 /* hash progid name */
4703 RtlInitUnicodeString(&str, progid);
4704 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4706 (*index)->name_offset = *data_offset;
4707 (*index)->name_len = str.Length;
4708 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4709 (*index)->data_len = sizeof(*data);
4710 (*index)->rosterindex = rosterindex;
4712 *data_offset += aligned_string_len(str.MaximumLength);
4714 /* setup data structure */
4715 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4716 data->size = sizeof(*data);
4717 data->reserved = 0;
4718 data->clsid_offset = *global_offset;
4720 /* write progid string */
4721 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4722 memcpy(ptrW, progid, (*index)->name_len);
4723 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4725 /* write guid to global area */
4726 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4727 *guid_ptr = *alias;
4729 /* to next entry */
4730 *global_offset += sizeof(GUID);
4731 *data_offset += data->size;
4732 (*index) += 1;
4735 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4736 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4738 unsigned int i, j;
4740 for (i = 0; i < entities->num; i++)
4742 struct entity *entity = &entities->base[i];
4743 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4745 const struct progids *progids = &entity->u.comclass.progids;
4746 struct comclassredirect_data *comclass;
4747 struct guid_index *guid_index;
4748 UNICODE_STRING str;
4749 GUID clsid;
4751 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4752 RtlGUIDFromString(&str, &clsid);
4754 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4755 comclass = get_comclass_data(actctx, guid_index);
4757 if (entity->u.comclass.progid)
4758 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4759 index, data_offset, global_offset, rosterindex);
4761 for (j = 0; j < progids->num; j++)
4762 write_progid_record(section, progids->progids[j], &comclass->alias,
4763 index, data_offset, global_offset, rosterindex);
4768 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4770 unsigned int i, j, total_len = 0, count = 0;
4771 struct strsection_header *header;
4772 ULONG data_offset, global_offset;
4773 struct string_index *index;
4775 /* compute section length */
4776 for (i = 0; i < actctx->num_assemblies; i++)
4778 struct assembly *assembly = &actctx->assemblies[i];
4780 get_progid_datalen(&assembly->entities, &count, &total_len);
4781 for (j = 0; j < assembly->num_dlls; j++)
4783 struct dll_redirect *dll = &assembly->dlls[j];
4784 get_progid_datalen(&dll->entities, &count, &total_len);
4788 total_len += sizeof(*header);
4790 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4791 if (!header) return STATUS_NO_MEMORY;
4793 memset(header, 0, sizeof(*header));
4794 header->magic = STRSECTION_MAGIC;
4795 header->size = sizeof(*header);
4796 header->count = count;
4797 header->global_offset = header->size;
4798 header->global_len = count*sizeof(GUID);
4799 header->index_offset = header->size + header->global_len;
4801 index = (struct string_index*)((BYTE*)header + header->index_offset);
4802 data_offset = header->index_offset + count*sizeof(*index);
4803 global_offset = header->global_offset;
4805 for (i = 0; i < actctx->num_assemblies; i++)
4807 struct assembly *assembly = &actctx->assemblies[i];
4809 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4810 for (j = 0; j < assembly->num_dlls; j++)
4812 struct dll_redirect *dll = &assembly->dlls[j];
4813 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4817 *section = header;
4819 return STATUS_SUCCESS;
4822 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4824 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4827 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4828 PACTCTX_SECTION_KEYED_DATA data)
4830 struct progidredirect_data *progid;
4831 struct string_index *index;
4833 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4835 if (!actctx->comserver_section)
4837 struct guidsection_header *section;
4839 NTSTATUS status = build_comserver_section(actctx, &section);
4840 if (status) return status;
4842 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
4843 RtlFreeHeap(GetProcessHeap(), 0, section);
4846 if (!actctx->progid_section)
4848 struct strsection_header *section;
4850 NTSTATUS status = build_progid_section(actctx, &section);
4851 if (status) return status;
4853 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
4854 RtlFreeHeap(GetProcessHeap(), 0, section);
4857 index = find_string_index(actctx->progid_section, name);
4858 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4860 if (data)
4862 progid = get_progid_data(actctx, index);
4864 data->ulDataFormatVersion = 1;
4865 data->lpData = progid;
4866 data->ulLength = progid->size;
4867 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4868 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4869 data->lpSectionBase = actctx->progid_section;
4870 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4871 data->hActCtx = NULL;
4873 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4874 data->ulAssemblyRosterIndex = index->rosterindex;
4877 return STATUS_SUCCESS;
4880 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4881 const UNICODE_STRING *section_name,
4882 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4884 NTSTATUS status;
4886 switch (section_kind)
4888 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4889 status = find_dll_redirection(actctx, section_name, data);
4890 break;
4891 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4892 status = find_window_class(actctx, section_name, data);
4893 break;
4894 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4895 status = find_progid_redirection(actctx, section_name, data);
4896 break;
4897 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4898 FIXME("Unsupported yet section_kind %x\n", section_kind);
4899 return STATUS_SXS_SECTION_NOT_FOUND;
4900 default:
4901 WARN("Unknown section_kind %x\n", section_kind);
4902 return STATUS_SXS_SECTION_NOT_FOUND;
4905 if (status != STATUS_SUCCESS) return status;
4907 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4909 actctx_addref(actctx);
4910 data->hActCtx = actctx;
4912 return STATUS_SUCCESS;
4915 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4916 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4918 NTSTATUS status;
4920 switch (section_kind)
4922 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4923 status = find_tlib_redirection(actctx, guid, data);
4924 break;
4925 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4926 status = find_comserver_redirection(actctx, guid, data);
4927 break;
4928 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4929 status = find_cominterface_redirection(actctx, guid, data);
4930 break;
4931 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4932 status = find_clr_surrogate(actctx, guid, data);
4933 break;
4934 default:
4935 WARN("Unknown section_kind %x\n", section_kind);
4936 return STATUS_SXS_SECTION_NOT_FOUND;
4939 if (status != STATUS_SUCCESS) return status;
4941 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4943 actctx_addref(actctx);
4944 data->hActCtx = actctx;
4946 return STATUS_SUCCESS;
4949 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns )
4951 unsigned int i, j;
4953 for (i = 0; i < actctx->num_assemblies; i++)
4955 struct assembly *assembly = &actctx->assemblies[i];
4956 for (j = 0; j < assembly->entities.num; j++)
4958 struct entity *entity = &assembly->entities.base[j];
4959 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS &&
4960 !wcscmp( entity->u.settings.name, settings ) &&
4961 !wcscmp( entity->u.settings.ns, ns ))
4962 return entity->u.settings.value;
4965 return NULL;
4968 /* initialize the activation context for the current process */
4969 void actctx_init(void)
4971 ACTCTXW ctx;
4972 HANDLE handle;
4974 ctx.cbSize = sizeof(ctx);
4975 ctx.lpSource = NULL;
4976 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4977 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4978 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4980 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4982 NtCurrentTeb()->Peb->ActivationContextData = process_actctx;
4986 /***********************************************************************
4987 * RtlCreateActivationContext (NTDLL.@)
4989 * Create an activation context.
4991 * FIXME: function signature/prototype is wrong
4993 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4995 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4996 const WCHAR *directory = NULL;
4997 ACTIVATION_CONTEXT *actctx;
4998 UNICODE_STRING nameW;
4999 ULONG lang = 0;
5000 NTSTATUS status = STATUS_NO_MEMORY;
5001 HANDLE file = 0;
5002 struct actctx_loader acl;
5004 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
5006 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
5007 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
5008 return STATUS_INVALID_PARAMETER;
5010 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
5011 return STATUS_NO_MEMORY;
5013 actctx->magic = ACTCTX_MAGIC;
5014 actctx->ref_count = 1;
5015 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
5016 actctx->config.info = NULL;
5017 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
5018 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
5020 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
5022 else
5024 UNICODE_STRING dir;
5025 WCHAR *p;
5026 HMODULE module;
5028 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
5029 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
5031 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
5032 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0;
5033 actctx->appdir.info = dir.Buffer;
5036 nameW.Buffer = NULL;
5038 /* open file only if it's going to be used */
5039 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
5040 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
5042 WCHAR *source = NULL;
5043 BOOLEAN ret;
5045 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
5046 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
5048 DWORD dir_len, source_len;
5050 dir_len = wcslen(pActCtx->lpAssemblyDirectory);
5051 source_len = wcslen(pActCtx->lpSource);
5052 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
5054 status = STATUS_NO_MEMORY;
5055 goto error;
5058 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
5059 source[dir_len] = '\\';
5060 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
5063 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
5064 RtlFreeHeap( GetProcessHeap(), 0, source );
5065 if (!ret)
5067 status = STATUS_NO_SUCH_FILE;
5068 goto error;
5070 status = open_nt_file( &file, &nameW );
5071 if (status)
5073 RtlFreeUnicodeString( &nameW );
5074 goto error;
5078 acl.actctx = actctx;
5079 acl.dependencies = NULL;
5080 acl.num_dependencies = 0;
5081 acl.allocated_dependencies = 0;
5083 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5084 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5086 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5088 /* if we have a resource it's a PE file */
5089 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5091 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5092 pActCtx->lpResourceName, lang );
5093 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5094 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5095 pActCtx->hModule, pActCtx->lpResourceName );
5097 else if (pActCtx->lpSource)
5099 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5100 file, pActCtx->lpResourceName, lang );
5101 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5102 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5103 NULL, pActCtx->lpResourceName );
5105 else status = STATUS_INVALID_PARAMETER;
5107 else
5109 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5112 if (file) NtClose( file );
5113 RtlFreeUnicodeString( &nameW );
5115 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5116 free_depend_manifests( &acl );
5118 if (status == STATUS_SUCCESS) *handle = actctx;
5119 else actctx_release( actctx );
5120 return status;
5122 error:
5123 if (file) NtClose( file );
5124 actctx_release( actctx );
5125 return status;
5129 /***********************************************************************
5130 * RtlAddRefActivationContext (NTDLL.@)
5132 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5134 ACTIVATION_CONTEXT *actctx;
5136 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5140 /******************************************************************
5141 * RtlReleaseActivationContext (NTDLL.@)
5143 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5145 ACTIVATION_CONTEXT *actctx;
5147 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5150 /******************************************************************
5151 * RtlZombifyActivationContext (NTDLL.@)
5153 * FIXME: function prototype might be wrong
5155 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5157 FIXME("%p: stub\n", handle);
5158 return STATUS_NOT_IMPLEMENTED;
5161 /******************************************************************
5162 * RtlActivateActivationContext (NTDLL.@)
5164 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5166 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie );
5170 /******************************************************************
5171 * RtlActivateActivationContextEx (NTDLL.@)
5173 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie )
5175 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5177 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5178 return STATUS_NO_MEMORY;
5180 frame->Previous = teb->ActivationContextStack.ActiveFrame;
5181 frame->ActivationContext = handle;
5182 frame->Flags = 0;
5183 teb->ActivationContextStack.ActiveFrame = frame;
5184 RtlAddRefActivationContext( handle );
5186 *cookie = (ULONG_PTR)frame;
5187 TRACE( "%p cookie=%lx\n", handle, *cookie );
5188 return STATUS_SUCCESS;
5192 /***********************************************************************
5193 * RtlDeactivateActivationContext (NTDLL.@)
5195 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5197 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5199 TRACE( "%x cookie=%lx\n", flags, cookie );
5201 /* find the right frame */
5202 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5203 for (frame = top; frame; frame = frame->Previous)
5204 if ((ULONG_PTR)frame == cookie) break;
5206 if (!frame)
5207 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5209 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5210 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5212 /* pop everything up to and including frame */
5213 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5215 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5217 frame = top->Previous;
5218 RtlReleaseActivationContext( top->ActivationContext );
5219 RtlFreeHeap( GetProcessHeap(), 0, top );
5220 top = frame;
5225 /******************************************************************
5226 * RtlFreeThreadActivationContextStack (NTDLL.@)
5228 void WINAPI RtlFreeThreadActivationContextStack(void)
5230 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5232 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5233 while (frame)
5235 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5236 RtlReleaseActivationContext( frame->ActivationContext );
5237 RtlFreeHeap( GetProcessHeap(), 0, frame );
5238 frame = prev;
5240 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5244 /******************************************************************
5245 * RtlGetActiveActivationContext (NTDLL.@)
5247 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5249 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5251 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5252 RtlAddRefActivationContext( *handle );
5254 else
5255 *handle = 0;
5257 return STATUS_SUCCESS;
5261 /******************************************************************
5262 * RtlIsActivationContextActive (NTDLL.@)
5264 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5266 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5268 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5269 if (frame->ActivationContext == handle) return TRUE;
5270 return FALSE;
5274 /***********************************************************************
5275 * RtlQueryInformationActivationContext (NTDLL.@)
5277 * Get information about an activation context.
5278 * FIXME: function signature/prototype may be wrong
5280 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5281 ULONG class, PVOID buffer,
5282 SIZE_T bufsize, SIZE_T *retlen )
5284 ACTIVATION_CONTEXT *actctx;
5285 NTSTATUS status;
5287 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5288 subinst, class, buffer, bufsize, retlen);
5290 if (retlen) *retlen = 0;
5291 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5293 switch (class)
5295 case ActivationContextBasicInformation:
5297 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5299 if (retlen) *retlen = sizeof(*info);
5300 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5302 info->hActCtx = handle;
5303 info->dwFlags = 0; /* FIXME */
5304 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5306 break;
5308 case ActivationContextDetailedInformation:
5310 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5311 struct assembly *assembly = NULL;
5312 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5313 LPWSTR ptr;
5315 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5317 if (actctx->num_assemblies) assembly = actctx->assemblies;
5319 if (assembly && assembly->manifest.info)
5320 manifest_len = wcslen(assembly->manifest.info) + 1;
5321 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1;
5322 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1;
5323 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5325 if (retlen) *retlen = len;
5326 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5328 acdi->dwFlags = 0;
5329 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5330 acdi->ulAssemblyCount = actctx->num_assemblies;
5331 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5332 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5333 acdi->ulRootConfigurationPathType = actctx->config.type;
5334 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5335 acdi->ulAppDirPathType = actctx->appdir.type;
5336 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5337 ptr = (LPWSTR)(acdi + 1);
5338 if (manifest_len)
5340 acdi->lpRootManifestPath = ptr;
5341 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5342 ptr += manifest_len;
5344 else acdi->lpRootManifestPath = NULL;
5345 if (config_len)
5347 acdi->lpRootConfigurationPath = ptr;
5348 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5349 ptr += config_len;
5351 else acdi->lpRootConfigurationPath = NULL;
5352 if (appdir_len)
5354 acdi->lpAppDirPath = ptr;
5355 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5357 else acdi->lpAppDirPath = NULL;
5359 break;
5361 case AssemblyDetailedInformationInActivationContext:
5363 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5364 struct assembly *assembly;
5365 WCHAR *assembly_id;
5366 DWORD index;
5367 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5368 LPWSTR ptr;
5370 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5371 if (!subinst) return STATUS_INVALID_PARAMETER;
5373 index = *(DWORD*)subinst;
5374 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5376 assembly = &actctx->assemblies[index - 1];
5378 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5379 id_len = wcslen(assembly_id) + 1;
5380 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1;
5382 if (assembly->manifest.info &&
5383 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5384 path_len = wcslen(assembly->manifest.info) + 1;
5386 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5388 if (retlen) *retlen = len;
5389 if (!buffer || bufsize < len)
5391 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5392 return STATUS_BUFFER_TOO_SMALL;
5395 afdi->ulFlags = 0; /* FIXME */
5396 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5397 afdi->ulManifestPathType = assembly->manifest.type;
5398 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5399 /* FIXME afdi->liManifestLastWriteTime = 0; */
5400 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5401 afdi->ulPolicyPathLength = 0;
5402 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5403 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5404 afdi->ulManifestVersionMajor = 1;
5405 afdi->ulManifestVersionMinor = 0;
5406 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5407 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5408 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5409 ptr = (LPWSTR)(afdi + 1);
5410 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5411 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5412 ptr += id_len;
5413 if (path_len)
5415 afdi->lpAssemblyManifestPath = ptr;
5416 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5417 ptr += path_len;
5418 } else afdi->lpAssemblyManifestPath = NULL;
5419 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5420 if (ad_len)
5422 afdi->lpAssemblyDirectoryName = ptr;
5423 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5425 else afdi->lpAssemblyDirectoryName = NULL;
5426 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5428 break;
5430 case FileInformationInAssemblyOfAssemblyInActivationContext:
5432 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5433 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5434 struct assembly *assembly;
5435 struct dll_redirect *dll;
5436 SIZE_T len, dll_len = 0;
5437 LPWSTR ptr;
5439 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5440 if (!acqi) return STATUS_INVALID_PARAMETER;
5442 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5443 return STATUS_INVALID_PARAMETER;
5444 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5446 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5447 return STATUS_INVALID_PARAMETER;
5448 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5450 if (dll->name) dll_len = wcslen(dll->name) + 1;
5451 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5453 if (!buffer || bufsize < len)
5455 if (retlen) *retlen = len;
5456 return STATUS_BUFFER_TOO_SMALL;
5458 if (retlen) *retlen = 0; /* yes that's what native does !! */
5459 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5460 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5461 afdi->ulPathLength = 0; /* FIXME */
5462 ptr = (LPWSTR)(afdi + 1);
5463 if (dll_len)
5465 afdi->lpFileName = ptr;
5466 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5467 } else afdi->lpFileName = NULL;
5468 afdi->lpFilePath = NULL; /* FIXME */
5470 break;
5472 case CompatibilityInformationInActivationContext:
5474 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5475 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5476 struct assembly *assembly = NULL;
5477 ULONG num_compat_contexts = 0, n;
5478 SIZE_T len;
5480 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5482 if (actctx->num_assemblies) assembly = actctx->assemblies;
5484 if (assembly)
5485 num_compat_contexts = assembly->num_compat_contexts;
5486 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5488 if (retlen) *retlen = len;
5489 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5491 *acci = num_compat_contexts;
5492 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5493 for (n = 0; n < num_compat_contexts; ++n)
5495 elements[n] = assembly->compat_contexts[n];
5498 break;
5500 case RunlevelInformationInActivationContext:
5502 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5503 struct assembly *assembly;
5504 SIZE_T len;
5506 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5508 len = sizeof(*acrli);
5509 if (retlen) *retlen = len;
5510 if (!buffer || bufsize < len)
5511 return STATUS_BUFFER_TOO_SMALL;
5513 assembly = actctx->assemblies;
5515 acrli->ulFlags = 0;
5516 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5517 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5519 break;
5521 default:
5522 FIXME( "class %u not implemented\n", class );
5523 return STATUS_NOT_IMPLEMENTED;
5525 return STATUS_SUCCESS;
5528 /***********************************************************************
5529 * RtlFindActivationContextSectionString (NTDLL.@)
5531 * Find information about a string in an activation context.
5532 * FIXME: function signature/prototype may be wrong
5534 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5535 const UNICODE_STRING *section_name, PVOID ptr )
5537 PACTCTX_SECTION_KEYED_DATA data = ptr;
5538 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5540 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5541 debugstr_us(section_name), data);
5543 if (guid)
5545 FIXME("expected guid == NULL\n");
5546 return STATUS_INVALID_PARAMETER;
5548 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5550 FIXME("unknown flags %08x\n", flags);
5551 return STATUS_INVALID_PARAMETER;
5553 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5554 !section_name || !section_name->Buffer)
5556 WARN("invalid parameter\n");
5557 return STATUS_INVALID_PARAMETER;
5560 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5562 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5563 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5566 if (status != STATUS_SUCCESS)
5567 status = find_string( process_actctx, section_kind, section_name, flags, data );
5569 return status;
5572 /***********************************************************************
5573 * RtlFindActivationContextSectionGuid (NTDLL.@)
5575 * Find information about a GUID in an activation context.
5576 * FIXME: function signature/prototype may be wrong
5578 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5579 const GUID *guid, void *ptr )
5581 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5582 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5584 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5586 if (extguid)
5588 FIXME("expected extguid == NULL\n");
5589 return STATUS_INVALID_PARAMETER;
5592 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5594 FIXME("unknown flags %08x\n", flags);
5595 return STATUS_INVALID_PARAMETER;
5598 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5599 return STATUS_INVALID_PARAMETER;
5601 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5603 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5604 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5607 if (status != STATUS_SUCCESS)
5608 status = find_guid( process_actctx, section_kind, guid, flags, data );
5610 return status;
5614 /***********************************************************************
5615 * RtlQueryActivationContextApplicationSettings (NTDLL.@)
5617 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns,
5618 const WCHAR *settings, WCHAR *buffer,
5619 SIZE_T size, SIZE_T *written )
5621 ACTIVATION_CONTEXT *actctx;
5622 const WCHAR *res;
5624 if (flags)
5626 WARN( "unknown flags %08x\n", flags );
5627 return STATUS_INVALID_PARAMETER;
5630 if (ns)
5632 if (wcscmp( ns, windowsSettings2005NSW ) &&
5633 wcscmp( ns, windowsSettings2011NSW ) &&
5634 wcscmp( ns, windowsSettings2016NSW ) &&
5635 wcscmp( ns, windowsSettings2017NSW ))
5636 return STATUS_INVALID_PARAMETER;
5638 else ns = windowsSettings2005NSW;
5640 if (!handle) handle = process_actctx;
5641 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER;
5643 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND;
5645 if (written) *written = wcslen(res) + 1;
5646 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL;
5647 wcscpy( buffer, res );
5648 return STATUS_SUCCESS;