1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Runtime Library 4 * PURPOSE: Activation Context Support 5 * FILE: lib/rtl/actctx.c 6 * PROGRAMERS: 7 * Jon Griffiths 8 * Eric Pouech 9 * Jacek Caban for CodeWeavers 10 * Alexandre Julliard 11 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 12 * Samuel Serapión 13 */ 14 15 /* Based on Wine 3.2-37c98396 */ 16 17 #include <rtl.h> 18 #include <ntstrsafe.h> 19 #include <compat_undoc.h> 20 21 #define NDEBUG 22 #include <debug.h> 23 24 #include <wine/unicode.h> 25 26 BOOLEAN RtlpNotAllowingMultipleActivation; 27 28 #define ACTCTX_FLAGS_ALL (\ 29 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\ 30 ACTCTX_FLAG_LANGID_VALID |\ 31 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\ 32 ACTCTX_FLAG_RESOURCE_NAME_VALID |\ 33 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\ 34 ACTCTX_FLAG_APPLICATION_NAME_VALID |\ 35 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\ 36 ACTCTX_FLAG_HMODULE_VALID ) 37 38 #define STRSECTION_MAGIC 0x64487353 /* dHsS */ 39 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */ 40 41 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA' 42 43 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa) 44 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad) 45 46 #define MAX_NAMESPACES 64 47 48 typedef struct 49 { 50 const WCHAR *ptr; 51 unsigned int len; 52 } xmlstr_t; 53 54 struct xml_elem 55 { 56 xmlstr_t name; 57 xmlstr_t ns; 58 int ns_pos; 59 }; 60 61 struct xml_attr 62 { 63 xmlstr_t name; 64 xmlstr_t value; 65 }; 66 67 typedef struct 68 { 69 const WCHAR *ptr; 70 const WCHAR *end; 71 struct xml_attr namespaces[MAX_NAMESPACES]; 72 int ns_pos; 73 BOOL error; 74 } xmlbuf_t; 75 76 struct file_info 77 { 78 ULONG type; 79 WCHAR *info; 80 }; 81 82 struct assembly_version 83 { 84 USHORT major; 85 USHORT minor; 86 USHORT build; 87 USHORT revision; 88 }; 89 90 struct assembly_identity 91 { 92 WCHAR *name; 93 WCHAR *arch; 94 WCHAR *public_key; 95 WCHAR *language; 96 WCHAR *type; 97 struct assembly_version version; 98 BOOL optional; 99 BOOL delayed; 100 }; 101 102 struct strsection_header 103 { 104 DWORD magic; 105 ULONG size; 106 DWORD unk1[3]; 107 ULONG count; 108 ULONG index_offset; 109 DWORD unk2[2]; 110 ULONG global_offset; 111 ULONG global_len; 112 }; 113 114 struct string_index 115 { 116 ULONG hash; /* key string hash */ 117 ULONG name_offset; 118 ULONG name_len; 119 ULONG data_offset; /* redirect data offset */ 120 ULONG data_len; 121 ULONG rosterindex; 122 }; 123 124 struct guidsection_header 125 { 126 DWORD magic; 127 ULONG size; 128 DWORD unk[3]; 129 ULONG count; 130 ULONG index_offset; 131 DWORD unk2; 132 ULONG names_offset; 133 ULONG names_len; 134 }; 135 136 struct guid_index 137 { 138 GUID guid; 139 ULONG data_offset; 140 ULONG data_len; 141 ULONG rosterindex; 142 }; 143 144 struct wndclass_redirect_data 145 { 146 ULONG size; 147 DWORD res; 148 ULONG name_len; 149 ULONG name_offset; /* versioned name offset */ 150 ULONG module_len; 151 ULONG module_offset;/* container name offset */ 152 }; 153 154 struct dllredirect_data 155 { 156 ULONG size; 157 ULONG unk; 158 DWORD res[3]; 159 }; 160 161 struct tlibredirect_data 162 { 163 ULONG size; 164 DWORD res; 165 ULONG name_len; 166 ULONG name_offset; 167 LANGID langid; 168 WORD flags; 169 ULONG help_len; 170 ULONG help_offset; 171 WORD major_version; 172 WORD minor_version; 173 }; 174 175 enum comclass_threadingmodel 176 { 177 ThreadingModel_Apartment = 1, 178 ThreadingModel_Free = 2, 179 ThreadingModel_No = 3, 180 ThreadingModel_Both = 4, 181 ThreadingModel_Neutral = 5 182 }; 183 184 enum comclass_miscfields 185 { 186 MiscStatus = 1, 187 MiscStatusIcon = 2, 188 MiscStatusContent = 4, 189 MiscStatusThumbnail = 8, 190 MiscStatusDocPrint = 16 191 }; 192 193 struct comclassredirect_data 194 { 195 ULONG size; 196 BYTE res; 197 BYTE miscmask; 198 BYTE res1[2]; 199 DWORD model; 200 GUID clsid; 201 GUID alias; 202 GUID clsid2; 203 GUID tlbid; 204 ULONG name_len; 205 ULONG name_offset; 206 ULONG progid_len; 207 ULONG progid_offset; 208 ULONG clrdata_len; 209 ULONG clrdata_offset; 210 DWORD miscstatus; 211 DWORD miscstatuscontent; 212 DWORD miscstatusthumbnail; 213 DWORD miscstatusicon; 214 DWORD miscstatusdocprint; 215 }; 216 217 enum ifaceps_mask 218 { 219 NumMethods = 1, 220 BaseIface = 2 221 }; 222 223 struct ifacepsredirect_data 224 { 225 ULONG size; 226 DWORD mask; 227 GUID iid; 228 ULONG nummethods; 229 GUID tlbid; 230 GUID base; 231 ULONG name_len; 232 ULONG name_offset; 233 }; 234 235 struct clrsurrogate_data 236 { 237 ULONG size; 238 DWORD res; 239 GUID clsid; 240 ULONG version_offset; 241 ULONG version_len; 242 ULONG name_offset; 243 ULONG name_len; 244 }; 245 246 struct clrclass_data 247 { 248 ULONG size; 249 DWORD res[2]; 250 ULONG module_len; 251 ULONG module_offset; 252 ULONG name_len; 253 ULONG name_offset; 254 ULONG version_len; 255 ULONG version_offset; 256 DWORD res2[2]; 257 }; 258 259 struct progidredirect_data 260 { 261 ULONG size; 262 DWORD reserved; 263 ULONG clsid_offset; 264 }; 265 266 /* 267 268 Sections structure. 269 270 Sections are accessible by string or guid key, that defines two types of sections. 271 All sections of each type have same magic value and header structure, index 272 data could be of two possible types too. So every string based section uses 273 the same index format, same applies to guid sections - they share same guid index 274 format. 275 276 - window class redirection section is a plain buffer with following format: 277 278 <section header> 279 <index[]> 280 <data[]> --- <original name> 281 <redirect data> 282 <versioned name> 283 <module name> 284 285 Header is fixed length structure - struct strsection_header, 286 contains redirected classes count; 287 288 Index is an array of fixed length index records, each record is 289 struct string_index. 290 291 All strings in data itself are WCHAR, null terminated, 4-bytes aligned. 292 293 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data), 294 others are relative to section itself. 295 296 - dll redirect section format: 297 298 <section header> 299 <index[]> 300 <data[]> --- <dll name> 301 <data> 302 303 This section doesn't seem to carry any payload data except dll names. 304 305 - typelib section format: 306 307 <section header> 308 <module names[]> 309 <index[]> 310 <data[]> --- <data> 311 <helpstring> 312 313 Header is fixed length, index is an array of fixed length 'struct guid_index'. 314 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is 315 4-bytes aligned as a whole. 316 317 Module name offsets are relative to section, helpstring offset is relative to data 318 structure itself. 319 320 - comclass section format: 321 322 <section header> 323 <module names[]> 324 <index[]> 325 <data[]> --- <data> --- <data> 326 <progid> <clrdata> 327 <name> 328 <version> 329 <progid> 330 331 This section uses two index records per comclass, one entry contains original guid 332 as specified by context, another one has a generated guid. Index and strings handling 333 is similar to typelib sections. 334 335 For CLR classes additional data is stored after main COM class data, it contains 336 class name and runtime version string, see 'struct clrclass_data'. 337 338 Module name offsets are relative to section, progid offset is relative to data 339 structure itself. 340 341 - COM interface section format: 342 343 <section header> 344 <index[]> 345 <data[]> --- <data> 346 <name> 347 348 Interface section contains data for proxy/stubs and external proxy/stubs. External 349 ones are defined at assembly level, so this section has no module information. 350 All records are indexed with 'iid' value from manifest. There an exception for 351 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in 352 redirect data, but index is still 'iid' from manifest. 353 354 Interface name offset is relative to data structure itself. 355 356 - CLR surrogates section format: 357 358 <section header> 359 <index[]> 360 <data[]> --- <data> 361 <name> 362 <version> 363 364 There's nothing special about this section, same way to store strings is used, 365 no modules part as it belongs to assembly level, not a file. 366 367 - ProgID section format: 368 369 <section header> 370 <guids[]> 371 <index[]> 372 <data[]> --- <progid> 373 <data> 374 375 This sections uses generated alias guids from COM server section. This way 376 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string 377 is stored too, aligned. 378 */ 379 380 struct progids 381 { 382 WCHAR **progids; 383 unsigned int num; 384 unsigned int allocated; 385 }; 386 387 struct entity 388 { 389 DWORD kind; 390 union 391 { 392 struct 393 { 394 WCHAR *tlbid; 395 WCHAR *helpdir; 396 WORD flags; 397 WORD major; 398 WORD minor; 399 } typelib; 400 struct 401 { 402 WCHAR *clsid; 403 WCHAR *tlbid; 404 WCHAR *progid; 405 WCHAR *name; /* clrClass: class name */ 406 WCHAR *version; /* clrClass: CLR runtime version */ 407 DWORD model; 408 DWORD miscstatus; 409 DWORD miscstatuscontent; 410 DWORD miscstatusthumbnail; 411 DWORD miscstatusicon; 412 DWORD miscstatusdocprint; 413 struct progids progids; 414 } comclass; 415 struct { 416 WCHAR *iid; 417 WCHAR *base; 418 WCHAR *tlib; 419 WCHAR *name; 420 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */ 421 DWORD mask; 422 ULONG nummethods; 423 } ifaceps; 424 struct 425 { 426 WCHAR *name; 427 BOOL versioned; 428 } class; 429 struct 430 { 431 WCHAR *name; 432 WCHAR *clsid; 433 WCHAR *version; 434 } clrsurrogate; 435 struct 436 { 437 WCHAR *name; 438 WCHAR *value; 439 WCHAR *ns; 440 } settings; 441 } u; 442 }; 443 444 struct entity_array 445 { 446 struct entity *base; 447 unsigned int num; 448 unsigned int allocated; 449 }; 450 451 struct dll_redirect 452 { 453 WCHAR *name; 454 WCHAR *hash; 455 struct entity_array entities; 456 }; 457 458 enum assembly_type 459 { 460 APPLICATION_MANIFEST, 461 ASSEMBLY_MANIFEST, 462 ASSEMBLY_SHARED_MANIFEST, 463 }; 464 465 struct assembly 466 { 467 enum assembly_type type; 468 struct assembly_identity id; 469 struct file_info manifest; 470 WCHAR *directory; 471 BOOL no_inherit; 472 struct dll_redirect *dlls; 473 unsigned int num_dlls; 474 unsigned int allocated_dlls; 475 struct entity_array entities; 476 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts; 477 ULONG num_compat_contexts; 478 ACTCTX_REQUESTED_RUN_LEVEL run_level; 479 ULONG ui_access; 480 }; 481 482 enum context_sections 483 { 484 WINDOWCLASS_SECTION = 1, 485 DLLREDIRECT_SECTION = 2, 486 TLIBREDIRECT_SECTION = 4, 487 SERVERREDIRECT_SECTION = 8, 488 IFACEREDIRECT_SECTION = 16, 489 CLRSURROGATES_SECTION = 32, 490 PROGIDREDIRECT_SECTION = 64 491 }; 492 493 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY 494 { 495 ULONG Flags; 496 UNICODE_STRING DosPath; 497 HANDLE Handle; 498 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY; 499 500 typedef struct _ASSEMBLY_STORAGE_MAP 501 { 502 ULONG Flags; 503 ULONG AssemblyCount; 504 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray; 505 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP; 506 507 typedef struct _ACTIVATION_CONTEXT 508 { 509 LONG RefCount; 510 ULONG Flags; 511 LIST_ENTRY Links; 512 PACTIVATION_CONTEXT_DATA ActivationContextData; 513 PVOID NotificationRoutine; 514 PVOID NotificationContext; 515 ULONG SentNotifications[8]; 516 ULONG DisabledNotifications[8]; 517 ASSEMBLY_STORAGE_MAP StorageMap; 518 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries; 519 ULONG StackTraceIndex; 520 PVOID StackTraces[4][4]; 521 struct file_info config; 522 struct file_info appdir; 523 struct assembly *assemblies; 524 unsigned int num_assemblies; 525 unsigned int allocated_assemblies; 526 /* section data */ 527 DWORD sections; 528 struct strsection_header *wndclass_section; 529 struct strsection_header *dllredirect_section; 530 struct strsection_header *progid_section; 531 struct guidsection_header *tlib_section; 532 struct guidsection_header *comserver_section; 533 struct guidsection_header *ifaceps_section; 534 struct guidsection_header *clrsurrogate_section; 535 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT; 536 537 struct actctx_loader 538 { 539 ACTIVATION_CONTEXT *actctx; 540 struct assembly_identity *dependencies; 541 unsigned int num_dependencies; 542 unsigned int allocated_dependencies; 543 }; 544 545 static const xmlstr_t empty_xmlstr; 546 547 #ifdef __i386__ 548 static const WCHAR current_archW[] = {'x','8','6',0}; 549 #elif defined __x86_64__ 550 static const WCHAR current_archW[] = {'a','m','d','6','4',0}; 551 #elif defined __arm__ 552 static const WCHAR current_archW[] = {'a','r','m',0}; 553 #elif defined __aarch64__ 554 static const WCHAR current_archW[] = {'a','r','m','6','4',0}; 555 #else 556 static const WCHAR current_archW[] = {'n','o','n','e',0}; 557 #endif 558 559 static const WCHAR asmv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0}; 560 static const WCHAR asmv2W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','2',0}; 561 static const WCHAR asmv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0}; 562 563 typedef struct _ACTIVATION_CONTEXT_WRAPPED 564 { 565 PVOID MagicMarker; 566 ACTIVATION_CONTEXT ActivationContext; 567 } ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED; 568 569 VOID 570 NTAPI 571 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx, 572 IN ULONG FailureCode) 573 { 574 EXCEPTION_RECORD ExceptionRecord; 575 576 /* Fatal SxS exception header */ 577 ExceptionRecord.ExceptionRecord = NULL; 578 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION; 579 ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; 580 581 /* With SxS-specific information plus the context itself */ 582 ExceptionRecord.ExceptionInformation[0] = 1; 583 ExceptionRecord.ExceptionInformation[1] = FailureCode; 584 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx; 585 ExceptionRecord.NumberParameters = 3; 586 587 /* Raise it */ 588 RtlRaiseException(&ExceptionRecord); 589 } 590 591 FORCEINLINE 592 VOID 593 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx) 594 { 595 PACTIVATION_CONTEXT_WRAPPED pActual; 596 597 /* Get the caller-opaque header */ 598 pActual = CONTAINING_RECORD(ActCtx, 599 ACTIVATION_CONTEXT_WRAPPED, 600 ActivationContext); 601 602 /* Check if the header matches as expected */ 603 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER) 604 { 605 /* Nope, print out a warning, assert, and then throw an exception */ 606 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n" 607 " This means someone stepped on the allocation, or someone is using a\n" 608 " deallocated activation context\n", 609 __FUNCTION__, 610 pActual->MagicMarker, 611 ActCtx); 612 ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER); 613 RtlpSxsBreakOnInvalidMarker(ActCtx, 1); 614 } 615 } 616 617 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0}; 618 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0}; 619 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0}; 620 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0}; 621 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0}; 622 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0}; 623 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}; 624 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}; 625 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0}; 626 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0}; 627 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0}; 628 static const WCHAR fileW[] = {'f','i','l','e',0}; 629 static const WCHAR hashW[] = {'h','a','s','h',0}; 630 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0}; 631 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0}; 632 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0}; 633 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0}; 634 635 static const WCHAR clsidW[] = {'c','l','s','i','d',0}; 636 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0}; 637 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0}; 638 static const WCHAR iidW[] = {'i','i','d',0}; 639 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0}; 640 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0}; 641 static const WCHAR g_nameW[] = {'n','a','m','e',0}; 642 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0}; 643 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0}; 644 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0}; 645 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0}; 646 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}; 647 static const WCHAR progidW[] = {'p','r','o','g','i','d',0}; 648 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; 649 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; 650 static const WCHAR tlbidW[] = {'t','l','b','i','d',0}; 651 static const WCHAR typeW[] = {'t','y','p','e',0}; 652 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; 653 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0}; 654 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0}; 655 static const WCHAR yesW[] = {'y','e','s',0}; 656 static const WCHAR noW[] = {'n','o',0}; 657 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0}; 658 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0}; 659 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0}; 660 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0}; 661 static const WCHAR flagsW[] = {'f','l','a','g','s',0}; 662 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0}; 663 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0}; 664 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0}; 665 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0}; 666 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0}; 667 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0}; 668 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0}; 669 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; 670 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0}; 671 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0}; 672 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0}; 673 674 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0}; 675 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0}; 676 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0}; 677 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0}; 678 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0}; 679 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0}; 680 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0}; 681 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}; 682 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0}; 683 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0}; 684 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0}; 685 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0}; 686 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0}; 687 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0}; 688 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0}; 689 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0}; 690 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}; 691 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0}; 692 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0}; 693 static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; 694 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}; 695 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0}; 696 697 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0}; 698 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0}; 699 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0}; 700 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0}; 701 static const WCHAR IdW[] = {'I','d',0}; 702 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0}; 703 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0}; 704 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0}; 705 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0}; 706 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 707 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0}; 708 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0}; 709 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0}; 710 static const WCHAR windowsSettings2005NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 711 static const WCHAR windowsSettings2011NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 712 static const WCHAR windowsSettings2016NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 713 static const WCHAR windowsSettings2017NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 714 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0}; 715 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0}; 716 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0}; 717 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0}; 718 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0}; 719 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0}; 720 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0}; 721 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0}; 722 723 struct olemisc_entry 724 { 725 const WCHAR *name; 726 OLEMISC value; 727 }; 728 729 static const struct olemisc_entry olemisc_values[] = 730 { 731 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE }, 732 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON }, 733 { actslikelabelW, OLEMISC_ACTSLIKELABEL }, 734 { alignableW, OLEMISC_ALIGNABLE }, 735 { alwaysrunW, OLEMISC_ALWAYSRUN }, 736 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 }, 737 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE }, 738 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE }, 739 { imemodeW, OLEMISC_IMEMODE }, 740 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE }, 741 { insideoutW, OLEMISC_INSIDEOUT }, 742 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME }, 743 { islinkobjectW, OLEMISC_ISLINKOBJECT }, 744 { nouiactivateW, OLEMISC_NOUIACTIVATE }, 745 { onlyiconicW, OLEMISC_ONLYICONIC }, 746 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE }, 747 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT }, 748 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST }, 749 { simpleframeW, OLEMISC_SIMPLEFRAME }, 750 { staticW, OLEMISC_STATIC }, 751 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO }, 752 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE } 753 }; 754 755 static const WCHAR g_xmlW[] = {'?','x','m','l',0}; 756 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}; 757 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}; 758 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}; 759 760 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; 761 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 762 static const WCHAR wildcardW[] = {'*',0}; 763 764 static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } }; 765 static ACTIVATION_CONTEXT *process_actctx = &system_actctx.ActivationContext; 766 static ACTIVATION_CONTEXT *implicit_actctx = &system_actctx.ActivationContext; 767 768 static WCHAR *strdupW(const WCHAR* str) 769 { 770 WCHAR* ptr; 771 772 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR)))) 773 return NULL; 774 return strcpyW(ptr, str); 775 } 776 777 static WCHAR *xmlstrdupW(const xmlstr_t* str) 778 { 779 WCHAR *strW; 780 781 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR)))) 782 { 783 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) ); 784 strW[str->len] = 0; 785 } 786 return strW; 787 } 788 789 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str) 790 { 791 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 792 } 793 794 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str) 795 { 796 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 797 } 798 799 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str) 800 { 801 return (xmlstr->len && xmlstr->ptr[0] == '/' && 802 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]); 803 } 804 805 static inline BOOL xml_attr_cmp(const struct xml_attr* attr, const WCHAR *str) 806 { 807 return xmlstr_cmp(&attr->name, str); 808 } 809 810 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 ) 811 { 812 return (elem1->name.len == elem2->name.len && 813 elem1->ns.len == elem2->ns.len && 814 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) && 815 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len )); 816 } 817 818 static inline BOOL xml_elem_cmp(const struct xml_elem* elem, const WCHAR *str, const WCHAR *namespace) 819 { 820 if (!xmlstr_cmp( &elem->name, str )) return FALSE; 821 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE; 822 if (!wcscmp( namespace, asmv1W )) 823 { 824 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE; 825 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE; 826 } 827 else if (!wcscmp( namespace, asmv2W )) 828 { 829 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE; 830 } 831 return FALSE; 832 } 833 834 static inline BOOL isxmlspace( WCHAR ch ) 835 { 836 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t'); 837 } 838 839 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at) 840 { 841 struct assembly *assembly; 842 843 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx); 844 845 if (actctx->num_assemblies == actctx->allocated_assemblies) 846 { 847 void *ptr; 848 unsigned int new_count; 849 if (actctx->assemblies) 850 { 851 new_count = actctx->allocated_assemblies * 2; 852 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 853 actctx->assemblies, new_count * sizeof(*assembly) ); 854 } 855 else 856 { 857 new_count = 4; 858 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) ); 859 } 860 if (!ptr) return NULL; 861 actctx->assemblies = ptr; 862 actctx->allocated_assemblies = new_count; 863 } 864 865 assembly = &actctx->assemblies[actctx->num_assemblies++]; 866 assembly->type = at; 867 return assembly; 868 } 869 870 static struct dll_redirect* add_dll_redirect(struct assembly* assembly) 871 { 872 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls); 873 874 if (assembly->num_dlls == assembly->allocated_dlls) 875 { 876 void *ptr; 877 unsigned int new_count; 878 if (assembly->dlls) 879 { 880 new_count = assembly->allocated_dlls * 2; 881 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 882 assembly->dlls, new_count * sizeof(*assembly->dlls) ); 883 } 884 else 885 { 886 new_count = 4; 887 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) ); 888 } 889 if (!ptr) return NULL; 890 assembly->dlls = ptr; 891 assembly->allocated_dlls = new_count; 892 } 893 return &assembly->dlls[assembly->num_dlls++]; 894 } 895 896 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly) 897 { 898 void *ptr; 899 if (assembly->num_compat_contexts) 900 { 901 unsigned int new_count = assembly->num_compat_contexts + 1; 902 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 903 assembly->compat_contexts, 904 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); 905 } 906 else 907 { 908 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); 909 } 910 if (!ptr) return NULL; 911 assembly->compat_contexts = ptr; 912 return &assembly->compat_contexts[assembly->num_compat_contexts++]; 913 } 914 915 static void free_assembly_identity(struct assembly_identity *ai) 916 { 917 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name ); 918 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch ); 919 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key ); 920 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language ); 921 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type ); 922 } 923 924 static struct entity* add_entity(struct entity_array *array, DWORD kind) 925 { 926 struct entity* entity; 927 928 if (array->num == array->allocated) 929 { 930 void *ptr; 931 unsigned int new_count; 932 if (array->base) 933 { 934 new_count = array->allocated * 2; 935 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 936 array->base, new_count * sizeof(*array->base) ); 937 } 938 else 939 { 940 new_count = 4; 941 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) ); 942 } 943 if (!ptr) return NULL; 944 array->base = ptr; 945 array->allocated = new_count; 946 } 947 entity = &array->base[array->num++]; 948 entity->kind = kind; 949 return entity; 950 } 951 952 static void free_entity_array(struct entity_array *array) 953 { 954 unsigned int i, j; 955 for (i = 0; i < array->num; i++) 956 { 957 struct entity *entity = &array->base[i]; 958 switch (entity->kind) 959 { 960 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 961 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid); 962 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid); 963 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid); 964 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name); 965 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version); 966 for (j = 0; j < entity->u.comclass.progids.num; j++) 967 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]); 968 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids); 969 break; 970 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 971 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid); 972 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base); 973 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32); 974 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name); 975 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.tlib); 976 break; 977 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 978 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid); 979 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir); 980 break; 981 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 982 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name); 983 break; 984 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 985 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name); 986 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid); 987 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version); 988 break; 989 default: 990 DPRINT1("Unknown entity kind %u\n", entity->kind); 991 } 992 } 993 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base ); 994 } 995 996 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 ) 997 { 998 if (!str1) return !str2; 999 return str2 && !strcmpiW( str1, str2 ); 1000 } 1001 1002 static BOOL is_matching_identity( const struct assembly_identity *id1, 1003 const struct assembly_identity *id2 ) 1004 { 1005 if (!is_matching_string( id1->name, id2->name )) return FALSE; 1006 if (!is_matching_string( id1->arch, id2->arch )) return FALSE; 1007 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE; 1008 1009 if (id1->language && id2->language && strcmpiW( id1->language, id2->language )) 1010 { 1011 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language )) 1012 return FALSE; 1013 } 1014 if (id1->version.major != id2->version.major) return FALSE; 1015 if (id1->version.minor != id2->version.minor) return FALSE; 1016 if (id1->version.build > id2->version.build) return FALSE; 1017 if (id1->version.build == id2->version.build && 1018 id1->version.revision > id2->version.revision) return FALSE; 1019 return TRUE; 1020 } 1021 1022 static BOOL add_dependent_assembly_id(struct actctx_loader* acl, 1023 struct assembly_identity* ai) 1024 { 1025 unsigned int i; 1026 1027 /* check if we already have that assembly */ 1028 1029 for (i = 0; i < acl->actctx->num_assemblies; i++) 1030 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id )) 1031 { 1032 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n", 1033 ai->name, ai->arch, ai->version.major, ai->version.minor, 1034 ai->version.build, ai->version.revision ); 1035 return TRUE; 1036 } 1037 1038 for (i = 0; i < acl->num_dependencies; i++) 1039 if (is_matching_identity( ai, &acl->dependencies[i] )) 1040 { 1041 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n", 1042 ai->name, ai->arch, ai->version.major, ai->version.minor, 1043 ai->version.build, ai->version.revision ); 1044 return TRUE; 1045 } 1046 1047 if (acl->num_dependencies == acl->allocated_dependencies) 1048 { 1049 void *ptr; 1050 unsigned int new_count; 1051 if (acl->dependencies) 1052 { 1053 new_count = acl->allocated_dependencies * 2; 1054 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies, 1055 new_count * sizeof(acl->dependencies[0])); 1056 } 1057 else 1058 { 1059 new_count = 4; 1060 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0])); 1061 } 1062 if (!ptr) return FALSE; 1063 acl->dependencies = ptr; 1064 acl->allocated_dependencies = new_count; 1065 } 1066 acl->dependencies[acl->num_dependencies++] = *ai; 1067 1068 return TRUE; 1069 } 1070 1071 static void free_depend_manifests(struct actctx_loader* acl) 1072 { 1073 unsigned int i; 1074 for (i = 0; i < acl->num_dependencies; i++) 1075 free_assembly_identity(&acl->dependencies[i]); 1076 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies); 1077 } 1078 1079 static WCHAR *build_assembly_dir(struct assembly_identity* ai) 1080 { 1081 static const WCHAR undW[] = {'_',0}; 1082 static const WCHAR noneW[] = {'n','o','n','e',0}; 1083 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0}; 1084 1085 const WCHAR *arch = ai->arch ? ai->arch : noneW; 1086 const WCHAR *key = ai->public_key ? ai->public_key : noneW; 1087 const WCHAR *lang = ai->language ? ai->language : noneW; 1088 const WCHAR *name = ai->name ? ai->name : noneW; 1089 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 + 1090 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW); 1091 WCHAR *ret; 1092 1093 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL; 1094 1095 strcpyW( ret, arch ); 1096 strcatW( ret, undW ); 1097 strcatW( ret, name ); 1098 strcatW( ret, undW ); 1099 strcatW( ret, key ); 1100 strcatW( ret, undW ); 1101 sprintfW( ret + strlenW(ret), version_formatW, 1102 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 1103 strcatW( ret, undW ); 1104 strcatW( ret, lang ); 1105 strcatW( ret, undW ); 1106 strcatW( ret, mskeyW ); 1107 return ret; 1108 } 1109 1110 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str ) 1111 { 1112 WCHAR *p = buffer; 1113 1114 if (!str) return; 1115 strcatW( buffer, prefix ); 1116 p += strlenW(p); 1117 *p++ = '"'; 1118 strcpyW( p, str ); 1119 p += strlenW(p); 1120 *p++ = '"'; 1121 *p = 0; 1122 } 1123 1124 static WCHAR *build_assembly_id( const struct assembly_identity *ai ) 1125 { 1126 static const WCHAR archW[] = 1127 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0}; 1128 static const WCHAR public_keyW[] = 1129 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0}; 1130 static const WCHAR typeW2[] = 1131 {',','t','y','p','e','=',0}; 1132 static const WCHAR versionW2[] = 1133 {',','v','e','r','s','i','o','n','=',0}; 1134 1135 WCHAR version[64], *ret; 1136 SIZE_T size = 0; 1137 1138 sprintfW( version, version_formatW, 1139 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 1140 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR); 1141 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2; 1142 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2; 1143 if (ai->type) size += strlenW(typeW2) + strlenW(ai->type) + 2; 1144 size += strlenW(versionW2) + strlenW(version) + 2; 1145 1146 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) ))) 1147 return NULL; 1148 1149 if (ai->name) strcpyW( ret, ai->name ); 1150 else *ret = 0; 1151 append_string( ret, archW, ai->arch ); 1152 append_string( ret, public_keyW, ai->public_key ); 1153 append_string( ret, typeW2, ai->type ); 1154 append_string( ret, versionW2, version ); 1155 return ret; 1156 } 1157 1158 static ACTIVATION_CONTEXT *check_actctx( HANDLE h ) 1159 { 1160 ACTIVATION_CONTEXT *ret = NULL, *actctx = h; 1161 PACTIVATION_CONTEXT_WRAPPED pActual; 1162 1163 if (!h || h == INVALID_HANDLE_VALUE) return NULL; 1164 _SEH2_TRY 1165 { 1166 if (actctx) 1167 { 1168 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext); 1169 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext; 1170 } 1171 } 1172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1173 { 1174 DPRINT1("Invalid activation context handle!\n"); 1175 } 1176 _SEH2_END; 1177 return ret; 1178 } 1179 1180 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx ) 1181 { 1182 InterlockedExchangeAdd( &actctx->RefCount, 1 ); 1183 } 1184 1185 static void actctx_release( ACTIVATION_CONTEXT *actctx ) 1186 { 1187 PACTIVATION_CONTEXT_WRAPPED pActual; 1188 1189 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1) 1190 { 1191 unsigned int i, j; 1192 1193 for (i = 0; i < actctx->num_assemblies; i++) 1194 { 1195 struct assembly *assembly = &actctx->assemblies[i]; 1196 for (j = 0; j < assembly->num_dlls; j++) 1197 { 1198 struct dll_redirect *dll = &assembly->dlls[j]; 1199 free_entity_array( &dll->entities ); 1200 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name ); 1201 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash ); 1202 } 1203 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls ); 1204 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info ); 1205 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory ); 1206 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->compat_contexts ); 1207 free_entity_array( &assembly->entities ); 1208 free_assembly_identity(&assembly->id); 1209 } 1210 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info ); 1211 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info ); 1212 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies ); 1213 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section ); 1214 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section ); 1215 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section ); 1216 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section ); 1217 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section ); 1218 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section ); 1219 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->progid_section ); 1220 1221 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext); 1222 pActual->MagicMarker = 0; 1223 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual); 1224 } 1225 } 1226 1227 static BOOL set_error(xmlbuf_t* xmlbuf) 1228 { 1229 xmlbuf->error = TRUE; 1230 return FALSE; 1231 } 1232 1233 static BOOL is_xmlns_attr(const struct xml_attr *attr) 1234 { 1235 const int len = wcslen( xmlnsW ); 1236 if (attr->name.len < len) return FALSE; 1237 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE; 1238 return (attr->name.len == len || attr->name.ptr[len] == ':'); 1239 } 1240 1241 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr ) 1242 { 1243 const int len = wcslen( xmlnsW ); 1244 struct xml_attr *ns; 1245 1246 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1) 1247 { 1248 // FIXME( "too many namespaces in manifest\n" ); 1249 set_error( xmlbuf ); 1250 return; 1251 } 1252 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++]; 1253 ns->value = attr->value; 1254 if (attr->name.len > len) 1255 { 1256 ns->name.ptr = attr->name.ptr + len + 1; 1257 ns->name.len = attr->name.len - len - 1; 1258 } 1259 else ns->name = empty_xmlstr; 1260 } 1261 1262 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name ) 1263 { 1264 int i; 1265 1266 for (i = xmlbuf->ns_pos - 1; i >= 0; i--) 1267 { 1268 if (xmlbuf->namespaces[i].name.len == name->len && 1269 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len )) 1270 return xmlbuf->namespaces[i].value; 1271 } 1272 1273 return empty_xmlstr; 1274 } 1275 1276 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, struct xml_attr* attr, BOOL* end) 1277 { 1278 const WCHAR* ptr; 1279 WCHAR quote; 1280 1281 if (xmlbuf->error) return FALSE; 1282 1283 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) 1284 xmlbuf->ptr++; 1285 1286 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf ); 1287 1288 if (*xmlbuf->ptr == '/') 1289 { 1290 xmlbuf->ptr++; 1291 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>') 1292 return set_error( xmlbuf ); 1293 1294 xmlbuf->ptr++; 1295 *end = TRUE; 1296 return FALSE; 1297 } 1298 1299 if (*xmlbuf->ptr == '>') 1300 { 1301 xmlbuf->ptr++; 1302 return FALSE; 1303 } 1304 1305 ptr = xmlbuf->ptr; 1306 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++; 1307 1308 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1309 1310 attr->name.ptr = xmlbuf->ptr; 1311 attr->name.len = ptr-xmlbuf->ptr; 1312 xmlbuf->ptr = ptr; 1313 1314 /* skip spaces before '=' */ 1315 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++; 1316 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf ); 1317 1318 /* skip '=' itself */ 1319 ptr++; 1320 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1321 1322 /* skip spaces after '=' */ 1323 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++; 1324 1325 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf ); 1326 1327 quote = *ptr++; 1328 attr->value.ptr = ptr; 1329 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1330 1331 while (ptr < xmlbuf->end && *ptr != quote) ptr++; 1332 if (ptr == xmlbuf->end) 1333 { 1334 xmlbuf->ptr = xmlbuf->end; 1335 return set_error( xmlbuf ); 1336 } 1337 1338 attr->value.len = ptr - attr->value.ptr; 1339 xmlbuf->ptr = ptr + 1; 1340 if (xmlbuf->ptr != xmlbuf->end) return TRUE; 1341 1342 return set_error( xmlbuf ); 1343 } 1344 1345 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem ) 1346 { 1347 const WCHAR* ptr = xmlbuf->ptr; 1348 1349 elem->ns = empty_xmlstr; 1350 elem->name.ptr = ptr; 1351 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/') 1352 { 1353 if (*ptr == ':') 1354 { 1355 elem->ns.ptr = elem->name.ptr; 1356 elem->ns.len = ptr - elem->ns.ptr; 1357 elem->name.ptr = ptr + 1; 1358 } 1359 ptr++; 1360 } 1361 elem->name.len = ptr - elem->name.ptr; 1362 xmlbuf->ptr = ptr; 1363 } 1364 1365 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent ) 1366 { 1367 const WCHAR* ptr; 1368 struct xml_attr attr; 1369 xmlbuf_t attr_buf; 1370 BOOL end = FALSE; 1371 1372 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */ 1373 1374 if (xmlbuf->error) return FALSE; 1375 1376 for (;;) 1377 { 1378 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break; 1379 if (ptr == xmlbuf->end) 1380 { 1381 xmlbuf->ptr = xmlbuf->end; 1382 return set_error( xmlbuf ); 1383 } 1384 ptr++; 1385 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */ 1386 { 1387 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++) 1388 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break; 1389 1390 if (ptr + 3 > xmlbuf->end) 1391 { 1392 xmlbuf->ptr = xmlbuf->end; 1393 return set_error( xmlbuf ); 1394 } 1395 xmlbuf->ptr = ptr + 3; 1396 } 1397 else break; 1398 } 1399 1400 xmlbuf->ptr = ptr; 1401 /* check for element terminating the parent element */ 1402 if (ptr < xmlbuf->end && *ptr == '/') 1403 { 1404 xmlbuf->ptr++; 1405 read_xml_elem( xmlbuf, elem ); 1406 elem->ns = find_xmlns( xmlbuf, &elem->ns ); 1407 if (!xml_name_cmp( elem, parent )) 1408 { 1409 /*ERR( "wrong closing element %s for %s\n", 1410 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name ));*/ 1411 return set_error( xmlbuf ); 1412 } 1413 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++; 1414 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf ); 1415 return FALSE; 1416 } 1417 1418 read_xml_elem( xmlbuf, elem ); 1419 1420 /* parse namespace attributes */ 1421 attr_buf = *xmlbuf; 1422 while (next_xml_attr( &attr_buf, &attr, &end )) 1423 { 1424 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr ); 1425 } 1426 elem->ns = find_xmlns( xmlbuf, &elem->ns ); 1427 elem->ns_pos = xmlbuf->ns_pos; 1428 1429 if (xmlbuf->ptr != xmlbuf->end) return TRUE; 1430 1431 return set_error( xmlbuf ); 1432 } 1433 1434 static BOOL parse_xml_header(xmlbuf_t* xmlbuf) 1435 { 1436 /* FIXME: parse attributes */ 1437 const WCHAR *ptr; 1438 1439 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++) 1440 { 1441 if (ptr[0] == '?' && ptr[1] == '>') 1442 { 1443 xmlbuf->ptr = ptr + 2; 1444 return TRUE; 1445 } 1446 } 1447 return FALSE; 1448 } 1449 1450 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content) 1451 { 1452 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr); 1453 1454 if (!ptr) return FALSE; 1455 1456 content->ptr = xmlbuf->ptr; 1457 content->len = ptr - xmlbuf->ptr; 1458 xmlbuf->ptr = ptr; 1459 1460 return TRUE; 1461 } 1462 1463 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version) 1464 { 1465 unsigned int ver[4]; 1466 unsigned int pos; 1467 const WCHAR *curr; 1468 1469 /* major.minor.build.revision */ 1470 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0; 1471 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1472 { 1473 if (*curr >= '0' && *curr <= '9') 1474 { 1475 ver[pos] = ver[pos] * 10 + *curr - '0'; 1476 if (ver[pos] >= 0x10000) goto error; 1477 } 1478 else if (*curr == '.') 1479 { 1480 if (++pos >= 4) goto error; 1481 } 1482 else goto error; 1483 } 1484 version->major = ver[0]; 1485 version->minor = ver[1]; 1486 version->build = ver[2]; 1487 version->revision = ver[3]; 1488 return TRUE; 1489 1490 error: 1491 return FALSE; 1492 } 1493 1494 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end) 1495 { 1496 struct xml_attr attr; 1497 1498 while (next_xml_attr(xmlbuf, &attr, end)) 1499 { 1500 // TODO: report error 1501 // if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr)); 1502 } 1503 } 1504 1505 static void parse_expect_end_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent) 1506 { 1507 struct xml_elem elem; 1508 1509 if (next_xml_elem(xmlbuf, &elem, parent)) 1510 { 1511 // FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) ); 1512 set_error( xmlbuf ); 1513 } 1514 } 1515 1516 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent) 1517 { 1518 struct xml_elem elem; 1519 struct xml_attr attr; 1520 BOOL end = FALSE; 1521 1522 while (next_xml_attr(xmlbuf, &attr, &end)); 1523 if (end) return; 1524 1525 while (next_xml_elem(xmlbuf, &elem, parent)) 1526 parse_unknown_elem(xmlbuf, &elem); 1527 } 1528 1529 static void parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx, 1530 struct assembly_identity* ai, const struct xml_elem *parent) 1531 { 1532 struct xml_attr attr; 1533 BOOL end = FALSE; 1534 1535 while (next_xml_attr(xmlbuf, &attr, &end)) 1536 { 1537 if (xml_attr_cmp(&attr, g_nameW)) 1538 { 1539 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1540 } 1541 else if (xml_attr_cmp(&attr, typeW)) 1542 { 1543 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1544 } 1545 else if (xml_attr_cmp(&attr, versionW)) 1546 { 1547 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf ); 1548 } 1549 else if (xml_attr_cmp(&attr, processorArchitectureW)) 1550 { 1551 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1552 } 1553 else if (xml_attr_cmp(&attr, publicKeyTokenW)) 1554 { 1555 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1556 } 1557 else if (xml_attr_cmp(&attr, languageW)) 1558 { 1559 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1560 } 1561 } 1562 1563 if (!end) parse_expect_end_elem(xmlbuf, parent); 1564 } 1565 1566 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value) 1567 { 1568 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0}; 1569 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0}; 1570 static const WCHAR freeW[] = {'F','r','e','e',0}; 1571 static const WCHAR bothW[] = {'B','o','t','h',0}; 1572 1573 if (value->len == 0) return ThreadingModel_No; 1574 if (xmlstr_cmp(value, apartW)) 1575 return ThreadingModel_Apartment; 1576 else if (xmlstr_cmp(value, freeW)) 1577 return ThreadingModel_Free; 1578 else if (xmlstr_cmp(value, bothW)) 1579 return ThreadingModel_Both; 1580 else if (xmlstr_cmp(value, neutralW)) 1581 return ThreadingModel_Neutral; 1582 else 1583 return ThreadingModel_No; 1584 }; 1585 1586 static OLEMISC get_olemisc_value(const WCHAR *str, int len) 1587 { 1588 int min, max; 1589 1590 min = 0; 1591 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1; 1592 1593 while (min <= max) 1594 { 1595 int n, c; 1596 1597 n = (min+max)/2; 1598 1599 c = strncmpW(olemisc_values[n].name, str, len); 1600 if (!c && !olemisc_values[n].name[len]) 1601 return olemisc_values[n].value; 1602 1603 if (c >= 0) 1604 max = n-1; 1605 else 1606 min = n+1; 1607 } 1608 1609 DPRINT1("unknown flag %S\n", str); 1610 return 0; 1611 } 1612 1613 static DWORD parse_com_class_misc(const xmlstr_t *value) 1614 { 1615 const WCHAR *str = value->ptr, *start; 1616 DWORD flags = 0; 1617 int i = 0; 1618 1619 /* it's comma separated list of flags */ 1620 while (i < value->len) 1621 { 1622 start = str; 1623 while (*str != ',' && (i++ < value->len)) str++; 1624 1625 flags |= get_olemisc_value(start, str-start); 1626 1627 /* skip separator */ 1628 str++; 1629 i++; 1630 } 1631 1632 return flags; 1633 } 1634 1635 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity) 1636 { 1637 struct progids *progids = &entity->u.comclass.progids; 1638 1639 if (progids->allocated == 0) 1640 { 1641 progids->allocated = 4; 1642 if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE; 1643 } 1644 1645 if (progids->allocated == progids->num) 1646 { 1647 WCHAR **new_progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids, 1648 2 * progids->allocated * sizeof(WCHAR*)); 1649 if (!new_progids) return FALSE; 1650 progids->allocated *= 2; 1651 progids->progids = new_progids; 1652 } 1653 1654 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE; 1655 progids->num++; 1656 1657 return TRUE; 1658 } 1659 1660 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent) 1661 { 1662 xmlstr_t content; 1663 BOOL end = FALSE; 1664 1665 parse_expect_no_attr(xmlbuf, &end); 1666 if (end) set_error( xmlbuf ); 1667 if (!parse_text_content(xmlbuf, &content)) return; 1668 1669 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf ); 1670 parse_expect_end_elem(xmlbuf, parent); 1671 } 1672 1673 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl, 1674 const struct xml_elem *parent ) 1675 { 1676 struct xml_elem elem; 1677 struct xml_attr attr; 1678 BOOL end = FALSE; 1679 struct entity* entity; 1680 1681 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 1682 { 1683 set_error( xmlbuf ); 1684 return; 1685 } 1686 1687 while (next_xml_attr(xmlbuf, &attr, &end)) 1688 { 1689 if (xml_attr_cmp(&attr, clsidW)) 1690 { 1691 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1692 } 1693 else if (xml_attr_cmp(&attr, progidW)) 1694 { 1695 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1696 } 1697 else if (xml_attr_cmp(&attr, tlbidW)) 1698 { 1699 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1700 } 1701 else if (xml_attr_cmp(&attr, threadingmodelW)) 1702 { 1703 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value); 1704 } 1705 else if (xml_attr_cmp(&attr, miscstatusW)) 1706 { 1707 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value); 1708 } 1709 else if (xml_attr_cmp(&attr, miscstatuscontentW)) 1710 { 1711 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value); 1712 } 1713 else if (xml_attr_cmp(&attr, miscstatusthumbnailW)) 1714 { 1715 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value); 1716 } 1717 else if (xml_attr_cmp(&attr, miscstatusiconW)) 1718 { 1719 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value); 1720 } 1721 else if (xml_attr_cmp(&attr, miscstatusdocprintW)) 1722 { 1723 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value); 1724 } 1725 else if (xml_attr_cmp(&attr, descriptionW)) 1726 { 1727 /* not stored */ 1728 } 1729 } 1730 1731 acl->actctx->sections |= SERVERREDIRECT_SECTION; 1732 if (entity->u.comclass.progid) 1733 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 1734 1735 if (end) return; 1736 1737 while (next_xml_elem(xmlbuf, &elem, parent)) 1738 { 1739 if (xml_elem_cmp(&elem, progidW, asmv1W)) 1740 { 1741 parse_com_class_progid(xmlbuf, entity, &elem); 1742 } 1743 else 1744 { 1745 parse_unknown_elem(xmlbuf, &elem); 1746 } 1747 } 1748 1749 if (entity->u.comclass.progids.num) 1750 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 1751 } 1752 1753 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity) 1754 { 1755 const WCHAR *curr; 1756 ULONG num = 0; 1757 1758 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1759 { 1760 if (*curr >= '0' && *curr <= '9') 1761 num = num * 10 + *curr - '0'; 1762 else 1763 { 1764 // DPRINT1("wrong numeric value %wZ\n", &strU); 1765 return FALSE; 1766 } 1767 } 1768 entity->u.ifaceps.nummethods = num; 1769 1770 return TRUE; 1771 } 1772 1773 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities, 1774 struct actctx_loader *acl, WCHAR *clsid ) 1775 { 1776 struct entity *entity; 1777 WCHAR *str; 1778 1779 if (!clsid) return; 1780 1781 if (!(str = strdupW(clsid))) 1782 { 1783 set_error( xmlbuf ); 1784 return; 1785 } 1786 1787 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 1788 { 1789 RtlFreeHeap(RtlGetProcessHeap(), 0, str); 1790 set_error( xmlbuf ); 1791 return; 1792 } 1793 1794 entity->u.comclass.clsid = str; 1795 entity->u.comclass.model = ThreadingModel_Both; 1796 1797 acl->actctx->sections |= SERVERREDIRECT_SECTION; 1798 } 1799 1800 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 1801 struct actctx_loader *acl, const struct xml_elem *parent ) 1802 { 1803 WCHAR *psclsid = NULL; 1804 struct entity *entity; 1805 struct xml_attr attr; 1806 BOOL end = FALSE; 1807 1808 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION))) 1809 { 1810 set_error( xmlbuf ); 1811 return; 1812 } 1813 1814 while (next_xml_attr(xmlbuf, &attr, &end)) 1815 { 1816 if (xml_attr_cmp(&attr, iidW)) 1817 { 1818 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1819 } 1820 else if (xml_attr_cmp(&attr, g_nameW)) 1821 { 1822 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1823 } 1824 else if (xml_attr_cmp(&attr, baseInterfaceW)) 1825 { 1826 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1827 entity->u.ifaceps.mask |= BaseIface; 1828 } 1829 else if (xml_attr_cmp(&attr, nummethodsW)) 1830 { 1831 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf ); 1832 entity->u.ifaceps.mask |= NumMethods; 1833 } 1834 else if (xml_attr_cmp(&attr, tlbidW)) 1835 { 1836 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1837 } 1838 else if (xml_attr_cmp(&attr, proxyStubClsid32W)) 1839 { 1840 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1841 } 1842 /* not used */ 1843 else if (xml_attr_cmp(&attr, threadingmodelW)) 1844 { 1845 } 1846 } 1847 1848 acl->actctx->sections |= IFACEREDIRECT_SECTION; 1849 if (!end) parse_expect_end_elem(xmlbuf, parent); 1850 1851 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid); 1852 1853 RtlFreeHeap(RtlGetProcessHeap(), 0, psclsid); 1854 } 1855 1856 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity) 1857 { 1858 WORD *flags = &entity->u.typelib.flags; 1859 const WCHAR *str = value->ptr, *start; 1860 int i = 0; 1861 1862 *flags = 0; 1863 1864 /* it's comma separated list of flags */ 1865 while (i < value->len) 1866 { 1867 start = str; 1868 while (*str != ',' && (i++ < value->len)) str++; 1869 1870 if (!strncmpiW(start, restrictedW, str-start)) 1871 *flags |= LIBFLAG_FRESTRICTED; 1872 else if (!strncmpiW(start, controlW, str-start)) 1873 *flags |= LIBFLAG_FCONTROL; 1874 else if (!strncmpiW(start, hiddenW, str-start)) 1875 *flags |= LIBFLAG_FHIDDEN; 1876 else if (!strncmpiW(start, hasdiskimageW, str-start)) 1877 *flags |= LIBFLAG_FHASDISKIMAGE; 1878 else 1879 { 1880 // DPRINT1("unknown flags value %wZ\n", &valueU); 1881 return FALSE; 1882 } 1883 1884 /* skip separator */ 1885 str++; 1886 i++; 1887 } 1888 1889 return TRUE; 1890 } 1891 1892 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity) 1893 { 1894 unsigned int ver[2]; 1895 unsigned int pos; 1896 const WCHAR *curr; 1897 1898 /* major.minor */ 1899 ver[0] = ver[1] = pos = 0; 1900 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1901 { 1902 if (*curr >= '0' && *curr <= '9') 1903 { 1904 ver[pos] = ver[pos] * 10 + *curr - '0'; 1905 if (ver[pos] >= 0x10000) goto error; 1906 } 1907 else if (*curr == '.') 1908 { 1909 if (++pos >= 2) goto error; 1910 } 1911 else goto error; 1912 } 1913 entity->u.typelib.major = ver[0]; 1914 entity->u.typelib.minor = ver[1]; 1915 return TRUE; 1916 1917 error: 1918 return FALSE; 1919 } 1920 1921 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 1922 struct actctx_loader *acl, const struct xml_elem *parent ) 1923 { 1924 struct xml_attr attr; 1925 BOOL end = FALSE; 1926 struct entity* entity; 1927 1928 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION))) 1929 { 1930 set_error( xmlbuf ); 1931 return; 1932 } 1933 1934 while (next_xml_attr(xmlbuf, &attr, &end)) 1935 { 1936 if (xml_attr_cmp(&attr, tlbidW)) 1937 { 1938 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1939 } 1940 else if (xml_attr_cmp(&attr, versionW)) 1941 { 1942 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf ); 1943 } 1944 else if (xml_attr_cmp(&attr, helpdirW)) 1945 { 1946 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1947 } 1948 else if (xml_attr_cmp(&attr, flagsW)) 1949 { 1950 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf ); 1951 } 1952 } 1953 1954 acl->actctx->sections |= TLIBREDIRECT_SECTION; 1955 if (!end) parse_expect_end_elem(xmlbuf, parent); 1956 } 1957 1958 static inline int aligned_string_len(int len) 1959 { 1960 return (len + 3) & ~3; 1961 } 1962 1963 static int get_assembly_version(struct assembly *assembly, WCHAR *ret) 1964 { 1965 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 1966 struct assembly_version *ver = &assembly->id.version; 1967 WCHAR buff[25]; 1968 1969 if (!ret) ret = buff; 1970 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision); 1971 } 1972 1973 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 1974 struct actctx_loader *acl, const struct xml_elem *parent ) 1975 { 1976 struct xml_elem elem; 1977 struct xml_attr attr; 1978 xmlstr_t content; 1979 BOOL end = FALSE; 1980 struct entity* entity; 1981 1982 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION))) 1983 { 1984 set_error( xmlbuf ); 1985 return; 1986 } 1987 entity->u.class.versioned = TRUE; 1988 while (next_xml_attr(xmlbuf, &attr, &end)) 1989 { 1990 if (xml_attr_cmp(&attr, versionedW)) 1991 { 1992 if (xmlstr_cmpi(&attr.value, noW)) 1993 entity->u.class.versioned = FALSE; 1994 else if (!xmlstr_cmpi(&attr.value, yesW)) 1995 set_error( xmlbuf ); 1996 } 1997 } 1998 1999 if (end) return; 2000 2001 if (!parse_text_content(xmlbuf, &content)) return; 2002 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf ); 2003 2004 acl->actctx->sections |= WINDOWCLASS_SECTION; 2005 2006 while (next_xml_elem(xmlbuf, &elem, parent)) 2007 { 2008 parse_unknown_elem(xmlbuf, &elem); 2009 } 2010 } 2011 2012 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2013 { 2014 struct xml_attr attr; 2015 BOOL end = FALSE; 2016 2017 while (next_xml_attr(xmlbuf, &attr, &end)) 2018 { 2019 if (xml_attr_cmp(&attr, oldVersionW)) 2020 { 2021 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr)); 2022 } 2023 else if (xml_attr_cmp(&attr, newVersionW)) 2024 { 2025 // FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr)); 2026 } 2027 } 2028 2029 if (!end) parse_expect_end_elem(xmlbuf, parent); 2030 } 2031 2032 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2033 { 2034 struct xml_elem elem; 2035 struct xml_attr attr; 2036 xmlstr_t content; 2037 BOOL end = FALSE; 2038 2039 while (next_xml_attr(xmlbuf, &attr, &end)); 2040 2041 if (end) return; 2042 if (!parse_text_content(xmlbuf, &content)) return; 2043 2044 while (next_xml_elem(xmlbuf, &elem, parent)) 2045 { 2046 parse_unknown_elem(xmlbuf, &elem); 2047 } 2048 } 2049 2050 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf, 2051 struct assembly* assembly, 2052 struct actctx_loader* acl, 2053 const struct xml_elem *parent) 2054 { 2055 struct xml_attr attr; 2056 BOOL end = FALSE; 2057 struct entity* entity; 2058 2059 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION))) 2060 { 2061 set_error( xmlbuf ); 2062 return; 2063 } 2064 2065 while (next_xml_attr(xmlbuf, &attr, &end)) 2066 { 2067 if (xml_attr_cmp(&attr, iidW)) 2068 { 2069 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2070 } 2071 else if (xml_attr_cmp(&attr, g_nameW)) 2072 { 2073 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2074 } 2075 else if (xml_attr_cmp(&attr, baseInterfaceW)) 2076 { 2077 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2078 entity->u.ifaceps.mask |= BaseIface; 2079 } 2080 else if (xml_attr_cmp(&attr, nummethodsW)) 2081 { 2082 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf ); 2083 entity->u.ifaceps.mask |= NumMethods; 2084 } 2085 else if (xml_attr_cmp(&attr, proxyStubClsid32W)) 2086 { 2087 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2088 } 2089 else if (xml_attr_cmp(&attr, tlbidW)) 2090 { 2091 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2092 } 2093 } 2094 2095 acl->actctx->sections |= IFACEREDIRECT_SECTION; 2096 if (!end) parse_expect_end_elem(xmlbuf, parent); 2097 } 2098 2099 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly, 2100 struct actctx_loader *acl, const struct xml_elem *parent ) 2101 2102 { 2103 struct xml_elem elem; 2104 struct xml_attr attr; 2105 BOOL end = FALSE; 2106 struct entity* entity; 2107 2108 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 2109 { 2110 set_error( xmlbuf ); 2111 return; 2112 } 2113 2114 while (next_xml_attr(xmlbuf, &attr, &end)) 2115 { 2116 if (xml_attr_cmp(&attr, g_nameW)) 2117 { 2118 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2119 } 2120 else if (xml_attr_cmp(&attr, clsidW)) 2121 { 2122 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2123 } 2124 else if (xml_attr_cmp(&attr, progidW)) 2125 { 2126 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2127 } 2128 else if (xml_attr_cmp(&attr, tlbidW)) 2129 { 2130 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2131 } 2132 else if (xml_attr_cmp(&attr, threadingmodelW)) 2133 { 2134 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value); 2135 } 2136 else if (xml_attr_cmp(&attr, runtimeVersionW)) 2137 { 2138 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2139 } 2140 } 2141 2142 acl->actctx->sections |= SERVERREDIRECT_SECTION; 2143 if (entity->u.comclass.progid) 2144 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 2145 if (end) return; 2146 2147 while (next_xml_elem(xmlbuf, &elem, parent)) 2148 { 2149 if (xml_elem_cmp(&elem, progidW, asmv1W)) 2150 { 2151 parse_com_class_progid(xmlbuf, entity, &elem); 2152 } 2153 else 2154 { 2155 parse_unknown_elem(xmlbuf, &elem); 2156 } 2157 } 2158 2159 if (entity->u.comclass.progids.num) 2160 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 2161 } 2162 2163 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2164 struct actctx_loader *acl, const struct xml_elem *parent ) 2165 { 2166 struct xml_attr attr; 2167 BOOL end = FALSE; 2168 struct entity* entity; 2169 2170 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES))) 2171 { 2172 set_error( xmlbuf ); 2173 return; 2174 } 2175 2176 while (next_xml_attr(xmlbuf, &attr, &end)) 2177 { 2178 if (xml_attr_cmp(&attr, g_nameW)) 2179 { 2180 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2181 } 2182 else if (xml_attr_cmp(&attr, clsidW)) 2183 { 2184 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2185 } 2186 else if (xml_attr_cmp(&attr, runtimeVersionW)) 2187 { 2188 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2189 } 2190 } 2191 2192 acl->actctx->sections |= CLRSURROGATES_SECTION; 2193 if (!end) parse_expect_end_elem(xmlbuf, parent); 2194 } 2195 2196 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl, 2197 const struct xml_elem *parent, BOOL optional ) 2198 { 2199 struct xml_elem elem; 2200 struct xml_attr attr; 2201 struct assembly_identity ai; 2202 BOOL end = FALSE; 2203 2204 memset(&ai, 0, sizeof(ai)); 2205 ai.optional = optional; 2206 2207 while (next_xml_attr(xmlbuf, &attr, &end)) 2208 { 2209 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0}; 2210 static const WCHAR trueW[] = {'t','r','u','e',0}; 2211 2212 if (xml_attr_cmp(&attr, allowDelayedBindingW)) 2213 ai.delayed = xmlstr_cmp(&attr.value, trueW); 2214 } 2215 2216 if (end) return; 2217 2218 while (next_xml_elem(xmlbuf, &elem, parent)) 2219 { 2220 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) 2221 { 2222 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem); 2223 /* store the newly found identity for later loading */ 2224 if (ai.arch && !wcscmp(ai.arch, wildcardW)) ai.arch = strdupW( current_archW ); 2225 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf ); 2226 } 2227 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W)) 2228 { 2229 parse_binding_redirect_elem(xmlbuf, &elem); 2230 } 2231 else 2232 { 2233 parse_unknown_elem(xmlbuf, &elem); 2234 } 2235 } 2236 } 2237 2238 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl, 2239 const struct xml_elem *parent ) 2240 2241 { 2242 struct xml_elem elem; 2243 struct xml_attr attr; 2244 BOOL end = FALSE, optional = FALSE; 2245 2246 while (next_xml_attr(xmlbuf, &attr, &end)) 2247 { 2248 if (xml_attr_cmp(&attr, optionalW)) 2249 { 2250 optional = xmlstr_cmpi( &attr.value, yesW ); 2251 } 2252 } 2253 2254 while (next_xml_elem(xmlbuf, &elem, parent)) 2255 { 2256 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W)) 2257 { 2258 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional); 2259 } 2260 else 2261 { 2262 parse_unknown_elem(xmlbuf, &elem); 2263 } 2264 } 2265 } 2266 2267 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2268 { 2269 BOOL end = FALSE; 2270 2271 parse_expect_no_attr(xmlbuf, &end); 2272 if (!end) parse_expect_end_elem(xmlbuf, parent); 2273 } 2274 2275 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2276 { 2277 BOOL end = FALSE; 2278 2279 parse_expect_no_attr(xmlbuf, &end); 2280 if (!end) parse_expect_end_elem(xmlbuf, parent); 2281 } 2282 2283 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly, 2284 struct actctx_loader* acl, const struct xml_elem *parent ) 2285 { 2286 struct xml_elem elem; 2287 struct xml_attr attr; 2288 BOOL end = FALSE; 2289 struct dll_redirect* dll; 2290 2291 if (!(dll = add_dll_redirect(assembly))) 2292 { 2293 set_error( xmlbuf ); 2294 return; 2295 } 2296 2297 while (next_xml_attr(xmlbuf, &attr, &end)) 2298 { 2299 if (xml_attr_cmp(&attr, g_nameW)) 2300 { 2301 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2302 } 2303 else if (xml_attr_cmp(&attr, hashW)) 2304 { 2305 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2306 } 2307 else if (xml_attr_cmp(&attr, hashalgW)) 2308 { 2309 static const WCHAR sha1W[] = {'S','H','A','1',0}; 2310 if (!xmlstr_cmpi(&attr.value, sha1W)) { 2311 //FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value)); 2312 } 2313 } 2314 } 2315 2316 if (!dll->name) set_error( xmlbuf ); 2317 2318 acl->actctx->sections |= DLLREDIRECT_SECTION; 2319 2320 if (end) return; 2321 2322 while (next_xml_elem(xmlbuf, &elem, parent)) 2323 { 2324 if (xml_elem_cmp(&elem, comClassW, asmv1W)) 2325 { 2326 parse_com_class_elem(xmlbuf, dll, acl, &elem); 2327 } 2328 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W)) 2329 { 2330 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem); 2331 } 2332 else if (xml_elem_cmp(&elem, hashW, asmv2W)) 2333 { 2334 parse_unknown_elem(xmlbuf, &elem); 2335 } 2336 else if (xml_elem_cmp(&elem, typelibW, asmv1W)) 2337 { 2338 parse_typelib_elem(xmlbuf, dll, acl, &elem); 2339 } 2340 else if (xml_elem_cmp(&elem, windowClassW, asmv1W)) 2341 { 2342 parse_window_class_elem(xmlbuf, dll, acl, &elem); 2343 } 2344 else 2345 { 2346 parse_unknown_elem( xmlbuf, &elem ); 2347 } 2348 } 2349 } 2350 2351 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2352 struct actctx_loader *acl, const struct xml_elem *parent ) 2353 { 2354 struct xml_attr attr; 2355 BOOL end = FALSE; 2356 2357 while (next_xml_attr(xmlbuf, &attr, &end)) 2358 { 2359 if (xml_attr_cmp(&attr, IdW)) 2360 { 2361 COMPATIBILITY_CONTEXT_ELEMENT *compat; 2362 UNICODE_STRING str; 2363 GUID compat_id; 2364 2365 str.Buffer = (PWSTR)attr.value.ptr; 2366 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR); 2367 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS) 2368 { 2369 if (!(compat = add_compat_context(assembly))) 2370 { 2371 set_error( xmlbuf ); 2372 return; 2373 } 2374 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS; 2375 compat->Id = compat_id; 2376 } 2377 } 2378 } 2379 2380 if (!end) parse_expect_end_elem(xmlbuf, parent); 2381 } 2382 2383 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, 2384 struct actctx_loader* acl, const struct xml_elem *parent) 2385 { 2386 struct xml_elem elem; 2387 2388 while (next_xml_elem(xmlbuf, &elem, parent)) 2389 { 2390 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW)) 2391 { 2392 parse_supportedos_elem(xmlbuf, assembly, acl, &elem); 2393 } 2394 else 2395 { 2396 parse_unknown_elem(xmlbuf, &elem); 2397 } 2398 } 2399 } 2400 2401 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, 2402 struct actctx_loader* acl, const struct xml_elem *parent) 2403 { 2404 struct xml_elem elem; 2405 2406 while (next_xml_elem(xmlbuf, &elem, parent)) 2407 { 2408 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW)) 2409 { 2410 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem); 2411 } 2412 else 2413 { 2414 parse_unknown_elem(xmlbuf, &elem); 2415 } 2416 } 2417 } 2418 2419 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl, 2420 struct xml_elem *parent ) 2421 { 2422 struct xml_elem elem; 2423 struct xml_attr attr; 2424 xmlstr_t content; 2425 BOOL end = FALSE; 2426 struct entity *entity; 2427 2428 while (next_xml_attr( xmlbuf, &attr, &end )) 2429 { 2430 } 2431 2432 if (end) return; 2433 2434 if (!parse_text_content( xmlbuf, &content )) return; 2435 2436 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS ); 2437 if (!entity) 2438 { 2439 set_error( xmlbuf ); 2440 return; 2441 } 2442 entity->u.settings.name = xmlstrdupW( &parent->name ); 2443 entity->u.settings.value = xmlstrdupW( &content ); 2444 entity->u.settings.ns = xmlstrdupW( &parent->ns ); 2445 2446 while (next_xml_elem(xmlbuf, &elem, parent)) 2447 { 2448 parse_unknown_elem( xmlbuf, &elem ); 2449 } 2450 } 2451 2452 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2453 struct actctx_loader *acl, const struct xml_elem *parent ) 2454 { 2455 struct xml_elem elem; 2456 2457 while (next_xml_elem( xmlbuf, &elem, parent )) 2458 { 2459 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) || 2460 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) || 2461 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) || 2462 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) || 2463 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) || 2464 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) || 2465 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) || 2466 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) || 2467 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) || 2468 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) || 2469 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW )) 2470 { 2471 parse_settings_elem( xmlbuf, assembly, acl, &elem ); 2472 } 2473 else 2474 { 2475 parse_unknown_elem( xmlbuf, &elem ); 2476 } 2477 } 2478 } 2479 2480 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2481 struct actctx_loader *acl, const struct xml_elem *parent ) 2482 { 2483 struct xml_elem elem; 2484 2485 while (next_xml_elem( xmlbuf, &elem, parent )) 2486 { 2487 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W )) 2488 { 2489 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem ); 2490 } 2491 else 2492 { 2493 parse_unknown_elem( xmlbuf, &elem ); 2494 } 2495 } 2496 } 2497 2498 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2499 struct actctx_loader *acl, const struct xml_elem *parent ) 2500 { 2501 static const WCHAR levelW[] = {'l','e','v','e','l',0}; 2502 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0}; 2503 static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0}; 2504 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0}; 2505 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0}; 2506 static const WCHAR falseW[] = {'f','a','l','s','e',0}; 2507 static const WCHAR trueW[] = {'t','r','u','e',0}; 2508 2509 struct xml_elem elem; 2510 struct xml_attr attr; 2511 BOOL end = FALSE; 2512 2513 /* Multiple requestedExecutionLevel elements are not supported. */ 2514 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf ); 2515 2516 while (next_xml_attr(xmlbuf, &attr, &end)) 2517 { 2518 if (xml_attr_cmp(&attr, levelW)) 2519 { 2520 if (xmlstr_cmpi(&attr.value, asInvokerW)) 2521 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER; 2522 else if (xmlstr_cmpi(&attr.value, highestAvailableW)) 2523 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE; 2524 else if (xmlstr_cmpi(&attr.value, requireAdministratorW)) 2525 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN; 2526 } 2527 else if (xml_attr_cmp(&attr, uiAccessW)) 2528 { 2529 if (xmlstr_cmpi(&attr.value, falseW)) 2530 assembly->ui_access = FALSE; 2531 else if (xmlstr_cmpi(&attr.value, trueW)) 2532 assembly->ui_access = TRUE; 2533 } 2534 } 2535 2536 if (end) return; 2537 2538 while (next_xml_elem(xmlbuf, &elem, parent)) 2539 { 2540 parse_unknown_elem(xmlbuf, &elem); 2541 } 2542 } 2543 2544 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2545 struct actctx_loader *acl, const struct xml_elem *parent ) 2546 { 2547 struct xml_elem elem; 2548 2549 while (next_xml_elem(xmlbuf, &elem, parent)) 2550 { 2551 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W)) 2552 { 2553 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem); 2554 } 2555 else 2556 { 2557 parse_unknown_elem(xmlbuf, &elem); 2558 } 2559 } 2560 } 2561 2562 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2563 struct actctx_loader *acl, const struct xml_elem *parent ) 2564 { 2565 struct xml_elem elem; 2566 2567 while (next_xml_elem(xmlbuf, &elem, parent)) 2568 { 2569 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W)) 2570 { 2571 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem); 2572 } 2573 else 2574 { 2575 parse_unknown_elem(xmlbuf, &elem); 2576 } 2577 } 2578 } 2579 2580 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2581 struct actctx_loader *acl, const struct xml_elem *parent ) 2582 { 2583 struct xml_elem elem; 2584 2585 while (next_xml_elem(xmlbuf, &elem, parent)) 2586 { 2587 if (xml_elem_cmp(&elem, securityW, asmv1W)) 2588 { 2589 parse_security_elem(xmlbuf, assembly, acl, &elem); 2590 } 2591 else 2592 { 2593 parse_unknown_elem(xmlbuf, &elem); 2594 } 2595 } 2596 } 2597 2598 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly, 2599 struct actctx_loader* acl, const struct xml_elem *parent, 2600 struct assembly_identity* expected_ai) 2601 { 2602 struct xml_elem elem; 2603 struct xml_attr attr; 2604 BOOL end = FALSE, version = FALSE; 2605 2606 while (next_xml_attr(xmlbuf, &attr, &end)) 2607 { 2608 if (xml_attr_cmp(&attr, manifestVersionW)) 2609 { 2610 static const WCHAR v10W[] = {'1','.','0',0}; 2611 if (!xmlstr_cmp(&attr.value, v10W)) 2612 { 2613 break; 2614 } 2615 version = TRUE; 2616 } 2617 } 2618 2619 if (end || !version) 2620 { 2621 set_error( xmlbuf ); 2622 return; 2623 } 2624 2625 while (next_xml_elem(xmlbuf, &elem, parent)) 2626 { 2627 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W)) 2628 { 2629 parse_noinherit_elem(xmlbuf, &elem); 2630 assembly->no_inherit = TRUE; 2631 } 2632 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W)) 2633 { 2634 parse_noinheritable_elem(xmlbuf, &elem); 2635 } 2636 else if (xml_elem_cmp(&elem, descriptionW, asmv1W)) 2637 { 2638 parse_description_elem(xmlbuf, &elem); 2639 } 2640 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W)) 2641 { 2642 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem); 2643 } 2644 else if (xml_elem_cmp(&elem, dependencyW, asmv1W)) 2645 { 2646 parse_dependency_elem(xmlbuf, acl, &elem); 2647 } 2648 else if (xml_elem_cmp(&elem, fileW, asmv1W)) 2649 { 2650 parse_file_elem(xmlbuf, assembly, acl, &elem); 2651 } 2652 else if (xml_elem_cmp(&elem, clrClassW, asmv1W)) 2653 { 2654 parse_clr_class_elem(xmlbuf, assembly, acl, &elem); 2655 } 2656 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W)) 2657 { 2658 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem); 2659 } 2660 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W)) 2661 { 2662 parse_trust_info_elem(xmlbuf, assembly, acl, &elem); 2663 } 2664 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) 2665 { 2666 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem); 2667 2668 if (!xmlbuf->error && expected_ai) 2669 { 2670 /* FIXME: more tests */ 2671 if (assembly->type == ASSEMBLY_MANIFEST && 2672 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version))) 2673 { 2674 set_error( xmlbuf ); 2675 } 2676 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST && 2677 (assembly->id.version.major != expected_ai->version.major || 2678 assembly->id.version.minor != expected_ai->version.minor || 2679 assembly->id.version.build < expected_ai->version.build || 2680 (assembly->id.version.build == expected_ai->version.build && 2681 assembly->id.version.revision < expected_ai->version.revision))) 2682 { 2683 set_error( xmlbuf ); 2684 } 2685 } 2686 } 2687 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW)) 2688 { 2689 parse_compatibility_elem(xmlbuf, assembly, acl, &elem); 2690 } 2691 else if (xml_elem_cmp(&elem, applicationW, asmv3W)) 2692 { 2693 parse_application_elem(xmlbuf, assembly, acl, &elem); 2694 } 2695 else 2696 { 2697 parse_unknown_elem(xmlbuf, &elem); 2698 } 2699 } 2700 2701 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) && 2702 assembly->no_inherit) 2703 { 2704 set_error( xmlbuf ); 2705 } 2706 } 2707 2708 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly, 2709 struct assembly_identity* ai, xmlbuf_t *xmlbuf ) 2710 { 2711 struct xml_elem elem; 2712 struct xml_elem parent = {0}; 2713 2714 xmlbuf->error = FALSE; 2715 xmlbuf->ns_pos = 0; 2716 2717 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX; 2718 2719 if (xmlstr_cmp(&elem.name, g_xmlW) && 2720 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent))) 2721 return STATUS_SXS_CANT_GEN_ACTCTX; 2722 2723 if (!xml_elem_cmp(&elem, assemblyW, asmv1W)) 2724 { 2725 return STATUS_SXS_CANT_GEN_ACTCTX; 2726 } 2727 2728 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai); 2729 if (xmlbuf->error) 2730 { 2731 return STATUS_SXS_CANT_GEN_ACTCTX; 2732 } 2733 2734 if (next_xml_elem(xmlbuf, &elem, &parent)) 2735 { 2736 return STATUS_SXS_CANT_GEN_ACTCTX; 2737 } 2738 2739 if (xmlbuf->ptr != xmlbuf->end) 2740 { 2741 return STATUS_SXS_CANT_GEN_ACTCTX; 2742 } 2743 return STATUS_SUCCESS; 2744 } 2745 2746 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 2747 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2748 const void *buffer, SIZE_T size ) 2749 { 2750 xmlbuf_t xmlbuf; 2751 NTSTATUS status; 2752 struct assembly *assembly; 2753 int unicode_tests; 2754 2755 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory ); 2756 2757 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST))) 2758 return STATUS_SXS_CANT_GEN_ACTCTX; 2759 2760 if (directory && !(assembly->directory = strdupW(directory))) 2761 return STATUS_NO_MEMORY; 2762 2763 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ); 2764 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE 2765 : ACTIVATION_CONTEXT_PATH_TYPE_NONE; 2766 2767 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE; 2768 if (RtlIsTextUnicode(buffer, size, &unicode_tests )) 2769 { 2770 xmlbuf.ptr = buffer; 2771 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 2772 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 2773 } 2774 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE) 2775 { 2776 const WCHAR *buf = buffer; 2777 WCHAR *new_buff; 2778 unsigned int i; 2779 2780 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) 2781 return STATUS_NO_MEMORY; 2782 for (i = 0; i < size / sizeof(WCHAR); i++) 2783 new_buff[i] = RtlUshortByteSwap( buf[i] ); 2784 xmlbuf.ptr = new_buff; 2785 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 2786 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 2787 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff ); 2788 } 2789 else 2790 { 2791 /* TODO: this doesn't handle arbitrary encodings */ 2792 WCHAR *new_buff; 2793 ULONG sizeU; 2794 2795 status = RtlMultiByteToUnicodeSize(&sizeU, buffer, size); 2796 if (!NT_SUCCESS(status)) 2797 { 2798 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status); 2799 return STATUS_SXS_CANT_GEN_ACTCTX; 2800 } 2801 2802 new_buff = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeU); 2803 if (!new_buff) 2804 return STATUS_NO_MEMORY; 2805 2806 status = RtlMultiByteToUnicodeN(new_buff, sizeU, &sizeU, buffer, size); 2807 if (!NT_SUCCESS(status)) 2808 { 2809 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status); 2810 return STATUS_SXS_CANT_GEN_ACTCTX; 2811 } 2812 2813 xmlbuf.ptr = new_buff; 2814 xmlbuf.end = xmlbuf.ptr + sizeU / sizeof(WCHAR); 2815 status = parse_manifest_buffer(acl, assembly, ai, &xmlbuf); 2816 RtlFreeHeap(RtlGetProcessHeap(), 0, new_buff); 2817 } 2818 return status; 2819 } 2820 2821 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name ) 2822 { 2823 OBJECT_ATTRIBUTES attr; 2824 IO_STATUS_BLOCK io; 2825 2826 attr.Length = sizeof(attr); 2827 attr.RootDirectory = 0; 2828 attr.Attributes = OBJ_CASE_INSENSITIVE; 2829 attr.ObjectName = name; 2830 attr.SecurityDescriptor = NULL; 2831 attr.SecurityQualityOfService = NULL; 2832 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT ); 2833 } 2834 2835 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len ) 2836 { 2837 NTSTATUS status; 2838 ULONG_PTR magic; 2839 LDR_DATA_TABLE_ENTRY *pldr; 2840 2841 LdrLockLoaderLock(0, NULL, &magic); 2842 status = LdrFindEntryForAddress( module, &pldr ); 2843 if (status == STATUS_SUCCESS) 2844 { 2845 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 2846 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) ))) 2847 { 2848 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) ); 2849 str->Length = pldr->FullDllName.Length; 2850 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR); 2851 } 2852 else status = STATUS_NO_MEMORY; 2853 } 2854 LdrUnlockLoaderLock(0, magic); 2855 return status; 2856 } 2857 2858 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 2859 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2860 HANDLE hModule, LPCWSTR resname, ULONG lang ) 2861 { 2862 NTSTATUS status; 2863 UNICODE_STRING nameW; 2864 LDR_RESOURCE_INFO info; 2865 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL; 2866 void *ptr; 2867 2868 //DPRINT( "looking for res %s in module %p %s\n", resname, 2869 // hModule, filename ); 2870 DPRINT("get_manifest_in_module %p\n", hModule); 2871 2872 #if 0 2873 if (TRACE_ON(actctx)) 2874 { 2875 if (!filename && !get_module_filename( hModule, &nameW, 0 )) 2876 { 2877 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname), 2878 hModule, debugstr_w(nameW.Buffer) ); 2879 RtlFreeUnicodeString( &nameW ); 2880 } 2881 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname), 2882 hModule, debugstr_w(filename) ); 2883 } 2884 #endif 2885 2886 if (!resname) return STATUS_INVALID_PARAMETER; 2887 2888 info.Type = (ULONG_PTR)RT_MANIFEST; 2889 info.Language = lang; 2890 if (!((ULONG_PTR)resname >> 16)) 2891 { 2892 info.Name = (ULONG_PTR)resname; 2893 status = LdrFindResource_U(hModule, &info, 3, &entry); 2894 } 2895 else if (resname[0] == '#') 2896 { 2897 ULONG value; 2898 RtlInitUnicodeString(&nameW, resname + 1); 2899 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value)) 2900 return STATUS_INVALID_PARAMETER; 2901 info.Name = value; 2902 status = LdrFindResource_U(hModule, &info, 3, &entry); 2903 } 2904 else 2905 { 2906 RtlCreateUnicodeString(&nameW, resname); 2907 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE); 2908 info.Name = (ULONG_PTR)nameW.Buffer; 2909 status = LdrFindResource_U(hModule, &info, 3, &entry); 2910 RtlFreeUnicodeString(&nameW); 2911 } 2912 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL); 2913 2914 if (status == STATUS_SUCCESS) 2915 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size); 2916 2917 return status; 2918 } 2919 2920 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir, 2921 LPCWSTR name, void *root, 2922 int want_dir ); 2923 2924 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir, 2925 void *root, int want_dir ); 2926 2927 2928 static IMAGE_RESOURCE_DIRECTORY *find_first_id_entry( IMAGE_RESOURCE_DIRECTORY *dir, 2929 void *root, int want_dir ) 2930 { 2931 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); 2932 int pos; 2933 2934 for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++) 2935 { 2936 if (!entry[pos].DataIsDirectory == !want_dir) 2937 return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory); 2938 } 2939 return NULL; 2940 } 2941 2942 2943 static NTSTATUS search_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 2944 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2945 HANDLE hModule, ULONG lang ) 2946 { 2947 ULONG size; 2948 PVOID root, ptr; 2949 IMAGE_RESOURCE_DIRECTORY *resdirptr; 2950 IMAGE_RESOURCE_DATA_ENTRY *entry; 2951 NTSTATUS status; 2952 2953 root = RtlImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); 2954 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; 2955 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; 2956 resdirptr = root; 2957 2958 if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1))) 2959 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2960 2961 resdirptr = ptr; 2962 if (!(ptr = find_first_id_entry(resdirptr, root, 1))) 2963 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2964 2965 resdirptr = ptr; 2966 if (!(ptr = find_first_entry(resdirptr, root, 0))) 2967 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2968 2969 entry = ptr; 2970 status = LdrAccessResource(hModule, entry, &ptr, NULL); 2971 2972 if (status == STATUS_SUCCESS) 2973 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size); 2974 2975 return status; 2976 } 2977 2978 2979 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai, 2980 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2981 HANDLE file, LPCWSTR resname, ULONG lang ) 2982 { 2983 HANDLE mapping; 2984 OBJECT_ATTRIBUTES attr; 2985 LARGE_INTEGER size; 2986 LARGE_INTEGER offset; 2987 NTSTATUS status; 2988 SIZE_T count; 2989 void *base; 2990 WCHAR resnameBuf[20]; 2991 LPCWSTR resptr = resname; 2992 2993 if ((!((ULONG_PTR)resname >> 16))) 2994 { 2995 sprintfW(resnameBuf, L"#%u", PtrToUlong(resname)); 2996 resptr = resnameBuf; 2997 } 2998 2999 DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>"); 3000 3001 attr.Length = sizeof(attr); 3002 attr.RootDirectory = 0; 3003 attr.ObjectName = NULL; 3004 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3005 attr.SecurityDescriptor = NULL; 3006 attr.SecurityQualityOfService = NULL; 3007 3008 size.QuadPart = 0; 3009 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3010 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3011 if (status != STATUS_SUCCESS) return status; 3012 3013 offset.QuadPart = 0; 3014 count = 0; 3015 base = NULL; 3016 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 3017 &count, ViewShare, 0, PAGE_READONLY ); 3018 NtClose( mapping ); 3019 if (status != STATUS_SUCCESS) return status; 3020 3021 if (RtlImageNtHeader(base)) /* we got a PE file */ 3022 { 3023 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */ 3024 if (resname) 3025 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang ); 3026 else 3027 status = search_manifest_in_module(acl, ai, filename, directory, shared, module, lang); 3028 } 3029 else status = STATUS_INVALID_IMAGE_FORMAT; 3030 3031 NtUnmapViewOfSection( NtCurrentProcess(), base ); 3032 return status; 3033 } 3034 3035 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai, 3036 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file ) 3037 { 3038 FILE_STANDARD_INFORMATION info; 3039 IO_STATUS_BLOCK io; 3040 HANDLE mapping; 3041 OBJECT_ATTRIBUTES attr; 3042 LARGE_INTEGER size; 3043 LARGE_INTEGER offset; 3044 NTSTATUS status; 3045 SIZE_T count; 3046 void *base; 3047 3048 DPRINT( "loading manifest file %S\n", filename ); 3049 3050 attr.Length = sizeof(attr); 3051 attr.RootDirectory = 0; 3052 attr.ObjectName = NULL; 3053 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3054 attr.SecurityDescriptor = NULL; 3055 attr.SecurityQualityOfService = NULL; 3056 3057 size.QuadPart = 0; 3058 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3059 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3060 3061 if (status != STATUS_SUCCESS) return status; 3062 3063 offset.QuadPart = 0; 3064 count = 0; 3065 base = NULL; 3066 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 3067 &count, ViewShare, 0, PAGE_READONLY ); 3068 NtClose( mapping ); 3069 if (status != STATUS_SUCCESS) return status; 3070 3071 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */ 3072 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation); 3073 3074 if (status == STATUS_SUCCESS) 3075 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart); 3076 3077 NtUnmapViewOfSection( NtCurrentProcess(), base ); 3078 return status; 3079 } 3080 3081 /* try to load the .manifest file associated to the file */ 3082 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 3083 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname ) 3084 { 3085 static const WCHAR fmtW[] = { '.','%','l','u',0 }; 3086 WCHAR *buffer; 3087 NTSTATUS status; 3088 UNICODE_STRING nameW; 3089 HANDLE file; 3090 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 3091 3092 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff; 3093 3094 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid ); 3095 3096 if (module) /* use the module filename */ 3097 { 3098 UNICODE_STRING name; 3099 3100 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) ))) 3101 { 3102 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid ); 3103 strcatW( name.Buffer, dotManifestW ); 3104 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL )) 3105 status = STATUS_RESOURCE_DATA_NOT_FOUND; 3106 RtlFreeUnicodeString( &name ); 3107 } 3108 if (status) return status; 3109 } 3110 else 3111 { 3112 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3113 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3114 return STATUS_NO_MEMORY; 3115 strcpyW( buffer, filename ); 3116 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid ); 3117 strcatW( buffer, dotManifestW ); 3118 RtlInitUnicodeString( &nameW, buffer ); 3119 } 3120 3121 if (!open_nt_file( &file, &nameW )) 3122 { 3123 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3124 NtClose( file ); 3125 } 3126 else status = STATUS_RESOURCE_TYPE_NOT_FOUND; 3127 RtlFreeUnicodeString( &nameW ); 3128 return status; 3129 } 3130 3131 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai ) 3132 { 3133 static const WCHAR lookup_fmtW[] = 3134 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_', 3135 '%','s','_','*','.','m','a','n','i','f','e','s','t',0}; 3136 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'}; 3137 3138 WCHAR *lookup, *ret = NULL; 3139 UNICODE_STRING lookup_us; 3140 IO_STATUS_BLOCK io; 3141 const WCHAR *lang = ai->language; 3142 unsigned int data_pos = 0, data_len; 3143 char buffer[8192]; 3144 3145 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3146 (strlenW(ai->arch) + strlenW(ai->name) 3147 + strlenW(ai->public_key) + 20) * sizeof(WCHAR) 3148 + sizeof(lookup_fmtW) ))) 3149 return NULL; 3150 3151 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW; 3152 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, 3153 ai->version.major, ai->version.minor, lang ); 3154 RtlInitUnicodeString( &lookup_us, lookup ); 3155 3156 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3157 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE )) 3158 { 3159 ULONG min_build = ai->version.build, min_revision = ai->version.revision; 3160 FILE_BOTH_DIR_INFORMATION *dir_info; 3161 WCHAR *tmp; 3162 ULONG build, revision; 3163 3164 data_len = (ULONG)io.Information; 3165 3166 for (;;) 3167 { 3168 if (data_pos >= data_len) 3169 { 3170 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3171 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE )) 3172 break; 3173 data_len = (ULONG)io.Information; 3174 data_pos = 0; 3175 } 3176 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos); 3177 3178 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset; 3179 else data_pos = data_len; 3180 3181 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup); 3182 build = atoiW(tmp); 3183 if (build < min_build) continue; 3184 tmp = strchrW(tmp, '.') + 1; 3185 revision = atoiW(tmp); 3186 if (build == min_build && revision < min_revision) continue; 3187 tmp = strchrW(tmp, '_') + 1; 3188 tmp = strchrW(tmp, '_') + 1; 3189 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) && 3190 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) )) 3191 { 3192 /* prefer a non-Wine manifest if we already have one */ 3193 /* we'll still load the builtin dll if specified through DllOverrides */ 3194 if (ret) continue; 3195 } 3196 else 3197 { 3198 min_build = build; 3199 min_revision = revision; 3200 } 3201 ai->version.build = build; 3202 ai->version.revision = revision; 3203 RtlFreeHeap( RtlGetProcessHeap(), 0, ret ); 3204 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) ))) 3205 { 3206 memcpy( ret, dir_info->FileName, dir_info->FileNameLength ); 3207 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0; 3208 } 3209 } 3210 } 3211 else DPRINT1("no matching file for %S\n", lookup); 3212 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup ); 3213 return ret; 3214 } 3215 3216 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai) 3217 { 3218 struct assembly_identity sxs_ai; 3219 UNICODE_STRING path_us; 3220 OBJECT_ATTRIBUTES attr; 3221 IO_STATUS_BLOCK io; 3222 WCHAR *path, *file = NULL; 3223 HANDLE handle; 3224 3225 static const WCHAR manifest_dirW[] = 3226 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0}; 3227 3228 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE; 3229 3230 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3231 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) ))) 3232 return STATUS_NO_MEMORY; 3233 3234 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) ); 3235 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) ); 3236 3237 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL )) 3238 { 3239 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 3240 return STATUS_NO_SUCH_FILE; 3241 } 3242 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 3243 3244 attr.Length = sizeof(attr); 3245 attr.RootDirectory = 0; 3246 attr.Attributes = OBJ_CASE_INSENSITIVE; 3247 attr.ObjectName = &path_us; 3248 attr.SecurityDescriptor = NULL; 3249 attr.SecurityQualityOfService = NULL; 3250 3251 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, 3252 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) 3253 { 3254 sxs_ai = *ai; 3255 file = lookup_manifest_file( handle, &sxs_ai ); 3256 NtClose( handle ); 3257 } 3258 if (!file) 3259 { 3260 RtlFreeUnicodeString( &path_us ); 3261 return STATUS_NO_SUCH_FILE; 3262 } 3263 3264 /* append file name to directory path */ 3265 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer, 3266 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) ))) 3267 { 3268 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 3269 RtlFreeUnicodeString( &path_us ); 3270 return STATUS_NO_MEMORY; 3271 } 3272 3273 path[path_us.Length/sizeof(WCHAR)] = '\\'; 3274 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file ); 3275 RtlInitUnicodeString( &path_us, path ); 3276 *strrchrW(file, '.') = 0; /* remove .manifest extension */ 3277 3278 if (!open_nt_file( &handle, &path_us )) 3279 { 3280 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle); 3281 NtClose( handle ); 3282 } 3283 else io.Status = STATUS_NO_SUCH_FILE; 3284 3285 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 3286 RtlFreeUnicodeString( &path_us ); 3287 return io.Status; 3288 } 3289 3290 static NTSTATUS lookup_assembly(struct actctx_loader* acl, 3291 struct assembly_identity* ai) 3292 { 3293 static const WCHAR dotDllW[] = {'.','d','l','l',0}; 3294 unsigned int i; 3295 WCHAR *buffer, *p, *directory; 3296 NTSTATUS status; 3297 UNICODE_STRING nameW; 3298 HANDLE file; 3299 DWORD len; 3300 3301 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n", 3302 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch ); 3303 3304 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status; 3305 3306 /* FIXME: add support for language specific lookup */ 3307 3308 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR), 3309 strlenW(acl->actctx->appdir.info)); 3310 3311 nameW.Buffer = NULL; 3312 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3313 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3314 return STATUS_NO_MEMORY; 3315 3316 if (!(directory = build_assembly_dir( ai ))) 3317 { 3318 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 3319 return STATUS_NO_MEMORY; 3320 } 3321 3322 /* Lookup in <dir>\name.dll 3323 * <dir>\name.manifest 3324 * <dir>\name\name.dll 3325 * <dir>\name\name.manifest 3326 * 3327 * First 'appdir' is used as <dir>, if that failed 3328 * it tries application manifest file path. 3329 */ 3330 strcpyW( buffer, acl->actctx->appdir.info ); 3331 p = buffer + strlenW(buffer); 3332 for (i = 0; i < 4; i++) 3333 { 3334 if (i == 2) 3335 { 3336 struct assembly *assembly = acl->actctx->assemblies; 3337 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break; 3338 } 3339 else *p++ = '\\'; 3340 3341 strcpyW( p, ai->name ); 3342 p += strlenW(p); 3343 3344 strcpyW( p, dotDllW ); 3345 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3346 { 3347 status = open_nt_file( &file, &nameW ); 3348 if (!status) 3349 { 3350 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, 3351 (LPCWSTR)0, 0 ); 3352 NtClose( file ); 3353 break; 3354 } 3355 RtlFreeUnicodeString( &nameW ); 3356 } 3357 3358 strcpyW( p, dotManifestW ); 3359 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3360 { 3361 status = open_nt_file( &file, &nameW ); 3362 if (!status) 3363 { 3364 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3365 NtClose( file ); 3366 break; 3367 } 3368 RtlFreeUnicodeString( &nameW ); 3369 } 3370 status = STATUS_SXS_ASSEMBLY_NOT_FOUND; 3371 } 3372 RtlFreeUnicodeString( &nameW ); 3373 RtlFreeHeap( RtlGetProcessHeap(), 0, directory ); 3374 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 3375 return status; 3376 } 3377 3378 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) 3379 { 3380 NTSTATUS status = STATUS_SUCCESS; 3381 unsigned int i; 3382 3383 for (i = 0; i < acl->num_dependencies; i++) 3384 { 3385 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS) 3386 { 3387 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed) 3388 { 3389 const struct assembly_version *ver = &acl->dependencies[i].version; 3390 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n", 3391 acl->dependencies[i].name, 3392 ver->major, ver->minor, ver->build, ver->revision ); 3393 status = STATUS_SXS_CANT_GEN_ACTCTX; 3394 break; 3395 } 3396 } 3397 } 3398 /* FIXME should now iterate through all refs */ 3399 return status; 3400 } 3401 3402 /* find the appropriate activation context for RtlQueryInformationActivationContext */ 3403 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class ) 3404 { 3405 NTSTATUS status = STATUS_SUCCESS; 3406 3407 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT) 3408 { 3409 if (*handle) return STATUS_INVALID_PARAMETER; 3410 3411 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 3412 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 3413 } 3414 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE)) 3415 { 3416 ULONG_PTR magic; 3417 LDR_DATA_TABLE_ENTRY *pldr; 3418 3419 if (!*handle) return STATUS_INVALID_PARAMETER; 3420 3421 LdrLockLoaderLock( 0, NULL, &magic ); 3422 if (!LdrFindEntryForAddress( *handle, &pldr )) 3423 { 3424 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase) 3425 status = STATUS_DLL_NOT_FOUND; 3426 else 3427 *handle = pldr->EntryPointActivationContext; 3428 } 3429 else status = STATUS_DLL_NOT_FOUND; 3430 LdrUnlockLoaderLock( 0, magic ); 3431 } 3432 else if (!*handle && (class != ActivationContextBasicInformation)) 3433 *handle = process_actctx; 3434 3435 return status; 3436 } 3437 3438 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3439 { 3440 unsigned int i, j, total_len = 0, dll_count = 0; 3441 struct strsection_header *header; 3442 struct dllredirect_data *data; 3443 struct string_index *index; 3444 ULONG name_offset; 3445 3446 DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies); 3447 3448 /* compute section length */ 3449 for (i = 0; i < actctx->num_assemblies; i++) 3450 { 3451 struct assembly *assembly = &actctx->assemblies[i]; 3452 for (j = 0; j < assembly->num_dlls; j++) 3453 { 3454 struct dll_redirect *dll = &assembly->dlls[j]; 3455 3456 /* each entry needs index, data and string data */ 3457 total_len += sizeof(*index); 3458 total_len += sizeof(*data); 3459 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR)); 3460 3461 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name); 3462 } 3463 3464 dll_count += assembly->num_dlls; 3465 } 3466 3467 total_len += sizeof(*header); 3468 3469 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3470 if (!header) return STATUS_NO_MEMORY; 3471 3472 memset(header, 0, sizeof(*header)); 3473 header->magic = STRSECTION_MAGIC; 3474 header->size = sizeof(*header); 3475 header->count = dll_count; 3476 header->index_offset = sizeof(*header); 3477 index = (struct string_index*)((BYTE*)header + header->index_offset); 3478 name_offset = header->index_offset + header->count*sizeof(*index); 3479 3480 for (i = 0; i < actctx->num_assemblies; i++) 3481 { 3482 struct assembly *assembly = &actctx->assemblies[i]; 3483 3484 DPRINT("assembly->num_dlls %d\n", assembly->num_dlls); 3485 3486 for (j = 0; j < assembly->num_dlls; j++) 3487 { 3488 struct dll_redirect *dll = &assembly->dlls[j]; 3489 UNICODE_STRING str; 3490 WCHAR *ptrW; 3491 3492 DPRINT("%d: dll name %S\n", j, dll->name); 3493 /* setup new index entry */ 3494 str.Buffer = dll->name; 3495 str.Length = (USHORT)strlenW(dll->name)*sizeof(WCHAR); 3496 str.MaximumLength = str.Length + sizeof(WCHAR); 3497 /* hash original class name */ 3498 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3499 3500 index->name_offset = name_offset; 3501 index->name_len = str.Length; 3502 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3503 index->data_len = sizeof(*data); 3504 index->rosterindex = i + 1; 3505 3506 /* setup data */ 3507 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset); 3508 data->size = sizeof(*data); 3509 data->unk = 2; /* FIXME: seems to be constant */ 3510 memset(data->res, 0, sizeof(data->res)); 3511 3512 /* dll name */ 3513 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3514 memcpy(ptrW, dll->name, index->name_len); 3515 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3516 3517 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength); 3518 3519 index++; 3520 } 3521 } 3522 3523 *section = header; 3524 3525 return STATUS_SUCCESS; 3526 } 3527 3528 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name) 3529 { 3530 struct string_index *iter, *index = NULL; 3531 ULONG hash = 0, i; 3532 3533 DPRINT("section %p, name %wZ\n", section, name); 3534 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3535 iter = (struct string_index*)((BYTE*)section + section->index_offset); 3536 3537 for (i = 0; i < section->count; i++) 3538 { 3539 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash); 3540 DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset)); 3541 if (iter->hash == hash) 3542 { 3543 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset); 3544 3545 if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) && 3546 wcslen(nameW) == name->Length / sizeof(WCHAR)) 3547 { 3548 index = iter; 3549 break; 3550 } 3551 else 3552 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); 3553 } 3554 iter++; 3555 } 3556 3557 return index; 3558 } 3559 3560 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid) 3561 { 3562 struct guid_index *iter, *index = NULL; 3563 ULONG i; 3564 3565 iter = (struct guid_index*)((BYTE*)section + section->index_offset); 3566 3567 for (i = 0; i < section->count; i++) 3568 { 3569 if (!memcmp(guid, &iter->guid, sizeof(*guid))) 3570 { 3571 index = iter; 3572 break; 3573 } 3574 iter++; 3575 } 3576 3577 return index; 3578 } 3579 3580 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3581 { 3582 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset); 3583 } 3584 3585 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3586 PACTCTX_SECTION_KEYED_DATA data) 3587 { 3588 struct dllredirect_data *dll; 3589 struct string_index *index; 3590 3591 DPRINT("sections: 0x%08X\n", actctx->sections); 3592 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3593 3594 DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section); 3595 if (!actctx->dllredirect_section) 3596 { 3597 struct strsection_header *section; 3598 3599 NTSTATUS status = build_dllredirect_section(actctx, §ion); 3600 if (status) return status; 3601 3602 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL)) 3603 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3604 } 3605 3606 index = find_string_index(actctx->dllredirect_section, name); 3607 DPRINT("index: %d\n", index); 3608 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3609 3610 if (data) 3611 { 3612 dll = get_dllredirect_data(actctx, index); 3613 3614 data->ulDataFormatVersion = 1; 3615 data->lpData = dll; 3616 data->ulLength = dll->size; 3617 data->lpSectionGlobalData = NULL; 3618 data->ulSectionGlobalDataLength = 0; 3619 data->lpSectionBase = actctx->dllredirect_section; 3620 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section ); 3621 data->hActCtx = NULL; 3622 3623 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3624 data->ulAssemblyRosterIndex = index->rosterindex; 3625 } 3626 3627 return STATUS_SUCCESS; 3628 } 3629 3630 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx) 3631 { 3632 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset); 3633 } 3634 3635 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3636 { 3637 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset); 3638 } 3639 3640 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3641 { 3642 unsigned int i, j, k, total_len = 0, class_count = 0; 3643 struct wndclass_redirect_data *data; 3644 struct strsection_header *header; 3645 struct string_index *index; 3646 ULONG name_offset; 3647 3648 /* compute section length */ 3649 for (i = 0; i < actctx->num_assemblies; i++) 3650 { 3651 struct assembly *assembly = &actctx->assemblies[i]; 3652 for (j = 0; j < assembly->num_dlls; j++) 3653 { 3654 struct dll_redirect *dll = &assembly->dlls[j]; 3655 for (k = 0; k < dll->entities.num; k++) 3656 { 3657 struct entity *entity = &dll->entities.base[k]; 3658 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3659 { 3660 int class_len = strlenW(entity->u.class.name) + 1; 3661 int len; 3662 3663 /* each class entry needs index, data and string data */ 3664 total_len += sizeof(*index); 3665 total_len += sizeof(*data); 3666 /* original name is stored separately */ 3667 total_len += aligned_string_len(class_len*sizeof(WCHAR)); 3668 /* versioned name and module name are stored one after another */ 3669 if (entity->u.class.versioned) 3670 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */; 3671 else 3672 len = class_len; 3673 len += strlenW(dll->name) + 1; 3674 total_len += aligned_string_len(len*sizeof(WCHAR)); 3675 3676 class_count++; 3677 } 3678 } 3679 } 3680 } 3681 3682 total_len += sizeof(*header); 3683 3684 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3685 if (!header) return STATUS_NO_MEMORY; 3686 3687 memset(header, 0, sizeof(*header)); 3688 header->magic = STRSECTION_MAGIC; 3689 header->size = sizeof(*header); 3690 header->count = class_count; 3691 header->index_offset = sizeof(*header); 3692 index = (struct string_index*)((BYTE*)header + header->index_offset); 3693 name_offset = header->index_offset + header->count*sizeof(*index); 3694 3695 for (i = 0; i < actctx->num_assemblies; i++) 3696 { 3697 struct assembly *assembly = &actctx->assemblies[i]; 3698 for (j = 0; j < assembly->num_dlls; j++) 3699 { 3700 struct dll_redirect *dll = &assembly->dlls[j]; 3701 for (k = 0; k < dll->entities.num; k++) 3702 { 3703 struct entity *entity = &dll->entities.base[k]; 3704 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3705 { 3706 static const WCHAR exclW[] = {'!',0}; 3707 ULONG versioned_len, module_len; 3708 UNICODE_STRING str; 3709 WCHAR *ptrW; 3710 3711 /* setup new index entry */ 3712 str.Buffer = entity->u.class.name; 3713 str.Length = (USHORT)strlenW(entity->u.class.name)*sizeof(WCHAR); 3714 str.MaximumLength = str.Length + sizeof(WCHAR); 3715 /* hash original class name */ 3716 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3717 3718 /* include '!' separator too */ 3719 if (entity->u.class.versioned) 3720 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length; 3721 else 3722 versioned_len = str.Length; 3723 module_len = strlenW(dll->name)*sizeof(WCHAR); 3724 3725 index->name_offset = name_offset; 3726 index->name_len = str.Length; 3727 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3728 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */; 3729 index->rosterindex = i + 1; 3730 3731 /* setup data */ 3732 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset); 3733 data->size = sizeof(*data); 3734 data->res = 0; 3735 data->name_len = versioned_len; 3736 data->name_offset = sizeof(*data); 3737 data->module_len = module_len; 3738 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR); 3739 3740 /* original class name */ 3741 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3742 memcpy(ptrW, entity->u.class.name, index->name_len); 3743 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3744 3745 /* module name */ 3746 ptrW = (WCHAR*)((BYTE*)header + data->module_offset); 3747 memcpy(ptrW, dll->name, data->module_len); 3748 ptrW[data->module_len/sizeof(WCHAR)] = 0; 3749 3750 /* versioned name */ 3751 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 3752 if (entity->u.class.versioned) 3753 { 3754 get_assembly_version(assembly, ptrW); 3755 strcatW(ptrW, exclW); 3756 strcatW(ptrW, entity->u.class.name); 3757 } 3758 else 3759 { 3760 memcpy(ptrW, entity->u.class.name, index->name_len); 3761 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3762 } 3763 3764 name_offset += sizeof(*data); 3765 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR)); 3766 3767 index++; 3768 } 3769 } 3770 } 3771 } 3772 3773 *section = header; 3774 3775 return STATUS_SUCCESS; 3776 } 3777 3778 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3779 PACTCTX_SECTION_KEYED_DATA data) 3780 { 3781 struct string_index *iter, *index = NULL; 3782 struct wndclass_redirect_data *class; 3783 ULONG hash; 3784 int i; 3785 3786 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3787 3788 if (!actctx->wndclass_section) 3789 { 3790 struct strsection_header *section; 3791 3792 NTSTATUS status = build_wndclass_section(actctx, §ion); 3793 if (status) return status; 3794 3795 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL)) 3796 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3797 } 3798 3799 hash = 0; 3800 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3801 iter = get_wndclass_first_index(actctx); 3802 3803 for (i = 0; i < actctx->wndclass_section->count; i++) 3804 { 3805 if (iter->hash == hash) 3806 { 3807 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset); 3808 3809 if (!strcmpiW(nameW, name->Buffer)) 3810 { 3811 index = iter; 3812 break; 3813 } 3814 else 3815 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); 3816 } 3817 iter++; 3818 } 3819 3820 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3821 3822 if (data) 3823 { 3824 class = get_wndclass_data(actctx, index); 3825 3826 data->ulDataFormatVersion = 1; 3827 data->lpData = class; 3828 /* full length includes string length with nulls */ 3829 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR); 3830 data->lpSectionGlobalData = NULL; 3831 data->ulSectionGlobalDataLength = 0; 3832 data->lpSectionBase = actctx->wndclass_section; 3833 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section ); 3834 data->hActCtx = NULL; 3835 3836 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3837 data->ulAssemblyRosterIndex = index->rosterindex; 3838 } 3839 3840 return STATUS_SUCCESS; 3841 } 3842 3843 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 3844 { 3845 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0; 3846 struct guidsection_header *header; 3847 ULONG module_offset, data_offset; 3848 struct tlibredirect_data *data; 3849 struct guid_index *index; 3850 3851 /* compute section length */ 3852 for (i = 0; i < actctx->num_assemblies; i++) 3853 { 3854 struct assembly *assembly = &actctx->assemblies[i]; 3855 for (j = 0; j < assembly->num_dlls; j++) 3856 { 3857 struct dll_redirect *dll = &assembly->dlls[j]; 3858 for (k = 0; k < dll->entities.num; k++) 3859 { 3860 struct entity *entity = &dll->entities.base[k]; 3861 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3862 { 3863 /* each entry needs index, data and string data for module name and help string */ 3864 total_len += sizeof(*index); 3865 total_len += sizeof(*data); 3866 /* help string is stored separately */ 3867 if (*entity->u.typelib.helpdir) 3868 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR)); 3869 3870 /* module names are packed one after another */ 3871 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 3872 3873 tlib_count++; 3874 } 3875 } 3876 } 3877 } 3878 3879 total_len += aligned_string_len(names_len); 3880 total_len += sizeof(*header); 3881 3882 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3883 if (!header) return STATUS_NO_MEMORY; 3884 3885 memset(header, 0, sizeof(*header)); 3886 header->magic = GUIDSECTION_MAGIC; 3887 header->size = sizeof(*header); 3888 header->count = tlib_count; 3889 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 3890 index = (struct guid_index*)((BYTE*)header + header->index_offset); 3891 module_offset = sizeof(*header); 3892 data_offset = header->index_offset + tlib_count*sizeof(*index); 3893 3894 for (i = 0; i < actctx->num_assemblies; i++) 3895 { 3896 struct assembly *assembly = &actctx->assemblies[i]; 3897 for (j = 0; j < assembly->num_dlls; j++) 3898 { 3899 struct dll_redirect *dll = &assembly->dlls[j]; 3900 for (k = 0; k < dll->entities.num; k++) 3901 { 3902 struct entity *entity = &dll->entities.base[k]; 3903 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3904 { 3905 ULONG module_len, help_len; 3906 UNICODE_STRING str; 3907 WCHAR *ptrW; 3908 3909 if (*entity->u.typelib.helpdir) 3910 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR); 3911 else 3912 help_len = 0; 3913 3914 module_len = strlenW(dll->name)*sizeof(WCHAR); 3915 3916 /* setup new index entry */ 3917 RtlInitUnicodeString(&str, entity->u.typelib.tlbid); 3918 RtlGUIDFromString(&str, &index->guid); 3919 index->data_offset = data_offset; 3920 index->data_len = sizeof(*data) + aligned_string_len(help_len); 3921 index->rosterindex = i + 1; 3922 3923 /* setup data */ 3924 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset); 3925 data->size = sizeof(*data); 3926 data->res = 0; 3927 data->name_len = module_len; 3928 data->name_offset = module_offset; 3929 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */ 3930 data->langid = 0; 3931 data->flags = entity->u.typelib.flags; 3932 data->help_len = help_len; 3933 data->help_offset = sizeof(*data); 3934 data->major_version = entity->u.typelib.major; 3935 data->minor_version = entity->u.typelib.minor; 3936 3937 /* module name */ 3938 ptrW = (WCHAR*)((BYTE*)header + data->name_offset); 3939 memcpy(ptrW, dll->name, data->name_len); 3940 ptrW[data->name_len/sizeof(WCHAR)] = 0; 3941 3942 /* help string */ 3943 if (data->help_len) 3944 { 3945 ptrW = (WCHAR*)((BYTE*)data + data->help_offset); 3946 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len); 3947 ptrW[data->help_len/sizeof(WCHAR)] = 0; 3948 } 3949 3950 data_offset += sizeof(*data); 3951 if (help_len) 3952 data_offset += aligned_string_len(help_len + sizeof(WCHAR)); 3953 3954 module_offset += module_len + sizeof(WCHAR); 3955 3956 index++; 3957 } 3958 } 3959 } 3960 } 3961 3962 *section = header; 3963 3964 return STATUS_SUCCESS; 3965 } 3966 3967 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 3968 { 3969 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset); 3970 } 3971 3972 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 3973 { 3974 struct guid_index *index = NULL; 3975 struct tlibredirect_data *tlib; 3976 3977 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3978 3979 if (!actctx->tlib_section) 3980 { 3981 struct guidsection_header *section; 3982 3983 NTSTATUS status = build_tlib_section(actctx, §ion); 3984 if (status) return status; 3985 3986 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL)) 3987 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3988 } 3989 3990 index = find_guid_index(actctx->tlib_section, guid); 3991 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3992 3993 tlib = get_tlib_data(actctx, index); 3994 3995 data->ulDataFormatVersion = 1; 3996 data->lpData = tlib; 3997 /* full length includes string length with nulls */ 3998 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR); 3999 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset; 4000 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len; 4001 data->lpSectionBase = actctx->tlib_section; 4002 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section ); 4003 data->hActCtx = NULL; 4004 4005 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4006 data->ulAssemblyRosterIndex = index->rosterindex; 4007 4008 return STATUS_SUCCESS; 4009 } 4010 4011 static void generate_uuid(ULONG *seed, GUID *guid) 4012 { 4013 ULONG *ptr = (ULONG*)guid; 4014 int i; 4015 4016 /* GUID is 16 bytes long */ 4017 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++) 4018 *ptr = RtlUniform(seed); 4019 4020 guid->Data3 &= 0x0fff; 4021 guid->Data3 |= (4 << 12); 4022 guid->Data4[0] &= 0x3f; 4023 guid->Data4[0] |= 0x80; 4024 } 4025 4026 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll, 4027 unsigned int *count, unsigned int *len, unsigned int *module_len) 4028 { 4029 unsigned int i; 4030 4031 for (i = 0; i < entities->num; i++) 4032 { 4033 struct entity *entity = &entities->base[i]; 4034 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4035 { 4036 /* each entry needs two index entries, extra one goes for alias GUID */ 4037 *len += 2*sizeof(struct guid_index); 4038 /* To save some memory we don't allocated two data structures, 4039 instead alias index and normal index point to the same data structure. */ 4040 *len += sizeof(struct comclassredirect_data); 4041 4042 /* for clrClass store some more */ 4043 if (entity->u.comclass.name) 4044 { 4045 unsigned int str_len; 4046 4047 /* all string data is stored together in aligned block */ 4048 str_len = strlenW(entity->u.comclass.name)+1; 4049 if (entity->u.comclass.progid) 4050 str_len += strlenW(entity->u.comclass.progid)+1; 4051 if (entity->u.comclass.version) 4052 str_len += strlenW(entity->u.comclass.version)+1; 4053 4054 *len += sizeof(struct clrclass_data); 4055 *len += aligned_string_len(str_len*sizeof(WCHAR)); 4056 4057 /* module name is forced to mscoree.dll, and stored two times with different case */ 4058 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W); 4059 } 4060 else 4061 { 4062 /* progid string is stored separately */ 4063 if (entity->u.comclass.progid) 4064 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4065 4066 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 4067 } 4068 4069 *count += 1; 4070 } 4071 } 4072 } 4073 4074 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities, 4075 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset, 4076 ULONG *seed, ULONG rosterindex) 4077 { 4078 unsigned int i; 4079 4080 for (i = 0; i < entities->num; i++) 4081 { 4082 struct entity *entity = &entities->base[i]; 4083 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4084 { 4085 ULONG module_len, progid_len, str_len = 0; 4086 struct comclassredirect_data *data; 4087 struct guid_index *alias_index; 4088 struct clrclass_data *clrdata; 4089 UNICODE_STRING str; 4090 WCHAR *ptrW; 4091 4092 if (entity->u.comclass.progid) 4093 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR); 4094 else 4095 progid_len = 0; 4096 4097 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR); 4098 4099 /* setup new index entry */ 4100 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4101 RtlGUIDFromString(&str, &(*index)->guid); 4102 4103 (*index)->data_offset = *data_offset; 4104 (*index)->data_len = sizeof(*data); /* additional length added later */ 4105 (*index)->rosterindex = rosterindex; 4106 4107 /* Setup new index entry for alias guid. Alias index records are placed after 4108 normal records, so normal guids are hit first on search. Note that class count 4109 is doubled. */ 4110 alias_index = (*index) + section->count/2; 4111 generate_uuid(seed, &alias_index->guid); 4112 alias_index->data_offset = (*index)->data_offset; 4113 alias_index->data_len = 0; 4114 alias_index->rosterindex = (*index)->rosterindex; 4115 4116 /* setup data */ 4117 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset); 4118 data->size = sizeof(*data); 4119 data->res = 0; 4120 data->res1[0] = 0; 4121 data->res1[1] = 0; 4122 data->model = entity->u.comclass.model; 4123 data->clsid = (*index)->guid; 4124 data->alias = alias_index->guid; 4125 data->clsid2 = data->clsid; 4126 if (entity->u.comclass.tlbid) 4127 { 4128 RtlInitUnicodeString(&str, entity->u.comclass.tlbid); 4129 RtlGUIDFromString(&str, &data->tlbid); 4130 } 4131 else 4132 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4133 data->name_len = module_len; 4134 data->name_offset = *module_offset; 4135 data->progid_len = progid_len; 4136 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */ 4137 data->clrdata_len = 0; /* will be set later */ 4138 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0; 4139 data->miscstatus = entity->u.comclass.miscstatus; 4140 data->miscstatuscontent = entity->u.comclass.miscstatuscontent; 4141 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail; 4142 data->miscstatusicon = entity->u.comclass.miscstatusicon; 4143 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint; 4144 4145 /* mask describes which misc* data is available */ 4146 data->miscmask = 0; 4147 if (data->miscstatus) 4148 data->miscmask |= MiscStatus; 4149 if (data->miscstatuscontent) 4150 data->miscmask |= MiscStatusContent; 4151 if (data->miscstatusthumbnail) 4152 data->miscmask |= MiscStatusThumbnail; 4153 if (data->miscstatusicon) 4154 data->miscmask |= MiscStatusIcon; 4155 if (data->miscstatusdocprint) 4156 data->miscmask |= MiscStatusDocPrint; 4157 4158 if (data->clrdata_offset) 4159 { 4160 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset); 4161 4162 clrdata->size = sizeof(*clrdata); 4163 clrdata->res[0] = 0; 4164 clrdata->res[1] = 2; /* FIXME: unknown field */ 4165 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR); 4166 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR); 4167 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR); 4168 clrdata->name_offset = clrdata->size; 4169 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0; 4170 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0; 4171 clrdata->res2[0] = 0; 4172 clrdata->res2[1] = 0; 4173 4174 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR); 4175 4176 /* module name */ 4177 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset); 4178 memcpy(ptrW, mscoree2W, clrdata->module_len); 4179 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0; 4180 4181 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4182 memcpy(ptrW, mscoreeW, data->name_len); 4183 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4184 4185 /* class name */ 4186 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset); 4187 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len); 4188 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0; 4189 4190 /* runtime version, optional */ 4191 if (clrdata->version_len) 4192 { 4193 data->clrdata_len += clrdata->version_len + sizeof(WCHAR); 4194 4195 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset); 4196 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len); 4197 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0; 4198 } 4199 4200 if (data->progid_len) 4201 data->progid_offset += data->clrdata_len; 4202 (*index)->data_len += sizeof(*clrdata); 4203 } 4204 else 4205 { 4206 clrdata = NULL; 4207 4208 /* module name */ 4209 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4210 memcpy(ptrW, dll->name, data->name_len); 4211 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4212 } 4213 4214 /* progid string */ 4215 if (data->progid_len) 4216 { 4217 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset); 4218 memcpy(ptrW, entity->u.comclass.progid, data->progid_len); 4219 ptrW[data->progid_len/sizeof(WCHAR)] = 0; 4220 } 4221 4222 /* string block length */ 4223 str_len = 0; 4224 if (clrdata) 4225 { 4226 str_len += clrdata->name_len + sizeof(WCHAR); 4227 if (clrdata->version_len) 4228 str_len += clrdata->version_len + sizeof(WCHAR); 4229 } 4230 if (progid_len) 4231 str_len += progid_len + sizeof(WCHAR); 4232 4233 (*index)->data_len += aligned_string_len(str_len); 4234 alias_index->data_len = (*index)->data_len; 4235 4236 /* move to next data record */ 4237 (*data_offset) += sizeof(*data) + aligned_string_len(str_len); 4238 (*module_offset) += module_len + sizeof(WCHAR); 4239 4240 if (clrdata) 4241 { 4242 (*data_offset) += sizeof(*clrdata); 4243 (*module_offset) += clrdata->module_len + sizeof(WCHAR); 4244 } 4245 (*index) += 1; 4246 } 4247 } 4248 } 4249 4250 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4251 { 4252 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0; 4253 struct guidsection_header *header; 4254 ULONG module_offset, data_offset; 4255 struct guid_index *index; 4256 ULONG seed; 4257 4258 /* compute section length */ 4259 for (i = 0; i < actctx->num_assemblies; i++) 4260 { 4261 struct assembly *assembly = &actctx->assemblies[i]; 4262 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len); 4263 for (j = 0; j < assembly->num_dlls; j++) 4264 { 4265 struct dll_redirect *dll = &assembly->dlls[j]; 4266 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len); 4267 } 4268 } 4269 4270 total_len += aligned_string_len(names_len); 4271 total_len += sizeof(*header); 4272 4273 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4274 if (!header) return STATUS_NO_MEMORY; 4275 4276 memset(header, 0, sizeof(*header)); 4277 header->magic = GUIDSECTION_MAGIC; 4278 header->size = sizeof(*header); 4279 header->count = 2*class_count; 4280 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 4281 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4282 module_offset = sizeof(*header); 4283 data_offset = header->index_offset + 2*class_count*sizeof(*index); 4284 4285 seed = NtGetTickCount(); 4286 for (i = 0; i < actctx->num_assemblies; i++) 4287 { 4288 struct assembly *assembly = &actctx->assemblies[i]; 4289 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1); 4290 for (j = 0; j < assembly->num_dlls; j++) 4291 { 4292 struct dll_redirect *dll = &assembly->dlls[j]; 4293 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1); 4294 } 4295 } 4296 4297 *section = header; 4298 4299 return STATUS_SUCCESS; 4300 } 4301 4302 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4303 { 4304 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset); 4305 } 4306 4307 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4308 { 4309 struct comclassredirect_data *comclass; 4310 struct guid_index *index = NULL; 4311 4312 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4313 4314 if (!actctx->comserver_section) 4315 { 4316 struct guidsection_header *section; 4317 4318 NTSTATUS status = build_comserver_section(actctx, §ion); 4319 if (status) return status; 4320 4321 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4322 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4323 } 4324 4325 index = find_guid_index(actctx->comserver_section, guid); 4326 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4327 4328 comclass = get_comclass_data(actctx, index); 4329 4330 data->ulDataFormatVersion = 1; 4331 data->lpData = comclass; 4332 /* full length includes string length with nulls */ 4333 data->ulLength = comclass->size + comclass->clrdata_len; 4334 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR); 4335 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset; 4336 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len; 4337 data->lpSectionBase = actctx->comserver_section; 4338 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section ); 4339 data->hActCtx = NULL; 4340 4341 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4342 data->ulAssemblyRosterIndex = index->rosterindex; 4343 4344 return STATUS_SUCCESS; 4345 } 4346 4347 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len) 4348 { 4349 unsigned int i; 4350 4351 for (i = 0; i < entities->num; i++) 4352 { 4353 struct entity *entity = &entities->base[i]; 4354 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4355 { 4356 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data); 4357 if (entity->u.ifaceps.name) 4358 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR)); 4359 *count += 1; 4360 } 4361 } 4362 } 4363 4364 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities, 4365 struct guid_index **index, ULONG *data_offset, ULONG rosterindex) 4366 { 4367 unsigned int i; 4368 4369 for (i = 0; i < entities->num; i++) 4370 { 4371 struct entity *entity = &entities->base[i]; 4372 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4373 { 4374 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset); 4375 UNICODE_STRING str; 4376 ULONG name_len; 4377 4378 if (entity->u.ifaceps.name) 4379 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR); 4380 else 4381 name_len = 0; 4382 4383 /* setup index */ 4384 RtlInitUnicodeString(&str, entity->u.ifaceps.iid); 4385 RtlGUIDFromString(&str, &(*index)->guid); 4386 (*index)->data_offset = *data_offset; 4387 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0; 4388 (*index)->rosterindex = rosterindex; 4389 4390 /* setup data record */ 4391 data->size = sizeof(*data); 4392 data->mask = entity->u.ifaceps.mask; 4393 4394 /* proxyStubClsid32 value is only stored for external PS, 4395 if set it's used as iid, otherwise 'iid' attribute value is used */ 4396 if (entity->u.ifaceps.ps32) 4397 { 4398 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32); 4399 RtlGUIDFromString(&str, &data->iid); 4400 } 4401 else 4402 data->iid = (*index)->guid; 4403 4404 data->nummethods = entity->u.ifaceps.nummethods; 4405 4406 if (entity->u.ifaceps.tlib) 4407 { 4408 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib); 4409 RtlGUIDFromString(&str, &data->tlbid); 4410 } 4411 else 4412 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4413 4414 if (entity->u.ifaceps.base) 4415 { 4416 RtlInitUnicodeString(&str, entity->u.ifaceps.base); 4417 RtlGUIDFromString(&str, &data->base); 4418 } 4419 else 4420 memset(&data->base, 0, sizeof(data->base)); 4421 4422 data->name_len = name_len; 4423 data->name_offset = data->name_len ? sizeof(*data) : 0; 4424 4425 /* name string */ 4426 if (data->name_len) 4427 { 4428 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4429 memcpy(ptrW, entity->u.ifaceps.name, data->name_len); 4430 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4431 } 4432 4433 /* move to next record */ 4434 (*index) += 1; 4435 *data_offset += sizeof(*data); 4436 if (data->name_len) 4437 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR)); 4438 } 4439 } 4440 } 4441 4442 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4443 { 4444 unsigned int i, j, total_len = 0, count = 0; 4445 struct guidsection_header *header; 4446 struct guid_index *index; 4447 ULONG data_offset; 4448 4449 /* compute section length */ 4450 for (i = 0; i < actctx->num_assemblies; i++) 4451 { 4452 struct assembly *assembly = &actctx->assemblies[i]; 4453 4454 get_ifaceps_datalen(&assembly->entities, &count, &total_len); 4455 for (j = 0; j < assembly->num_dlls; j++) 4456 { 4457 struct dll_redirect *dll = &assembly->dlls[j]; 4458 get_ifaceps_datalen(&dll->entities, &count, &total_len); 4459 } 4460 } 4461 4462 total_len += sizeof(*header); 4463 4464 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4465 if (!header) return STATUS_NO_MEMORY; 4466 4467 memset(header, 0, sizeof(*header)); 4468 header->magic = GUIDSECTION_MAGIC; 4469 header->size = sizeof(*header); 4470 header->count = count; 4471 header->index_offset = sizeof(*header); 4472 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4473 data_offset = header->index_offset + count*sizeof(*index); 4474 4475 for (i = 0; i < actctx->num_assemblies; i++) 4476 { 4477 struct assembly *assembly = &actctx->assemblies[i]; 4478 4479 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1); 4480 for (j = 0; j < assembly->num_dlls; j++) 4481 { 4482 struct dll_redirect *dll = &assembly->dlls[j]; 4483 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1); 4484 } 4485 } 4486 4487 *section = header; 4488 4489 return STATUS_SUCCESS; 4490 } 4491 4492 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4493 { 4494 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset); 4495 } 4496 4497 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4498 { 4499 struct ifacepsredirect_data *iface; 4500 struct guid_index *index = NULL; 4501 4502 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4503 4504 if (!actctx->ifaceps_section) 4505 { 4506 struct guidsection_header *section; 4507 4508 NTSTATUS status = build_ifaceps_section(actctx, §ion); 4509 if (status) return status; 4510 4511 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL)) 4512 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4513 } 4514 4515 index = find_guid_index(actctx->ifaceps_section, guid); 4516 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4517 4518 iface = get_ifaceps_data(actctx, index); 4519 4520 data->ulDataFormatVersion = 1; 4521 data->lpData = iface; 4522 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0); 4523 data->lpSectionGlobalData = NULL; 4524 data->ulSectionGlobalDataLength = 0; 4525 data->lpSectionBase = actctx->ifaceps_section; 4526 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section ); 4527 data->hActCtx = NULL; 4528 4529 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4530 data->ulAssemblyRosterIndex = index->rosterindex; 4531 4532 return STATUS_SUCCESS; 4533 } 4534 4535 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4536 { 4537 unsigned int i, j, total_len = 0, count = 0; 4538 struct guidsection_header *header; 4539 struct clrsurrogate_data *data; 4540 struct guid_index *index; 4541 ULONG data_offset; 4542 4543 /* compute section length */ 4544 for (i = 0; i < actctx->num_assemblies; i++) 4545 { 4546 struct assembly *assembly = &actctx->assemblies[i]; 4547 for (j = 0; j < assembly->entities.num; j++) 4548 { 4549 struct entity *entity = &assembly->entities.base[j]; 4550 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4551 { 4552 ULONG len; 4553 4554 total_len += sizeof(*index) + sizeof(*data); 4555 len = strlenW(entity->u.clrsurrogate.name) + 1; 4556 if (entity->u.clrsurrogate.version) 4557 len += strlenW(entity->u.clrsurrogate.version) + 1; 4558 total_len += aligned_string_len(len*sizeof(WCHAR)); 4559 4560 count++; 4561 } 4562 } 4563 } 4564 4565 total_len += sizeof(*header); 4566 4567 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4568 if (!header) return STATUS_NO_MEMORY; 4569 4570 memset(header, 0, sizeof(*header)); 4571 header->magic = GUIDSECTION_MAGIC; 4572 header->size = sizeof(*header); 4573 header->count = count; 4574 header->index_offset = sizeof(*header); 4575 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4576 data_offset = header->index_offset + count*sizeof(*index); 4577 4578 for (i = 0; i < actctx->num_assemblies; i++) 4579 { 4580 struct assembly *assembly = &actctx->assemblies[i]; 4581 for (j = 0; j < assembly->entities.num; j++) 4582 { 4583 struct entity *entity = &assembly->entities.base[j]; 4584 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4585 { 4586 ULONG version_len, name_len; 4587 UNICODE_STRING str; 4588 WCHAR *ptrW; 4589 4590 if (entity->u.clrsurrogate.version) 4591 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR); 4592 else 4593 version_len = 0; 4594 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR); 4595 4596 /* setup new index entry */ 4597 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid); 4598 RtlGUIDFromString(&str, &index->guid); 4599 4600 index->data_offset = data_offset; 4601 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0)); 4602 index->rosterindex = i + 1; 4603 4604 /* setup data */ 4605 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset); 4606 data->size = sizeof(*data); 4607 data->res = 0; 4608 data->clsid = index->guid; 4609 data->version_offset = version_len ? data->size : 0; 4610 data->version_len = version_len; 4611 data->name_offset = data->size + version_len; 4612 if (version_len) 4613 data->name_offset += sizeof(WCHAR); 4614 data->name_len = name_len; 4615 4616 /* surrogate name */ 4617 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4618 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len); 4619 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4620 4621 /* runtime version */ 4622 if (data->version_len) 4623 { 4624 ptrW = (WCHAR*)((BYTE*)data + data->version_offset); 4625 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len); 4626 ptrW[data->version_len/sizeof(WCHAR)] = 0; 4627 } 4628 4629 data_offset += index->data_offset; 4630 index++; 4631 } 4632 } 4633 } 4634 4635 *section = header; 4636 4637 return STATUS_SUCCESS; 4638 } 4639 4640 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index) 4641 { 4642 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset); 4643 } 4644 4645 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4646 { 4647 struct clrsurrogate_data *surrogate; 4648 struct guid_index *index = NULL; 4649 4650 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4651 4652 if (!actctx->clrsurrogate_section) 4653 { 4654 struct guidsection_header *section; 4655 4656 NTSTATUS status = build_clr_surrogate_section(actctx, §ion); 4657 if (status) return status; 4658 4659 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL)) 4660 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4661 } 4662 4663 index = find_guid_index(actctx->clrsurrogate_section, guid); 4664 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4665 4666 surrogate = get_surrogate_data(actctx, index); 4667 4668 data->ulDataFormatVersion = 1; 4669 data->lpData = surrogate; 4670 /* full length includes string length with nulls */ 4671 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR); 4672 if (surrogate->version_len) 4673 data->ulLength += surrogate->version_len + sizeof(WCHAR); 4674 4675 data->lpSectionGlobalData = NULL; 4676 data->ulSectionGlobalDataLength = 0; 4677 data->lpSectionBase = actctx->clrsurrogate_section; 4678 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section ); 4679 data->hActCtx = NULL; 4680 4681 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4682 data->ulAssemblyRosterIndex = index->rosterindex; 4683 4684 return STATUS_SUCCESS; 4685 } 4686 4687 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len) 4688 { 4689 unsigned int i, j, single_len; 4690 4691 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID); 4692 for (i = 0; i < entities->num; i++) 4693 { 4694 struct entity *entity = &entities->base[i]; 4695 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4696 { 4697 if (entity->u.comclass.progid) 4698 { 4699 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4700 *count += 1; 4701 } 4702 4703 for (j = 0; j < entity->u.comclass.progids.num; j++) 4704 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR)); 4705 4706 *total_len += single_len*entity->u.comclass.progids.num; 4707 *count += entity->u.comclass.progids.num; 4708 } 4709 } 4710 } 4711 4712 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias, 4713 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4714 { 4715 struct progidredirect_data *data; 4716 UNICODE_STRING str; 4717 GUID *guid_ptr; 4718 WCHAR *ptrW; 4719 4720 /* setup new index entry */ 4721 4722 /* hash progid name */ 4723 RtlInitUnicodeString(&str, progid); 4724 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash); 4725 4726 (*index)->name_offset = *data_offset; 4727 (*index)->name_len = str.Length; 4728 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength); 4729 (*index)->data_len = sizeof(*data); 4730 (*index)->rosterindex = rosterindex; 4731 4732 *data_offset += aligned_string_len(str.MaximumLength); 4733 4734 /* setup data structure */ 4735 data = (struct progidredirect_data*)((BYTE*)section + *data_offset); 4736 data->size = sizeof(*data); 4737 data->reserved = 0; 4738 data->clsid_offset = *global_offset; 4739 4740 /* write progid string */ 4741 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset); 4742 memcpy(ptrW, progid, (*index)->name_len); 4743 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0; 4744 4745 /* write guid to global area */ 4746 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset); 4747 *guid_ptr = *alias; 4748 4749 /* to next entry */ 4750 *global_offset += sizeof(GUID); 4751 *data_offset += data->size; 4752 (*index) += 1; 4753 } 4754 4755 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities, 4756 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4757 { 4758 unsigned int i, j; 4759 4760 for (i = 0; i < entities->num; i++) 4761 { 4762 struct entity *entity = &entities->base[i]; 4763 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4764 { 4765 const struct progids *progids = &entity->u.comclass.progids; 4766 struct comclassredirect_data *comclass; 4767 struct guid_index *guid_index; 4768 UNICODE_STRING str; 4769 GUID clsid; 4770 4771 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4772 RtlGUIDFromString(&str, &clsid); 4773 4774 guid_index = find_guid_index(actctx->comserver_section, &clsid); 4775 comclass = get_comclass_data(actctx, guid_index); 4776 4777 if (entity->u.comclass.progid) 4778 write_progid_record(section, entity->u.comclass.progid, &comclass->alias, 4779 index, data_offset, global_offset, rosterindex); 4780 4781 for (j = 0; j < progids->num; j++) 4782 write_progid_record(section, progids->progids[j], &comclass->alias, 4783 index, data_offset, global_offset, rosterindex); 4784 } 4785 } 4786 } 4787 4788 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 4789 { 4790 unsigned int i, j, total_len = 0, count = 0; 4791 struct strsection_header *header; 4792 ULONG data_offset, global_offset; 4793 struct string_index *index; 4794 4795 /* compute section length */ 4796 for (i = 0; i < actctx->num_assemblies; i++) 4797 { 4798 struct assembly *assembly = &actctx->assemblies[i]; 4799 4800 get_progid_datalen(&assembly->entities, &count, &total_len); 4801 for (j = 0; j < assembly->num_dlls; j++) 4802 { 4803 struct dll_redirect *dll = &assembly->dlls[j]; 4804 get_progid_datalen(&dll->entities, &count, &total_len); 4805 } 4806 } 4807 4808 total_len += sizeof(*header); 4809 4810 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4811 if (!header) return STATUS_NO_MEMORY; 4812 4813 memset(header, 0, sizeof(*header)); 4814 header->magic = STRSECTION_MAGIC; 4815 header->size = sizeof(*header); 4816 header->count = count; 4817 header->global_offset = header->size; 4818 header->global_len = count*sizeof(GUID); 4819 header->index_offset = header->size + header->global_len; 4820 4821 index = (struct string_index*)((BYTE*)header + header->index_offset); 4822 data_offset = header->index_offset + count*sizeof(*index); 4823 global_offset = header->global_offset; 4824 4825 for (i = 0; i < actctx->num_assemblies; i++) 4826 { 4827 struct assembly *assembly = &actctx->assemblies[i]; 4828 4829 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1); 4830 for (j = 0; j < assembly->num_dlls; j++) 4831 { 4832 struct dll_redirect *dll = &assembly->dlls[j]; 4833 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1); 4834 } 4835 } 4836 4837 *section = header; 4838 4839 return STATUS_SUCCESS; 4840 } 4841 4842 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index) 4843 { 4844 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset); 4845 } 4846 4847 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 4848 PACTCTX_SECTION_KEYED_DATA data) 4849 { 4850 struct progidredirect_data *progid; 4851 struct string_index *index; 4852 4853 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4854 4855 if (!actctx->comserver_section) 4856 { 4857 struct guidsection_header *section; 4858 4859 NTSTATUS status = build_comserver_section(actctx, §ion); 4860 if (status) return status; 4861 4862 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4863 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4864 } 4865 4866 if (!actctx->progid_section) 4867 { 4868 struct strsection_header *section; 4869 4870 NTSTATUS status = build_progid_section(actctx, §ion); 4871 if (status) return status; 4872 4873 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL)) 4874 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4875 } 4876 4877 index = find_string_index(actctx->progid_section, name); 4878 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4879 4880 if (data) 4881 { 4882 progid = get_progid_data(actctx, index); 4883 4884 data->ulDataFormatVersion = 1; 4885 data->lpData = progid; 4886 data->ulLength = progid->size; 4887 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset; 4888 data->ulSectionGlobalDataLength = actctx->progid_section->global_len; 4889 data->lpSectionBase = actctx->progid_section; 4890 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section ); 4891 data->hActCtx = NULL; 4892 4893 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4894 data->ulAssemblyRosterIndex = index->rosterindex; 4895 } 4896 4897 return STATUS_SUCCESS; 4898 } 4899 4900 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 4901 const UNICODE_STRING *section_name, 4902 DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 4903 { 4904 NTSTATUS status; 4905 4906 switch (section_kind) 4907 { 4908 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION: 4909 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 4910 return STATUS_SXS_KEY_NOT_FOUND; 4911 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: 4912 status = find_dll_redirection(actctx, section_name, data); 4913 break; 4914 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 4915 status = find_window_class(actctx, section_name, data); 4916 break; 4917 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 4918 status = find_progid_redirection(actctx, section_name, data); 4919 break; 4920 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: 4921 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 4922 return STATUS_SXS_SECTION_NOT_FOUND; 4923 default: 4924 DPRINT1("Unknown section_kind %x\n", section_kind); 4925 return STATUS_SXS_SECTION_NOT_FOUND; 4926 } 4927 4928 if (status != STATUS_SUCCESS) return status; 4929 4930 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)) 4931 { 4932 actctx_addref(actctx); 4933 data->hActCtx = actctx; 4934 } 4935 return STATUS_SUCCESS; 4936 } 4937 4938 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 4939 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 4940 { 4941 NTSTATUS status; 4942 4943 switch (section_kind) 4944 { 4945 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 4946 status = find_tlib_redirection(actctx, guid, data); 4947 break; 4948 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 4949 status = find_comserver_redirection(actctx, guid, data); 4950 break; 4951 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 4952 status = find_cominterface_redirection(actctx, guid, data); 4953 break; 4954 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 4955 status = find_clr_surrogate(actctx, guid, data); 4956 break; 4957 default: 4958 DPRINT("Unknown section_kind %x\n", section_kind); 4959 return STATUS_SXS_SECTION_NOT_FOUND; 4960 } 4961 4962 if (status != STATUS_SUCCESS) return status; 4963 4964 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 4965 { 4966 actctx_addref(actctx); 4967 data->hActCtx = actctx; 4968 } 4969 return STATUS_SUCCESS; 4970 } 4971 4972 /* initialize the activation context for the current process */ 4973 void actctx_init(PVOID* pOldShimData) 4974 { 4975 ACTCTXW ctx; 4976 HANDLE handle; 4977 WCHAR buffer[1024]; 4978 NTSTATUS Status; 4979 4980 ctx.cbSize = sizeof(ctx); 4981 ctx.lpSource = NULL; 4982 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 4983 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 4984 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 4985 4986 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle))) 4987 { 4988 process_actctx = check_actctx(handle); 4989 } 4990 4991 /* ReactOS specific: 4992 Now that we have found the process_actctx we can initialize the process compat subsystem */ 4993 LdrpInitializeProcessCompat(process_actctx, pOldShimData); 4994 4995 4996 ctx.dwFlags = 0; 4997 ctx.hModule = NULL; 4998 ctx.lpResourceName = NULL; 4999 ctx.lpSource = buffer; 5000 RtlStringCchCopyW(buffer, RTL_NUMBER_OF(buffer), SharedUserData->NtSystemRoot); 5001 5002 if (RosGetProcessCompatVersion()) 5003 { 5004 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\forwardcompatible.manifest"); 5005 } 5006 else 5007 { 5008 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\systemcompatible.manifest"); 5009 } 5010 5011 Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle); 5012 if (NT_SUCCESS(Status)) 5013 { 5014 implicit_actctx = check_actctx(handle); 5015 } 5016 else 5017 { 5018 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status); 5019 } 5020 } 5021 5022 /* FUNCTIONS ***************************************************************/ 5023 5024 /*********************************************************************** 5025 * RtlCreateActivationContext (NTDLL.@) 5026 * 5027 * Create an activation context. 5028 */ 5029 NTSTATUS 5030 NTAPI 5031 RtlCreateActivationContext(IN ULONG Flags, 5032 IN PACTIVATION_CONTEXT_DATA ActivationContextData, 5033 IN ULONG ExtraBytes, 5034 IN PVOID NotificationRoutine, 5035 IN PVOID NotificationContext, 5036 OUT PACTIVATION_CONTEXT *ActCtx) 5037 { 5038 const ACTCTXW *pActCtx = (PVOID)ActivationContextData; 5039 const WCHAR *directory = NULL; 5040 PACTIVATION_CONTEXT_WRAPPED ActualActCtx; 5041 ACTIVATION_CONTEXT *actctx; 5042 UNICODE_STRING nameW; 5043 ULONG lang = 0; 5044 NTSTATUS status = STATUS_NO_MEMORY; 5045 HANDLE file = 0; 5046 struct actctx_loader acl; 5047 5048 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule); 5049 5050 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) || 5051 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL)) 5052 return STATUS_INVALID_PARAMETER; 5053 5054 5055 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx)))) 5056 return STATUS_NO_MEMORY; 5057 5058 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER; 5059 5060 actctx = &ActualActCtx->ActivationContext; 5061 actctx->RefCount = 1; 5062 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; 5063 actctx->config.info = NULL; 5064 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; 5065 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) 5066 { 5067 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error; 5068 } 5069 else 5070 { 5071 UNICODE_STRING dir; 5072 WCHAR *p; 5073 HMODULE module; 5074 5075 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule; 5076 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5077 5078 status = get_module_filename( module, &dir, 0 ); 5079 if (!NT_SUCCESS(status)) goto error; 5080 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0; 5081 actctx->appdir.info = dir.Buffer; 5082 } 5083 5084 nameW.Buffer = NULL; 5085 5086 /* open file only if it's going to be used */ 5087 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && 5088 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID))) 5089 { 5090 WCHAR *source = NULL; 5091 BOOLEAN ret; 5092 5093 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID && 5094 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative) 5095 { 5096 DWORD dir_len, source_len; 5097 5098 dir_len = strlenW(pActCtx->lpAssemblyDirectory); 5099 source_len = strlenW(pActCtx->lpSource); 5100 if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR)))) 5101 { 5102 status = STATUS_NO_MEMORY; 5103 goto error; 5104 } 5105 5106 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR)); 5107 source[dir_len] = '\\'; 5108 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR)); 5109 } 5110 5111 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL); 5112 RtlFreeHeap( RtlGetProcessHeap(), 0, source ); 5113 if (!ret) 5114 { 5115 status = STATUS_NO_SUCH_FILE; 5116 goto error; 5117 } 5118 status = open_nt_file( &file, &nameW ); 5119 if (!NT_SUCCESS(status)) 5120 { 5121 RtlFreeUnicodeString( &nameW ); 5122 goto error; 5123 } 5124 } 5125 5126 acl.actctx = actctx; 5127 acl.dependencies = NULL; 5128 acl.num_dependencies = 0; 5129 acl.allocated_dependencies = 0; 5130 5131 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; 5132 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; 5133 5134 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) 5135 { 5136 /* if we have a resource it's a PE file */ 5137 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) 5138 { 5139 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule, 5140 pActCtx->lpResourceName, lang ); 5141 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5142 /* FIXME: what to do if pActCtx->lpSource is set */ 5143 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, 5144 pActCtx->hModule, pActCtx->lpResourceName ); 5145 } 5146 else if (pActCtx->lpSource && pActCtx->lpResourceName) 5147 { 5148 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE, 5149 file, pActCtx->lpResourceName, lang ); 5150 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5151 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, 5152 NULL, pActCtx->lpResourceName ); 5153 } 5154 else status = STATUS_INVALID_PARAMETER; 5155 } 5156 else 5157 { 5158 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file ); 5159 } 5160 5161 if (file) NtClose( file ); 5162 RtlFreeUnicodeString( &nameW ); 5163 5164 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl); 5165 free_depend_manifests( &acl ); 5166 5167 if (NT_SUCCESS(status)) 5168 *ActCtx = actctx; 5169 else actctx_release( actctx ); 5170 return status; 5171 5172 error: 5173 if (file) NtClose( file ); 5174 actctx_release( actctx ); 5175 return status; 5176 } 5177 5178 #if 0 5179 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1) 5180 5181 VOID 5182 NTAPI 5183 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle) 5184 { 5185 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle; 5186 LONG OldRefCount, NewRefCount; 5187 5188 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5189 { 5190 RtlpValidateActCtx(ActCtx); 5191 5192 while (TRUE) 5193 { 5194 OldRefCount = ActCtx->RefCount; 5195 ASSERT(OldRefCount > 0); 5196 5197 if (OldRefCount == LONG_MAX) break; 5198 5199 NewRefCount = OldRefCount + 1; 5200 if (InterlockedCompareExchange(&ActCtx->RefCount, 5201 NewRefCount, 5202 OldRefCount) == OldRefCount) 5203 { 5204 break; 5205 } 5206 } 5207 5208 NewRefCount = LONG_MAX; 5209 ASSERT(NewRefCount > 0); 5210 } 5211 } 5212 5213 VOID 5214 NTAPI 5215 RtlReleaseActivationContext( HANDLE handle ) 5216 { 5217 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle; 5218 5219 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5220 { 5221 RtlpValidateActCtx(ActCtx); 5222 5223 actctx_release(ActCtx); 5224 } 5225 } 5226 #else 5227 5228 /*********************************************************************** 5229 * RtlAddRefActivationContext (NTDLL.@) 5230 */ 5231 VOID NTAPI RtlAddRefActivationContext( HANDLE handle ) 5232 { 5233 ACTIVATION_CONTEXT *actctx; 5234 5235 if ((actctx = check_actctx( handle ))) actctx_addref( actctx ); 5236 } 5237 5238 5239 /****************************************************************** 5240 * RtlReleaseActivationContext (NTDLL.@) 5241 */ 5242 VOID NTAPI RtlReleaseActivationContext( HANDLE handle ) 5243 { 5244 ACTIVATION_CONTEXT *actctx; 5245 5246 if ((actctx = check_actctx( handle ))) actctx_release( actctx ); 5247 } 5248 5249 #endif 5250 5251 /****************************************************************** 5252 * RtlZombifyActivationContext (NTDLL.@) 5253 * 5254 */ 5255 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context) 5256 { 5257 UNIMPLEMENTED; 5258 5259 if (Context == ACTCTX_FAKE_HANDLE) 5260 return STATUS_SUCCESS; 5261 5262 return STATUS_NOT_IMPLEMENTED; 5263 } 5264 5265 NTSTATUS 5266 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie ) 5267 { 5268 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5269 5270 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) ))) 5271 return STATUS_NO_MEMORY; 5272 5273 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame; 5274 frame->ActivationContext = handle; 5275 frame->Flags = 0; 5276 5277 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5278 tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame, 5279 frame, handle); 5280 5281 tebAddress->ActivationContextStackPointer->ActiveFrame = frame; 5282 RtlAddRefActivationContext( handle ); 5283 5284 *cookie = (ULONG_PTR)frame; 5285 DPRINT( "%p cookie=%lx\n", handle, *cookie ); 5286 return STATUS_SUCCESS; 5287 } 5288 5289 /****************************************************************** 5290 * RtlActivateActivationContext (NTDLL.@) 5291 */ 5292 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie ) 5293 { 5294 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie); 5295 } 5296 5297 /*********************************************************************** 5298 * RtlDeactivateActivationContext (NTDLL.@) 5299 */ 5300 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) 5301 { 5302 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; 5303 5304 DPRINT( "%x cookie=%lx\n", flags, cookie ); 5305 5306 /* find the right frame */ 5307 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5308 for (frame = top; frame; frame = frame->Previous) 5309 if ((ULONG_PTR)frame == cookie) break; 5310 5311 if (!frame) 5312 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 5313 5314 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION)) 5315 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); 5316 5317 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5318 NtCurrentTeb()->ActivationContextStackPointer, 5319 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame, 5320 frame->Previous); 5321 5322 /* pop everything up to and including frame */ 5323 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 5324 5325 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5326 { 5327 frame = top->Previous; 5328 RtlReleaseActivationContext( top->ActivationContext ); 5329 RtlFreeHeap( RtlGetProcessHeap(), 0, top ); 5330 top = frame; 5331 } 5332 5333 return STATUS_SUCCESS; 5334 } 5335 5336 VOID 5337 NTAPI 5338 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack) 5339 { 5340 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame; 5341 5342 /* Nothing to do if there is no stack */ 5343 if (!Stack) return; 5344 5345 /* Get the current active frame */ 5346 ActiveFrame = Stack->ActiveFrame; 5347 5348 /* Go through them in backwards order and release */ 5349 while (ActiveFrame) 5350 { 5351 PrevFrame = ActiveFrame->Previous; 5352 RtlReleaseActivationContext(ActiveFrame->ActivationContext); 5353 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame); 5354 ActiveFrame = PrevFrame; 5355 } 5356 5357 /* Zero out the active frame */ 5358 Stack->ActiveFrame = NULL; 5359 5360 /* TODO: Empty the Frame List Cache */ 5361 ASSERT(IsListEmpty(&Stack->FrameListCache)); 5362 5363 /* Free activation stack memory */ 5364 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack); 5365 } 5366 5367 /****************************************************************** 5368 * RtlFreeThreadActivationContextStack (NTDLL.@) 5369 */ 5370 VOID NTAPI RtlFreeThreadActivationContextStack(VOID) 5371 { 5372 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer); 5373 NtCurrentTeb()->ActivationContextStackPointer = NULL; 5374 } 5375 5376 5377 /****************************************************************** 5378 * RtlGetActiveActivationContext (NTDLL.@) 5379 */ 5380 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle ) 5381 { 5382 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5383 { 5384 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 5385 RtlAddRefActivationContext( *handle ); 5386 } 5387 else 5388 *handle = 0; 5389 5390 return STATUS_SUCCESS; 5391 } 5392 5393 5394 /****************************************************************** 5395 * RtlIsActivationContextActive (NTDLL.@) 5396 */ 5397 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle ) 5398 { 5399 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5400 5401 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous) 5402 if (frame->ActivationContext == handle) return TRUE; 5403 return FALSE; 5404 } 5405 5406 5407 /*********************************************************************** 5408 * RtlQueryInformationActivationContext (NTDLL.@) 5409 * 5410 * Get information about an activation context. 5411 * FIXME: function signature/prototype may be wrong 5412 */ 5413 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, 5414 ULONG class, PVOID buffer, 5415 SIZE_T bufsize, SIZE_T *retlen ) 5416 { 5417 ACTIVATION_CONTEXT *actctx; 5418 NTSTATUS status; 5419 5420 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle, 5421 subinst, class, buffer, bufsize, retlen); 5422 5423 if (retlen) *retlen = 0; 5424 if ((status = find_query_actctx( &handle, flags, class ))) return status; 5425 5426 switch (class) 5427 { 5428 case ActivationContextBasicInformation: 5429 { 5430 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; 5431 5432 if (retlen) *retlen = sizeof(*info); 5433 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; 5434 5435 info->hActCtx = handle; 5436 info->dwFlags = 0; /* FIXME */ 5437 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle); 5438 } 5439 break; 5440 5441 case ActivationContextDetailedInformation: 5442 { 5443 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; 5444 struct assembly *assembly = NULL; 5445 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; 5446 LPWSTR ptr; 5447 5448 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5449 5450 if (actctx->num_assemblies) assembly = actctx->assemblies; 5451 5452 if (assembly && assembly->manifest.info) 5453 manifest_len = strlenW(assembly->manifest.info) + 1; 5454 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1; 5455 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1; 5456 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); 5457 5458 if (retlen) *retlen = len; 5459 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5460 5461 acdi->dwFlags = 0; 5462 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ 5463 acdi->ulAssemblyCount = actctx->num_assemblies; 5464 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; 5465 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0; 5466 acdi->ulRootConfigurationPathType = actctx->config.type; 5467 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0; 5468 acdi->ulAppDirPathType = actctx->appdir.type; 5469 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0; 5470 ptr = (LPWSTR)(acdi + 1); 5471 if (manifest_len) 5472 { 5473 acdi->lpRootManifestPath = ptr; 5474 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); 5475 ptr += manifest_len; 5476 } 5477 else acdi->lpRootManifestPath = NULL; 5478 if (config_len) 5479 { 5480 acdi->lpRootConfigurationPath = ptr; 5481 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); 5482 ptr += config_len; 5483 } 5484 else acdi->lpRootConfigurationPath = NULL; 5485 if (appdir_len) 5486 { 5487 acdi->lpAppDirPath = ptr; 5488 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); 5489 } 5490 else acdi->lpAppDirPath = NULL; 5491 } 5492 break; 5493 5494 case AssemblyDetailedInformationInActivationContext: 5495 { 5496 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; 5497 struct assembly *assembly; 5498 WCHAR *assembly_id; 5499 DWORD index; 5500 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; 5501 LPWSTR ptr; 5502 5503 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5504 if (!subinst) return STATUS_INVALID_PARAMETER; 5505 5506 index = *(DWORD*)subinst; 5507 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; 5508 5509 assembly = &actctx->assemblies[index - 1]; 5510 5511 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; 5512 id_len = strlenW(assembly_id) + 1; 5513 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1; 5514 5515 if (assembly->manifest.info && 5516 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST)) 5517 path_len = strlenW(assembly->manifest.info) + 1; 5518 5519 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); 5520 5521 if (retlen) *retlen = len; 5522 if (!buffer || bufsize < len) 5523 { 5524 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5525 return STATUS_BUFFER_TOO_SMALL; 5526 } 5527 5528 afdi->ulFlags = 0; /* FIXME */ 5529 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR); 5530 afdi->ulManifestPathType = assembly->manifest.type; 5531 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0; 5532 /* FIXME afdi->liManifestLastWriteTime = 0; */ 5533 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ 5534 afdi->ulPolicyPathLength = 0; 5535 /* FIXME afdi->liPolicyLastWriteTime = 0; */ 5536 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ 5537 afdi->ulManifestVersionMajor = 1; 5538 afdi->ulManifestVersionMinor = 0; 5539 afdi->ulPolicyVersionMajor = 0; /* FIXME */ 5540 afdi->ulPolicyVersionMinor = 0; /* FIXME */ 5541 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0; 5542 ptr = (LPWSTR)(afdi + 1); 5543 afdi->lpAssemblyEncodedAssemblyIdentity = ptr; 5544 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); 5545 ptr += id_len; 5546 if (path_len) 5547 { 5548 afdi->lpAssemblyManifestPath = ptr; 5549 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); 5550 ptr += path_len; 5551 } else afdi->lpAssemblyManifestPath = NULL; 5552 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ 5553 if (ad_len) 5554 { 5555 afdi->lpAssemblyDirectoryName = ptr; 5556 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); 5557 } 5558 else afdi->lpAssemblyDirectoryName = NULL; 5559 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5560 } 5561 break; 5562 5563 case FileInformationInAssemblyOfAssemblyInActivationContext: 5564 { 5565 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; 5566 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; 5567 struct assembly *assembly; 5568 struct dll_redirect *dll; 5569 SIZE_T len, dll_len = 0; 5570 LPWSTR ptr; 5571 5572 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5573 if (!acqi) return STATUS_INVALID_PARAMETER; 5574 5575 if (acqi->ulAssemblyIndex >= actctx->num_assemblies) 5576 return STATUS_INVALID_PARAMETER; 5577 assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; 5578 5579 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) 5580 return STATUS_INVALID_PARAMETER; 5581 dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; 5582 5583 if (dll->name) dll_len = strlenW(dll->name) + 1; 5584 len = sizeof(*afdi) + dll_len * sizeof(WCHAR); 5585 5586 if (!buffer || bufsize < len) 5587 { 5588 if (retlen) *retlen = len; 5589 return STATUS_BUFFER_TOO_SMALL; 5590 } 5591 if (retlen) *retlen = 0; /* yes that's what native does !! */ 5592 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; 5593 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0; 5594 afdi->ulPathLength = 0; /* FIXME */ 5595 ptr = (LPWSTR)(afdi + 1); 5596 if (dll_len) 5597 { 5598 afdi->lpFileName = ptr; 5599 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); 5600 } else afdi->lpFileName = NULL; 5601 afdi->lpFilePath = NULL; /* FIXME */ 5602 } 5603 break; 5604 5605 case CompatibilityInformationInActivationContext: 5606 { 5607 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer; 5608 COMPATIBILITY_CONTEXT_ELEMENT *elements; 5609 struct assembly *assembly = NULL; 5610 ULONG num_compat_contexts = 0, n; 5611 SIZE_T len; 5612 5613 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5614 5615 if (actctx->num_assemblies) assembly = actctx->assemblies; 5616 5617 if (assembly) 5618 num_compat_contexts = assembly->num_compat_contexts; 5619 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); 5620 5621 if (retlen) *retlen = len; 5622 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5623 5624 *acci = num_compat_contexts; 5625 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1); 5626 for (n = 0; n < num_compat_contexts; ++n) 5627 { 5628 elements[n] = assembly->compat_contexts[n]; 5629 } 5630 } 5631 break; 5632 5633 case RunlevelInformationInActivationContext: 5634 { 5635 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer; 5636 struct assembly *assembly; 5637 SIZE_T len; 5638 5639 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5640 5641 len = sizeof(*acrli); 5642 if (retlen) *retlen = len; 5643 if (!buffer || bufsize < len) 5644 return STATUS_BUFFER_TOO_SMALL; 5645 5646 assembly = actctx->assemblies; 5647 5648 acrli->ulFlags = 0; 5649 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED; 5650 acrli->UiAccess = assembly ? assembly->ui_access : 0; 5651 } 5652 break; 5653 5654 default: 5655 DPRINT( "class %u not implemented\n", class ); 5656 return STATUS_NOT_IMPLEMENTED; 5657 } 5658 return STATUS_SUCCESS; 5659 } 5660 5661 NTSTATUS 5662 NTAPI 5663 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, 5664 PVOID pvBuffer, 5665 SIZE_T cbBuffer OPTIONAL, 5666 SIZE_T *pcbWrittenOrRequired OPTIONAL) 5667 { 5668 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT, 5669 NULL, 5670 NULL, 5671 ulInfoClass, 5672 pvBuffer, 5673 cbBuffer, 5674 pcbWrittenOrRequired); 5675 } 5676 5677 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002 5678 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004 5679 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5680 5681 NTSTATUS 5682 NTAPI 5683 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, 5684 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) 5685 { 5686 /* Check general parameter combinations */ 5687 if (!section_name || !section_name->Buffer || 5688 (flags & ~FIND_ACTCTX_VALID_MASK) || 5689 ((flags & FIND_ACTCTX_VALID_MASK) && !data) || 5690 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) 5691 { 5692 DPRINT1("invalid parameter\n"); 5693 return STATUS_INVALID_PARAMETER; 5694 } 5695 5696 /* TODO */ 5697 if (flags & FIND_ACTCTX_RETURN_FLAGS || 5698 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5699 { 5700 DPRINT1("unknown flags %08x\n", flags); 5701 return STATUS_INVALID_PARAMETER; 5702 } 5703 5704 return STATUS_SUCCESS; 5705 } 5706 5707 /*********************************************************************** 5708 * RtlFindActivationContextSectionString (NTDLL.@) 5709 * 5710 * Find information about a string in an activation context. 5711 * FIXME: function signature/prototype may be wrong 5712 */ 5713 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, 5714 const UNICODE_STRING *section_name, PVOID ptr ) 5715 { 5716 PACTCTX_SECTION_KEYED_DATA data = ptr; 5717 NTSTATUS status; 5718 5719 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr); 5720 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data); 5721 if (!NT_SUCCESS(status)) 5722 { 5723 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status); 5724 return status; 5725 } 5726 5727 status = STATUS_SXS_KEY_NOT_FOUND; 5728 5729 /* if there is no data, but params are valid, 5730 we return that sxs key is not found to be at least somehow compatible */ 5731 if (!data) 5732 { 5733 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status); 5734 return status; 5735 } 5736 5737 ASSERT(NtCurrentTeb()); 5738 ASSERT(NtCurrentTeb()->ActivationContextStackPointer); 5739 5740 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame); 5741 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5742 { 5743 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5744 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); 5745 } 5746 5747 DPRINT("status %x\n", status); 5748 if (status != STATUS_SUCCESS) 5749 status = find_string( process_actctx, section_kind, section_name, flags, data ); 5750 5751 if (status != STATUS_SUCCESS) 5752 status = find_string( implicit_actctx, section_kind, section_name, flags, data ); 5753 5754 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status); 5755 return status; 5756 } 5757 5758 /*********************************************************************** 5759 * RtlFindActivationContextSectionGuid (NTDLL.@) 5760 * 5761 * Find information about a GUID in an activation context. 5762 * FIXME: function signature/prototype may be wrong 5763 */ 5764 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind, 5765 const GUID *guid, void *ptr ) 5766 { 5767 ACTCTX_SECTION_KEYED_DATA *data = ptr; 5768 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; 5769 5770 if (extguid) 5771 { 5772 DPRINT1("expected extguid == NULL\n"); 5773 return STATUS_INVALID_PARAMETER; 5774 } 5775 5776 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5777 { 5778 DPRINT1("unknown flags %08x\n", flags); 5779 return STATUS_INVALID_PARAMETER; 5780 } 5781 5782 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid) 5783 return STATUS_INVALID_PARAMETER; 5784 5785 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5786 { 5787 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5788 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data ); 5789 } 5790 5791 if (status != STATUS_SUCCESS) 5792 status = find_guid( process_actctx, section_kind, guid, flags, data ); 5793 5794 if (status != STATUS_SUCCESS) 5795 status = find_guid( implicit_actctx, section_kind, guid, flags, data ); 5796 5797 return status; 5798 } 5799 5800 /* Stubs */ 5801 5802 NTSTATUS 5803 NTAPI 5804 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack) 5805 { 5806 PACTIVATION_CONTEXT_STACK ContextStack; 5807 5808 /* Check if it's already allocated */ 5809 if (*Stack) return STATUS_SUCCESS; 5810 5811 /* Allocate space for the context stack */ 5812 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK)); 5813 if (!ContextStack) 5814 { 5815 return STATUS_NO_MEMORY; 5816 } 5817 5818 /* Initialize the context stack */ 5819 ContextStack->Flags = 0; 5820 ContextStack->ActiveFrame = NULL; 5821 InitializeListHead(&ContextStack->FrameListCache); 5822 ContextStack->NextCookieSequenceNumber = 1; 5823 ContextStack->StackId = 1; //TODO: Timer-based 5824 5825 *Stack = ContextStack; 5826 5827 return STATUS_SUCCESS; 5828 } 5829 5830 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 5831 FASTCALL 5832 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, 5833 IN PVOID Context) 5834 { 5835 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame; 5836 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame; 5837 5838 /* Get the current active frame */ 5839 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5840 5841 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5842 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame, 5843 &Frame->Frame, Context); 5844 5845 /* Ensure it's in the right format and at least fits basic info */ 5846 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 5847 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 5848 5849 /* Set debug info if size allows*/ 5850 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 5851 { 5852 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame); 5853 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context); 5854 //Frame->Extra3 = ...; 5855 } 5856 5857 if (ActiveFrame) 5858 { 5859 /*ASSERT((ActiveFrame->Flags & 5860 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | 5861 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED | 5862 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/ 5863 5864 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED)) 5865 { 5866 // TODO: Perform some additional checks if it was not heap allocated 5867 } 5868 } 5869 5870 /* Save pointer to the new activation frame */ 5871 NewFrame = &Frame->Frame; 5872 5873 /* Actually activate it */ 5874 Frame->Frame.Previous = ActiveFrame; 5875 Frame->Frame.ActivationContext = Context; 5876 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED; 5877 5878 /* Check if we can activate this context */ 5879 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) || 5880 Context) 5881 { 5882 /* Set new active frame */ 5883 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame); 5884 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5885 return NewFrame; 5886 } 5887 5888 /* We can get here only one way: it was already activated */ 5889 DPRINT("Trying to activate already activated activation context\n"); 5890 5891 /* Activate only if we are allowing multiple activation */ 5892 #if 0 5893 if (!RtlpNotAllowingMultipleActivation) 5894 { 5895 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED; 5896 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5897 } 5898 #else 5899 // Activate it anyway 5900 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5901 #endif 5902 5903 /* Return pointer to the activation frame */ 5904 return NewFrame; 5905 } 5906 5907 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 5908 FASTCALL 5909 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) 5910 { 5911 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame; 5912 5913 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5914 5915 /* Ensure it's in the right format and at least fits basic info */ 5916 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 5917 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 5918 5919 /* Make sure it is not deactivated and it is activated */ 5920 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0); 5921 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 5922 ASSERT((Frame->Frame.Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 5923 5924 /* Check debug info if it is present */ 5925 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 5926 { 5927 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous)); 5928 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext)); 5929 //Frame->Extra3 = ...; 5930 } 5931 5932 if (ActiveFrame) 5933 { 5934 // TODO: Perform some additional checks here 5935 } 5936 5937 /* Special handling for not-really-activated */ 5938 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED) 5939 { 5940 DPRINT1("Deactivating not really activated activation context\n"); 5941 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 5942 return &Frame->Frame; 5943 } 5944 5945 /* find the right frame */ 5946 NewFrame = &Frame->Frame; 5947 if (ActiveFrame != NewFrame) 5948 { 5949 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame); 5950 } 5951 5952 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5953 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous); 5954 5955 /* Pop everything up to and including frame */ 5956 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous; 5957 5958 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 5959 return NewFrame->Previous; 5960 } 5961