wined3d: Track if a context's private hdc has had its pixel format set, so we don...
[wine/multimedia.git] / dlls / ntdll / actctx.c
blob5d88b9acdc7d0635c3f7365e329b064cf389ed32
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 break;
855 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
856 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
857 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
858 break;
859 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
860 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
861 break;
862 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
863 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
864 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
865 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
866 break;
867 default:
868 FIXME("Unknown entity kind %d\n", entity->kind);
871 RtlFreeHeap( GetProcessHeap(), 0, array->base );
874 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
876 if (!str1) return !str2;
877 return str2 && !strcmpiW( str1, str2 );
880 static BOOL is_matching_identity( const struct assembly_identity *id1,
881 const struct assembly_identity *id2 )
883 if (!is_matching_string( id1->name, id2->name )) return FALSE;
884 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
885 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
887 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
889 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
890 return FALSE;
892 if (id1->version.major != id2->version.major) return FALSE;
893 if (id1->version.minor != id2->version.minor) return FALSE;
894 if (id1->version.build > id2->version.build) return FALSE;
895 if (id1->version.build == id2->version.build &&
896 id1->version.revision > id2->version.revision) return FALSE;
897 return TRUE;
900 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
901 struct assembly_identity* ai)
903 unsigned int i;
905 /* check if we already have that assembly */
907 for (i = 0; i < acl->actctx->num_assemblies; i++)
908 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
910 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
911 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
912 ai->version.build, ai->version.revision );
913 return TRUE;
916 for (i = 0; i < acl->num_dependencies; i++)
917 if (is_matching_identity( ai, &acl->dependencies[i] ))
919 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
920 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
921 ai->version.build, ai->version.revision );
922 return TRUE;
925 if (acl->num_dependencies == acl->allocated_dependencies)
927 void *ptr;
928 unsigned int new_count;
929 if (acl->dependencies)
931 new_count = acl->allocated_dependencies * 2;
932 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
933 new_count * sizeof(acl->dependencies[0]));
935 else
937 new_count = 4;
938 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
940 if (!ptr) return FALSE;
941 acl->dependencies = ptr;
942 acl->allocated_dependencies = new_count;
944 acl->dependencies[acl->num_dependencies++] = *ai;
946 return TRUE;
949 static void free_depend_manifests(struct actctx_loader* acl)
951 unsigned int i;
952 for (i = 0; i < acl->num_dependencies; i++)
953 free_assembly_identity(&acl->dependencies[i]);
954 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
957 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
959 static const WCHAR undW[] = {'_',0};
960 static const WCHAR noneW[] = {'n','o','n','e',0};
961 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
963 const WCHAR *arch = ai->arch ? ai->arch : noneW;
964 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
965 const WCHAR *lang = ai->language ? ai->language : noneW;
966 const WCHAR *name = ai->name ? ai->name : noneW;
967 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
968 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
969 WCHAR *ret;
971 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
973 strcpyW( ret, arch );
974 strcatW( ret, undW );
975 strcatW( ret, name );
976 strcatW( ret, undW );
977 strcatW( ret, key );
978 strcatW( ret, undW );
979 sprintfW( ret + strlenW(ret), version_formatW,
980 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
981 strcatW( ret, undW );
982 strcatW( ret, lang );
983 strcatW( ret, undW );
984 strcatW( ret, mskeyW );
985 return ret;
988 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
990 WCHAR *p = buffer;
992 if (!str) return;
993 strcatW( buffer, prefix );
994 p += strlenW(p);
995 *p++ = '"';
996 strcpyW( p, str );
997 p += strlenW(p);
998 *p++ = '"';
999 *p = 0;
1002 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1004 static const WCHAR archW[] =
1005 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1006 static const WCHAR public_keyW[] =
1007 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1008 static const WCHAR typeW[] =
1009 {',','t','y','p','e','=',0};
1010 static const WCHAR versionW[] =
1011 {',','v','e','r','s','i','o','n','=',0};
1013 WCHAR version[64], *ret;
1014 SIZE_T size = 0;
1016 sprintfW( version, version_formatW,
1017 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1018 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1019 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1020 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1021 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1022 size += strlenW(versionW) + strlenW(version) + 2;
1024 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1025 return NULL;
1027 if (ai->name) strcpyW( ret, ai->name );
1028 else *ret = 0;
1029 append_string( ret, archW, ai->arch );
1030 append_string( ret, public_keyW, ai->public_key );
1031 append_string( ret, typeW, ai->type );
1032 append_string( ret, versionW, version );
1033 return ret;
1036 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1038 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1040 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1041 __TRY
1043 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1045 __EXCEPT_PAGE_FAULT
1048 __ENDTRY
1049 return ret;
1052 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1054 interlocked_xchg_add( &actctx->ref_count, 1 );
1057 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1059 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1061 unsigned int i, j;
1063 for (i = 0; i < actctx->num_assemblies; i++)
1065 struct assembly *assembly = &actctx->assemblies[i];
1066 for (j = 0; j < assembly->num_dlls; j++)
1068 struct dll_redirect *dll = &assembly->dlls[j];
1069 free_entity_array( &dll->entities );
1070 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1071 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1073 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1074 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1076 free_entity_array( &assembly->entities );
1077 free_assembly_identity(&assembly->id);
1079 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1080 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1089 actctx->magic = 0;
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1094 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1095 BOOL* error, BOOL* end)
1097 const WCHAR* ptr;
1099 *error = TRUE;
1101 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1102 xmlbuf->ptr++;
1104 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1106 if (*xmlbuf->ptr == '/')
1108 xmlbuf->ptr++;
1109 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1110 return FALSE;
1112 xmlbuf->ptr++;
1113 *end = TRUE;
1114 *error = FALSE;
1115 return FALSE;
1118 if (*xmlbuf->ptr == '>')
1120 xmlbuf->ptr++;
1121 *error = FALSE;
1122 return FALSE;
1125 ptr = xmlbuf->ptr;
1126 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1128 if (ptr == xmlbuf->end) return FALSE;
1130 name->ptr = xmlbuf->ptr;
1131 name->len = ptr-xmlbuf->ptr;
1132 xmlbuf->ptr = ptr;
1134 /* skip spaces before '=' */
1135 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1136 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1138 /* skip '=' itself */
1139 ptr++;
1140 if (ptr == xmlbuf->end) return FALSE;
1142 /* skip spaces after '=' */
1143 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1145 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1147 value->ptr = ++ptr;
1148 if (ptr == xmlbuf->end) return FALSE;
1150 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1151 if (!ptr)
1153 xmlbuf->ptr = xmlbuf->end;
1154 return FALSE;
1157 value->len = ptr - value->ptr;
1158 xmlbuf->ptr = ptr + 1;
1160 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1162 *error = FALSE;
1163 return TRUE;
1166 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1168 const WCHAR* ptr;
1170 for (;;)
1172 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1173 if (!ptr)
1175 xmlbuf->ptr = xmlbuf->end;
1176 return FALSE;
1178 ptr++;
1179 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1181 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1182 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1184 if (ptr + 3 > xmlbuf->end)
1186 xmlbuf->ptr = xmlbuf->end;
1187 return FALSE;
1189 xmlbuf->ptr = ptr + 3;
1191 else break;
1194 xmlbuf->ptr = ptr;
1195 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1196 ptr++;
1198 elem->ptr = xmlbuf->ptr;
1199 elem->len = ptr - xmlbuf->ptr;
1200 xmlbuf->ptr = ptr;
1201 return xmlbuf->ptr != xmlbuf->end;
1204 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1206 /* FIXME: parse attributes */
1207 const WCHAR *ptr;
1209 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1211 if (ptr[0] == '?' && ptr[1] == '>')
1213 xmlbuf->ptr = ptr + 2;
1214 return TRUE;
1217 return FALSE;
1220 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1222 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1224 if (!ptr) return FALSE;
1226 content->ptr = xmlbuf->ptr;
1227 content->len = ptr - xmlbuf->ptr;
1228 xmlbuf->ptr = ptr;
1230 return TRUE;
1233 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1235 unsigned int ver[4];
1236 unsigned int pos;
1237 const WCHAR *curr;
1239 /* major.minor.build.revision */
1240 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1241 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1243 if (*curr >= '0' && *curr <= '9')
1245 ver[pos] = ver[pos] * 10 + *curr - '0';
1246 if (ver[pos] >= 0x10000) goto error;
1248 else if (*curr == '.')
1250 if (++pos >= 4) goto error;
1252 else goto error;
1254 version->major = ver[0];
1255 version->minor = ver[1];
1256 version->build = ver[2];
1257 version->revision = ver[3];
1258 return TRUE;
1260 error:
1261 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1262 return FALSE;
1265 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1267 xmlstr_t elem;
1268 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1269 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1270 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1271 return FALSE;
1274 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1276 xmlstr_t attr_name, attr_value;
1277 BOOL error;
1279 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1281 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1282 debugstr_xmlstr(&attr_value));
1284 return !error;
1287 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1289 BOOL end = FALSE;
1290 return parse_expect_no_attr(xmlbuf, &end) && !end;
1293 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1295 xmlstr_t elem;
1296 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1297 if (!xml_elem_cmp_end(&elem, name, namespace))
1299 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1300 return FALSE;
1302 return parse_end_element(xmlbuf);
1305 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1307 xmlstr_t attr_name, attr_value, elem;
1308 BOOL end = FALSE, error, ret = TRUE;
1310 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1311 if(error || end) return end;
1313 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1315 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1316 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1317 break;
1318 else
1319 ret = parse_unknown_elem(xmlbuf, &elem);
1322 return ret && parse_end_element(xmlbuf);
1325 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1326 struct assembly_identity* ai)
1328 xmlstr_t attr_name, attr_value;
1329 BOOL end = FALSE, error;
1331 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1333 if (xmlstr_cmp(&attr_name, nameW))
1335 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1337 else if (xmlstr_cmp(&attr_name, typeW))
1339 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1341 else if (xmlstr_cmp(&attr_name, versionW))
1343 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1345 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1347 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1349 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1351 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1353 else if (xmlstr_cmp(&attr_name, languageW))
1355 WARN("Unsupported yet language attribute (%s)\n",
1356 debugstr_xmlstr(&attr_value));
1357 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1359 else
1361 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1362 debugstr_xmlstr(&attr_value));
1366 TRACE( "name=%s version=%s arch=%s\n",
1367 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1369 if (error || end) return end;
1370 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1373 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1375 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1376 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1377 static const WCHAR freeW[] = {'F','r','e','e',0};
1378 static const WCHAR bothW[] = {'B','o','t','h',0};
1380 if (value->len == 0) return ThreadingModel_No;
1381 if (xmlstr_cmp(value, apartW))
1382 return ThreadingModel_Apartment;
1383 else if (xmlstr_cmp(value, freeW))
1384 return ThreadingModel_Free;
1385 else if (xmlstr_cmp(value, bothW))
1386 return ThreadingModel_Both;
1387 else if (xmlstr_cmp(value, neutralW))
1388 return ThreadingModel_Neutral;
1389 else
1390 return ThreadingModel_No;
1393 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1395 int min, max;
1397 min = 0;
1398 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1400 while (min <= max)
1402 int n, c;
1404 n = (min+max)/2;
1406 c = strncmpW(olemisc_values[n].name, str, len);
1407 if (!c && !olemisc_values[n].name[len])
1408 return olemisc_values[n].value;
1410 if (c >= 0)
1411 max = n-1;
1412 else
1413 min = n+1;
1416 WARN("unknown flag %s\n", debugstr_wn(str, len));
1417 return 0;
1420 static DWORD parse_com_class_misc(const xmlstr_t *value)
1422 const WCHAR *str = value->ptr, *start;
1423 DWORD flags = 0;
1424 int i = 0;
1426 /* it's comma separated list of flags */
1427 while (i < value->len)
1429 start = str;
1430 while (*str != ',' && (i++ < value->len)) str++;
1432 flags |= get_olemisc_value(start, str-start);
1434 /* skip separator */
1435 str++;
1436 i++;
1439 return flags;
1442 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1444 struct progids *progids = &entity->u.comclass.progids;
1446 if (progids->allocated == 0)
1448 progids->allocated = 4;
1449 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1452 if (progids->allocated == progids->num)
1454 progids->allocated *= 2;
1455 progids->progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1458 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1459 progids->num++;
1461 return TRUE;
1464 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1466 xmlstr_t content;
1467 BOOL end = FALSE;
1469 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1470 return FALSE;
1472 if (!com_class_add_progid(&content, entity)) return FALSE;
1473 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1476 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1478 xmlstr_t elem, attr_name, attr_value;
1479 BOOL ret = TRUE, end = FALSE, error;
1480 struct entity* entity;
1482 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1483 return FALSE;
1485 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1487 if (xmlstr_cmp(&attr_name, clsidW))
1489 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1491 else if (xmlstr_cmp(&attr_name, progidW))
1493 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1495 else if (xmlstr_cmp(&attr_name, tlbidW))
1497 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1499 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1501 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1503 else if (xmlstr_cmp(&attr_name, miscstatusW))
1505 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1507 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1509 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1511 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1513 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1515 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1517 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1519 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1521 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1523 else if (xmlstr_cmp(&attr_name, descriptionW))
1525 /* not stored */
1527 else
1529 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1533 if (error) return FALSE;
1535 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1536 if (entity->u.comclass.progid)
1537 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1539 if (end) return TRUE;
1541 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1543 if (xmlstr_cmp_end(&elem, comClassW))
1545 ret = parse_end_element(xmlbuf);
1546 break;
1548 else if (xmlstr_cmp(&elem, progidW))
1550 ret = parse_com_class_progid(xmlbuf, entity);
1552 else
1554 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1555 ret = parse_unknown_elem(xmlbuf, &elem);
1559 if (entity->u.comclass.progids.num)
1560 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1562 return ret;
1565 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1567 const WCHAR *curr;
1568 ULONG num = 0;
1570 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1572 if (*curr >= '0' && *curr <= '9')
1573 num = num * 10 + *curr - '0';
1574 else
1576 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1577 return FALSE;
1580 entity->u.ifaceps.nummethods = num;
1582 return TRUE;
1585 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1587 xmlstr_t attr_name, attr_value;
1588 BOOL end = FALSE, error;
1589 struct entity* entity;
1591 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1592 return FALSE;
1594 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1596 if (xmlstr_cmp(&attr_name, iidW))
1598 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1600 else if (xmlstr_cmp(&attr_name, nameW))
1602 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1604 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1606 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1607 entity->u.ifaceps.mask |= BaseIface;
1609 else if (xmlstr_cmp(&attr_name, nummethodsW))
1611 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1612 entity->u.ifaceps.mask |= NumMethods;
1614 else if (xmlstr_cmp(&attr_name, tlbidW))
1616 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1618 /* not used */
1619 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1622 else
1624 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1628 if (error) return FALSE;
1629 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1630 if (end) return TRUE;
1632 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1635 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1637 WORD *flags = &entity->u.typelib.flags;
1638 const WCHAR *str = value->ptr, *start;
1639 int i = 0;
1641 *flags = 0;
1643 /* it's comma separated list of flags */
1644 while (i < value->len)
1646 start = str;
1647 while (*str != ',' && (i++ < value->len)) str++;
1649 if (!strncmpiW(start, restrictedW, str-start))
1650 *flags |= LIBFLAG_FRESTRICTED;
1651 else if (!strncmpiW(start, controlW, str-start))
1652 *flags |= LIBFLAG_FCONTROL;
1653 else if (!strncmpiW(start, hiddenW, str-start))
1654 *flags |= LIBFLAG_FHIDDEN;
1655 else if (!strncmpiW(start, hasdiskimageW, str-start))
1656 *flags |= LIBFLAG_FHASDISKIMAGE;
1657 else
1659 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1660 return FALSE;
1663 /* skip separator */
1664 str++;
1665 i++;
1668 return TRUE;
1671 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1673 unsigned int ver[2];
1674 unsigned int pos;
1675 const WCHAR *curr;
1677 /* major.minor */
1678 ver[0] = ver[1] = pos = 0;
1679 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1681 if (*curr >= '0' && *curr <= '9')
1683 ver[pos] = ver[pos] * 10 + *curr - '0';
1684 if (ver[pos] >= 0x10000) goto error;
1686 else if (*curr == '.')
1688 if (++pos >= 2) goto error;
1690 else goto error;
1692 entity->u.typelib.major = ver[0];
1693 entity->u.typelib.minor = ver[1];
1694 return TRUE;
1696 error:
1697 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1698 return FALSE;
1701 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1703 xmlstr_t attr_name, attr_value;
1704 BOOL end = FALSE, error;
1705 struct entity* entity;
1707 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1708 return FALSE;
1710 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1712 if (xmlstr_cmp(&attr_name, tlbidW))
1714 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1716 else if (xmlstr_cmp(&attr_name, versionW))
1718 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1720 else if (xmlstr_cmp(&attr_name, helpdirW))
1722 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1724 else if (xmlstr_cmp(&attr_name, flagsW))
1726 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1728 else
1730 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1734 if (error) return FALSE;
1736 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1738 if (end) return TRUE;
1740 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1743 static inline int aligned_string_len(int len)
1745 return (len + 3) & ~3;
1748 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1750 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1751 struct assembly_version *ver = &assembly->id.version;
1752 WCHAR buff[25];
1754 if (!ret) ret = buff;
1755 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1758 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1760 xmlstr_t elem, content, attr_name, attr_value;
1761 BOOL end = FALSE, ret = TRUE, error;
1762 struct entity* entity;
1764 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1765 return FALSE;
1767 entity->u.class.versioned = TRUE;
1768 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1770 if (xmlstr_cmp(&attr_name, versionedW))
1772 if (xmlstr_cmpi(&attr_value, noW))
1773 entity->u.class.versioned = FALSE;
1774 else if (!xmlstr_cmpi(&attr_value, yesW))
1775 return FALSE;
1777 else
1779 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1783 if (error || end) return end;
1785 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1787 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1789 acl->actctx->sections |= WINDOWCLASS_SECTION;
1791 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1793 if (xmlstr_cmp_end(&elem, windowClassW))
1795 ret = parse_end_element(xmlbuf);
1796 break;
1798 else
1800 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1801 ret = parse_unknown_elem(xmlbuf, &elem);
1805 return ret;
1808 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1810 xmlstr_t attr_name, attr_value;
1811 BOOL end = FALSE, error;
1813 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1815 if (xmlstr_cmp(&attr_name, oldVersionW))
1817 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1819 else if (xmlstr_cmp(&attr_name, newVersionW))
1821 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1823 else
1825 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1829 if (error || end) return end;
1830 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1833 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1835 xmlstr_t elem, content;
1836 BOOL end = FALSE, ret = TRUE;
1838 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
1839 !parse_text_content(xmlbuf, &content))
1840 return FALSE;
1842 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1844 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1846 if (xmlstr_cmp_end(&elem, descriptionW))
1848 ret = parse_end_element(xmlbuf);
1849 break;
1851 else
1853 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1854 ret = parse_unknown_elem(xmlbuf, &elem);
1858 return ret;
1861 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1862 struct assembly* assembly,
1863 struct actctx_loader* acl)
1865 xmlstr_t attr_name, attr_value;
1866 BOOL end = FALSE, error;
1867 struct entity* entity;
1869 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1870 if (!entity) return FALSE;
1872 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1874 if (xmlstr_cmp(&attr_name, iidW))
1876 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1878 else if (xmlstr_cmp(&attr_name, nameW))
1880 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1882 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1884 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1885 entity->u.ifaceps.mask |= BaseIface;
1887 else if (xmlstr_cmp(&attr_name, nummethodsW))
1889 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1890 entity->u.ifaceps.mask |= NumMethods;
1892 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1894 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1896 else if (xmlstr_cmp(&attr_name, tlbidW))
1898 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1900 else
1902 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1906 if (error) return FALSE;
1907 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1908 if (end) return TRUE;
1910 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1913 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1915 xmlstr_t attr_name, attr_value, elem;
1916 BOOL end = FALSE, error, ret = TRUE;
1917 struct entity* entity;
1919 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1920 if (!entity) return FALSE;
1922 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1924 if (xmlstr_cmp(&attr_name, nameW))
1926 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1928 else if (xmlstr_cmp(&attr_name, clsidW))
1930 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1932 else if (xmlstr_cmp(&attr_name, progidW))
1934 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1936 else if (xmlstr_cmp(&attr_name, tlbidW))
1938 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1940 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1942 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1944 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1946 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1948 else
1950 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1954 if (error) return FALSE;
1955 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1956 if (entity->u.comclass.progid)
1957 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1958 if (end) return TRUE;
1960 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1962 if (xmlstr_cmp_end(&elem, clrClassW))
1964 ret = parse_end_element(xmlbuf);
1965 break;
1967 else if (xmlstr_cmp(&elem, progidW))
1969 ret = parse_com_class_progid(xmlbuf, entity);
1971 else
1973 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1974 ret = parse_unknown_elem(xmlbuf, &elem);
1978 if (entity->u.comclass.progids.num)
1979 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1981 return ret;
1984 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1986 xmlstr_t attr_name, attr_value;
1987 BOOL end = FALSE, error;
1988 struct entity* entity;
1990 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1991 if (!entity) return FALSE;
1993 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1995 if (xmlstr_cmp(&attr_name, nameW))
1997 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
1999 else if (xmlstr_cmp(&attr_name, clsidW))
2001 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2003 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2005 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2007 else
2009 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2013 if (error) return FALSE;
2014 acl->actctx->sections |= CLRSURROGATES_SECTION;
2015 if (end) return TRUE;
2017 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2020 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2022 struct assembly_identity ai;
2023 xmlstr_t elem;
2024 BOOL end = FALSE, ret = TRUE;
2026 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
2028 memset(&ai, 0, sizeof(ai));
2029 ai.optional = optional;
2031 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2032 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2033 return FALSE;
2035 TRACE( "adding name=%s version=%s arch=%s\n",
2036 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2038 /* store the newly found identity for later loading */
2039 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2041 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2043 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2045 ret = parse_end_element(xmlbuf);
2046 break;
2048 else if (xmlstr_cmp(&elem, bindingRedirectW))
2050 ret = parse_binding_redirect_elem(xmlbuf);
2052 else
2054 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2055 ret = parse_unknown_elem(xmlbuf, &elem);
2059 return ret;
2062 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2064 xmlstr_t attr_name, attr_value, elem;
2065 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2067 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2069 if (xmlstr_cmp(&attr_name, optionalW))
2071 optional = xmlstr_cmpi( &attr_value, yesW );
2072 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2074 else
2076 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2080 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2082 if (xmlstr_cmp_end(&elem, dependencyW))
2084 ret = parse_end_element(xmlbuf);
2085 break;
2087 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2089 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2091 else
2093 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2094 ret = parse_unknown_elem(xmlbuf, &elem);
2098 return ret;
2101 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2103 BOOL end = FALSE;
2105 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2106 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2109 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2111 BOOL end = FALSE;
2113 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2114 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2117 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2119 xmlstr_t attr_name, attr_value, elem;
2120 BOOL end = FALSE, error, ret = TRUE;
2121 struct dll_redirect* dll;
2123 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2125 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2127 if (xmlstr_cmp(&attr_name, nameW))
2129 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2130 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2132 else if (xmlstr_cmp(&attr_name, hashW))
2134 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2136 else if (xmlstr_cmp(&attr_name, hashalgW))
2138 static const WCHAR sha1W[] = {'S','H','A','1',0};
2139 if (!xmlstr_cmpi(&attr_value, sha1W))
2140 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2142 else
2144 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2148 if (error || !dll->name) return FALSE;
2150 acl->actctx->sections |= DLLREDIRECT_SECTION;
2152 if (end) return TRUE;
2154 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2156 if (xmlstr_cmp_end(&elem, fileW))
2158 ret = parse_end_element(xmlbuf);
2159 break;
2161 else if (xmlstr_cmp(&elem, comClassW))
2163 ret = parse_com_class_elem(xmlbuf, dll, acl);
2165 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2167 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2169 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2171 WARN("asmv2:hash (undocumented) not supported\n");
2172 ret = parse_unknown_elem(xmlbuf, &elem);
2174 else if (xmlstr_cmp(&elem, typelibW))
2176 ret = parse_typelib_elem(xmlbuf, dll, acl);
2178 else if (xmlstr_cmp(&elem, windowClassW))
2180 ret = parse_window_class_elem(xmlbuf, dll, acl);
2182 else
2184 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2185 ret = parse_unknown_elem( xmlbuf, &elem );
2189 return ret;
2192 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2193 struct assembly* assembly,
2194 struct assembly_identity* expected_ai)
2196 xmlstr_t attr_name, attr_value, elem;
2197 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2199 TRACE("(%p)\n", xmlbuf);
2201 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2203 if (xmlstr_cmp(&attr_name, manifestVersionW))
2205 static const WCHAR v10W[] = {'1','.','0',0};
2206 if (!xmlstr_cmp(&attr_value, v10W))
2208 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2209 return FALSE;
2211 version = TRUE;
2213 else if (xmlstr_cmp(&attr_name, xmlnsW))
2215 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
2217 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2218 return FALSE;
2220 xmlns = TRUE;
2222 else
2224 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2228 if (error || end || !xmlns || !version) return FALSE;
2229 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2231 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2233 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2234 return FALSE;
2235 assembly->no_inherit = TRUE;
2238 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2240 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2241 return FALSE;
2243 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2244 assembly->no_inherit)
2245 return FALSE;
2247 while (ret)
2249 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2251 ret = parse_end_element(xmlbuf);
2252 break;
2254 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2256 ret = parse_description_elem(xmlbuf);
2258 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2260 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2262 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2264 ret = parse_dependency_elem(xmlbuf, acl);
2266 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2268 ret = parse_file_elem(xmlbuf, assembly, acl);
2270 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2272 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2274 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2276 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2278 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2280 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2282 if (expected_ai)
2284 /* FIXME: more tests */
2285 if (assembly->type == ASSEMBLY_MANIFEST &&
2286 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2288 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2289 expected_ai->version.major, expected_ai->version.minor,
2290 expected_ai->version.build, expected_ai->version.revision,
2291 assembly->id.version.major, assembly->id.version.minor,
2292 assembly->id.version.build, assembly->id.version.revision);
2293 ret = FALSE;
2295 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2296 (assembly->id.version.major != expected_ai->version.major ||
2297 assembly->id.version.minor != expected_ai->version.minor ||
2298 assembly->id.version.build < expected_ai->version.build ||
2299 (assembly->id.version.build == expected_ai->version.build &&
2300 assembly->id.version.revision < expected_ai->version.revision)))
2302 FIXME("wrong version for shared assembly manifest\n");
2303 ret = FALSE;
2307 else
2309 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2310 ret = parse_unknown_elem(xmlbuf, &elem);
2312 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2315 return ret;
2318 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2319 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2321 xmlstr_t elem;
2323 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2325 if (xmlstr_cmp(&elem, xmlW) &&
2326 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2327 return STATUS_SXS_CANT_GEN_ACTCTX;
2329 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2331 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2332 return STATUS_SXS_CANT_GEN_ACTCTX;
2335 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2337 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2338 return STATUS_SXS_CANT_GEN_ACTCTX;
2341 if (next_xml_elem(xmlbuf, &elem))
2343 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2344 return STATUS_SXS_CANT_GEN_ACTCTX;
2347 if (xmlbuf->ptr != xmlbuf->end)
2349 FIXME("parse error\n");
2350 return STATUS_SXS_CANT_GEN_ACTCTX;
2352 return STATUS_SUCCESS;
2355 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2356 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2357 const void *buffer, SIZE_T size )
2359 xmlbuf_t xmlbuf;
2360 NTSTATUS status;
2361 struct assembly *assembly;
2362 int unicode_tests;
2364 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2366 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2367 return STATUS_SXS_CANT_GEN_ACTCTX;
2369 if (directory && !(assembly->directory = strdupW(directory)))
2370 return STATUS_NO_MEMORY;
2372 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2373 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2374 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2376 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2377 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2379 xmlbuf.ptr = buffer;
2380 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2381 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2383 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2385 const WCHAR *buf = buffer;
2386 WCHAR *new_buff;
2387 unsigned int i;
2389 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2390 return STATUS_NO_MEMORY;
2391 for (i = 0; i < size / sizeof(WCHAR); i++)
2392 new_buff[i] = RtlUshortByteSwap( buf[i] );
2393 xmlbuf.ptr = new_buff;
2394 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2395 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2396 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2398 else
2400 /* let's assume utf-8 for now */
2401 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2402 WCHAR *new_buff;
2404 if (len == -1)
2406 FIXME( "utf-8 conversion failed\n" );
2407 return STATUS_SXS_CANT_GEN_ACTCTX;
2409 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2410 return STATUS_NO_MEMORY;
2411 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2412 xmlbuf.ptr = new_buff;
2413 xmlbuf.end = xmlbuf.ptr + len;
2414 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2415 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2417 return status;
2420 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2422 OBJECT_ATTRIBUTES attr;
2423 IO_STATUS_BLOCK io;
2425 attr.Length = sizeof(attr);
2426 attr.RootDirectory = 0;
2427 attr.Attributes = OBJ_CASE_INSENSITIVE;
2428 attr.ObjectName = name;
2429 attr.SecurityDescriptor = NULL;
2430 attr.SecurityQualityOfService = NULL;
2431 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2434 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2436 NTSTATUS status;
2437 ULONG magic;
2438 LDR_MODULE *pldr;
2440 LdrLockLoaderLock(0, NULL, &magic);
2441 status = LdrFindEntryForAddress( module, &pldr );
2442 if (status == STATUS_SUCCESS)
2444 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2445 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2447 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2448 str->Length = pldr->FullDllName.Length;
2449 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2451 else status = STATUS_NO_MEMORY;
2453 LdrUnlockLoaderLock(0, magic);
2454 return status;
2457 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2458 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2459 HANDLE hModule, LPCWSTR resname, ULONG lang )
2461 NTSTATUS status;
2462 UNICODE_STRING nameW;
2463 LDR_RESOURCE_INFO info;
2464 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2465 void *ptr;
2467 if (TRACE_ON(actctx))
2469 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2471 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2472 hModule, debugstr_w(nameW.Buffer) );
2473 RtlFreeUnicodeString( &nameW );
2475 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2476 hModule, debugstr_w(filename) );
2479 if (!resname) return STATUS_INVALID_PARAMETER;
2481 info.Type = RT_MANIFEST;
2482 info.Language = lang;
2483 if (!((ULONG_PTR)resname >> 16))
2485 info.Name = (ULONG_PTR)resname;
2486 status = LdrFindResource_U(hModule, &info, 3, &entry);
2488 else if (resname[0] == '#')
2490 ULONG value;
2491 RtlInitUnicodeString(&nameW, resname + 1);
2492 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2493 return STATUS_INVALID_PARAMETER;
2494 info.Name = value;
2495 status = LdrFindResource_U(hModule, &info, 3, &entry);
2497 else
2499 RtlCreateUnicodeString(&nameW, resname);
2500 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2501 info.Name = (ULONG_PTR)nameW.Buffer;
2502 status = LdrFindResource_U(hModule, &info, 3, &entry);
2503 RtlFreeUnicodeString(&nameW);
2505 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2507 if (status == STATUS_SUCCESS)
2508 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2510 return status;
2513 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2514 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2515 HANDLE file, LPCWSTR resname, ULONG lang )
2517 HANDLE mapping;
2518 OBJECT_ATTRIBUTES attr;
2519 LARGE_INTEGER size;
2520 LARGE_INTEGER offset;
2521 NTSTATUS status;
2522 SIZE_T count;
2523 void *base;
2525 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2527 attr.Length = sizeof(attr);
2528 attr.RootDirectory = 0;
2529 attr.ObjectName = NULL;
2530 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2531 attr.SecurityDescriptor = NULL;
2532 attr.SecurityQualityOfService = NULL;
2534 size.QuadPart = 0;
2535 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2536 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2537 if (status != STATUS_SUCCESS) return status;
2539 offset.QuadPart = 0;
2540 count = 0;
2541 base = NULL;
2542 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2543 &count, ViewShare, 0, PAGE_READONLY );
2544 NtClose( mapping );
2545 if (status != STATUS_SUCCESS) return status;
2547 if (RtlImageNtHeader(base)) /* we got a PE file */
2549 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2550 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2552 else status = STATUS_INVALID_IMAGE_FORMAT;
2554 NtUnmapViewOfSection( GetCurrentProcess(), base );
2555 return status;
2558 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2559 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2561 FILE_END_OF_FILE_INFORMATION info;
2562 IO_STATUS_BLOCK io;
2563 HANDLE mapping;
2564 OBJECT_ATTRIBUTES attr;
2565 LARGE_INTEGER size;
2566 LARGE_INTEGER offset;
2567 NTSTATUS status;
2568 SIZE_T count;
2569 void *base;
2571 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2573 attr.Length = sizeof(attr);
2574 attr.RootDirectory = 0;
2575 attr.ObjectName = NULL;
2576 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2577 attr.SecurityDescriptor = NULL;
2578 attr.SecurityQualityOfService = NULL;
2580 size.QuadPart = 0;
2581 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2582 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2583 if (status != STATUS_SUCCESS) return status;
2585 offset.QuadPart = 0;
2586 count = 0;
2587 base = NULL;
2588 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2589 &count, ViewShare, 0, PAGE_READONLY );
2590 NtClose( mapping );
2591 if (status != STATUS_SUCCESS) return status;
2593 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2594 if (status == STATUS_SUCCESS)
2595 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2597 NtUnmapViewOfSection( GetCurrentProcess(), base );
2598 return status;
2601 /* try to load the .manifest file associated to the file */
2602 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2603 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2605 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2606 WCHAR *buffer;
2607 NTSTATUS status;
2608 UNICODE_STRING nameW;
2609 HANDLE file;
2610 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2612 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2614 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2616 if (module) /* use the module filename */
2618 UNICODE_STRING name;
2620 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2622 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2623 strcatW( name.Buffer, dotManifestW );
2624 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2625 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2626 RtlFreeUnicodeString( &name );
2628 if (status) return status;
2630 else
2632 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2633 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2634 return STATUS_NO_MEMORY;
2635 strcpyW( buffer, filename );
2636 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2637 strcatW( buffer, dotManifestW );
2638 RtlInitUnicodeString( &nameW, buffer );
2641 if (!open_nt_file( &file, &nameW ))
2643 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2644 NtClose( file );
2646 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2647 RtlFreeUnicodeString( &nameW );
2648 return status;
2651 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2653 static const WCHAR lookup_fmtW[] =
2654 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2655 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2656 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2658 WCHAR *lookup, *ret = NULL;
2659 UNICODE_STRING lookup_us;
2660 IO_STATUS_BLOCK io;
2661 const WCHAR *lang = ai->language;
2662 unsigned int data_pos = 0, data_len;
2663 char buffer[8192];
2665 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2666 (strlenW(ai->arch) + strlenW(ai->name)
2667 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2668 + sizeof(lookup_fmtW) )))
2669 return NULL;
2671 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2672 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2673 ai->version.major, ai->version.minor, lang );
2674 RtlInitUnicodeString( &lookup_us, lookup );
2676 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2677 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2678 if (io.u.Status == STATUS_SUCCESS)
2680 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2681 FILE_BOTH_DIR_INFORMATION *dir_info;
2682 WCHAR *tmp;
2683 ULONG build, revision;
2685 data_len = io.Information;
2687 for (;;)
2689 if (data_pos >= data_len)
2691 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2692 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2693 if (io.u.Status != STATUS_SUCCESS) break;
2694 data_len = io.Information;
2695 data_pos = 0;
2697 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2699 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2700 else data_pos = data_len;
2702 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2703 build = atoiW(tmp);
2704 if (build < min_build) continue;
2705 tmp = strchrW(tmp, '.') + 1;
2706 revision = atoiW(tmp);
2707 if (build == min_build && revision < min_revision) continue;
2708 tmp = strchrW(tmp, '_') + 1;
2709 tmp = strchrW(tmp, '_') + 1;
2710 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2711 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2713 /* prefer a non-Wine manifest if we already have one */
2714 /* we'll still load the builtin dll if specified through DllOverrides */
2715 if (ret) continue;
2717 else
2719 min_build = build;
2720 min_revision = revision;
2722 ai->version.build = build;
2723 ai->version.revision = revision;
2724 RtlFreeHeap( GetProcessHeap(), 0, ret );
2725 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2727 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2728 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2732 else WARN("no matching file for %s\n", debugstr_w(lookup));
2733 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2734 return ret;
2737 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2739 struct assembly_identity sxs_ai;
2740 UNICODE_STRING path_us;
2741 OBJECT_ATTRIBUTES attr;
2742 IO_STATUS_BLOCK io;
2743 WCHAR *path, *file = NULL;
2744 HANDLE handle;
2746 static const WCHAR manifest_dirW[] =
2747 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2749 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2751 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2752 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2753 return STATUS_NO_MEMORY;
2755 strcpyW( path, user_shared_data->NtSystemRoot );
2756 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2758 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2760 RtlFreeHeap( GetProcessHeap(), 0, path );
2761 return STATUS_NO_SUCH_FILE;
2763 RtlFreeHeap( GetProcessHeap(), 0, path );
2765 attr.Length = sizeof(attr);
2766 attr.RootDirectory = 0;
2767 attr.Attributes = OBJ_CASE_INSENSITIVE;
2768 attr.ObjectName = &path_us;
2769 attr.SecurityDescriptor = NULL;
2770 attr.SecurityQualityOfService = NULL;
2772 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2773 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2775 sxs_ai = *ai;
2776 file = lookup_manifest_file( handle, &sxs_ai );
2777 NtClose( handle );
2779 if (!file)
2781 RtlFreeUnicodeString( &path_us );
2782 return STATUS_NO_SUCH_FILE;
2785 /* append file name to directory path */
2786 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2787 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2789 RtlFreeHeap( GetProcessHeap(), 0, file );
2790 RtlFreeUnicodeString( &path_us );
2791 return STATUS_NO_MEMORY;
2794 path[path_us.Length/sizeof(WCHAR)] = '\\';
2795 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2796 RtlInitUnicodeString( &path_us, path );
2797 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2799 if (!open_nt_file( &handle, &path_us ))
2801 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2802 NtClose( handle );
2804 else io.u.Status = STATUS_NO_SUCH_FILE;
2806 RtlFreeHeap( GetProcessHeap(), 0, file );
2807 RtlFreeUnicodeString( &path_us );
2808 return io.u.Status;
2811 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2812 struct assembly_identity* ai)
2814 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2815 unsigned int i;
2816 WCHAR *buffer, *p, *directory;
2817 NTSTATUS status;
2818 UNICODE_STRING nameW;
2819 HANDLE file;
2820 DWORD len;
2822 TRACE( "looking for name=%s version=%s arch=%s\n",
2823 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2825 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2827 /* FIXME: add support for language specific lookup */
2829 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2830 strlenW(acl->actctx->appdir.info));
2832 nameW.Buffer = NULL;
2833 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2834 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2835 return STATUS_NO_MEMORY;
2837 if (!(directory = build_assembly_dir( ai )))
2839 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2840 return STATUS_NO_MEMORY;
2843 /* Lookup in <dir>\name.dll
2844 * <dir>\name.manifest
2845 * <dir>\name\name.dll
2846 * <dir>\name\name.manifest
2848 * First 'appdir' is used as <dir>, if that failed
2849 * it tries application manifest file path.
2851 strcpyW( buffer, acl->actctx->appdir.info );
2852 p = buffer + strlenW(buffer);
2853 for (i = 0; i < 4; i++)
2855 if (i == 2)
2857 struct assembly *assembly = acl->actctx->assemblies;
2858 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
2860 else *p++ = '\\';
2862 strcpyW( p, ai->name );
2863 p += strlenW(p);
2865 strcpyW( p, dotDllW );
2866 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2868 status = open_nt_file( &file, &nameW );
2869 if (!status)
2871 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2872 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2873 NtClose( file );
2874 break;
2876 RtlFreeUnicodeString( &nameW );
2879 strcpyW( p, dotManifestW );
2880 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2882 status = open_nt_file( &file, &nameW );
2883 if (!status)
2885 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2886 NtClose( file );
2887 break;
2889 RtlFreeUnicodeString( &nameW );
2891 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2893 RtlFreeUnicodeString( &nameW );
2894 RtlFreeHeap( GetProcessHeap(), 0, directory );
2895 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2896 return status;
2899 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2901 NTSTATUS status = STATUS_SUCCESS;
2902 unsigned int i;
2904 for (i = 0; i < acl->num_dependencies; i++)
2906 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2908 if (!acl->dependencies[i].optional)
2910 FIXME( "Could not find dependent assembly %s (%s)\n",
2911 debugstr_w(acl->dependencies[i].name),
2912 debugstr_version(&acl->dependencies[i].version) );
2913 status = STATUS_SXS_CANT_GEN_ACTCTX;
2914 break;
2918 /* FIXME should now iterate through all refs */
2919 return status;
2922 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2923 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2925 NTSTATUS status = STATUS_SUCCESS;
2927 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2929 if (*handle) return STATUS_INVALID_PARAMETER;
2931 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2932 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2934 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2936 ULONG magic;
2937 LDR_MODULE *pldr;
2939 if (!*handle) return STATUS_INVALID_PARAMETER;
2941 LdrLockLoaderLock( 0, NULL, &magic );
2942 if (!LdrFindEntryForAddress( *handle, &pldr ))
2944 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2945 status = STATUS_DLL_NOT_FOUND;
2946 else
2947 *handle = pldr->ActivationContext;
2949 else status = STATUS_DLL_NOT_FOUND;
2950 LdrUnlockLoaderLock( 0, magic );
2952 else if (!*handle && (class != ActivationContextBasicInformation))
2953 *handle = process_actctx;
2955 return status;
2958 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2960 unsigned int i, j, total_len = 0, dll_count = 0;
2961 struct strsection_header *header;
2962 struct dllredirect_data *data;
2963 struct string_index *index;
2964 ULONG name_offset;
2966 /* compute section length */
2967 for (i = 0; i < actctx->num_assemblies; i++)
2969 struct assembly *assembly = &actctx->assemblies[i];
2970 for (j = 0; j < assembly->num_dlls; j++)
2972 struct dll_redirect *dll = &assembly->dlls[j];
2974 /* each entry needs index, data and string data */
2975 total_len += sizeof(*index);
2976 total_len += sizeof(*data);
2977 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
2980 dll_count += assembly->num_dlls;
2983 total_len += sizeof(*header);
2985 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
2986 if (!header) return STATUS_NO_MEMORY;
2988 memset(header, 0, sizeof(*header));
2989 header->magic = STRSECTION_MAGIC;
2990 header->size = sizeof(*header);
2991 header->count = dll_count;
2992 header->index_offset = sizeof(*header);
2993 index = (struct string_index*)((BYTE*)header + header->index_offset);
2994 name_offset = header->index_offset + header->count*sizeof(*index);
2996 for (i = 0; i < actctx->num_assemblies; i++)
2998 struct assembly *assembly = &actctx->assemblies[i];
2999 for (j = 0; j < assembly->num_dlls; j++)
3001 struct dll_redirect *dll = &assembly->dlls[j];
3002 UNICODE_STRING str;
3003 WCHAR *ptrW;
3005 /* setup new index entry */
3006 str.Buffer = dll->name;
3007 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3008 str.MaximumLength = str.Length + sizeof(WCHAR);
3009 /* hash original class name */
3010 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3012 index->name_offset = name_offset;
3013 index->name_len = str.Length;
3014 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3015 index->data_len = sizeof(*data);
3016 index->rosterindex = i + 1;
3018 /* setup data */
3019 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3020 data->size = sizeof(*data);
3021 data->unk = 2; /* FIXME: seems to be constant */
3022 memset(data->res, 0, sizeof(data->res));
3024 /* dll name */
3025 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3026 memcpy(ptrW, dll->name, index->name_len);
3027 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3029 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3031 index++;
3035 *section = header;
3037 return STATUS_SUCCESS;
3040 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3042 struct string_index *iter, *index = NULL;
3043 ULONG hash = 0, i;
3045 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3046 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3048 for (i = 0; i < section->count; i++)
3050 if (iter->hash == hash)
3052 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3054 if (!strcmpiW(nameW, name->Buffer))
3056 index = iter;
3057 break;
3059 else
3060 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3062 iter++;
3065 return index;
3068 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3070 struct guid_index *iter, *index = NULL;
3071 ULONG i;
3073 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3075 for (i = 0; i < section->count; i++)
3077 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3079 index = iter;
3080 break;
3082 iter++;
3085 return index;
3088 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3090 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3093 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3094 PACTCTX_SECTION_KEYED_DATA data)
3096 struct dllredirect_data *dll;
3097 struct string_index *index;
3099 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3101 if (!actctx->dllredirect_section)
3103 struct strsection_header *section;
3105 NTSTATUS status = build_dllredirect_section(actctx, &section);
3106 if (status) return status;
3108 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3109 RtlFreeHeap(GetProcessHeap(), 0, section);
3112 index = find_string_index(actctx->dllredirect_section, name);
3113 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3115 dll = get_dllredirect_data(actctx, index);
3117 data->ulDataFormatVersion = 1;
3118 data->lpData = dll;
3119 data->ulLength = dll->size;
3120 data->lpSectionGlobalData = NULL;
3121 data->ulSectionGlobalDataLength = 0;
3122 data->lpSectionBase = actctx->dllredirect_section;
3123 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3124 data->hActCtx = NULL;
3126 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3127 data->ulAssemblyRosterIndex = index->rosterindex;
3129 return STATUS_SUCCESS;
3132 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3134 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3137 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3139 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3142 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3144 unsigned int i, j, k, total_len = 0, class_count = 0;
3145 struct wndclass_redirect_data *data;
3146 struct strsection_header *header;
3147 struct string_index *index;
3148 ULONG name_offset;
3150 /* compute section length */
3151 for (i = 0; i < actctx->num_assemblies; i++)
3153 struct assembly *assembly = &actctx->assemblies[i];
3154 for (j = 0; j < assembly->num_dlls; j++)
3156 struct dll_redirect *dll = &assembly->dlls[j];
3157 for (k = 0; k < dll->entities.num; k++)
3159 struct entity *entity = &dll->entities.base[k];
3160 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3162 int class_len = strlenW(entity->u.class.name) + 1;
3163 int len;
3165 /* each class entry needs index, data and string data */
3166 total_len += sizeof(*index);
3167 total_len += sizeof(*data);
3168 /* original name is stored separately */
3169 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3170 /* versioned name and module name are stored one after another */
3171 if (entity->u.class.versioned)
3172 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3173 else
3174 len = class_len;
3175 len += strlenW(dll->name) + 1;
3176 total_len += aligned_string_len(len*sizeof(WCHAR));
3178 class_count++;
3184 total_len += sizeof(*header);
3186 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3187 if (!header) return STATUS_NO_MEMORY;
3189 memset(header, 0, sizeof(*header));
3190 header->magic = STRSECTION_MAGIC;
3191 header->size = sizeof(*header);
3192 header->count = class_count;
3193 header->index_offset = sizeof(*header);
3194 index = (struct string_index*)((BYTE*)header + header->index_offset);
3195 name_offset = header->index_offset + header->count*sizeof(*index);
3197 for (i = 0; i < actctx->num_assemblies; i++)
3199 struct assembly *assembly = &actctx->assemblies[i];
3200 for (j = 0; j < assembly->num_dlls; j++)
3202 struct dll_redirect *dll = &assembly->dlls[j];
3203 for (k = 0; k < dll->entities.num; k++)
3205 struct entity *entity = &dll->entities.base[k];
3206 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3208 static const WCHAR exclW[] = {'!',0};
3209 ULONG versioned_len, module_len;
3210 UNICODE_STRING str;
3211 WCHAR *ptrW;
3213 /* setup new index entry */
3214 str.Buffer = entity->u.class.name;
3215 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3216 str.MaximumLength = str.Length + sizeof(WCHAR);
3217 /* hash original class name */
3218 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3220 /* include '!' separator too */
3221 if (entity->u.class.versioned)
3222 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3223 else
3224 versioned_len = str.Length;
3225 module_len = strlenW(dll->name)*sizeof(WCHAR);
3227 index->name_offset = name_offset;
3228 index->name_len = str.Length;
3229 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3230 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3231 index->rosterindex = i + 1;
3233 /* setup data */
3234 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3235 data->size = sizeof(*data);
3236 data->res = 0;
3237 data->name_len = versioned_len;
3238 data->name_offset = sizeof(*data);
3239 data->module_len = module_len;
3240 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3242 /* original class name */
3243 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3244 memcpy(ptrW, entity->u.class.name, index->name_len);
3245 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3247 /* module name */
3248 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3249 memcpy(ptrW, dll->name, data->module_len);
3250 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3252 /* versioned name */
3253 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3254 if (entity->u.class.versioned)
3256 get_assembly_version(assembly, ptrW);
3257 strcatW(ptrW, exclW);
3258 strcatW(ptrW, entity->u.class.name);
3260 else
3262 memcpy(ptrW, entity->u.class.name, index->name_len);
3263 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3266 name_offset += sizeof(*data);
3267 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3269 index++;
3275 *section = header;
3277 return STATUS_SUCCESS;
3280 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3281 PACTCTX_SECTION_KEYED_DATA data)
3283 struct string_index *iter, *index = NULL;
3284 struct wndclass_redirect_data *class;
3285 ULONG hash;
3286 int i;
3288 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3290 if (!actctx->wndclass_section)
3292 struct strsection_header *section;
3294 NTSTATUS status = build_wndclass_section(actctx, &section);
3295 if (status) return status;
3297 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3298 RtlFreeHeap(GetProcessHeap(), 0, section);
3301 hash = 0;
3302 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3303 iter = get_wndclass_first_index(actctx);
3305 for (i = 0; i < actctx->wndclass_section->count; i++)
3307 if (iter->hash == hash)
3309 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3311 if (!strcmpW(nameW, name->Buffer))
3313 index = iter;
3314 break;
3316 else
3317 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3319 iter++;
3322 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3324 class = get_wndclass_data(actctx, index);
3326 data->ulDataFormatVersion = 1;
3327 data->lpData = class;
3328 /* full length includes string length with nulls */
3329 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3330 data->lpSectionGlobalData = NULL;
3331 data->ulSectionGlobalDataLength = 0;
3332 data->lpSectionBase = actctx->wndclass_section;
3333 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3334 data->hActCtx = NULL;
3336 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3337 data->ulAssemblyRosterIndex = index->rosterindex;
3339 return STATUS_SUCCESS;
3342 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3344 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3345 struct guidsection_header *header;
3346 ULONG module_offset, data_offset;
3347 struct tlibredirect_data *data;
3348 struct guid_index *index;
3350 /* compute section length */
3351 for (i = 0; i < actctx->num_assemblies; i++)
3353 struct assembly *assembly = &actctx->assemblies[i];
3354 for (j = 0; j < assembly->num_dlls; j++)
3356 struct dll_redirect *dll = &assembly->dlls[j];
3357 for (k = 0; k < dll->entities.num; k++)
3359 struct entity *entity = &dll->entities.base[k];
3360 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3362 /* each entry needs index, data and string data for module name and help string */
3363 total_len += sizeof(*index);
3364 total_len += sizeof(*data);
3365 /* help string is stored separately */
3366 if (*entity->u.typelib.helpdir)
3367 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3369 /* module names are packed one after another */
3370 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3372 tlib_count++;
3378 total_len += aligned_string_len(names_len);
3379 total_len += sizeof(*header);
3381 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3382 if (!header) return STATUS_NO_MEMORY;
3384 memset(header, 0, sizeof(*header));
3385 header->magic = GUIDSECTION_MAGIC;
3386 header->size = sizeof(*header);
3387 header->count = tlib_count;
3388 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3389 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3390 module_offset = sizeof(*header);
3391 data_offset = header->index_offset + tlib_count*sizeof(*index);
3393 for (i = 0; i < actctx->num_assemblies; i++)
3395 struct assembly *assembly = &actctx->assemblies[i];
3396 for (j = 0; j < assembly->num_dlls; j++)
3398 struct dll_redirect *dll = &assembly->dlls[j];
3399 for (k = 0; k < dll->entities.num; k++)
3401 struct entity *entity = &dll->entities.base[k];
3402 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3404 ULONG module_len, help_len;
3405 UNICODE_STRING str;
3406 WCHAR *ptrW;
3408 if (*entity->u.typelib.helpdir)
3409 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3410 else
3411 help_len = 0;
3413 module_len = strlenW(dll->name)*sizeof(WCHAR);
3415 /* setup new index entry */
3416 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3417 RtlGUIDFromString(&str, &index->guid);
3418 index->data_offset = data_offset;
3419 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3420 index->rosterindex = i + 1;
3422 /* setup data */
3423 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3424 data->size = sizeof(*data);
3425 data->res = 0;
3426 data->name_len = module_len;
3427 data->name_offset = module_offset;
3428 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3429 data->langid = 0;
3430 data->flags = entity->u.typelib.flags;
3431 data->help_len = help_len;
3432 data->help_offset = sizeof(*data);
3433 data->major_version = entity->u.typelib.major;
3434 data->minor_version = entity->u.typelib.minor;
3436 /* module name */
3437 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3438 memcpy(ptrW, dll->name, data->name_len);
3439 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3441 /* help string */
3442 if (data->help_len)
3444 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3445 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3446 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3449 data_offset += sizeof(*data);
3450 if (help_len)
3451 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3453 module_offset += module_len + sizeof(WCHAR);
3455 index++;
3461 *section = header;
3463 return STATUS_SUCCESS;
3466 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3468 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3471 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3473 struct guid_index *index = NULL;
3474 struct tlibredirect_data *tlib;
3476 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3478 if (!actctx->tlib_section)
3480 struct guidsection_header *section;
3482 NTSTATUS status = build_tlib_section(actctx, &section);
3483 if (status) return status;
3485 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3486 RtlFreeHeap(GetProcessHeap(), 0, section);
3489 index = find_guid_index(actctx->tlib_section, guid);
3490 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3492 tlib = get_tlib_data(actctx, index);
3494 data->ulDataFormatVersion = 1;
3495 data->lpData = tlib;
3496 /* full length includes string length with nulls */
3497 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3498 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3499 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3500 data->lpSectionBase = actctx->tlib_section;
3501 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3502 data->hActCtx = NULL;
3504 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3505 data->ulAssemblyRosterIndex = index->rosterindex;
3507 return STATUS_SUCCESS;
3510 static void generate_uuid(ULONG *seed, GUID *guid)
3512 ULONG *ptr = (ULONG*)guid;
3513 int i;
3515 /* GUID is 16 bytes long */
3516 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3517 *ptr = RtlUniform(seed);
3519 guid->Data3 &= 0x0fff;
3520 guid->Data3 |= (4 << 12);
3521 guid->Data4[0] &= 0x3f;
3522 guid->Data4[0] |= 0x80;
3525 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3526 unsigned int *count, unsigned int *len, unsigned int *module_len)
3528 unsigned int i;
3530 for (i = 0; i < entities->num; i++)
3532 struct entity *entity = &entities->base[i];
3533 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3535 /* each entry needs two index entries, extra one goes for alias GUID */
3536 *len += 2*sizeof(struct guid_index);
3537 /* To save some memory we don't allocated two data structures,
3538 instead alias index and normal index point to the same data structure. */
3539 *len += sizeof(struct comclassredirect_data);
3541 /* for clrClass store some more */
3542 if (entity->u.comclass.name)
3544 unsigned int str_len;
3546 /* all string data is stored together in aligned block */
3547 str_len = strlenW(entity->u.comclass.name)+1;
3548 if (entity->u.comclass.progid)
3549 str_len += strlenW(entity->u.comclass.progid)+1;
3550 if (entity->u.comclass.version)
3551 str_len += strlenW(entity->u.comclass.version)+1;
3553 *len += sizeof(struct clrclass_data);
3554 *len += aligned_string_len(str_len*sizeof(WCHAR));
3556 /* module name is forced to mscoree.dll, and stored two times with different case */
3557 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3559 else
3561 /* progid string is stored separately */
3562 if (entity->u.comclass.progid)
3563 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3565 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3568 *count += 1;
3573 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3574 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3575 ULONG *seed, ULONG rosterindex)
3577 unsigned int i;
3579 for (i = 0; i < entities->num; i++)
3581 struct entity *entity = &entities->base[i];
3582 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3584 ULONG module_len, progid_len, str_len = 0;
3585 struct comclassredirect_data *data;
3586 struct guid_index *alias_index;
3587 struct clrclass_data *clrdata;
3588 UNICODE_STRING str;
3589 WCHAR *ptrW;
3591 if (entity->u.comclass.progid)
3592 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3593 else
3594 progid_len = 0;
3596 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3598 /* setup new index entry */
3599 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3600 RtlGUIDFromString(&str, &(*index)->guid);
3602 (*index)->data_offset = *data_offset;
3603 (*index)->data_len = sizeof(*data); /* additional length added later */
3604 (*index)->rosterindex = rosterindex;
3606 /* Setup new index entry for alias guid. Alias index records are placed after
3607 normal records, so normal guids are hit first on search. Note that class count
3608 is doubled. */
3609 alias_index = (*index) + section->count/2;
3610 generate_uuid(seed, &alias_index->guid);
3611 alias_index->data_offset = (*index)->data_offset;
3612 alias_index->data_len = 0;
3613 alias_index->rosterindex = (*index)->rosterindex;
3615 /* setup data */
3616 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3617 data->size = sizeof(*data);
3618 data->res = 0;
3619 data->res1[0] = 0;
3620 data->res1[1] = 0;
3621 data->model = entity->u.comclass.model;
3622 data->clsid = (*index)->guid;
3623 data->alias = alias_index->guid;
3624 data->clsid2 = data->clsid;
3625 if (entity->u.comclass.tlbid)
3627 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3628 RtlGUIDFromString(&str, &data->tlbid);
3630 else
3631 memset(&data->tlbid, 0, sizeof(data->tlbid));
3632 data->name_len = module_len;
3633 data->name_offset = *module_offset;
3634 data->progid_len = progid_len;
3635 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3636 data->clrdata_len = 0; /* will be set later */
3637 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3638 data->miscstatus = entity->u.comclass.miscstatus;
3639 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3640 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3641 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3642 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3644 /* mask describes which misc* data is available */
3645 data->miscmask = 0;
3646 if (data->miscstatus)
3647 data->miscmask |= MiscStatus;
3648 if (data->miscstatuscontent)
3649 data->miscmask |= MiscStatusContent;
3650 if (data->miscstatusthumbnail)
3651 data->miscmask |= MiscStatusThumbnail;
3652 if (data->miscstatusicon)
3653 data->miscmask |= MiscStatusIcon;
3654 if (data->miscstatusdocprint)
3655 data->miscmask |= MiscStatusDocPrint;
3657 if (data->clrdata_offset)
3659 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3661 clrdata->size = sizeof(*clrdata);
3662 clrdata->res[0] = 0;
3663 clrdata->res[1] = 2; /* FIXME: unknown field */
3664 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3665 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3666 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3667 clrdata->name_offset = clrdata->size;
3668 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3669 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3670 clrdata->res2[0] = 0;
3671 clrdata->res2[1] = 0;
3673 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3675 /* module name */
3676 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3677 memcpy(ptrW, mscoree2W, clrdata->module_len);
3678 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3680 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3681 memcpy(ptrW, mscoreeW, data->name_len);
3682 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3684 /* class name */
3685 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3686 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3687 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3689 /* runtime version, optional */
3690 if (clrdata->version_len)
3692 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3694 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3695 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3696 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3699 if (data->progid_len)
3700 data->progid_offset += data->clrdata_len;
3701 (*index)->data_len += sizeof(*clrdata);
3703 else
3705 clrdata = NULL;
3707 /* module name */
3708 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3709 memcpy(ptrW, dll->name, data->name_len);
3710 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3713 /* progid string */
3714 if (data->progid_len)
3716 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3717 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3718 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3721 /* string block length */
3722 str_len = 0;
3723 if (clrdata)
3725 str_len += clrdata->name_len + sizeof(WCHAR);
3726 if (clrdata->version_len)
3727 str_len += clrdata->version_len + sizeof(WCHAR);
3729 if (progid_len)
3730 str_len += progid_len + sizeof(WCHAR);
3732 (*index)->data_len += aligned_string_len(str_len);
3733 alias_index->data_len = (*index)->data_len;
3735 /* move to next data record */
3736 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3737 (*module_offset) += module_len + sizeof(WCHAR);
3739 if (clrdata)
3741 (*data_offset) += sizeof(*clrdata);
3742 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3744 (*index) += 1;
3749 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3751 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3752 struct guidsection_header *header;
3753 ULONG module_offset, data_offset;
3754 struct guid_index *index;
3755 ULONG seed;
3757 /* compute section length */
3758 for (i = 0; i < actctx->num_assemblies; i++)
3760 struct assembly *assembly = &actctx->assemblies[i];
3761 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3762 for (j = 0; j < assembly->num_dlls; j++)
3764 struct dll_redirect *dll = &assembly->dlls[j];
3765 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3769 total_len += aligned_string_len(names_len);
3770 total_len += sizeof(*header);
3772 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3773 if (!header) return STATUS_NO_MEMORY;
3775 memset(header, 0, sizeof(*header));
3776 header->magic = GUIDSECTION_MAGIC;
3777 header->size = sizeof(*header);
3778 header->count = 2*class_count;
3779 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3780 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3781 module_offset = sizeof(*header);
3782 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3784 seed = NtGetTickCount();
3785 for (i = 0; i < actctx->num_assemblies; i++)
3787 struct assembly *assembly = &actctx->assemblies[i];
3788 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3789 for (j = 0; j < assembly->num_dlls; j++)
3791 struct dll_redirect *dll = &assembly->dlls[j];
3792 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3796 *section = header;
3798 return STATUS_SUCCESS;
3801 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3803 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3806 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3808 struct comclassredirect_data *comclass;
3809 struct guid_index *index = NULL;
3811 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3813 if (!actctx->comserver_section)
3815 struct guidsection_header *section;
3817 NTSTATUS status = build_comserver_section(actctx, &section);
3818 if (status) return status;
3820 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3821 RtlFreeHeap(GetProcessHeap(), 0, section);
3824 index = find_guid_index(actctx->comserver_section, guid);
3825 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3827 comclass = get_comclass_data(actctx, index);
3829 data->ulDataFormatVersion = 1;
3830 data->lpData = comclass;
3831 /* full length includes string length with nulls */
3832 data->ulLength = comclass->size + comclass->clrdata_len;
3833 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
3834 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3835 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3836 data->lpSectionBase = actctx->comserver_section;
3837 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3838 data->hActCtx = NULL;
3840 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3841 data->ulAssemblyRosterIndex = index->rosterindex;
3843 return STATUS_SUCCESS;
3846 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3848 unsigned int i;
3850 for (i = 0; i < entities->num; i++)
3852 struct entity *entity = &entities->base[i];
3853 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3855 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3856 if (entity->u.ifaceps.name)
3857 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3858 *count += 1;
3863 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3864 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3866 unsigned int i;
3868 for (i = 0; i < entities->num; i++)
3870 struct entity *entity = &entities->base[i];
3871 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3873 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3874 UNICODE_STRING str;
3875 ULONG name_len;
3877 if (entity->u.ifaceps.name)
3878 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3879 else
3880 name_len = 0;
3882 /* setup index */
3883 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3884 RtlGUIDFromString(&str, &(*index)->guid);
3885 (*index)->data_offset = *data_offset;
3886 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3887 (*index)->rosterindex = rosterindex;
3889 /* setup data record */
3890 data->size = sizeof(*data);
3891 data->mask = entity->u.ifaceps.mask;
3893 /* proxyStubClsid32 value is only stored for external PS,
3894 if set it's used as iid, otherwise 'iid' attribute value is used */
3895 if (entity->u.ifaceps.ps32)
3897 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3898 RtlGUIDFromString(&str, &data->iid);
3900 else
3901 data->iid = (*index)->guid;
3903 data->nummethods = entity->u.ifaceps.nummethods;
3905 if (entity->u.ifaceps.tlib)
3907 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3908 RtlGUIDFromString(&str, &data->tlbid);
3910 else
3911 memset(&data->tlbid, 0, sizeof(data->tlbid));
3913 if (entity->u.ifaceps.base)
3915 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3916 RtlGUIDFromString(&str, &data->base);
3918 else
3919 memset(&data->base, 0, sizeof(data->base));
3921 data->name_len = name_len;
3922 data->name_offset = data->name_len ? sizeof(*data) : 0;
3924 /* name string */
3925 if (data->name_len)
3927 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3928 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3929 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3932 /* move to next record */
3933 (*index) += 1;
3934 *data_offset += sizeof(*data);
3935 if (data->name_len)
3936 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3941 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3943 unsigned int i, j, total_len = 0, count = 0;
3944 struct guidsection_header *header;
3945 struct guid_index *index;
3946 ULONG data_offset;
3948 /* compute section length */
3949 for (i = 0; i < actctx->num_assemblies; i++)
3951 struct assembly *assembly = &actctx->assemblies[i];
3953 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3954 for (j = 0; j < assembly->num_dlls; j++)
3956 struct dll_redirect *dll = &assembly->dlls[j];
3957 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3961 total_len += sizeof(*header);
3963 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3964 if (!header) return STATUS_NO_MEMORY;
3966 memset(header, 0, sizeof(*header));
3967 header->magic = GUIDSECTION_MAGIC;
3968 header->size = sizeof(*header);
3969 header->count = count;
3970 header->index_offset = sizeof(*header);
3971 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3972 data_offset = header->index_offset + count*sizeof(*index);
3974 for (i = 0; i < actctx->num_assemblies; i++)
3976 struct assembly *assembly = &actctx->assemblies[i];
3978 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
3979 for (j = 0; j < assembly->num_dlls; j++)
3981 struct dll_redirect *dll = &assembly->dlls[j];
3982 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
3986 *section = header;
3988 return STATUS_SUCCESS;
3991 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3993 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
3996 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3998 struct ifacepsredirect_data *iface;
3999 struct guid_index *index = NULL;
4001 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4003 if (!actctx->ifaceps_section)
4005 struct guidsection_header *section;
4007 NTSTATUS status = build_ifaceps_section(actctx, &section);
4008 if (status) return status;
4010 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4011 RtlFreeHeap(GetProcessHeap(), 0, section);
4014 index = find_guid_index(actctx->ifaceps_section, guid);
4015 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4017 iface = get_ifaceps_data(actctx, index);
4019 data->ulDataFormatVersion = 1;
4020 data->lpData = iface;
4021 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4022 data->lpSectionGlobalData = NULL;
4023 data->ulSectionGlobalDataLength = 0;
4024 data->lpSectionBase = actctx->ifaceps_section;
4025 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4026 data->hActCtx = NULL;
4028 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4029 data->ulAssemblyRosterIndex = index->rosterindex;
4031 return STATUS_SUCCESS;
4034 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4036 unsigned int i, j, total_len = 0, count = 0;
4037 struct guidsection_header *header;
4038 struct clrsurrogate_data *data;
4039 struct guid_index *index;
4040 ULONG data_offset;
4042 /* compute section length */
4043 for (i = 0; i < actctx->num_assemblies; i++)
4045 struct assembly *assembly = &actctx->assemblies[i];
4046 for (j = 0; j < assembly->entities.num; j++)
4048 struct entity *entity = &assembly->entities.base[j];
4049 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4051 ULONG len;
4053 total_len += sizeof(*index) + sizeof(*data);
4054 len = strlenW(entity->u.clrsurrogate.name) + 1;
4055 if (entity->u.clrsurrogate.version)
4056 len += strlenW(entity->u.clrsurrogate.version) + 1;
4057 total_len += aligned_string_len(len*sizeof(WCHAR));
4059 count++;
4064 total_len += sizeof(*header);
4066 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4067 if (!header) return STATUS_NO_MEMORY;
4069 memset(header, 0, sizeof(*header));
4070 header->magic = GUIDSECTION_MAGIC;
4071 header->size = sizeof(*header);
4072 header->count = count;
4073 header->index_offset = sizeof(*header);
4074 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4075 data_offset = header->index_offset + count*sizeof(*index);
4077 for (i = 0; i < actctx->num_assemblies; i++)
4079 struct assembly *assembly = &actctx->assemblies[i];
4080 for (j = 0; j < assembly->entities.num; j++)
4082 struct entity *entity = &assembly->entities.base[j];
4083 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4085 ULONG version_len, name_len;
4086 UNICODE_STRING str;
4087 WCHAR *ptrW;
4089 if (entity->u.clrsurrogate.version)
4090 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4091 else
4092 version_len = 0;
4093 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4095 /* setup new index entry */
4096 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4097 RtlGUIDFromString(&str, &index->guid);
4099 index->data_offset = data_offset;
4100 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4101 index->rosterindex = i + 1;
4103 /* setup data */
4104 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4105 data->size = sizeof(*data);
4106 data->res = 0;
4107 data->clsid = index->guid;
4108 data->version_offset = version_len ? data->size : 0;
4109 data->version_len = version_len;
4110 data->name_offset = data->size + version_len;
4111 if (version_len)
4112 data->name_offset += sizeof(WCHAR);
4113 data->name_len = name_len;
4115 /* surrogate name */
4116 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4117 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4118 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4120 /* runtime version */
4121 if (data->version_len)
4123 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4124 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4125 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4128 data_offset += index->data_offset;
4129 index++;
4134 *section = header;
4136 return STATUS_SUCCESS;
4139 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4141 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4144 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4146 struct clrsurrogate_data *surrogate;
4147 struct guid_index *index = NULL;
4149 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4151 if (!actctx->clrsurrogate_section)
4153 struct guidsection_header *section;
4155 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4156 if (status) return status;
4158 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4159 RtlFreeHeap(GetProcessHeap(), 0, section);
4162 index = find_guid_index(actctx->clrsurrogate_section, guid);
4163 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4165 surrogate = get_surrogate_data(actctx, index);
4167 data->ulDataFormatVersion = 1;
4168 data->lpData = surrogate;
4169 /* full length includes string length with nulls */
4170 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4171 if (surrogate->version_len)
4172 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4174 data->lpSectionGlobalData = NULL;
4175 data->ulSectionGlobalDataLength = 0;
4176 data->lpSectionBase = actctx->clrsurrogate_section;
4177 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4178 data->hActCtx = NULL;
4180 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4181 data->ulAssemblyRosterIndex = index->rosterindex;
4183 return STATUS_SUCCESS;
4186 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4188 unsigned int i, j, single_len;
4190 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4191 for (i = 0; i < entities->num; i++)
4193 struct entity *entity = &entities->base[i];
4194 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4196 if (entity->u.comclass.progid)
4198 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4199 *count += 1;
4202 for (j = 0; j < entity->u.comclass.progids.num; j++)
4203 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4205 *total_len += single_len*entity->u.comclass.progids.num;
4206 *count += entity->u.comclass.progids.num;
4211 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4212 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4214 struct progidredirect_data *data;
4215 UNICODE_STRING str;
4216 GUID *guid_ptr;
4217 WCHAR *ptrW;
4219 /* setup new index entry */
4221 /* hash progid name */
4222 RtlInitUnicodeString(&str, progid);
4223 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4225 (*index)->name_offset = *data_offset;
4226 (*index)->name_len = str.Length;
4227 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4228 (*index)->data_len = sizeof(*data);
4229 (*index)->rosterindex = rosterindex;
4231 *data_offset += aligned_string_len(str.MaximumLength);
4233 /* setup data structure */
4234 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4235 data->size = sizeof(*data);
4236 data->reserved = 0;
4237 data->clsid_offset = *global_offset;
4239 /* write progid string */
4240 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4241 memcpy(ptrW, progid, (*index)->name_len);
4242 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4244 /* write guid to global area */
4245 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4246 *guid_ptr = *alias;
4248 /* to next entry */
4249 *global_offset += sizeof(GUID);
4250 *data_offset += data->size;
4251 (*index) += 1;
4254 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4255 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4257 unsigned int i, j;
4259 for (i = 0; i < entities->num; i++)
4261 struct entity *entity = &entities->base[i];
4262 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4264 const struct progids *progids = &entity->u.comclass.progids;
4265 struct comclassredirect_data *comclass;
4266 struct guid_index *guid_index;
4267 UNICODE_STRING str;
4268 GUID clsid;
4270 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4271 RtlGUIDFromString(&str, &clsid);
4273 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4274 comclass = get_comclass_data(actctx, guid_index);
4276 if (entity->u.comclass.progid)
4277 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4278 index, data_offset, global_offset, rosterindex);
4280 for (j = 0; j < progids->num; j++)
4281 write_progid_record(section, progids->progids[j], &comclass->alias,
4282 index, data_offset, global_offset, rosterindex);
4287 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4289 unsigned int i, j, total_len = 0, count = 0;
4290 struct strsection_header *header;
4291 ULONG data_offset, global_offset;
4292 struct string_index *index;
4294 /* compute section length */
4295 for (i = 0; i < actctx->num_assemblies; i++)
4297 struct assembly *assembly = &actctx->assemblies[i];
4299 get_progid_datalen(&assembly->entities, &count, &total_len);
4300 for (j = 0; j < assembly->num_dlls; j++)
4302 struct dll_redirect *dll = &assembly->dlls[j];
4303 get_progid_datalen(&dll->entities, &count, &total_len);
4307 total_len += sizeof(*header);
4309 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4310 if (!header) return STATUS_NO_MEMORY;
4312 memset(header, 0, sizeof(*header));
4313 header->magic = STRSECTION_MAGIC;
4314 header->size = sizeof(*header);
4315 header->count = count;
4316 header->global_offset = header->size;
4317 header->global_len = count*sizeof(GUID);
4318 header->index_offset = header->size + header->global_len;
4320 index = (struct string_index*)((BYTE*)header + header->index_offset);
4321 data_offset = header->index_offset + count*sizeof(*index);
4322 global_offset = header->global_offset;
4324 for (i = 0; i < actctx->num_assemblies; i++)
4326 struct assembly *assembly = &actctx->assemblies[i];
4328 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4329 for (j = 0; j < assembly->num_dlls; j++)
4331 struct dll_redirect *dll = &assembly->dlls[j];
4332 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4336 *section = header;
4338 return STATUS_SUCCESS;
4341 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4343 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4346 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4347 PACTCTX_SECTION_KEYED_DATA data)
4349 struct progidredirect_data *progid;
4350 struct string_index *index;
4352 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4354 if (!actctx->comserver_section)
4356 struct guidsection_header *section;
4358 NTSTATUS status = build_comserver_section(actctx, &section);
4359 if (status) return status;
4361 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4362 RtlFreeHeap(GetProcessHeap(), 0, section);
4365 if (!actctx->progid_section)
4367 struct strsection_header *section;
4369 NTSTATUS status = build_progid_section(actctx, &section);
4370 if (status) return status;
4372 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4373 RtlFreeHeap(GetProcessHeap(), 0, section);
4376 index = find_string_index(actctx->progid_section, name);
4377 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4379 progid = get_progid_data(actctx, index);
4381 data->ulDataFormatVersion = 1;
4382 data->lpData = progid;
4383 data->ulLength = progid->size;
4384 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4385 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4386 data->lpSectionBase = actctx->progid_section;
4387 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4388 data->hActCtx = NULL;
4390 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4391 data->ulAssemblyRosterIndex = index->rosterindex;
4393 return STATUS_SUCCESS;
4396 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4397 const UNICODE_STRING *section_name,
4398 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4400 NTSTATUS status;
4402 switch (section_kind)
4404 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4405 status = find_dll_redirection(actctx, section_name, data);
4406 break;
4407 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4408 status = find_window_class(actctx, section_name, data);
4409 break;
4410 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4411 status = find_progid_redirection(actctx, section_name, data);
4412 break;
4413 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4414 FIXME("Unsupported yet section_kind %x\n", section_kind);
4415 return STATUS_SXS_SECTION_NOT_FOUND;
4416 default:
4417 WARN("Unknown section_kind %x\n", section_kind);
4418 return STATUS_SXS_SECTION_NOT_FOUND;
4421 if (status != STATUS_SUCCESS) return status;
4423 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4425 actctx_addref(actctx);
4426 data->hActCtx = actctx;
4428 return STATUS_SUCCESS;
4431 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4432 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4434 NTSTATUS status;
4436 switch (section_kind)
4438 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4439 status = find_tlib_redirection(actctx, guid, data);
4440 break;
4441 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4442 status = find_comserver_redirection(actctx, guid, data);
4443 break;
4444 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4445 status = find_cominterface_redirection(actctx, guid, data);
4446 break;
4447 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4448 status = find_clr_surrogate(actctx, guid, data);
4449 break;
4450 default:
4451 WARN("Unknown section_kind %x\n", section_kind);
4452 return STATUS_SXS_SECTION_NOT_FOUND;
4455 if (status != STATUS_SUCCESS) return status;
4457 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4459 actctx_addref(actctx);
4460 data->hActCtx = actctx;
4462 return STATUS_SUCCESS;
4465 /* initialize the activation context for the current process */
4466 void actctx_init(void)
4468 ACTCTXW ctx;
4469 HANDLE handle;
4471 ctx.cbSize = sizeof(ctx);
4472 ctx.lpSource = NULL;
4473 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4474 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4475 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4477 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4481 /***********************************************************************
4482 * RtlCreateActivationContext (NTDLL.@)
4484 * Create an activation context.
4486 * FIXME: function signature/prototype is wrong
4488 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4490 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4491 const WCHAR *directory = NULL;
4492 ACTIVATION_CONTEXT *actctx;
4493 UNICODE_STRING nameW;
4494 ULONG lang = 0;
4495 NTSTATUS status = STATUS_NO_MEMORY;
4496 HANDLE file = 0;
4497 struct actctx_loader acl;
4499 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4501 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4502 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4503 return STATUS_INVALID_PARAMETER;
4505 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4506 return STATUS_NO_MEMORY;
4508 actctx->magic = ACTCTX_MAGIC;
4509 actctx->ref_count = 1;
4510 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4511 actctx->config.info = NULL;
4512 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4513 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4515 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4517 else
4519 UNICODE_STRING dir;
4520 WCHAR *p;
4521 HMODULE module;
4523 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4524 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4526 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4527 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4528 actctx->appdir.info = dir.Buffer;
4531 nameW.Buffer = NULL;
4533 /* open file only if it's going to be used */
4534 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4535 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4537 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
4539 status = STATUS_NO_SUCH_FILE;
4540 goto error;
4542 status = open_nt_file( &file, &nameW );
4543 if (status)
4545 RtlFreeUnicodeString( &nameW );
4546 goto error;
4550 acl.actctx = actctx;
4551 acl.dependencies = NULL;
4552 acl.num_dependencies = 0;
4553 acl.allocated_dependencies = 0;
4555 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4556 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4558 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4560 /* if we have a resource it's a PE file */
4561 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4563 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4564 pActCtx->lpResourceName, lang );
4565 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4566 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4567 pActCtx->hModule, pActCtx->lpResourceName );
4569 else if (pActCtx->lpSource)
4571 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4572 file, pActCtx->lpResourceName, lang );
4573 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4574 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4575 NULL, pActCtx->lpResourceName );
4577 else status = STATUS_INVALID_PARAMETER;
4579 else
4581 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4584 if (file) NtClose( file );
4585 RtlFreeUnicodeString( &nameW );
4587 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4588 free_depend_manifests( &acl );
4590 if (status == STATUS_SUCCESS) *handle = actctx;
4591 else actctx_release( actctx );
4592 return status;
4594 error:
4595 if (file) NtClose( file );
4596 actctx_release( actctx );
4597 return status;
4601 /***********************************************************************
4602 * RtlAddRefActivationContext (NTDLL.@)
4604 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4606 ACTIVATION_CONTEXT *actctx;
4608 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4612 /******************************************************************
4613 * RtlReleaseActivationContext (NTDLL.@)
4615 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4617 ACTIVATION_CONTEXT *actctx;
4619 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4622 /******************************************************************
4623 * RtlZombifyActivationContext (NTDLL.@)
4625 * FIXME: function prototype might be wrong
4627 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4629 FIXME("%p: stub\n", handle);
4630 return STATUS_NOT_IMPLEMENTED;
4633 /******************************************************************
4634 * RtlActivateActivationContext (NTDLL.@)
4636 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4638 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4640 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4641 return STATUS_NO_MEMORY;
4643 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4644 frame->ActivationContext = handle;
4645 frame->Flags = 0;
4646 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4647 RtlAddRefActivationContext( handle );
4649 *cookie = (ULONG_PTR)frame;
4650 TRACE( "%p cookie=%lx\n", handle, *cookie );
4651 return STATUS_SUCCESS;
4655 /***********************************************************************
4656 * RtlDeactivateActivationContext (NTDLL.@)
4658 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4660 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4662 TRACE( "%x cookie=%lx\n", flags, cookie );
4664 /* find the right frame */
4665 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4666 for (frame = top; frame; frame = frame->Previous)
4667 if ((ULONG_PTR)frame == cookie) break;
4669 if (!frame)
4670 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4672 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4673 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4675 /* pop everything up to and including frame */
4676 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4678 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4680 frame = top->Previous;
4681 RtlReleaseActivationContext( top->ActivationContext );
4682 RtlFreeHeap( GetProcessHeap(), 0, top );
4683 top = frame;
4688 /******************************************************************
4689 * RtlFreeThreadActivationContextStack (NTDLL.@)
4691 void WINAPI RtlFreeThreadActivationContextStack(void)
4693 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4695 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4696 while (frame)
4698 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4699 RtlReleaseActivationContext( frame->ActivationContext );
4700 RtlFreeHeap( GetProcessHeap(), 0, frame );
4701 frame = prev;
4703 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4707 /******************************************************************
4708 * RtlGetActiveActivationContext (NTDLL.@)
4710 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4712 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4714 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4715 RtlAddRefActivationContext( *handle );
4717 else
4718 *handle = 0;
4720 return STATUS_SUCCESS;
4724 /******************************************************************
4725 * RtlIsActivationContextActive (NTDLL.@)
4727 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4729 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4731 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4732 if (frame->ActivationContext == handle) return TRUE;
4733 return FALSE;
4737 /***********************************************************************
4738 * RtlQueryInformationActivationContext (NTDLL.@)
4740 * Get information about an activation context.
4741 * FIXME: function signature/prototype may be wrong
4743 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4744 ULONG class, PVOID buffer,
4745 SIZE_T bufsize, SIZE_T *retlen )
4747 ACTIVATION_CONTEXT *actctx;
4748 NTSTATUS status;
4750 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4751 subinst, class, buffer, bufsize, retlen);
4753 if (retlen) *retlen = 0;
4754 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4756 switch (class)
4758 case ActivationContextBasicInformation:
4760 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4762 if (retlen) *retlen = sizeof(*info);
4763 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4765 info->hActCtx = handle;
4766 info->dwFlags = 0; /* FIXME */
4767 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4769 break;
4771 case ActivationContextDetailedInformation:
4773 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4774 struct assembly *assembly = NULL;
4775 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4776 LPWSTR ptr;
4778 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4780 if (actctx->num_assemblies) assembly = actctx->assemblies;
4782 if (assembly && assembly->manifest.info)
4783 manifest_len = strlenW(assembly->manifest.info) + 1;
4784 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4785 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4786 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4788 if (retlen) *retlen = len;
4789 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4791 acdi->dwFlags = 0;
4792 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4793 acdi->ulAssemblyCount = actctx->num_assemblies;
4794 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4795 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4796 acdi->ulRootConfigurationPathType = actctx->config.type;
4797 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4798 acdi->ulAppDirPathType = actctx->appdir.type;
4799 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4800 ptr = (LPWSTR)(acdi + 1);
4801 if (manifest_len)
4803 acdi->lpRootManifestPath = ptr;
4804 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4805 ptr += manifest_len;
4807 else acdi->lpRootManifestPath = NULL;
4808 if (config_len)
4810 acdi->lpRootConfigurationPath = ptr;
4811 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4812 ptr += config_len;
4814 else acdi->lpRootConfigurationPath = NULL;
4815 if (appdir_len)
4817 acdi->lpAppDirPath = ptr;
4818 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4820 else acdi->lpAppDirPath = NULL;
4822 break;
4824 case AssemblyDetailedInformationInActivationContext:
4826 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4827 struct assembly *assembly;
4828 WCHAR *assembly_id;
4829 DWORD index;
4830 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4831 LPWSTR ptr;
4833 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4834 if (!subinst) return STATUS_INVALID_PARAMETER;
4836 index = *(DWORD*)subinst;
4837 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4839 assembly = &actctx->assemblies[index - 1];
4841 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4842 id_len = strlenW(assembly_id) + 1;
4843 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4845 if (assembly->manifest.info &&
4846 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4847 path_len = strlenW(assembly->manifest.info) + 1;
4849 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4851 if (retlen) *retlen = len;
4852 if (!buffer || bufsize < len)
4854 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4855 return STATUS_BUFFER_TOO_SMALL;
4858 afdi->ulFlags = 0; /* FIXME */
4859 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4860 afdi->ulManifestPathType = assembly->manifest.type;
4861 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4862 /* FIXME afdi->liManifestLastWriteTime = 0; */
4863 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4864 afdi->ulPolicyPathLength = 0;
4865 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4866 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4867 afdi->ulManifestVersionMajor = 1;
4868 afdi->ulManifestVersionMinor = 0;
4869 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4870 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4871 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4872 ptr = (LPWSTR)(afdi + 1);
4873 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4874 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4875 ptr += id_len;
4876 if (path_len)
4878 afdi->lpAssemblyManifestPath = ptr;
4879 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4880 ptr += path_len;
4881 } else afdi->lpAssemblyManifestPath = NULL;
4882 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4883 if (ad_len)
4885 afdi->lpAssemblyDirectoryName = ptr;
4886 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4888 else afdi->lpAssemblyDirectoryName = NULL;
4889 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4891 break;
4893 case FileInformationInAssemblyOfAssemblyInActivationContext:
4895 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4896 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4897 struct assembly *assembly;
4898 struct dll_redirect *dll;
4899 SIZE_T len, dll_len = 0;
4900 LPWSTR ptr;
4902 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4903 if (!acqi) return STATUS_INVALID_PARAMETER;
4905 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4906 return STATUS_INVALID_PARAMETER;
4907 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4909 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4910 return STATUS_INVALID_PARAMETER;
4911 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4913 if (dll->name) dll_len = strlenW(dll->name) + 1;
4914 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4916 if (!buffer || bufsize < len)
4918 if (retlen) *retlen = len;
4919 return STATUS_BUFFER_TOO_SMALL;
4921 if (retlen) *retlen = 0; /* yes that's what native does !! */
4922 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4923 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4924 afdi->ulPathLength = 0; /* FIXME */
4925 ptr = (LPWSTR)(afdi + 1);
4926 if (dll_len)
4928 afdi->lpFileName = ptr;
4929 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4930 } else afdi->lpFileName = NULL;
4931 afdi->lpFilePath = NULL; /* FIXME */
4933 break;
4935 default:
4936 FIXME( "class %u not implemented\n", class );
4937 return STATUS_NOT_IMPLEMENTED;
4939 return STATUS_SUCCESS;
4942 /***********************************************************************
4943 * RtlFindActivationContextSectionString (NTDLL.@)
4945 * Find information about a string in an activation context.
4946 * FIXME: function signature/prototype may be wrong
4948 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
4949 const UNICODE_STRING *section_name, PVOID ptr )
4951 PACTCTX_SECTION_KEYED_DATA data = ptr;
4952 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4954 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
4955 debugstr_us(section_name), data);
4957 if (guid)
4959 FIXME("expected guid == NULL\n");
4960 return STATUS_INVALID_PARAMETER;
4962 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4964 FIXME("unknown flags %08x\n", flags);
4965 return STATUS_INVALID_PARAMETER;
4967 if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
4968 !section_name || !section_name->Buffer)
4970 WARN("invalid parameter\n");
4971 return STATUS_INVALID_PARAMETER;
4974 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4976 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
4977 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
4980 if (status != STATUS_SUCCESS)
4981 status = find_string( process_actctx, section_kind, section_name, flags, data );
4983 return status;
4986 /***********************************************************************
4987 * RtlFindActivationContextSectionGuid (NTDLL.@)
4989 * Find information about a GUID in an activation context.
4990 * FIXME: function signature/prototype may be wrong
4992 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
4993 const GUID *guid, void *ptr )
4995 ACTCTX_SECTION_KEYED_DATA *data = ptr;
4996 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4998 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5000 if (extguid)
5002 FIXME("expected extguid == NULL\n");
5003 return STATUS_INVALID_PARAMETER;
5006 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5008 FIXME("unknown flags %08x\n", flags);
5009 return STATUS_INVALID_PARAMETER;
5012 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5013 return STATUS_INVALID_PARAMETER;
5015 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5017 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5018 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5021 if (status != STATUS_SUCCESS)
5022 status = find_guid( process_actctx, section_kind, guid, flags, data );
5024 return status;