ddraw: Return early in d3d_device7_DrawIndexedPrimitiveStrided() with a 0 vertex...
[wine.git] / dlls / ntdll / actctx.c
blob4aa1a72ea7ebe4d8f547339f0a6da5ee0a921e33
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
34 #include "winternl.h"
35 #include "ddk/wdm.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 /* from oaidl.h */
62 typedef enum tagLIBFLAGS {
63 LIBFLAG_FRESTRICTED = 0x1,
64 LIBFLAG_FCONTROL = 0x2,
65 LIBFLAG_FHIDDEN = 0x4,
66 LIBFLAG_FHASDISKIMAGE = 0x8
67 } LIBFLAGS;
69 /* from oleidl.idl */
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE = 0x1,
73 OLEMISC_ONLYICONIC = 0x2,
74 OLEMISC_INSERTNOTREPLACE = 0x4,
75 OLEMISC_STATIC = 0x8,
76 OLEMISC_CANTLINKINSIDE = 0x10,
77 OLEMISC_CANLINKBYOLE1 = 0x20,
78 OLEMISC_ISLINKOBJECT = 0x40,
79 OLEMISC_INSIDEOUT = 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
82 OLEMISC_INVISIBLEATRUNTIME = 0x400,
83 OLEMISC_ALWAYSRUN = 0x800,
84 OLEMISC_ACTSLIKEBUTTON = 0x1000,
85 OLEMISC_ACTSLIKELABEL = 0x2000,
86 OLEMISC_NOUIACTIVATE = 0x4000,
87 OLEMISC_ALIGNABLE = 0x8000,
88 OLEMISC_SIMPLEFRAME = 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
90 OLEMISC_IMEMODE = 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
92 OLEMISC_WANTSTOMENUMERGE = 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
94 } OLEMISC;
96 typedef struct
98 const WCHAR *ptr;
99 unsigned int len;
100 } xmlstr_t;
102 typedef struct
104 const WCHAR *ptr;
105 const WCHAR *end;
106 } xmlbuf_t;
108 struct file_info
110 ULONG type;
111 WCHAR *info;
114 struct assembly_version
116 USHORT major;
117 USHORT minor;
118 USHORT build;
119 USHORT revision;
122 struct assembly_identity
124 WCHAR *name;
125 WCHAR *arch;
126 WCHAR *public_key;
127 WCHAR *language;
128 WCHAR *type;
129 struct assembly_version version;
130 BOOL optional;
131 BOOL delayed;
134 struct strsection_header
136 DWORD magic;
137 ULONG size;
138 DWORD unk1[3];
139 ULONG count;
140 ULONG index_offset;
141 DWORD unk2[2];
142 ULONG global_offset;
143 ULONG global_len;
146 struct string_index
148 ULONG hash; /* key string hash */
149 ULONG name_offset;
150 ULONG name_len;
151 ULONG data_offset; /* redirect data offset */
152 ULONG data_len;
153 ULONG rosterindex;
156 struct guidsection_header
158 DWORD magic;
159 ULONG size;
160 DWORD unk[3];
161 ULONG count;
162 ULONG index_offset;
163 DWORD unk2;
164 ULONG names_offset;
165 ULONG names_len;
168 struct guid_index
170 GUID guid;
171 ULONG data_offset;
172 ULONG data_len;
173 ULONG rosterindex;
176 struct wndclass_redirect_data
178 ULONG size;
179 DWORD res;
180 ULONG name_len;
181 ULONG name_offset; /* versioned name offset */
182 ULONG module_len;
183 ULONG module_offset;/* container name offset */
186 struct dllredirect_data
188 ULONG size;
189 ULONG unk;
190 DWORD res[3];
193 struct tlibredirect_data
195 ULONG size;
196 DWORD res;
197 ULONG name_len;
198 ULONG name_offset;
199 LANGID langid;
200 WORD flags;
201 ULONG help_len;
202 ULONG help_offset;
203 WORD major_version;
204 WORD minor_version;
207 enum comclass_threadingmodel
209 ThreadingModel_Apartment = 1,
210 ThreadingModel_Free = 2,
211 ThreadingModel_No = 3,
212 ThreadingModel_Both = 4,
213 ThreadingModel_Neutral = 5
216 enum comclass_miscfields
218 MiscStatus = 1,
219 MiscStatusIcon = 2,
220 MiscStatusContent = 4,
221 MiscStatusThumbnail = 8,
222 MiscStatusDocPrint = 16
225 struct comclassredirect_data
227 ULONG size;
228 BYTE res;
229 BYTE miscmask;
230 BYTE res1[2];
231 DWORD model;
232 GUID clsid;
233 GUID alias;
234 GUID clsid2;
235 GUID tlbid;
236 ULONG name_len;
237 ULONG name_offset;
238 ULONG progid_len;
239 ULONG progid_offset;
240 ULONG clrdata_len;
241 ULONG clrdata_offset;
242 DWORD miscstatus;
243 DWORD miscstatuscontent;
244 DWORD miscstatusthumbnail;
245 DWORD miscstatusicon;
246 DWORD miscstatusdocprint;
249 enum ifaceps_mask
251 NumMethods = 1,
252 BaseIface = 2
255 struct ifacepsredirect_data
257 ULONG size;
258 DWORD mask;
259 GUID iid;
260 ULONG nummethods;
261 GUID tlbid;
262 GUID base;
263 ULONG name_len;
264 ULONG name_offset;
267 struct clrsurrogate_data
269 ULONG size;
270 DWORD res;
271 GUID clsid;
272 ULONG version_offset;
273 ULONG version_len;
274 ULONG name_offset;
275 ULONG name_len;
278 struct clrclass_data
280 ULONG size;
281 DWORD res[2];
282 ULONG module_len;
283 ULONG module_offset;
284 ULONG name_len;
285 ULONG name_offset;
286 ULONG version_len;
287 ULONG version_offset;
288 DWORD res2[2];
291 struct progidredirect_data
293 ULONG size;
294 DWORD reserved;
295 ULONG clsid_offset;
300 Sections structure.
302 Sections are accessible by string or guid key, that defines two types of sections.
303 All sections of each type have same magic value and header structure, index
304 data could be of two possible types too. So every string based section uses
305 the same index format, same applies to guid sections - they share same guid index
306 format.
308 - window class redirection section is a plain buffer with following format:
310 <section header>
311 <index[]>
312 <data[]> --- <original name>
313 <redirect data>
314 <versioned name>
315 <module name>
317 Header is fixed length structure - struct strsection_header,
318 contains redirected classes count;
320 Index is an array of fixed length index records, each record is
321 struct string_index.
323 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
325 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
326 others are relative to section itself.
328 - dll redirect section format:
330 <section header>
331 <index[]>
332 <data[]> --- <dll name>
333 <data>
335 This section doesn't seem to carry any payload data except dll names.
337 - typelib section format:
339 <section header>
340 <module names[]>
341 <index[]>
342 <data[]> --- <data>
343 <helpstring>
345 Header is fixed length, index is an array of fixed length 'struct guid_index'.
346 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
347 4-bytes aligned as a whole.
349 Module name offsets are relative to section, helpstring offset is relative to data
350 structure itself.
352 - comclass section format:
354 <section header>
355 <module names[]>
356 <index[]>
357 <data[]> --- <data> --- <data>
358 <progid> <clrdata>
359 <name>
360 <version>
361 <progid>
363 This section uses two index records per comclass, one entry contains original guid
364 as specified by context, another one has a generated guid. Index and strings handling
365 is similar to typelib sections.
367 For CLR classes additional data is stored after main COM class data, it contains
368 class name and runtime version string, see 'struct clrclass_data'.
370 Module name offsets are relative to section, progid offset is relative to data
371 structure itself.
373 - COM interface section format:
375 <section header>
376 <index[]>
377 <data[]> --- <data>
378 <name>
380 Interface section contains data for proxy/stubs and external proxy/stubs. External
381 ones are defined at assembly level, so this section has no module information.
382 All records are indexed with 'iid' value from manifest. There an exception for
383 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
384 redirect data, but index is still 'iid' from manifest.
386 Interface name offset is relative to data structure itself.
388 - CLR surrogates section format:
390 <section header>
391 <index[]>
392 <data[]> --- <data>
393 <name>
394 <version>
396 There's nothing special about this section, same way to store strings is used,
397 no modules part as it belongs to assembly level, not a file.
399 - ProgID section format:
401 <section header>
402 <guids[]>
403 <index[]>
404 <data[]> --- <progid>
405 <data>
407 This sections uses generated alias guids from COM server section. This way
408 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
409 is stored too, aligned.
412 struct progids
414 WCHAR **progids;
415 unsigned int num;
416 unsigned int allocated;
419 struct entity
421 DWORD kind;
422 union
424 struct
426 WCHAR *tlbid;
427 WCHAR *helpdir;
428 WORD flags;
429 WORD major;
430 WORD minor;
431 } typelib;
432 struct
434 WCHAR *clsid;
435 WCHAR *tlbid;
436 WCHAR *progid;
437 WCHAR *name; /* clrClass: class name */
438 WCHAR *version; /* clrClass: CLR runtime version */
439 DWORD model;
440 DWORD miscstatus;
441 DWORD miscstatuscontent;
442 DWORD miscstatusthumbnail;
443 DWORD miscstatusicon;
444 DWORD miscstatusdocprint;
445 struct progids progids;
446 } comclass;
447 struct {
448 WCHAR *iid;
449 WCHAR *base;
450 WCHAR *tlib;
451 WCHAR *name;
452 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
453 DWORD mask;
454 ULONG nummethods;
455 } ifaceps;
456 struct
458 WCHAR *name;
459 BOOL versioned;
460 } class;
461 struct
463 WCHAR *name;
464 WCHAR *clsid;
465 WCHAR *version;
466 } clrsurrogate;
467 } u;
470 struct entity_array
472 struct entity *base;
473 unsigned int num;
474 unsigned int allocated;
477 struct dll_redirect
479 WCHAR *name;
480 WCHAR *hash;
481 struct entity_array entities;
484 enum assembly_type
486 APPLICATION_MANIFEST,
487 ASSEMBLY_MANIFEST,
488 ASSEMBLY_SHARED_MANIFEST,
491 struct assembly
493 enum assembly_type type;
494 struct assembly_identity id;
495 struct file_info manifest;
496 WCHAR *directory;
497 BOOL no_inherit;
498 struct dll_redirect *dlls;
499 unsigned int num_dlls;
500 unsigned int allocated_dlls;
501 struct entity_array entities;
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 manifestv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0};
660 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};
662 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
663 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
664 static const WCHAR wildcardW[] = {'*',0};
666 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
667 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
669 static WCHAR *strdupW(const WCHAR* str)
671 WCHAR* ptr;
673 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
674 return NULL;
675 return strcpyW(ptr, str);
678 static WCHAR *xmlstrdupW(const xmlstr_t* str)
680 WCHAR *strW;
682 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
684 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
685 strW[str->len] = 0;
687 return strW;
690 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
692 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
695 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
697 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
700 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
702 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
703 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
706 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
708 UINT len = strlenW( namespace );
710 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
711 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
712 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
715 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
717 if (elem->len && elem->ptr[0] == '/')
719 xmlstr_t elem_end;
720 elem_end.ptr = elem->ptr + 1;
721 elem_end.len = elem->len - 1;
722 return xml_elem_cmp( &elem_end, str, namespace );
724 return FALSE;
727 static inline BOOL isxmlspace( WCHAR ch )
729 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
732 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
734 return debugstr_wn(str->ptr, str->len);
737 static inline const char* debugstr_version(const struct assembly_version *ver)
739 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
742 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
744 struct assembly *assembly;
746 if (actctx->num_assemblies == actctx->allocated_assemblies)
748 void *ptr;
749 unsigned int new_count;
750 if (actctx->assemblies)
752 new_count = actctx->allocated_assemblies * 2;
753 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
754 actctx->assemblies, new_count * sizeof(*assembly) );
756 else
758 new_count = 4;
759 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
761 if (!ptr) return NULL;
762 actctx->assemblies = ptr;
763 actctx->allocated_assemblies = new_count;
766 assembly = &actctx->assemblies[actctx->num_assemblies++];
767 assembly->type = at;
768 return assembly;
771 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
773 if (assembly->num_dlls == assembly->allocated_dlls)
775 void *ptr;
776 unsigned int new_count;
777 if (assembly->dlls)
779 new_count = assembly->allocated_dlls * 2;
780 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
781 assembly->dlls, new_count * sizeof(*assembly->dlls) );
783 else
785 new_count = 4;
786 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
788 if (!ptr) return NULL;
789 assembly->dlls = ptr;
790 assembly->allocated_dlls = new_count;
792 return &assembly->dlls[assembly->num_dlls++];
795 static void free_assembly_identity(struct assembly_identity *ai)
797 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
798 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
799 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
800 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
801 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
804 static struct entity* add_entity(struct entity_array *array, DWORD kind)
806 struct entity* entity;
808 if (array->num == array->allocated)
810 void *ptr;
811 unsigned int new_count;
812 if (array->base)
814 new_count = array->allocated * 2;
815 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
816 array->base, new_count * sizeof(*array->base) );
818 else
820 new_count = 4;
821 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
823 if (!ptr) return NULL;
824 array->base = ptr;
825 array->allocated = new_count;
827 entity = &array->base[array->num++];
828 entity->kind = kind;
829 return entity;
832 static void free_entity_array(struct entity_array *array)
834 unsigned int i, j;
835 for (i = 0; i < array->num; i++)
837 struct entity *entity = &array->base[i];
838 switch (entity->kind)
840 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
841 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
842 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
843 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
844 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
845 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
846 for (j = 0; j < entity->u.comclass.progids.num; j++)
847 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
848 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
849 break;
850 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
851 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
852 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
853 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
854 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
855 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
856 break;
857 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
858 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
859 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
860 break;
861 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
862 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
863 break;
864 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
865 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
866 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
867 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
868 break;
869 default:
870 FIXME("Unknown entity kind %d\n", entity->kind);
873 RtlFreeHeap( GetProcessHeap(), 0, array->base );
876 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
878 if (!str1) return !str2;
879 return str2 && !strcmpiW( str1, str2 );
882 static BOOL is_matching_identity( const struct assembly_identity *id1,
883 const struct assembly_identity *id2 )
885 if (!is_matching_string( id1->name, id2->name )) return FALSE;
886 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
887 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
889 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
891 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
892 return FALSE;
894 if (id1->version.major != id2->version.major) return FALSE;
895 if (id1->version.minor != id2->version.minor) return FALSE;
896 if (id1->version.build > id2->version.build) return FALSE;
897 if (id1->version.build == id2->version.build &&
898 id1->version.revision > id2->version.revision) return FALSE;
899 return TRUE;
902 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
903 struct assembly_identity* ai)
905 unsigned int i;
907 /* check if we already have that assembly */
909 for (i = 0; i < acl->actctx->num_assemblies; i++)
910 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
912 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
913 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
914 ai->version.build, ai->version.revision );
915 return TRUE;
918 for (i = 0; i < acl->num_dependencies; i++)
919 if (is_matching_identity( ai, &acl->dependencies[i] ))
921 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
922 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
923 ai->version.build, ai->version.revision );
924 return TRUE;
927 if (acl->num_dependencies == acl->allocated_dependencies)
929 void *ptr;
930 unsigned int new_count;
931 if (acl->dependencies)
933 new_count = acl->allocated_dependencies * 2;
934 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
935 new_count * sizeof(acl->dependencies[0]));
937 else
939 new_count = 4;
940 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
942 if (!ptr) return FALSE;
943 acl->dependencies = ptr;
944 acl->allocated_dependencies = new_count;
946 acl->dependencies[acl->num_dependencies++] = *ai;
948 return TRUE;
951 static void free_depend_manifests(struct actctx_loader* acl)
953 unsigned int i;
954 for (i = 0; i < acl->num_dependencies; i++)
955 free_assembly_identity(&acl->dependencies[i]);
956 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
959 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
961 static const WCHAR undW[] = {'_',0};
962 static const WCHAR noneW[] = {'n','o','n','e',0};
963 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
965 const WCHAR *arch = ai->arch ? ai->arch : noneW;
966 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
967 const WCHAR *lang = ai->language ? ai->language : noneW;
968 const WCHAR *name = ai->name ? ai->name : noneW;
969 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
970 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
971 WCHAR *ret;
973 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
975 strcpyW( ret, arch );
976 strcatW( ret, undW );
977 strcatW( ret, name );
978 strcatW( ret, undW );
979 strcatW( ret, key );
980 strcatW( ret, undW );
981 sprintfW( ret + strlenW(ret), version_formatW,
982 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
983 strcatW( ret, undW );
984 strcatW( ret, lang );
985 strcatW( ret, undW );
986 strcatW( ret, mskeyW );
987 return ret;
990 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
992 WCHAR *p = buffer;
994 if (!str) return;
995 strcatW( buffer, prefix );
996 p += strlenW(p);
997 *p++ = '"';
998 strcpyW( p, str );
999 p += strlenW(p);
1000 *p++ = '"';
1001 *p = 0;
1004 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1006 static const WCHAR archW[] =
1007 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1008 static const WCHAR public_keyW[] =
1009 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1010 static const WCHAR typeW[] =
1011 {',','t','y','p','e','=',0};
1012 static const WCHAR versionW[] =
1013 {',','v','e','r','s','i','o','n','=',0};
1015 WCHAR version[64], *ret;
1016 SIZE_T size = 0;
1018 sprintfW( version, version_formatW,
1019 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1020 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1021 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1022 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1023 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1024 size += strlenW(versionW) + strlenW(version) + 2;
1026 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1027 return NULL;
1029 if (ai->name) strcpyW( ret, ai->name );
1030 else *ret = 0;
1031 append_string( ret, archW, ai->arch );
1032 append_string( ret, public_keyW, ai->public_key );
1033 append_string( ret, typeW, ai->type );
1034 append_string( ret, versionW, version );
1035 return ret;
1038 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1040 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1042 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1043 __TRY
1045 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1047 __EXCEPT_PAGE_FAULT
1050 __ENDTRY
1051 return ret;
1054 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1056 interlocked_xchg_add( &actctx->ref_count, 1 );
1059 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1061 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1063 unsigned int i, j;
1065 for (i = 0; i < actctx->num_assemblies; i++)
1067 struct assembly *assembly = &actctx->assemblies[i];
1068 for (j = 0; j < assembly->num_dlls; j++)
1070 struct dll_redirect *dll = &assembly->dlls[j];
1071 free_entity_array( &dll->entities );
1072 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1073 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1077 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1078 free_entity_array( &assembly->entities );
1079 free_assembly_identity(&assembly->id);
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1091 actctx->magic = 0;
1092 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1096 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1097 BOOL* error, BOOL* end)
1099 const WCHAR* ptr;
1101 *error = TRUE;
1103 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1104 xmlbuf->ptr++;
1106 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1108 if (*xmlbuf->ptr == '/')
1110 xmlbuf->ptr++;
1111 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1112 return FALSE;
1114 xmlbuf->ptr++;
1115 *end = TRUE;
1116 *error = FALSE;
1117 return FALSE;
1120 if (*xmlbuf->ptr == '>')
1122 xmlbuf->ptr++;
1123 *error = FALSE;
1124 return FALSE;
1127 ptr = xmlbuf->ptr;
1128 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1130 if (ptr == xmlbuf->end) return FALSE;
1132 name->ptr = xmlbuf->ptr;
1133 name->len = ptr-xmlbuf->ptr;
1134 xmlbuf->ptr = ptr;
1136 /* skip spaces before '=' */
1137 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1138 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1140 /* skip '=' itself */
1141 ptr++;
1142 if (ptr == xmlbuf->end) return FALSE;
1144 /* skip spaces after '=' */
1145 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1147 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1149 value->ptr = ++ptr;
1150 if (ptr == xmlbuf->end) return FALSE;
1152 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1153 if (!ptr)
1155 xmlbuf->ptr = xmlbuf->end;
1156 return FALSE;
1159 value->len = ptr - value->ptr;
1160 xmlbuf->ptr = ptr + 1;
1162 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1164 *error = FALSE;
1165 return TRUE;
1168 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1170 const WCHAR* ptr;
1172 for (;;)
1174 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1175 if (!ptr)
1177 xmlbuf->ptr = xmlbuf->end;
1178 return FALSE;
1180 ptr++;
1181 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1183 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1184 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1186 if (ptr + 3 > xmlbuf->end)
1188 xmlbuf->ptr = xmlbuf->end;
1189 return FALSE;
1191 xmlbuf->ptr = ptr + 3;
1193 else break;
1196 xmlbuf->ptr = ptr;
1197 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1198 ptr++;
1200 elem->ptr = xmlbuf->ptr;
1201 elem->len = ptr - xmlbuf->ptr;
1202 xmlbuf->ptr = ptr;
1203 return xmlbuf->ptr != xmlbuf->end;
1206 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1208 /* FIXME: parse attributes */
1209 const WCHAR *ptr;
1211 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1213 if (ptr[0] == '?' && ptr[1] == '>')
1215 xmlbuf->ptr = ptr + 2;
1216 return TRUE;
1219 return FALSE;
1222 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1224 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1226 if (!ptr) return FALSE;
1228 content->ptr = xmlbuf->ptr;
1229 content->len = ptr - xmlbuf->ptr;
1230 xmlbuf->ptr = ptr;
1232 return TRUE;
1235 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1237 unsigned int ver[4];
1238 unsigned int pos;
1239 const WCHAR *curr;
1241 /* major.minor.build.revision */
1242 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1243 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1245 if (*curr >= '0' && *curr <= '9')
1247 ver[pos] = ver[pos] * 10 + *curr - '0';
1248 if (ver[pos] >= 0x10000) goto error;
1250 else if (*curr == '.')
1252 if (++pos >= 4) goto error;
1254 else goto error;
1256 version->major = ver[0];
1257 version->minor = ver[1];
1258 version->build = ver[2];
1259 version->revision = ver[3];
1260 return TRUE;
1262 error:
1263 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1264 return FALSE;
1267 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1269 xmlstr_t elem;
1270 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1271 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1272 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1273 return FALSE;
1276 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1278 xmlstr_t attr_name, attr_value;
1279 BOOL error;
1281 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1283 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1284 debugstr_xmlstr(&attr_value));
1286 return !error;
1289 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1291 BOOL end = FALSE;
1292 return parse_expect_no_attr(xmlbuf, &end) && !end;
1295 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1297 xmlstr_t elem;
1298 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1299 if (!xml_elem_cmp_end(&elem, name, namespace))
1301 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1302 return FALSE;
1304 return parse_end_element(xmlbuf);
1307 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1309 xmlstr_t attr_name, attr_value, elem;
1310 BOOL end = FALSE, error, ret = TRUE;
1312 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1313 if(error || end) return end;
1315 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1317 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1318 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1319 break;
1320 else
1321 ret = parse_unknown_elem(xmlbuf, &elem);
1324 return ret && parse_end_element(xmlbuf);
1327 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1328 struct assembly_identity* ai)
1330 xmlstr_t attr_name, attr_value;
1331 BOOL end = FALSE, error;
1333 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1335 if (xmlstr_cmp(&attr_name, nameW))
1337 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1339 else if (xmlstr_cmp(&attr_name, typeW))
1341 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1343 else if (xmlstr_cmp(&attr_name, versionW))
1345 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1347 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1349 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1351 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1353 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1355 else if (xmlstr_cmp(&attr_name, languageW))
1357 WARN("Unsupported yet language attribute (%s)\n",
1358 debugstr_xmlstr(&attr_value));
1359 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1361 else
1363 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1364 debugstr_xmlstr(&attr_value));
1368 TRACE( "name=%s version=%s arch=%s\n",
1369 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1371 if (error || end) return end;
1372 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1375 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1377 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1378 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1379 static const WCHAR freeW[] = {'F','r','e','e',0};
1380 static const WCHAR bothW[] = {'B','o','t','h',0};
1382 if (value->len == 0) return ThreadingModel_No;
1383 if (xmlstr_cmp(value, apartW))
1384 return ThreadingModel_Apartment;
1385 else if (xmlstr_cmp(value, freeW))
1386 return ThreadingModel_Free;
1387 else if (xmlstr_cmp(value, bothW))
1388 return ThreadingModel_Both;
1389 else if (xmlstr_cmp(value, neutralW))
1390 return ThreadingModel_Neutral;
1391 else
1392 return ThreadingModel_No;
1395 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1397 int min, max;
1399 min = 0;
1400 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1402 while (min <= max)
1404 int n, c;
1406 n = (min+max)/2;
1408 c = strncmpW(olemisc_values[n].name, str, len);
1409 if (!c && !olemisc_values[n].name[len])
1410 return olemisc_values[n].value;
1412 if (c >= 0)
1413 max = n-1;
1414 else
1415 min = n+1;
1418 WARN("unknown flag %s\n", debugstr_wn(str, len));
1419 return 0;
1422 static DWORD parse_com_class_misc(const xmlstr_t *value)
1424 const WCHAR *str = value->ptr, *start;
1425 DWORD flags = 0;
1426 int i = 0;
1428 /* it's comma separated list of flags */
1429 while (i < value->len)
1431 start = str;
1432 while (*str != ',' && (i++ < value->len)) str++;
1434 flags |= get_olemisc_value(start, str-start);
1436 /* skip separator */
1437 str++;
1438 i++;
1441 return flags;
1444 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1446 struct progids *progids = &entity->u.comclass.progids;
1448 if (progids->allocated == 0)
1450 progids->allocated = 4;
1451 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1454 if (progids->allocated == progids->num)
1456 progids->allocated *= 2;
1457 progids->progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1460 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1461 progids->num++;
1463 return TRUE;
1466 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1468 xmlstr_t content;
1469 BOOL end = FALSE;
1471 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1472 return FALSE;
1474 if (!com_class_add_progid(&content, entity)) return FALSE;
1475 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1478 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1480 xmlstr_t elem, attr_name, attr_value;
1481 BOOL ret = TRUE, end = FALSE, error;
1482 struct entity* entity;
1484 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1485 return FALSE;
1487 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1489 if (xmlstr_cmp(&attr_name, clsidW))
1491 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1493 else if (xmlstr_cmp(&attr_name, progidW))
1495 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1497 else if (xmlstr_cmp(&attr_name, tlbidW))
1499 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1501 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1503 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1505 else if (xmlstr_cmp(&attr_name, miscstatusW))
1507 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1509 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1511 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1513 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1515 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1517 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1519 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1521 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1523 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1525 else if (xmlstr_cmp(&attr_name, descriptionW))
1527 /* not stored */
1529 else
1531 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1535 if (error) return FALSE;
1537 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1538 if (entity->u.comclass.progid)
1539 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1541 if (end) return TRUE;
1543 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1545 if (xmlstr_cmp_end(&elem, comClassW))
1547 ret = parse_end_element(xmlbuf);
1548 break;
1550 else if (xmlstr_cmp(&elem, progidW))
1552 ret = parse_com_class_progid(xmlbuf, entity);
1554 else
1556 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1557 ret = parse_unknown_elem(xmlbuf, &elem);
1561 if (entity->u.comclass.progids.num)
1562 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1564 return ret;
1567 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1569 const WCHAR *curr;
1570 ULONG num = 0;
1572 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1574 if (*curr >= '0' && *curr <= '9')
1575 num = num * 10 + *curr - '0';
1576 else
1578 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1579 return FALSE;
1582 entity->u.ifaceps.nummethods = num;
1584 return TRUE;
1587 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1589 xmlstr_t attr_name, attr_value;
1590 BOOL end = FALSE, error;
1591 struct entity* entity;
1593 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1594 return FALSE;
1596 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1598 if (xmlstr_cmp(&attr_name, iidW))
1600 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1602 else if (xmlstr_cmp(&attr_name, nameW))
1604 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1606 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1608 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1609 entity->u.ifaceps.mask |= BaseIface;
1611 else if (xmlstr_cmp(&attr_name, nummethodsW))
1613 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1614 entity->u.ifaceps.mask |= NumMethods;
1616 else if (xmlstr_cmp(&attr_name, tlbidW))
1618 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1620 /* not used */
1621 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1624 else
1626 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1630 if (error) return FALSE;
1631 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1632 if (end) return TRUE;
1634 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1637 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1639 WORD *flags = &entity->u.typelib.flags;
1640 const WCHAR *str = value->ptr, *start;
1641 int i = 0;
1643 *flags = 0;
1645 /* it's comma separated list of flags */
1646 while (i < value->len)
1648 start = str;
1649 while (*str != ',' && (i++ < value->len)) str++;
1651 if (!strncmpiW(start, restrictedW, str-start))
1652 *flags |= LIBFLAG_FRESTRICTED;
1653 else if (!strncmpiW(start, controlW, str-start))
1654 *flags |= LIBFLAG_FCONTROL;
1655 else if (!strncmpiW(start, hiddenW, str-start))
1656 *flags |= LIBFLAG_FHIDDEN;
1657 else if (!strncmpiW(start, hasdiskimageW, str-start))
1658 *flags |= LIBFLAG_FHASDISKIMAGE;
1659 else
1661 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1662 return FALSE;
1665 /* skip separator */
1666 str++;
1667 i++;
1670 return TRUE;
1673 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1675 unsigned int ver[2];
1676 unsigned int pos;
1677 const WCHAR *curr;
1679 /* major.minor */
1680 ver[0] = ver[1] = pos = 0;
1681 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1683 if (*curr >= '0' && *curr <= '9')
1685 ver[pos] = ver[pos] * 10 + *curr - '0';
1686 if (ver[pos] >= 0x10000) goto error;
1688 else if (*curr == '.')
1690 if (++pos >= 2) goto error;
1692 else goto error;
1694 entity->u.typelib.major = ver[0];
1695 entity->u.typelib.minor = ver[1];
1696 return TRUE;
1698 error:
1699 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1700 return FALSE;
1703 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1705 xmlstr_t attr_name, attr_value;
1706 BOOL end = FALSE, error;
1707 struct entity* entity;
1709 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1710 return FALSE;
1712 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1714 if (xmlstr_cmp(&attr_name, tlbidW))
1716 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1718 else if (xmlstr_cmp(&attr_name, versionW))
1720 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1722 else if (xmlstr_cmp(&attr_name, helpdirW))
1724 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1726 else if (xmlstr_cmp(&attr_name, flagsW))
1728 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1730 else
1732 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1736 if (error) return FALSE;
1738 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1740 if (end) return TRUE;
1742 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1745 static inline int aligned_string_len(int len)
1747 return (len + 3) & ~3;
1750 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1752 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1753 struct assembly_version *ver = &assembly->id.version;
1754 WCHAR buff[25];
1756 if (!ret) ret = buff;
1757 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1760 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1762 xmlstr_t elem, content, attr_name, attr_value;
1763 BOOL end = FALSE, ret = TRUE, error;
1764 struct entity* entity;
1766 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1767 return FALSE;
1769 entity->u.class.versioned = TRUE;
1770 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1772 if (xmlstr_cmp(&attr_name, versionedW))
1774 if (xmlstr_cmpi(&attr_value, noW))
1775 entity->u.class.versioned = FALSE;
1776 else if (!xmlstr_cmpi(&attr_value, yesW))
1777 return FALSE;
1779 else
1781 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1785 if (error || end) return end;
1787 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1789 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1791 acl->actctx->sections |= WINDOWCLASS_SECTION;
1793 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1795 if (xmlstr_cmp_end(&elem, windowClassW))
1797 ret = parse_end_element(xmlbuf);
1798 break;
1800 else
1802 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1803 ret = parse_unknown_elem(xmlbuf, &elem);
1807 return ret;
1810 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1812 xmlstr_t attr_name, attr_value;
1813 BOOL end = FALSE, error;
1815 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1817 if (xmlstr_cmp(&attr_name, oldVersionW))
1819 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1821 else if (xmlstr_cmp(&attr_name, newVersionW))
1823 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1825 else
1827 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1831 if (error || end) return end;
1832 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1835 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1837 xmlstr_t elem, content, attr_name, attr_value;
1838 BOOL end = FALSE, ret = TRUE, error = FALSE;
1840 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1841 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1843 if (error) return FALSE;
1844 if (end) return TRUE;
1846 if (!parse_text_content(xmlbuf, &content))
1847 return FALSE;
1849 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1851 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1853 if (xmlstr_cmp_end(&elem, descriptionW))
1855 ret = parse_end_element(xmlbuf);
1856 break;
1858 else
1860 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1861 ret = parse_unknown_elem(xmlbuf, &elem);
1865 return ret;
1868 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1869 struct assembly* assembly,
1870 struct actctx_loader* acl)
1872 xmlstr_t attr_name, attr_value;
1873 BOOL end = FALSE, error;
1874 struct entity* entity;
1876 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1877 if (!entity) return FALSE;
1879 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1881 if (xmlstr_cmp(&attr_name, iidW))
1883 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1885 else if (xmlstr_cmp(&attr_name, nameW))
1887 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1889 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1891 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1892 entity->u.ifaceps.mask |= BaseIface;
1894 else if (xmlstr_cmp(&attr_name, nummethodsW))
1896 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1897 entity->u.ifaceps.mask |= NumMethods;
1899 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1901 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1903 else if (xmlstr_cmp(&attr_name, tlbidW))
1905 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1907 else
1909 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1913 if (error) return FALSE;
1914 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1915 if (end) return TRUE;
1917 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1920 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1922 xmlstr_t attr_name, attr_value, elem;
1923 BOOL end = FALSE, error, ret = TRUE;
1924 struct entity* entity;
1926 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1927 if (!entity) return FALSE;
1929 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1931 if (xmlstr_cmp(&attr_name, nameW))
1933 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1935 else if (xmlstr_cmp(&attr_name, clsidW))
1937 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1939 else if (xmlstr_cmp(&attr_name, progidW))
1941 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1943 else if (xmlstr_cmp(&attr_name, tlbidW))
1945 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1947 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1949 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1951 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1953 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1955 else
1957 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1961 if (error) return FALSE;
1962 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1963 if (entity->u.comclass.progid)
1964 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1965 if (end) return TRUE;
1967 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1969 if (xmlstr_cmp_end(&elem, clrClassW))
1971 ret = parse_end_element(xmlbuf);
1972 break;
1974 else if (xmlstr_cmp(&elem, progidW))
1976 ret = parse_com_class_progid(xmlbuf, entity);
1978 else
1980 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1981 ret = parse_unknown_elem(xmlbuf, &elem);
1985 if (entity->u.comclass.progids.num)
1986 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1988 return ret;
1991 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1993 xmlstr_t attr_name, attr_value;
1994 BOOL end = FALSE, error;
1995 struct entity* entity;
1997 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1998 if (!entity) return FALSE;
2000 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2002 if (xmlstr_cmp(&attr_name, nameW))
2004 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2006 else if (xmlstr_cmp(&attr_name, clsidW))
2008 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2010 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2012 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2014 else
2016 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2020 if (error) return FALSE;
2021 acl->actctx->sections |= CLRSURROGATES_SECTION;
2022 if (end) return TRUE;
2024 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2027 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2029 struct assembly_identity ai;
2030 xmlstr_t elem, attr_name, attr_value;
2031 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2033 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2035 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2036 static const WCHAR trueW[] = {'t','r','u','e',0};
2038 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2039 delayed = xmlstr_cmp(&attr_value, trueW);
2040 else
2041 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2044 if (error || end) return end;
2046 memset(&ai, 0, sizeof(ai));
2047 ai.optional = optional;
2048 ai.delayed = delayed;
2050 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2051 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2052 return FALSE;
2054 TRACE( "adding name=%s version=%s arch=%s\n",
2055 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2057 /* store the newly found identity for later loading */
2058 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2060 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2062 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2064 ret = parse_end_element(xmlbuf);
2065 break;
2067 else if (xmlstr_cmp(&elem, bindingRedirectW))
2069 ret = parse_binding_redirect_elem(xmlbuf);
2071 else
2073 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2074 ret = parse_unknown_elem(xmlbuf, &elem);
2078 return ret;
2081 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2083 xmlstr_t attr_name, attr_value, elem;
2084 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2086 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2088 if (xmlstr_cmp(&attr_name, optionalW))
2090 optional = xmlstr_cmpi( &attr_value, yesW );
2091 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2093 else
2095 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2099 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2101 if (xmlstr_cmp_end(&elem, dependencyW))
2103 ret = parse_end_element(xmlbuf);
2104 break;
2106 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2108 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2110 else
2112 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2113 ret = parse_unknown_elem(xmlbuf, &elem);
2117 return ret;
2120 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2122 BOOL end = FALSE;
2124 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2125 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2128 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2130 BOOL end = FALSE;
2132 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2133 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2136 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2138 xmlstr_t attr_name, attr_value, elem;
2139 BOOL end = FALSE, error, ret = TRUE;
2140 struct dll_redirect* dll;
2142 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2144 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2146 if (xmlstr_cmp(&attr_name, nameW))
2148 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2149 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2151 else if (xmlstr_cmp(&attr_name, hashW))
2153 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2155 else if (xmlstr_cmp(&attr_name, hashalgW))
2157 static const WCHAR sha1W[] = {'S','H','A','1',0};
2158 if (!xmlstr_cmpi(&attr_value, sha1W))
2159 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2161 else
2163 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2167 if (error || !dll->name) return FALSE;
2169 acl->actctx->sections |= DLLREDIRECT_SECTION;
2171 if (end) return TRUE;
2173 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2175 if (xmlstr_cmp_end(&elem, fileW))
2177 ret = parse_end_element(xmlbuf);
2178 break;
2180 else if (xmlstr_cmp(&elem, comClassW))
2182 ret = parse_com_class_elem(xmlbuf, dll, acl);
2184 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2186 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2188 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2190 WARN("asmv2:hash (undocumented) not supported\n");
2191 ret = parse_unknown_elem(xmlbuf, &elem);
2193 else if (xmlstr_cmp(&elem, typelibW))
2195 ret = parse_typelib_elem(xmlbuf, dll, acl);
2197 else if (xmlstr_cmp(&elem, windowClassW))
2199 ret = parse_window_class_elem(xmlbuf, dll, acl);
2201 else
2203 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2204 ret = parse_unknown_elem( xmlbuf, &elem );
2208 return ret;
2211 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2212 struct assembly* assembly,
2213 struct assembly_identity* expected_ai)
2215 xmlstr_t attr_name, attr_value, elem;
2216 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2218 TRACE("(%p)\n", xmlbuf);
2220 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2222 if (xmlstr_cmp(&attr_name, manifestVersionW))
2224 static const WCHAR v10W[] = {'1','.','0',0};
2225 if (!xmlstr_cmp(&attr_value, v10W))
2227 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2228 return FALSE;
2230 version = TRUE;
2232 else if (xmlstr_cmp(&attr_name, xmlnsW))
2234 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2235 !xmlstr_cmp(&attr_value, manifestv2W) &&
2236 !xmlstr_cmp(&attr_value, manifestv3W))
2238 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2239 return FALSE;
2241 xmlns = TRUE;
2243 else
2245 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2249 if (error || end || !xmlns || !version) return FALSE;
2250 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2252 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2254 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2255 return FALSE;
2256 assembly->no_inherit = TRUE;
2259 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2261 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2262 return FALSE;
2264 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2265 assembly->no_inherit)
2266 return FALSE;
2268 while (ret)
2270 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2272 ret = parse_end_element(xmlbuf);
2273 break;
2275 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2277 ret = parse_description_elem(xmlbuf);
2279 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2281 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2283 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2285 ret = parse_dependency_elem(xmlbuf, acl);
2287 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2289 ret = parse_file_elem(xmlbuf, assembly, acl);
2291 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2293 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2295 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2297 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2299 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2301 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2303 if (expected_ai)
2305 /* FIXME: more tests */
2306 if (assembly->type == ASSEMBLY_MANIFEST &&
2307 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2309 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2310 expected_ai->version.major, expected_ai->version.minor,
2311 expected_ai->version.build, expected_ai->version.revision,
2312 assembly->id.version.major, assembly->id.version.minor,
2313 assembly->id.version.build, assembly->id.version.revision);
2314 ret = FALSE;
2316 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2317 (assembly->id.version.major != expected_ai->version.major ||
2318 assembly->id.version.minor != expected_ai->version.minor ||
2319 assembly->id.version.build < expected_ai->version.build ||
2320 (assembly->id.version.build == expected_ai->version.build &&
2321 assembly->id.version.revision < expected_ai->version.revision)))
2323 FIXME("wrong version for shared assembly manifest\n");
2324 ret = FALSE;
2328 else
2330 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2331 ret = parse_unknown_elem(xmlbuf, &elem);
2333 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2336 return ret;
2339 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2340 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2342 xmlstr_t elem;
2344 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2346 if (xmlstr_cmp(&elem, xmlW) &&
2347 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2348 return STATUS_SXS_CANT_GEN_ACTCTX;
2350 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2352 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2353 return STATUS_SXS_CANT_GEN_ACTCTX;
2356 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2358 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2359 return STATUS_SXS_CANT_GEN_ACTCTX;
2362 if (next_xml_elem(xmlbuf, &elem))
2364 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2365 return STATUS_SXS_CANT_GEN_ACTCTX;
2368 if (xmlbuf->ptr != xmlbuf->end)
2370 FIXME("parse error\n");
2371 return STATUS_SXS_CANT_GEN_ACTCTX;
2373 return STATUS_SUCCESS;
2376 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2377 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2378 const void *buffer, SIZE_T size )
2380 xmlbuf_t xmlbuf;
2381 NTSTATUS status;
2382 struct assembly *assembly;
2383 int unicode_tests;
2385 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2387 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2388 return STATUS_SXS_CANT_GEN_ACTCTX;
2390 if (directory && !(assembly->directory = strdupW(directory)))
2391 return STATUS_NO_MEMORY;
2393 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2394 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2395 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2397 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2398 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2400 xmlbuf.ptr = buffer;
2401 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2402 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2404 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2406 const WCHAR *buf = buffer;
2407 WCHAR *new_buff;
2408 unsigned int i;
2410 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2411 return STATUS_NO_MEMORY;
2412 for (i = 0; i < size / sizeof(WCHAR); i++)
2413 new_buff[i] = RtlUshortByteSwap( buf[i] );
2414 xmlbuf.ptr = new_buff;
2415 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2416 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2417 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2419 else
2421 /* let's assume utf-8 for now */
2422 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2423 WCHAR *new_buff;
2425 if (len == -1)
2427 FIXME( "utf-8 conversion failed\n" );
2428 return STATUS_SXS_CANT_GEN_ACTCTX;
2430 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2431 return STATUS_NO_MEMORY;
2432 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2433 xmlbuf.ptr = new_buff;
2434 xmlbuf.end = xmlbuf.ptr + len;
2435 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2436 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2438 return status;
2441 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2443 OBJECT_ATTRIBUTES attr;
2444 IO_STATUS_BLOCK io;
2446 attr.Length = sizeof(attr);
2447 attr.RootDirectory = 0;
2448 attr.Attributes = OBJ_CASE_INSENSITIVE;
2449 attr.ObjectName = name;
2450 attr.SecurityDescriptor = NULL;
2451 attr.SecurityQualityOfService = NULL;
2452 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2455 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2457 NTSTATUS status;
2458 ULONG_PTR magic;
2459 LDR_MODULE *pldr;
2461 LdrLockLoaderLock(0, NULL, &magic);
2462 status = LdrFindEntryForAddress( module, &pldr );
2463 if (status == STATUS_SUCCESS)
2465 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2466 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2468 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2469 str->Length = pldr->FullDllName.Length;
2470 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2472 else status = STATUS_NO_MEMORY;
2474 LdrUnlockLoaderLock(0, magic);
2475 return status;
2478 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2479 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2480 HANDLE hModule, LPCWSTR resname, ULONG lang )
2482 NTSTATUS status;
2483 UNICODE_STRING nameW;
2484 LDR_RESOURCE_INFO info;
2485 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2486 void *ptr;
2488 if (TRACE_ON(actctx))
2490 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2492 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2493 hModule, debugstr_w(nameW.Buffer) );
2494 RtlFreeUnicodeString( &nameW );
2496 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2497 hModule, debugstr_w(filename) );
2500 if (!resname) return STATUS_INVALID_PARAMETER;
2502 info.Type = RT_MANIFEST;
2503 info.Language = lang;
2504 if (!((ULONG_PTR)resname >> 16))
2506 info.Name = (ULONG_PTR)resname;
2507 status = LdrFindResource_U(hModule, &info, 3, &entry);
2509 else if (resname[0] == '#')
2511 ULONG value;
2512 RtlInitUnicodeString(&nameW, resname + 1);
2513 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2514 return STATUS_INVALID_PARAMETER;
2515 info.Name = value;
2516 status = LdrFindResource_U(hModule, &info, 3, &entry);
2518 else
2520 RtlCreateUnicodeString(&nameW, resname);
2521 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2522 info.Name = (ULONG_PTR)nameW.Buffer;
2523 status = LdrFindResource_U(hModule, &info, 3, &entry);
2524 RtlFreeUnicodeString(&nameW);
2526 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2528 if (status == STATUS_SUCCESS)
2529 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2531 return status;
2534 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2535 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2536 HANDLE file, LPCWSTR resname, ULONG lang )
2538 HANDLE mapping;
2539 OBJECT_ATTRIBUTES attr;
2540 LARGE_INTEGER size;
2541 LARGE_INTEGER offset;
2542 NTSTATUS status;
2543 SIZE_T count;
2544 void *base;
2546 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2548 attr.Length = sizeof(attr);
2549 attr.RootDirectory = 0;
2550 attr.ObjectName = NULL;
2551 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2552 attr.SecurityDescriptor = NULL;
2553 attr.SecurityQualityOfService = NULL;
2555 size.QuadPart = 0;
2556 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2557 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2558 if (status != STATUS_SUCCESS) return status;
2560 offset.QuadPart = 0;
2561 count = 0;
2562 base = NULL;
2563 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2564 &count, ViewShare, 0, PAGE_READONLY );
2565 NtClose( mapping );
2566 if (status != STATUS_SUCCESS) return status;
2568 if (RtlImageNtHeader(base)) /* we got a PE file */
2570 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2571 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2573 else status = STATUS_INVALID_IMAGE_FORMAT;
2575 NtUnmapViewOfSection( GetCurrentProcess(), base );
2576 return status;
2579 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2580 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2582 FILE_END_OF_FILE_INFORMATION info;
2583 IO_STATUS_BLOCK io;
2584 HANDLE mapping;
2585 OBJECT_ATTRIBUTES attr;
2586 LARGE_INTEGER size;
2587 LARGE_INTEGER offset;
2588 NTSTATUS status;
2589 SIZE_T count;
2590 void *base;
2592 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2594 attr.Length = sizeof(attr);
2595 attr.RootDirectory = 0;
2596 attr.ObjectName = NULL;
2597 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2598 attr.SecurityDescriptor = NULL;
2599 attr.SecurityQualityOfService = NULL;
2601 size.QuadPart = 0;
2602 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2603 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2604 if (status != STATUS_SUCCESS) return status;
2606 offset.QuadPart = 0;
2607 count = 0;
2608 base = NULL;
2609 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2610 &count, ViewShare, 0, PAGE_READONLY );
2611 NtClose( mapping );
2612 if (status != STATUS_SUCCESS) return status;
2614 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2615 if (status == STATUS_SUCCESS)
2616 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2618 NtUnmapViewOfSection( GetCurrentProcess(), base );
2619 return status;
2622 /* try to load the .manifest file associated to the file */
2623 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2624 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2626 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2627 WCHAR *buffer;
2628 NTSTATUS status;
2629 UNICODE_STRING nameW;
2630 HANDLE file;
2631 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2633 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2635 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2637 if (module) /* use the module filename */
2639 UNICODE_STRING name;
2641 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2643 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2644 strcatW( name.Buffer, dotManifestW );
2645 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2646 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2647 RtlFreeUnicodeString( &name );
2649 if (status) return status;
2651 else
2653 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2654 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2655 return STATUS_NO_MEMORY;
2656 strcpyW( buffer, filename );
2657 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2658 strcatW( buffer, dotManifestW );
2659 RtlInitUnicodeString( &nameW, buffer );
2662 if (!open_nt_file( &file, &nameW ))
2664 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2665 NtClose( file );
2667 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2668 RtlFreeUnicodeString( &nameW );
2669 return status;
2672 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2674 static const WCHAR lookup_fmtW[] =
2675 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2676 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2677 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2679 WCHAR *lookup, *ret = NULL;
2680 UNICODE_STRING lookup_us;
2681 IO_STATUS_BLOCK io;
2682 const WCHAR *lang = ai->language;
2683 unsigned int data_pos = 0, data_len;
2684 char buffer[8192];
2686 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2687 (strlenW(ai->arch) + strlenW(ai->name)
2688 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2689 + sizeof(lookup_fmtW) )))
2690 return NULL;
2692 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2693 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2694 ai->version.major, ai->version.minor, lang );
2695 RtlInitUnicodeString( &lookup_us, lookup );
2697 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2698 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2699 if (io.u.Status == STATUS_SUCCESS)
2701 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2702 FILE_BOTH_DIR_INFORMATION *dir_info;
2703 WCHAR *tmp;
2704 ULONG build, revision;
2706 data_len = io.Information;
2708 for (;;)
2710 if (data_pos >= data_len)
2712 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2713 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2714 if (io.u.Status != STATUS_SUCCESS) break;
2715 data_len = io.Information;
2716 data_pos = 0;
2718 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2720 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2721 else data_pos = data_len;
2723 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2724 build = atoiW(tmp);
2725 if (build < min_build) continue;
2726 tmp = strchrW(tmp, '.') + 1;
2727 revision = atoiW(tmp);
2728 if (build == min_build && revision < min_revision) continue;
2729 tmp = strchrW(tmp, '_') + 1;
2730 tmp = strchrW(tmp, '_') + 1;
2731 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2732 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2734 /* prefer a non-Wine manifest if we already have one */
2735 /* we'll still load the builtin dll if specified through DllOverrides */
2736 if (ret) continue;
2738 else
2740 min_build = build;
2741 min_revision = revision;
2743 ai->version.build = build;
2744 ai->version.revision = revision;
2745 RtlFreeHeap( GetProcessHeap(), 0, ret );
2746 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2748 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2749 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2753 else WARN("no matching file for %s\n", debugstr_w(lookup));
2754 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2755 return ret;
2758 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2760 struct assembly_identity sxs_ai;
2761 UNICODE_STRING path_us;
2762 OBJECT_ATTRIBUTES attr;
2763 IO_STATUS_BLOCK io;
2764 WCHAR *path, *file = NULL;
2765 HANDLE handle;
2767 static const WCHAR manifest_dirW[] =
2768 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2770 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2772 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2773 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2774 return STATUS_NO_MEMORY;
2776 strcpyW( path, user_shared_data->NtSystemRoot );
2777 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2779 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2781 RtlFreeHeap( GetProcessHeap(), 0, path );
2782 return STATUS_NO_SUCH_FILE;
2784 RtlFreeHeap( GetProcessHeap(), 0, path );
2786 attr.Length = sizeof(attr);
2787 attr.RootDirectory = 0;
2788 attr.Attributes = OBJ_CASE_INSENSITIVE;
2789 attr.ObjectName = &path_us;
2790 attr.SecurityDescriptor = NULL;
2791 attr.SecurityQualityOfService = NULL;
2793 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2794 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2796 sxs_ai = *ai;
2797 file = lookup_manifest_file( handle, &sxs_ai );
2798 NtClose( handle );
2800 if (!file)
2802 RtlFreeUnicodeString( &path_us );
2803 return STATUS_NO_SUCH_FILE;
2806 /* append file name to directory path */
2807 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2808 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2810 RtlFreeHeap( GetProcessHeap(), 0, file );
2811 RtlFreeUnicodeString( &path_us );
2812 return STATUS_NO_MEMORY;
2815 path[path_us.Length/sizeof(WCHAR)] = '\\';
2816 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2817 RtlInitUnicodeString( &path_us, path );
2818 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2820 if (!open_nt_file( &handle, &path_us ))
2822 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2823 NtClose( handle );
2825 else io.u.Status = STATUS_NO_SUCH_FILE;
2827 RtlFreeHeap( GetProcessHeap(), 0, file );
2828 RtlFreeUnicodeString( &path_us );
2829 return io.u.Status;
2832 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2833 struct assembly_identity* ai)
2835 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2836 unsigned int i;
2837 WCHAR *buffer, *p, *directory;
2838 NTSTATUS status;
2839 UNICODE_STRING nameW;
2840 HANDLE file;
2841 DWORD len;
2843 TRACE( "looking for name=%s version=%s arch=%s\n",
2844 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2846 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2848 /* FIXME: add support for language specific lookup */
2850 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2851 strlenW(acl->actctx->appdir.info));
2853 nameW.Buffer = NULL;
2854 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2855 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2856 return STATUS_NO_MEMORY;
2858 if (!(directory = build_assembly_dir( ai )))
2860 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2861 return STATUS_NO_MEMORY;
2864 /* Lookup in <dir>\name.dll
2865 * <dir>\name.manifest
2866 * <dir>\name\name.dll
2867 * <dir>\name\name.manifest
2869 * First 'appdir' is used as <dir>, if that failed
2870 * it tries application manifest file path.
2872 strcpyW( buffer, acl->actctx->appdir.info );
2873 p = buffer + strlenW(buffer);
2874 for (i = 0; i < 4; i++)
2876 if (i == 2)
2878 struct assembly *assembly = acl->actctx->assemblies;
2879 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
2881 else *p++ = '\\';
2883 strcpyW( p, ai->name );
2884 p += strlenW(p);
2886 strcpyW( p, dotDllW );
2887 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2889 status = open_nt_file( &file, &nameW );
2890 if (!status)
2892 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2893 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2894 NtClose( file );
2895 break;
2897 RtlFreeUnicodeString( &nameW );
2900 strcpyW( p, dotManifestW );
2901 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2903 status = open_nt_file( &file, &nameW );
2904 if (!status)
2906 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2907 NtClose( file );
2908 break;
2910 RtlFreeUnicodeString( &nameW );
2912 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2914 RtlFreeUnicodeString( &nameW );
2915 RtlFreeHeap( GetProcessHeap(), 0, directory );
2916 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2917 return status;
2920 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2922 NTSTATUS status = STATUS_SUCCESS;
2923 unsigned int i;
2925 for (i = 0; i < acl->num_dependencies; i++)
2927 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2929 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
2931 FIXME( "Could not find dependent assembly %s (%s)\n",
2932 debugstr_w(acl->dependencies[i].name),
2933 debugstr_version(&acl->dependencies[i].version) );
2934 status = STATUS_SXS_CANT_GEN_ACTCTX;
2935 break;
2939 /* FIXME should now iterate through all refs */
2940 return status;
2943 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2944 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2946 NTSTATUS status = STATUS_SUCCESS;
2948 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2950 if (*handle) return STATUS_INVALID_PARAMETER;
2952 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2953 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2955 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2957 ULONG_PTR magic;
2958 LDR_MODULE *pldr;
2960 if (!*handle) return STATUS_INVALID_PARAMETER;
2962 LdrLockLoaderLock( 0, NULL, &magic );
2963 if (!LdrFindEntryForAddress( *handle, &pldr ))
2965 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2966 status = STATUS_DLL_NOT_FOUND;
2967 else
2968 *handle = pldr->ActivationContext;
2970 else status = STATUS_DLL_NOT_FOUND;
2971 LdrUnlockLoaderLock( 0, magic );
2973 else if (!*handle && (class != ActivationContextBasicInformation))
2974 *handle = process_actctx;
2976 return status;
2979 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2981 unsigned int i, j, total_len = 0, dll_count = 0;
2982 struct strsection_header *header;
2983 struct dllredirect_data *data;
2984 struct string_index *index;
2985 ULONG name_offset;
2987 /* compute section length */
2988 for (i = 0; i < actctx->num_assemblies; i++)
2990 struct assembly *assembly = &actctx->assemblies[i];
2991 for (j = 0; j < assembly->num_dlls; j++)
2993 struct dll_redirect *dll = &assembly->dlls[j];
2995 /* each entry needs index, data and string data */
2996 total_len += sizeof(*index);
2997 total_len += sizeof(*data);
2998 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3001 dll_count += assembly->num_dlls;
3004 total_len += sizeof(*header);
3006 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3007 if (!header) return STATUS_NO_MEMORY;
3009 memset(header, 0, sizeof(*header));
3010 header->magic = STRSECTION_MAGIC;
3011 header->size = sizeof(*header);
3012 header->count = dll_count;
3013 header->index_offset = sizeof(*header);
3014 index = (struct string_index*)((BYTE*)header + header->index_offset);
3015 name_offset = header->index_offset + header->count*sizeof(*index);
3017 for (i = 0; i < actctx->num_assemblies; i++)
3019 struct assembly *assembly = &actctx->assemblies[i];
3020 for (j = 0; j < assembly->num_dlls; j++)
3022 struct dll_redirect *dll = &assembly->dlls[j];
3023 UNICODE_STRING str;
3024 WCHAR *ptrW;
3026 /* setup new index entry */
3027 str.Buffer = dll->name;
3028 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3029 str.MaximumLength = str.Length + sizeof(WCHAR);
3030 /* hash original class name */
3031 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3033 index->name_offset = name_offset;
3034 index->name_len = str.Length;
3035 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3036 index->data_len = sizeof(*data);
3037 index->rosterindex = i + 1;
3039 /* setup data */
3040 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3041 data->size = sizeof(*data);
3042 data->unk = 2; /* FIXME: seems to be constant */
3043 memset(data->res, 0, sizeof(data->res));
3045 /* dll name */
3046 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3047 memcpy(ptrW, dll->name, index->name_len);
3048 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3050 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3052 index++;
3056 *section = header;
3058 return STATUS_SUCCESS;
3061 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3063 struct string_index *iter, *index = NULL;
3064 ULONG hash = 0, i;
3066 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3067 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3069 for (i = 0; i < section->count; i++)
3071 if (iter->hash == hash)
3073 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3075 if (!strcmpiW(nameW, name->Buffer))
3077 index = iter;
3078 break;
3080 else
3081 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3083 iter++;
3086 return index;
3089 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3091 struct guid_index *iter, *index = NULL;
3092 ULONG i;
3094 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3096 for (i = 0; i < section->count; i++)
3098 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3100 index = iter;
3101 break;
3103 iter++;
3106 return index;
3109 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3111 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3114 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3115 PACTCTX_SECTION_KEYED_DATA data)
3117 struct dllredirect_data *dll;
3118 struct string_index *index;
3120 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3122 if (!actctx->dllredirect_section)
3124 struct strsection_header *section;
3126 NTSTATUS status = build_dllredirect_section(actctx, &section);
3127 if (status) return status;
3129 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3130 RtlFreeHeap(GetProcessHeap(), 0, section);
3133 index = find_string_index(actctx->dllredirect_section, name);
3134 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3136 if (data)
3138 dll = get_dllredirect_data(actctx, index);
3140 data->ulDataFormatVersion = 1;
3141 data->lpData = dll;
3142 data->ulLength = dll->size;
3143 data->lpSectionGlobalData = NULL;
3144 data->ulSectionGlobalDataLength = 0;
3145 data->lpSectionBase = actctx->dllredirect_section;
3146 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3147 data->hActCtx = NULL;
3149 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3150 data->ulAssemblyRosterIndex = index->rosterindex;
3153 return STATUS_SUCCESS;
3156 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3158 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3161 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3163 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3166 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3168 unsigned int i, j, k, total_len = 0, class_count = 0;
3169 struct wndclass_redirect_data *data;
3170 struct strsection_header *header;
3171 struct string_index *index;
3172 ULONG name_offset;
3174 /* compute section length */
3175 for (i = 0; i < actctx->num_assemblies; i++)
3177 struct assembly *assembly = &actctx->assemblies[i];
3178 for (j = 0; j < assembly->num_dlls; j++)
3180 struct dll_redirect *dll = &assembly->dlls[j];
3181 for (k = 0; k < dll->entities.num; k++)
3183 struct entity *entity = &dll->entities.base[k];
3184 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3186 int class_len = strlenW(entity->u.class.name) + 1;
3187 int len;
3189 /* each class entry needs index, data and string data */
3190 total_len += sizeof(*index);
3191 total_len += sizeof(*data);
3192 /* original name is stored separately */
3193 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3194 /* versioned name and module name are stored one after another */
3195 if (entity->u.class.versioned)
3196 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3197 else
3198 len = class_len;
3199 len += strlenW(dll->name) + 1;
3200 total_len += aligned_string_len(len*sizeof(WCHAR));
3202 class_count++;
3208 total_len += sizeof(*header);
3210 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3211 if (!header) return STATUS_NO_MEMORY;
3213 memset(header, 0, sizeof(*header));
3214 header->magic = STRSECTION_MAGIC;
3215 header->size = sizeof(*header);
3216 header->count = class_count;
3217 header->index_offset = sizeof(*header);
3218 index = (struct string_index*)((BYTE*)header + header->index_offset);
3219 name_offset = header->index_offset + header->count*sizeof(*index);
3221 for (i = 0; i < actctx->num_assemblies; i++)
3223 struct assembly *assembly = &actctx->assemblies[i];
3224 for (j = 0; j < assembly->num_dlls; j++)
3226 struct dll_redirect *dll = &assembly->dlls[j];
3227 for (k = 0; k < dll->entities.num; k++)
3229 struct entity *entity = &dll->entities.base[k];
3230 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3232 static const WCHAR exclW[] = {'!',0};
3233 ULONG versioned_len, module_len;
3234 UNICODE_STRING str;
3235 WCHAR *ptrW;
3237 /* setup new index entry */
3238 str.Buffer = entity->u.class.name;
3239 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3240 str.MaximumLength = str.Length + sizeof(WCHAR);
3241 /* hash original class name */
3242 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3244 /* include '!' separator too */
3245 if (entity->u.class.versioned)
3246 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3247 else
3248 versioned_len = str.Length;
3249 module_len = strlenW(dll->name)*sizeof(WCHAR);
3251 index->name_offset = name_offset;
3252 index->name_len = str.Length;
3253 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3254 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3255 index->rosterindex = i + 1;
3257 /* setup data */
3258 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3259 data->size = sizeof(*data);
3260 data->res = 0;
3261 data->name_len = versioned_len;
3262 data->name_offset = sizeof(*data);
3263 data->module_len = module_len;
3264 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3266 /* original class name */
3267 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3268 memcpy(ptrW, entity->u.class.name, index->name_len);
3269 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3271 /* module name */
3272 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3273 memcpy(ptrW, dll->name, data->module_len);
3274 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3276 /* versioned name */
3277 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3278 if (entity->u.class.versioned)
3280 get_assembly_version(assembly, ptrW);
3281 strcatW(ptrW, exclW);
3282 strcatW(ptrW, entity->u.class.name);
3284 else
3286 memcpy(ptrW, entity->u.class.name, index->name_len);
3287 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3290 name_offset += sizeof(*data);
3291 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3293 index++;
3299 *section = header;
3301 return STATUS_SUCCESS;
3304 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3305 PACTCTX_SECTION_KEYED_DATA data)
3307 struct string_index *iter, *index = NULL;
3308 struct wndclass_redirect_data *class;
3309 ULONG hash;
3310 int i;
3312 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3314 if (!actctx->wndclass_section)
3316 struct strsection_header *section;
3318 NTSTATUS status = build_wndclass_section(actctx, &section);
3319 if (status) return status;
3321 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3322 RtlFreeHeap(GetProcessHeap(), 0, section);
3325 hash = 0;
3326 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3327 iter = get_wndclass_first_index(actctx);
3329 for (i = 0; i < actctx->wndclass_section->count; i++)
3331 if (iter->hash == hash)
3333 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3335 if (!strcmpiW(nameW, name->Buffer))
3337 index = iter;
3338 break;
3340 else
3341 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3343 iter++;
3346 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3348 if (data)
3350 class = get_wndclass_data(actctx, index);
3352 data->ulDataFormatVersion = 1;
3353 data->lpData = class;
3354 /* full length includes string length with nulls */
3355 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3356 data->lpSectionGlobalData = NULL;
3357 data->ulSectionGlobalDataLength = 0;
3358 data->lpSectionBase = actctx->wndclass_section;
3359 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3360 data->hActCtx = NULL;
3362 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3363 data->ulAssemblyRosterIndex = index->rosterindex;
3366 return STATUS_SUCCESS;
3369 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3371 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3372 struct guidsection_header *header;
3373 ULONG module_offset, data_offset;
3374 struct tlibredirect_data *data;
3375 struct guid_index *index;
3377 /* compute section length */
3378 for (i = 0; i < actctx->num_assemblies; i++)
3380 struct assembly *assembly = &actctx->assemblies[i];
3381 for (j = 0; j < assembly->num_dlls; j++)
3383 struct dll_redirect *dll = &assembly->dlls[j];
3384 for (k = 0; k < dll->entities.num; k++)
3386 struct entity *entity = &dll->entities.base[k];
3387 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3389 /* each entry needs index, data and string data for module name and help string */
3390 total_len += sizeof(*index);
3391 total_len += sizeof(*data);
3392 /* help string is stored separately */
3393 if (*entity->u.typelib.helpdir)
3394 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3396 /* module names are packed one after another */
3397 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3399 tlib_count++;
3405 total_len += aligned_string_len(names_len);
3406 total_len += sizeof(*header);
3408 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3409 if (!header) return STATUS_NO_MEMORY;
3411 memset(header, 0, sizeof(*header));
3412 header->magic = GUIDSECTION_MAGIC;
3413 header->size = sizeof(*header);
3414 header->count = tlib_count;
3415 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3416 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3417 module_offset = sizeof(*header);
3418 data_offset = header->index_offset + tlib_count*sizeof(*index);
3420 for (i = 0; i < actctx->num_assemblies; i++)
3422 struct assembly *assembly = &actctx->assemblies[i];
3423 for (j = 0; j < assembly->num_dlls; j++)
3425 struct dll_redirect *dll = &assembly->dlls[j];
3426 for (k = 0; k < dll->entities.num; k++)
3428 struct entity *entity = &dll->entities.base[k];
3429 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3431 ULONG module_len, help_len;
3432 UNICODE_STRING str;
3433 WCHAR *ptrW;
3435 if (*entity->u.typelib.helpdir)
3436 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3437 else
3438 help_len = 0;
3440 module_len = strlenW(dll->name)*sizeof(WCHAR);
3442 /* setup new index entry */
3443 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3444 RtlGUIDFromString(&str, &index->guid);
3445 index->data_offset = data_offset;
3446 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3447 index->rosterindex = i + 1;
3449 /* setup data */
3450 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3451 data->size = sizeof(*data);
3452 data->res = 0;
3453 data->name_len = module_len;
3454 data->name_offset = module_offset;
3455 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3456 data->langid = 0;
3457 data->flags = entity->u.typelib.flags;
3458 data->help_len = help_len;
3459 data->help_offset = sizeof(*data);
3460 data->major_version = entity->u.typelib.major;
3461 data->minor_version = entity->u.typelib.minor;
3463 /* module name */
3464 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3465 memcpy(ptrW, dll->name, data->name_len);
3466 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3468 /* help string */
3469 if (data->help_len)
3471 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3472 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3473 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3476 data_offset += sizeof(*data);
3477 if (help_len)
3478 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3480 module_offset += module_len + sizeof(WCHAR);
3482 index++;
3488 *section = header;
3490 return STATUS_SUCCESS;
3493 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3495 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3498 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3500 struct guid_index *index = NULL;
3501 struct tlibredirect_data *tlib;
3503 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3505 if (!actctx->tlib_section)
3507 struct guidsection_header *section;
3509 NTSTATUS status = build_tlib_section(actctx, &section);
3510 if (status) return status;
3512 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3513 RtlFreeHeap(GetProcessHeap(), 0, section);
3516 index = find_guid_index(actctx->tlib_section, guid);
3517 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3519 tlib = get_tlib_data(actctx, index);
3521 data->ulDataFormatVersion = 1;
3522 data->lpData = tlib;
3523 /* full length includes string length with nulls */
3524 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3525 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3526 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3527 data->lpSectionBase = actctx->tlib_section;
3528 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3529 data->hActCtx = NULL;
3531 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3532 data->ulAssemblyRosterIndex = index->rosterindex;
3534 return STATUS_SUCCESS;
3537 static void generate_uuid(ULONG *seed, GUID *guid)
3539 ULONG *ptr = (ULONG*)guid;
3540 int i;
3542 /* GUID is 16 bytes long */
3543 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3544 *ptr = RtlUniform(seed);
3546 guid->Data3 &= 0x0fff;
3547 guid->Data3 |= (4 << 12);
3548 guid->Data4[0] &= 0x3f;
3549 guid->Data4[0] |= 0x80;
3552 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3553 unsigned int *count, unsigned int *len, unsigned int *module_len)
3555 unsigned int i;
3557 for (i = 0; i < entities->num; i++)
3559 struct entity *entity = &entities->base[i];
3560 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3562 /* each entry needs two index entries, extra one goes for alias GUID */
3563 *len += 2*sizeof(struct guid_index);
3564 /* To save some memory we don't allocated two data structures,
3565 instead alias index and normal index point to the same data structure. */
3566 *len += sizeof(struct comclassredirect_data);
3568 /* for clrClass store some more */
3569 if (entity->u.comclass.name)
3571 unsigned int str_len;
3573 /* all string data is stored together in aligned block */
3574 str_len = strlenW(entity->u.comclass.name)+1;
3575 if (entity->u.comclass.progid)
3576 str_len += strlenW(entity->u.comclass.progid)+1;
3577 if (entity->u.comclass.version)
3578 str_len += strlenW(entity->u.comclass.version)+1;
3580 *len += sizeof(struct clrclass_data);
3581 *len += aligned_string_len(str_len*sizeof(WCHAR));
3583 /* module name is forced to mscoree.dll, and stored two times with different case */
3584 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3586 else
3588 /* progid string is stored separately */
3589 if (entity->u.comclass.progid)
3590 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3592 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3595 *count += 1;
3600 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3601 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3602 ULONG *seed, ULONG rosterindex)
3604 unsigned int i;
3606 for (i = 0; i < entities->num; i++)
3608 struct entity *entity = &entities->base[i];
3609 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3611 ULONG module_len, progid_len, str_len = 0;
3612 struct comclassredirect_data *data;
3613 struct guid_index *alias_index;
3614 struct clrclass_data *clrdata;
3615 UNICODE_STRING str;
3616 WCHAR *ptrW;
3618 if (entity->u.comclass.progid)
3619 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3620 else
3621 progid_len = 0;
3623 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3625 /* setup new index entry */
3626 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3627 RtlGUIDFromString(&str, &(*index)->guid);
3629 (*index)->data_offset = *data_offset;
3630 (*index)->data_len = sizeof(*data); /* additional length added later */
3631 (*index)->rosterindex = rosterindex;
3633 /* Setup new index entry for alias guid. Alias index records are placed after
3634 normal records, so normal guids are hit first on search. Note that class count
3635 is doubled. */
3636 alias_index = (*index) + section->count/2;
3637 generate_uuid(seed, &alias_index->guid);
3638 alias_index->data_offset = (*index)->data_offset;
3639 alias_index->data_len = 0;
3640 alias_index->rosterindex = (*index)->rosterindex;
3642 /* setup data */
3643 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3644 data->size = sizeof(*data);
3645 data->res = 0;
3646 data->res1[0] = 0;
3647 data->res1[1] = 0;
3648 data->model = entity->u.comclass.model;
3649 data->clsid = (*index)->guid;
3650 data->alias = alias_index->guid;
3651 data->clsid2 = data->clsid;
3652 if (entity->u.comclass.tlbid)
3654 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3655 RtlGUIDFromString(&str, &data->tlbid);
3657 else
3658 memset(&data->tlbid, 0, sizeof(data->tlbid));
3659 data->name_len = module_len;
3660 data->name_offset = *module_offset;
3661 data->progid_len = progid_len;
3662 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3663 data->clrdata_len = 0; /* will be set later */
3664 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3665 data->miscstatus = entity->u.comclass.miscstatus;
3666 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3667 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3668 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3669 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3671 /* mask describes which misc* data is available */
3672 data->miscmask = 0;
3673 if (data->miscstatus)
3674 data->miscmask |= MiscStatus;
3675 if (data->miscstatuscontent)
3676 data->miscmask |= MiscStatusContent;
3677 if (data->miscstatusthumbnail)
3678 data->miscmask |= MiscStatusThumbnail;
3679 if (data->miscstatusicon)
3680 data->miscmask |= MiscStatusIcon;
3681 if (data->miscstatusdocprint)
3682 data->miscmask |= MiscStatusDocPrint;
3684 if (data->clrdata_offset)
3686 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3688 clrdata->size = sizeof(*clrdata);
3689 clrdata->res[0] = 0;
3690 clrdata->res[1] = 2; /* FIXME: unknown field */
3691 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3692 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3693 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3694 clrdata->name_offset = clrdata->size;
3695 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3696 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3697 clrdata->res2[0] = 0;
3698 clrdata->res2[1] = 0;
3700 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3702 /* module name */
3703 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3704 memcpy(ptrW, mscoree2W, clrdata->module_len);
3705 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3707 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3708 memcpy(ptrW, mscoreeW, data->name_len);
3709 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3711 /* class name */
3712 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3713 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3714 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3716 /* runtime version, optional */
3717 if (clrdata->version_len)
3719 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3721 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3722 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3723 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3726 if (data->progid_len)
3727 data->progid_offset += data->clrdata_len;
3728 (*index)->data_len += sizeof(*clrdata);
3730 else
3732 clrdata = NULL;
3734 /* module name */
3735 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3736 memcpy(ptrW, dll->name, data->name_len);
3737 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3740 /* progid string */
3741 if (data->progid_len)
3743 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3744 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3745 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3748 /* string block length */
3749 str_len = 0;
3750 if (clrdata)
3752 str_len += clrdata->name_len + sizeof(WCHAR);
3753 if (clrdata->version_len)
3754 str_len += clrdata->version_len + sizeof(WCHAR);
3756 if (progid_len)
3757 str_len += progid_len + sizeof(WCHAR);
3759 (*index)->data_len += aligned_string_len(str_len);
3760 alias_index->data_len = (*index)->data_len;
3762 /* move to next data record */
3763 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3764 (*module_offset) += module_len + sizeof(WCHAR);
3766 if (clrdata)
3768 (*data_offset) += sizeof(*clrdata);
3769 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3771 (*index) += 1;
3776 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3778 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3779 struct guidsection_header *header;
3780 ULONG module_offset, data_offset;
3781 struct guid_index *index;
3782 ULONG seed;
3784 /* compute section length */
3785 for (i = 0; i < actctx->num_assemblies; i++)
3787 struct assembly *assembly = &actctx->assemblies[i];
3788 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3789 for (j = 0; j < assembly->num_dlls; j++)
3791 struct dll_redirect *dll = &assembly->dlls[j];
3792 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3796 total_len += aligned_string_len(names_len);
3797 total_len += sizeof(*header);
3799 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3800 if (!header) return STATUS_NO_MEMORY;
3802 memset(header, 0, sizeof(*header));
3803 header->magic = GUIDSECTION_MAGIC;
3804 header->size = sizeof(*header);
3805 header->count = 2*class_count;
3806 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3807 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3808 module_offset = sizeof(*header);
3809 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3811 seed = NtGetTickCount();
3812 for (i = 0; i < actctx->num_assemblies; i++)
3814 struct assembly *assembly = &actctx->assemblies[i];
3815 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3816 for (j = 0; j < assembly->num_dlls; j++)
3818 struct dll_redirect *dll = &assembly->dlls[j];
3819 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3823 *section = header;
3825 return STATUS_SUCCESS;
3828 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3830 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3833 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3835 struct comclassredirect_data *comclass;
3836 struct guid_index *index = NULL;
3838 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3840 if (!actctx->comserver_section)
3842 struct guidsection_header *section;
3844 NTSTATUS status = build_comserver_section(actctx, &section);
3845 if (status) return status;
3847 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3848 RtlFreeHeap(GetProcessHeap(), 0, section);
3851 index = find_guid_index(actctx->comserver_section, guid);
3852 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3854 comclass = get_comclass_data(actctx, index);
3856 data->ulDataFormatVersion = 1;
3857 data->lpData = comclass;
3858 /* full length includes string length with nulls */
3859 data->ulLength = comclass->size + comclass->clrdata_len;
3860 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
3861 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3862 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3863 data->lpSectionBase = actctx->comserver_section;
3864 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3865 data->hActCtx = NULL;
3867 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3868 data->ulAssemblyRosterIndex = index->rosterindex;
3870 return STATUS_SUCCESS;
3873 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3875 unsigned int i;
3877 for (i = 0; i < entities->num; i++)
3879 struct entity *entity = &entities->base[i];
3880 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3882 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3883 if (entity->u.ifaceps.name)
3884 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3885 *count += 1;
3890 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3891 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3893 unsigned int i;
3895 for (i = 0; i < entities->num; i++)
3897 struct entity *entity = &entities->base[i];
3898 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3900 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3901 UNICODE_STRING str;
3902 ULONG name_len;
3904 if (entity->u.ifaceps.name)
3905 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3906 else
3907 name_len = 0;
3909 /* setup index */
3910 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3911 RtlGUIDFromString(&str, &(*index)->guid);
3912 (*index)->data_offset = *data_offset;
3913 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3914 (*index)->rosterindex = rosterindex;
3916 /* setup data record */
3917 data->size = sizeof(*data);
3918 data->mask = entity->u.ifaceps.mask;
3920 /* proxyStubClsid32 value is only stored for external PS,
3921 if set it's used as iid, otherwise 'iid' attribute value is used */
3922 if (entity->u.ifaceps.ps32)
3924 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3925 RtlGUIDFromString(&str, &data->iid);
3927 else
3928 data->iid = (*index)->guid;
3930 data->nummethods = entity->u.ifaceps.nummethods;
3932 if (entity->u.ifaceps.tlib)
3934 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3935 RtlGUIDFromString(&str, &data->tlbid);
3937 else
3938 memset(&data->tlbid, 0, sizeof(data->tlbid));
3940 if (entity->u.ifaceps.base)
3942 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3943 RtlGUIDFromString(&str, &data->base);
3945 else
3946 memset(&data->base, 0, sizeof(data->base));
3948 data->name_len = name_len;
3949 data->name_offset = data->name_len ? sizeof(*data) : 0;
3951 /* name string */
3952 if (data->name_len)
3954 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3955 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3956 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3959 /* move to next record */
3960 (*index) += 1;
3961 *data_offset += sizeof(*data);
3962 if (data->name_len)
3963 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3968 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3970 unsigned int i, j, total_len = 0, count = 0;
3971 struct guidsection_header *header;
3972 struct guid_index *index;
3973 ULONG data_offset;
3975 /* compute section length */
3976 for (i = 0; i < actctx->num_assemblies; i++)
3978 struct assembly *assembly = &actctx->assemblies[i];
3980 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3981 for (j = 0; j < assembly->num_dlls; j++)
3983 struct dll_redirect *dll = &assembly->dlls[j];
3984 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3988 total_len += sizeof(*header);
3990 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3991 if (!header) return STATUS_NO_MEMORY;
3993 memset(header, 0, sizeof(*header));
3994 header->magic = GUIDSECTION_MAGIC;
3995 header->size = sizeof(*header);
3996 header->count = count;
3997 header->index_offset = sizeof(*header);
3998 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3999 data_offset = header->index_offset + count*sizeof(*index);
4001 for (i = 0; i < actctx->num_assemblies; i++)
4003 struct assembly *assembly = &actctx->assemblies[i];
4005 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4006 for (j = 0; j < assembly->num_dlls; j++)
4008 struct dll_redirect *dll = &assembly->dlls[j];
4009 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4013 *section = header;
4015 return STATUS_SUCCESS;
4018 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4020 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4023 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4025 struct ifacepsredirect_data *iface;
4026 struct guid_index *index = NULL;
4028 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4030 if (!actctx->ifaceps_section)
4032 struct guidsection_header *section;
4034 NTSTATUS status = build_ifaceps_section(actctx, &section);
4035 if (status) return status;
4037 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4038 RtlFreeHeap(GetProcessHeap(), 0, section);
4041 index = find_guid_index(actctx->ifaceps_section, guid);
4042 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4044 iface = get_ifaceps_data(actctx, index);
4046 data->ulDataFormatVersion = 1;
4047 data->lpData = iface;
4048 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4049 data->lpSectionGlobalData = NULL;
4050 data->ulSectionGlobalDataLength = 0;
4051 data->lpSectionBase = actctx->ifaceps_section;
4052 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4053 data->hActCtx = NULL;
4055 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4056 data->ulAssemblyRosterIndex = index->rosterindex;
4058 return STATUS_SUCCESS;
4061 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4063 unsigned int i, j, total_len = 0, count = 0;
4064 struct guidsection_header *header;
4065 struct clrsurrogate_data *data;
4066 struct guid_index *index;
4067 ULONG data_offset;
4069 /* compute section length */
4070 for (i = 0; i < actctx->num_assemblies; i++)
4072 struct assembly *assembly = &actctx->assemblies[i];
4073 for (j = 0; j < assembly->entities.num; j++)
4075 struct entity *entity = &assembly->entities.base[j];
4076 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4078 ULONG len;
4080 total_len += sizeof(*index) + sizeof(*data);
4081 len = strlenW(entity->u.clrsurrogate.name) + 1;
4082 if (entity->u.clrsurrogate.version)
4083 len += strlenW(entity->u.clrsurrogate.version) + 1;
4084 total_len += aligned_string_len(len*sizeof(WCHAR));
4086 count++;
4091 total_len += sizeof(*header);
4093 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4094 if (!header) return STATUS_NO_MEMORY;
4096 memset(header, 0, sizeof(*header));
4097 header->magic = GUIDSECTION_MAGIC;
4098 header->size = sizeof(*header);
4099 header->count = count;
4100 header->index_offset = sizeof(*header);
4101 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4102 data_offset = header->index_offset + count*sizeof(*index);
4104 for (i = 0; i < actctx->num_assemblies; i++)
4106 struct assembly *assembly = &actctx->assemblies[i];
4107 for (j = 0; j < assembly->entities.num; j++)
4109 struct entity *entity = &assembly->entities.base[j];
4110 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4112 ULONG version_len, name_len;
4113 UNICODE_STRING str;
4114 WCHAR *ptrW;
4116 if (entity->u.clrsurrogate.version)
4117 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4118 else
4119 version_len = 0;
4120 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4122 /* setup new index entry */
4123 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4124 RtlGUIDFromString(&str, &index->guid);
4126 index->data_offset = data_offset;
4127 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4128 index->rosterindex = i + 1;
4130 /* setup data */
4131 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4132 data->size = sizeof(*data);
4133 data->res = 0;
4134 data->clsid = index->guid;
4135 data->version_offset = version_len ? data->size : 0;
4136 data->version_len = version_len;
4137 data->name_offset = data->size + version_len;
4138 if (version_len)
4139 data->name_offset += sizeof(WCHAR);
4140 data->name_len = name_len;
4142 /* surrogate name */
4143 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4144 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4145 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4147 /* runtime version */
4148 if (data->version_len)
4150 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4151 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4152 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4155 data_offset += index->data_offset;
4156 index++;
4161 *section = header;
4163 return STATUS_SUCCESS;
4166 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4168 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4171 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4173 struct clrsurrogate_data *surrogate;
4174 struct guid_index *index = NULL;
4176 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4178 if (!actctx->clrsurrogate_section)
4180 struct guidsection_header *section;
4182 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4183 if (status) return status;
4185 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4186 RtlFreeHeap(GetProcessHeap(), 0, section);
4189 index = find_guid_index(actctx->clrsurrogate_section, guid);
4190 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4192 surrogate = get_surrogate_data(actctx, index);
4194 data->ulDataFormatVersion = 1;
4195 data->lpData = surrogate;
4196 /* full length includes string length with nulls */
4197 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4198 if (surrogate->version_len)
4199 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4201 data->lpSectionGlobalData = NULL;
4202 data->ulSectionGlobalDataLength = 0;
4203 data->lpSectionBase = actctx->clrsurrogate_section;
4204 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4205 data->hActCtx = NULL;
4207 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4208 data->ulAssemblyRosterIndex = index->rosterindex;
4210 return STATUS_SUCCESS;
4213 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4215 unsigned int i, j, single_len;
4217 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4218 for (i = 0; i < entities->num; i++)
4220 struct entity *entity = &entities->base[i];
4221 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4223 if (entity->u.comclass.progid)
4225 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4226 *count += 1;
4229 for (j = 0; j < entity->u.comclass.progids.num; j++)
4230 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4232 *total_len += single_len*entity->u.comclass.progids.num;
4233 *count += entity->u.comclass.progids.num;
4238 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4239 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4241 struct progidredirect_data *data;
4242 UNICODE_STRING str;
4243 GUID *guid_ptr;
4244 WCHAR *ptrW;
4246 /* setup new index entry */
4248 /* hash progid name */
4249 RtlInitUnicodeString(&str, progid);
4250 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4252 (*index)->name_offset = *data_offset;
4253 (*index)->name_len = str.Length;
4254 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4255 (*index)->data_len = sizeof(*data);
4256 (*index)->rosterindex = rosterindex;
4258 *data_offset += aligned_string_len(str.MaximumLength);
4260 /* setup data structure */
4261 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4262 data->size = sizeof(*data);
4263 data->reserved = 0;
4264 data->clsid_offset = *global_offset;
4266 /* write progid string */
4267 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4268 memcpy(ptrW, progid, (*index)->name_len);
4269 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4271 /* write guid to global area */
4272 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4273 *guid_ptr = *alias;
4275 /* to next entry */
4276 *global_offset += sizeof(GUID);
4277 *data_offset += data->size;
4278 (*index) += 1;
4281 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4282 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4284 unsigned int i, j;
4286 for (i = 0; i < entities->num; i++)
4288 struct entity *entity = &entities->base[i];
4289 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4291 const struct progids *progids = &entity->u.comclass.progids;
4292 struct comclassredirect_data *comclass;
4293 struct guid_index *guid_index;
4294 UNICODE_STRING str;
4295 GUID clsid;
4297 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4298 RtlGUIDFromString(&str, &clsid);
4300 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4301 comclass = get_comclass_data(actctx, guid_index);
4303 if (entity->u.comclass.progid)
4304 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4305 index, data_offset, global_offset, rosterindex);
4307 for (j = 0; j < progids->num; j++)
4308 write_progid_record(section, progids->progids[j], &comclass->alias,
4309 index, data_offset, global_offset, rosterindex);
4314 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4316 unsigned int i, j, total_len = 0, count = 0;
4317 struct strsection_header *header;
4318 ULONG data_offset, global_offset;
4319 struct string_index *index;
4321 /* compute section length */
4322 for (i = 0; i < actctx->num_assemblies; i++)
4324 struct assembly *assembly = &actctx->assemblies[i];
4326 get_progid_datalen(&assembly->entities, &count, &total_len);
4327 for (j = 0; j < assembly->num_dlls; j++)
4329 struct dll_redirect *dll = &assembly->dlls[j];
4330 get_progid_datalen(&dll->entities, &count, &total_len);
4334 total_len += sizeof(*header);
4336 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4337 if (!header) return STATUS_NO_MEMORY;
4339 memset(header, 0, sizeof(*header));
4340 header->magic = STRSECTION_MAGIC;
4341 header->size = sizeof(*header);
4342 header->count = count;
4343 header->global_offset = header->size;
4344 header->global_len = count*sizeof(GUID);
4345 header->index_offset = header->size + header->global_len;
4347 index = (struct string_index*)((BYTE*)header + header->index_offset);
4348 data_offset = header->index_offset + count*sizeof(*index);
4349 global_offset = header->global_offset;
4351 for (i = 0; i < actctx->num_assemblies; i++)
4353 struct assembly *assembly = &actctx->assemblies[i];
4355 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4356 for (j = 0; j < assembly->num_dlls; j++)
4358 struct dll_redirect *dll = &assembly->dlls[j];
4359 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4363 *section = header;
4365 return STATUS_SUCCESS;
4368 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4370 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4373 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4374 PACTCTX_SECTION_KEYED_DATA data)
4376 struct progidredirect_data *progid;
4377 struct string_index *index;
4379 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4381 if (!actctx->comserver_section)
4383 struct guidsection_header *section;
4385 NTSTATUS status = build_comserver_section(actctx, &section);
4386 if (status) return status;
4388 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4389 RtlFreeHeap(GetProcessHeap(), 0, section);
4392 if (!actctx->progid_section)
4394 struct strsection_header *section;
4396 NTSTATUS status = build_progid_section(actctx, &section);
4397 if (status) return status;
4399 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4400 RtlFreeHeap(GetProcessHeap(), 0, section);
4403 index = find_string_index(actctx->progid_section, name);
4404 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4406 if (data)
4408 progid = get_progid_data(actctx, index);
4410 data->ulDataFormatVersion = 1;
4411 data->lpData = progid;
4412 data->ulLength = progid->size;
4413 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4414 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4415 data->lpSectionBase = actctx->progid_section;
4416 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4417 data->hActCtx = NULL;
4419 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4420 data->ulAssemblyRosterIndex = index->rosterindex;
4423 return STATUS_SUCCESS;
4426 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4427 const UNICODE_STRING *section_name,
4428 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4430 NTSTATUS status;
4432 switch (section_kind)
4434 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4435 status = find_dll_redirection(actctx, section_name, data);
4436 break;
4437 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4438 status = find_window_class(actctx, section_name, data);
4439 break;
4440 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4441 status = find_progid_redirection(actctx, section_name, data);
4442 break;
4443 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4444 FIXME("Unsupported yet section_kind %x\n", section_kind);
4445 return STATUS_SXS_SECTION_NOT_FOUND;
4446 default:
4447 WARN("Unknown section_kind %x\n", section_kind);
4448 return STATUS_SXS_SECTION_NOT_FOUND;
4451 if (status != STATUS_SUCCESS) return status;
4453 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4455 actctx_addref(actctx);
4456 data->hActCtx = actctx;
4458 return STATUS_SUCCESS;
4461 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4462 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4464 NTSTATUS status;
4466 switch (section_kind)
4468 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4469 status = find_tlib_redirection(actctx, guid, data);
4470 break;
4471 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4472 status = find_comserver_redirection(actctx, guid, data);
4473 break;
4474 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4475 status = find_cominterface_redirection(actctx, guid, data);
4476 break;
4477 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4478 status = find_clr_surrogate(actctx, guid, data);
4479 break;
4480 default:
4481 WARN("Unknown section_kind %x\n", section_kind);
4482 return STATUS_SXS_SECTION_NOT_FOUND;
4485 if (status != STATUS_SUCCESS) return status;
4487 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4489 actctx_addref(actctx);
4490 data->hActCtx = actctx;
4492 return STATUS_SUCCESS;
4495 /* initialize the activation context for the current process */
4496 void actctx_init(void)
4498 ACTCTXW ctx;
4499 HANDLE handle;
4501 ctx.cbSize = sizeof(ctx);
4502 ctx.lpSource = NULL;
4503 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4504 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4505 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4507 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4511 /***********************************************************************
4512 * RtlCreateActivationContext (NTDLL.@)
4514 * Create an activation context.
4516 * FIXME: function signature/prototype is wrong
4518 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4520 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4521 const WCHAR *directory = NULL;
4522 ACTIVATION_CONTEXT *actctx;
4523 UNICODE_STRING nameW;
4524 ULONG lang = 0;
4525 NTSTATUS status = STATUS_NO_MEMORY;
4526 HANDLE file = 0;
4527 struct actctx_loader acl;
4529 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4531 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4532 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4533 return STATUS_INVALID_PARAMETER;
4535 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4536 return STATUS_NO_MEMORY;
4538 actctx->magic = ACTCTX_MAGIC;
4539 actctx->ref_count = 1;
4540 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4541 actctx->config.info = NULL;
4542 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4543 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4545 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4547 else
4549 UNICODE_STRING dir;
4550 WCHAR *p;
4551 HMODULE module;
4553 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4554 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4556 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4557 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4558 actctx->appdir.info = dir.Buffer;
4561 nameW.Buffer = NULL;
4563 /* open file only if it's going to be used */
4564 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4565 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4567 WCHAR *source = NULL;
4568 BOOLEAN ret;
4570 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4571 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4573 DWORD dir_len, source_len;
4575 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4576 source_len = strlenW(pActCtx->lpSource);
4577 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4579 status = STATUS_NO_MEMORY;
4580 goto error;
4583 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4584 source[dir_len] = '\\';
4585 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4588 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4589 if (source) RtlFreeHeap( GetProcessHeap(), 0, source );
4590 if (!ret)
4592 status = STATUS_NO_SUCH_FILE;
4593 goto error;
4595 status = open_nt_file( &file, &nameW );
4596 if (status)
4598 RtlFreeUnicodeString( &nameW );
4599 goto error;
4603 acl.actctx = actctx;
4604 acl.dependencies = NULL;
4605 acl.num_dependencies = 0;
4606 acl.allocated_dependencies = 0;
4608 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4609 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4611 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4613 /* if we have a resource it's a PE file */
4614 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4616 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4617 pActCtx->lpResourceName, lang );
4618 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4619 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4620 pActCtx->hModule, pActCtx->lpResourceName );
4622 else if (pActCtx->lpSource)
4624 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4625 file, pActCtx->lpResourceName, lang );
4626 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4627 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4628 NULL, pActCtx->lpResourceName );
4630 else status = STATUS_INVALID_PARAMETER;
4632 else
4634 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4637 if (file) NtClose( file );
4638 RtlFreeUnicodeString( &nameW );
4640 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4641 free_depend_manifests( &acl );
4643 if (status == STATUS_SUCCESS) *handle = actctx;
4644 else actctx_release( actctx );
4645 return status;
4647 error:
4648 if (file) NtClose( file );
4649 actctx_release( actctx );
4650 return status;
4654 /***********************************************************************
4655 * RtlAddRefActivationContext (NTDLL.@)
4657 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4659 ACTIVATION_CONTEXT *actctx;
4661 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4665 /******************************************************************
4666 * RtlReleaseActivationContext (NTDLL.@)
4668 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4670 ACTIVATION_CONTEXT *actctx;
4672 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4675 /******************************************************************
4676 * RtlZombifyActivationContext (NTDLL.@)
4678 * FIXME: function prototype might be wrong
4680 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4682 FIXME("%p: stub\n", handle);
4683 return STATUS_NOT_IMPLEMENTED;
4686 /******************************************************************
4687 * RtlActivateActivationContext (NTDLL.@)
4689 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4691 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4693 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4694 return STATUS_NO_MEMORY;
4696 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4697 frame->ActivationContext = handle;
4698 frame->Flags = 0;
4699 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4700 RtlAddRefActivationContext( handle );
4702 *cookie = (ULONG_PTR)frame;
4703 TRACE( "%p cookie=%lx\n", handle, *cookie );
4704 return STATUS_SUCCESS;
4708 /***********************************************************************
4709 * RtlDeactivateActivationContext (NTDLL.@)
4711 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4713 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4715 TRACE( "%x cookie=%lx\n", flags, cookie );
4717 /* find the right frame */
4718 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4719 for (frame = top; frame; frame = frame->Previous)
4720 if ((ULONG_PTR)frame == cookie) break;
4722 if (!frame)
4723 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4725 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4726 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4728 /* pop everything up to and including frame */
4729 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4731 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4733 frame = top->Previous;
4734 RtlReleaseActivationContext( top->ActivationContext );
4735 RtlFreeHeap( GetProcessHeap(), 0, top );
4736 top = frame;
4741 /******************************************************************
4742 * RtlFreeThreadActivationContextStack (NTDLL.@)
4744 void WINAPI RtlFreeThreadActivationContextStack(void)
4746 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4748 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4749 while (frame)
4751 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4752 RtlReleaseActivationContext( frame->ActivationContext );
4753 RtlFreeHeap( GetProcessHeap(), 0, frame );
4754 frame = prev;
4756 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4760 /******************************************************************
4761 * RtlGetActiveActivationContext (NTDLL.@)
4763 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4765 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4767 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4768 RtlAddRefActivationContext( *handle );
4770 else
4771 *handle = 0;
4773 return STATUS_SUCCESS;
4777 /******************************************************************
4778 * RtlIsActivationContextActive (NTDLL.@)
4780 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4782 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4784 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4785 if (frame->ActivationContext == handle) return TRUE;
4786 return FALSE;
4790 /***********************************************************************
4791 * RtlQueryInformationActivationContext (NTDLL.@)
4793 * Get information about an activation context.
4794 * FIXME: function signature/prototype may be wrong
4796 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4797 ULONG class, PVOID buffer,
4798 SIZE_T bufsize, SIZE_T *retlen )
4800 ACTIVATION_CONTEXT *actctx;
4801 NTSTATUS status;
4803 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4804 subinst, class, buffer, bufsize, retlen);
4806 if (retlen) *retlen = 0;
4807 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4809 switch (class)
4811 case ActivationContextBasicInformation:
4813 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4815 if (retlen) *retlen = sizeof(*info);
4816 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4818 info->hActCtx = handle;
4819 info->dwFlags = 0; /* FIXME */
4820 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4822 break;
4824 case ActivationContextDetailedInformation:
4826 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4827 struct assembly *assembly = NULL;
4828 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4829 LPWSTR ptr;
4831 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4833 if (actctx->num_assemblies) assembly = actctx->assemblies;
4835 if (assembly && assembly->manifest.info)
4836 manifest_len = strlenW(assembly->manifest.info) + 1;
4837 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4838 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4839 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4841 if (retlen) *retlen = len;
4842 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4844 acdi->dwFlags = 0;
4845 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4846 acdi->ulAssemblyCount = actctx->num_assemblies;
4847 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4848 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4849 acdi->ulRootConfigurationPathType = actctx->config.type;
4850 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4851 acdi->ulAppDirPathType = actctx->appdir.type;
4852 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4853 ptr = (LPWSTR)(acdi + 1);
4854 if (manifest_len)
4856 acdi->lpRootManifestPath = ptr;
4857 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4858 ptr += manifest_len;
4860 else acdi->lpRootManifestPath = NULL;
4861 if (config_len)
4863 acdi->lpRootConfigurationPath = ptr;
4864 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4865 ptr += config_len;
4867 else acdi->lpRootConfigurationPath = NULL;
4868 if (appdir_len)
4870 acdi->lpAppDirPath = ptr;
4871 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4873 else acdi->lpAppDirPath = NULL;
4875 break;
4877 case AssemblyDetailedInformationInActivationContext:
4879 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4880 struct assembly *assembly;
4881 WCHAR *assembly_id;
4882 DWORD index;
4883 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4884 LPWSTR ptr;
4886 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4887 if (!subinst) return STATUS_INVALID_PARAMETER;
4889 index = *(DWORD*)subinst;
4890 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4892 assembly = &actctx->assemblies[index - 1];
4894 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4895 id_len = strlenW(assembly_id) + 1;
4896 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4898 if (assembly->manifest.info &&
4899 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4900 path_len = strlenW(assembly->manifest.info) + 1;
4902 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4904 if (retlen) *retlen = len;
4905 if (!buffer || bufsize < len)
4907 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4908 return STATUS_BUFFER_TOO_SMALL;
4911 afdi->ulFlags = 0; /* FIXME */
4912 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4913 afdi->ulManifestPathType = assembly->manifest.type;
4914 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4915 /* FIXME afdi->liManifestLastWriteTime = 0; */
4916 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4917 afdi->ulPolicyPathLength = 0;
4918 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4919 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4920 afdi->ulManifestVersionMajor = 1;
4921 afdi->ulManifestVersionMinor = 0;
4922 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4923 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4924 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4925 ptr = (LPWSTR)(afdi + 1);
4926 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4927 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4928 ptr += id_len;
4929 if (path_len)
4931 afdi->lpAssemblyManifestPath = ptr;
4932 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4933 ptr += path_len;
4934 } else afdi->lpAssemblyManifestPath = NULL;
4935 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4936 if (ad_len)
4938 afdi->lpAssemblyDirectoryName = ptr;
4939 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4941 else afdi->lpAssemblyDirectoryName = NULL;
4942 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4944 break;
4946 case FileInformationInAssemblyOfAssemblyInActivationContext:
4948 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4949 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4950 struct assembly *assembly;
4951 struct dll_redirect *dll;
4952 SIZE_T len, dll_len = 0;
4953 LPWSTR ptr;
4955 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4956 if (!acqi) return STATUS_INVALID_PARAMETER;
4958 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4959 return STATUS_INVALID_PARAMETER;
4960 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4962 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4963 return STATUS_INVALID_PARAMETER;
4964 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4966 if (dll->name) dll_len = strlenW(dll->name) + 1;
4967 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4969 if (!buffer || bufsize < len)
4971 if (retlen) *retlen = len;
4972 return STATUS_BUFFER_TOO_SMALL;
4974 if (retlen) *retlen = 0; /* yes that's what native does !! */
4975 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4976 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4977 afdi->ulPathLength = 0; /* FIXME */
4978 ptr = (LPWSTR)(afdi + 1);
4979 if (dll_len)
4981 afdi->lpFileName = ptr;
4982 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4983 } else afdi->lpFileName = NULL;
4984 afdi->lpFilePath = NULL; /* FIXME */
4986 break;
4988 default:
4989 FIXME( "class %u not implemented\n", class );
4990 return STATUS_NOT_IMPLEMENTED;
4992 return STATUS_SUCCESS;
4995 /***********************************************************************
4996 * RtlFindActivationContextSectionString (NTDLL.@)
4998 * Find information about a string in an activation context.
4999 * FIXME: function signature/prototype may be wrong
5001 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5002 const UNICODE_STRING *section_name, PVOID ptr )
5004 PACTCTX_SECTION_KEYED_DATA data = ptr;
5005 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5007 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5008 debugstr_us(section_name), data);
5010 if (guid)
5012 FIXME("expected guid == NULL\n");
5013 return STATUS_INVALID_PARAMETER;
5015 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5017 FIXME("unknown flags %08x\n", flags);
5018 return STATUS_INVALID_PARAMETER;
5020 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5021 !section_name || !section_name->Buffer)
5023 WARN("invalid parameter\n");
5024 return STATUS_INVALID_PARAMETER;
5027 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5029 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5030 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5033 if (status != STATUS_SUCCESS)
5034 status = find_string( process_actctx, section_kind, section_name, flags, data );
5036 return status;
5039 /***********************************************************************
5040 * RtlFindActivationContextSectionGuid (NTDLL.@)
5042 * Find information about a GUID in an activation context.
5043 * FIXME: function signature/prototype may be wrong
5045 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5046 const GUID *guid, void *ptr )
5048 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5049 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5051 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5053 if (extguid)
5055 FIXME("expected extguid == NULL\n");
5056 return STATUS_INVALID_PARAMETER;
5059 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5061 FIXME("unknown flags %08x\n", flags);
5062 return STATUS_INVALID_PARAMETER;
5065 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5066 return STATUS_INVALID_PARAMETER;
5068 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5070 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5071 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5074 if (status != STATUS_SUCCESS)
5075 status = find_guid( process_actctx, section_kind, guid, flags, data );
5077 return status;