wineconsole: Free registry key name (valgrind).
[wine.git] / dlls / ntdll / actctx.c
blob9a9dec90961f5ea807a16b288852d8c1ca88c05d
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 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "winternl.h"
36 #include "ddk/wdm.h"
37 #include "ntdll_misc.h"
38 #include "wine/exception.h"
39 #include "wine/debug.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
44 #define ACTCTX_FLAGS_ALL (\
45 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
46 ACTCTX_FLAG_LANGID_VALID |\
47 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
48 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
49 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
50 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
51 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
52 ACTCTX_FLAG_HMODULE_VALID )
54 #define ACTCTX_MAGIC 0xC07E3E11
55 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
56 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
58 /* we don't want to include winuser.h */
59 #define RT_MANIFEST ((ULONG_PTR)24)
60 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
62 /* from oaidl.h */
63 typedef enum tagLIBFLAGS {
64 LIBFLAG_FRESTRICTED = 0x1,
65 LIBFLAG_FCONTROL = 0x2,
66 LIBFLAG_FHIDDEN = 0x4,
67 LIBFLAG_FHASDISKIMAGE = 0x8
68 } LIBFLAGS;
70 /* from oleidl.idl */
71 typedef enum tagOLEMISC
73 OLEMISC_RECOMPOSEONRESIZE = 0x1,
74 OLEMISC_ONLYICONIC = 0x2,
75 OLEMISC_INSERTNOTREPLACE = 0x4,
76 OLEMISC_STATIC = 0x8,
77 OLEMISC_CANTLINKINSIDE = 0x10,
78 OLEMISC_CANLINKBYOLE1 = 0x20,
79 OLEMISC_ISLINKOBJECT = 0x40,
80 OLEMISC_INSIDEOUT = 0x80,
81 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
82 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
83 OLEMISC_INVISIBLEATRUNTIME = 0x400,
84 OLEMISC_ALWAYSRUN = 0x800,
85 OLEMISC_ACTSLIKEBUTTON = 0x1000,
86 OLEMISC_ACTSLIKELABEL = 0x2000,
87 OLEMISC_NOUIACTIVATE = 0x4000,
88 OLEMISC_ALIGNABLE = 0x8000,
89 OLEMISC_SIMPLEFRAME = 0x10000,
90 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
91 OLEMISC_IMEMODE = 0x40000,
92 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
93 OLEMISC_WANTSTOMENUMERGE = 0x100000,
94 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
95 } OLEMISC;
97 typedef struct
99 const WCHAR *ptr;
100 unsigned int len;
101 } xmlstr_t;
103 typedef struct
105 const WCHAR *ptr;
106 const WCHAR *end;
107 } xmlbuf_t;
109 struct file_info
111 ULONG type;
112 WCHAR *info;
115 struct assembly_version
117 USHORT major;
118 USHORT minor;
119 USHORT build;
120 USHORT revision;
123 struct assembly_identity
125 WCHAR *name;
126 WCHAR *arch;
127 WCHAR *public_key;
128 WCHAR *language;
129 WCHAR *type;
130 struct assembly_version version;
131 BOOL optional;
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;
504 enum context_sections
506 WINDOWCLASS_SECTION = 1,
507 DLLREDIRECT_SECTION = 2,
508 TLIBREDIRECT_SECTION = 4,
509 SERVERREDIRECT_SECTION = 8,
510 IFACEREDIRECT_SECTION = 16,
511 CLRSURROGATES_SECTION = 32,
512 PROGIDREDIRECT_SECTION = 64
515 typedef struct _ACTIVATION_CONTEXT
517 ULONG magic;
518 int ref_count;
519 struct file_info config;
520 struct file_info appdir;
521 struct assembly *assemblies;
522 unsigned int num_assemblies;
523 unsigned int allocated_assemblies;
524 /* section data */
525 DWORD sections;
526 struct strsection_header *wndclass_section;
527 struct strsection_header *dllredirect_section;
528 struct strsection_header *progid_section;
529 struct guidsection_header *tlib_section;
530 struct guidsection_header *comserver_section;
531 struct guidsection_header *ifaceps_section;
532 struct guidsection_header *clrsurrogate_section;
533 } ACTIVATION_CONTEXT;
535 struct actctx_loader
537 ACTIVATION_CONTEXT *actctx;
538 struct assembly_identity *dependencies;
539 unsigned int num_dependencies;
540 unsigned int allocated_dependencies;
543 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
544 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
545 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
546 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
547 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
548 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
549 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
550 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
551 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};
552 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};
553 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
554 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
555 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
556 static const WCHAR fileW[] = {'f','i','l','e',0};
557 static const WCHAR hashW[] = {'h','a','s','h',0};
558 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
559 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
560 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
561 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
563 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
564 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
565 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
566 static const WCHAR iidW[] = {'i','i','d',0};
567 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
568 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
569 static const WCHAR nameW[] = {'n','a','m','e',0};
570 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
571 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
572 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
573 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
574 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};
575 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
576 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
577 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
578 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
579 static const WCHAR typeW[] = {'t','y','p','e',0};
580 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
581 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
582 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
583 static const WCHAR yesW[] = {'y','e','s',0};
584 static const WCHAR noW[] = {'n','o',0};
585 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
586 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
587 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
588 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
589 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
590 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
591 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
592 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
593 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
594 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
595 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
596 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
597 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
598 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
599 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
600 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
602 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
603 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
604 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
605 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
606 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
607 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
608 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
609 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};
610 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
611 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
612 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
613 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
614 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
615 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
616 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
617 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
618 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};
619 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
620 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
621 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
622 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};
623 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
625 struct olemisc_entry
627 const WCHAR *name;
628 OLEMISC value;
631 static const struct olemisc_entry olemisc_values[] =
633 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
634 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
635 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
636 { alignableW, OLEMISC_ALIGNABLE },
637 { alwaysrunW, OLEMISC_ALWAYSRUN },
638 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
639 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
640 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
641 { imemodeW, OLEMISC_IMEMODE },
642 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
643 { insideoutW, OLEMISC_INSIDEOUT },
644 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
645 { islinkobjectW, OLEMISC_ISLINKOBJECT },
646 { nouiactivateW, OLEMISC_NOUIACTIVATE },
647 { onlyiconicW, OLEMISC_ONLYICONIC },
648 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
649 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
650 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
651 { simpleframeW, OLEMISC_SIMPLEFRAME },
652 { staticW, OLEMISC_STATIC },
653 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
654 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
657 static const WCHAR xmlW[] = {'?','x','m','l',0};
658 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};
659 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};
661 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
662 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
663 static const WCHAR wildcardW[] = {'*',0};
665 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
666 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
668 static WCHAR *strdupW(const WCHAR* str)
670 WCHAR* ptr;
672 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
673 return NULL;
674 return strcpyW(ptr, str);
677 static WCHAR *xmlstrdupW(const xmlstr_t* str)
679 WCHAR *strW;
681 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
683 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
684 strW[str->len] = 0;
686 return strW;
689 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
691 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
694 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
696 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
699 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
701 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
702 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
705 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
707 UINT len = strlenW( namespace );
709 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
710 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
711 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
714 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
716 if (elem->len && elem->ptr[0] == '/')
718 xmlstr_t elem_end;
719 elem_end.ptr = elem->ptr + 1;
720 elem_end.len = elem->len - 1;
721 return xml_elem_cmp( &elem_end, str, namespace );
723 return FALSE;
726 static inline BOOL isxmlspace( WCHAR ch )
728 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
731 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
733 return debugstr_wn(str->ptr, str->len);
736 static inline const char* debugstr_version(const struct assembly_version *ver)
738 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
741 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
743 struct assembly *assembly;
745 if (actctx->num_assemblies == actctx->allocated_assemblies)
747 void *ptr;
748 unsigned int new_count;
749 if (actctx->assemblies)
751 new_count = actctx->allocated_assemblies * 2;
752 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
753 actctx->assemblies, new_count * sizeof(*assembly) );
755 else
757 new_count = 4;
758 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
760 if (!ptr) return NULL;
761 actctx->assemblies = ptr;
762 actctx->allocated_assemblies = new_count;
765 assembly = &actctx->assemblies[actctx->num_assemblies++];
766 assembly->type = at;
767 return assembly;
770 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
772 if (assembly->num_dlls == assembly->allocated_dlls)
774 void *ptr;
775 unsigned int new_count;
776 if (assembly->dlls)
778 new_count = assembly->allocated_dlls * 2;
779 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
780 assembly->dlls, new_count * sizeof(*assembly->dlls) );
782 else
784 new_count = 4;
785 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
787 if (!ptr) return NULL;
788 assembly->dlls = ptr;
789 assembly->allocated_dlls = new_count;
791 return &assembly->dlls[assembly->num_dlls++];
794 static void free_assembly_identity(struct assembly_identity *ai)
796 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
797 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
798 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
799 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
800 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
803 static struct entity* add_entity(struct entity_array *array, DWORD kind)
805 struct entity* entity;
807 if (array->num == array->allocated)
809 void *ptr;
810 unsigned int new_count;
811 if (array->base)
813 new_count = array->allocated * 2;
814 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
815 array->base, new_count * sizeof(*array->base) );
817 else
819 new_count = 4;
820 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
822 if (!ptr) return NULL;
823 array->base = ptr;
824 array->allocated = new_count;
826 entity = &array->base[array->num++];
827 entity->kind = kind;
828 return entity;
831 static void free_entity_array(struct entity_array *array)
833 unsigned int i, j;
834 for (i = 0; i < array->num; i++)
836 struct entity *entity = &array->base[i];
837 switch (entity->kind)
839 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
840 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
841 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
842 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
843 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
844 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
845 for (j = 0; j < entity->u.comclass.progids.num; j++)
846 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
847 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
848 break;
849 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
850 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
851 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
852 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
853 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
854 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
855 break;
856 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
857 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
858 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
859 break;
860 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
861 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
862 break;
863 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
864 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
865 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
866 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
867 break;
868 default:
869 FIXME("Unknown entity kind %d\n", entity->kind);
872 RtlFreeHeap( GetProcessHeap(), 0, array->base );
875 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
877 if (!str1) return !str2;
878 return str2 && !strcmpiW( str1, str2 );
881 static BOOL is_matching_identity( const struct assembly_identity *id1,
882 const struct assembly_identity *id2 )
884 if (!is_matching_string( id1->name, id2->name )) return FALSE;
885 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
886 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
888 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
890 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
891 return FALSE;
893 if (id1->version.major != id2->version.major) return FALSE;
894 if (id1->version.minor != id2->version.minor) return FALSE;
895 if (id1->version.build > id2->version.build) return FALSE;
896 if (id1->version.build == id2->version.build &&
897 id1->version.revision > id2->version.revision) return FALSE;
898 return TRUE;
901 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
902 struct assembly_identity* ai)
904 unsigned int i;
906 /* check if we already have that assembly */
908 for (i = 0; i < acl->actctx->num_assemblies; i++)
909 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
911 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
912 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
913 ai->version.build, ai->version.revision );
914 return TRUE;
917 for (i = 0; i < acl->num_dependencies; i++)
918 if (is_matching_identity( ai, &acl->dependencies[i] ))
920 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
921 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
922 ai->version.build, ai->version.revision );
923 return TRUE;
926 if (acl->num_dependencies == acl->allocated_dependencies)
928 void *ptr;
929 unsigned int new_count;
930 if (acl->dependencies)
932 new_count = acl->allocated_dependencies * 2;
933 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
934 new_count * sizeof(acl->dependencies[0]));
936 else
938 new_count = 4;
939 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
941 if (!ptr) return FALSE;
942 acl->dependencies = ptr;
943 acl->allocated_dependencies = new_count;
945 acl->dependencies[acl->num_dependencies++] = *ai;
947 return TRUE;
950 static void free_depend_manifests(struct actctx_loader* acl)
952 unsigned int i;
953 for (i = 0; i < acl->num_dependencies; i++)
954 free_assembly_identity(&acl->dependencies[i]);
955 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
958 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
960 static const WCHAR undW[] = {'_',0};
961 static const WCHAR noneW[] = {'n','o','n','e',0};
962 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
964 const WCHAR *arch = ai->arch ? ai->arch : noneW;
965 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
966 const WCHAR *lang = ai->language ? ai->language : noneW;
967 const WCHAR *name = ai->name ? ai->name : noneW;
968 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
969 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
970 WCHAR *ret;
972 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
974 strcpyW( ret, arch );
975 strcatW( ret, undW );
976 strcatW( ret, name );
977 strcatW( ret, undW );
978 strcatW( ret, key );
979 strcatW( ret, undW );
980 sprintfW( ret + strlenW(ret), version_formatW,
981 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
982 strcatW( ret, undW );
983 strcatW( ret, lang );
984 strcatW( ret, undW );
985 strcatW( ret, mskeyW );
986 return ret;
989 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
991 WCHAR *p = buffer;
993 if (!str) return;
994 strcatW( buffer, prefix );
995 p += strlenW(p);
996 *p++ = '"';
997 strcpyW( p, str );
998 p += strlenW(p);
999 *p++ = '"';
1000 *p = 0;
1003 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1005 static const WCHAR archW[] =
1006 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1007 static const WCHAR public_keyW[] =
1008 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1009 static const WCHAR typeW[] =
1010 {',','t','y','p','e','=',0};
1011 static const WCHAR versionW[] =
1012 {',','v','e','r','s','i','o','n','=',0};
1014 WCHAR version[64], *ret;
1015 SIZE_T size = 0;
1017 sprintfW( version, version_formatW,
1018 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1019 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1020 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1021 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1022 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1023 size += strlenW(versionW) + strlenW(version) + 2;
1025 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1026 return NULL;
1028 if (ai->name) strcpyW( ret, ai->name );
1029 else *ret = 0;
1030 append_string( ret, archW, ai->arch );
1031 append_string( ret, public_keyW, ai->public_key );
1032 append_string( ret, typeW, ai->type );
1033 append_string( ret, versionW, version );
1034 return ret;
1037 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1039 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1041 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1042 __TRY
1044 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1046 __EXCEPT_PAGE_FAULT
1049 __ENDTRY
1050 return ret;
1053 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1055 interlocked_xchg_add( &actctx->ref_count, 1 );
1058 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1060 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1062 unsigned int i, j;
1064 for (i = 0; i < actctx->num_assemblies; i++)
1066 struct assembly *assembly = &actctx->assemblies[i];
1067 for (j = 0; j < assembly->num_dlls; j++)
1069 struct dll_redirect *dll = &assembly->dlls[j];
1070 free_entity_array( &dll->entities );
1071 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1072 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1074 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1077 free_entity_array( &assembly->entities );
1078 free_assembly_identity(&assembly->id);
1080 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1090 actctx->magic = 0;
1091 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1095 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1096 BOOL* error, BOOL* end)
1098 const WCHAR* ptr;
1100 *error = TRUE;
1102 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1103 xmlbuf->ptr++;
1105 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1107 if (*xmlbuf->ptr == '/')
1109 xmlbuf->ptr++;
1110 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1111 return FALSE;
1113 xmlbuf->ptr++;
1114 *end = TRUE;
1115 *error = FALSE;
1116 return FALSE;
1119 if (*xmlbuf->ptr == '>')
1121 xmlbuf->ptr++;
1122 *error = FALSE;
1123 return FALSE;
1126 ptr = xmlbuf->ptr;
1127 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1129 if (ptr == xmlbuf->end) return FALSE;
1131 name->ptr = xmlbuf->ptr;
1132 name->len = ptr-xmlbuf->ptr;
1133 xmlbuf->ptr = ptr;
1135 /* skip spaces before '=' */
1136 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1137 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1139 /* skip '=' itself */
1140 ptr++;
1141 if (ptr == xmlbuf->end) return FALSE;
1143 /* skip spaces after '=' */
1144 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1146 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1148 value->ptr = ++ptr;
1149 if (ptr == xmlbuf->end) return FALSE;
1151 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1152 if (!ptr)
1154 xmlbuf->ptr = xmlbuf->end;
1155 return FALSE;
1158 value->len = ptr - value->ptr;
1159 xmlbuf->ptr = ptr + 1;
1161 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1163 *error = FALSE;
1164 return TRUE;
1167 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1169 const WCHAR* ptr;
1171 for (;;)
1173 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1174 if (!ptr)
1176 xmlbuf->ptr = xmlbuf->end;
1177 return FALSE;
1179 ptr++;
1180 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1182 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1183 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1185 if (ptr + 3 > xmlbuf->end)
1187 xmlbuf->ptr = xmlbuf->end;
1188 return FALSE;
1190 xmlbuf->ptr = ptr + 3;
1192 else break;
1195 xmlbuf->ptr = ptr;
1196 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1197 ptr++;
1199 elem->ptr = xmlbuf->ptr;
1200 elem->len = ptr - xmlbuf->ptr;
1201 xmlbuf->ptr = ptr;
1202 return xmlbuf->ptr != xmlbuf->end;
1205 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1207 /* FIXME: parse attributes */
1208 const WCHAR *ptr;
1210 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1212 if (ptr[0] == '?' && ptr[1] == '>')
1214 xmlbuf->ptr = ptr + 2;
1215 return TRUE;
1218 return FALSE;
1221 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1223 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1225 if (!ptr) return FALSE;
1227 content->ptr = xmlbuf->ptr;
1228 content->len = ptr - xmlbuf->ptr;
1229 xmlbuf->ptr = ptr;
1231 return TRUE;
1234 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1236 unsigned int ver[4];
1237 unsigned int pos;
1238 const WCHAR *curr;
1240 /* major.minor.build.revision */
1241 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1242 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1244 if (*curr >= '0' && *curr <= '9')
1246 ver[pos] = ver[pos] * 10 + *curr - '0';
1247 if (ver[pos] >= 0x10000) goto error;
1249 else if (*curr == '.')
1251 if (++pos >= 4) goto error;
1253 else goto error;
1255 version->major = ver[0];
1256 version->minor = ver[1];
1257 version->build = ver[2];
1258 version->revision = ver[3];
1259 return TRUE;
1261 error:
1262 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1263 return FALSE;
1266 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1268 xmlstr_t elem;
1269 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1270 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1271 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1272 return FALSE;
1275 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1277 xmlstr_t attr_name, attr_value;
1278 BOOL error;
1280 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1282 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1283 debugstr_xmlstr(&attr_value));
1285 return !error;
1288 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1290 BOOL end = FALSE;
1291 return parse_expect_no_attr(xmlbuf, &end) && !end;
1294 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1296 xmlstr_t elem;
1297 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1298 if (!xml_elem_cmp_end(&elem, name, namespace))
1300 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1301 return FALSE;
1303 return parse_end_element(xmlbuf);
1306 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1308 xmlstr_t attr_name, attr_value, elem;
1309 BOOL end = FALSE, error, ret = TRUE;
1311 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1312 if(error || end) return end;
1314 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1316 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1317 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1318 break;
1319 else
1320 ret = parse_unknown_elem(xmlbuf, &elem);
1323 return ret && parse_end_element(xmlbuf);
1326 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1327 struct assembly_identity* ai)
1329 xmlstr_t attr_name, attr_value;
1330 BOOL end = FALSE, error;
1332 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1334 if (xmlstr_cmp(&attr_name, nameW))
1336 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1338 else if (xmlstr_cmp(&attr_name, typeW))
1340 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1342 else if (xmlstr_cmp(&attr_name, versionW))
1344 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1346 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1348 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1350 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1352 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1354 else if (xmlstr_cmp(&attr_name, languageW))
1356 WARN("Unsupported yet language attribute (%s)\n",
1357 debugstr_xmlstr(&attr_value));
1358 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1360 else
1362 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1363 debugstr_xmlstr(&attr_value));
1367 TRACE( "name=%s version=%s arch=%s\n",
1368 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1370 if (error || end) return end;
1371 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1374 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1376 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1377 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1378 static const WCHAR freeW[] = {'F','r','e','e',0};
1379 static const WCHAR bothW[] = {'B','o','t','h',0};
1381 if (value->len == 0) return ThreadingModel_No;
1382 if (xmlstr_cmp(value, apartW))
1383 return ThreadingModel_Apartment;
1384 else if (xmlstr_cmp(value, freeW))
1385 return ThreadingModel_Free;
1386 else if (xmlstr_cmp(value, bothW))
1387 return ThreadingModel_Both;
1388 else if (xmlstr_cmp(value, neutralW))
1389 return ThreadingModel_Neutral;
1390 else
1391 return ThreadingModel_No;
1394 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1396 int min, max;
1398 min = 0;
1399 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1401 while (min <= max)
1403 int n, c;
1405 n = (min+max)/2;
1407 c = strncmpW(olemisc_values[n].name, str, len);
1408 if (!c && !olemisc_values[n].name[len])
1409 return olemisc_values[n].value;
1411 if (c >= 0)
1412 max = n-1;
1413 else
1414 min = n+1;
1417 WARN("unknown flag %s\n", debugstr_wn(str, len));
1418 return 0;
1421 static DWORD parse_com_class_misc(const xmlstr_t *value)
1423 const WCHAR *str = value->ptr, *start;
1424 DWORD flags = 0;
1425 int i = 0;
1427 /* it's comma separated list of flags */
1428 while (i < value->len)
1430 start = str;
1431 while (*str != ',' && (i++ < value->len)) str++;
1433 flags |= get_olemisc_value(start, str-start);
1435 /* skip separator */
1436 str++;
1437 i++;
1440 return flags;
1443 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1445 struct progids *progids = &entity->u.comclass.progids;
1447 if (progids->allocated == 0)
1449 progids->allocated = 4;
1450 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1453 if (progids->allocated == progids->num)
1455 progids->allocated *= 2;
1456 progids->progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1459 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1460 progids->num++;
1462 return TRUE;
1465 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1467 xmlstr_t content;
1468 BOOL end = FALSE;
1470 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1471 return FALSE;
1473 if (!com_class_add_progid(&content, entity)) return FALSE;
1474 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1477 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1479 xmlstr_t elem, attr_name, attr_value;
1480 BOOL ret = TRUE, end = FALSE, error;
1481 struct entity* entity;
1483 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1484 return FALSE;
1486 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1488 if (xmlstr_cmp(&attr_name, clsidW))
1490 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1492 else if (xmlstr_cmp(&attr_name, progidW))
1494 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1496 else if (xmlstr_cmp(&attr_name, tlbidW))
1498 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1500 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1502 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1504 else if (xmlstr_cmp(&attr_name, miscstatusW))
1506 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1508 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1510 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1512 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1514 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1516 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1518 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1520 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1522 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1524 else if (xmlstr_cmp(&attr_name, descriptionW))
1526 /* not stored */
1528 else
1530 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1534 if (error) return FALSE;
1536 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1537 if (entity->u.comclass.progid)
1538 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1540 if (end) return TRUE;
1542 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1544 if (xmlstr_cmp_end(&elem, comClassW))
1546 ret = parse_end_element(xmlbuf);
1547 break;
1549 else if (xmlstr_cmp(&elem, progidW))
1551 ret = parse_com_class_progid(xmlbuf, entity);
1553 else
1555 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1556 ret = parse_unknown_elem(xmlbuf, &elem);
1560 if (entity->u.comclass.progids.num)
1561 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1563 return ret;
1566 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1568 const WCHAR *curr;
1569 ULONG num = 0;
1571 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1573 if (*curr >= '0' && *curr <= '9')
1574 num = num * 10 + *curr - '0';
1575 else
1577 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1578 return FALSE;
1581 entity->u.ifaceps.nummethods = num;
1583 return TRUE;
1586 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1588 xmlstr_t attr_name, attr_value;
1589 BOOL end = FALSE, error;
1590 struct entity* entity;
1592 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1593 return FALSE;
1595 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1597 if (xmlstr_cmp(&attr_name, iidW))
1599 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1601 else if (xmlstr_cmp(&attr_name, nameW))
1603 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1605 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1607 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1608 entity->u.ifaceps.mask |= BaseIface;
1610 else if (xmlstr_cmp(&attr_name, nummethodsW))
1612 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1613 entity->u.ifaceps.mask |= NumMethods;
1615 else if (xmlstr_cmp(&attr_name, tlbidW))
1617 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1619 /* not used */
1620 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1623 else
1625 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1629 if (error) return FALSE;
1630 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1631 if (end) return TRUE;
1633 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1636 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1638 WORD *flags = &entity->u.typelib.flags;
1639 const WCHAR *str = value->ptr, *start;
1640 int i = 0;
1642 *flags = 0;
1644 /* it's comma separated list of flags */
1645 while (i < value->len)
1647 start = str;
1648 while (*str != ',' && (i++ < value->len)) str++;
1650 if (!strncmpiW(start, restrictedW, str-start))
1651 *flags |= LIBFLAG_FRESTRICTED;
1652 else if (!strncmpiW(start, controlW, str-start))
1653 *flags |= LIBFLAG_FCONTROL;
1654 else if (!strncmpiW(start, hiddenW, str-start))
1655 *flags |= LIBFLAG_FHIDDEN;
1656 else if (!strncmpiW(start, hasdiskimageW, str-start))
1657 *flags |= LIBFLAG_FHASDISKIMAGE;
1658 else
1660 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1661 return FALSE;
1664 /* skip separator */
1665 str++;
1666 i++;
1669 return TRUE;
1672 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1674 unsigned int ver[2];
1675 unsigned int pos;
1676 const WCHAR *curr;
1678 /* major.minor */
1679 ver[0] = ver[1] = pos = 0;
1680 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1682 if (*curr >= '0' && *curr <= '9')
1684 ver[pos] = ver[pos] * 10 + *curr - '0';
1685 if (ver[pos] >= 0x10000) goto error;
1687 else if (*curr == '.')
1689 if (++pos >= 2) goto error;
1691 else goto error;
1693 entity->u.typelib.major = ver[0];
1694 entity->u.typelib.minor = ver[1];
1695 return TRUE;
1697 error:
1698 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1699 return FALSE;
1702 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1704 xmlstr_t attr_name, attr_value;
1705 BOOL end = FALSE, error;
1706 struct entity* entity;
1708 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1709 return FALSE;
1711 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1713 if (xmlstr_cmp(&attr_name, tlbidW))
1715 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1717 else if (xmlstr_cmp(&attr_name, versionW))
1719 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1721 else if (xmlstr_cmp(&attr_name, helpdirW))
1723 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1725 else if (xmlstr_cmp(&attr_name, flagsW))
1727 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1729 else
1731 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1735 if (error) return FALSE;
1737 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1739 if (end) return TRUE;
1741 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1744 static inline int aligned_string_len(int len)
1746 return (len + 3) & ~3;
1749 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1751 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1752 struct assembly_version *ver = &assembly->id.version;
1753 WCHAR buff[25];
1755 if (!ret) ret = buff;
1756 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1759 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1761 xmlstr_t elem, content, attr_name, attr_value;
1762 BOOL end = FALSE, ret = TRUE, error;
1763 struct entity* entity;
1765 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1766 return FALSE;
1768 entity->u.class.versioned = TRUE;
1769 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1771 if (xmlstr_cmp(&attr_name, versionedW))
1773 if (xmlstr_cmpi(&attr_value, noW))
1774 entity->u.class.versioned = FALSE;
1775 else if (!xmlstr_cmpi(&attr_value, yesW))
1776 return FALSE;
1778 else
1780 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1784 if (error || end) return end;
1786 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1788 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1790 acl->actctx->sections |= WINDOWCLASS_SECTION;
1792 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1794 if (xmlstr_cmp_end(&elem, windowClassW))
1796 ret = parse_end_element(xmlbuf);
1797 break;
1799 else
1801 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1802 ret = parse_unknown_elem(xmlbuf, &elem);
1806 return ret;
1809 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1811 xmlstr_t attr_name, attr_value;
1812 BOOL end = FALSE, error;
1814 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1816 if (xmlstr_cmp(&attr_name, oldVersionW))
1818 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1820 else if (xmlstr_cmp(&attr_name, newVersionW))
1822 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1824 else
1826 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1830 if (error || end) return end;
1831 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1834 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1836 xmlstr_t elem, content;
1837 BOOL end = FALSE, ret = TRUE;
1839 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
1840 !parse_text_content(xmlbuf, &content))
1841 return FALSE;
1843 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1845 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1847 if (xmlstr_cmp_end(&elem, descriptionW))
1849 ret = parse_end_element(xmlbuf);
1850 break;
1852 else
1854 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1855 ret = parse_unknown_elem(xmlbuf, &elem);
1859 return ret;
1862 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1863 struct assembly* assembly,
1864 struct actctx_loader* acl)
1866 xmlstr_t attr_name, attr_value;
1867 BOOL end = FALSE, error;
1868 struct entity* entity;
1870 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1871 if (!entity) return FALSE;
1873 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1875 if (xmlstr_cmp(&attr_name, iidW))
1877 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1879 else if (xmlstr_cmp(&attr_name, nameW))
1881 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1883 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1885 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1886 entity->u.ifaceps.mask |= BaseIface;
1888 else if (xmlstr_cmp(&attr_name, nummethodsW))
1890 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1891 entity->u.ifaceps.mask |= NumMethods;
1893 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1895 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1897 else if (xmlstr_cmp(&attr_name, tlbidW))
1899 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1901 else
1903 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1907 if (error) return FALSE;
1908 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1909 if (end) return TRUE;
1911 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1914 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1916 xmlstr_t attr_name, attr_value, elem;
1917 BOOL end = FALSE, error, ret = TRUE;
1918 struct entity* entity;
1920 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1921 if (!entity) return FALSE;
1923 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1925 if (xmlstr_cmp(&attr_name, nameW))
1927 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1929 else if (xmlstr_cmp(&attr_name, clsidW))
1931 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1933 else if (xmlstr_cmp(&attr_name, progidW))
1935 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1937 else if (xmlstr_cmp(&attr_name, tlbidW))
1939 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1941 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1943 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1945 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1947 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1949 else
1951 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1955 if (error) return FALSE;
1956 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1957 if (entity->u.comclass.progid)
1958 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1959 if (end) return TRUE;
1961 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1963 if (xmlstr_cmp_end(&elem, clrClassW))
1965 ret = parse_end_element(xmlbuf);
1966 break;
1968 else if (xmlstr_cmp(&elem, progidW))
1970 ret = parse_com_class_progid(xmlbuf, entity);
1972 else
1974 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1975 ret = parse_unknown_elem(xmlbuf, &elem);
1979 if (entity->u.comclass.progids.num)
1980 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1982 return ret;
1985 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1987 xmlstr_t attr_name, attr_value;
1988 BOOL end = FALSE, error;
1989 struct entity* entity;
1991 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1992 if (!entity) return FALSE;
1994 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1996 if (xmlstr_cmp(&attr_name, nameW))
1998 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2000 else if (xmlstr_cmp(&attr_name, clsidW))
2002 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2004 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2006 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2008 else
2010 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2014 if (error) return FALSE;
2015 acl->actctx->sections |= CLRSURROGATES_SECTION;
2016 if (end) return TRUE;
2018 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2021 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2023 struct assembly_identity ai;
2024 xmlstr_t elem;
2025 BOOL end = FALSE, ret = TRUE;
2027 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
2029 memset(&ai, 0, sizeof(ai));
2030 ai.optional = optional;
2032 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2033 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2034 return FALSE;
2036 TRACE( "adding name=%s version=%s arch=%s\n",
2037 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2039 /* store the newly found identity for later loading */
2040 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2042 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2044 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2046 ret = parse_end_element(xmlbuf);
2047 break;
2049 else if (xmlstr_cmp(&elem, bindingRedirectW))
2051 ret = parse_binding_redirect_elem(xmlbuf);
2053 else
2055 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2056 ret = parse_unknown_elem(xmlbuf, &elem);
2060 return ret;
2063 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2065 xmlstr_t attr_name, attr_value, elem;
2066 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2068 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2070 if (xmlstr_cmp(&attr_name, optionalW))
2072 optional = xmlstr_cmpi( &attr_value, yesW );
2073 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2075 else
2077 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2081 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2083 if (xmlstr_cmp_end(&elem, dependencyW))
2085 ret = parse_end_element(xmlbuf);
2086 break;
2088 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2090 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2092 else
2094 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2095 ret = parse_unknown_elem(xmlbuf, &elem);
2099 return ret;
2102 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2104 BOOL end = FALSE;
2106 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2107 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2110 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2112 BOOL end = FALSE;
2114 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2115 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2118 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2120 xmlstr_t attr_name, attr_value, elem;
2121 BOOL end = FALSE, error, ret = TRUE;
2122 struct dll_redirect* dll;
2124 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2126 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2128 if (xmlstr_cmp(&attr_name, nameW))
2130 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2131 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2133 else if (xmlstr_cmp(&attr_name, hashW))
2135 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2137 else if (xmlstr_cmp(&attr_name, hashalgW))
2139 static const WCHAR sha1W[] = {'S','H','A','1',0};
2140 if (!xmlstr_cmpi(&attr_value, sha1W))
2141 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2143 else
2145 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2149 if (error || !dll->name) return FALSE;
2151 acl->actctx->sections |= DLLREDIRECT_SECTION;
2153 if (end) return TRUE;
2155 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2157 if (xmlstr_cmp_end(&elem, fileW))
2159 ret = parse_end_element(xmlbuf);
2160 break;
2162 else if (xmlstr_cmp(&elem, comClassW))
2164 ret = parse_com_class_elem(xmlbuf, dll, acl);
2166 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2168 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2170 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2172 WARN("asmv2:hash (undocumented) not supported\n");
2173 ret = parse_unknown_elem(xmlbuf, &elem);
2175 else if (xmlstr_cmp(&elem, typelibW))
2177 ret = parse_typelib_elem(xmlbuf, dll, acl);
2179 else if (xmlstr_cmp(&elem, windowClassW))
2181 ret = parse_window_class_elem(xmlbuf, dll, acl);
2183 else
2185 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2186 ret = parse_unknown_elem( xmlbuf, &elem );
2190 return ret;
2193 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2194 struct assembly* assembly,
2195 struct assembly_identity* expected_ai)
2197 xmlstr_t attr_name, attr_value, elem;
2198 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2200 TRACE("(%p)\n", xmlbuf);
2202 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2204 if (xmlstr_cmp(&attr_name, manifestVersionW))
2206 static const WCHAR v10W[] = {'1','.','0',0};
2207 if (!xmlstr_cmp(&attr_value, v10W))
2209 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2210 return FALSE;
2212 version = TRUE;
2214 else if (xmlstr_cmp(&attr_name, xmlnsW))
2216 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
2218 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2219 return FALSE;
2221 xmlns = TRUE;
2223 else
2225 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2229 if (error || end || !xmlns || !version) return FALSE;
2230 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2232 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2234 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2235 return FALSE;
2236 assembly->no_inherit = TRUE;
2239 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2241 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2242 return FALSE;
2244 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2245 assembly->no_inherit)
2246 return FALSE;
2248 while (ret)
2250 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2252 ret = parse_end_element(xmlbuf);
2253 break;
2255 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2257 ret = parse_description_elem(xmlbuf);
2259 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2261 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2263 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2265 ret = parse_dependency_elem(xmlbuf, acl);
2267 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2269 ret = parse_file_elem(xmlbuf, assembly, acl);
2271 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2273 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2275 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2277 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2279 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2281 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2283 if (expected_ai)
2285 /* FIXME: more tests */
2286 if (assembly->type == ASSEMBLY_MANIFEST &&
2287 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2289 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2290 expected_ai->version.major, expected_ai->version.minor,
2291 expected_ai->version.build, expected_ai->version.revision,
2292 assembly->id.version.major, assembly->id.version.minor,
2293 assembly->id.version.build, assembly->id.version.revision);
2294 ret = FALSE;
2296 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2297 (assembly->id.version.major != expected_ai->version.major ||
2298 assembly->id.version.minor != expected_ai->version.minor ||
2299 assembly->id.version.build < expected_ai->version.build ||
2300 (assembly->id.version.build == expected_ai->version.build &&
2301 assembly->id.version.revision < expected_ai->version.revision)))
2303 FIXME("wrong version for shared assembly manifest\n");
2304 ret = FALSE;
2308 else
2310 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2311 ret = parse_unknown_elem(xmlbuf, &elem);
2313 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2316 return ret;
2319 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2320 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2322 xmlstr_t elem;
2324 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2326 if (xmlstr_cmp(&elem, xmlW) &&
2327 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2328 return STATUS_SXS_CANT_GEN_ACTCTX;
2330 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2332 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2333 return STATUS_SXS_CANT_GEN_ACTCTX;
2336 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2338 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2339 return STATUS_SXS_CANT_GEN_ACTCTX;
2342 if (next_xml_elem(xmlbuf, &elem))
2344 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2345 return STATUS_SXS_CANT_GEN_ACTCTX;
2348 if (xmlbuf->ptr != xmlbuf->end)
2350 FIXME("parse error\n");
2351 return STATUS_SXS_CANT_GEN_ACTCTX;
2353 return STATUS_SUCCESS;
2356 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2357 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2358 const void *buffer, SIZE_T size )
2360 xmlbuf_t xmlbuf;
2361 NTSTATUS status;
2362 struct assembly *assembly;
2363 int unicode_tests;
2365 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2367 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2368 return STATUS_SXS_CANT_GEN_ACTCTX;
2370 if (directory && !(assembly->directory = strdupW(directory)))
2371 return STATUS_NO_MEMORY;
2373 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2374 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2375 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2377 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2378 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2380 xmlbuf.ptr = buffer;
2381 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2382 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2384 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2386 const WCHAR *buf = buffer;
2387 WCHAR *new_buff;
2388 unsigned int i;
2390 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2391 return STATUS_NO_MEMORY;
2392 for (i = 0; i < size / sizeof(WCHAR); i++)
2393 new_buff[i] = RtlUshortByteSwap( buf[i] );
2394 xmlbuf.ptr = new_buff;
2395 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2396 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2397 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2399 else
2401 /* let's assume utf-8 for now */
2402 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2403 WCHAR *new_buff;
2405 if (len == -1)
2407 FIXME( "utf-8 conversion failed\n" );
2408 return STATUS_SXS_CANT_GEN_ACTCTX;
2410 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2411 return STATUS_NO_MEMORY;
2412 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2413 xmlbuf.ptr = new_buff;
2414 xmlbuf.end = xmlbuf.ptr + len;
2415 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2416 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2418 return status;
2421 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2423 OBJECT_ATTRIBUTES attr;
2424 IO_STATUS_BLOCK io;
2426 attr.Length = sizeof(attr);
2427 attr.RootDirectory = 0;
2428 attr.Attributes = OBJ_CASE_INSENSITIVE;
2429 attr.ObjectName = name;
2430 attr.SecurityDescriptor = NULL;
2431 attr.SecurityQualityOfService = NULL;
2432 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2435 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2437 NTSTATUS status;
2438 ULONG_PTR magic;
2439 LDR_MODULE *pldr;
2441 LdrLockLoaderLock(0, NULL, &magic);
2442 status = LdrFindEntryForAddress( module, &pldr );
2443 if (status == STATUS_SUCCESS)
2445 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2446 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2448 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2449 str->Length = pldr->FullDllName.Length;
2450 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2452 else status = STATUS_NO_MEMORY;
2454 LdrUnlockLoaderLock(0, magic);
2455 return status;
2458 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2459 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2460 HANDLE hModule, LPCWSTR resname, ULONG lang )
2462 NTSTATUS status;
2463 UNICODE_STRING nameW;
2464 LDR_RESOURCE_INFO info;
2465 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2466 void *ptr;
2468 if (TRACE_ON(actctx))
2470 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2472 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2473 hModule, debugstr_w(nameW.Buffer) );
2474 RtlFreeUnicodeString( &nameW );
2476 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2477 hModule, debugstr_w(filename) );
2480 if (!resname) return STATUS_INVALID_PARAMETER;
2482 info.Type = RT_MANIFEST;
2483 info.Language = lang;
2484 if (!((ULONG_PTR)resname >> 16))
2486 info.Name = (ULONG_PTR)resname;
2487 status = LdrFindResource_U(hModule, &info, 3, &entry);
2489 else if (resname[0] == '#')
2491 ULONG value;
2492 RtlInitUnicodeString(&nameW, resname + 1);
2493 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2494 return STATUS_INVALID_PARAMETER;
2495 info.Name = value;
2496 status = LdrFindResource_U(hModule, &info, 3, &entry);
2498 else
2500 RtlCreateUnicodeString(&nameW, resname);
2501 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2502 info.Name = (ULONG_PTR)nameW.Buffer;
2503 status = LdrFindResource_U(hModule, &info, 3, &entry);
2504 RtlFreeUnicodeString(&nameW);
2506 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2508 if (status == STATUS_SUCCESS)
2509 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2511 return status;
2514 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2515 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2516 HANDLE file, LPCWSTR resname, ULONG lang )
2518 HANDLE mapping;
2519 OBJECT_ATTRIBUTES attr;
2520 LARGE_INTEGER size;
2521 LARGE_INTEGER offset;
2522 NTSTATUS status;
2523 SIZE_T count;
2524 void *base;
2526 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2528 attr.Length = sizeof(attr);
2529 attr.RootDirectory = 0;
2530 attr.ObjectName = NULL;
2531 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2532 attr.SecurityDescriptor = NULL;
2533 attr.SecurityQualityOfService = NULL;
2535 size.QuadPart = 0;
2536 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2537 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2538 if (status != STATUS_SUCCESS) return status;
2540 offset.QuadPart = 0;
2541 count = 0;
2542 base = NULL;
2543 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2544 &count, ViewShare, 0, PAGE_READONLY );
2545 NtClose( mapping );
2546 if (status != STATUS_SUCCESS) return status;
2548 if (RtlImageNtHeader(base)) /* we got a PE file */
2550 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2551 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2553 else status = STATUS_INVALID_IMAGE_FORMAT;
2555 NtUnmapViewOfSection( GetCurrentProcess(), base );
2556 return status;
2559 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2560 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2562 FILE_END_OF_FILE_INFORMATION info;
2563 IO_STATUS_BLOCK io;
2564 HANDLE mapping;
2565 OBJECT_ATTRIBUTES attr;
2566 LARGE_INTEGER size;
2567 LARGE_INTEGER offset;
2568 NTSTATUS status;
2569 SIZE_T count;
2570 void *base;
2572 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2574 attr.Length = sizeof(attr);
2575 attr.RootDirectory = 0;
2576 attr.ObjectName = NULL;
2577 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2578 attr.SecurityDescriptor = NULL;
2579 attr.SecurityQualityOfService = NULL;
2581 size.QuadPart = 0;
2582 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2583 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2584 if (status != STATUS_SUCCESS) return status;
2586 offset.QuadPart = 0;
2587 count = 0;
2588 base = NULL;
2589 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2590 &count, ViewShare, 0, PAGE_READONLY );
2591 NtClose( mapping );
2592 if (status != STATUS_SUCCESS) return status;
2594 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2595 if (status == STATUS_SUCCESS)
2596 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2598 NtUnmapViewOfSection( GetCurrentProcess(), base );
2599 return status;
2602 /* try to load the .manifest file associated to the file */
2603 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2604 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2606 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2607 WCHAR *buffer;
2608 NTSTATUS status;
2609 UNICODE_STRING nameW;
2610 HANDLE file;
2611 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2613 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2615 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2617 if (module) /* use the module filename */
2619 UNICODE_STRING name;
2621 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2623 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2624 strcatW( name.Buffer, dotManifestW );
2625 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2626 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2627 RtlFreeUnicodeString( &name );
2629 if (status) return status;
2631 else
2633 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2634 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2635 return STATUS_NO_MEMORY;
2636 strcpyW( buffer, filename );
2637 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2638 strcatW( buffer, dotManifestW );
2639 RtlInitUnicodeString( &nameW, buffer );
2642 if (!open_nt_file( &file, &nameW ))
2644 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2645 NtClose( file );
2647 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2648 RtlFreeUnicodeString( &nameW );
2649 return status;
2652 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2654 static const WCHAR lookup_fmtW[] =
2655 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2656 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2657 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2659 WCHAR *lookup, *ret = NULL;
2660 UNICODE_STRING lookup_us;
2661 IO_STATUS_BLOCK io;
2662 const WCHAR *lang = ai->language;
2663 unsigned int data_pos = 0, data_len;
2664 char buffer[8192];
2666 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2667 (strlenW(ai->arch) + strlenW(ai->name)
2668 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2669 + sizeof(lookup_fmtW) )))
2670 return NULL;
2672 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2673 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2674 ai->version.major, ai->version.minor, lang );
2675 RtlInitUnicodeString( &lookup_us, lookup );
2677 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2678 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2679 if (io.u.Status == STATUS_SUCCESS)
2681 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2682 FILE_BOTH_DIR_INFORMATION *dir_info;
2683 WCHAR *tmp;
2684 ULONG build, revision;
2686 data_len = io.Information;
2688 for (;;)
2690 if (data_pos >= data_len)
2692 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2693 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2694 if (io.u.Status != STATUS_SUCCESS) break;
2695 data_len = io.Information;
2696 data_pos = 0;
2698 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2700 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2701 else data_pos = data_len;
2703 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2704 build = atoiW(tmp);
2705 if (build < min_build) continue;
2706 tmp = strchrW(tmp, '.') + 1;
2707 revision = atoiW(tmp);
2708 if (build == min_build && revision < min_revision) continue;
2709 tmp = strchrW(tmp, '_') + 1;
2710 tmp = strchrW(tmp, '_') + 1;
2711 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2712 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2714 /* prefer a non-Wine manifest if we already have one */
2715 /* we'll still load the builtin dll if specified through DllOverrides */
2716 if (ret) continue;
2718 else
2720 min_build = build;
2721 min_revision = revision;
2723 ai->version.build = build;
2724 ai->version.revision = revision;
2725 RtlFreeHeap( GetProcessHeap(), 0, ret );
2726 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2728 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2729 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2733 else WARN("no matching file for %s\n", debugstr_w(lookup));
2734 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2735 return ret;
2738 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2740 struct assembly_identity sxs_ai;
2741 UNICODE_STRING path_us;
2742 OBJECT_ATTRIBUTES attr;
2743 IO_STATUS_BLOCK io;
2744 WCHAR *path, *file = NULL;
2745 HANDLE handle;
2747 static const WCHAR manifest_dirW[] =
2748 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2750 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2752 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2753 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2754 return STATUS_NO_MEMORY;
2756 strcpyW( path, user_shared_data->NtSystemRoot );
2757 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2759 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2761 RtlFreeHeap( GetProcessHeap(), 0, path );
2762 return STATUS_NO_SUCH_FILE;
2764 RtlFreeHeap( GetProcessHeap(), 0, path );
2766 attr.Length = sizeof(attr);
2767 attr.RootDirectory = 0;
2768 attr.Attributes = OBJ_CASE_INSENSITIVE;
2769 attr.ObjectName = &path_us;
2770 attr.SecurityDescriptor = NULL;
2771 attr.SecurityQualityOfService = NULL;
2773 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2774 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2776 sxs_ai = *ai;
2777 file = lookup_manifest_file( handle, &sxs_ai );
2778 NtClose( handle );
2780 if (!file)
2782 RtlFreeUnicodeString( &path_us );
2783 return STATUS_NO_SUCH_FILE;
2786 /* append file name to directory path */
2787 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2788 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2790 RtlFreeHeap( GetProcessHeap(), 0, file );
2791 RtlFreeUnicodeString( &path_us );
2792 return STATUS_NO_MEMORY;
2795 path[path_us.Length/sizeof(WCHAR)] = '\\';
2796 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2797 RtlInitUnicodeString( &path_us, path );
2798 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2800 if (!open_nt_file( &handle, &path_us ))
2802 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2803 NtClose( handle );
2805 else io.u.Status = STATUS_NO_SUCH_FILE;
2807 RtlFreeHeap( GetProcessHeap(), 0, file );
2808 RtlFreeUnicodeString( &path_us );
2809 return io.u.Status;
2812 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2813 struct assembly_identity* ai)
2815 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2816 unsigned int i;
2817 WCHAR *buffer, *p, *directory;
2818 NTSTATUS status;
2819 UNICODE_STRING nameW;
2820 HANDLE file;
2821 DWORD len;
2823 TRACE( "looking for name=%s version=%s arch=%s\n",
2824 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2826 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2828 /* FIXME: add support for language specific lookup */
2830 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2831 strlenW(acl->actctx->appdir.info));
2833 nameW.Buffer = NULL;
2834 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2835 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2836 return STATUS_NO_MEMORY;
2838 if (!(directory = build_assembly_dir( ai )))
2840 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2841 return STATUS_NO_MEMORY;
2844 /* Lookup in <dir>\name.dll
2845 * <dir>\name.manifest
2846 * <dir>\name\name.dll
2847 * <dir>\name\name.manifest
2849 * First 'appdir' is used as <dir>, if that failed
2850 * it tries application manifest file path.
2852 strcpyW( buffer, acl->actctx->appdir.info );
2853 p = buffer + strlenW(buffer);
2854 for (i = 0; i < 4; i++)
2856 if (i == 2)
2858 struct assembly *assembly = acl->actctx->assemblies;
2859 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
2861 else *p++ = '\\';
2863 strcpyW( p, ai->name );
2864 p += strlenW(p);
2866 strcpyW( p, dotDllW );
2867 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2869 status = open_nt_file( &file, &nameW );
2870 if (!status)
2872 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2873 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2874 NtClose( file );
2875 break;
2877 RtlFreeUnicodeString( &nameW );
2880 strcpyW( p, dotManifestW );
2881 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2883 status = open_nt_file( &file, &nameW );
2884 if (!status)
2886 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2887 NtClose( file );
2888 break;
2890 RtlFreeUnicodeString( &nameW );
2892 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2894 RtlFreeUnicodeString( &nameW );
2895 RtlFreeHeap( GetProcessHeap(), 0, directory );
2896 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2897 return status;
2900 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2902 NTSTATUS status = STATUS_SUCCESS;
2903 unsigned int i;
2905 for (i = 0; i < acl->num_dependencies; i++)
2907 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2909 if (!acl->dependencies[i].optional)
2911 FIXME( "Could not find dependent assembly %s (%s)\n",
2912 debugstr_w(acl->dependencies[i].name),
2913 debugstr_version(&acl->dependencies[i].version) );
2914 status = STATUS_SXS_CANT_GEN_ACTCTX;
2915 break;
2919 /* FIXME should now iterate through all refs */
2920 return status;
2923 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2924 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2926 NTSTATUS status = STATUS_SUCCESS;
2928 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2930 if (*handle) return STATUS_INVALID_PARAMETER;
2932 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2933 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2935 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2937 ULONG_PTR magic;
2938 LDR_MODULE *pldr;
2940 if (!*handle) return STATUS_INVALID_PARAMETER;
2942 LdrLockLoaderLock( 0, NULL, &magic );
2943 if (!LdrFindEntryForAddress( *handle, &pldr ))
2945 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2946 status = STATUS_DLL_NOT_FOUND;
2947 else
2948 *handle = pldr->ActivationContext;
2950 else status = STATUS_DLL_NOT_FOUND;
2951 LdrUnlockLoaderLock( 0, magic );
2953 else if (!*handle && (class != ActivationContextBasicInformation))
2954 *handle = process_actctx;
2956 return status;
2959 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2961 unsigned int i, j, total_len = 0, dll_count = 0;
2962 struct strsection_header *header;
2963 struct dllredirect_data *data;
2964 struct string_index *index;
2965 ULONG name_offset;
2967 /* compute section length */
2968 for (i = 0; i < actctx->num_assemblies; i++)
2970 struct assembly *assembly = &actctx->assemblies[i];
2971 for (j = 0; j < assembly->num_dlls; j++)
2973 struct dll_redirect *dll = &assembly->dlls[j];
2975 /* each entry needs index, data and string data */
2976 total_len += sizeof(*index);
2977 total_len += sizeof(*data);
2978 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
2981 dll_count += assembly->num_dlls;
2984 total_len += sizeof(*header);
2986 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
2987 if (!header) return STATUS_NO_MEMORY;
2989 memset(header, 0, sizeof(*header));
2990 header->magic = STRSECTION_MAGIC;
2991 header->size = sizeof(*header);
2992 header->count = dll_count;
2993 header->index_offset = sizeof(*header);
2994 index = (struct string_index*)((BYTE*)header + header->index_offset);
2995 name_offset = header->index_offset + header->count*sizeof(*index);
2997 for (i = 0; i < actctx->num_assemblies; i++)
2999 struct assembly *assembly = &actctx->assemblies[i];
3000 for (j = 0; j < assembly->num_dlls; j++)
3002 struct dll_redirect *dll = &assembly->dlls[j];
3003 UNICODE_STRING str;
3004 WCHAR *ptrW;
3006 /* setup new index entry */
3007 str.Buffer = dll->name;
3008 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3009 str.MaximumLength = str.Length + sizeof(WCHAR);
3010 /* hash original class name */
3011 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3013 index->name_offset = name_offset;
3014 index->name_len = str.Length;
3015 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3016 index->data_len = sizeof(*data);
3017 index->rosterindex = i + 1;
3019 /* setup data */
3020 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3021 data->size = sizeof(*data);
3022 data->unk = 2; /* FIXME: seems to be constant */
3023 memset(data->res, 0, sizeof(data->res));
3025 /* dll name */
3026 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3027 memcpy(ptrW, dll->name, index->name_len);
3028 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3030 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3032 index++;
3036 *section = header;
3038 return STATUS_SUCCESS;
3041 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3043 struct string_index *iter, *index = NULL;
3044 ULONG hash = 0, i;
3046 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3047 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3049 for (i = 0; i < section->count; i++)
3051 if (iter->hash == hash)
3053 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3055 if (!strcmpiW(nameW, name->Buffer))
3057 index = iter;
3058 break;
3060 else
3061 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3063 iter++;
3066 return index;
3069 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3071 struct guid_index *iter, *index = NULL;
3072 ULONG i;
3074 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3076 for (i = 0; i < section->count; i++)
3078 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3080 index = iter;
3081 break;
3083 iter++;
3086 return index;
3089 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3091 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3094 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3095 PACTCTX_SECTION_KEYED_DATA data)
3097 struct dllredirect_data *dll;
3098 struct string_index *index;
3100 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3102 if (!actctx->dllredirect_section)
3104 struct strsection_header *section;
3106 NTSTATUS status = build_dllredirect_section(actctx, &section);
3107 if (status) return status;
3109 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3110 RtlFreeHeap(GetProcessHeap(), 0, section);
3113 index = find_string_index(actctx->dllredirect_section, name);
3114 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3116 dll = get_dllredirect_data(actctx, index);
3118 data->ulDataFormatVersion = 1;
3119 data->lpData = dll;
3120 data->ulLength = dll->size;
3121 data->lpSectionGlobalData = NULL;
3122 data->ulSectionGlobalDataLength = 0;
3123 data->lpSectionBase = actctx->dllredirect_section;
3124 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3125 data->hActCtx = NULL;
3127 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3128 data->ulAssemblyRosterIndex = index->rosterindex;
3130 return STATUS_SUCCESS;
3133 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3135 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3138 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3140 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3143 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3145 unsigned int i, j, k, total_len = 0, class_count = 0;
3146 struct wndclass_redirect_data *data;
3147 struct strsection_header *header;
3148 struct string_index *index;
3149 ULONG name_offset;
3151 /* compute section length */
3152 for (i = 0; i < actctx->num_assemblies; i++)
3154 struct assembly *assembly = &actctx->assemblies[i];
3155 for (j = 0; j < assembly->num_dlls; j++)
3157 struct dll_redirect *dll = &assembly->dlls[j];
3158 for (k = 0; k < dll->entities.num; k++)
3160 struct entity *entity = &dll->entities.base[k];
3161 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3163 int class_len = strlenW(entity->u.class.name) + 1;
3164 int len;
3166 /* each class entry needs index, data and string data */
3167 total_len += sizeof(*index);
3168 total_len += sizeof(*data);
3169 /* original name is stored separately */
3170 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3171 /* versioned name and module name are stored one after another */
3172 if (entity->u.class.versioned)
3173 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3174 else
3175 len = class_len;
3176 len += strlenW(dll->name) + 1;
3177 total_len += aligned_string_len(len*sizeof(WCHAR));
3179 class_count++;
3185 total_len += sizeof(*header);
3187 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3188 if (!header) return STATUS_NO_MEMORY;
3190 memset(header, 0, sizeof(*header));
3191 header->magic = STRSECTION_MAGIC;
3192 header->size = sizeof(*header);
3193 header->count = class_count;
3194 header->index_offset = sizeof(*header);
3195 index = (struct string_index*)((BYTE*)header + header->index_offset);
3196 name_offset = header->index_offset + header->count*sizeof(*index);
3198 for (i = 0; i < actctx->num_assemblies; i++)
3200 struct assembly *assembly = &actctx->assemblies[i];
3201 for (j = 0; j < assembly->num_dlls; j++)
3203 struct dll_redirect *dll = &assembly->dlls[j];
3204 for (k = 0; k < dll->entities.num; k++)
3206 struct entity *entity = &dll->entities.base[k];
3207 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3209 static const WCHAR exclW[] = {'!',0};
3210 ULONG versioned_len, module_len;
3211 UNICODE_STRING str;
3212 WCHAR *ptrW;
3214 /* setup new index entry */
3215 str.Buffer = entity->u.class.name;
3216 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3217 str.MaximumLength = str.Length + sizeof(WCHAR);
3218 /* hash original class name */
3219 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3221 /* include '!' separator too */
3222 if (entity->u.class.versioned)
3223 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3224 else
3225 versioned_len = str.Length;
3226 module_len = strlenW(dll->name)*sizeof(WCHAR);
3228 index->name_offset = name_offset;
3229 index->name_len = str.Length;
3230 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3231 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3232 index->rosterindex = i + 1;
3234 /* setup data */
3235 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3236 data->size = sizeof(*data);
3237 data->res = 0;
3238 data->name_len = versioned_len;
3239 data->name_offset = sizeof(*data);
3240 data->module_len = module_len;
3241 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3243 /* original class name */
3244 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3245 memcpy(ptrW, entity->u.class.name, index->name_len);
3246 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3248 /* module name */
3249 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3250 memcpy(ptrW, dll->name, data->module_len);
3251 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3253 /* versioned name */
3254 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3255 if (entity->u.class.versioned)
3257 get_assembly_version(assembly, ptrW);
3258 strcatW(ptrW, exclW);
3259 strcatW(ptrW, entity->u.class.name);
3261 else
3263 memcpy(ptrW, entity->u.class.name, index->name_len);
3264 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3267 name_offset += sizeof(*data);
3268 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3270 index++;
3276 *section = header;
3278 return STATUS_SUCCESS;
3281 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3282 PACTCTX_SECTION_KEYED_DATA data)
3284 struct string_index *iter, *index = NULL;
3285 struct wndclass_redirect_data *class;
3286 ULONG hash;
3287 int i;
3289 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3291 if (!actctx->wndclass_section)
3293 struct strsection_header *section;
3295 NTSTATUS status = build_wndclass_section(actctx, &section);
3296 if (status) return status;
3298 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3299 RtlFreeHeap(GetProcessHeap(), 0, section);
3302 hash = 0;
3303 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3304 iter = get_wndclass_first_index(actctx);
3306 for (i = 0; i < actctx->wndclass_section->count; i++)
3308 if (iter->hash == hash)
3310 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3312 if (!strcmpW(nameW, name->Buffer))
3314 index = iter;
3315 break;
3317 else
3318 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3320 iter++;
3323 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3325 class = get_wndclass_data(actctx, index);
3327 data->ulDataFormatVersion = 1;
3328 data->lpData = class;
3329 /* full length includes string length with nulls */
3330 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3331 data->lpSectionGlobalData = NULL;
3332 data->ulSectionGlobalDataLength = 0;
3333 data->lpSectionBase = actctx->wndclass_section;
3334 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3335 data->hActCtx = NULL;
3337 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3338 data->ulAssemblyRosterIndex = index->rosterindex;
3340 return STATUS_SUCCESS;
3343 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3345 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3346 struct guidsection_header *header;
3347 ULONG module_offset, data_offset;
3348 struct tlibredirect_data *data;
3349 struct guid_index *index;
3351 /* compute section length */
3352 for (i = 0; i < actctx->num_assemblies; i++)
3354 struct assembly *assembly = &actctx->assemblies[i];
3355 for (j = 0; j < assembly->num_dlls; j++)
3357 struct dll_redirect *dll = &assembly->dlls[j];
3358 for (k = 0; k < dll->entities.num; k++)
3360 struct entity *entity = &dll->entities.base[k];
3361 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3363 /* each entry needs index, data and string data for module name and help string */
3364 total_len += sizeof(*index);
3365 total_len += sizeof(*data);
3366 /* help string is stored separately */
3367 if (*entity->u.typelib.helpdir)
3368 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3370 /* module names are packed one after another */
3371 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3373 tlib_count++;
3379 total_len += aligned_string_len(names_len);
3380 total_len += sizeof(*header);
3382 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3383 if (!header) return STATUS_NO_MEMORY;
3385 memset(header, 0, sizeof(*header));
3386 header->magic = GUIDSECTION_MAGIC;
3387 header->size = sizeof(*header);
3388 header->count = tlib_count;
3389 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3390 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3391 module_offset = sizeof(*header);
3392 data_offset = header->index_offset + tlib_count*sizeof(*index);
3394 for (i = 0; i < actctx->num_assemblies; i++)
3396 struct assembly *assembly = &actctx->assemblies[i];
3397 for (j = 0; j < assembly->num_dlls; j++)
3399 struct dll_redirect *dll = &assembly->dlls[j];
3400 for (k = 0; k < dll->entities.num; k++)
3402 struct entity *entity = &dll->entities.base[k];
3403 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3405 ULONG module_len, help_len;
3406 UNICODE_STRING str;
3407 WCHAR *ptrW;
3409 if (*entity->u.typelib.helpdir)
3410 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3411 else
3412 help_len = 0;
3414 module_len = strlenW(dll->name)*sizeof(WCHAR);
3416 /* setup new index entry */
3417 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3418 RtlGUIDFromString(&str, &index->guid);
3419 index->data_offset = data_offset;
3420 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3421 index->rosterindex = i + 1;
3423 /* setup data */
3424 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3425 data->size = sizeof(*data);
3426 data->res = 0;
3427 data->name_len = module_len;
3428 data->name_offset = module_offset;
3429 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3430 data->langid = 0;
3431 data->flags = entity->u.typelib.flags;
3432 data->help_len = help_len;
3433 data->help_offset = sizeof(*data);
3434 data->major_version = entity->u.typelib.major;
3435 data->minor_version = entity->u.typelib.minor;
3437 /* module name */
3438 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3439 memcpy(ptrW, dll->name, data->name_len);
3440 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3442 /* help string */
3443 if (data->help_len)
3445 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3446 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3447 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3450 data_offset += sizeof(*data);
3451 if (help_len)
3452 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3454 module_offset += module_len + sizeof(WCHAR);
3456 index++;
3462 *section = header;
3464 return STATUS_SUCCESS;
3467 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3469 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3472 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3474 struct guid_index *index = NULL;
3475 struct tlibredirect_data *tlib;
3477 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3479 if (!actctx->tlib_section)
3481 struct guidsection_header *section;
3483 NTSTATUS status = build_tlib_section(actctx, &section);
3484 if (status) return status;
3486 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3487 RtlFreeHeap(GetProcessHeap(), 0, section);
3490 index = find_guid_index(actctx->tlib_section, guid);
3491 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3493 tlib = get_tlib_data(actctx, index);
3495 data->ulDataFormatVersion = 1;
3496 data->lpData = tlib;
3497 /* full length includes string length with nulls */
3498 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3499 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3500 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3501 data->lpSectionBase = actctx->tlib_section;
3502 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3503 data->hActCtx = NULL;
3505 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3506 data->ulAssemblyRosterIndex = index->rosterindex;
3508 return STATUS_SUCCESS;
3511 static void generate_uuid(ULONG *seed, GUID *guid)
3513 ULONG *ptr = (ULONG*)guid;
3514 int i;
3516 /* GUID is 16 bytes long */
3517 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3518 *ptr = RtlUniform(seed);
3520 guid->Data3 &= 0x0fff;
3521 guid->Data3 |= (4 << 12);
3522 guid->Data4[0] &= 0x3f;
3523 guid->Data4[0] |= 0x80;
3526 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3527 unsigned int *count, unsigned int *len, unsigned int *module_len)
3529 unsigned int i;
3531 for (i = 0; i < entities->num; i++)
3533 struct entity *entity = &entities->base[i];
3534 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3536 /* each entry needs two index entries, extra one goes for alias GUID */
3537 *len += 2*sizeof(struct guid_index);
3538 /* To save some memory we don't allocated two data structures,
3539 instead alias index and normal index point to the same data structure. */
3540 *len += sizeof(struct comclassredirect_data);
3542 /* for clrClass store some more */
3543 if (entity->u.comclass.name)
3545 unsigned int str_len;
3547 /* all string data is stored together in aligned block */
3548 str_len = strlenW(entity->u.comclass.name)+1;
3549 if (entity->u.comclass.progid)
3550 str_len += strlenW(entity->u.comclass.progid)+1;
3551 if (entity->u.comclass.version)
3552 str_len += strlenW(entity->u.comclass.version)+1;
3554 *len += sizeof(struct clrclass_data);
3555 *len += aligned_string_len(str_len*sizeof(WCHAR));
3557 /* module name is forced to mscoree.dll, and stored two times with different case */
3558 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3560 else
3562 /* progid string is stored separately */
3563 if (entity->u.comclass.progid)
3564 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3566 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3569 *count += 1;
3574 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3575 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3576 ULONG *seed, ULONG rosterindex)
3578 unsigned int i;
3580 for (i = 0; i < entities->num; i++)
3582 struct entity *entity = &entities->base[i];
3583 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3585 ULONG module_len, progid_len, str_len = 0;
3586 struct comclassredirect_data *data;
3587 struct guid_index *alias_index;
3588 struct clrclass_data *clrdata;
3589 UNICODE_STRING str;
3590 WCHAR *ptrW;
3592 if (entity->u.comclass.progid)
3593 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3594 else
3595 progid_len = 0;
3597 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3599 /* setup new index entry */
3600 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3601 RtlGUIDFromString(&str, &(*index)->guid);
3603 (*index)->data_offset = *data_offset;
3604 (*index)->data_len = sizeof(*data); /* additional length added later */
3605 (*index)->rosterindex = rosterindex;
3607 /* Setup new index entry for alias guid. Alias index records are placed after
3608 normal records, so normal guids are hit first on search. Note that class count
3609 is doubled. */
3610 alias_index = (*index) + section->count/2;
3611 generate_uuid(seed, &alias_index->guid);
3612 alias_index->data_offset = (*index)->data_offset;
3613 alias_index->data_len = 0;
3614 alias_index->rosterindex = (*index)->rosterindex;
3616 /* setup data */
3617 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3618 data->size = sizeof(*data);
3619 data->res = 0;
3620 data->res1[0] = 0;
3621 data->res1[1] = 0;
3622 data->model = entity->u.comclass.model;
3623 data->clsid = (*index)->guid;
3624 data->alias = alias_index->guid;
3625 data->clsid2 = data->clsid;
3626 if (entity->u.comclass.tlbid)
3628 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3629 RtlGUIDFromString(&str, &data->tlbid);
3631 else
3632 memset(&data->tlbid, 0, sizeof(data->tlbid));
3633 data->name_len = module_len;
3634 data->name_offset = *module_offset;
3635 data->progid_len = progid_len;
3636 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3637 data->clrdata_len = 0; /* will be set later */
3638 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3639 data->miscstatus = entity->u.comclass.miscstatus;
3640 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3641 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3642 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3643 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3645 /* mask describes which misc* data is available */
3646 data->miscmask = 0;
3647 if (data->miscstatus)
3648 data->miscmask |= MiscStatus;
3649 if (data->miscstatuscontent)
3650 data->miscmask |= MiscStatusContent;
3651 if (data->miscstatusthumbnail)
3652 data->miscmask |= MiscStatusThumbnail;
3653 if (data->miscstatusicon)
3654 data->miscmask |= MiscStatusIcon;
3655 if (data->miscstatusdocprint)
3656 data->miscmask |= MiscStatusDocPrint;
3658 if (data->clrdata_offset)
3660 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3662 clrdata->size = sizeof(*clrdata);
3663 clrdata->res[0] = 0;
3664 clrdata->res[1] = 2; /* FIXME: unknown field */
3665 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3666 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3667 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3668 clrdata->name_offset = clrdata->size;
3669 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3670 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3671 clrdata->res2[0] = 0;
3672 clrdata->res2[1] = 0;
3674 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3676 /* module name */
3677 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3678 memcpy(ptrW, mscoree2W, clrdata->module_len);
3679 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3681 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3682 memcpy(ptrW, mscoreeW, data->name_len);
3683 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3685 /* class name */
3686 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3687 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3688 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3690 /* runtime version, optional */
3691 if (clrdata->version_len)
3693 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3695 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3696 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3697 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3700 if (data->progid_len)
3701 data->progid_offset += data->clrdata_len;
3702 (*index)->data_len += sizeof(*clrdata);
3704 else
3706 clrdata = NULL;
3708 /* module name */
3709 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3710 memcpy(ptrW, dll->name, data->name_len);
3711 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3714 /* progid string */
3715 if (data->progid_len)
3717 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3718 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3719 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3722 /* string block length */
3723 str_len = 0;
3724 if (clrdata)
3726 str_len += clrdata->name_len + sizeof(WCHAR);
3727 if (clrdata->version_len)
3728 str_len += clrdata->version_len + sizeof(WCHAR);
3730 if (progid_len)
3731 str_len += progid_len + sizeof(WCHAR);
3733 (*index)->data_len += aligned_string_len(str_len);
3734 alias_index->data_len = (*index)->data_len;
3736 /* move to next data record */
3737 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3738 (*module_offset) += module_len + sizeof(WCHAR);
3740 if (clrdata)
3742 (*data_offset) += sizeof(*clrdata);
3743 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3745 (*index) += 1;
3750 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3752 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3753 struct guidsection_header *header;
3754 ULONG module_offset, data_offset;
3755 struct guid_index *index;
3756 ULONG seed;
3758 /* compute section length */
3759 for (i = 0; i < actctx->num_assemblies; i++)
3761 struct assembly *assembly = &actctx->assemblies[i];
3762 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3763 for (j = 0; j < assembly->num_dlls; j++)
3765 struct dll_redirect *dll = &assembly->dlls[j];
3766 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3770 total_len += aligned_string_len(names_len);
3771 total_len += sizeof(*header);
3773 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3774 if (!header) return STATUS_NO_MEMORY;
3776 memset(header, 0, sizeof(*header));
3777 header->magic = GUIDSECTION_MAGIC;
3778 header->size = sizeof(*header);
3779 header->count = 2*class_count;
3780 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3781 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3782 module_offset = sizeof(*header);
3783 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3785 seed = NtGetTickCount();
3786 for (i = 0; i < actctx->num_assemblies; i++)
3788 struct assembly *assembly = &actctx->assemblies[i];
3789 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3790 for (j = 0; j < assembly->num_dlls; j++)
3792 struct dll_redirect *dll = &assembly->dlls[j];
3793 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3797 *section = header;
3799 return STATUS_SUCCESS;
3802 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3804 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3807 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3809 struct comclassredirect_data *comclass;
3810 struct guid_index *index = NULL;
3812 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3814 if (!actctx->comserver_section)
3816 struct guidsection_header *section;
3818 NTSTATUS status = build_comserver_section(actctx, &section);
3819 if (status) return status;
3821 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3822 RtlFreeHeap(GetProcessHeap(), 0, section);
3825 index = find_guid_index(actctx->comserver_section, guid);
3826 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3828 comclass = get_comclass_data(actctx, index);
3830 data->ulDataFormatVersion = 1;
3831 data->lpData = comclass;
3832 /* full length includes string length with nulls */
3833 data->ulLength = comclass->size + comclass->clrdata_len;
3834 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
3835 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3836 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3837 data->lpSectionBase = actctx->comserver_section;
3838 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3839 data->hActCtx = NULL;
3841 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3842 data->ulAssemblyRosterIndex = index->rosterindex;
3844 return STATUS_SUCCESS;
3847 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3849 unsigned int i;
3851 for (i = 0; i < entities->num; i++)
3853 struct entity *entity = &entities->base[i];
3854 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3856 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3857 if (entity->u.ifaceps.name)
3858 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3859 *count += 1;
3864 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3865 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3867 unsigned int i;
3869 for (i = 0; i < entities->num; i++)
3871 struct entity *entity = &entities->base[i];
3872 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3874 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3875 UNICODE_STRING str;
3876 ULONG name_len;
3878 if (entity->u.ifaceps.name)
3879 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3880 else
3881 name_len = 0;
3883 /* setup index */
3884 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3885 RtlGUIDFromString(&str, &(*index)->guid);
3886 (*index)->data_offset = *data_offset;
3887 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3888 (*index)->rosterindex = rosterindex;
3890 /* setup data record */
3891 data->size = sizeof(*data);
3892 data->mask = entity->u.ifaceps.mask;
3894 /* proxyStubClsid32 value is only stored for external PS,
3895 if set it's used as iid, otherwise 'iid' attribute value is used */
3896 if (entity->u.ifaceps.ps32)
3898 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3899 RtlGUIDFromString(&str, &data->iid);
3901 else
3902 data->iid = (*index)->guid;
3904 data->nummethods = entity->u.ifaceps.nummethods;
3906 if (entity->u.ifaceps.tlib)
3908 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3909 RtlGUIDFromString(&str, &data->tlbid);
3911 else
3912 memset(&data->tlbid, 0, sizeof(data->tlbid));
3914 if (entity->u.ifaceps.base)
3916 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3917 RtlGUIDFromString(&str, &data->base);
3919 else
3920 memset(&data->base, 0, sizeof(data->base));
3922 data->name_len = name_len;
3923 data->name_offset = data->name_len ? sizeof(*data) : 0;
3925 /* name string */
3926 if (data->name_len)
3928 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3929 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3930 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3933 /* move to next record */
3934 (*index) += 1;
3935 *data_offset += sizeof(*data);
3936 if (data->name_len)
3937 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3942 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3944 unsigned int i, j, total_len = 0, count = 0;
3945 struct guidsection_header *header;
3946 struct guid_index *index;
3947 ULONG data_offset;
3949 /* compute section length */
3950 for (i = 0; i < actctx->num_assemblies; i++)
3952 struct assembly *assembly = &actctx->assemblies[i];
3954 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3955 for (j = 0; j < assembly->num_dlls; j++)
3957 struct dll_redirect *dll = &assembly->dlls[j];
3958 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3962 total_len += sizeof(*header);
3964 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3965 if (!header) return STATUS_NO_MEMORY;
3967 memset(header, 0, sizeof(*header));
3968 header->magic = GUIDSECTION_MAGIC;
3969 header->size = sizeof(*header);
3970 header->count = count;
3971 header->index_offset = sizeof(*header);
3972 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3973 data_offset = header->index_offset + count*sizeof(*index);
3975 for (i = 0; i < actctx->num_assemblies; i++)
3977 struct assembly *assembly = &actctx->assemblies[i];
3979 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
3980 for (j = 0; j < assembly->num_dlls; j++)
3982 struct dll_redirect *dll = &assembly->dlls[j];
3983 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
3987 *section = header;
3989 return STATUS_SUCCESS;
3992 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3994 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
3997 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3999 struct ifacepsredirect_data *iface;
4000 struct guid_index *index = NULL;
4002 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4004 if (!actctx->ifaceps_section)
4006 struct guidsection_header *section;
4008 NTSTATUS status = build_ifaceps_section(actctx, &section);
4009 if (status) return status;
4011 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4012 RtlFreeHeap(GetProcessHeap(), 0, section);
4015 index = find_guid_index(actctx->ifaceps_section, guid);
4016 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4018 iface = get_ifaceps_data(actctx, index);
4020 data->ulDataFormatVersion = 1;
4021 data->lpData = iface;
4022 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4023 data->lpSectionGlobalData = NULL;
4024 data->ulSectionGlobalDataLength = 0;
4025 data->lpSectionBase = actctx->ifaceps_section;
4026 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4027 data->hActCtx = NULL;
4029 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4030 data->ulAssemblyRosterIndex = index->rosterindex;
4032 return STATUS_SUCCESS;
4035 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4037 unsigned int i, j, total_len = 0, count = 0;
4038 struct guidsection_header *header;
4039 struct clrsurrogate_data *data;
4040 struct guid_index *index;
4041 ULONG data_offset;
4043 /* compute section length */
4044 for (i = 0; i < actctx->num_assemblies; i++)
4046 struct assembly *assembly = &actctx->assemblies[i];
4047 for (j = 0; j < assembly->entities.num; j++)
4049 struct entity *entity = &assembly->entities.base[j];
4050 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4052 ULONG len;
4054 total_len += sizeof(*index) + sizeof(*data);
4055 len = strlenW(entity->u.clrsurrogate.name) + 1;
4056 if (entity->u.clrsurrogate.version)
4057 len += strlenW(entity->u.clrsurrogate.version) + 1;
4058 total_len += aligned_string_len(len*sizeof(WCHAR));
4060 count++;
4065 total_len += sizeof(*header);
4067 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4068 if (!header) return STATUS_NO_MEMORY;
4070 memset(header, 0, sizeof(*header));
4071 header->magic = GUIDSECTION_MAGIC;
4072 header->size = sizeof(*header);
4073 header->count = count;
4074 header->index_offset = sizeof(*header);
4075 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4076 data_offset = header->index_offset + count*sizeof(*index);
4078 for (i = 0; i < actctx->num_assemblies; i++)
4080 struct assembly *assembly = &actctx->assemblies[i];
4081 for (j = 0; j < assembly->entities.num; j++)
4083 struct entity *entity = &assembly->entities.base[j];
4084 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4086 ULONG version_len, name_len;
4087 UNICODE_STRING str;
4088 WCHAR *ptrW;
4090 if (entity->u.clrsurrogate.version)
4091 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4092 else
4093 version_len = 0;
4094 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4096 /* setup new index entry */
4097 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4098 RtlGUIDFromString(&str, &index->guid);
4100 index->data_offset = data_offset;
4101 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4102 index->rosterindex = i + 1;
4104 /* setup data */
4105 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4106 data->size = sizeof(*data);
4107 data->res = 0;
4108 data->clsid = index->guid;
4109 data->version_offset = version_len ? data->size : 0;
4110 data->version_len = version_len;
4111 data->name_offset = data->size + version_len;
4112 if (version_len)
4113 data->name_offset += sizeof(WCHAR);
4114 data->name_len = name_len;
4116 /* surrogate name */
4117 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4118 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4119 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4121 /* runtime version */
4122 if (data->version_len)
4124 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4125 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4126 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4129 data_offset += index->data_offset;
4130 index++;
4135 *section = header;
4137 return STATUS_SUCCESS;
4140 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4142 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4145 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4147 struct clrsurrogate_data *surrogate;
4148 struct guid_index *index = NULL;
4150 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4152 if (!actctx->clrsurrogate_section)
4154 struct guidsection_header *section;
4156 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4157 if (status) return status;
4159 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4160 RtlFreeHeap(GetProcessHeap(), 0, section);
4163 index = find_guid_index(actctx->clrsurrogate_section, guid);
4164 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4166 surrogate = get_surrogate_data(actctx, index);
4168 data->ulDataFormatVersion = 1;
4169 data->lpData = surrogate;
4170 /* full length includes string length with nulls */
4171 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4172 if (surrogate->version_len)
4173 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4175 data->lpSectionGlobalData = NULL;
4176 data->ulSectionGlobalDataLength = 0;
4177 data->lpSectionBase = actctx->clrsurrogate_section;
4178 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4179 data->hActCtx = NULL;
4181 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4182 data->ulAssemblyRosterIndex = index->rosterindex;
4184 return STATUS_SUCCESS;
4187 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4189 unsigned int i, j, single_len;
4191 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4192 for (i = 0; i < entities->num; i++)
4194 struct entity *entity = &entities->base[i];
4195 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4197 if (entity->u.comclass.progid)
4199 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4200 *count += 1;
4203 for (j = 0; j < entity->u.comclass.progids.num; j++)
4204 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4206 *total_len += single_len*entity->u.comclass.progids.num;
4207 *count += entity->u.comclass.progids.num;
4212 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4213 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4215 struct progidredirect_data *data;
4216 UNICODE_STRING str;
4217 GUID *guid_ptr;
4218 WCHAR *ptrW;
4220 /* setup new index entry */
4222 /* hash progid name */
4223 RtlInitUnicodeString(&str, progid);
4224 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4226 (*index)->name_offset = *data_offset;
4227 (*index)->name_len = str.Length;
4228 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4229 (*index)->data_len = sizeof(*data);
4230 (*index)->rosterindex = rosterindex;
4232 *data_offset += aligned_string_len(str.MaximumLength);
4234 /* setup data structure */
4235 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4236 data->size = sizeof(*data);
4237 data->reserved = 0;
4238 data->clsid_offset = *global_offset;
4240 /* write progid string */
4241 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4242 memcpy(ptrW, progid, (*index)->name_len);
4243 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4245 /* write guid to global area */
4246 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4247 *guid_ptr = *alias;
4249 /* to next entry */
4250 *global_offset += sizeof(GUID);
4251 *data_offset += data->size;
4252 (*index) += 1;
4255 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4256 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4258 unsigned int i, j;
4260 for (i = 0; i < entities->num; i++)
4262 struct entity *entity = &entities->base[i];
4263 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4265 const struct progids *progids = &entity->u.comclass.progids;
4266 struct comclassredirect_data *comclass;
4267 struct guid_index *guid_index;
4268 UNICODE_STRING str;
4269 GUID clsid;
4271 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4272 RtlGUIDFromString(&str, &clsid);
4274 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4275 comclass = get_comclass_data(actctx, guid_index);
4277 if (entity->u.comclass.progid)
4278 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4279 index, data_offset, global_offset, rosterindex);
4281 for (j = 0; j < progids->num; j++)
4282 write_progid_record(section, progids->progids[j], &comclass->alias,
4283 index, data_offset, global_offset, rosterindex);
4288 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4290 unsigned int i, j, total_len = 0, count = 0;
4291 struct strsection_header *header;
4292 ULONG data_offset, global_offset;
4293 struct string_index *index;
4295 /* compute section length */
4296 for (i = 0; i < actctx->num_assemblies; i++)
4298 struct assembly *assembly = &actctx->assemblies[i];
4300 get_progid_datalen(&assembly->entities, &count, &total_len);
4301 for (j = 0; j < assembly->num_dlls; j++)
4303 struct dll_redirect *dll = &assembly->dlls[j];
4304 get_progid_datalen(&dll->entities, &count, &total_len);
4308 total_len += sizeof(*header);
4310 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4311 if (!header) return STATUS_NO_MEMORY;
4313 memset(header, 0, sizeof(*header));
4314 header->magic = STRSECTION_MAGIC;
4315 header->size = sizeof(*header);
4316 header->count = count;
4317 header->global_offset = header->size;
4318 header->global_len = count*sizeof(GUID);
4319 header->index_offset = header->size + header->global_len;
4321 index = (struct string_index*)((BYTE*)header + header->index_offset);
4322 data_offset = header->index_offset + count*sizeof(*index);
4323 global_offset = header->global_offset;
4325 for (i = 0; i < actctx->num_assemblies; i++)
4327 struct assembly *assembly = &actctx->assemblies[i];
4329 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4330 for (j = 0; j < assembly->num_dlls; j++)
4332 struct dll_redirect *dll = &assembly->dlls[j];
4333 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4337 *section = header;
4339 return STATUS_SUCCESS;
4342 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4344 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4347 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4348 PACTCTX_SECTION_KEYED_DATA data)
4350 struct progidredirect_data *progid;
4351 struct string_index *index;
4353 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4355 if (!actctx->comserver_section)
4357 struct guidsection_header *section;
4359 NTSTATUS status = build_comserver_section(actctx, &section);
4360 if (status) return status;
4362 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4363 RtlFreeHeap(GetProcessHeap(), 0, section);
4366 if (!actctx->progid_section)
4368 struct strsection_header *section;
4370 NTSTATUS status = build_progid_section(actctx, &section);
4371 if (status) return status;
4373 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4374 RtlFreeHeap(GetProcessHeap(), 0, section);
4377 index = find_string_index(actctx->progid_section, name);
4378 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4380 progid = get_progid_data(actctx, index);
4382 data->ulDataFormatVersion = 1;
4383 data->lpData = progid;
4384 data->ulLength = progid->size;
4385 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4386 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4387 data->lpSectionBase = actctx->progid_section;
4388 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4389 data->hActCtx = NULL;
4391 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4392 data->ulAssemblyRosterIndex = index->rosterindex;
4394 return STATUS_SUCCESS;
4397 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4398 const UNICODE_STRING *section_name,
4399 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4401 NTSTATUS status;
4403 switch (section_kind)
4405 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4406 status = find_dll_redirection(actctx, section_name, data);
4407 break;
4408 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4409 status = find_window_class(actctx, section_name, data);
4410 break;
4411 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4412 status = find_progid_redirection(actctx, section_name, data);
4413 break;
4414 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4415 FIXME("Unsupported yet section_kind %x\n", section_kind);
4416 return STATUS_SXS_SECTION_NOT_FOUND;
4417 default:
4418 WARN("Unknown section_kind %x\n", section_kind);
4419 return STATUS_SXS_SECTION_NOT_FOUND;
4422 if (status != STATUS_SUCCESS) return status;
4424 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4426 actctx_addref(actctx);
4427 data->hActCtx = actctx;
4429 return STATUS_SUCCESS;
4432 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4433 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4435 NTSTATUS status;
4437 switch (section_kind)
4439 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4440 status = find_tlib_redirection(actctx, guid, data);
4441 break;
4442 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4443 status = find_comserver_redirection(actctx, guid, data);
4444 break;
4445 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4446 status = find_cominterface_redirection(actctx, guid, data);
4447 break;
4448 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4449 status = find_clr_surrogate(actctx, guid, data);
4450 break;
4451 default:
4452 WARN("Unknown section_kind %x\n", section_kind);
4453 return STATUS_SXS_SECTION_NOT_FOUND;
4456 if (status != STATUS_SUCCESS) return status;
4458 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4460 actctx_addref(actctx);
4461 data->hActCtx = actctx;
4463 return STATUS_SUCCESS;
4466 /* initialize the activation context for the current process */
4467 void actctx_init(void)
4469 ACTCTXW ctx;
4470 HANDLE handle;
4472 ctx.cbSize = sizeof(ctx);
4473 ctx.lpSource = NULL;
4474 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4475 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4476 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4478 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4482 /***********************************************************************
4483 * RtlCreateActivationContext (NTDLL.@)
4485 * Create an activation context.
4487 * FIXME: function signature/prototype is wrong
4489 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4491 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4492 const WCHAR *directory = NULL;
4493 ACTIVATION_CONTEXT *actctx;
4494 UNICODE_STRING nameW;
4495 ULONG lang = 0;
4496 NTSTATUS status = STATUS_NO_MEMORY;
4497 HANDLE file = 0;
4498 struct actctx_loader acl;
4500 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4502 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4503 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4504 return STATUS_INVALID_PARAMETER;
4506 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4507 return STATUS_NO_MEMORY;
4509 actctx->magic = ACTCTX_MAGIC;
4510 actctx->ref_count = 1;
4511 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4512 actctx->config.info = NULL;
4513 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4514 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4516 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4518 else
4520 UNICODE_STRING dir;
4521 WCHAR *p;
4522 HMODULE module;
4524 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4525 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4527 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4528 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4529 actctx->appdir.info = dir.Buffer;
4532 nameW.Buffer = NULL;
4534 /* open file only if it's going to be used */
4535 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4536 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4538 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
4540 status = STATUS_NO_SUCH_FILE;
4541 goto error;
4543 status = open_nt_file( &file, &nameW );
4544 if (status)
4546 RtlFreeUnicodeString( &nameW );
4547 goto error;
4551 acl.actctx = actctx;
4552 acl.dependencies = NULL;
4553 acl.num_dependencies = 0;
4554 acl.allocated_dependencies = 0;
4556 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4557 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4559 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4561 /* if we have a resource it's a PE file */
4562 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4564 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4565 pActCtx->lpResourceName, lang );
4566 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4567 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4568 pActCtx->hModule, pActCtx->lpResourceName );
4570 else if (pActCtx->lpSource)
4572 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4573 file, pActCtx->lpResourceName, lang );
4574 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4575 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4576 NULL, pActCtx->lpResourceName );
4578 else status = STATUS_INVALID_PARAMETER;
4580 else
4582 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4585 if (file) NtClose( file );
4586 RtlFreeUnicodeString( &nameW );
4588 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4589 free_depend_manifests( &acl );
4591 if (status == STATUS_SUCCESS) *handle = actctx;
4592 else actctx_release( actctx );
4593 return status;
4595 error:
4596 if (file) NtClose( file );
4597 actctx_release( actctx );
4598 return status;
4602 /***********************************************************************
4603 * RtlAddRefActivationContext (NTDLL.@)
4605 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4607 ACTIVATION_CONTEXT *actctx;
4609 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4613 /******************************************************************
4614 * RtlReleaseActivationContext (NTDLL.@)
4616 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4618 ACTIVATION_CONTEXT *actctx;
4620 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4623 /******************************************************************
4624 * RtlZombifyActivationContext (NTDLL.@)
4626 * FIXME: function prototype might be wrong
4628 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4630 FIXME("%p: stub\n", handle);
4631 return STATUS_NOT_IMPLEMENTED;
4634 /******************************************************************
4635 * RtlActivateActivationContext (NTDLL.@)
4637 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4639 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4641 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4642 return STATUS_NO_MEMORY;
4644 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4645 frame->ActivationContext = handle;
4646 frame->Flags = 0;
4647 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4648 RtlAddRefActivationContext( handle );
4650 *cookie = (ULONG_PTR)frame;
4651 TRACE( "%p cookie=%lx\n", handle, *cookie );
4652 return STATUS_SUCCESS;
4656 /***********************************************************************
4657 * RtlDeactivateActivationContext (NTDLL.@)
4659 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4661 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4663 TRACE( "%x cookie=%lx\n", flags, cookie );
4665 /* find the right frame */
4666 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4667 for (frame = top; frame; frame = frame->Previous)
4668 if ((ULONG_PTR)frame == cookie) break;
4670 if (!frame)
4671 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4673 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4674 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4676 /* pop everything up to and including frame */
4677 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4679 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4681 frame = top->Previous;
4682 RtlReleaseActivationContext( top->ActivationContext );
4683 RtlFreeHeap( GetProcessHeap(), 0, top );
4684 top = frame;
4689 /******************************************************************
4690 * RtlFreeThreadActivationContextStack (NTDLL.@)
4692 void WINAPI RtlFreeThreadActivationContextStack(void)
4694 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4696 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4697 while (frame)
4699 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4700 RtlReleaseActivationContext( frame->ActivationContext );
4701 RtlFreeHeap( GetProcessHeap(), 0, frame );
4702 frame = prev;
4704 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4708 /******************************************************************
4709 * RtlGetActiveActivationContext (NTDLL.@)
4711 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4713 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4715 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4716 RtlAddRefActivationContext( *handle );
4718 else
4719 *handle = 0;
4721 return STATUS_SUCCESS;
4725 /******************************************************************
4726 * RtlIsActivationContextActive (NTDLL.@)
4728 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4730 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4732 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4733 if (frame->ActivationContext == handle) return TRUE;
4734 return FALSE;
4738 /***********************************************************************
4739 * RtlQueryInformationActivationContext (NTDLL.@)
4741 * Get information about an activation context.
4742 * FIXME: function signature/prototype may be wrong
4744 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4745 ULONG class, PVOID buffer,
4746 SIZE_T bufsize, SIZE_T *retlen )
4748 ACTIVATION_CONTEXT *actctx;
4749 NTSTATUS status;
4751 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4752 subinst, class, buffer, bufsize, retlen);
4754 if (retlen) *retlen = 0;
4755 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4757 switch (class)
4759 case ActivationContextBasicInformation:
4761 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4763 if (retlen) *retlen = sizeof(*info);
4764 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4766 info->hActCtx = handle;
4767 info->dwFlags = 0; /* FIXME */
4768 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4770 break;
4772 case ActivationContextDetailedInformation:
4774 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4775 struct assembly *assembly = NULL;
4776 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4777 LPWSTR ptr;
4779 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4781 if (actctx->num_assemblies) assembly = actctx->assemblies;
4783 if (assembly && assembly->manifest.info)
4784 manifest_len = strlenW(assembly->manifest.info) + 1;
4785 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4786 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4787 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4789 if (retlen) *retlen = len;
4790 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4792 acdi->dwFlags = 0;
4793 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4794 acdi->ulAssemblyCount = actctx->num_assemblies;
4795 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4796 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4797 acdi->ulRootConfigurationPathType = actctx->config.type;
4798 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4799 acdi->ulAppDirPathType = actctx->appdir.type;
4800 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4801 ptr = (LPWSTR)(acdi + 1);
4802 if (manifest_len)
4804 acdi->lpRootManifestPath = ptr;
4805 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4806 ptr += manifest_len;
4808 else acdi->lpRootManifestPath = NULL;
4809 if (config_len)
4811 acdi->lpRootConfigurationPath = ptr;
4812 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4813 ptr += config_len;
4815 else acdi->lpRootConfigurationPath = NULL;
4816 if (appdir_len)
4818 acdi->lpAppDirPath = ptr;
4819 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4821 else acdi->lpAppDirPath = NULL;
4823 break;
4825 case AssemblyDetailedInformationInActivationContext:
4827 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4828 struct assembly *assembly;
4829 WCHAR *assembly_id;
4830 DWORD index;
4831 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4832 LPWSTR ptr;
4834 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4835 if (!subinst) return STATUS_INVALID_PARAMETER;
4837 index = *(DWORD*)subinst;
4838 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4840 assembly = &actctx->assemblies[index - 1];
4842 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4843 id_len = strlenW(assembly_id) + 1;
4844 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4846 if (assembly->manifest.info &&
4847 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4848 path_len = strlenW(assembly->manifest.info) + 1;
4850 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4852 if (retlen) *retlen = len;
4853 if (!buffer || bufsize < len)
4855 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4856 return STATUS_BUFFER_TOO_SMALL;
4859 afdi->ulFlags = 0; /* FIXME */
4860 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4861 afdi->ulManifestPathType = assembly->manifest.type;
4862 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4863 /* FIXME afdi->liManifestLastWriteTime = 0; */
4864 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4865 afdi->ulPolicyPathLength = 0;
4866 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4867 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4868 afdi->ulManifestVersionMajor = 1;
4869 afdi->ulManifestVersionMinor = 0;
4870 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4871 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4872 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4873 ptr = (LPWSTR)(afdi + 1);
4874 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4875 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4876 ptr += id_len;
4877 if (path_len)
4879 afdi->lpAssemblyManifestPath = ptr;
4880 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4881 ptr += path_len;
4882 } else afdi->lpAssemblyManifestPath = NULL;
4883 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4884 if (ad_len)
4886 afdi->lpAssemblyDirectoryName = ptr;
4887 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4889 else afdi->lpAssemblyDirectoryName = NULL;
4890 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4892 break;
4894 case FileInformationInAssemblyOfAssemblyInActivationContext:
4896 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4897 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4898 struct assembly *assembly;
4899 struct dll_redirect *dll;
4900 SIZE_T len, dll_len = 0;
4901 LPWSTR ptr;
4903 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4904 if (!acqi) return STATUS_INVALID_PARAMETER;
4906 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4907 return STATUS_INVALID_PARAMETER;
4908 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4910 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4911 return STATUS_INVALID_PARAMETER;
4912 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4914 if (dll->name) dll_len = strlenW(dll->name) + 1;
4915 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4917 if (!buffer || bufsize < len)
4919 if (retlen) *retlen = len;
4920 return STATUS_BUFFER_TOO_SMALL;
4922 if (retlen) *retlen = 0; /* yes that's what native does !! */
4923 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4924 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4925 afdi->ulPathLength = 0; /* FIXME */
4926 ptr = (LPWSTR)(afdi + 1);
4927 if (dll_len)
4929 afdi->lpFileName = ptr;
4930 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4931 } else afdi->lpFileName = NULL;
4932 afdi->lpFilePath = NULL; /* FIXME */
4934 break;
4936 default:
4937 FIXME( "class %u not implemented\n", class );
4938 return STATUS_NOT_IMPLEMENTED;
4940 return STATUS_SUCCESS;
4943 /***********************************************************************
4944 * RtlFindActivationContextSectionString (NTDLL.@)
4946 * Find information about a string in an activation context.
4947 * FIXME: function signature/prototype may be wrong
4949 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
4950 const UNICODE_STRING *section_name, PVOID ptr )
4952 PACTCTX_SECTION_KEYED_DATA data = ptr;
4953 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4955 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
4956 debugstr_us(section_name), data);
4958 if (guid)
4960 FIXME("expected guid == NULL\n");
4961 return STATUS_INVALID_PARAMETER;
4963 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4965 FIXME("unknown flags %08x\n", flags);
4966 return STATUS_INVALID_PARAMETER;
4968 if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
4969 !section_name || !section_name->Buffer)
4971 WARN("invalid parameter\n");
4972 return STATUS_INVALID_PARAMETER;
4975 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4977 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
4978 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
4981 if (status != STATUS_SUCCESS)
4982 status = find_string( process_actctx, section_kind, section_name, flags, data );
4984 return status;
4987 /***********************************************************************
4988 * RtlFindActivationContextSectionGuid (NTDLL.@)
4990 * Find information about a GUID in an activation context.
4991 * FIXME: function signature/prototype may be wrong
4993 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
4994 const GUID *guid, void *ptr )
4996 ACTCTX_SECTION_KEYED_DATA *data = ptr;
4997 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4999 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5001 if (extguid)
5003 FIXME("expected extguid == NULL\n");
5004 return STATUS_INVALID_PARAMETER;
5007 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5009 FIXME("unknown flags %08x\n", flags);
5010 return STATUS_INVALID_PARAMETER;
5013 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5014 return STATUS_INVALID_PARAMETER;
5016 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5018 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5019 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5022 if (status != STATUS_SUCCESS)
5023 status = find_guid( process_actctx, section_kind, guid, flags, data );
5025 return status;