Index: dll/ntdll/ldr/ldrpe.c =================================================================== --- dll/ntdll/ldr/ldrpe.c (revision 75728) +++ dll/ntdll/ldr/ldrpe.c (working copy) @@ -815,7 +815,6 @@ return Status; } -/* FIXME: This function is missing SxS support */ NTSTATUS NTAPI LdrpLoadImportModule(IN PWSTR DllPath OPTIONAL, @@ -831,9 +830,14 @@ NTSTATUS Status; PPEB Peb = RtlGetCurrentPeb(); PTEB Teb = NtCurrentTeb(); + UNICODE_STRING DllString1; + BOOLEAN RedirectedDll; DPRINT("LdrpLoadImportModule('%S' '%s' %p %p)\n", DllPath, ImportName, DataTableEntry, Existing); + RedirectedDll = FALSE; + RtlInitEmptyUnicodeString(&DllString1, NULL, 0); + /* Convert import descriptor name to unicode string */ ImpDescName = &Teb->StaticUnicodeString; RtlInitAnsiString(&AnsiString, ImportName); @@ -883,66 +887,45 @@ &LdrApiDefaultExtension); } + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImpDescName, + &LdrApiDefaultExtension, + NULL, + &DllString1, + &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, @@ -949,11 +932,13 @@ ImpDescName->Buffer, NULL, TRUE, - FALSE, + RedirectedDll, DataTableEntry); + if (!NT_SUCCESS(Status)) + { + goto done; + } - if (!NT_SUCCESS(Status)) return Status; - /* Walk its import descriptor table */ Status = LdrpWalkImportDescriptor(DllPath, *DataTableEntry); @@ -964,6 +949,11 @@ &(*DataTableEntry)->InInitializationOrderLinks); } +done: + + /* Do we have a redirect string? */ + if (DllString1.Buffer) RtlFreeUnicodeString(&DllString1); + return Status; } Index: dll/ntdll/ldr/ldrutils.c =================================================================== --- dll/ntdll/ldr/ldrutils.c (revision 75728) +++ dll/ntdll/ldr/ldrutils.c (working copy) @@ -28,101 +28,6 @@ /* 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, @@ -220,13 +125,24 @@ 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 @@ { /* 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,32 @@ if (NT_SUCCESS(Status)) { - if (LdrpCheckForLoadedDll(NULL, - ImportNameUnic, - TRUE, - FALSE, - &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; - } + RedirectedDll = FALSE; - /* Show snaps */ - if (ShowSnaps) - { - DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); - } - } + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &ImportNameUnic, + NULL, + NULL, + NULL); - /* Recurse into this entry */ - LdrpUpdateLoadCount3(Entry, Flags, UpdateString); + /* Check success */ + if (NT_SUCCESS(Status)) + { + /* Let Ldrp know */ + 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, TRUE, - FALSE, + RedirectedDll, &Entry)) { if (Entry->LoadCount != 0xFFFF) @@ -344,7 +238,79 @@ LdrpUpdateLoadCount3(Entry, Flags, UpdateString); } } + else + { + /* Unrecoverable SxS failure */ + } + } + + /* 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; + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &ImportNameUnic, + NULL, + NULL, + NULL); + /* Check success */ + if (NT_SUCCESS(Status)) + { + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + + if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND) + { + if (LdrpCheckForLoadedDll(NULL, + ImportNameUnic, + 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, ImportNameUnic, Entry->LoadCount); + } + } + + /* Recurse into this entry */ + LdrpUpdateLoadCount3(Entry, Flags, UpdateString); + } + } + } + NewImportForwarder++; } @@ -352,7 +318,7 @@ } /* We're done */ - return; + goto done; } /* Check oldstyle import descriptor */ @@ -380,37 +346,59 @@ Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); if (NT_SUCCESS(Status)) { - if (LdrpCheckForLoadedDll(NULL, - ImportNameUnic, - TRUE, - FALSE, - &Entry)) + RedirectedDll = FALSE; + + /* Check if the SxS Assemblies specify another file */ + Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, + ImportNameUnic, + &LdrApiDefaultExtension, + UpdateString, + NULL, + &ImportNameUnic, + NULL, + NULL, + NULL); + /* Check success */ + if (NT_SUCCESS(Status)) { - if (Entry->LoadCount != 0xFFFF) + /* Let Ldrp know */ + RedirectedDll = TRUE; + } + + if (RedirectedDll || Status == STATUS_SXS_KEY_NOT_FOUND) + { + if (LdrpCheckForLoadedDll(NULL, + ImportNameUnic, + TRUE, + RedirectedDll, + &Entry)) { - /* Perform the required action */ - switch (Flags) + if (Entry->LoadCount != 0xFFFF) { - case LDRP_UPDATE_REFCOUNT: - Entry->LoadCount++; - break; - case LDRP_UPDATE_DEREFCOUNT: - Entry->LoadCount--; - break; - case LDRP_UPDATE_PIN: - Entry->LoadCount = 0xFFFF; - break; + /* 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); + } } - /* Show snaps */ - if (ShowSnaps) - { - DPRINT1("LDR: Flags %lu %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); - } + /* Recurse */ + LdrpUpdateLoadCount3(Entry, Flags, UpdateString); } - - /* Recurse */ - LdrpUpdateLoadCount3(Entry, Flags, UpdateString); } } @@ -418,6 +406,10 @@ ImportEntry++; } } + +done: + /* Release the context */ + RtlDeactivateActivationContextUnsafeFast(&ActCtx); } VOID @@ -665,7 +657,6 @@ 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 +671,14 @@ 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 +1018,7 @@ } /* Check if we have a known dll directory */ - if (LdrpKnownDllObjectDirectory) + if (LdrpKnownDllObjectDirectory && Redirect == FALSE) { /* Check if the path is full */ while (*p1) @@ -1977,8 +1957,10 @@ /* 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 +1988,54 @@ 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; + /* Check for a slash in the current position*/ + if ((*wc == L'\\') || (*wc == L'/')) + { + /* Found the slash, so dll name contains path */ + FullPath = TRUE; - /* Setup full dll name string */ - FullDllName.Buffer = NameBuf; + /* 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); + /* 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)))) - { - /* HACK: Try to find active context dll */ - Status = find_actctx_dll(DllName->Buffer, FullDllName.Buffer); - if(Status == STATUS_SUCCESS) + /* 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); + if (ShowSnaps) + { + DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %wZ: 0x%08x\n", + &DllName, Length); + } } - else - { - 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 */ Index: dll/ntdll/rtl/libsupp.c =================================================================== --- dll/ntdll/rtl/libsupp.c (revision 75728) +++ dll/ntdll/rtl/libsupp.c (working copy) @@ -642,6 +642,123 @@ return ImageBase; } +/* NOTE: Remove this one once our actctx support becomes better */ +NTSTATUS find_actctx_dll( PUNICODE_STRING pnameW, LPWSTR *fullname, PUNICODE_STRING CallerBuffer) +{ + 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) 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) + pnameW->Length; + + if (CallerBuffer && CallerBuffer->MaximumLength > needed) + { + p = CallerBuffer->Buffer; + CallerBuffer->Length = needed; + } + else + { + p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed ); + if (!p) + { + status = STATUS_NO_MEMORY; + goto done; + } + } + *fullname = p; + + 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)); + + if (CallerBuffer && CallerBuffer->MaximumLength > needed) + { + p = CallerBuffer->Buffer; + CallerBuffer->Length = needed; + } + else + { + p = RtlAllocateHeap(RtlGetProcessHeap(), 0, needed ); + if (!p) + { + status = STATUS_NO_MEMORY; + goto done; + } + } + *fullname = p; + + 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 +775,46 @@ IN PSIZE_T FileNameSize, IN PSIZE_T RequiredLength) { - return STATUS_SXS_KEY_NOT_FOUND; + NTSTATUS Status; + LPWSTR fullname; + + /* Check for invalid parameters */ + if ((DynamicString) && !(NewName) && (StaticString)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Use wine's function as long as we use wine's sxs implementation in ntdll */ + Status = find_actctx_dll(OriginalName, &fullname, StaticString); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + Status = RtlDoesFileExists_U(fullname); + if (!NT_SUCCESS(Status)) + { + 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; } /* Index: dll/win32/comctl32/commctrl.c =================================================================== --- dll/win32/comctl32/commctrl.c (revision 75728) +++ dll/win32/comctl32/commctrl.c (working copy) @@ -1192,6 +1192,11 @@ ERR("Failed to install comctl32 v5 manifest!\n"); return HRESULT_FROM_WIN32(GetLastError()); } + + CreateDirectoryW(L"C:\\ReactOS\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef", NULL); + CreateDirectoryW(L"C:\\ReactOS\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef", NULL); + CopyFile(L"C:\\ReactOS\\system32\\comctl32.dll", L"C:\\ReactOS\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.2600.2982_none_deadbeef\\comctl32.dll", FALSE); + CopyFile(L"C:\\ReactOS\\system32\\comctl32.dll", L"C:\\ReactOS\\winsxs\\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef\\comctl32.dll", FALSE); #endif return S_OK;