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 _Must_inspect_result_ 3844 static 3845 NTSTATUS 3846 build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 3847 { 3848 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0; 3849 struct guidsection_header *header; 3850 ULONG module_offset, data_offset; 3851 struct tlibredirect_data *data; 3852 struct guid_index *index; 3853 3854 /* compute section length */ 3855 for (i = 0; i < actctx->num_assemblies; i++) 3856 { 3857 struct assembly *assembly = &actctx->assemblies[i]; 3858 for (j = 0; j < assembly->num_dlls; j++) 3859 { 3860 struct dll_redirect *dll = &assembly->dlls[j]; 3861 for (k = 0; k < dll->entities.num; k++) 3862 { 3863 struct entity *entity = &dll->entities.base[k]; 3864 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3865 { 3866 /* each entry needs index, data and string data for module name and help string */ 3867 total_len += sizeof(*index); 3868 total_len += sizeof(*data); 3869 /* help string is stored separately */ 3870 if (*entity->u.typelib.helpdir) 3871 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR)); 3872 3873 /* module names are packed one after another */ 3874 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 3875 3876 tlib_count++; 3877 } 3878 } 3879 } 3880 } 3881 3882 total_len += aligned_string_len(names_len); 3883 total_len += sizeof(*header); 3884 3885 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3886 if (!header) return STATUS_NO_MEMORY; 3887 3888 memset(header, 0, sizeof(*header)); 3889 header->magic = GUIDSECTION_MAGIC; 3890 header->size = sizeof(*header); 3891 header->count = tlib_count; 3892 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 3893 index = (struct guid_index*)((BYTE*)header + header->index_offset); 3894 module_offset = sizeof(*header); 3895 data_offset = header->index_offset + tlib_count*sizeof(*index); 3896 3897 for (i = 0; i < actctx->num_assemblies; i++) 3898 { 3899 struct assembly *assembly = &actctx->assemblies[i]; 3900 for (j = 0; j < assembly->num_dlls; j++) 3901 { 3902 struct dll_redirect *dll = &assembly->dlls[j]; 3903 for (k = 0; k < dll->entities.num; k++) 3904 { 3905 struct entity *entity = &dll->entities.base[k]; 3906 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3907 { 3908 ULONG module_len, help_len; 3909 UNICODE_STRING str; 3910 WCHAR *ptrW; 3911 NTSTATUS Status; 3912 3913 if (*entity->u.typelib.helpdir) 3914 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR); 3915 else 3916 help_len = 0; 3917 3918 module_len = strlenW(dll->name)*sizeof(WCHAR); 3919 3920 /* setup new index entry */ 3921 RtlInitUnicodeString(&str, entity->u.typelib.tlbid); 3922 Status = RtlGUIDFromString(&str, &index->guid); 3923 if (!NT_SUCCESS(Status)) 3924 { 3925 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 3926 return Status; 3927 } 3928 index->data_offset = data_offset; 3929 index->data_len = sizeof(*data) + aligned_string_len(help_len); 3930 index->rosterindex = i + 1; 3931 3932 /* setup data */ 3933 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset); 3934 data->size = sizeof(*data); 3935 data->res = 0; 3936 data->name_len = module_len; 3937 data->name_offset = module_offset; 3938 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */ 3939 data->langid = 0; 3940 data->flags = entity->u.typelib.flags; 3941 data->help_len = help_len; 3942 data->help_offset = sizeof(*data); 3943 data->major_version = entity->u.typelib.major; 3944 data->minor_version = entity->u.typelib.minor; 3945 3946 /* module name */ 3947 ptrW = (WCHAR*)((BYTE*)header + data->name_offset); 3948 memcpy(ptrW, dll->name, data->name_len); 3949 ptrW[data->name_len/sizeof(WCHAR)] = 0; 3950 3951 /* help string */ 3952 if (data->help_len) 3953 { 3954 ptrW = (WCHAR*)((BYTE*)data + data->help_offset); 3955 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len); 3956 ptrW[data->help_len/sizeof(WCHAR)] = 0; 3957 } 3958 3959 data_offset += sizeof(*data); 3960 if (help_len) 3961 data_offset += aligned_string_len(help_len + sizeof(WCHAR)); 3962 3963 module_offset += module_len + sizeof(WCHAR); 3964 3965 index++; 3966 } 3967 } 3968 } 3969 } 3970 3971 *section = header; 3972 3973 return STATUS_SUCCESS; 3974 } 3975 3976 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 3977 { 3978 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset); 3979 } 3980 3981 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 3982 { 3983 struct guid_index *index = NULL; 3984 struct tlibredirect_data *tlib; 3985 3986 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3987 3988 if (!actctx->tlib_section) 3989 { 3990 struct guidsection_header *section; 3991 3992 NTSTATUS status = build_tlib_section(actctx, §ion); 3993 if (status) return status; 3994 3995 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL)) 3996 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3997 } 3998 3999 index = find_guid_index(actctx->tlib_section, guid); 4000 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4001 4002 tlib = get_tlib_data(actctx, index); 4003 4004 data->ulDataFormatVersion = 1; 4005 data->lpData = tlib; 4006 /* full length includes string length with nulls */ 4007 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR); 4008 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset; 4009 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len; 4010 data->lpSectionBase = actctx->tlib_section; 4011 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section ); 4012 data->hActCtx = NULL; 4013 4014 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4015 data->ulAssemblyRosterIndex = index->rosterindex; 4016 4017 return STATUS_SUCCESS; 4018 } 4019 4020 static void generate_uuid(ULONG *seed, GUID *guid) 4021 { 4022 ULONG *ptr = (ULONG*)guid; 4023 int i; 4024 4025 /* GUID is 16 bytes long */ 4026 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++) 4027 *ptr = RtlUniform(seed); 4028 4029 guid->Data3 &= 0x0fff; 4030 guid->Data3 |= (4 << 12); 4031 guid->Data4[0] &= 0x3f; 4032 guid->Data4[0] |= 0x80; 4033 } 4034 4035 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll, 4036 unsigned int *count, unsigned int *len, unsigned int *module_len) 4037 { 4038 unsigned int i; 4039 4040 for (i = 0; i < entities->num; i++) 4041 { 4042 struct entity *entity = &entities->base[i]; 4043 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4044 { 4045 /* each entry needs two index entries, extra one goes for alias GUID */ 4046 *len += 2*sizeof(struct guid_index); 4047 /* To save some memory we don't allocated two data structures, 4048 instead alias index and normal index point to the same data structure. */ 4049 *len += sizeof(struct comclassredirect_data); 4050 4051 /* for clrClass store some more */ 4052 if (entity->u.comclass.name) 4053 { 4054 unsigned int str_len; 4055 4056 /* all string data is stored together in aligned block */ 4057 str_len = strlenW(entity->u.comclass.name)+1; 4058 if (entity->u.comclass.progid) 4059 str_len += strlenW(entity->u.comclass.progid)+1; 4060 if (entity->u.comclass.version) 4061 str_len += strlenW(entity->u.comclass.version)+1; 4062 4063 *len += sizeof(struct clrclass_data); 4064 *len += aligned_string_len(str_len*sizeof(WCHAR)); 4065 4066 /* module name is forced to mscoree.dll, and stored two times with different case */ 4067 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W); 4068 } 4069 else 4070 { 4071 /* progid string is stored separately */ 4072 if (entity->u.comclass.progid) 4073 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4074 4075 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 4076 } 4077 4078 *count += 1; 4079 } 4080 } 4081 } 4082 4083 _Must_inspect_result_ 4084 static 4085 NTSTATUS 4086 add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities, 4087 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset, 4088 ULONG *seed, ULONG rosterindex) 4089 { 4090 unsigned int i; 4091 NTSTATUS Status; 4092 4093 for (i = 0; i < entities->num; i++) 4094 { 4095 struct entity *entity = &entities->base[i]; 4096 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4097 { 4098 ULONG module_len, progid_len, str_len = 0; 4099 struct comclassredirect_data *data; 4100 struct guid_index *alias_index; 4101 struct clrclass_data *clrdata; 4102 UNICODE_STRING str; 4103 WCHAR *ptrW; 4104 4105 if (entity->u.comclass.progid) 4106 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR); 4107 else 4108 progid_len = 0; 4109 4110 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR); 4111 4112 /* setup new index entry */ 4113 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4114 Status = RtlGUIDFromString(&str, &(*index)->guid); 4115 if (!NT_SUCCESS(Status)) 4116 return Status; 4117 4118 (*index)->data_offset = *data_offset; 4119 (*index)->data_len = sizeof(*data); /* additional length added later */ 4120 (*index)->rosterindex = rosterindex; 4121 4122 /* Setup new index entry for alias guid. Alias index records are placed after 4123 normal records, so normal guids are hit first on search. Note that class count 4124 is doubled. */ 4125 alias_index = (*index) + section->count/2; 4126 generate_uuid(seed, &alias_index->guid); 4127 alias_index->data_offset = (*index)->data_offset; 4128 alias_index->data_len = 0; 4129 alias_index->rosterindex = (*index)->rosterindex; 4130 4131 /* setup data */ 4132 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset); 4133 data->size = sizeof(*data); 4134 data->res = 0; 4135 data->res1[0] = 0; 4136 data->res1[1] = 0; 4137 data->model = entity->u.comclass.model; 4138 data->clsid = (*index)->guid; 4139 data->alias = alias_index->guid; 4140 data->clsid2 = data->clsid; 4141 if (entity->u.comclass.tlbid) 4142 { 4143 RtlInitUnicodeString(&str, entity->u.comclass.tlbid); 4144 Status = RtlGUIDFromString(&str, &data->tlbid); 4145 if (!NT_SUCCESS(Status)) 4146 return Status; 4147 } 4148 else 4149 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4150 data->name_len = module_len; 4151 data->name_offset = *module_offset; 4152 data->progid_len = progid_len; 4153 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */ 4154 data->clrdata_len = 0; /* will be set later */ 4155 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0; 4156 data->miscstatus = entity->u.comclass.miscstatus; 4157 data->miscstatuscontent = entity->u.comclass.miscstatuscontent; 4158 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail; 4159 data->miscstatusicon = entity->u.comclass.miscstatusicon; 4160 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint; 4161 4162 /* mask describes which misc* data is available */ 4163 data->miscmask = 0; 4164 if (data->miscstatus) 4165 data->miscmask |= MiscStatus; 4166 if (data->miscstatuscontent) 4167 data->miscmask |= MiscStatusContent; 4168 if (data->miscstatusthumbnail) 4169 data->miscmask |= MiscStatusThumbnail; 4170 if (data->miscstatusicon) 4171 data->miscmask |= MiscStatusIcon; 4172 if (data->miscstatusdocprint) 4173 data->miscmask |= MiscStatusDocPrint; 4174 4175 if (data->clrdata_offset) 4176 { 4177 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset); 4178 4179 clrdata->size = sizeof(*clrdata); 4180 clrdata->res[0] = 0; 4181 clrdata->res[1] = 2; /* FIXME: unknown field */ 4182 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR); 4183 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR); 4184 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR); 4185 clrdata->name_offset = clrdata->size; 4186 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0; 4187 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0; 4188 clrdata->res2[0] = 0; 4189 clrdata->res2[1] = 0; 4190 4191 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR); 4192 4193 /* module name */ 4194 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset); 4195 memcpy(ptrW, mscoree2W, clrdata->module_len); 4196 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0; 4197 4198 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4199 memcpy(ptrW, mscoreeW, data->name_len); 4200 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4201 4202 /* class name */ 4203 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset); 4204 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len); 4205 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0; 4206 4207 /* runtime version, optional */ 4208 if (clrdata->version_len) 4209 { 4210 data->clrdata_len += clrdata->version_len + sizeof(WCHAR); 4211 4212 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset); 4213 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len); 4214 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0; 4215 } 4216 4217 if (data->progid_len) 4218 data->progid_offset += data->clrdata_len; 4219 (*index)->data_len += sizeof(*clrdata); 4220 } 4221 else 4222 { 4223 clrdata = NULL; 4224 4225 /* module name */ 4226 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4227 memcpy(ptrW, dll->name, data->name_len); 4228 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4229 } 4230 4231 /* progid string */ 4232 if (data->progid_len) 4233 { 4234 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset); 4235 memcpy(ptrW, entity->u.comclass.progid, data->progid_len); 4236 ptrW[data->progid_len/sizeof(WCHAR)] = 0; 4237 } 4238 4239 /* string block length */ 4240 str_len = 0; 4241 if (clrdata) 4242 { 4243 str_len += clrdata->name_len + sizeof(WCHAR); 4244 if (clrdata->version_len) 4245 str_len += clrdata->version_len + sizeof(WCHAR); 4246 } 4247 if (progid_len) 4248 str_len += progid_len + sizeof(WCHAR); 4249 4250 (*index)->data_len += aligned_string_len(str_len); 4251 alias_index->data_len = (*index)->data_len; 4252 4253 /* move to next data record */ 4254 (*data_offset) += sizeof(*data) + aligned_string_len(str_len); 4255 (*module_offset) += module_len + sizeof(WCHAR); 4256 4257 if (clrdata) 4258 { 4259 (*data_offset) += sizeof(*clrdata); 4260 (*module_offset) += clrdata->module_len + sizeof(WCHAR); 4261 } 4262 (*index) += 1; 4263 } 4264 } 4265 4266 return STATUS_SUCCESS; 4267 } 4268 4269 _Must_inspect_result_ 4270 static 4271 NTSTATUS 4272 build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4273 { 4274 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0; 4275 struct guidsection_header *header; 4276 ULONG module_offset, data_offset; 4277 struct guid_index *index; 4278 ULONG seed; 4279 NTSTATUS Status; 4280 4281 /* compute section length */ 4282 for (i = 0; i < actctx->num_assemblies; i++) 4283 { 4284 struct assembly *assembly = &actctx->assemblies[i]; 4285 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len); 4286 for (j = 0; j < assembly->num_dlls; j++) 4287 { 4288 struct dll_redirect *dll = &assembly->dlls[j]; 4289 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len); 4290 } 4291 } 4292 4293 total_len += aligned_string_len(names_len); 4294 total_len += sizeof(*header); 4295 4296 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4297 if (!header) return STATUS_NO_MEMORY; 4298 4299 memset(header, 0, sizeof(*header)); 4300 header->magic = GUIDSECTION_MAGIC; 4301 header->size = sizeof(*header); 4302 header->count = 2*class_count; 4303 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 4304 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4305 module_offset = sizeof(*header); 4306 data_offset = header->index_offset + 2*class_count*sizeof(*index); 4307 4308 seed = NtGetTickCount(); 4309 for (i = 0; i < actctx->num_assemblies; i++) 4310 { 4311 struct assembly *assembly = &actctx->assemblies[i]; 4312 Status = add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1); 4313 if (!NT_SUCCESS(Status)) 4314 { 4315 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4316 return Status; 4317 } 4318 for (j = 0; j < assembly->num_dlls; j++) 4319 { 4320 struct dll_redirect *dll = &assembly->dlls[j]; 4321 Status = add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1); 4322 if (!NT_SUCCESS(Status)) 4323 { 4324 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4325 return Status; 4326 } 4327 } 4328 } 4329 4330 *section = header; 4331 4332 return STATUS_SUCCESS; 4333 } 4334 4335 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4336 { 4337 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset); 4338 } 4339 4340 _Must_inspect_result_ 4341 static 4342 NTSTATUS 4343 find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4344 { 4345 struct comclassredirect_data *comclass; 4346 struct guid_index *index = NULL; 4347 4348 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4349 4350 if (!actctx->comserver_section) 4351 { 4352 struct guidsection_header *section; 4353 4354 NTSTATUS status = build_comserver_section(actctx, §ion); 4355 if (status) return status; 4356 4357 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4358 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4359 } 4360 4361 index = find_guid_index(actctx->comserver_section, guid); 4362 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4363 4364 comclass = get_comclass_data(actctx, index); 4365 4366 data->ulDataFormatVersion = 1; 4367 data->lpData = comclass; 4368 /* full length includes string length with nulls */ 4369 data->ulLength = comclass->size + comclass->clrdata_len; 4370 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR); 4371 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset; 4372 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len; 4373 data->lpSectionBase = actctx->comserver_section; 4374 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section ); 4375 data->hActCtx = NULL; 4376 4377 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4378 data->ulAssemblyRosterIndex = index->rosterindex; 4379 4380 return STATUS_SUCCESS; 4381 } 4382 4383 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len) 4384 { 4385 unsigned int i; 4386 4387 for (i = 0; i < entities->num; i++) 4388 { 4389 struct entity *entity = &entities->base[i]; 4390 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4391 { 4392 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data); 4393 if (entity->u.ifaceps.name) 4394 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR)); 4395 *count += 1; 4396 } 4397 } 4398 } 4399 4400 _Must_inspect_result_ 4401 static 4402 NTSTATUS 4403 add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities, 4404 struct guid_index **index, ULONG *data_offset, ULONG rosterindex) 4405 { 4406 unsigned int i; 4407 4408 for (i = 0; i < entities->num; i++) 4409 { 4410 struct entity *entity = &entities->base[i]; 4411 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4412 { 4413 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset); 4414 UNICODE_STRING str; 4415 ULONG name_len; 4416 NTSTATUS Status; 4417 4418 if (entity->u.ifaceps.name) 4419 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR); 4420 else 4421 name_len = 0; 4422 4423 /* setup index */ 4424 RtlInitUnicodeString(&str, entity->u.ifaceps.iid); 4425 Status = RtlGUIDFromString(&str, &(*index)->guid); 4426 if (!NT_SUCCESS(Status)) 4427 return Status; 4428 (*index)->data_offset = *data_offset; 4429 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0; 4430 (*index)->rosterindex = rosterindex; 4431 4432 /* setup data record */ 4433 data->size = sizeof(*data); 4434 data->mask = entity->u.ifaceps.mask; 4435 4436 /* proxyStubClsid32 value is only stored for external PS, 4437 if set it's used as iid, otherwise 'iid' attribute value is used */ 4438 if (entity->u.ifaceps.ps32) 4439 { 4440 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32); 4441 Status = RtlGUIDFromString(&str, &data->iid); 4442 if (!NT_SUCCESS(Status)) 4443 return Status; 4444 } 4445 else 4446 data->iid = (*index)->guid; 4447 4448 data->nummethods = entity->u.ifaceps.nummethods; 4449 4450 if (entity->u.ifaceps.tlib) 4451 { 4452 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib); 4453 Status = RtlGUIDFromString(&str, &data->tlbid); 4454 if (!NT_SUCCESS(Status)) 4455 return Status; 4456 } 4457 else 4458 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4459 4460 if (entity->u.ifaceps.base) 4461 { 4462 RtlInitUnicodeString(&str, entity->u.ifaceps.base); 4463 Status = RtlGUIDFromString(&str, &data->base); 4464 if (!NT_SUCCESS(Status)) 4465 return Status; 4466 } 4467 else 4468 memset(&data->base, 0, sizeof(data->base)); 4469 4470 data->name_len = name_len; 4471 data->name_offset = data->name_len ? sizeof(*data) : 0; 4472 4473 /* name string */ 4474 if (data->name_len) 4475 { 4476 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4477 memcpy(ptrW, entity->u.ifaceps.name, data->name_len); 4478 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4479 } 4480 4481 /* move to next record */ 4482 (*index) += 1; 4483 *data_offset += sizeof(*data); 4484 if (data->name_len) 4485 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR)); 4486 } 4487 } 4488 4489 return STATUS_SUCCESS; 4490 } 4491 4492 _Must_inspect_result_ 4493 static 4494 NTSTATUS 4495 build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4496 { 4497 unsigned int i, j, total_len = 0, count = 0; 4498 struct guidsection_header *header; 4499 struct guid_index *index; 4500 ULONG data_offset; 4501 4502 /* compute section length */ 4503 for (i = 0; i < actctx->num_assemblies; i++) 4504 { 4505 struct assembly *assembly = &actctx->assemblies[i]; 4506 4507 get_ifaceps_datalen(&assembly->entities, &count, &total_len); 4508 for (j = 0; j < assembly->num_dlls; j++) 4509 { 4510 struct dll_redirect *dll = &assembly->dlls[j]; 4511 get_ifaceps_datalen(&dll->entities, &count, &total_len); 4512 } 4513 } 4514 4515 total_len += sizeof(*header); 4516 4517 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4518 if (!header) return STATUS_NO_MEMORY; 4519 4520 memset(header, 0, sizeof(*header)); 4521 header->magic = GUIDSECTION_MAGIC; 4522 header->size = sizeof(*header); 4523 header->count = count; 4524 header->index_offset = sizeof(*header); 4525 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4526 data_offset = header->index_offset + count*sizeof(*index); 4527 4528 for (i = 0; i < actctx->num_assemblies; i++) 4529 { 4530 struct assembly *assembly = &actctx->assemblies[i]; 4531 NTSTATUS Status; 4532 4533 Status = add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1); 4534 if (!NT_SUCCESS(Status)) 4535 { 4536 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4537 return Status; 4538 } 4539 4540 for (j = 0; j < assembly->num_dlls; j++) 4541 { 4542 struct dll_redirect *dll = &assembly->dlls[j]; 4543 Status = add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1); 4544 if (!NT_SUCCESS(Status)) 4545 { 4546 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4547 return Status; 4548 } 4549 } 4550 } 4551 4552 *section = header; 4553 4554 return STATUS_SUCCESS; 4555 } 4556 4557 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4558 { 4559 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset); 4560 } 4561 4562 _Must_inspect_result_ 4563 static 4564 NTSTATUS 4565 find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4566 { 4567 struct ifacepsredirect_data *iface; 4568 struct guid_index *index = NULL; 4569 4570 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4571 4572 if (!actctx->ifaceps_section) 4573 { 4574 struct guidsection_header *section; 4575 4576 NTSTATUS status = build_ifaceps_section(actctx, §ion); 4577 if (status) return status; 4578 4579 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL)) 4580 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4581 } 4582 4583 index = find_guid_index(actctx->ifaceps_section, guid); 4584 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4585 4586 iface = get_ifaceps_data(actctx, index); 4587 4588 data->ulDataFormatVersion = 1; 4589 data->lpData = iface; 4590 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0); 4591 data->lpSectionGlobalData = NULL; 4592 data->ulSectionGlobalDataLength = 0; 4593 data->lpSectionBase = actctx->ifaceps_section; 4594 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section ); 4595 data->hActCtx = NULL; 4596 4597 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4598 data->ulAssemblyRosterIndex = index->rosterindex; 4599 4600 return STATUS_SUCCESS; 4601 } 4602 4603 _Must_inspect_result_ 4604 static 4605 NTSTATUS 4606 build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4607 { 4608 unsigned int i, j, total_len = 0, count = 0; 4609 struct guidsection_header *header; 4610 struct clrsurrogate_data *data; 4611 struct guid_index *index; 4612 ULONG data_offset; 4613 4614 /* compute section length */ 4615 for (i = 0; i < actctx->num_assemblies; i++) 4616 { 4617 struct assembly *assembly = &actctx->assemblies[i]; 4618 for (j = 0; j < assembly->entities.num; j++) 4619 { 4620 struct entity *entity = &assembly->entities.base[j]; 4621 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4622 { 4623 ULONG len; 4624 4625 total_len += sizeof(*index) + sizeof(*data); 4626 len = strlenW(entity->u.clrsurrogate.name) + 1; 4627 if (entity->u.clrsurrogate.version) 4628 len += strlenW(entity->u.clrsurrogate.version) + 1; 4629 total_len += aligned_string_len(len*sizeof(WCHAR)); 4630 4631 count++; 4632 } 4633 } 4634 } 4635 4636 total_len += sizeof(*header); 4637 4638 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4639 if (!header) return STATUS_NO_MEMORY; 4640 4641 memset(header, 0, sizeof(*header)); 4642 header->magic = GUIDSECTION_MAGIC; 4643 header->size = sizeof(*header); 4644 header->count = count; 4645 header->index_offset = sizeof(*header); 4646 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4647 data_offset = header->index_offset + count*sizeof(*index); 4648 4649 for (i = 0; i < actctx->num_assemblies; i++) 4650 { 4651 struct assembly *assembly = &actctx->assemblies[i]; 4652 for (j = 0; j < assembly->entities.num; j++) 4653 { 4654 struct entity *entity = &assembly->entities.base[j]; 4655 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4656 { 4657 ULONG version_len, name_len; 4658 UNICODE_STRING str; 4659 WCHAR *ptrW; 4660 NTSTATUS Status; 4661 4662 if (entity->u.clrsurrogate.version) 4663 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR); 4664 else 4665 version_len = 0; 4666 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR); 4667 4668 /* setup new index entry */ 4669 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid); 4670 Status = RtlGUIDFromString(&str, &index->guid); 4671 if (!NT_SUCCESS(Status)) 4672 { 4673 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4674 return Status; 4675 } 4676 4677 index->data_offset = data_offset; 4678 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0)); 4679 index->rosterindex = i + 1; 4680 4681 /* setup data */ 4682 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset); 4683 data->size = sizeof(*data); 4684 data->res = 0; 4685 data->clsid = index->guid; 4686 data->version_offset = version_len ? data->size : 0; 4687 data->version_len = version_len; 4688 data->name_offset = data->size + version_len; 4689 if (version_len) 4690 data->name_offset += sizeof(WCHAR); 4691 data->name_len = name_len; 4692 4693 /* surrogate name */ 4694 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4695 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len); 4696 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4697 4698 /* runtime version */ 4699 if (data->version_len) 4700 { 4701 ptrW = (WCHAR*)((BYTE*)data + data->version_offset); 4702 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len); 4703 ptrW[data->version_len/sizeof(WCHAR)] = 0; 4704 } 4705 4706 data_offset += index->data_offset; 4707 index++; 4708 } 4709 } 4710 } 4711 4712 *section = header; 4713 4714 return STATUS_SUCCESS; 4715 } 4716 4717 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index) 4718 { 4719 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset); 4720 } 4721 4722 _Must_inspect_result_ 4723 static 4724 NTSTATUS 4725 find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4726 { 4727 struct clrsurrogate_data *surrogate; 4728 struct guid_index *index = NULL; 4729 4730 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4731 4732 if (!actctx->clrsurrogate_section) 4733 { 4734 struct guidsection_header *section; 4735 4736 NTSTATUS status = build_clr_surrogate_section(actctx, §ion); 4737 if (status) return status; 4738 4739 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL)) 4740 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4741 } 4742 4743 index = find_guid_index(actctx->clrsurrogate_section, guid); 4744 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4745 4746 surrogate = get_surrogate_data(actctx, index); 4747 4748 data->ulDataFormatVersion = 1; 4749 data->lpData = surrogate; 4750 /* full length includes string length with nulls */ 4751 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR); 4752 if (surrogate->version_len) 4753 data->ulLength += surrogate->version_len + sizeof(WCHAR); 4754 4755 data->lpSectionGlobalData = NULL; 4756 data->ulSectionGlobalDataLength = 0; 4757 data->lpSectionBase = actctx->clrsurrogate_section; 4758 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section ); 4759 data->hActCtx = NULL; 4760 4761 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4762 data->ulAssemblyRosterIndex = index->rosterindex; 4763 4764 return STATUS_SUCCESS; 4765 } 4766 4767 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len) 4768 { 4769 unsigned int i, j, single_len; 4770 4771 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID); 4772 for (i = 0; i < entities->num; i++) 4773 { 4774 struct entity *entity = &entities->base[i]; 4775 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4776 { 4777 if (entity->u.comclass.progid) 4778 { 4779 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4780 *count += 1; 4781 } 4782 4783 for (j = 0; j < entity->u.comclass.progids.num; j++) 4784 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR)); 4785 4786 *total_len += single_len*entity->u.comclass.progids.num; 4787 *count += entity->u.comclass.progids.num; 4788 } 4789 } 4790 } 4791 4792 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias, 4793 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4794 { 4795 struct progidredirect_data *data; 4796 UNICODE_STRING str; 4797 GUID *guid_ptr; 4798 WCHAR *ptrW; 4799 4800 /* setup new index entry */ 4801 4802 /* hash progid name */ 4803 RtlInitUnicodeString(&str, progid); 4804 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash); 4805 4806 (*index)->name_offset = *data_offset; 4807 (*index)->name_len = str.Length; 4808 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength); 4809 (*index)->data_len = sizeof(*data); 4810 (*index)->rosterindex = rosterindex; 4811 4812 *data_offset += aligned_string_len(str.MaximumLength); 4813 4814 /* setup data structure */ 4815 data = (struct progidredirect_data*)((BYTE*)section + *data_offset); 4816 data->size = sizeof(*data); 4817 data->reserved = 0; 4818 data->clsid_offset = *global_offset; 4819 4820 /* write progid string */ 4821 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset); 4822 memcpy(ptrW, progid, (*index)->name_len); 4823 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0; 4824 4825 /* write guid to global area */ 4826 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset); 4827 *guid_ptr = *alias; 4828 4829 /* to next entry */ 4830 *global_offset += sizeof(GUID); 4831 *data_offset += data->size; 4832 (*index) += 1; 4833 } 4834 4835 _Must_inspect_result_ 4836 static 4837 NTSTATUS 4838 add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities, 4839 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4840 { 4841 unsigned int i, j; 4842 NTSTATUS Status; 4843 4844 for (i = 0; i < entities->num; i++) 4845 { 4846 struct entity *entity = &entities->base[i]; 4847 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4848 { 4849 const struct progids *progids = &entity->u.comclass.progids; 4850 struct comclassredirect_data *comclass; 4851 struct guid_index *guid_index; 4852 UNICODE_STRING str; 4853 GUID clsid; 4854 4855 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4856 Status = RtlGUIDFromString(&str, &clsid); 4857 if (!NT_SUCCESS(Status)) 4858 return Status; 4859 4860 guid_index = find_guid_index(actctx->comserver_section, &clsid); 4861 comclass = get_comclass_data(actctx, guid_index); 4862 4863 if (entity->u.comclass.progid) 4864 write_progid_record(section, entity->u.comclass.progid, &comclass->alias, 4865 index, data_offset, global_offset, rosterindex); 4866 4867 for (j = 0; j < progids->num; j++) 4868 write_progid_record(section, progids->progids[j], &comclass->alias, 4869 index, data_offset, global_offset, rosterindex); 4870 } 4871 } 4872 return Status; 4873 } 4874 4875 _Must_inspect_result_ 4876 static 4877 NTSTATUS 4878 build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 4879 { 4880 unsigned int i, j, total_len = 0, count = 0; 4881 struct strsection_header *header; 4882 ULONG data_offset, global_offset; 4883 struct string_index *index; 4884 NTSTATUS Status; 4885 4886 /* compute section length */ 4887 for (i = 0; i < actctx->num_assemblies; i++) 4888 { 4889 struct assembly *assembly = &actctx->assemblies[i]; 4890 4891 get_progid_datalen(&assembly->entities, &count, &total_len); 4892 for (j = 0; j < assembly->num_dlls; j++) 4893 { 4894 struct dll_redirect *dll = &assembly->dlls[j]; 4895 get_progid_datalen(&dll->entities, &count, &total_len); 4896 } 4897 } 4898 4899 total_len += sizeof(*header); 4900 4901 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4902 if (!header) return STATUS_NO_MEMORY; 4903 4904 memset(header, 0, sizeof(*header)); 4905 header->magic = STRSECTION_MAGIC; 4906 header->size = sizeof(*header); 4907 header->count = count; 4908 header->global_offset = header->size; 4909 header->global_len = count*sizeof(GUID); 4910 header->index_offset = header->size + header->global_len; 4911 4912 index = (struct string_index*)((BYTE*)header + header->index_offset); 4913 data_offset = header->index_offset + count*sizeof(*index); 4914 global_offset = header->global_offset; 4915 4916 for (i = 0; i < actctx->num_assemblies; i++) 4917 { 4918 struct assembly *assembly = &actctx->assemblies[i]; 4919 4920 Status = add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1); 4921 if (!NT_SUCCESS(Status)) 4922 { 4923 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4924 return Status; 4925 } 4926 4927 for (j = 0; j < assembly->num_dlls; j++) 4928 { 4929 struct dll_redirect *dll = &assembly->dlls[j]; 4930 Status = add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1); 4931 if (!NT_SUCCESS(Status)) 4932 { 4933 RtlFreeHeap(RtlGetProcessHeap(), 0, header); 4934 return Status; 4935 } 4936 } 4937 } 4938 4939 *section = header; 4940 4941 return STATUS_SUCCESS; 4942 } 4943 4944 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index) 4945 { 4946 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset); 4947 } 4948 4949 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 4950 PACTCTX_SECTION_KEYED_DATA data) 4951 { 4952 struct progidredirect_data *progid; 4953 struct string_index *index; 4954 4955 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4956 4957 if (!actctx->comserver_section) 4958 { 4959 struct guidsection_header *section; 4960 4961 NTSTATUS status = build_comserver_section(actctx, §ion); 4962 if (status) return status; 4963 4964 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4965 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4966 } 4967 4968 if (!actctx->progid_section) 4969 { 4970 struct strsection_header *section; 4971 4972 NTSTATUS status = build_progid_section(actctx, §ion); 4973 if (status) return status; 4974 4975 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL)) 4976 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4977 } 4978 4979 index = find_string_index(actctx->progid_section, name); 4980 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4981 4982 if (data) 4983 { 4984 progid = get_progid_data(actctx, index); 4985 4986 data->ulDataFormatVersion = 1; 4987 data->lpData = progid; 4988 data->ulLength = progid->size; 4989 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset; 4990 data->ulSectionGlobalDataLength = actctx->progid_section->global_len; 4991 data->lpSectionBase = actctx->progid_section; 4992 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section ); 4993 data->hActCtx = NULL; 4994 4995 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4996 data->ulAssemblyRosterIndex = index->rosterindex; 4997 } 4998 4999 return STATUS_SUCCESS; 5000 } 5001 5002 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 5003 const UNICODE_STRING *section_name, 5004 DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 5005 { 5006 NTSTATUS status; 5007 5008 switch (section_kind) 5009 { 5010 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION: 5011 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 5012 return STATUS_SXS_KEY_NOT_FOUND; 5013 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: 5014 status = find_dll_redirection(actctx, section_name, data); 5015 break; 5016 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 5017 status = find_window_class(actctx, section_name, data); 5018 break; 5019 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 5020 status = find_progid_redirection(actctx, section_name, data); 5021 break; 5022 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: 5023 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 5024 return STATUS_SXS_SECTION_NOT_FOUND; 5025 default: 5026 DPRINT1("Unknown section_kind %x\n", section_kind); 5027 return STATUS_SXS_SECTION_NOT_FOUND; 5028 } 5029 5030 if (status != STATUS_SUCCESS) return status; 5031 5032 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)) 5033 { 5034 actctx_addref(actctx); 5035 data->hActCtx = actctx; 5036 } 5037 return STATUS_SUCCESS; 5038 } 5039 5040 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 5041 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 5042 { 5043 NTSTATUS status; 5044 5045 switch (section_kind) 5046 { 5047 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 5048 status = find_tlib_redirection(actctx, guid, data); 5049 break; 5050 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 5051 status = find_comserver_redirection(actctx, guid, data); 5052 break; 5053 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 5054 status = find_cominterface_redirection(actctx, guid, data); 5055 break; 5056 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 5057 status = find_clr_surrogate(actctx, guid, data); 5058 break; 5059 default: 5060 DPRINT("Unknown section_kind %x\n", section_kind); 5061 return STATUS_SXS_SECTION_NOT_FOUND; 5062 } 5063 5064 if (status != STATUS_SUCCESS) return status; 5065 5066 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5067 { 5068 actctx_addref(actctx); 5069 data->hActCtx = actctx; 5070 } 5071 return STATUS_SUCCESS; 5072 } 5073 5074 /* initialize the activation context for the current process */ 5075 void actctx_init(PVOID* pOldShimData) 5076 { 5077 ACTCTXW ctx; 5078 HANDLE handle; 5079 WCHAR buffer[1024]; 5080 NTSTATUS Status; 5081 5082 ctx.cbSize = sizeof(ctx); 5083 ctx.lpSource = NULL; 5084 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 5085 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5086 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 5087 5088 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle))) 5089 { 5090 process_actctx = check_actctx(handle); 5091 } 5092 5093 /* ReactOS specific: 5094 Now that we have found the process_actctx we can initialize the process compat subsystem */ 5095 LdrpInitializeProcessCompat(process_actctx, pOldShimData); 5096 5097 5098 ctx.dwFlags = 0; 5099 ctx.hModule = NULL; 5100 ctx.lpResourceName = NULL; 5101 ctx.lpSource = buffer; 5102 RtlStringCchCopyW(buffer, RTL_NUMBER_OF(buffer), SharedUserData->NtSystemRoot); 5103 5104 if (RosGetProcessCompatVersion()) 5105 { 5106 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\forwardcompatible.manifest"); 5107 } 5108 else 5109 { 5110 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\systemcompatible.manifest"); 5111 } 5112 5113 Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle); 5114 if (NT_SUCCESS(Status)) 5115 { 5116 implicit_actctx = check_actctx(handle); 5117 } 5118 else 5119 { 5120 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status); 5121 } 5122 } 5123 5124 /* FUNCTIONS ***************************************************************/ 5125 5126 /*********************************************************************** 5127 * RtlCreateActivationContext (NTDLL.@) 5128 * 5129 * Create an activation context. 5130 */ 5131 NTSTATUS 5132 NTAPI 5133 RtlCreateActivationContext(IN ULONG Flags, 5134 IN PACTIVATION_CONTEXT_DATA ActivationContextData, 5135 IN ULONG ExtraBytes, 5136 IN PVOID NotificationRoutine, 5137 IN PVOID NotificationContext, 5138 OUT PACTIVATION_CONTEXT *ActCtx) 5139 { 5140 const ACTCTXW *pActCtx = (PVOID)ActivationContextData; 5141 const WCHAR *directory = NULL; 5142 PACTIVATION_CONTEXT_WRAPPED ActualActCtx; 5143 ACTIVATION_CONTEXT *actctx; 5144 UNICODE_STRING nameW; 5145 ULONG lang = 0; 5146 NTSTATUS status = STATUS_NO_MEMORY; 5147 HANDLE file = 0; 5148 struct actctx_loader acl; 5149 5150 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule); 5151 5152 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) || 5153 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL)) 5154 return STATUS_INVALID_PARAMETER; 5155 5156 5157 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx)))) 5158 return STATUS_NO_MEMORY; 5159 5160 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER; 5161 5162 actctx = &ActualActCtx->ActivationContext; 5163 actctx->RefCount = 1; 5164 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; 5165 actctx->config.info = NULL; 5166 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; 5167 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) 5168 { 5169 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error; 5170 } 5171 else 5172 { 5173 UNICODE_STRING dir; 5174 WCHAR *p; 5175 HMODULE module; 5176 5177 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule; 5178 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5179 5180 status = get_module_filename( module, &dir, 0 ); 5181 if (!NT_SUCCESS(status)) goto error; 5182 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0; 5183 actctx->appdir.info = dir.Buffer; 5184 } 5185 5186 nameW.Buffer = NULL; 5187 5188 /* open file only if it's going to be used */ 5189 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && 5190 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID))) 5191 { 5192 WCHAR *source = NULL; 5193 BOOLEAN ret; 5194 5195 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID && 5196 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative) 5197 { 5198 DWORD dir_len, source_len; 5199 5200 dir_len = strlenW(pActCtx->lpAssemblyDirectory); 5201 source_len = strlenW(pActCtx->lpSource); 5202 if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR)))) 5203 { 5204 status = STATUS_NO_MEMORY; 5205 goto error; 5206 } 5207 5208 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR)); 5209 source[dir_len] = '\\'; 5210 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR)); 5211 } 5212 5213 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL); 5214 RtlFreeHeap( RtlGetProcessHeap(), 0, source ); 5215 if (!ret) 5216 { 5217 status = STATUS_NO_SUCH_FILE; 5218 goto error; 5219 } 5220 status = open_nt_file( &file, &nameW ); 5221 if (!NT_SUCCESS(status)) 5222 { 5223 RtlFreeUnicodeString( &nameW ); 5224 goto error; 5225 } 5226 } 5227 5228 acl.actctx = actctx; 5229 acl.dependencies = NULL; 5230 acl.num_dependencies = 0; 5231 acl.allocated_dependencies = 0; 5232 5233 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; 5234 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; 5235 5236 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) 5237 { 5238 /* if we have a resource it's a PE file */ 5239 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) 5240 { 5241 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule, 5242 pActCtx->lpResourceName, lang ); 5243 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5244 /* FIXME: what to do if pActCtx->lpSource is set */ 5245 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, 5246 pActCtx->hModule, pActCtx->lpResourceName ); 5247 } 5248 else if (pActCtx->lpSource && pActCtx->lpResourceName) 5249 { 5250 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE, 5251 file, pActCtx->lpResourceName, lang ); 5252 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5253 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, 5254 NULL, pActCtx->lpResourceName ); 5255 } 5256 else status = STATUS_INVALID_PARAMETER; 5257 } 5258 else 5259 { 5260 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file ); 5261 } 5262 5263 if (file) NtClose( file ); 5264 RtlFreeUnicodeString( &nameW ); 5265 5266 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl); 5267 free_depend_manifests( &acl ); 5268 5269 if (NT_SUCCESS(status)) 5270 *ActCtx = actctx; 5271 else actctx_release( actctx ); 5272 return status; 5273 5274 error: 5275 if (file) NtClose( file ); 5276 actctx_release( actctx ); 5277 return status; 5278 } 5279 5280 #if 0 5281 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1) 5282 5283 VOID 5284 NTAPI 5285 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle) 5286 { 5287 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle; 5288 LONG OldRefCount, NewRefCount; 5289 5290 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5291 { 5292 RtlpValidateActCtx(ActCtx); 5293 5294 while (TRUE) 5295 { 5296 OldRefCount = ActCtx->RefCount; 5297 ASSERT(OldRefCount > 0); 5298 5299 if (OldRefCount == LONG_MAX) break; 5300 5301 NewRefCount = OldRefCount + 1; 5302 if (InterlockedCompareExchange(&ActCtx->RefCount, 5303 NewRefCount, 5304 OldRefCount) == OldRefCount) 5305 { 5306 break; 5307 } 5308 } 5309 5310 NewRefCount = LONG_MAX; 5311 ASSERT(NewRefCount > 0); 5312 } 5313 } 5314 5315 VOID 5316 NTAPI 5317 RtlReleaseActivationContext( HANDLE handle ) 5318 { 5319 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle; 5320 5321 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5322 { 5323 RtlpValidateActCtx(ActCtx); 5324 5325 actctx_release(ActCtx); 5326 } 5327 } 5328 #else 5329 5330 /*********************************************************************** 5331 * RtlAddRefActivationContext (NTDLL.@) 5332 */ 5333 VOID NTAPI RtlAddRefActivationContext( HANDLE handle ) 5334 { 5335 ACTIVATION_CONTEXT *actctx; 5336 5337 if ((actctx = check_actctx( handle ))) actctx_addref( actctx ); 5338 } 5339 5340 5341 /****************************************************************** 5342 * RtlReleaseActivationContext (NTDLL.@) 5343 */ 5344 VOID NTAPI RtlReleaseActivationContext( HANDLE handle ) 5345 { 5346 ACTIVATION_CONTEXT *actctx; 5347 5348 if ((actctx = check_actctx( handle ))) actctx_release( actctx ); 5349 } 5350 5351 #endif 5352 5353 /****************************************************************** 5354 * RtlZombifyActivationContext (NTDLL.@) 5355 * 5356 */ 5357 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context) 5358 { 5359 UNIMPLEMENTED; 5360 5361 if (Context == ACTCTX_FAKE_HANDLE) 5362 return STATUS_SUCCESS; 5363 5364 return STATUS_NOT_IMPLEMENTED; 5365 } 5366 5367 NTSTATUS 5368 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie ) 5369 { 5370 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5371 5372 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) ))) 5373 return STATUS_NO_MEMORY; 5374 5375 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame; 5376 frame->ActivationContext = handle; 5377 frame->Flags = 0; 5378 5379 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5380 tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame, 5381 frame, handle); 5382 5383 tebAddress->ActivationContextStackPointer->ActiveFrame = frame; 5384 RtlAddRefActivationContext( handle ); 5385 5386 *cookie = (ULONG_PTR)frame; 5387 DPRINT( "%p cookie=%lx\n", handle, *cookie ); 5388 return STATUS_SUCCESS; 5389 } 5390 5391 /****************************************************************** 5392 * RtlActivateActivationContext (NTDLL.@) 5393 */ 5394 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie ) 5395 { 5396 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie); 5397 } 5398 5399 /*********************************************************************** 5400 * RtlDeactivateActivationContext (NTDLL.@) 5401 */ 5402 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) 5403 { 5404 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; 5405 5406 DPRINT( "%x cookie=%lx\n", flags, cookie ); 5407 5408 /* find the right frame */ 5409 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5410 for (frame = top; frame; frame = frame->Previous) 5411 if ((ULONG_PTR)frame == cookie) break; 5412 5413 if (!frame) 5414 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 5415 5416 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION)) 5417 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); 5418 5419 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5420 NtCurrentTeb()->ActivationContextStackPointer, 5421 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame, 5422 frame->Previous); 5423 5424 /* pop everything up to and including frame */ 5425 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 5426 5427 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5428 { 5429 frame = top->Previous; 5430 RtlReleaseActivationContext( top->ActivationContext ); 5431 RtlFreeHeap( RtlGetProcessHeap(), 0, top ); 5432 top = frame; 5433 } 5434 5435 return STATUS_SUCCESS; 5436 } 5437 5438 VOID 5439 NTAPI 5440 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack) 5441 { 5442 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame; 5443 5444 /* Nothing to do if there is no stack */ 5445 if (!Stack) return; 5446 5447 /* Get the current active frame */ 5448 ActiveFrame = Stack->ActiveFrame; 5449 5450 /* Go through them in backwards order and release */ 5451 while (ActiveFrame) 5452 { 5453 PrevFrame = ActiveFrame->Previous; 5454 RtlReleaseActivationContext(ActiveFrame->ActivationContext); 5455 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame); 5456 ActiveFrame = PrevFrame; 5457 } 5458 5459 /* Zero out the active frame */ 5460 Stack->ActiveFrame = NULL; 5461 5462 /* TODO: Empty the Frame List Cache */ 5463 ASSERT(IsListEmpty(&Stack->FrameListCache)); 5464 5465 /* Free activation stack memory */ 5466 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack); 5467 } 5468 5469 /****************************************************************** 5470 * RtlFreeThreadActivationContextStack (NTDLL.@) 5471 */ 5472 VOID NTAPI RtlFreeThreadActivationContextStack(VOID) 5473 { 5474 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer); 5475 NtCurrentTeb()->ActivationContextStackPointer = NULL; 5476 } 5477 5478 5479 /****************************************************************** 5480 * RtlGetActiveActivationContext (NTDLL.@) 5481 */ 5482 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle ) 5483 { 5484 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5485 { 5486 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 5487 RtlAddRefActivationContext( *handle ); 5488 } 5489 else 5490 *handle = 0; 5491 5492 return STATUS_SUCCESS; 5493 } 5494 5495 5496 /****************************************************************** 5497 * RtlIsActivationContextActive (NTDLL.@) 5498 */ 5499 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle ) 5500 { 5501 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5502 5503 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous) 5504 if (frame->ActivationContext == handle) return TRUE; 5505 return FALSE; 5506 } 5507 5508 5509 /*********************************************************************** 5510 * RtlQueryInformationActivationContext (NTDLL.@) 5511 * 5512 * Get information about an activation context. 5513 * FIXME: function signature/prototype may be wrong 5514 */ 5515 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, 5516 ULONG class, PVOID buffer, 5517 SIZE_T bufsize, SIZE_T *retlen ) 5518 { 5519 ACTIVATION_CONTEXT *actctx; 5520 NTSTATUS status; 5521 5522 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle, 5523 subinst, class, buffer, bufsize, retlen); 5524 5525 if (retlen) *retlen = 0; 5526 if ((status = find_query_actctx( &handle, flags, class ))) return status; 5527 5528 switch (class) 5529 { 5530 case ActivationContextBasicInformation: 5531 { 5532 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; 5533 5534 if (retlen) *retlen = sizeof(*info); 5535 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; 5536 5537 info->hActCtx = handle; 5538 info->dwFlags = 0; /* FIXME */ 5539 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle); 5540 } 5541 break; 5542 5543 case ActivationContextDetailedInformation: 5544 { 5545 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; 5546 struct assembly *assembly = NULL; 5547 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; 5548 LPWSTR ptr; 5549 5550 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5551 5552 if (actctx->num_assemblies) assembly = actctx->assemblies; 5553 5554 if (assembly && assembly->manifest.info) 5555 manifest_len = strlenW(assembly->manifest.info) + 1; 5556 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1; 5557 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1; 5558 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); 5559 5560 if (retlen) *retlen = len; 5561 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5562 5563 acdi->dwFlags = 0; 5564 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ 5565 acdi->ulAssemblyCount = actctx->num_assemblies; 5566 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; 5567 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0; 5568 acdi->ulRootConfigurationPathType = actctx->config.type; 5569 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0; 5570 acdi->ulAppDirPathType = actctx->appdir.type; 5571 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0; 5572 ptr = (LPWSTR)(acdi + 1); 5573 if (manifest_len) 5574 { 5575 acdi->lpRootManifestPath = ptr; 5576 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); 5577 ptr += manifest_len; 5578 } 5579 else acdi->lpRootManifestPath = NULL; 5580 if (config_len) 5581 { 5582 acdi->lpRootConfigurationPath = ptr; 5583 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); 5584 ptr += config_len; 5585 } 5586 else acdi->lpRootConfigurationPath = NULL; 5587 if (appdir_len) 5588 { 5589 acdi->lpAppDirPath = ptr; 5590 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); 5591 } 5592 else acdi->lpAppDirPath = NULL; 5593 } 5594 break; 5595 5596 case AssemblyDetailedInformationInActivationContext: 5597 { 5598 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; 5599 struct assembly *assembly; 5600 WCHAR *assembly_id; 5601 DWORD index; 5602 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; 5603 LPWSTR ptr; 5604 5605 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5606 if (!subinst) return STATUS_INVALID_PARAMETER; 5607 5608 index = *(DWORD*)subinst; 5609 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; 5610 5611 assembly = &actctx->assemblies[index - 1]; 5612 5613 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; 5614 id_len = strlenW(assembly_id) + 1; 5615 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1; 5616 5617 if (assembly->manifest.info && 5618 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST)) 5619 path_len = strlenW(assembly->manifest.info) + 1; 5620 5621 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); 5622 5623 if (retlen) *retlen = len; 5624 if (!buffer || bufsize < len) 5625 { 5626 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5627 return STATUS_BUFFER_TOO_SMALL; 5628 } 5629 5630 afdi->ulFlags = 0; /* FIXME */ 5631 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR); 5632 afdi->ulManifestPathType = assembly->manifest.type; 5633 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0; 5634 /* FIXME afdi->liManifestLastWriteTime = 0; */ 5635 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ 5636 afdi->ulPolicyPathLength = 0; 5637 /* FIXME afdi->liPolicyLastWriteTime = 0; */ 5638 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ 5639 afdi->ulManifestVersionMajor = 1; 5640 afdi->ulManifestVersionMinor = 0; 5641 afdi->ulPolicyVersionMajor = 0; /* FIXME */ 5642 afdi->ulPolicyVersionMinor = 0; /* FIXME */ 5643 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0; 5644 ptr = (LPWSTR)(afdi + 1); 5645 afdi->lpAssemblyEncodedAssemblyIdentity = ptr; 5646 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); 5647 ptr += id_len; 5648 if (path_len) 5649 { 5650 afdi->lpAssemblyManifestPath = ptr; 5651 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); 5652 ptr += path_len; 5653 } else afdi->lpAssemblyManifestPath = NULL; 5654 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ 5655 if (ad_len) 5656 { 5657 afdi->lpAssemblyDirectoryName = ptr; 5658 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); 5659 } 5660 else afdi->lpAssemblyDirectoryName = NULL; 5661 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5662 } 5663 break; 5664 5665 case FileInformationInAssemblyOfAssemblyInActivationContext: 5666 { 5667 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; 5668 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; 5669 struct assembly *assembly; 5670 struct dll_redirect *dll; 5671 SIZE_T len, dll_len = 0; 5672 LPWSTR ptr; 5673 5674 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5675 if (!acqi) return STATUS_INVALID_PARAMETER; 5676 5677 if (acqi->ulAssemblyIndex >= actctx->num_assemblies) 5678 return STATUS_INVALID_PARAMETER; 5679 assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; 5680 5681 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) 5682 return STATUS_INVALID_PARAMETER; 5683 dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; 5684 5685 if (dll->name) dll_len = strlenW(dll->name) + 1; 5686 len = sizeof(*afdi) + dll_len * sizeof(WCHAR); 5687 5688 if (!buffer || bufsize < len) 5689 { 5690 if (retlen) *retlen = len; 5691 return STATUS_BUFFER_TOO_SMALL; 5692 } 5693 if (retlen) *retlen = 0; /* yes that's what native does !! */ 5694 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; 5695 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0; 5696 afdi->ulPathLength = 0; /* FIXME */ 5697 ptr = (LPWSTR)(afdi + 1); 5698 if (dll_len) 5699 { 5700 afdi->lpFileName = ptr; 5701 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); 5702 } else afdi->lpFileName = NULL; 5703 afdi->lpFilePath = NULL; /* FIXME */ 5704 } 5705 break; 5706 5707 case CompatibilityInformationInActivationContext: 5708 { 5709 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer; 5710 COMPATIBILITY_CONTEXT_ELEMENT *elements; 5711 struct assembly *assembly = NULL; 5712 ULONG num_compat_contexts = 0, n; 5713 SIZE_T len; 5714 5715 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5716 5717 if (actctx->num_assemblies) assembly = actctx->assemblies; 5718 5719 if (assembly) 5720 num_compat_contexts = assembly->num_compat_contexts; 5721 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); 5722 5723 if (retlen) *retlen = len; 5724 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5725 5726 *acci = num_compat_contexts; 5727 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1); 5728 for (n = 0; n < num_compat_contexts; ++n) 5729 { 5730 elements[n] = assembly->compat_contexts[n]; 5731 } 5732 } 5733 break; 5734 5735 case RunlevelInformationInActivationContext: 5736 { 5737 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer; 5738 struct assembly *assembly; 5739 SIZE_T len; 5740 5741 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5742 5743 len = sizeof(*acrli); 5744 if (retlen) *retlen = len; 5745 if (!buffer || bufsize < len) 5746 return STATUS_BUFFER_TOO_SMALL; 5747 5748 assembly = actctx->assemblies; 5749 5750 acrli->ulFlags = 0; 5751 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED; 5752 acrli->UiAccess = assembly ? assembly->ui_access : 0; 5753 } 5754 break; 5755 5756 default: 5757 DPRINT( "class %u not implemented\n", class ); 5758 return STATUS_NOT_IMPLEMENTED; 5759 } 5760 return STATUS_SUCCESS; 5761 } 5762 5763 NTSTATUS 5764 NTAPI 5765 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, 5766 PVOID pvBuffer, 5767 SIZE_T cbBuffer OPTIONAL, 5768 SIZE_T *pcbWrittenOrRequired OPTIONAL) 5769 { 5770 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT, 5771 NULL, 5772 NULL, 5773 ulInfoClass, 5774 pvBuffer, 5775 cbBuffer, 5776 pcbWrittenOrRequired); 5777 } 5778 5779 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002 5780 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004 5781 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5782 5783 NTSTATUS 5784 NTAPI 5785 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, 5786 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) 5787 { 5788 /* Check general parameter combinations */ 5789 if (!section_name || !section_name->Buffer || 5790 (flags & ~FIND_ACTCTX_VALID_MASK) || 5791 ((flags & FIND_ACTCTX_VALID_MASK) && !data) || 5792 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) 5793 { 5794 DPRINT1("invalid parameter\n"); 5795 return STATUS_INVALID_PARAMETER; 5796 } 5797 5798 /* TODO */ 5799 if (flags & FIND_ACTCTX_RETURN_FLAGS || 5800 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5801 { 5802 DPRINT1("unknown flags %08x\n", flags); 5803 return STATUS_INVALID_PARAMETER; 5804 } 5805 5806 return STATUS_SUCCESS; 5807 } 5808 5809 /*********************************************************************** 5810 * RtlFindActivationContextSectionString (NTDLL.@) 5811 * 5812 * Find information about a string in an activation context. 5813 * FIXME: function signature/prototype may be wrong 5814 */ 5815 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, 5816 const UNICODE_STRING *section_name, PVOID ptr ) 5817 { 5818 PACTCTX_SECTION_KEYED_DATA data = ptr; 5819 NTSTATUS status; 5820 5821 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr); 5822 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data); 5823 if (!NT_SUCCESS(status)) 5824 { 5825 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status); 5826 return status; 5827 } 5828 5829 status = STATUS_SXS_KEY_NOT_FOUND; 5830 5831 /* if there is no data, but params are valid, 5832 we return that sxs key is not found to be at least somehow compatible */ 5833 if (!data) 5834 { 5835 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status); 5836 return status; 5837 } 5838 5839 ASSERT(NtCurrentTeb()); 5840 ASSERT(NtCurrentTeb()->ActivationContextStackPointer); 5841 5842 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame); 5843 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5844 { 5845 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5846 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); 5847 } 5848 5849 DPRINT("status %x\n", status); 5850 if (status != STATUS_SUCCESS) 5851 status = find_string( process_actctx, section_kind, section_name, flags, data ); 5852 5853 if (status != STATUS_SUCCESS) 5854 status = find_string( implicit_actctx, section_kind, section_name, flags, data ); 5855 5856 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status); 5857 return status; 5858 } 5859 5860 /*********************************************************************** 5861 * RtlFindActivationContextSectionGuid (NTDLL.@) 5862 * 5863 * Find information about a GUID in an activation context. 5864 * FIXME: function signature/prototype may be wrong 5865 */ 5866 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind, 5867 const GUID *guid, void *ptr ) 5868 { 5869 ACTCTX_SECTION_KEYED_DATA *data = ptr; 5870 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; 5871 5872 if (extguid) 5873 { 5874 DPRINT1("expected extguid == NULL\n"); 5875 return STATUS_INVALID_PARAMETER; 5876 } 5877 5878 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5879 { 5880 DPRINT1("unknown flags %08x\n", flags); 5881 return STATUS_INVALID_PARAMETER; 5882 } 5883 5884 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid) 5885 return STATUS_INVALID_PARAMETER; 5886 5887 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5888 { 5889 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5890 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data ); 5891 } 5892 5893 if (status != STATUS_SUCCESS) 5894 status = find_guid( process_actctx, section_kind, guid, flags, data ); 5895 5896 if (status != STATUS_SUCCESS) 5897 status = find_guid( implicit_actctx, section_kind, guid, flags, data ); 5898 5899 return status; 5900 } 5901 5902 /* Stubs */ 5903 5904 NTSTATUS 5905 NTAPI 5906 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack) 5907 { 5908 PACTIVATION_CONTEXT_STACK ContextStack; 5909 5910 /* Check if it's already allocated */ 5911 if (*Stack) return STATUS_SUCCESS; 5912 5913 /* Allocate space for the context stack */ 5914 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK)); 5915 if (!ContextStack) 5916 { 5917 return STATUS_NO_MEMORY; 5918 } 5919 5920 /* Initialize the context stack */ 5921 ContextStack->Flags = 0; 5922 ContextStack->ActiveFrame = NULL; 5923 InitializeListHead(&ContextStack->FrameListCache); 5924 ContextStack->NextCookieSequenceNumber = 1; 5925 ContextStack->StackId = 1; //TODO: Timer-based 5926 5927 *Stack = ContextStack; 5928 5929 return STATUS_SUCCESS; 5930 } 5931 5932 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 5933 FASTCALL 5934 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, 5935 IN PVOID Context) 5936 { 5937 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame; 5938 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame; 5939 5940 /* Get the current active frame */ 5941 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5942 5943 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5944 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame, 5945 &Frame->Frame, Context); 5946 5947 /* Ensure it's in the right format and at least fits basic info */ 5948 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 5949 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 5950 5951 /* Set debug info if size allows*/ 5952 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 5953 { 5954 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame); 5955 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context); 5956 //Frame->Extra3 = ...; 5957 } 5958 5959 if (ActiveFrame) 5960 { 5961 /*ASSERT((ActiveFrame->Flags & 5962 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | 5963 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED | 5964 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/ 5965 5966 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED)) 5967 { 5968 // TODO: Perform some additional checks if it was not heap allocated 5969 } 5970 } 5971 5972 /* Save pointer to the new activation frame */ 5973 NewFrame = &Frame->Frame; 5974 5975 /* Actually activate it */ 5976 Frame->Frame.Previous = ActiveFrame; 5977 Frame->Frame.ActivationContext = Context; 5978 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED; 5979 5980 /* Check if we can activate this context */ 5981 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) || 5982 Context) 5983 { 5984 /* Set new active frame */ 5985 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame); 5986 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5987 return NewFrame; 5988 } 5989 5990 /* We can get here only one way: it was already activated */ 5991 DPRINT("Trying to activate already activated activation context\n"); 5992 5993 /* Activate only if we are allowing multiple activation */ 5994 #if 0 5995 if (!RtlpNotAllowingMultipleActivation) 5996 { 5997 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED; 5998 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5999 } 6000 #else 6001 // Activate it anyway 6002 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 6003 #endif 6004 6005 /* Return pointer to the activation frame */ 6006 return NewFrame; 6007 } 6008 6009 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 6010 FASTCALL 6011 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) 6012 { 6013 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame; 6014 6015 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 6016 6017 /* Ensure it's in the right format and at least fits basic info */ 6018 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 6019 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 6020 6021 /* Make sure it is not deactivated and it is activated */ 6022 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0); 6023 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 6024 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); 6025 6026 /* Check debug info if it is present */ 6027 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 6028 { 6029 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous)); 6030 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext)); 6031 //Frame->Extra3 = ...; 6032 } 6033 6034 if (ActiveFrame) 6035 { 6036 // TODO: Perform some additional checks here 6037 } 6038 6039 /* Special handling for not-really-activated */ 6040 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED) 6041 { 6042 DPRINT1("Deactivating not really activated activation context\n"); 6043 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 6044 return &Frame->Frame; 6045 } 6046 6047 /* find the right frame */ 6048 NewFrame = &Frame->Frame; 6049 if (ActiveFrame != NewFrame) 6050 { 6051 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame); 6052 } 6053 6054 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 6055 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous); 6056 6057 /* Pop everything up to and including frame */ 6058 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous; 6059 6060 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 6061 return NewFrame->Previous; 6062 } 6063