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