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