[0.4.12] [NTDLL/LDR] Revert the 0.4.12-workaround for comctl32 imagelist

This reverts 0.4.12-RC-2-g
f57e9ed926
and therefore brings the SxS state back to master. It allows many SxS-dependent apps to run again that broke by the new 0.4.12-workaround.
e.g: Miranda 0.10.48

Unfortunately this will expose many issues for the first time in the 0.4.12release (same way like in master),
that I could properly hide in all past releases by a different workaround (that we can not longer use due to heavy 0.4.12-dev SxS works)

This commit reintroduces:
- CORE-14433 MSVCPP 6 installer open-dlg, MS Word Viewer 2003 open-dlg lacks icons
- CORE-15118 OCR CuneiForm 12 lacks icons in the menubar
- CORE-15892 DosBOX 0.74.2 NSIS-installer lacks checkboxes

We think that all those issues are caused by incompatible comctl32 v5/v6 imagelists actually.
If time will allow it, I might experiment with some macros later to hide the comctl32-issue leaving SxS intact.
This commit is contained in:
Joachim Henze 2019-05-09 20:14:20 +02:00
parent 5ac548544f
commit fbe1fbe32b

View file

@ -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,169 @@ 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;
C_ASSERT(sizeof(UNICODE_NULL) == sizeof(WCHAR));
/* 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;
}
if (NtCurrentPeb()->ProcessParameters &&
(NtCurrentPeb()->ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_PRIVATE_DLL_PATH))
{
UNICODE_STRING RealName, LocalName;
WCHAR RealNameBuf[MAX_PATH], LocalNameBuf[MAX_PATH];
RtlInitEmptyUnicodeString(&RealName, RealNameBuf, sizeof(RealNameBuf));
RtlInitEmptyUnicodeString(&LocalName, LocalNameBuf, sizeof(LocalNameBuf));
Status = RtlComputePrivatizedDllName_U(OriginalName, &RealName, &LocalName);
if (!NT_SUCCESS(Status))
{
DPRINT1("RtlComputePrivatizedDllName_U failed for %wZ: 0x%lx\n", OriginalName, Status);
return Status;
}
if (RtlDoesFileExists_UStr(&LocalName))
{
Status = get_buffer(&fullname, LocalName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
if (NT_SUCCESS(Status))
{
RtlCopyMemory(fullname, LocalName.Buffer, LocalName.Length + sizeof(UNICODE_NULL));
}
else
{
DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
}
}
else if (RtlDoesFileExists_UStr(&RealName))
{
Status = get_buffer(&fullname, RealName.Length + sizeof(UNICODE_NULL), StaticString, DynamicString != NULL);
if (NT_SUCCESS(Status))
{
RtlCopyMemory(fullname, RealName.Buffer, RealName.Length + sizeof(UNICODE_NULL));
}
else
{
DPRINT1("Error while retrieving buffer for %wZ: 0x%lx\n", OriginalName, Status);
}
}
else
{
Status = STATUS_NOT_FOUND;
}
if (RealName.Buffer != RealNameBuf)
RtlFreeUnicodeString(&RealName);
if (LocalName.Buffer != LocalNameBuf)
RtlFreeUnicodeString(&LocalName);
if (NT_SUCCESS(Status))
{
DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
if (!StaticString || StaticString->Buffer != fullname)
{
RtlInitUnicodeString(DynamicString, fullname);
*NewName = DynamicString;
}
else
{
*NewName = StaticString;
}
return Status;
}
}
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;
}
DPRINT("Redirecting %wZ to %S\n", OriginalName, fullname);
if (!StaticString || StaticString->Buffer != fullname)
{
RtlInitUnicodeString(DynamicString, fullname);
*NewName = DynamicString;
}
else
{
*NewName = StaticString;
}
return Status;
}
/*