ntdll: Implement RunlevelInformationInActivationContext in RtlQueryInformationActivat...
[wine.git] / dlls / ntdll / actctx.c
blob4a3370048fa0315480225f7f52982ae853162014
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
34 #include "winternl.h"
35 #include "ddk/wdm.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 /* from oaidl.h */
62 typedef enum tagLIBFLAGS {
63 LIBFLAG_FRESTRICTED = 0x1,
64 LIBFLAG_FCONTROL = 0x2,
65 LIBFLAG_FHIDDEN = 0x4,
66 LIBFLAG_FHASDISKIMAGE = 0x8
67 } LIBFLAGS;
69 /* from oleidl.idl */
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE = 0x1,
73 OLEMISC_ONLYICONIC = 0x2,
74 OLEMISC_INSERTNOTREPLACE = 0x4,
75 OLEMISC_STATIC = 0x8,
76 OLEMISC_CANTLINKINSIDE = 0x10,
77 OLEMISC_CANLINKBYOLE1 = 0x20,
78 OLEMISC_ISLINKOBJECT = 0x40,
79 OLEMISC_INSIDEOUT = 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
82 OLEMISC_INVISIBLEATRUNTIME = 0x400,
83 OLEMISC_ALWAYSRUN = 0x800,
84 OLEMISC_ACTSLIKEBUTTON = 0x1000,
85 OLEMISC_ACTSLIKELABEL = 0x2000,
86 OLEMISC_NOUIACTIVATE = 0x4000,
87 OLEMISC_ALIGNABLE = 0x8000,
88 OLEMISC_SIMPLEFRAME = 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
90 OLEMISC_IMEMODE = 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
92 OLEMISC_WANTSTOMENUMERGE = 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
94 } OLEMISC;
96 typedef struct
98 const WCHAR *ptr;
99 unsigned int len;
100 } xmlstr_t;
102 typedef struct
104 const WCHAR *ptr;
105 const WCHAR *end;
106 } xmlbuf_t;
108 struct file_info
110 ULONG type;
111 WCHAR *info;
114 struct assembly_version
116 USHORT major;
117 USHORT minor;
118 USHORT build;
119 USHORT revision;
122 struct assembly_identity
124 WCHAR *name;
125 WCHAR *arch;
126 WCHAR *public_key;
127 WCHAR *language;
128 WCHAR *type;
129 struct assembly_version version;
130 BOOL optional;
131 BOOL delayed;
134 struct strsection_header
136 DWORD magic;
137 ULONG size;
138 DWORD unk1[3];
139 ULONG count;
140 ULONG index_offset;
141 DWORD unk2[2];
142 ULONG global_offset;
143 ULONG global_len;
146 struct string_index
148 ULONG hash; /* key string hash */
149 ULONG name_offset;
150 ULONG name_len;
151 ULONG data_offset; /* redirect data offset */
152 ULONG data_len;
153 ULONG rosterindex;
156 struct guidsection_header
158 DWORD magic;
159 ULONG size;
160 DWORD unk[3];
161 ULONG count;
162 ULONG index_offset;
163 DWORD unk2;
164 ULONG names_offset;
165 ULONG names_len;
168 struct guid_index
170 GUID guid;
171 ULONG data_offset;
172 ULONG data_len;
173 ULONG rosterindex;
176 struct wndclass_redirect_data
178 ULONG size;
179 DWORD res;
180 ULONG name_len;
181 ULONG name_offset; /* versioned name offset */
182 ULONG module_len;
183 ULONG module_offset;/* container name offset */
186 struct dllredirect_data
188 ULONG size;
189 ULONG unk;
190 DWORD res[3];
193 struct tlibredirect_data
195 ULONG size;
196 DWORD res;
197 ULONG name_len;
198 ULONG name_offset;
199 LANGID langid;
200 WORD flags;
201 ULONG help_len;
202 ULONG help_offset;
203 WORD major_version;
204 WORD minor_version;
207 enum comclass_threadingmodel
209 ThreadingModel_Apartment = 1,
210 ThreadingModel_Free = 2,
211 ThreadingModel_No = 3,
212 ThreadingModel_Both = 4,
213 ThreadingModel_Neutral = 5
216 enum comclass_miscfields
218 MiscStatus = 1,
219 MiscStatusIcon = 2,
220 MiscStatusContent = 4,
221 MiscStatusThumbnail = 8,
222 MiscStatusDocPrint = 16
225 struct comclassredirect_data
227 ULONG size;
228 BYTE res;
229 BYTE miscmask;
230 BYTE res1[2];
231 DWORD model;
232 GUID clsid;
233 GUID alias;
234 GUID clsid2;
235 GUID tlbid;
236 ULONG name_len;
237 ULONG name_offset;
238 ULONG progid_len;
239 ULONG progid_offset;
240 ULONG clrdata_len;
241 ULONG clrdata_offset;
242 DWORD miscstatus;
243 DWORD miscstatuscontent;
244 DWORD miscstatusthumbnail;
245 DWORD miscstatusicon;
246 DWORD miscstatusdocprint;
249 enum ifaceps_mask
251 NumMethods = 1,
252 BaseIface = 2
255 struct ifacepsredirect_data
257 ULONG size;
258 DWORD mask;
259 GUID iid;
260 ULONG nummethods;
261 GUID tlbid;
262 GUID base;
263 ULONG name_len;
264 ULONG name_offset;
267 struct clrsurrogate_data
269 ULONG size;
270 DWORD res;
271 GUID clsid;
272 ULONG version_offset;
273 ULONG version_len;
274 ULONG name_offset;
275 ULONG name_len;
278 struct clrclass_data
280 ULONG size;
281 DWORD res[2];
282 ULONG module_len;
283 ULONG module_offset;
284 ULONG name_len;
285 ULONG name_offset;
286 ULONG version_len;
287 ULONG version_offset;
288 DWORD res2[2];
291 struct progidredirect_data
293 ULONG size;
294 DWORD reserved;
295 ULONG clsid_offset;
300 Sections structure.
302 Sections are accessible by string or guid key, that defines two types of sections.
303 All sections of each type have same magic value and header structure, index
304 data could be of two possible types too. So every string based section uses
305 the same index format, same applies to guid sections - they share same guid index
306 format.
308 - window class redirection section is a plain buffer with following format:
310 <section header>
311 <index[]>
312 <data[]> --- <original name>
313 <redirect data>
314 <versioned name>
315 <module name>
317 Header is fixed length structure - struct strsection_header,
318 contains redirected classes count;
320 Index is an array of fixed length index records, each record is
321 struct string_index.
323 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
325 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
326 others are relative to section itself.
328 - dll redirect section format:
330 <section header>
331 <index[]>
332 <data[]> --- <dll name>
333 <data>
335 This section doesn't seem to carry any payload data except dll names.
337 - typelib section format:
339 <section header>
340 <module names[]>
341 <index[]>
342 <data[]> --- <data>
343 <helpstring>
345 Header is fixed length, index is an array of fixed length 'struct guid_index'.
346 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
347 4-bytes aligned as a whole.
349 Module name offsets are relative to section, helpstring offset is relative to data
350 structure itself.
352 - comclass section format:
354 <section header>
355 <module names[]>
356 <index[]>
357 <data[]> --- <data> --- <data>
358 <progid> <clrdata>
359 <name>
360 <version>
361 <progid>
363 This section uses two index records per comclass, one entry contains original guid
364 as specified by context, another one has a generated guid. Index and strings handling
365 is similar to typelib sections.
367 For CLR classes additional data is stored after main COM class data, it contains
368 class name and runtime version string, see 'struct clrclass_data'.
370 Module name offsets are relative to section, progid offset is relative to data
371 structure itself.
373 - COM interface section format:
375 <section header>
376 <index[]>
377 <data[]> --- <data>
378 <name>
380 Interface section contains data for proxy/stubs and external proxy/stubs. External
381 ones are defined at assembly level, so this section has no module information.
382 All records are indexed with 'iid' value from manifest. There an exception for
383 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
384 redirect data, but index is still 'iid' from manifest.
386 Interface name offset is relative to data structure itself.
388 - CLR surrogates section format:
390 <section header>
391 <index[]>
392 <data[]> --- <data>
393 <name>
394 <version>
396 There's nothing special about this section, same way to store strings is used,
397 no modules part as it belongs to assembly level, not a file.
399 - ProgID section format:
401 <section header>
402 <guids[]>
403 <index[]>
404 <data[]> --- <progid>
405 <data>
407 This sections uses generated alias guids from COM server section. This way
408 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
409 is stored too, aligned.
412 struct progids
414 WCHAR **progids;
415 unsigned int num;
416 unsigned int allocated;
419 struct entity
421 DWORD kind;
422 union
424 struct
426 WCHAR *tlbid;
427 WCHAR *helpdir;
428 WORD flags;
429 WORD major;
430 WORD minor;
431 } typelib;
432 struct
434 WCHAR *clsid;
435 WCHAR *tlbid;
436 WCHAR *progid;
437 WCHAR *name; /* clrClass: class name */
438 WCHAR *version; /* clrClass: CLR runtime version */
439 DWORD model;
440 DWORD miscstatus;
441 DWORD miscstatuscontent;
442 DWORD miscstatusthumbnail;
443 DWORD miscstatusicon;
444 DWORD miscstatusdocprint;
445 struct progids progids;
446 } comclass;
447 struct {
448 WCHAR *iid;
449 WCHAR *base;
450 WCHAR *tlib;
451 WCHAR *name;
452 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
453 DWORD mask;
454 ULONG nummethods;
455 } ifaceps;
456 struct
458 WCHAR *name;
459 BOOL versioned;
460 } class;
461 struct
463 WCHAR *name;
464 WCHAR *clsid;
465 WCHAR *version;
466 } clrsurrogate;
467 } u;
470 struct entity_array
472 struct entity *base;
473 unsigned int num;
474 unsigned int allocated;
477 struct dll_redirect
479 WCHAR *name;
480 WCHAR *hash;
481 struct entity_array entities;
484 enum assembly_type
486 APPLICATION_MANIFEST,
487 ASSEMBLY_MANIFEST,
488 ASSEMBLY_SHARED_MANIFEST,
491 struct assembly
493 enum assembly_type type;
494 struct assembly_identity id;
495 struct file_info manifest;
496 WCHAR *directory;
497 BOOL no_inherit;
498 struct dll_redirect *dlls;
499 unsigned int num_dlls;
500 unsigned int allocated_dlls;
501 struct entity_array entities;
502 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
503 ULONG num_compat_contexts;
504 ACTCTX_REQUESTED_RUN_LEVEL run_level;
505 ULONG ui_access;
508 enum context_sections
510 WINDOWCLASS_SECTION = 1,
511 DLLREDIRECT_SECTION = 2,
512 TLIBREDIRECT_SECTION = 4,
513 SERVERREDIRECT_SECTION = 8,
514 IFACEREDIRECT_SECTION = 16,
515 CLRSURROGATES_SECTION = 32,
516 PROGIDREDIRECT_SECTION = 64
519 typedef struct _ACTIVATION_CONTEXT
521 ULONG magic;
522 int ref_count;
523 struct file_info config;
524 struct file_info appdir;
525 struct assembly *assemblies;
526 unsigned int num_assemblies;
527 unsigned int allocated_assemblies;
528 /* section data */
529 DWORD sections;
530 struct strsection_header *wndclass_section;
531 struct strsection_header *dllredirect_section;
532 struct strsection_header *progid_section;
533 struct guidsection_header *tlib_section;
534 struct guidsection_header *comserver_section;
535 struct guidsection_header *ifaceps_section;
536 struct guidsection_header *clrsurrogate_section;
537 } ACTIVATION_CONTEXT;
539 struct actctx_loader
541 ACTIVATION_CONTEXT *actctx;
542 struct assembly_identity *dependencies;
543 unsigned int num_dependencies;
544 unsigned int allocated_dependencies;
547 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
548 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
549 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
550 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
551 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
552 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
553 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
554 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
555 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};
556 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};
557 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
558 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
559 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
560 static const WCHAR fileW[] = {'f','i','l','e',0};
561 static const WCHAR hashW[] = {'h','a','s','h',0};
562 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
563 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
564 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
565 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
567 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
568 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
569 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
570 static const WCHAR iidW[] = {'i','i','d',0};
571 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
572 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
573 static const WCHAR nameW[] = {'n','a','m','e',0};
574 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
575 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
576 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
577 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
578 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};
579 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
580 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
581 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
582 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
583 static const WCHAR typeW[] = {'t','y','p','e',0};
584 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
585 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
586 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
587 static const WCHAR yesW[] = {'y','e','s',0};
588 static const WCHAR noW[] = {'n','o',0};
589 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
590 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
591 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
592 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
593 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
594 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
595 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
596 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
597 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
598 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
599 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
600 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
601 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
602 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
603 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
604 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
606 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
607 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
608 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
609 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
610 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
611 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
612 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
613 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};
614 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
615 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
616 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
617 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
618 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
619 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
620 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
621 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
622 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};
623 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
624 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
625 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
626 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};
627 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
629 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
630 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};
631 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
632 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
633 static const WCHAR IdW[] = {'I','d',0};
634 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};
635 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
636 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
637 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
639 struct olemisc_entry
641 const WCHAR *name;
642 OLEMISC value;
645 static const struct olemisc_entry olemisc_values[] =
647 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
648 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
649 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
650 { alignableW, OLEMISC_ALIGNABLE },
651 { alwaysrunW, OLEMISC_ALWAYSRUN },
652 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
653 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
654 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
655 { imemodeW, OLEMISC_IMEMODE },
656 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
657 { insideoutW, OLEMISC_INSIDEOUT },
658 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
659 { islinkobjectW, OLEMISC_ISLINKOBJECT },
660 { nouiactivateW, OLEMISC_NOUIACTIVATE },
661 { onlyiconicW, OLEMISC_ONLYICONIC },
662 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
663 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
664 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
665 { simpleframeW, OLEMISC_SIMPLEFRAME },
666 { staticW, OLEMISC_STATIC },
667 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
668 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
671 static const WCHAR xmlW[] = {'?','x','m','l',0};
672 static const WCHAR manifestv1W[] = {'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};
673 static const WCHAR manifestv2W[] = {'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};
674 static const WCHAR manifestv3W[] = {'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};
676 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
677 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
678 static const WCHAR wildcardW[] = {'*',0};
680 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
681 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
683 static WCHAR *strdupW(const WCHAR* str)
685 WCHAR* ptr;
687 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
688 return NULL;
689 return strcpyW(ptr, str);
692 static WCHAR *xmlstrdupW(const xmlstr_t* str)
694 WCHAR *strW;
696 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
698 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
699 strW[str->len] = 0;
701 return strW;
704 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
706 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
709 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
711 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
714 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
716 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
717 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
720 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
722 UINT len = strlenW( namespace );
724 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
725 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
726 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
729 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
731 if (elem->len && elem->ptr[0] == '/')
733 xmlstr_t elem_end;
734 elem_end.ptr = elem->ptr + 1;
735 elem_end.len = elem->len - 1;
736 return xml_elem_cmp( &elem_end, str, namespace );
738 return FALSE;
741 static inline BOOL isxmlspace( WCHAR ch )
743 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
746 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
748 return debugstr_wn(str->ptr, str->len);
751 static inline const char* debugstr_version(const struct assembly_version *ver)
753 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
756 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
758 struct assembly *assembly;
760 if (actctx->num_assemblies == actctx->allocated_assemblies)
762 void *ptr;
763 unsigned int new_count;
764 if (actctx->assemblies)
766 new_count = actctx->allocated_assemblies * 2;
767 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
768 actctx->assemblies, new_count * sizeof(*assembly) );
770 else
772 new_count = 4;
773 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
775 if (!ptr) return NULL;
776 actctx->assemblies = ptr;
777 actctx->allocated_assemblies = new_count;
780 assembly = &actctx->assemblies[actctx->num_assemblies++];
781 assembly->type = at;
782 return assembly;
785 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
787 if (assembly->num_dlls == assembly->allocated_dlls)
789 void *ptr;
790 unsigned int new_count;
791 if (assembly->dlls)
793 new_count = assembly->allocated_dlls * 2;
794 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
795 assembly->dlls, new_count * sizeof(*assembly->dlls) );
797 else
799 new_count = 4;
800 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
802 if (!ptr) return NULL;
803 assembly->dlls = ptr;
804 assembly->allocated_dlls = new_count;
806 return &assembly->dlls[assembly->num_dlls++];
809 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
811 void *ptr;
812 if (assembly->num_compat_contexts)
814 unsigned int new_count = assembly->num_compat_contexts + 1;
815 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
816 assembly->compat_contexts,
817 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
819 else
821 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
823 if (!ptr) return NULL;
824 assembly->compat_contexts = ptr;
825 return &assembly->compat_contexts[assembly->num_compat_contexts++];
828 static void free_assembly_identity(struct assembly_identity *ai)
830 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
831 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
832 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
833 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
834 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
837 static struct entity* add_entity(struct entity_array *array, DWORD kind)
839 struct entity* entity;
841 if (array->num == array->allocated)
843 void *ptr;
844 unsigned int new_count;
845 if (array->base)
847 new_count = array->allocated * 2;
848 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
849 array->base, new_count * sizeof(*array->base) );
851 else
853 new_count = 4;
854 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
856 if (!ptr) return NULL;
857 array->base = ptr;
858 array->allocated = new_count;
860 entity = &array->base[array->num++];
861 entity->kind = kind;
862 return entity;
865 static void free_entity_array(struct entity_array *array)
867 unsigned int i, j;
868 for (i = 0; i < array->num; i++)
870 struct entity *entity = &array->base[i];
871 switch (entity->kind)
873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
874 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
875 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
876 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
877 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
878 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
879 for (j = 0; j < entity->u.comclass.progids.num; j++)
880 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
881 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
882 break;
883 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
884 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
885 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
886 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
887 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
888 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
889 break;
890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
891 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
892 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
893 break;
894 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
895 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
896 break;
897 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
898 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
899 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
900 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
901 break;
902 default:
903 FIXME("Unknown entity kind %d\n", entity->kind);
906 RtlFreeHeap( GetProcessHeap(), 0, array->base );
909 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
911 if (!str1) return !str2;
912 return str2 && !strcmpiW( str1, str2 );
915 static BOOL is_matching_identity( const struct assembly_identity *id1,
916 const struct assembly_identity *id2 )
918 if (!is_matching_string( id1->name, id2->name )) return FALSE;
919 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
920 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
922 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
924 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
925 return FALSE;
927 if (id1->version.major != id2->version.major) return FALSE;
928 if (id1->version.minor != id2->version.minor) return FALSE;
929 if (id1->version.build > id2->version.build) return FALSE;
930 if (id1->version.build == id2->version.build &&
931 id1->version.revision > id2->version.revision) return FALSE;
932 return TRUE;
935 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
936 struct assembly_identity* ai)
938 unsigned int i;
940 /* check if we already have that assembly */
942 for (i = 0; i < acl->actctx->num_assemblies; i++)
943 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
945 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
946 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
947 ai->version.build, ai->version.revision );
948 return TRUE;
951 for (i = 0; i < acl->num_dependencies; i++)
952 if (is_matching_identity( ai, &acl->dependencies[i] ))
954 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
955 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
956 ai->version.build, ai->version.revision );
957 return TRUE;
960 if (acl->num_dependencies == acl->allocated_dependencies)
962 void *ptr;
963 unsigned int new_count;
964 if (acl->dependencies)
966 new_count = acl->allocated_dependencies * 2;
967 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
968 new_count * sizeof(acl->dependencies[0]));
970 else
972 new_count = 4;
973 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
975 if (!ptr) return FALSE;
976 acl->dependencies = ptr;
977 acl->allocated_dependencies = new_count;
979 acl->dependencies[acl->num_dependencies++] = *ai;
981 return TRUE;
984 static void free_depend_manifests(struct actctx_loader* acl)
986 unsigned int i;
987 for (i = 0; i < acl->num_dependencies; i++)
988 free_assembly_identity(&acl->dependencies[i]);
989 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
992 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
994 static const WCHAR undW[] = {'_',0};
995 static const WCHAR noneW[] = {'n','o','n','e',0};
996 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
998 const WCHAR *arch = ai->arch ? ai->arch : noneW;
999 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1000 const WCHAR *lang = ai->language ? ai->language : noneW;
1001 const WCHAR *name = ai->name ? ai->name : noneW;
1002 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1003 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1004 WCHAR *ret;
1006 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1008 strcpyW( ret, arch );
1009 strcatW( ret, undW );
1010 strcatW( ret, name );
1011 strcatW( ret, undW );
1012 strcatW( ret, key );
1013 strcatW( ret, undW );
1014 sprintfW( ret + strlenW(ret), version_formatW,
1015 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1016 strcatW( ret, undW );
1017 strcatW( ret, lang );
1018 strcatW( ret, undW );
1019 strcatW( ret, mskeyW );
1020 return ret;
1023 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1025 WCHAR *p = buffer;
1027 if (!str) return;
1028 strcatW( buffer, prefix );
1029 p += strlenW(p);
1030 *p++ = '"';
1031 strcpyW( p, str );
1032 p += strlenW(p);
1033 *p++ = '"';
1034 *p = 0;
1037 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1039 static const WCHAR archW[] =
1040 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1041 static const WCHAR public_keyW[] =
1042 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1043 static const WCHAR typeW[] =
1044 {',','t','y','p','e','=',0};
1045 static const WCHAR versionW[] =
1046 {',','v','e','r','s','i','o','n','=',0};
1048 WCHAR version[64], *ret;
1049 SIZE_T size = 0;
1051 sprintfW( version, version_formatW,
1052 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1053 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1054 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1055 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1056 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1057 size += strlenW(versionW) + strlenW(version) + 2;
1059 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1060 return NULL;
1062 if (ai->name) strcpyW( ret, ai->name );
1063 else *ret = 0;
1064 append_string( ret, archW, ai->arch );
1065 append_string( ret, public_keyW, ai->public_key );
1066 append_string( ret, typeW, ai->type );
1067 append_string( ret, versionW, version );
1068 return ret;
1071 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1073 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1075 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1076 __TRY
1078 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1080 __EXCEPT_PAGE_FAULT
1083 __ENDTRY
1084 return ret;
1087 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1089 interlocked_xchg_add( &actctx->ref_count, 1 );
1092 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1094 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1096 unsigned int i, j;
1098 for (i = 0; i < actctx->num_assemblies; i++)
1100 struct assembly *assembly = &actctx->assemblies[i];
1101 for (j = 0; j < assembly->num_dlls; j++)
1103 struct dll_redirect *dll = &assembly->dlls[j];
1104 free_entity_array( &dll->entities );
1105 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1106 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1108 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1109 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1110 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1111 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1112 free_entity_array( &assembly->entities );
1113 free_assembly_identity(&assembly->id);
1115 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1116 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1117 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1118 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1119 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1120 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1121 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1125 actctx->magic = 0;
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1130 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1131 BOOL* error, BOOL* end)
1133 const WCHAR* ptr;
1135 *error = TRUE;
1137 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1138 xmlbuf->ptr++;
1140 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1142 if (*xmlbuf->ptr == '/')
1144 xmlbuf->ptr++;
1145 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1146 return FALSE;
1148 xmlbuf->ptr++;
1149 *end = TRUE;
1150 *error = FALSE;
1151 return FALSE;
1154 if (*xmlbuf->ptr == '>')
1156 xmlbuf->ptr++;
1157 *error = FALSE;
1158 return FALSE;
1161 ptr = xmlbuf->ptr;
1162 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1164 if (ptr == xmlbuf->end) return FALSE;
1166 name->ptr = xmlbuf->ptr;
1167 name->len = ptr-xmlbuf->ptr;
1168 xmlbuf->ptr = ptr;
1170 /* skip spaces before '=' */
1171 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1172 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1174 /* skip '=' itself */
1175 ptr++;
1176 if (ptr == xmlbuf->end) return FALSE;
1178 /* skip spaces after '=' */
1179 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1181 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1183 value->ptr = ++ptr;
1184 if (ptr == xmlbuf->end) return FALSE;
1186 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1187 if (!ptr)
1189 xmlbuf->ptr = xmlbuf->end;
1190 return FALSE;
1193 value->len = ptr - value->ptr;
1194 xmlbuf->ptr = ptr + 1;
1196 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1198 *error = FALSE;
1199 return TRUE;
1202 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1204 const WCHAR* ptr;
1206 for (;;)
1208 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1209 if (!ptr)
1211 xmlbuf->ptr = xmlbuf->end;
1212 return FALSE;
1214 ptr++;
1215 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1217 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1218 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1220 if (ptr + 3 > xmlbuf->end)
1222 xmlbuf->ptr = xmlbuf->end;
1223 return FALSE;
1225 xmlbuf->ptr = ptr + 3;
1227 else break;
1230 xmlbuf->ptr = ptr;
1231 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1232 ptr++;
1234 elem->ptr = xmlbuf->ptr;
1235 elem->len = ptr - xmlbuf->ptr;
1236 xmlbuf->ptr = ptr;
1237 return xmlbuf->ptr != xmlbuf->end;
1240 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1242 /* FIXME: parse attributes */
1243 const WCHAR *ptr;
1245 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1247 if (ptr[0] == '?' && ptr[1] == '>')
1249 xmlbuf->ptr = ptr + 2;
1250 return TRUE;
1253 return FALSE;
1256 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1258 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1260 if (!ptr) return FALSE;
1262 content->ptr = xmlbuf->ptr;
1263 content->len = ptr - xmlbuf->ptr;
1264 xmlbuf->ptr = ptr;
1266 return TRUE;
1269 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1271 unsigned int ver[4];
1272 unsigned int pos;
1273 const WCHAR *curr;
1275 /* major.minor.build.revision */
1276 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1277 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1279 if (*curr >= '0' && *curr <= '9')
1281 ver[pos] = ver[pos] * 10 + *curr - '0';
1282 if (ver[pos] >= 0x10000) goto error;
1284 else if (*curr == '.')
1286 if (++pos >= 4) goto error;
1288 else goto error;
1290 version->major = ver[0];
1291 version->minor = ver[1];
1292 version->build = ver[2];
1293 version->revision = ver[3];
1294 return TRUE;
1296 error:
1297 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1298 return FALSE;
1301 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1303 xmlstr_t elem;
1304 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1305 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1306 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1307 return FALSE;
1310 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1312 xmlstr_t attr_name, attr_value;
1313 BOOL error;
1315 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1317 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1318 debugstr_xmlstr(&attr_value));
1320 return !error;
1323 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1325 BOOL end = FALSE;
1326 return parse_expect_no_attr(xmlbuf, &end) && !end;
1329 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1331 xmlstr_t elem;
1332 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1333 if (!xml_elem_cmp_end(&elem, name, namespace))
1335 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1336 return FALSE;
1338 return parse_end_element(xmlbuf);
1341 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1343 xmlstr_t attr_name, attr_value, elem;
1344 BOOL end = FALSE, error, ret = TRUE;
1346 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1347 if(error || end) return end;
1349 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1351 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1352 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1353 break;
1354 else
1355 ret = parse_unknown_elem(xmlbuf, &elem);
1358 return ret && parse_end_element(xmlbuf);
1361 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1362 struct assembly_identity* ai)
1364 xmlstr_t attr_name, attr_value;
1365 BOOL end = FALSE, error;
1367 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1369 if (xmlstr_cmp(&attr_name, nameW))
1371 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1373 else if (xmlstr_cmp(&attr_name, typeW))
1375 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1377 else if (xmlstr_cmp(&attr_name, versionW))
1379 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1381 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1383 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1385 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1387 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1389 else if (xmlstr_cmp(&attr_name, languageW))
1391 WARN("Unsupported yet language attribute (%s)\n",
1392 debugstr_xmlstr(&attr_value));
1393 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1395 else
1397 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1398 debugstr_xmlstr(&attr_value));
1402 TRACE( "name=%s version=%s arch=%s\n",
1403 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1405 if (error || end) return end;
1406 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1409 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1411 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1412 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1413 static const WCHAR freeW[] = {'F','r','e','e',0};
1414 static const WCHAR bothW[] = {'B','o','t','h',0};
1416 if (value->len == 0) return ThreadingModel_No;
1417 if (xmlstr_cmp(value, apartW))
1418 return ThreadingModel_Apartment;
1419 else if (xmlstr_cmp(value, freeW))
1420 return ThreadingModel_Free;
1421 else if (xmlstr_cmp(value, bothW))
1422 return ThreadingModel_Both;
1423 else if (xmlstr_cmp(value, neutralW))
1424 return ThreadingModel_Neutral;
1425 else
1426 return ThreadingModel_No;
1429 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1431 int min, max;
1433 min = 0;
1434 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1436 while (min <= max)
1438 int n, c;
1440 n = (min+max)/2;
1442 c = strncmpW(olemisc_values[n].name, str, len);
1443 if (!c && !olemisc_values[n].name[len])
1444 return olemisc_values[n].value;
1446 if (c >= 0)
1447 max = n-1;
1448 else
1449 min = n+1;
1452 WARN("unknown flag %s\n", debugstr_wn(str, len));
1453 return 0;
1456 static DWORD parse_com_class_misc(const xmlstr_t *value)
1458 const WCHAR *str = value->ptr, *start;
1459 DWORD flags = 0;
1460 int i = 0;
1462 /* it's comma separated list of flags */
1463 while (i < value->len)
1465 start = str;
1466 while (*str != ',' && (i++ < value->len)) str++;
1468 flags |= get_olemisc_value(start, str-start);
1470 /* skip separator */
1471 str++;
1472 i++;
1475 return flags;
1478 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1480 struct progids *progids = &entity->u.comclass.progids;
1482 if (progids->allocated == 0)
1484 progids->allocated = 4;
1485 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1488 if (progids->allocated == progids->num)
1490 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1491 2 * progids->allocated * sizeof(WCHAR*));
1492 if (!new_progids) return FALSE;
1493 progids->allocated *= 2;
1494 progids->progids = new_progids;
1497 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1498 progids->num++;
1500 return TRUE;
1503 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1505 xmlstr_t content;
1506 BOOL end = FALSE;
1508 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1509 return FALSE;
1511 if (!com_class_add_progid(&content, entity)) return FALSE;
1512 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1515 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1517 xmlstr_t elem, attr_name, attr_value;
1518 BOOL ret = TRUE, end = FALSE, error;
1519 struct entity* entity;
1521 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1522 return FALSE;
1524 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1526 if (xmlstr_cmp(&attr_name, clsidW))
1528 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1530 else if (xmlstr_cmp(&attr_name, progidW))
1532 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1534 else if (xmlstr_cmp(&attr_name, tlbidW))
1536 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1538 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1540 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1542 else if (xmlstr_cmp(&attr_name, miscstatusW))
1544 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1546 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1548 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1550 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1552 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1554 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1556 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1558 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1560 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1562 else if (xmlstr_cmp(&attr_name, descriptionW))
1564 /* not stored */
1566 else
1568 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1572 if (error) return FALSE;
1574 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1575 if (entity->u.comclass.progid)
1576 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1578 if (end) return TRUE;
1580 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1582 if (xmlstr_cmp_end(&elem, comClassW))
1584 ret = parse_end_element(xmlbuf);
1585 break;
1587 else if (xmlstr_cmp(&elem, progidW))
1589 ret = parse_com_class_progid(xmlbuf, entity);
1591 else
1593 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1594 ret = parse_unknown_elem(xmlbuf, &elem);
1598 if (entity->u.comclass.progids.num)
1599 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1601 return ret;
1604 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1606 const WCHAR *curr;
1607 ULONG num = 0;
1609 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1611 if (*curr >= '0' && *curr <= '9')
1612 num = num * 10 + *curr - '0';
1613 else
1615 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1616 return FALSE;
1619 entity->u.ifaceps.nummethods = num;
1621 return TRUE;
1624 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1626 xmlstr_t attr_name, attr_value;
1627 BOOL end = FALSE, error;
1628 struct entity* entity;
1630 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1631 return FALSE;
1633 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1635 if (xmlstr_cmp(&attr_name, iidW))
1637 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1639 else if (xmlstr_cmp(&attr_name, nameW))
1641 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1643 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1645 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1646 entity->u.ifaceps.mask |= BaseIface;
1648 else if (xmlstr_cmp(&attr_name, nummethodsW))
1650 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1651 entity->u.ifaceps.mask |= NumMethods;
1653 else if (xmlstr_cmp(&attr_name, tlbidW))
1655 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1657 /* not used */
1658 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1661 else
1663 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1667 if (error) return FALSE;
1668 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1669 if (end) return TRUE;
1671 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1674 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1676 WORD *flags = &entity->u.typelib.flags;
1677 const WCHAR *str = value->ptr, *start;
1678 int i = 0;
1680 *flags = 0;
1682 /* it's comma separated list of flags */
1683 while (i < value->len)
1685 start = str;
1686 while (*str != ',' && (i++ < value->len)) str++;
1688 if (!strncmpiW(start, restrictedW, str-start))
1689 *flags |= LIBFLAG_FRESTRICTED;
1690 else if (!strncmpiW(start, controlW, str-start))
1691 *flags |= LIBFLAG_FCONTROL;
1692 else if (!strncmpiW(start, hiddenW, str-start))
1693 *flags |= LIBFLAG_FHIDDEN;
1694 else if (!strncmpiW(start, hasdiskimageW, str-start))
1695 *flags |= LIBFLAG_FHASDISKIMAGE;
1696 else
1698 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1699 return FALSE;
1702 /* skip separator */
1703 str++;
1704 i++;
1707 return TRUE;
1710 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1712 unsigned int ver[2];
1713 unsigned int pos;
1714 const WCHAR *curr;
1716 /* major.minor */
1717 ver[0] = ver[1] = pos = 0;
1718 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1720 if (*curr >= '0' && *curr <= '9')
1722 ver[pos] = ver[pos] * 10 + *curr - '0';
1723 if (ver[pos] >= 0x10000) goto error;
1725 else if (*curr == '.')
1727 if (++pos >= 2) goto error;
1729 else goto error;
1731 entity->u.typelib.major = ver[0];
1732 entity->u.typelib.minor = ver[1];
1733 return TRUE;
1735 error:
1736 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1737 return FALSE;
1740 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1742 xmlstr_t attr_name, attr_value;
1743 BOOL end = FALSE, error;
1744 struct entity* entity;
1746 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1747 return FALSE;
1749 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1751 if (xmlstr_cmp(&attr_name, tlbidW))
1753 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1755 else if (xmlstr_cmp(&attr_name, versionW))
1757 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1759 else if (xmlstr_cmp(&attr_name, helpdirW))
1761 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1763 else if (xmlstr_cmp(&attr_name, flagsW))
1765 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1767 else
1769 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1773 if (error) return FALSE;
1775 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1777 if (end) return TRUE;
1779 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1782 static inline int aligned_string_len(int len)
1784 return (len + 3) & ~3;
1787 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1789 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1790 struct assembly_version *ver = &assembly->id.version;
1791 WCHAR buff[25];
1793 if (!ret) ret = buff;
1794 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1797 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1799 xmlstr_t elem, content, attr_name, attr_value;
1800 BOOL end = FALSE, ret = TRUE, error;
1801 struct entity* entity;
1803 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1804 return FALSE;
1806 entity->u.class.versioned = TRUE;
1807 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1809 if (xmlstr_cmp(&attr_name, versionedW))
1811 if (xmlstr_cmpi(&attr_value, noW))
1812 entity->u.class.versioned = FALSE;
1813 else if (!xmlstr_cmpi(&attr_value, yesW))
1814 return FALSE;
1816 else
1818 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1822 if (error || end) return end;
1824 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1826 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1828 acl->actctx->sections |= WINDOWCLASS_SECTION;
1830 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1832 if (xmlstr_cmp_end(&elem, windowClassW))
1834 ret = parse_end_element(xmlbuf);
1835 break;
1837 else
1839 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1840 ret = parse_unknown_elem(xmlbuf, &elem);
1844 return ret;
1847 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1849 xmlstr_t attr_name, attr_value;
1850 BOOL end = FALSE, error;
1852 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1854 if (xmlstr_cmp(&attr_name, oldVersionW))
1856 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1858 else if (xmlstr_cmp(&attr_name, newVersionW))
1860 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1862 else
1864 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1868 if (error || end) return end;
1869 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1872 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1874 xmlstr_t elem, content, attr_name, attr_value;
1875 BOOL end = FALSE, ret = TRUE, error = FALSE;
1877 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1878 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1880 if (error) return FALSE;
1881 if (end) return TRUE;
1883 if (!parse_text_content(xmlbuf, &content))
1884 return FALSE;
1886 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1888 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1890 if (xmlstr_cmp_end(&elem, descriptionW))
1892 ret = parse_end_element(xmlbuf);
1893 break;
1895 else
1897 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1898 ret = parse_unknown_elem(xmlbuf, &elem);
1902 return ret;
1905 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1906 struct assembly* assembly,
1907 struct actctx_loader* acl)
1909 xmlstr_t attr_name, attr_value;
1910 BOOL end = FALSE, error;
1911 struct entity* entity;
1913 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1914 if (!entity) return FALSE;
1916 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1918 if (xmlstr_cmp(&attr_name, iidW))
1920 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1922 else if (xmlstr_cmp(&attr_name, nameW))
1924 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1926 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1928 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1929 entity->u.ifaceps.mask |= BaseIface;
1931 else if (xmlstr_cmp(&attr_name, nummethodsW))
1933 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1934 entity->u.ifaceps.mask |= NumMethods;
1936 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1938 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1940 else if (xmlstr_cmp(&attr_name, tlbidW))
1942 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1944 else
1946 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1950 if (error) return FALSE;
1951 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1952 if (end) return TRUE;
1954 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1957 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1959 xmlstr_t attr_name, attr_value, elem;
1960 BOOL end = FALSE, error, ret = TRUE;
1961 struct entity* entity;
1963 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1964 if (!entity) return FALSE;
1966 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1968 if (xmlstr_cmp(&attr_name, nameW))
1970 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1972 else if (xmlstr_cmp(&attr_name, clsidW))
1974 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1976 else if (xmlstr_cmp(&attr_name, progidW))
1978 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1980 else if (xmlstr_cmp(&attr_name, tlbidW))
1982 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1984 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1986 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1988 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1990 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1992 else
1994 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1998 if (error) return FALSE;
1999 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2000 if (entity->u.comclass.progid)
2001 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2002 if (end) return TRUE;
2004 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2006 if (xmlstr_cmp_end(&elem, clrClassW))
2008 ret = parse_end_element(xmlbuf);
2009 break;
2011 else if (xmlstr_cmp(&elem, progidW))
2013 ret = parse_com_class_progid(xmlbuf, entity);
2015 else
2017 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2018 ret = parse_unknown_elem(xmlbuf, &elem);
2022 if (entity->u.comclass.progids.num)
2023 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2025 return ret;
2028 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2030 xmlstr_t attr_name, attr_value;
2031 BOOL end = FALSE, error;
2032 struct entity* entity;
2034 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2035 if (!entity) return FALSE;
2037 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2039 if (xmlstr_cmp(&attr_name, nameW))
2041 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2043 else if (xmlstr_cmp(&attr_name, clsidW))
2045 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2047 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2049 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2051 else
2053 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2057 if (error) return FALSE;
2058 acl->actctx->sections |= CLRSURROGATES_SECTION;
2059 if (end) return TRUE;
2061 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2064 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2066 struct assembly_identity ai;
2067 xmlstr_t elem, attr_name, attr_value;
2068 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2070 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2072 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2073 static const WCHAR trueW[] = {'t','r','u','e',0};
2075 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2076 delayed = xmlstr_cmp(&attr_value, trueW);
2077 else
2078 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2081 if (error || end) return end;
2083 memset(&ai, 0, sizeof(ai));
2084 ai.optional = optional;
2085 ai.delayed = delayed;
2087 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2088 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2089 return FALSE;
2091 TRACE( "adding name=%s version=%s arch=%s\n",
2092 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2094 /* store the newly found identity for later loading */
2095 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2097 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2099 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2101 ret = parse_end_element(xmlbuf);
2102 break;
2104 else if (xmlstr_cmp(&elem, bindingRedirectW))
2106 ret = parse_binding_redirect_elem(xmlbuf);
2108 else
2110 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2111 ret = parse_unknown_elem(xmlbuf, &elem);
2115 return ret;
2118 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2120 xmlstr_t attr_name, attr_value, elem;
2121 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2123 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2125 if (xmlstr_cmp(&attr_name, optionalW))
2127 optional = xmlstr_cmpi( &attr_value, yesW );
2128 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2130 else
2132 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2136 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2138 if (xmlstr_cmp_end(&elem, dependencyW))
2140 ret = parse_end_element(xmlbuf);
2141 break;
2143 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2145 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2147 else
2149 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2150 ret = parse_unknown_elem(xmlbuf, &elem);
2154 return ret;
2157 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2159 BOOL end = FALSE;
2161 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2162 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2165 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2167 BOOL end = FALSE;
2169 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2170 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2173 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2175 xmlstr_t attr_name, attr_value, elem;
2176 BOOL end = FALSE, error, ret = TRUE;
2177 struct dll_redirect* dll;
2179 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2181 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2183 if (xmlstr_cmp(&attr_name, nameW))
2185 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2186 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2188 else if (xmlstr_cmp(&attr_name, hashW))
2190 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2192 else if (xmlstr_cmp(&attr_name, hashalgW))
2194 static const WCHAR sha1W[] = {'S','H','A','1',0};
2195 if (!xmlstr_cmpi(&attr_value, sha1W))
2196 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2198 else
2200 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2204 if (error || !dll->name) return FALSE;
2206 acl->actctx->sections |= DLLREDIRECT_SECTION;
2208 if (end) return TRUE;
2210 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2212 if (xmlstr_cmp_end(&elem, fileW))
2214 ret = parse_end_element(xmlbuf);
2215 break;
2217 else if (xmlstr_cmp(&elem, comClassW))
2219 ret = parse_com_class_elem(xmlbuf, dll, acl);
2221 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2223 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2225 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2227 WARN("asmv2:hash (undocumented) not supported\n");
2228 ret = parse_unknown_elem(xmlbuf, &elem);
2230 else if (xmlstr_cmp(&elem, typelibW))
2232 ret = parse_typelib_elem(xmlbuf, dll, acl);
2234 else if (xmlstr_cmp(&elem, windowClassW))
2236 ret = parse_window_class_elem(xmlbuf, dll, acl);
2238 else
2240 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2241 ret = parse_unknown_elem( xmlbuf, &elem );
2245 return ret;
2248 static BOOL parse_compatibility_application_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2249 struct actctx_loader* acl)
2251 xmlstr_t attr_name, attr_value, elem;
2252 BOOL end = FALSE, ret = TRUE, error;
2254 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2256 if (xmlstr_cmp_end(&elem, applicationW))
2258 ret = parse_end_element(xmlbuf);
2259 break;
2261 else if (xmlstr_cmp(&elem, supportedOSW))
2263 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2265 if (xmlstr_cmp(&attr_name, IdW))
2267 UNICODE_STRING str;
2268 COMPATIBILITY_CONTEXT_ELEMENT* compat;
2269 GUID compat_id;
2270 str.Buffer = (PWSTR)attr_value.ptr;
2271 str.Length = str.MaximumLength = (USHORT)attr_value.len * sizeof(WCHAR);
2272 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2274 if (!(compat = add_compat_context(assembly))) return FALSE;
2275 compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2276 compat->Id = compat_id;
2278 else
2280 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value));
2283 else
2285 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
2286 debugstr_xmlstr(&attr_value));
2290 else
2292 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2293 ret = parse_unknown_elem(xmlbuf, &elem);
2297 return ret;
2300 static BOOL parse_compatibility_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2301 struct actctx_loader* acl)
2303 xmlstr_t elem;
2304 BOOL ret = TRUE;
2306 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2308 if (xmlstr_cmp_end(&elem, compatibilityW))
2310 ret = parse_end_element(xmlbuf);
2311 break;
2313 else if (xmlstr_cmp(&elem, applicationW))
2315 ret = parse_compatibility_application_elem(xmlbuf, assembly, acl);
2317 else
2319 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2320 ret = parse_unknown_elem(xmlbuf, &elem);
2323 return ret;
2326 static BOOL parse_requested_execution_level_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2328 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2329 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2330 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};
2331 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2332 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2333 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2334 static const WCHAR trueW[] = {'t','r','u','e',0};
2336 xmlstr_t attr_name, attr_value, elem;
2337 BOOL end = FALSE, ret = TRUE, error;
2339 /* Multiple requestedExecutionLevel elements are not supported. */
2340 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED)
2341 return FALSE;
2343 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2345 if (xmlstr_cmp(&attr_name, levelW))
2347 if (xmlstr_cmpi(&attr_value, asInvokerW))
2348 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2349 else if (xmlstr_cmpi(&attr_value, highestAvailableW))
2350 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2351 else if (xmlstr_cmpi(&attr_value, requireAdministratorW))
2352 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2353 else
2354 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr_value));
2356 else if (xmlstr_cmp(&attr_name, uiAccessW))
2358 if (xmlstr_cmpi(&attr_value, falseW))
2359 assembly->ui_access = FALSE;
2360 else if (xmlstr_cmpi(&attr_value, trueW))
2361 assembly->ui_access = TRUE;
2362 else
2363 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr_value));
2365 else
2366 FIXME("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2369 if (error) return FALSE;
2370 if (end) return TRUE;
2372 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2374 if (xmlstr_cmp_end(&elem, requestedExecutionLevelW))
2376 ret = parse_end_element(xmlbuf);
2377 break;
2379 else
2381 FIXME("unknown element %s\n", debugstr_xmlstr(&elem));
2382 ret = parse_unknown_elem(xmlbuf, &elem);
2386 return ret;
2389 static BOOL parse_requested_privileges_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2391 xmlstr_t elem;
2392 BOOL ret = TRUE;
2394 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2396 if (xmlstr_cmp_end(&elem, requestedPrivilegesW))
2398 ret = parse_end_element(xmlbuf);
2399 break;
2401 else if (xmlstr_cmp(&elem, requestedExecutionLevelW))
2402 ret = parse_requested_execution_level_elem(xmlbuf, assembly, acl);
2403 else
2405 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2406 ret = parse_unknown_elem(xmlbuf, &elem);
2410 return ret;
2413 static BOOL parse_security_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2415 xmlstr_t elem;
2416 BOOL ret = TRUE;
2418 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2420 if (xmlstr_cmp_end(&elem, securityW))
2422 ret = parse_end_element(xmlbuf);
2423 break;
2425 else if (xmlstr_cmp(&elem, requestedPrivilegesW))
2426 ret = parse_requested_privileges_elem(xmlbuf, assembly, acl);
2427 else
2429 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2430 ret = parse_unknown_elem(xmlbuf, &elem);
2434 return ret;
2437 static BOOL parse_trust_info_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2439 xmlstr_t elem;
2440 BOOL ret = TRUE;
2442 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2444 if (xmlstr_cmp_end(&elem, trustInfoW))
2446 ret = parse_end_element(xmlbuf);
2447 break;
2449 else if (xmlstr_cmp(&elem, securityW))
2450 ret = parse_security_elem(xmlbuf, assembly, acl);
2451 else
2453 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2454 ret = parse_unknown_elem(xmlbuf, &elem);
2458 return ret;
2461 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2462 struct assembly* assembly,
2463 struct assembly_identity* expected_ai)
2465 xmlstr_t attr_name, attr_value, elem;
2466 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2468 TRACE("(%p)\n", xmlbuf);
2470 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2472 if (xmlstr_cmp(&attr_name, manifestVersionW))
2474 static const WCHAR v10W[] = {'1','.','0',0};
2475 if (!xmlstr_cmp(&attr_value, v10W))
2477 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2478 return FALSE;
2480 version = TRUE;
2482 else if (xmlstr_cmp(&attr_name, xmlnsW))
2484 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2485 !xmlstr_cmp(&attr_value, manifestv2W) &&
2486 !xmlstr_cmp(&attr_value, manifestv3W))
2488 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2489 return FALSE;
2491 xmlns = TRUE;
2493 else
2495 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2499 if (error || end || !xmlns || !version) return FALSE;
2500 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2502 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2504 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2505 return FALSE;
2506 assembly->no_inherit = TRUE;
2509 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2511 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2512 return FALSE;
2514 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2515 assembly->no_inherit)
2516 return FALSE;
2518 while (ret)
2520 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2522 ret = parse_end_element(xmlbuf);
2523 break;
2525 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2527 ret = parse_description_elem(xmlbuf);
2529 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2531 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2533 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2535 ret = parse_dependency_elem(xmlbuf, acl);
2537 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2539 ret = parse_file_elem(xmlbuf, assembly, acl);
2541 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2543 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2545 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2547 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2549 else if (xml_elem_cmp(&elem, trustInfoW, asmv2W) ||
2550 xml_elem_cmp(&elem, trustInfoW, asmv1W))
2552 ret = parse_trust_info_elem(xmlbuf, assembly, acl);
2554 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2556 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2558 if (expected_ai)
2560 /* FIXME: more tests */
2561 if (assembly->type == ASSEMBLY_MANIFEST &&
2562 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2564 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2565 expected_ai->version.major, expected_ai->version.minor,
2566 expected_ai->version.build, expected_ai->version.revision,
2567 assembly->id.version.major, assembly->id.version.minor,
2568 assembly->id.version.build, assembly->id.version.revision);
2569 ret = FALSE;
2571 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2572 (assembly->id.version.major != expected_ai->version.major ||
2573 assembly->id.version.minor != expected_ai->version.minor ||
2574 assembly->id.version.build < expected_ai->version.build ||
2575 (assembly->id.version.build == expected_ai->version.build &&
2576 assembly->id.version.revision < expected_ai->version.revision)))
2578 FIXME("wrong version for shared assembly manifest\n");
2579 ret = FALSE;
2583 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2585 ret = parse_compatibility_elem(xmlbuf, assembly, acl);
2587 else
2589 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2590 ret = parse_unknown_elem(xmlbuf, &elem);
2592 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2595 return ret;
2598 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2599 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2601 xmlstr_t elem;
2603 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2605 if (xmlstr_cmp(&elem, xmlW) &&
2606 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2607 return STATUS_SXS_CANT_GEN_ACTCTX;
2609 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2611 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2612 return STATUS_SXS_CANT_GEN_ACTCTX;
2615 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2617 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2618 return STATUS_SXS_CANT_GEN_ACTCTX;
2621 if (next_xml_elem(xmlbuf, &elem))
2623 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2624 return STATUS_SXS_CANT_GEN_ACTCTX;
2627 if (xmlbuf->ptr != xmlbuf->end)
2629 FIXME("parse error\n");
2630 return STATUS_SXS_CANT_GEN_ACTCTX;
2632 return STATUS_SUCCESS;
2635 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2636 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2637 const void *buffer, SIZE_T size )
2639 xmlbuf_t xmlbuf;
2640 NTSTATUS status;
2641 struct assembly *assembly;
2642 int unicode_tests;
2644 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2646 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2647 return STATUS_SXS_CANT_GEN_ACTCTX;
2649 if (directory && !(assembly->directory = strdupW(directory)))
2650 return STATUS_NO_MEMORY;
2652 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2653 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2654 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2656 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2657 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2659 xmlbuf.ptr = buffer;
2660 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2661 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2663 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2665 const WCHAR *buf = buffer;
2666 WCHAR *new_buff;
2667 unsigned int i;
2669 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2670 return STATUS_NO_MEMORY;
2671 for (i = 0; i < size / sizeof(WCHAR); i++)
2672 new_buff[i] = RtlUshortByteSwap( buf[i] );
2673 xmlbuf.ptr = new_buff;
2674 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2675 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2676 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2678 else
2680 /* let's assume utf-8 for now */
2681 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2682 WCHAR *new_buff;
2684 if (len == -1)
2686 FIXME( "utf-8 conversion failed\n" );
2687 return STATUS_SXS_CANT_GEN_ACTCTX;
2689 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2690 return STATUS_NO_MEMORY;
2691 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2692 xmlbuf.ptr = new_buff;
2693 xmlbuf.end = xmlbuf.ptr + len;
2694 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2695 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2697 return status;
2700 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2702 OBJECT_ATTRIBUTES attr;
2703 IO_STATUS_BLOCK io;
2705 attr.Length = sizeof(attr);
2706 attr.RootDirectory = 0;
2707 attr.Attributes = OBJ_CASE_INSENSITIVE;
2708 attr.ObjectName = name;
2709 attr.SecurityDescriptor = NULL;
2710 attr.SecurityQualityOfService = NULL;
2711 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2714 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2716 NTSTATUS status;
2717 ULONG_PTR magic;
2718 LDR_MODULE *pldr;
2720 LdrLockLoaderLock(0, NULL, &magic);
2721 status = LdrFindEntryForAddress( module, &pldr );
2722 if (status == STATUS_SUCCESS)
2724 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2725 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2727 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2728 str->Length = pldr->FullDllName.Length;
2729 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2731 else status = STATUS_NO_MEMORY;
2733 LdrUnlockLoaderLock(0, magic);
2734 return status;
2737 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2738 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2739 HANDLE hModule, LPCWSTR resname, ULONG lang )
2741 NTSTATUS status;
2742 UNICODE_STRING nameW;
2743 LDR_RESOURCE_INFO info;
2744 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2745 void *ptr;
2747 if (TRACE_ON(actctx))
2749 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2751 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2752 hModule, debugstr_w(nameW.Buffer) );
2753 RtlFreeUnicodeString( &nameW );
2755 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2756 hModule, debugstr_w(filename) );
2759 if (!resname) return STATUS_INVALID_PARAMETER;
2761 info.Type = RT_MANIFEST;
2762 info.Language = lang;
2763 if (!((ULONG_PTR)resname >> 16))
2765 info.Name = (ULONG_PTR)resname;
2766 status = LdrFindResource_U(hModule, &info, 3, &entry);
2768 else if (resname[0] == '#')
2770 ULONG value;
2771 RtlInitUnicodeString(&nameW, resname + 1);
2772 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2773 return STATUS_INVALID_PARAMETER;
2774 info.Name = value;
2775 status = LdrFindResource_U(hModule, &info, 3, &entry);
2777 else
2779 RtlCreateUnicodeString(&nameW, resname);
2780 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2781 info.Name = (ULONG_PTR)nameW.Buffer;
2782 status = LdrFindResource_U(hModule, &info, 3, &entry);
2783 RtlFreeUnicodeString(&nameW);
2785 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2787 if (status == STATUS_SUCCESS)
2788 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2790 return status;
2793 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2794 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2795 HANDLE file, LPCWSTR resname, ULONG lang )
2797 HANDLE mapping;
2798 OBJECT_ATTRIBUTES attr;
2799 LARGE_INTEGER size;
2800 LARGE_INTEGER offset;
2801 NTSTATUS status;
2802 SIZE_T count;
2803 void *base;
2805 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2807 attr.Length = sizeof(attr);
2808 attr.RootDirectory = 0;
2809 attr.ObjectName = NULL;
2810 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2811 attr.SecurityDescriptor = NULL;
2812 attr.SecurityQualityOfService = NULL;
2814 size.QuadPart = 0;
2815 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2816 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2817 if (status != STATUS_SUCCESS) return status;
2819 offset.QuadPart = 0;
2820 count = 0;
2821 base = NULL;
2822 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2823 &count, ViewShare, 0, PAGE_READONLY );
2824 NtClose( mapping );
2825 if (status != STATUS_SUCCESS) return status;
2827 if (RtlImageNtHeader(base)) /* we got a PE file */
2829 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2830 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2832 else status = STATUS_INVALID_IMAGE_FORMAT;
2834 NtUnmapViewOfSection( GetCurrentProcess(), base );
2835 return status;
2838 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2839 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2841 FILE_END_OF_FILE_INFORMATION info;
2842 IO_STATUS_BLOCK io;
2843 HANDLE mapping;
2844 OBJECT_ATTRIBUTES attr;
2845 LARGE_INTEGER size;
2846 LARGE_INTEGER offset;
2847 NTSTATUS status;
2848 SIZE_T count;
2849 void *base;
2851 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2853 attr.Length = sizeof(attr);
2854 attr.RootDirectory = 0;
2855 attr.ObjectName = NULL;
2856 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2857 attr.SecurityDescriptor = NULL;
2858 attr.SecurityQualityOfService = NULL;
2860 size.QuadPart = 0;
2861 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2862 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2863 if (status != STATUS_SUCCESS) return status;
2865 offset.QuadPart = 0;
2866 count = 0;
2867 base = NULL;
2868 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2869 &count, ViewShare, 0, PAGE_READONLY );
2870 NtClose( mapping );
2871 if (status != STATUS_SUCCESS) return status;
2873 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2874 if (status == STATUS_SUCCESS)
2875 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2877 NtUnmapViewOfSection( GetCurrentProcess(), base );
2878 return status;
2881 /* try to load the .manifest file associated to the file */
2882 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2883 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2885 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2886 WCHAR *buffer;
2887 NTSTATUS status;
2888 UNICODE_STRING nameW;
2889 HANDLE file;
2890 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2892 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2894 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2896 if (module) /* use the module filename */
2898 UNICODE_STRING name;
2900 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2902 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2903 strcatW( name.Buffer, dotManifestW );
2904 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2905 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2906 RtlFreeUnicodeString( &name );
2908 if (status) return status;
2910 else
2912 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2913 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2914 return STATUS_NO_MEMORY;
2915 strcpyW( buffer, filename );
2916 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2917 strcatW( buffer, dotManifestW );
2918 RtlInitUnicodeString( &nameW, buffer );
2921 if (!open_nt_file( &file, &nameW ))
2923 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2924 NtClose( file );
2926 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2927 RtlFreeUnicodeString( &nameW );
2928 return status;
2931 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2933 static const WCHAR lookup_fmtW[] =
2934 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2935 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2936 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2938 WCHAR *lookup, *ret = NULL;
2939 UNICODE_STRING lookup_us;
2940 IO_STATUS_BLOCK io;
2941 const WCHAR *lang = ai->language;
2942 unsigned int data_pos = 0, data_len;
2943 char buffer[8192];
2945 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2946 (strlenW(ai->arch) + strlenW(ai->name)
2947 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2948 + sizeof(lookup_fmtW) )))
2949 return NULL;
2951 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2952 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2953 ai->version.major, ai->version.minor, lang );
2954 RtlInitUnicodeString( &lookup_us, lookup );
2956 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2957 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2959 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2960 FILE_BOTH_DIR_INFORMATION *dir_info;
2961 WCHAR *tmp;
2962 ULONG build, revision;
2964 data_len = io.Information;
2966 for (;;)
2968 if (data_pos >= data_len)
2970 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2971 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2972 break;
2973 data_len = io.Information;
2974 data_pos = 0;
2976 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2978 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2979 else data_pos = data_len;
2981 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2982 build = atoiW(tmp);
2983 if (build < min_build) continue;
2984 tmp = strchrW(tmp, '.') + 1;
2985 revision = atoiW(tmp);
2986 if (build == min_build && revision < min_revision) continue;
2987 tmp = strchrW(tmp, '_') + 1;
2988 tmp = strchrW(tmp, '_') + 1;
2989 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2990 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2992 /* prefer a non-Wine manifest if we already have one */
2993 /* we'll still load the builtin dll if specified through DllOverrides */
2994 if (ret) continue;
2996 else
2998 min_build = build;
2999 min_revision = revision;
3001 ai->version.build = build;
3002 ai->version.revision = revision;
3003 RtlFreeHeap( GetProcessHeap(), 0, ret );
3004 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3006 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3007 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3011 else WARN("no matching file for %s\n", debugstr_w(lookup));
3012 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3013 return ret;
3016 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3018 struct assembly_identity sxs_ai;
3019 UNICODE_STRING path_us;
3020 OBJECT_ATTRIBUTES attr;
3021 IO_STATUS_BLOCK io;
3022 WCHAR *path, *file = NULL;
3023 HANDLE handle;
3025 static const WCHAR manifest_dirW[] =
3026 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3028 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3030 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3031 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3032 return STATUS_NO_MEMORY;
3034 strcpyW( path, user_shared_data->NtSystemRoot );
3035 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3037 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3039 RtlFreeHeap( GetProcessHeap(), 0, path );
3040 return STATUS_NO_SUCH_FILE;
3042 RtlFreeHeap( GetProcessHeap(), 0, path );
3044 attr.Length = sizeof(attr);
3045 attr.RootDirectory = 0;
3046 attr.Attributes = OBJ_CASE_INSENSITIVE;
3047 attr.ObjectName = &path_us;
3048 attr.SecurityDescriptor = NULL;
3049 attr.SecurityQualityOfService = NULL;
3051 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3052 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3054 sxs_ai = *ai;
3055 file = lookup_manifest_file( handle, &sxs_ai );
3056 NtClose( handle );
3058 if (!file)
3060 RtlFreeUnicodeString( &path_us );
3061 return STATUS_NO_SUCH_FILE;
3064 /* append file name to directory path */
3065 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3066 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3068 RtlFreeHeap( GetProcessHeap(), 0, file );
3069 RtlFreeUnicodeString( &path_us );
3070 return STATUS_NO_MEMORY;
3073 path[path_us.Length/sizeof(WCHAR)] = '\\';
3074 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3075 RtlInitUnicodeString( &path_us, path );
3076 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3078 if (!open_nt_file( &handle, &path_us ))
3080 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3081 NtClose( handle );
3083 else io.u.Status = STATUS_NO_SUCH_FILE;
3085 RtlFreeHeap( GetProcessHeap(), 0, file );
3086 RtlFreeUnicodeString( &path_us );
3087 return io.u.Status;
3090 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3091 struct assembly_identity* ai)
3093 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3094 unsigned int i;
3095 WCHAR *buffer, *p, *directory;
3096 NTSTATUS status;
3097 UNICODE_STRING nameW;
3098 HANDLE file;
3099 DWORD len;
3101 TRACE( "looking for name=%s version=%s arch=%s\n",
3102 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3104 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3106 /* FIXME: add support for language specific lookup */
3108 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3109 strlenW(acl->actctx->appdir.info));
3111 nameW.Buffer = NULL;
3112 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3113 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3114 return STATUS_NO_MEMORY;
3116 if (!(directory = build_assembly_dir( ai )))
3118 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3119 return STATUS_NO_MEMORY;
3122 /* Lookup in <dir>\name.dll
3123 * <dir>\name.manifest
3124 * <dir>\name\name.dll
3125 * <dir>\name\name.manifest
3127 * First 'appdir' is used as <dir>, if that failed
3128 * it tries application manifest file path.
3130 strcpyW( buffer, acl->actctx->appdir.info );
3131 p = buffer + strlenW(buffer);
3132 for (i = 0; i < 4; i++)
3134 if (i == 2)
3136 struct assembly *assembly = acl->actctx->assemblies;
3137 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3139 else *p++ = '\\';
3141 strcpyW( p, ai->name );
3142 p += strlenW(p);
3144 strcpyW( p, dotDllW );
3145 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3147 status = open_nt_file( &file, &nameW );
3148 if (!status)
3150 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3151 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3152 NtClose( file );
3153 break;
3155 RtlFreeUnicodeString( &nameW );
3158 strcpyW( p, dotManifestW );
3159 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3161 status = open_nt_file( &file, &nameW );
3162 if (!status)
3164 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3165 NtClose( file );
3166 break;
3168 RtlFreeUnicodeString( &nameW );
3170 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3172 RtlFreeUnicodeString( &nameW );
3173 RtlFreeHeap( GetProcessHeap(), 0, directory );
3174 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3175 return status;
3178 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3180 NTSTATUS status = STATUS_SUCCESS;
3181 unsigned int i;
3183 for (i = 0; i < acl->num_dependencies; i++)
3185 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3187 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3189 FIXME( "Could not find dependent assembly %s (%s)\n",
3190 debugstr_w(acl->dependencies[i].name),
3191 debugstr_version(&acl->dependencies[i].version) );
3192 status = STATUS_SXS_CANT_GEN_ACTCTX;
3193 break;
3197 /* FIXME should now iterate through all refs */
3198 return status;
3201 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3202 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3204 NTSTATUS status = STATUS_SUCCESS;
3206 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3208 if (*handle) return STATUS_INVALID_PARAMETER;
3210 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3211 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3213 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3215 ULONG_PTR magic;
3216 LDR_MODULE *pldr;
3218 if (!*handle) return STATUS_INVALID_PARAMETER;
3220 LdrLockLoaderLock( 0, NULL, &magic );
3221 if (!LdrFindEntryForAddress( *handle, &pldr ))
3223 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3224 status = STATUS_DLL_NOT_FOUND;
3225 else
3226 *handle = pldr->ActivationContext;
3228 else status = STATUS_DLL_NOT_FOUND;
3229 LdrUnlockLoaderLock( 0, magic );
3231 else if (!*handle && (class != ActivationContextBasicInformation))
3232 *handle = process_actctx;
3234 return status;
3237 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3239 unsigned int i, j, total_len = 0, dll_count = 0;
3240 struct strsection_header *header;
3241 struct dllredirect_data *data;
3242 struct string_index *index;
3243 ULONG name_offset;
3245 /* compute section length */
3246 for (i = 0; i < actctx->num_assemblies; i++)
3248 struct assembly *assembly = &actctx->assemblies[i];
3249 for (j = 0; j < assembly->num_dlls; j++)
3251 struct dll_redirect *dll = &assembly->dlls[j];
3253 /* each entry needs index, data and string data */
3254 total_len += sizeof(*index);
3255 total_len += sizeof(*data);
3256 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3259 dll_count += assembly->num_dlls;
3262 total_len += sizeof(*header);
3264 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3265 if (!header) return STATUS_NO_MEMORY;
3267 memset(header, 0, sizeof(*header));
3268 header->magic = STRSECTION_MAGIC;
3269 header->size = sizeof(*header);
3270 header->count = dll_count;
3271 header->index_offset = sizeof(*header);
3272 index = (struct string_index*)((BYTE*)header + header->index_offset);
3273 name_offset = header->index_offset + header->count*sizeof(*index);
3275 for (i = 0; i < actctx->num_assemblies; i++)
3277 struct assembly *assembly = &actctx->assemblies[i];
3278 for (j = 0; j < assembly->num_dlls; j++)
3280 struct dll_redirect *dll = &assembly->dlls[j];
3281 UNICODE_STRING str;
3282 WCHAR *ptrW;
3284 /* setup new index entry */
3285 str.Buffer = dll->name;
3286 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3287 str.MaximumLength = str.Length + sizeof(WCHAR);
3288 /* hash original class name */
3289 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3291 index->name_offset = name_offset;
3292 index->name_len = str.Length;
3293 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3294 index->data_len = sizeof(*data);
3295 index->rosterindex = i + 1;
3297 /* setup data */
3298 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3299 data->size = sizeof(*data);
3300 data->unk = 2; /* FIXME: seems to be constant */
3301 memset(data->res, 0, sizeof(data->res));
3303 /* dll name */
3304 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3305 memcpy(ptrW, dll->name, index->name_len);
3306 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3308 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3310 index++;
3314 *section = header;
3316 return STATUS_SUCCESS;
3319 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3321 struct string_index *iter, *index = NULL;
3322 ULONG hash = 0, i;
3324 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3325 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3327 for (i = 0; i < section->count; i++)
3329 if (iter->hash == hash)
3331 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3333 if (!strcmpiW(nameW, name->Buffer))
3335 index = iter;
3336 break;
3338 else
3339 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3341 iter++;
3344 return index;
3347 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3349 struct guid_index *iter, *index = NULL;
3350 ULONG i;
3352 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3354 for (i = 0; i < section->count; i++)
3356 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3358 index = iter;
3359 break;
3361 iter++;
3364 return index;
3367 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3369 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3372 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3373 PACTCTX_SECTION_KEYED_DATA data)
3375 struct dllredirect_data *dll;
3376 struct string_index *index;
3378 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3380 if (!actctx->dllredirect_section)
3382 struct strsection_header *section;
3384 NTSTATUS status = build_dllredirect_section(actctx, &section);
3385 if (status) return status;
3387 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3388 RtlFreeHeap(GetProcessHeap(), 0, section);
3391 index = find_string_index(actctx->dllredirect_section, name);
3392 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3394 if (data)
3396 dll = get_dllredirect_data(actctx, index);
3398 data->ulDataFormatVersion = 1;
3399 data->lpData = dll;
3400 data->ulLength = dll->size;
3401 data->lpSectionGlobalData = NULL;
3402 data->ulSectionGlobalDataLength = 0;
3403 data->lpSectionBase = actctx->dllredirect_section;
3404 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3405 data->hActCtx = NULL;
3407 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3408 data->ulAssemblyRosterIndex = index->rosterindex;
3411 return STATUS_SUCCESS;
3414 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3416 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3419 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3421 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3424 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3426 unsigned int i, j, k, total_len = 0, class_count = 0;
3427 struct wndclass_redirect_data *data;
3428 struct strsection_header *header;
3429 struct string_index *index;
3430 ULONG name_offset;
3432 /* compute section length */
3433 for (i = 0; i < actctx->num_assemblies; i++)
3435 struct assembly *assembly = &actctx->assemblies[i];
3436 for (j = 0; j < assembly->num_dlls; j++)
3438 struct dll_redirect *dll = &assembly->dlls[j];
3439 for (k = 0; k < dll->entities.num; k++)
3441 struct entity *entity = &dll->entities.base[k];
3442 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3444 int class_len = strlenW(entity->u.class.name) + 1;
3445 int len;
3447 /* each class entry needs index, data and string data */
3448 total_len += sizeof(*index);
3449 total_len += sizeof(*data);
3450 /* original name is stored separately */
3451 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3452 /* versioned name and module name are stored one after another */
3453 if (entity->u.class.versioned)
3454 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3455 else
3456 len = class_len;
3457 len += strlenW(dll->name) + 1;
3458 total_len += aligned_string_len(len*sizeof(WCHAR));
3460 class_count++;
3466 total_len += sizeof(*header);
3468 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3469 if (!header) return STATUS_NO_MEMORY;
3471 memset(header, 0, sizeof(*header));
3472 header->magic = STRSECTION_MAGIC;
3473 header->size = sizeof(*header);
3474 header->count = class_count;
3475 header->index_offset = sizeof(*header);
3476 index = (struct string_index*)((BYTE*)header + header->index_offset);
3477 name_offset = header->index_offset + header->count*sizeof(*index);
3479 for (i = 0; i < actctx->num_assemblies; i++)
3481 struct assembly *assembly = &actctx->assemblies[i];
3482 for (j = 0; j < assembly->num_dlls; j++)
3484 struct dll_redirect *dll = &assembly->dlls[j];
3485 for (k = 0; k < dll->entities.num; k++)
3487 struct entity *entity = &dll->entities.base[k];
3488 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3490 static const WCHAR exclW[] = {'!',0};
3491 ULONG versioned_len, module_len;
3492 UNICODE_STRING str;
3493 WCHAR *ptrW;
3495 /* setup new index entry */
3496 str.Buffer = entity->u.class.name;
3497 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3498 str.MaximumLength = str.Length + sizeof(WCHAR);
3499 /* hash original class name */
3500 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3502 /* include '!' separator too */
3503 if (entity->u.class.versioned)
3504 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3505 else
3506 versioned_len = str.Length;
3507 module_len = strlenW(dll->name)*sizeof(WCHAR);
3509 index->name_offset = name_offset;
3510 index->name_len = str.Length;
3511 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3512 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3513 index->rosterindex = i + 1;
3515 /* setup data */
3516 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3517 data->size = sizeof(*data);
3518 data->res = 0;
3519 data->name_len = versioned_len;
3520 data->name_offset = sizeof(*data);
3521 data->module_len = module_len;
3522 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3524 /* original class name */
3525 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3526 memcpy(ptrW, entity->u.class.name, index->name_len);
3527 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3529 /* module name */
3530 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3531 memcpy(ptrW, dll->name, data->module_len);
3532 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3534 /* versioned name */
3535 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3536 if (entity->u.class.versioned)
3538 get_assembly_version(assembly, ptrW);
3539 strcatW(ptrW, exclW);
3540 strcatW(ptrW, entity->u.class.name);
3542 else
3544 memcpy(ptrW, entity->u.class.name, index->name_len);
3545 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3548 name_offset += sizeof(*data);
3549 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3551 index++;
3557 *section = header;
3559 return STATUS_SUCCESS;
3562 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3563 PACTCTX_SECTION_KEYED_DATA data)
3565 struct string_index *iter, *index = NULL;
3566 struct wndclass_redirect_data *class;
3567 ULONG hash;
3568 int i;
3570 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3572 if (!actctx->wndclass_section)
3574 struct strsection_header *section;
3576 NTSTATUS status = build_wndclass_section(actctx, &section);
3577 if (status) return status;
3579 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3580 RtlFreeHeap(GetProcessHeap(), 0, section);
3583 hash = 0;
3584 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3585 iter = get_wndclass_first_index(actctx);
3587 for (i = 0; i < actctx->wndclass_section->count; i++)
3589 if (iter->hash == hash)
3591 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3593 if (!strcmpiW(nameW, name->Buffer))
3595 index = iter;
3596 break;
3598 else
3599 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3601 iter++;
3604 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3606 if (data)
3608 class = get_wndclass_data(actctx, index);
3610 data->ulDataFormatVersion = 1;
3611 data->lpData = class;
3612 /* full length includes string length with nulls */
3613 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3614 data->lpSectionGlobalData = NULL;
3615 data->ulSectionGlobalDataLength = 0;
3616 data->lpSectionBase = actctx->wndclass_section;
3617 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3618 data->hActCtx = NULL;
3620 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3621 data->ulAssemblyRosterIndex = index->rosterindex;
3624 return STATUS_SUCCESS;
3627 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3629 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3630 struct guidsection_header *header;
3631 ULONG module_offset, data_offset;
3632 struct tlibredirect_data *data;
3633 struct guid_index *index;
3635 /* compute section length */
3636 for (i = 0; i < actctx->num_assemblies; i++)
3638 struct assembly *assembly = &actctx->assemblies[i];
3639 for (j = 0; j < assembly->num_dlls; j++)
3641 struct dll_redirect *dll = &assembly->dlls[j];
3642 for (k = 0; k < dll->entities.num; k++)
3644 struct entity *entity = &dll->entities.base[k];
3645 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3647 /* each entry needs index, data and string data for module name and help string */
3648 total_len += sizeof(*index);
3649 total_len += sizeof(*data);
3650 /* help string is stored separately */
3651 if (*entity->u.typelib.helpdir)
3652 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3654 /* module names are packed one after another */
3655 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3657 tlib_count++;
3663 total_len += aligned_string_len(names_len);
3664 total_len += sizeof(*header);
3666 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3667 if (!header) return STATUS_NO_MEMORY;
3669 memset(header, 0, sizeof(*header));
3670 header->magic = GUIDSECTION_MAGIC;
3671 header->size = sizeof(*header);
3672 header->count = tlib_count;
3673 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3674 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3675 module_offset = sizeof(*header);
3676 data_offset = header->index_offset + tlib_count*sizeof(*index);
3678 for (i = 0; i < actctx->num_assemblies; i++)
3680 struct assembly *assembly = &actctx->assemblies[i];
3681 for (j = 0; j < assembly->num_dlls; j++)
3683 struct dll_redirect *dll = &assembly->dlls[j];
3684 for (k = 0; k < dll->entities.num; k++)
3686 struct entity *entity = &dll->entities.base[k];
3687 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3689 ULONG module_len, help_len;
3690 UNICODE_STRING str;
3691 WCHAR *ptrW;
3693 if (*entity->u.typelib.helpdir)
3694 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3695 else
3696 help_len = 0;
3698 module_len = strlenW(dll->name)*sizeof(WCHAR);
3700 /* setup new index entry */
3701 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3702 RtlGUIDFromString(&str, &index->guid);
3703 index->data_offset = data_offset;
3704 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3705 index->rosterindex = i + 1;
3707 /* setup data */
3708 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3709 data->size = sizeof(*data);
3710 data->res = 0;
3711 data->name_len = module_len;
3712 data->name_offset = module_offset;
3713 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3714 data->langid = 0;
3715 data->flags = entity->u.typelib.flags;
3716 data->help_len = help_len;
3717 data->help_offset = sizeof(*data);
3718 data->major_version = entity->u.typelib.major;
3719 data->minor_version = entity->u.typelib.minor;
3721 /* module name */
3722 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3723 memcpy(ptrW, dll->name, data->name_len);
3724 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3726 /* help string */
3727 if (data->help_len)
3729 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3730 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3731 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3734 data_offset += sizeof(*data);
3735 if (help_len)
3736 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3738 module_offset += module_len + sizeof(WCHAR);
3740 index++;
3746 *section = header;
3748 return STATUS_SUCCESS;
3751 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3753 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3756 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3758 struct guid_index *index = NULL;
3759 struct tlibredirect_data *tlib;
3761 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3763 if (!actctx->tlib_section)
3765 struct guidsection_header *section;
3767 NTSTATUS status = build_tlib_section(actctx, &section);
3768 if (status) return status;
3770 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3771 RtlFreeHeap(GetProcessHeap(), 0, section);
3774 index = find_guid_index(actctx->tlib_section, guid);
3775 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3777 tlib = get_tlib_data(actctx, index);
3779 data->ulDataFormatVersion = 1;
3780 data->lpData = tlib;
3781 /* full length includes string length with nulls */
3782 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3783 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3784 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3785 data->lpSectionBase = actctx->tlib_section;
3786 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3787 data->hActCtx = NULL;
3789 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3790 data->ulAssemblyRosterIndex = index->rosterindex;
3792 return STATUS_SUCCESS;
3795 static void generate_uuid(ULONG *seed, GUID *guid)
3797 ULONG *ptr = (ULONG*)guid;
3798 int i;
3800 /* GUID is 16 bytes long */
3801 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3802 *ptr = RtlUniform(seed);
3804 guid->Data3 &= 0x0fff;
3805 guid->Data3 |= (4 << 12);
3806 guid->Data4[0] &= 0x3f;
3807 guid->Data4[0] |= 0x80;
3810 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3811 unsigned int *count, unsigned int *len, unsigned int *module_len)
3813 unsigned int i;
3815 for (i = 0; i < entities->num; i++)
3817 struct entity *entity = &entities->base[i];
3818 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3820 /* each entry needs two index entries, extra one goes for alias GUID */
3821 *len += 2*sizeof(struct guid_index);
3822 /* To save some memory we don't allocated two data structures,
3823 instead alias index and normal index point to the same data structure. */
3824 *len += sizeof(struct comclassredirect_data);
3826 /* for clrClass store some more */
3827 if (entity->u.comclass.name)
3829 unsigned int str_len;
3831 /* all string data is stored together in aligned block */
3832 str_len = strlenW(entity->u.comclass.name)+1;
3833 if (entity->u.comclass.progid)
3834 str_len += strlenW(entity->u.comclass.progid)+1;
3835 if (entity->u.comclass.version)
3836 str_len += strlenW(entity->u.comclass.version)+1;
3838 *len += sizeof(struct clrclass_data);
3839 *len += aligned_string_len(str_len*sizeof(WCHAR));
3841 /* module name is forced to mscoree.dll, and stored two times with different case */
3842 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3844 else
3846 /* progid string is stored separately */
3847 if (entity->u.comclass.progid)
3848 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3850 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3853 *count += 1;
3858 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3859 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3860 ULONG *seed, ULONG rosterindex)
3862 unsigned int i;
3864 for (i = 0; i < entities->num; i++)
3866 struct entity *entity = &entities->base[i];
3867 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3869 ULONG module_len, progid_len, str_len = 0;
3870 struct comclassredirect_data *data;
3871 struct guid_index *alias_index;
3872 struct clrclass_data *clrdata;
3873 UNICODE_STRING str;
3874 WCHAR *ptrW;
3876 if (entity->u.comclass.progid)
3877 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3878 else
3879 progid_len = 0;
3881 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3883 /* setup new index entry */
3884 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3885 RtlGUIDFromString(&str, &(*index)->guid);
3887 (*index)->data_offset = *data_offset;
3888 (*index)->data_len = sizeof(*data); /* additional length added later */
3889 (*index)->rosterindex = rosterindex;
3891 /* Setup new index entry for alias guid. Alias index records are placed after
3892 normal records, so normal guids are hit first on search. Note that class count
3893 is doubled. */
3894 alias_index = (*index) + section->count/2;
3895 generate_uuid(seed, &alias_index->guid);
3896 alias_index->data_offset = (*index)->data_offset;
3897 alias_index->data_len = 0;
3898 alias_index->rosterindex = (*index)->rosterindex;
3900 /* setup data */
3901 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3902 data->size = sizeof(*data);
3903 data->res = 0;
3904 data->res1[0] = 0;
3905 data->res1[1] = 0;
3906 data->model = entity->u.comclass.model;
3907 data->clsid = (*index)->guid;
3908 data->alias = alias_index->guid;
3909 data->clsid2 = data->clsid;
3910 if (entity->u.comclass.tlbid)
3912 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3913 RtlGUIDFromString(&str, &data->tlbid);
3915 else
3916 memset(&data->tlbid, 0, sizeof(data->tlbid));
3917 data->name_len = module_len;
3918 data->name_offset = *module_offset;
3919 data->progid_len = progid_len;
3920 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3921 data->clrdata_len = 0; /* will be set later */
3922 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3923 data->miscstatus = entity->u.comclass.miscstatus;
3924 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3925 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3926 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3927 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3929 /* mask describes which misc* data is available */
3930 data->miscmask = 0;
3931 if (data->miscstatus)
3932 data->miscmask |= MiscStatus;
3933 if (data->miscstatuscontent)
3934 data->miscmask |= MiscStatusContent;
3935 if (data->miscstatusthumbnail)
3936 data->miscmask |= MiscStatusThumbnail;
3937 if (data->miscstatusicon)
3938 data->miscmask |= MiscStatusIcon;
3939 if (data->miscstatusdocprint)
3940 data->miscmask |= MiscStatusDocPrint;
3942 if (data->clrdata_offset)
3944 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3946 clrdata->size = sizeof(*clrdata);
3947 clrdata->res[0] = 0;
3948 clrdata->res[1] = 2; /* FIXME: unknown field */
3949 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3950 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3951 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3952 clrdata->name_offset = clrdata->size;
3953 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3954 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3955 clrdata->res2[0] = 0;
3956 clrdata->res2[1] = 0;
3958 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3960 /* module name */
3961 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3962 memcpy(ptrW, mscoree2W, clrdata->module_len);
3963 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3965 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3966 memcpy(ptrW, mscoreeW, data->name_len);
3967 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3969 /* class name */
3970 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3971 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3972 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3974 /* runtime version, optional */
3975 if (clrdata->version_len)
3977 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3979 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3980 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3981 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3984 if (data->progid_len)
3985 data->progid_offset += data->clrdata_len;
3986 (*index)->data_len += sizeof(*clrdata);
3988 else
3990 clrdata = NULL;
3992 /* module name */
3993 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3994 memcpy(ptrW, dll->name, data->name_len);
3995 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3998 /* progid string */
3999 if (data->progid_len)
4001 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4002 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4003 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4006 /* string block length */
4007 str_len = 0;
4008 if (clrdata)
4010 str_len += clrdata->name_len + sizeof(WCHAR);
4011 if (clrdata->version_len)
4012 str_len += clrdata->version_len + sizeof(WCHAR);
4014 if (progid_len)
4015 str_len += progid_len + sizeof(WCHAR);
4017 (*index)->data_len += aligned_string_len(str_len);
4018 alias_index->data_len = (*index)->data_len;
4020 /* move to next data record */
4021 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4022 (*module_offset) += module_len + sizeof(WCHAR);
4024 if (clrdata)
4026 (*data_offset) += sizeof(*clrdata);
4027 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4029 (*index) += 1;
4034 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4036 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4037 struct guidsection_header *header;
4038 ULONG module_offset, data_offset;
4039 struct guid_index *index;
4040 ULONG seed;
4042 /* compute section length */
4043 for (i = 0; i < actctx->num_assemblies; i++)
4045 struct assembly *assembly = &actctx->assemblies[i];
4046 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4047 for (j = 0; j < assembly->num_dlls; j++)
4049 struct dll_redirect *dll = &assembly->dlls[j];
4050 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4054 total_len += aligned_string_len(names_len);
4055 total_len += sizeof(*header);
4057 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4058 if (!header) return STATUS_NO_MEMORY;
4060 memset(header, 0, sizeof(*header));
4061 header->magic = GUIDSECTION_MAGIC;
4062 header->size = sizeof(*header);
4063 header->count = 2*class_count;
4064 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4065 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4066 module_offset = sizeof(*header);
4067 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4069 seed = NtGetTickCount();
4070 for (i = 0; i < actctx->num_assemblies; i++)
4072 struct assembly *assembly = &actctx->assemblies[i];
4073 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4074 for (j = 0; j < assembly->num_dlls; j++)
4076 struct dll_redirect *dll = &assembly->dlls[j];
4077 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4081 *section = header;
4083 return STATUS_SUCCESS;
4086 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4088 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4091 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4093 struct comclassredirect_data *comclass;
4094 struct guid_index *index = NULL;
4096 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4098 if (!actctx->comserver_section)
4100 struct guidsection_header *section;
4102 NTSTATUS status = build_comserver_section(actctx, &section);
4103 if (status) return status;
4105 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4106 RtlFreeHeap(GetProcessHeap(), 0, section);
4109 index = find_guid_index(actctx->comserver_section, guid);
4110 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4112 comclass = get_comclass_data(actctx, index);
4114 data->ulDataFormatVersion = 1;
4115 data->lpData = comclass;
4116 /* full length includes string length with nulls */
4117 data->ulLength = comclass->size + comclass->clrdata_len;
4118 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4119 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4120 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4121 data->lpSectionBase = actctx->comserver_section;
4122 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4123 data->hActCtx = NULL;
4125 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4126 data->ulAssemblyRosterIndex = index->rosterindex;
4128 return STATUS_SUCCESS;
4131 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4133 unsigned int i;
4135 for (i = 0; i < entities->num; i++)
4137 struct entity *entity = &entities->base[i];
4138 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4140 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4141 if (entity->u.ifaceps.name)
4142 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4143 *count += 1;
4148 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4149 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4151 unsigned int i;
4153 for (i = 0; i < entities->num; i++)
4155 struct entity *entity = &entities->base[i];
4156 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4158 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4159 UNICODE_STRING str;
4160 ULONG name_len;
4162 if (entity->u.ifaceps.name)
4163 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4164 else
4165 name_len = 0;
4167 /* setup index */
4168 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4169 RtlGUIDFromString(&str, &(*index)->guid);
4170 (*index)->data_offset = *data_offset;
4171 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4172 (*index)->rosterindex = rosterindex;
4174 /* setup data record */
4175 data->size = sizeof(*data);
4176 data->mask = entity->u.ifaceps.mask;
4178 /* proxyStubClsid32 value is only stored for external PS,
4179 if set it's used as iid, otherwise 'iid' attribute value is used */
4180 if (entity->u.ifaceps.ps32)
4182 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4183 RtlGUIDFromString(&str, &data->iid);
4185 else
4186 data->iid = (*index)->guid;
4188 data->nummethods = entity->u.ifaceps.nummethods;
4190 if (entity->u.ifaceps.tlib)
4192 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4193 RtlGUIDFromString(&str, &data->tlbid);
4195 else
4196 memset(&data->tlbid, 0, sizeof(data->tlbid));
4198 if (entity->u.ifaceps.base)
4200 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4201 RtlGUIDFromString(&str, &data->base);
4203 else
4204 memset(&data->base, 0, sizeof(data->base));
4206 data->name_len = name_len;
4207 data->name_offset = data->name_len ? sizeof(*data) : 0;
4209 /* name string */
4210 if (data->name_len)
4212 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4213 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4214 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4217 /* move to next record */
4218 (*index) += 1;
4219 *data_offset += sizeof(*data);
4220 if (data->name_len)
4221 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4226 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4228 unsigned int i, j, total_len = 0, count = 0;
4229 struct guidsection_header *header;
4230 struct guid_index *index;
4231 ULONG data_offset;
4233 /* compute section length */
4234 for (i = 0; i < actctx->num_assemblies; i++)
4236 struct assembly *assembly = &actctx->assemblies[i];
4238 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4239 for (j = 0; j < assembly->num_dlls; j++)
4241 struct dll_redirect *dll = &assembly->dlls[j];
4242 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4246 total_len += sizeof(*header);
4248 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4249 if (!header) return STATUS_NO_MEMORY;
4251 memset(header, 0, sizeof(*header));
4252 header->magic = GUIDSECTION_MAGIC;
4253 header->size = sizeof(*header);
4254 header->count = count;
4255 header->index_offset = sizeof(*header);
4256 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4257 data_offset = header->index_offset + count*sizeof(*index);
4259 for (i = 0; i < actctx->num_assemblies; i++)
4261 struct assembly *assembly = &actctx->assemblies[i];
4263 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4264 for (j = 0; j < assembly->num_dlls; j++)
4266 struct dll_redirect *dll = &assembly->dlls[j];
4267 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4271 *section = header;
4273 return STATUS_SUCCESS;
4276 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4278 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4281 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4283 struct ifacepsredirect_data *iface;
4284 struct guid_index *index = NULL;
4286 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4288 if (!actctx->ifaceps_section)
4290 struct guidsection_header *section;
4292 NTSTATUS status = build_ifaceps_section(actctx, &section);
4293 if (status) return status;
4295 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4296 RtlFreeHeap(GetProcessHeap(), 0, section);
4299 index = find_guid_index(actctx->ifaceps_section, guid);
4300 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4302 iface = get_ifaceps_data(actctx, index);
4304 data->ulDataFormatVersion = 1;
4305 data->lpData = iface;
4306 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4307 data->lpSectionGlobalData = NULL;
4308 data->ulSectionGlobalDataLength = 0;
4309 data->lpSectionBase = actctx->ifaceps_section;
4310 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4311 data->hActCtx = NULL;
4313 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4314 data->ulAssemblyRosterIndex = index->rosterindex;
4316 return STATUS_SUCCESS;
4319 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4321 unsigned int i, j, total_len = 0, count = 0;
4322 struct guidsection_header *header;
4323 struct clrsurrogate_data *data;
4324 struct guid_index *index;
4325 ULONG data_offset;
4327 /* compute section length */
4328 for (i = 0; i < actctx->num_assemblies; i++)
4330 struct assembly *assembly = &actctx->assemblies[i];
4331 for (j = 0; j < assembly->entities.num; j++)
4333 struct entity *entity = &assembly->entities.base[j];
4334 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4336 ULONG len;
4338 total_len += sizeof(*index) + sizeof(*data);
4339 len = strlenW(entity->u.clrsurrogate.name) + 1;
4340 if (entity->u.clrsurrogate.version)
4341 len += strlenW(entity->u.clrsurrogate.version) + 1;
4342 total_len += aligned_string_len(len*sizeof(WCHAR));
4344 count++;
4349 total_len += sizeof(*header);
4351 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4352 if (!header) return STATUS_NO_MEMORY;
4354 memset(header, 0, sizeof(*header));
4355 header->magic = GUIDSECTION_MAGIC;
4356 header->size = sizeof(*header);
4357 header->count = count;
4358 header->index_offset = sizeof(*header);
4359 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4360 data_offset = header->index_offset + count*sizeof(*index);
4362 for (i = 0; i < actctx->num_assemblies; i++)
4364 struct assembly *assembly = &actctx->assemblies[i];
4365 for (j = 0; j < assembly->entities.num; j++)
4367 struct entity *entity = &assembly->entities.base[j];
4368 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4370 ULONG version_len, name_len;
4371 UNICODE_STRING str;
4372 WCHAR *ptrW;
4374 if (entity->u.clrsurrogate.version)
4375 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4376 else
4377 version_len = 0;
4378 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4380 /* setup new index entry */
4381 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4382 RtlGUIDFromString(&str, &index->guid);
4384 index->data_offset = data_offset;
4385 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4386 index->rosterindex = i + 1;
4388 /* setup data */
4389 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4390 data->size = sizeof(*data);
4391 data->res = 0;
4392 data->clsid = index->guid;
4393 data->version_offset = version_len ? data->size : 0;
4394 data->version_len = version_len;
4395 data->name_offset = data->size + version_len;
4396 if (version_len)
4397 data->name_offset += sizeof(WCHAR);
4398 data->name_len = name_len;
4400 /* surrogate name */
4401 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4402 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4403 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4405 /* runtime version */
4406 if (data->version_len)
4408 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4409 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4410 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4413 data_offset += index->data_offset;
4414 index++;
4419 *section = header;
4421 return STATUS_SUCCESS;
4424 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4426 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4429 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4431 struct clrsurrogate_data *surrogate;
4432 struct guid_index *index = NULL;
4434 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4436 if (!actctx->clrsurrogate_section)
4438 struct guidsection_header *section;
4440 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4441 if (status) return status;
4443 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4444 RtlFreeHeap(GetProcessHeap(), 0, section);
4447 index = find_guid_index(actctx->clrsurrogate_section, guid);
4448 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4450 surrogate = get_surrogate_data(actctx, index);
4452 data->ulDataFormatVersion = 1;
4453 data->lpData = surrogate;
4454 /* full length includes string length with nulls */
4455 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4456 if (surrogate->version_len)
4457 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4459 data->lpSectionGlobalData = NULL;
4460 data->ulSectionGlobalDataLength = 0;
4461 data->lpSectionBase = actctx->clrsurrogate_section;
4462 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4463 data->hActCtx = NULL;
4465 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4466 data->ulAssemblyRosterIndex = index->rosterindex;
4468 return STATUS_SUCCESS;
4471 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4473 unsigned int i, j, single_len;
4475 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4476 for (i = 0; i < entities->num; i++)
4478 struct entity *entity = &entities->base[i];
4479 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4481 if (entity->u.comclass.progid)
4483 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4484 *count += 1;
4487 for (j = 0; j < entity->u.comclass.progids.num; j++)
4488 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4490 *total_len += single_len*entity->u.comclass.progids.num;
4491 *count += entity->u.comclass.progids.num;
4496 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4497 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4499 struct progidredirect_data *data;
4500 UNICODE_STRING str;
4501 GUID *guid_ptr;
4502 WCHAR *ptrW;
4504 /* setup new index entry */
4506 /* hash progid name */
4507 RtlInitUnicodeString(&str, progid);
4508 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4510 (*index)->name_offset = *data_offset;
4511 (*index)->name_len = str.Length;
4512 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4513 (*index)->data_len = sizeof(*data);
4514 (*index)->rosterindex = rosterindex;
4516 *data_offset += aligned_string_len(str.MaximumLength);
4518 /* setup data structure */
4519 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4520 data->size = sizeof(*data);
4521 data->reserved = 0;
4522 data->clsid_offset = *global_offset;
4524 /* write progid string */
4525 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4526 memcpy(ptrW, progid, (*index)->name_len);
4527 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4529 /* write guid to global area */
4530 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4531 *guid_ptr = *alias;
4533 /* to next entry */
4534 *global_offset += sizeof(GUID);
4535 *data_offset += data->size;
4536 (*index) += 1;
4539 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4540 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4542 unsigned int i, j;
4544 for (i = 0; i < entities->num; i++)
4546 struct entity *entity = &entities->base[i];
4547 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4549 const struct progids *progids = &entity->u.comclass.progids;
4550 struct comclassredirect_data *comclass;
4551 struct guid_index *guid_index;
4552 UNICODE_STRING str;
4553 GUID clsid;
4555 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4556 RtlGUIDFromString(&str, &clsid);
4558 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4559 comclass = get_comclass_data(actctx, guid_index);
4561 if (entity->u.comclass.progid)
4562 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4563 index, data_offset, global_offset, rosterindex);
4565 for (j = 0; j < progids->num; j++)
4566 write_progid_record(section, progids->progids[j], &comclass->alias,
4567 index, data_offset, global_offset, rosterindex);
4572 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4574 unsigned int i, j, total_len = 0, count = 0;
4575 struct strsection_header *header;
4576 ULONG data_offset, global_offset;
4577 struct string_index *index;
4579 /* compute section length */
4580 for (i = 0; i < actctx->num_assemblies; i++)
4582 struct assembly *assembly = &actctx->assemblies[i];
4584 get_progid_datalen(&assembly->entities, &count, &total_len);
4585 for (j = 0; j < assembly->num_dlls; j++)
4587 struct dll_redirect *dll = &assembly->dlls[j];
4588 get_progid_datalen(&dll->entities, &count, &total_len);
4592 total_len += sizeof(*header);
4594 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4595 if (!header) return STATUS_NO_MEMORY;
4597 memset(header, 0, sizeof(*header));
4598 header->magic = STRSECTION_MAGIC;
4599 header->size = sizeof(*header);
4600 header->count = count;
4601 header->global_offset = header->size;
4602 header->global_len = count*sizeof(GUID);
4603 header->index_offset = header->size + header->global_len;
4605 index = (struct string_index*)((BYTE*)header + header->index_offset);
4606 data_offset = header->index_offset + count*sizeof(*index);
4607 global_offset = header->global_offset;
4609 for (i = 0; i < actctx->num_assemblies; i++)
4611 struct assembly *assembly = &actctx->assemblies[i];
4613 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4614 for (j = 0; j < assembly->num_dlls; j++)
4616 struct dll_redirect *dll = &assembly->dlls[j];
4617 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4621 *section = header;
4623 return STATUS_SUCCESS;
4626 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4628 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4631 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4632 PACTCTX_SECTION_KEYED_DATA data)
4634 struct progidredirect_data *progid;
4635 struct string_index *index;
4637 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4639 if (!actctx->comserver_section)
4641 struct guidsection_header *section;
4643 NTSTATUS status = build_comserver_section(actctx, &section);
4644 if (status) return status;
4646 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4647 RtlFreeHeap(GetProcessHeap(), 0, section);
4650 if (!actctx->progid_section)
4652 struct strsection_header *section;
4654 NTSTATUS status = build_progid_section(actctx, &section);
4655 if (status) return status;
4657 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4658 RtlFreeHeap(GetProcessHeap(), 0, section);
4661 index = find_string_index(actctx->progid_section, name);
4662 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4664 if (data)
4666 progid = get_progid_data(actctx, index);
4668 data->ulDataFormatVersion = 1;
4669 data->lpData = progid;
4670 data->ulLength = progid->size;
4671 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4672 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4673 data->lpSectionBase = actctx->progid_section;
4674 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4675 data->hActCtx = NULL;
4677 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4678 data->ulAssemblyRosterIndex = index->rosterindex;
4681 return STATUS_SUCCESS;
4684 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4685 const UNICODE_STRING *section_name,
4686 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4688 NTSTATUS status;
4690 switch (section_kind)
4692 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4693 status = find_dll_redirection(actctx, section_name, data);
4694 break;
4695 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4696 status = find_window_class(actctx, section_name, data);
4697 break;
4698 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4699 status = find_progid_redirection(actctx, section_name, data);
4700 break;
4701 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4702 FIXME("Unsupported yet section_kind %x\n", section_kind);
4703 return STATUS_SXS_SECTION_NOT_FOUND;
4704 default:
4705 WARN("Unknown section_kind %x\n", section_kind);
4706 return STATUS_SXS_SECTION_NOT_FOUND;
4709 if (status != STATUS_SUCCESS) return status;
4711 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4713 actctx_addref(actctx);
4714 data->hActCtx = actctx;
4716 return STATUS_SUCCESS;
4719 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4720 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4722 NTSTATUS status;
4724 switch (section_kind)
4726 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4727 status = find_tlib_redirection(actctx, guid, data);
4728 break;
4729 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4730 status = find_comserver_redirection(actctx, guid, data);
4731 break;
4732 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4733 status = find_cominterface_redirection(actctx, guid, data);
4734 break;
4735 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4736 status = find_clr_surrogate(actctx, guid, data);
4737 break;
4738 default:
4739 WARN("Unknown section_kind %x\n", section_kind);
4740 return STATUS_SXS_SECTION_NOT_FOUND;
4743 if (status != STATUS_SUCCESS) return status;
4745 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4747 actctx_addref(actctx);
4748 data->hActCtx = actctx;
4750 return STATUS_SUCCESS;
4753 /* initialize the activation context for the current process */
4754 void actctx_init(void)
4756 ACTCTXW ctx;
4757 HANDLE handle;
4759 ctx.cbSize = sizeof(ctx);
4760 ctx.lpSource = NULL;
4761 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4762 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4763 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4765 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4769 /***********************************************************************
4770 * RtlCreateActivationContext (NTDLL.@)
4772 * Create an activation context.
4774 * FIXME: function signature/prototype is wrong
4776 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4778 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4779 const WCHAR *directory = NULL;
4780 ACTIVATION_CONTEXT *actctx;
4781 UNICODE_STRING nameW;
4782 ULONG lang = 0;
4783 NTSTATUS status = STATUS_NO_MEMORY;
4784 HANDLE file = 0;
4785 struct actctx_loader acl;
4787 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4789 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4790 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4791 return STATUS_INVALID_PARAMETER;
4793 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4794 return STATUS_NO_MEMORY;
4796 actctx->magic = ACTCTX_MAGIC;
4797 actctx->ref_count = 1;
4798 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4799 actctx->config.info = NULL;
4800 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4801 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4803 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4805 else
4807 UNICODE_STRING dir;
4808 WCHAR *p;
4809 HMODULE module;
4811 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4812 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4814 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4815 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4816 actctx->appdir.info = dir.Buffer;
4819 nameW.Buffer = NULL;
4821 /* open file only if it's going to be used */
4822 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4823 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4825 WCHAR *source = NULL;
4826 BOOLEAN ret;
4828 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4829 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4831 DWORD dir_len, source_len;
4833 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4834 source_len = strlenW(pActCtx->lpSource);
4835 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4837 status = STATUS_NO_MEMORY;
4838 goto error;
4841 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4842 source[dir_len] = '\\';
4843 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4846 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4847 RtlFreeHeap( GetProcessHeap(), 0, source );
4848 if (!ret)
4850 status = STATUS_NO_SUCH_FILE;
4851 goto error;
4853 status = open_nt_file( &file, &nameW );
4854 if (status)
4856 RtlFreeUnicodeString( &nameW );
4857 goto error;
4861 acl.actctx = actctx;
4862 acl.dependencies = NULL;
4863 acl.num_dependencies = 0;
4864 acl.allocated_dependencies = 0;
4866 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4867 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4869 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4871 /* if we have a resource it's a PE file */
4872 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4874 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4875 pActCtx->lpResourceName, lang );
4876 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4877 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4878 pActCtx->hModule, pActCtx->lpResourceName );
4880 else if (pActCtx->lpSource)
4882 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4883 file, pActCtx->lpResourceName, lang );
4884 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4885 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4886 NULL, pActCtx->lpResourceName );
4888 else status = STATUS_INVALID_PARAMETER;
4890 else
4892 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4895 if (file) NtClose( file );
4896 RtlFreeUnicodeString( &nameW );
4898 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4899 free_depend_manifests( &acl );
4901 if (status == STATUS_SUCCESS) *handle = actctx;
4902 else actctx_release( actctx );
4903 return status;
4905 error:
4906 if (file) NtClose( file );
4907 actctx_release( actctx );
4908 return status;
4912 /***********************************************************************
4913 * RtlAddRefActivationContext (NTDLL.@)
4915 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4917 ACTIVATION_CONTEXT *actctx;
4919 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4923 /******************************************************************
4924 * RtlReleaseActivationContext (NTDLL.@)
4926 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4928 ACTIVATION_CONTEXT *actctx;
4930 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4933 /******************************************************************
4934 * RtlZombifyActivationContext (NTDLL.@)
4936 * FIXME: function prototype might be wrong
4938 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4940 FIXME("%p: stub\n", handle);
4941 return STATUS_NOT_IMPLEMENTED;
4944 /******************************************************************
4945 * RtlActivateActivationContext (NTDLL.@)
4947 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4949 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4951 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4952 return STATUS_NO_MEMORY;
4954 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4955 frame->ActivationContext = handle;
4956 frame->Flags = 0;
4957 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4958 RtlAddRefActivationContext( handle );
4960 *cookie = (ULONG_PTR)frame;
4961 TRACE( "%p cookie=%lx\n", handle, *cookie );
4962 return STATUS_SUCCESS;
4966 /***********************************************************************
4967 * RtlDeactivateActivationContext (NTDLL.@)
4969 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4971 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4973 TRACE( "%x cookie=%lx\n", flags, cookie );
4975 /* find the right frame */
4976 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4977 for (frame = top; frame; frame = frame->Previous)
4978 if ((ULONG_PTR)frame == cookie) break;
4980 if (!frame)
4981 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4983 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4984 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4986 /* pop everything up to and including frame */
4987 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4989 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4991 frame = top->Previous;
4992 RtlReleaseActivationContext( top->ActivationContext );
4993 RtlFreeHeap( GetProcessHeap(), 0, top );
4994 top = frame;
4999 /******************************************************************
5000 * RtlFreeThreadActivationContextStack (NTDLL.@)
5002 void WINAPI RtlFreeThreadActivationContextStack(void)
5004 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5006 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5007 while (frame)
5009 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5010 RtlReleaseActivationContext( frame->ActivationContext );
5011 RtlFreeHeap( GetProcessHeap(), 0, frame );
5012 frame = prev;
5014 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5018 /******************************************************************
5019 * RtlGetActiveActivationContext (NTDLL.@)
5021 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5023 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5025 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5026 RtlAddRefActivationContext( *handle );
5028 else
5029 *handle = 0;
5031 return STATUS_SUCCESS;
5035 /******************************************************************
5036 * RtlIsActivationContextActive (NTDLL.@)
5038 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5040 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5042 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5043 if (frame->ActivationContext == handle) return TRUE;
5044 return FALSE;
5048 /***********************************************************************
5049 * RtlQueryInformationActivationContext (NTDLL.@)
5051 * Get information about an activation context.
5052 * FIXME: function signature/prototype may be wrong
5054 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5055 ULONG class, PVOID buffer,
5056 SIZE_T bufsize, SIZE_T *retlen )
5058 ACTIVATION_CONTEXT *actctx;
5059 NTSTATUS status;
5061 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5062 subinst, class, buffer, bufsize, retlen);
5064 if (retlen) *retlen = 0;
5065 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5067 switch (class)
5069 case ActivationContextBasicInformation:
5071 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5073 if (retlen) *retlen = sizeof(*info);
5074 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5076 info->hActCtx = handle;
5077 info->dwFlags = 0; /* FIXME */
5078 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5080 break;
5082 case ActivationContextDetailedInformation:
5084 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5085 struct assembly *assembly = NULL;
5086 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5087 LPWSTR ptr;
5089 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5091 if (actctx->num_assemblies) assembly = actctx->assemblies;
5093 if (assembly && assembly->manifest.info)
5094 manifest_len = strlenW(assembly->manifest.info) + 1;
5095 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5096 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5097 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5099 if (retlen) *retlen = len;
5100 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5102 acdi->dwFlags = 0;
5103 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5104 acdi->ulAssemblyCount = actctx->num_assemblies;
5105 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5106 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5107 acdi->ulRootConfigurationPathType = actctx->config.type;
5108 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5109 acdi->ulAppDirPathType = actctx->appdir.type;
5110 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5111 ptr = (LPWSTR)(acdi + 1);
5112 if (manifest_len)
5114 acdi->lpRootManifestPath = ptr;
5115 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5116 ptr += manifest_len;
5118 else acdi->lpRootManifestPath = NULL;
5119 if (config_len)
5121 acdi->lpRootConfigurationPath = ptr;
5122 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5123 ptr += config_len;
5125 else acdi->lpRootConfigurationPath = NULL;
5126 if (appdir_len)
5128 acdi->lpAppDirPath = ptr;
5129 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5131 else acdi->lpAppDirPath = NULL;
5133 break;
5135 case AssemblyDetailedInformationInActivationContext:
5137 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5138 struct assembly *assembly;
5139 WCHAR *assembly_id;
5140 DWORD index;
5141 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5142 LPWSTR ptr;
5144 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5145 if (!subinst) return STATUS_INVALID_PARAMETER;
5147 index = *(DWORD*)subinst;
5148 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5150 assembly = &actctx->assemblies[index - 1];
5152 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5153 id_len = strlenW(assembly_id) + 1;
5154 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5156 if (assembly->manifest.info &&
5157 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5158 path_len = strlenW(assembly->manifest.info) + 1;
5160 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5162 if (retlen) *retlen = len;
5163 if (!buffer || bufsize < len)
5165 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5166 return STATUS_BUFFER_TOO_SMALL;
5169 afdi->ulFlags = 0; /* FIXME */
5170 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5171 afdi->ulManifestPathType = assembly->manifest.type;
5172 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5173 /* FIXME afdi->liManifestLastWriteTime = 0; */
5174 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5175 afdi->ulPolicyPathLength = 0;
5176 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5177 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5178 afdi->ulManifestVersionMajor = 1;
5179 afdi->ulManifestVersionMinor = 0;
5180 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5181 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5182 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5183 ptr = (LPWSTR)(afdi + 1);
5184 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5185 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5186 ptr += id_len;
5187 if (path_len)
5189 afdi->lpAssemblyManifestPath = ptr;
5190 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5191 ptr += path_len;
5192 } else afdi->lpAssemblyManifestPath = NULL;
5193 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5194 if (ad_len)
5196 afdi->lpAssemblyDirectoryName = ptr;
5197 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5199 else afdi->lpAssemblyDirectoryName = NULL;
5200 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5202 break;
5204 case FileInformationInAssemblyOfAssemblyInActivationContext:
5206 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5207 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5208 struct assembly *assembly;
5209 struct dll_redirect *dll;
5210 SIZE_T len, dll_len = 0;
5211 LPWSTR ptr;
5213 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5214 if (!acqi) return STATUS_INVALID_PARAMETER;
5216 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5217 return STATUS_INVALID_PARAMETER;
5218 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5220 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5221 return STATUS_INVALID_PARAMETER;
5222 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5224 if (dll->name) dll_len = strlenW(dll->name) + 1;
5225 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5227 if (!buffer || bufsize < len)
5229 if (retlen) *retlen = len;
5230 return STATUS_BUFFER_TOO_SMALL;
5232 if (retlen) *retlen = 0; /* yes that's what native does !! */
5233 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5234 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5235 afdi->ulPathLength = 0; /* FIXME */
5236 ptr = (LPWSTR)(afdi + 1);
5237 if (dll_len)
5239 afdi->lpFileName = ptr;
5240 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5241 } else afdi->lpFileName = NULL;
5242 afdi->lpFilePath = NULL; /* FIXME */
5244 break;
5246 case CompatibilityInformationInActivationContext:
5248 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5249 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5250 struct assembly *assembly = NULL;
5251 ULONG num_compat_contexts = 0, n;
5252 SIZE_T len;
5254 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5256 if (actctx->num_assemblies) assembly = actctx->assemblies;
5258 if (assembly)
5259 num_compat_contexts = assembly->num_compat_contexts;
5260 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5262 if (retlen) *retlen = len;
5263 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5265 *acci = num_compat_contexts;
5266 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5267 for (n = 0; n < num_compat_contexts; ++n)
5269 elements[n] = assembly->compat_contexts[n];
5272 break;
5274 case RunlevelInformationInActivationContext:
5276 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5277 struct assembly *assembly;
5278 SIZE_T len;
5280 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5282 len = sizeof(*acrli);
5283 if (retlen) *retlen = len;
5284 if (!buffer || bufsize < len)
5285 return STATUS_BUFFER_TOO_SMALL;
5287 assembly = actctx->assemblies;
5289 acrli->ulFlags = 0;
5290 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5291 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5293 break;
5295 default:
5296 FIXME( "class %u not implemented\n", class );
5297 return STATUS_NOT_IMPLEMENTED;
5299 return STATUS_SUCCESS;
5302 /***********************************************************************
5303 * RtlFindActivationContextSectionString (NTDLL.@)
5305 * Find information about a string in an activation context.
5306 * FIXME: function signature/prototype may be wrong
5308 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5309 const UNICODE_STRING *section_name, PVOID ptr )
5311 PACTCTX_SECTION_KEYED_DATA data = ptr;
5312 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5314 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5315 debugstr_us(section_name), data);
5317 if (guid)
5319 FIXME("expected guid == NULL\n");
5320 return STATUS_INVALID_PARAMETER;
5322 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5324 FIXME("unknown flags %08x\n", flags);
5325 return STATUS_INVALID_PARAMETER;
5327 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5328 !section_name || !section_name->Buffer)
5330 WARN("invalid parameter\n");
5331 return STATUS_INVALID_PARAMETER;
5334 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5336 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5337 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5340 if (status != STATUS_SUCCESS)
5341 status = find_string( process_actctx, section_kind, section_name, flags, data );
5343 return status;
5346 /***********************************************************************
5347 * RtlFindActivationContextSectionGuid (NTDLL.@)
5349 * Find information about a GUID in an activation context.
5350 * FIXME: function signature/prototype may be wrong
5352 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5353 const GUID *guid, void *ptr )
5355 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5356 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5358 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5360 if (extguid)
5362 FIXME("expected extguid == NULL\n");
5363 return STATUS_INVALID_PARAMETER;
5366 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5368 FIXME("unknown flags %08x\n", flags);
5369 return STATUS_INVALID_PARAMETER;
5372 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5373 return STATUS_INVALID_PARAMETER;
5375 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5377 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5378 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5381 if (status != STATUS_SUCCESS)
5382 status = find_guid( process_actctx, section_kind, guid, flags, data );
5384 return status;