boot/bootdata/packages/reactos.dff.in | 4 + dll/ntdll/ldr/ldrpe.c | 91 ++-- dll/ntdll/ldr/ldrutils.c | 471 +++++++++++---------- dll/ntdll/rtl/libsupp.c | 233 +++++++++- dll/win32/comctl32/CMakeLists.txt | 6 +- dll/win32/comctl32/commctrl.c | 6 +- dll/win32/comctl32/rsrc.rc | 4 - ...44ccf1df_5.82.2600.2982_none_deadbeef.manifest} | 0 ...144ccf1df_6.0.2600.2982_none_deadbeef.manifest} | 0 modules/rostests/apitests/ntdll/CMakeLists.txt | 1 + .../RtlDosApplyFileIsolationRedirection_Ustr.c | 273 +++++++++++- sdk/cmake/CMakeMacros.cmake | 8 + sdk/lib/rtl/actctx.c | 3 +- 13 files changed, 808 insertions(+), 292 deletions(-) diff --git a/boot/bootdata/packages/reactos.dff.in b/boot/bootdata/packages/reactos.dff.in index 4382637..24a5138 100644 --- a/boot/bootdata/packages/reactos.dff.in +++ b/boot/bootdata/packages/reactos.dff.in @@ -70,6 +70,10 @@ Signature = "$ReactOS$" 51 = system32\CatRoot 52 = system32\CatRoot2 53 = AppPatch +54 = winsxs +55 = winsxs\manifests +56 = winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef +57 = winsxs\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef .InfEnd diff --git a/dll/ntdll/ldr/ldrpe.c b/dll/ntdll/ldr/ldrpe.c index 10d128f..2fceeb3 100644 --- a/dll/ntdll/ldr/ldrpe.c +++ b/dll/ntdll/ldr/ldrpe.c @@ -815,7 +815,6 @@ LdrpWalkImportDescriptor(IN LPWSTR DllPath OPTIONAL, return Status; } -/* FIXME: This function is missing SxS support */ NTSTATUS NTAPI LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, @@ -831,9 +830,14 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, NTSTATUS Status; PPEB Peb = RtlGetCurrentPeb(); PTEB Teb = NtCurrentTeb(); + UNICODE_STRING RedirectedImpDescName; + BOOLEAN RedirectedDll; DPRINT("LdrpLoadImportModule('%S' '%s' %p %p)\n", DllPath, ImportName, DataTableEntry, Existing); + RedirectedDll = FALSE; + RtlInitEmptyUnicodeString(&RedirectedImpDescName, NULL, 0); + /* Convert import descriptor name to unicode string */ ImpDescName = &Teb->StaticUnicodeString; RtlInitAnsiString(&AnsiString, ImportName); @@ -883,76 +887,57 @@ LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, &LdrApiDefaultExtension); } + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImpDescName, + &LdrApiDefaultExtension, + NULL, + &RedirectedImpDescName, + &ImpDescName, + NULL, + NULL, + NULL); + + /* Check success */ + if (NT_SUCCESS(Status)) + { + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + else if (Status != STATUS_SXS_KEY_NOT_FOUND) + { + /* Unrecoverable SxS failure */ + goto done; + } + /* Check if it's loaded */ if (LdrpCheckForLoadedDll(DllPath, ImpDescName, TRUE, - FALSE, + RedirectedDll, DataTableEntry)) { /* It's already existing in the list */ *Existing = TRUE; - return STATUS_SUCCESS; + Status = STATUS_SUCCESS; + goto done; } /* We're loading it for the first time */ *Existing = FALSE; -#if 0 - /* Load manifest */ - { - ACTCTX_SECTION_KEYED_DATA data; - NTSTATUS status; - - //DPRINT1("find_actctx_dll for %S\n", fullname); - //RtlInitUnicodeString(&nameW, libname); - data.cbSize = sizeof(data); - status = RtlFindActivationContextSectionString( - FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, - ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, - ImpDescName, - &data); - //if (status != STATUS_SUCCESS) return status; - DPRINT1("Status: 0x%08X\n", status); - - if (NT_SUCCESS(status)) - { - ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; - SIZE_T needed, size = 1024; - - for (;;) - { - if (!(info = RtlAllocateHeap(RtlGetProcessHeap(), 0, size))) - { - status = STATUS_NO_MEMORY; - goto done; - } - status = RtlQueryInformationActivationContext(0, data.hActCtx, &data.ulAssemblyRosterIndex, - AssemblyDetailedInformationInActivationContext, - info, size, &needed); - if (status == STATUS_SUCCESS) break; - if (status != STATUS_BUFFER_TOO_SMALL) goto done; - RtlFreeHeap(RtlGetProcessHeap(), 0, info); - size = needed; - } - - DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath); - DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); - } - } -done: -#endif - /* Map it */ Status = LdrpMapDll(DllPath, NULL, ImpDescName->Buffer, NULL, TRUE, - FALSE, + RedirectedDll, DataTableEntry); - - if (!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) + { + goto done; + } /* Walk its import descriptor table */ Status = LdrpWalkImportDescriptor(DllPath, @@ -964,6 +949,10 @@ done: &(*DataTableEntry)->InInitializationOrderLinks); } +done: + /* Do we have a redirect string? */ + RtlFreeUnicodeString(&RedirectedImpDescName); + return Status; } diff --git a/dll/ntdll/ldr/ldrutils.c b/dll/ntdll/ldr/ldrutils.c index d960c7f..040d4c3 100644 --- a/dll/ntdll/ldr/ldrutils.c +++ b/dll/ntdll/ldr/ldrutils.c @@ -28,101 +28,6 @@ PVOID g_pfnSE_ProcessDying; /* FUNCTIONS *****************************************************************/ -/* NOTE: Remove this one once our actctx support becomes better */ -NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fullname ) -{ - static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'}; - static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; - - ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; - ACTCTX_SECTION_KEYED_DATA data; - UNICODE_STRING nameW; - NTSTATUS status; - SIZE_T needed, size = 1024; - WCHAR *p; - - RtlInitUnicodeString( &nameW, libname ); - data.cbSize = sizeof(data); - status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, - ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, - &nameW, &data ); - if (status != STATUS_SUCCESS) return status; - - for (;;) - { - if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) - { - status = STATUS_NO_MEMORY; - goto done; - } - status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, - AssemblyDetailedInformationInActivationContext, - info, size, &needed ); - if (status == STATUS_SUCCESS) break; - if (status != STATUS_BUFFER_TOO_SMALL) goto done; - RtlFreeHeap( RtlGetProcessHeap(), 0, info ); - size = needed; - } - - DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath); - DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); - if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName) - { - status = STATUS_SXS_KEY_NOT_FOUND; - goto done; - } - - if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' ))) - { - DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); - - p++; - if (_wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW )) - { - /* manifest name does not match directory name, so it's not a global - * windows/winsxs manifest; use the manifest directory name instead */ - dirlen = p - info->lpAssemblyManifestPath; - needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length; - - p = fullname; - /*if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) - { - status = STATUS_NO_MEMORY; - goto done; - }*/ - memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) ); - p += dirlen; - wcscpy( p, libname ); - goto done; - } - } - - needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) + - sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR)); - - p = fullname; - //if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) - //{ - //status = STATUS_NO_MEMORY; - //goto done; - //} - wcscpy( p, SharedUserData->NtSystemRoot ); - p += wcslen(p); - memcpy( p, winsxsW, sizeof(winsxsW) ); - p += sizeof(winsxsW) / sizeof(WCHAR); - memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength ); - p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); - *p++ = '\\'; - wcscpy( p, libname ); - -done: - RtlFreeHeap( RtlGetProcessHeap(), 0, info ); - RtlReleaseActivationContext( data.hActCtx ); - DPRINT("%S\n", fullname); - return status; -} - - NTSTATUS NTAPI LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut, @@ -214,19 +119,30 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, PIMAGE_IMPORT_DESCRIPTOR ImportEntry; PIMAGE_THUNK_DATA FirstThunk; PLDR_DATA_TABLE_ENTRY Entry; - PUNICODE_STRING ImportNameUnic; + PUNICODE_STRING ImportNameUnic, RedirectedImportName; ANSI_STRING ImportNameAnsi; LPSTR ImportName; ULONG ImportSize; NTSTATUS Status; ULONG i; + BOOLEAN RedirectedDll; + RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED ActCtx; + + /* Set up the Act Ctx */ + ActCtx.Size = sizeof(ActCtx); + ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; + RtlZeroMemory(&ActCtx.Frame, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME)); + + /* Activate the ActCtx */ + RtlActivateActivationContextUnsafeFast(&ActCtx, + LdrEntry->EntryPointActivationContext); /* Check the action we need to perform */ if ((Flags == LDRP_UPDATE_REFCOUNT) || (Flags == LDRP_UPDATE_PIN)) { /* Make sure entry is not being loaded already */ if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS) - return; + goto done; LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS; } @@ -234,7 +150,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, { /* Make sure the entry is not being unloaded already */ if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS) - return; + goto done; LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS; } @@ -267,54 +183,38 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, if (NT_SUCCESS(Status)) { - if (LdrpCheckForLoadedDll(NULL, - ImportNameUnic, - TRUE, - FALSE, - &Entry)) + RedirectedDll = FALSE; + RedirectedImportName = ImportNameUnic; + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &RedirectedImportName, + NULL, + NULL, + NULL); + + /* Check success */ + if (NT_SUCCESS(Status)) { - if (Entry->LoadCount != 0xFFFF) + /* Let Ldrp know */ + if (ShowSnaps) { - /* Perform the required action */ - switch (Flags) - { - case LDRP_UPDATE_REFCOUNT: - Entry->LoadCount++; - break; - case LDRP_UPDATE_DEREFCOUNT: - Entry->LoadCount--; - break; - case LDRP_UPDATE_PIN: - Entry->LoadCount = 0xFFFF; - break; - } - - /* Show snaps */ - if (ShowSnaps) - { - DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); - } + DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName); } - /* Recurse into this entry */ - LdrpUpdateLoadCount3(Entry, Flags, UpdateString); + RedirectedDll = TRUE; } - } - /* Go through forwarders */ - NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1); - for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++) - { - ImportName = (LPSTR)FirstEntry + NewImportForwarder->OffsetModuleName; - - RtlInitAnsiString(&ImportNameAnsi, ImportName); - Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); - if (NT_SUCCESS(Status)) + if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND) { if (LdrpCheckForLoadedDll(NULL, - ImportNameUnic, + RedirectedImportName, TRUE, - FALSE, + RedirectedDll, &Entry)) { if (Entry->LoadCount != 0xFFFF) @@ -336,13 +236,105 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, /* Show snaps */ if (ShowSnaps) { - DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); + DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount); } } /* Recurse into this entry */ LdrpUpdateLoadCount3(Entry, Flags, UpdateString); } + else if (RedirectedDll) + { + DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName); + } + } + else + { + /* Unrecoverable SxS failure */ + DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed for dll %wZ\n", ImportNameUnic); + } + + } + + /* Go through forwarders */ + NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1); + for (i = 0; i < BoundEntry->NumberOfModuleForwarderRefs; i++) + { + ImportName = (LPSTR)FirstEntry + NewImportForwarder->OffsetModuleName; + + RtlInitAnsiString(&ImportNameAnsi, ImportName); + Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); + if (NT_SUCCESS(Status)) + { + RedirectedDll = FALSE; + RedirectedImportName = ImportNameUnic; + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &RedirectedImportName, + NULL, + NULL, + NULL); + /* Check success */ + if (NT_SUCCESS(Status)) + { + if (ShowSnaps) + { + DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName); + } + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + + if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND) + { + if (LdrpCheckForLoadedDll(NULL, + RedirectedImportName, + TRUE, + RedirectedDll, + &Entry)) + { + if (Entry->LoadCount != 0xFFFF) + { + /* Perform the required action */ + switch (Flags) + { + case LDRP_UPDATE_REFCOUNT: + Entry->LoadCount++; + break; + case LDRP_UPDATE_DEREFCOUNT: + Entry->LoadCount--; + break; + case LDRP_UPDATE_PIN: + Entry->LoadCount = 0xFFFF; + break; + } + + /* Show snaps */ + if (ShowSnaps) + { + DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount); + } + } + + /* Recurse into this entry */ + LdrpUpdateLoadCount3(Entry, Flags, UpdateString); + } + else if (RedirectedDll) + { + DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName); + } + } + else + { + /* Unrecoverable SxS failure */ + DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed for dll %wZ\n", ImportNameUnic); + } + } NewImportForwarder++; @@ -352,7 +344,7 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, } /* We're done */ - return; + goto done; } /* Check oldstyle import descriptor */ @@ -380,44 +372,87 @@ LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); if (NT_SUCCESS(Status)) { - if (LdrpCheckForLoadedDll(NULL, - ImportNameUnic, - TRUE, - FALSE, - &Entry)) + RedirectedDll = FALSE; + RedirectedImportName = ImportNameUnic; + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &RedirectedImportName, + NULL, + NULL, + NULL); + /* Check success */ + if (NT_SUCCESS(Status)) { - if (Entry->LoadCount != 0xFFFF) + if (ShowSnaps) { - /* Perform the required action */ - switch (Flags) - { - case LDRP_UPDATE_REFCOUNT: - Entry->LoadCount++; - break; - case LDRP_UPDATE_DEREFCOUNT: - Entry->LoadCount--; - break; - case LDRP_UPDATE_PIN: - Entry->LoadCount = 0xFFFF; - break; - } + DPRINT1("LDR: %Z got redirected to %wZ\n", &ImportNameAnsi, RedirectedImportName); + } - /* Show snaps */ - if (ShowSnaps) + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + + if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND) + { + if (LdrpCheckForLoadedDll(NULL, + RedirectedImportName, + TRUE, + RedirectedDll, + &Entry)) + { + if (Entry->LoadCount != 0xFFFF) { - DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); + /* Perform the required action */ + switch (Flags) + { + case LDRP_UPDATE_REFCOUNT: + Entry->LoadCount++; + break; + case LDRP_UPDATE_DEREFCOUNT: + Entry->LoadCount--; + break; + case LDRP_UPDATE_PIN: + Entry->LoadCount = 0xFFFF; + break; + } + + /* Show snaps */ + if (ShowSnaps) + { + DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, RedirectedImportName, Entry->LoadCount); + } } + + /* Recurse */ + LdrpUpdateLoadCount3(Entry, Flags, UpdateString); + } + else if (RedirectedDll) + { + DPRINT1("LDR: LdrpCheckForLoadedDll failed for redirected dll %wZ\n", RedirectedImportName); } - /* Recurse */ - LdrpUpdateLoadCount3(Entry, Flags, UpdateString); } + else + { + /* Unrecoverable SxS failure */ + DPRINT1("LDR: RtlDosApplyFileIsolationRedirection_Ustr failed for dll %wZ\n", ImportNameUnic); + } + } /* Go to the next entry */ ImportEntry++; } } + +done: + /* Release the context */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); } VOID @@ -665,7 +700,6 @@ LdrpResolveDllName(PWSTR DllPath, PWCHAR NameBuffer, p1, p2 = 0; ULONG Length; ULONG BufSize = 500; - NTSTATUS Status; /* Allocate space for full DLL name */ FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL)); @@ -680,25 +714,14 @@ LdrpResolveDllName(PWSTR DllPath, if (!Length || Length > BufSize) { - /* HACK: Try to find active context dll */ - Status = find_actctx_dll(DllName, FullDllName->Buffer); - if(Status == STATUS_SUCCESS) + if (ShowSnaps) { - Length = wcslen(FullDllName->Buffer) * sizeof(WCHAR); - DPRINT1("found %S for %S\n", FullDllName->Buffer, DllName); + DPRINT1("LDR: LdrResolveDllName - Unable to find "); + DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer); } - else - { - /* NOTE: This code should remain after removing the hack */ - if (ShowSnaps) - { - DPRINT1("LDR: LdrResolveDllName - Unable to find "); - DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer); - } - RtlFreeUnicodeString(FullDllName); - return FALSE; - } + RtlFreeUnicodeString(FullDllName); + return FALSE; } /* Construct full DLL name */ @@ -1038,7 +1061,7 @@ LdrpMapDll(IN PWSTR SearchPath OPTIONAL, } /* Check if we have a known dll directory */ - if (LdrpKnownDllObjectDirectory) + if (LdrpKnownDllObjectDirectory && Redirect == FALSE) { /* Check if the path is full */ while (*p1) @@ -1977,8 +2000,10 @@ LdrpCheckForLoadedDll(IN PWSTR DllPath, /* Look in the hash table if flag was set */ lookinhash: - if (Flag) + if (Flag /* the second check is a hack */ && !RedirectedDll) { + /* FIXME: if we get redirected dll it means that we also get a full path so we need to find its filename for the hash lookup */ + /* Get hash index */ HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]); @@ -2006,58 +2031,54 @@ lookinhash: return FALSE; } - /* Check if there is a full path in this DLL */ - wc = DllName->Buffer; - while (*wc) + /* Check if this is a redirected DLL */ + if (RedirectedDll) { - /* Check for a slash in the current position*/ - if ((*wc == L'\\') || (*wc == L'/')) + /* Redirected dlls already have a full path */ + FullPath = TRUE; + FullDllName = *DllName; + } + else + { + /* Check if there is a full path in this DLL */ + wc = DllName->Buffer; + while (*wc) { - /* Found the slash, so dll name contains path */ - FullPath = TRUE; - - /* Setup full dll name string */ - FullDllName.Buffer = NameBuf; - - /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */ - Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, - DllName->Buffer, - NULL, - sizeof(NameBuf) - sizeof(UNICODE_NULL), - FullDllName.Buffer, - NULL); - - /* Check if that was successful */ - if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL)))) + /* Check for a slash in the current position*/ + if ((*wc == L'\\') || (*wc == L'/')) { - /* HACK: Try to find active context dll */ - Status = find_actctx_dll(DllName->Buffer, FullDllName.Buffer); - if(Status == STATUS_SUCCESS) + /* Found the slash, so dll name contains path */ + FullPath = TRUE; + + /* Setup full dll name string */ + FullDllName.Buffer = NameBuf; + + /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */ + Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, + DllName->Buffer, + NULL, + sizeof(NameBuf) - sizeof(UNICODE_NULL), + FullDllName.Buffer, + NULL); + + /* Check if that was successful */ + if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL)))) { - Length = wcslen(FullDllName.Buffer) * sizeof(WCHAR); - DPRINT1("found %S for %S\n", FullDllName.Buffer, DllName->Buffer); - } - else - { - - if (ShowSnaps) - { - DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n", - &DllName, Length); + if (ShowSnaps) + { + DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n", + &DllName, Length); + } } - /* Return failure */ - return FALSE; - } + /* Full dll name is found */ + FullDllName.Length = Length; + FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL); + break; } - /* Full dll name is found */ - FullDllName.Length = Length; - FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL); - break; + wc++; } - - wc++; } /* Go check the hash table */ diff --git a/dll/ntdll/rtl/libsupp.c b/dll/ntdll/rtl/libsupp.c index 08a26cc..c88278c 100644 --- a/dll/ntdll/rtl/libsupp.c +++ b/dll/ntdll/rtl/libsupp.c @@ -642,6 +642,133 @@ RtlPcToFileHeader(IN PVOID PcValue, return ImageBase; } +NTSTATUS get_buffer(LPWSTR *buffer, SIZE_T needed, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer) +{ + WCHAR *p; + + if (CallerBuffer && CallerBuffer->MaximumLength > needed) + { + p = CallerBuffer->Buffer; + CallerBuffer->Length = needed - sizeof(WCHAR); + } + else + { + if (!bAllocateBuffer) + return STATUS_BUFFER_TOO_SMALL; + + if (CallerBuffer) + CallerBuffer->Buffer[0] = 0; + + p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed ); + if (!p) + return STATUS_NO_MEMORY; + } + *buffer = p; + + return STATUS_SUCCESS; +} + +/* NOTE: Remove this one once our actctx support becomes better */ +NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer, BOOLEAN bAllocateBuffer) +{ + static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'}; + static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; + + ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; + ACTCTX_SECTION_KEYED_DATA data; + NTSTATUS status; + SIZE_T needed, size = 1024; + WCHAR *p; + + data.cbSize = sizeof(data); + status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, + ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, + pnameW, &data ); + if (status != STATUS_SUCCESS) + { + //DPRINT1("RtlFindActivationContextSectionString returned 0x%x for %wZ\n", status, pnameW); + return status; + } + + for (;;) + { + if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) + { + status = STATUS_NO_MEMORY; + goto done; + } + status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, + AssemblyDetailedInformationInActivationContext, + info, size, &needed ); + if (status == STATUS_SUCCESS) break; + if (status != STATUS_BUFFER_TOO_SMALL) goto done; + RtlFreeHeap( RtlGetProcessHeap(), 0, info ); + size = needed; + } + + DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath); + DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); + if (!info->lpAssemblyManifestPath /*|| !info->lpAssemblyDirectoryName*/) + { + status = STATUS_SXS_KEY_NOT_FOUND; + goto done; + } + + if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' ))) + { + DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); + + p++; + if (!info->lpAssemblyDirectoryName || _wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW )) + { + /* manifest name does not match directory name, so it's not a global + * windows/winsxs manifest; use the manifest directory name instead */ + dirlen = p - info->lpAssemblyManifestPath; + needed = (dirlen + 1) * sizeof(WCHAR) + pnameW->Length; + + status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer); + if (!NT_SUCCESS(status)) + goto done; + + p = *fullname; + + memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) ); + p += dirlen; + memcpy( p, pnameW->Buffer, pnameW->Length); + p += (pnameW->Length / sizeof(WCHAR)); + *p = L'\0'; + + goto done; + } + } + + needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) + + sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + pnameW->Length + 2*sizeof(WCHAR)); + + status = get_buffer(fullname, needed, CallerBuffer, bAllocateBuffer); + if (!NT_SUCCESS(status)) + goto done; + + p = *fullname; + + wcscpy( p, SharedUserData->NtSystemRoot ); + p += wcslen(p); + memcpy( p, winsxsW, sizeof(winsxsW) ); + p += sizeof(winsxsW) / sizeof(WCHAR); + memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength ); + p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); + *p++ = L'\\'; + memcpy( p, pnameW->Buffer, pnameW->Length); + p += (pnameW->Length / sizeof(WCHAR)); + *p = L'\0'; + +done: + RtlFreeHeap( RtlGetProcessHeap(), 0, info ); + RtlReleaseActivationContext( data.hActCtx ); + DPRINT("%S\n", fullname); + return status; +} + /* * @unimplemented */ @@ -658,7 +785,111 @@ RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG Flags, IN PSIZE_T FileNameSize, IN PSIZE_T RequiredLength) { - return STATUS_SXS_KEY_NOT_FOUND; + NTSTATUS Status; + LPWSTR fullname; + WCHAR buffer [MAX_PATH]; + UNICODE_STRING localStr, localStr2, *pstrParam; + WCHAR *p; + BOOLEAN GotExtension; + WCHAR c; + + /* Check for invalid parameters */ + if (!OriginalName) + { + return STATUS_INVALID_PARAMETER; + } + + if (!DynamicString && !StaticString) + { + return STATUS_INVALID_PARAMETER; + } + + if ((DynamicString) && (StaticString) && !(NewName)) + { + return STATUS_INVALID_PARAMETER; + } + + if (!OriginalName->Buffer || OriginalName->Length == 0) + { + return STATUS_SXS_KEY_NOT_FOUND; + } + + if (StaticString && (OriginalName == StaticString || OriginalName->Buffer == StaticString->Buffer)) + { + return STATUS_SXS_KEY_NOT_FOUND; + } + + pstrParam = OriginalName; + + /* Get the file name with an extension */ + p = OriginalName->Buffer + OriginalName->Length / sizeof(WCHAR) - 1; + GotExtension = FALSE; + while (p >= OriginalName->Buffer) + { + c = *p--; + if (c == L'.') + { + GotExtension = TRUE; + } + else if (c == L'\\') + { + localStr.Buffer = p + 2; + localStr.Length = OriginalName->Length - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer); + localStr.MaximumLength = OriginalName->MaximumLength - ((ULONG_PTR)localStr.Buffer - (ULONG_PTR)OriginalName->Buffer); + pstrParam = &localStr; + break; + } + } + + if (!GotExtension) + { + if (!Extension) + { + return STATUS_SXS_KEY_NOT_FOUND; + } + + if (pstrParam->Length + Extension->Length > sizeof(buffer)) + { + //FIXME! + return STATUS_NO_MEMORY; + } + + RtlInitEmptyUnicodeString(&localStr2, buffer, sizeof(buffer)); + RtlAppendUnicodeStringToString(&localStr2, pstrParam); + RtlAppendUnicodeStringToString(&localStr2, Extension); + pstrParam = &localStr2; + } + + /* Use wine's function as long as we use wine's sxs implementation in ntdll */ + Status = find_actctx_dll(pstrParam, &fullname, StaticString, DynamicString != NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + //if (!RtlDoesFileExists_U(fullname)) + //{ + // if (StaticString && StaticString->Buffer != fullname) + // { + // RtlFreeHeap( RtlGetProcessHeap(), 0, fullname ); + // } + + // return STATUS_SXS_KEY_NOT_FOUND; + //} + + DPRINT1("Redirecting %wZ to %S\n", OriginalName, fullname); + + if (!StaticString || StaticString->Buffer != fullname) + { + RtlInitUnicodeString(DynamicString, fullname); + *NewName = DynamicString; + } + else + { + *NewName = StaticString; + } + + return Status; } /* diff --git a/dll/win32/comctl32/CMakeLists.txt b/dll/win32/comctl32/CMakeLists.txt index 1b55c5d..9285001 100644 --- a/dll/win32/comctl32/CMakeLists.txt +++ b/dll/win32/comctl32/CMakeLists.txt @@ -64,5 +64,7 @@ add_delay_importlibs(comctl32 winmm uxtheme) add_importlibs(comctl32 user32 gdi32 advapi32 msvcrt kernel32 ntdll) add_pch(comctl32 comctl32.h SOURCE) add_cd_file(TARGET comctl32 DESTINATION reactos/system32 FOR all) -add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/comctl32v5.manifest DESTINATION reactos/winsxs/manifests NAME_ON_CD x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef.manifest FOR livecd) -add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/comctl32.manifest DESTINATION reactos/winsxs/manifests NAME_ON_CD x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest FOR livecd) \ No newline at end of file +add_cd_file(TARGET comctl32 DESTINATION reactos/winsxs/x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef FOR all) +add_cd_file(TARGET comctl32 DESTINATION reactos/winsxs/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef FOR all) +add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef.manifest DESTINATION reactos/winsxs/manifests FOR all) +add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest DESTINATION reactos/winsxs/manifests FOR all) \ No newline at end of file diff --git a/dll/win32/comctl32/commctrl.c b/dll/win32/comctl32/commctrl.c index e091ccc..35c07f0 100644 --- a/dll/win32/comctl32/commctrl.c +++ b/dll/win32/comctl32/commctrl.c @@ -128,7 +128,7 @@ static WCHAR* GetManifestPath(BOOL create, BOOL bV6) return pwszBuf; } - +#if 0 static BOOL create_manifest(BOOL install, BOOL bV6) { WCHAR *pwszBuf; @@ -186,7 +186,7 @@ static BOOL create_manifest(BOOL install, BOOL bV6) return bRet; } - +#endif static HANDLE CreateComctl32ActCtx(BOOL bV6) { HANDLE ret; @@ -1179,7 +1179,7 @@ HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) { TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline)); -#ifdef __REACTOS__ +#if 0 if (!create_manifest(bInstall, TRUE)) { diff --git a/dll/win32/comctl32/rsrc.rc b/dll/win32/comctl32/rsrc.rc index 0fb8289..e0a9376 100644 --- a/dll/win32/comctl32/rsrc.rc +++ b/dll/win32/comctl32/rsrc.rc @@ -36,10 +36,6 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #include "wine/wine_common_ver.rc" -/* @makedep: comctl32.manifest */ -WINE_MANIFEST RT_MANIFEST comctl32.manifest -WINE_MANIFESTV5 RT_MANIFEST comctl32v5.manifest - /* @makedep: idt_check.bmp */ IDT_CHECK BITMAP idt_check.bmp diff --git a/dll/win32/comctl32/comctl32v5.manifest b/dll/win32/comctl32/x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef.manifest similarity index 100% rename from dll/win32/comctl32/comctl32v5.manifest rename to dll/win32/comctl32/x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef.manifest diff --git a/dll/win32/comctl32/comctl32.manifest b/dll/win32/comctl32/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest similarity index 100% rename from dll/win32/comctl32/comctl32.manifest rename to dll/win32/comctl32/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt b/modules/rostests/apitests/ntdll/CMakeLists.txt index 7a56d74..5a09cf7 100644 --- a/modules/rostests/apitests/ntdll/CMakeLists.txt +++ b/modules/rostests/apitests/ntdll/CMakeLists.txt @@ -75,3 +75,4 @@ add_rostests_file(TARGET ntdll_apitest SUBDIR testdata) add_rostests_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/ntdll_apitest.exe.local" SUBDIR testdata) add_rostests_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/shell32.dll" SUBDIR testdata) add_rostests_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/test.dll" SUBDIR testdata) +add_rostests_file(FILE "${CMAKE_CURRENT_SOURCE_DIR}/ntdlltest.manifest" SUBDIR testdata) diff --git a/modules/rostests/apitests/ntdll/RtlDosApplyFileIsolationRedirection_Ustr.c b/modules/rostests/apitests/ntdll/RtlDosApplyFileIsolationRedirection_Ustr.c index 9a77f04..222da6a 100644 --- a/modules/rostests/apitests/ntdll/RtlDosApplyFileIsolationRedirection_Ustr.c +++ b/modules/rostests/apitests/ntdll/RtlDosApplyFileIsolationRedirection_Ustr.c @@ -36,6 +36,11 @@ struct test_data Tests[] = {__LINE__, STATUS_SUCCESS, L"COMCTL32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"}, {__LINE__, STATUS_SUCCESS, L"comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"}, {__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\comctl32.DLL", L"\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82"}, + /* Files defined in the manifest, one exists, one doesn't */ + {__LINE__, STATUS_SUCCESS, L"deptest.dll", EXPECT_IN_SAME_DIR}, + {__LINE__, STATUS_SUCCESS, L"adllfile.dll", EXPECT_IN_SAME_DIR}, + /* A file that exists in the same dir but isn't mentioned in the manifest */ + {__LINE__, STATUS_SUCCESS, L"fil1.txt", EXPECT_IN_SAME_DIR}, /* This is a weird case; the source doesn't exist but does get redirected */ {__LINE__, STATUS_SUCCESS, L"c:\\windows\\system32\\gdiplus.DLL", L"\\winsxs\\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1."}, /* But redirecting gdiplus from a different directory doesn't work */ @@ -51,6 +56,28 @@ struct test_data Tests[] = {__LINE__, STATUS_SUCCESS, L"c:\\shell32.dll", EXPECT_IN_SAME_DIR} }; +HANDLE _CreateActCtxFromFile(LPCWSTR FileName, int line) +{ + ACTCTXW ActCtx = {sizeof(ACTCTX)}; + HANDLE h; + WCHAR buffer[MAX_PATH] , *separator; + + ok (GetModuleFileNameW(NULL, buffer, MAX_PATH), "GetModuleFileName failed\n"); + separator = wcsrchr(buffer, L'\\'); + if (separator) + wcscpy(separator + 1, FileName); + + ActCtx.lpSource = buffer; + + SetLastError(0xdeaddead); + h = CreateActCtxW(&ActCtx); + ok_(__FILE__, line)(h != INVALID_HANDLE_VALUE, "CreateActCtx failed for %S\n", FileName); + // In win10 last error is unchanged and in win2k3 it is ERROR_BAD_EXE_FORMAT + ok_(__FILE__, line)(GetLastError() == ERROR_BAD_EXE_FORMAT || GetLastError() == 0xdeaddead, "Wrong last error %lu\n", GetLastError()); + + return h; +} + void TestRedirection(void) { WCHAR SystemDir[MAX_PATH]; @@ -95,11 +122,11 @@ void TestRedirection(void) NULL); ok(Status == Tests[i].ExpectedStatus, "%d: Status 0x%lx, expected 0x%lx\n", Tests[i].testline, Status, Tests[i].ExpectedStatus); - if (DynamicString.Buffer) - { - BOOL exists = RtlDoesFileExists_U(DynamicString.Buffer); - ok(exists, "%d: Expected file %S to exist!\n", Tests[i].testline, DynamicString.Buffer); - } + //if (DynamicString.Buffer) + //{ + // BOOL exists = RtlDoesFileExists_U(DynamicString.Buffer); + // ok(exists, "%d: Expected file %S to exist!\n", Tests[i].testline, DynamicString.Buffer); + //} if(Tests[i].ExpectedSubString && DynamicString.Buffer == NULL) { @@ -121,6 +148,231 @@ void TestRedirection(void) } } +void TestBuffers() +{ + UNICODE_STRING Param, DynamicString, StaticString; + PUNICODE_STRING StringUsed = NULL; + NTSTATUS Status; + WCHAR buffer[MAX_PATH]; + + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + NULL, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_INVALID_PARAMETER, "0x%x\n", Status); + + RtlInitEmptyUnicodeString(&Param, NULL, 0); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%x\n", Status); + + /* Tests for NULL termination of OriginalName */ + Param.MaximumLength = Param.Length = 12 * sizeof(WCHAR); + Param.Buffer = L"comctl32.dllcrapcrap"; + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + + /* Tests for the Extension parameter */ + RtlInitUnicodeString(&Param, L"comctl32.dll"); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + + RtlInitUnicodeString(&Param, L"comctl32"); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%x\n", Status); + + RtlInitUnicodeString(&Param, L"comctl32"); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + &DotDll, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + + /* Tests for the DynamicString parameter */ + RtlInitUnicodeString(&Param, L"comctl32.dll"); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + NULL, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + ok(DynamicString.Length >0 , "\n"); + ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n"); + if (DynamicString.Buffer && DynamicString.Length) + ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer) * sizeof(WCHAR) , DynamicString.Length); + else + ok(DynamicString.Buffer != NULL, "Expected non NULL buffer\n"); + ok(StringUsed == &DynamicString, "\n"); + + /* Tests for the StaticString parameter */ + wcscpy(buffer, L"comctl32.dll"); + StaticString.Buffer = buffer; + StaticString.Length = sizeof(L"comctl32.dll"); + StaticString.MaximumLength = sizeof(buffer); + Param = StaticString; + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + &StaticString, + NULL, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%x\n", Status); + + wcscpy(buffer, L"comctl32.dll"); + StaticString.Buffer = buffer; + StaticString.Length = sizeof(L"comctl32.dll"); + StaticString.MaximumLength = sizeof(buffer); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &StaticString, + NULL, + &StaticString, + NULL, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SXS_KEY_NOT_FOUND, "0x%x\n", Status); + + RtlInitUnicodeString(&Param, L"comctl32.dll"); + RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer)); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + &StaticString, + NULL, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + ok(StaticString.Length >0 , "\n"); + ok(StaticString.MaximumLength == sizeof(buffer) , "\n"); + if (StaticString.Buffer && StaticString.Length) + ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer) * sizeof(WCHAR) , StaticString.Length); + else + ok(StaticString.Length != 0, "Expected non 0 lenght\n"); + ok(StringUsed == &StaticString, "\n"); + + RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR)); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + &StaticString, + NULL, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status == STATUS_BUFFER_TOO_SMALL, "0x%x\n", Status); + + RtlInitUnicodeString(&Param, L"comctl32.dll"); + RtlInitEmptyUnicodeString(&StaticString, buffer, sizeof(buffer)); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + &StaticString, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + ok(StaticString.Length >0 , "\n"); + ok(StaticString.MaximumLength == sizeof(buffer) , "\n"); + if (StaticString.Buffer && StaticString.Length) + ok(wcslen(StaticString.Buffer) * sizeof(WCHAR) == StaticString.Length, "got %d and %d\n", wcslen(StaticString.Buffer) * sizeof(WCHAR) , StaticString.Length); + else + ok(StaticString.Length != 0, "Expected non 0 lenght\n"); + ok(DynamicString.Buffer == NULL, "\n"); + ok(DynamicString.Length == 0, "\n"); + ok(DynamicString.MaximumLength == 0, "\n"); + ok(StringUsed == &StaticString, "\n"); + + /* Test a small buffer and a dynamic buffer */ + RtlInitUnicodeString(&Param, L"comctl32.dll"); + RtlInitEmptyUnicodeString(&StaticString, buffer, 5 * sizeof(WCHAR)); + RtlInitEmptyUnicodeString(&DynamicString, NULL, 0); + StaticString.Buffer[0] = 1; + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + &Param, + NULL, + &StaticString, + &DynamicString, + &StringUsed, + NULL, + NULL, + NULL); + ok(Status ==STATUS_SUCCESS, "\n"); + ok(StaticString.Buffer == buffer, "\n"); + ok(StaticString.Length == 0 , "%d\n", StaticString.Length); + ok(StaticString.Buffer[0] == 0, "\n"); + ok(StaticString.MaximumLength == 5 * sizeof(WCHAR) , "%d\n", StaticString.MaximumLength); + ok(DynamicString.Length >0 , "\n"); + ok(DynamicString.MaximumLength == DynamicString.Length + sizeof(WCHAR) , "\n"); + if (DynamicString.Buffer && DynamicString.Length) + ok(wcslen(DynamicString.Buffer) * sizeof(WCHAR) == DynamicString.Length, "got %d and %d\n", wcslen(DynamicString.Buffer) * sizeof(WCHAR) , DynamicString.Length); + else + ok(DynamicString.Length != 0, "Expected non 0 lenght\n"); + + ok(StringUsed == &DynamicString, "\n"); +} + START_TEST(RtlDosApplyFileIsolationRedirection_Ustr) { int argc; @@ -128,7 +380,18 @@ START_TEST(RtlDosApplyFileIsolationRedirection_Ustr) argc = winetest_get_mainargs( &test_argv ); if (argc >= 3) { + HANDLE h = _CreateActCtxFromFile(L"ntdlltest.manifest", __LINE__); + BOOL bactivated = FALSE; + ULONG_PTR cookie; + + if (h != INVALID_HANDLE_VALUE) + bactivated = ActivateActCtx(h, &cookie); + TestRedirection(); + TestBuffers(); + + if (bactivated) + DeactivateActCtx(0, cookie); } else { diff --git a/sdk/cmake/CMakeMacros.cmake b/sdk/cmake/CMakeMacros.cmake index 850bb7f..a44ac5e 100644 --- a/sdk/cmake/CMakeMacros.cmake +++ b/sdk/cmake/CMakeMacros.cmake @@ -269,6 +269,14 @@ macro(dir_to_num dir var) set(${var} 52) elseif(${dir} STREQUAL reactos/AppPatch) set(${var} 53) + elseif(${dir} STREQUAL reactos/winsxs) + set(${var} 54) + elseif(${dir} STREQUAL reactos/winsxs/manifests) + set(${var} 55) + elseif(${dir} STREQUAL reactos/winsxs/x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef) + set(${var} 56) + elseif(${dir} STREQUAL reactos/winsxs/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef) + set(${var} 57) else() message(FATAL_ERROR "Wrong destination: ${dir}") endif() diff --git a/sdk/lib/rtl/actctx.c b/sdk/lib/rtl/actctx.c index 3768f72..4cf9bba 100644 --- a/sdk/lib/rtl/actctx.c +++ b/sdk/lib/rtl/actctx.c @@ -3222,7 +3222,8 @@ static struct string_index *find_string_index(const struct strsection_header *se { const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset); - if (!strcmpiW(nameW, name->Buffer)) + if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) && + wcslen(nameW) == name->Length / sizeof(WCHAR)) { index = iter; break;