mirror of
https://github.com/reactos/reactos.git
synced 2025-01-11 16:51:06 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
364 lines
10 KiB
C
364 lines
10 KiB
C
/*
|
|
* COPYRIGHT: GPL, see COPYING in the top level directory
|
|
* PROJECT: ReactOS win32 kernel mode subsystem server
|
|
* PURPOSE: File access support routines
|
|
* FILE: subsystem/win32/win32k/misc/registry.c
|
|
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
BOOL
|
|
NTAPI
|
|
W32kDosPathNameToNtPathName(
|
|
IN PCWSTR pwszDosPathName,
|
|
OUT PUNICODE_STRING pustrNtPathName)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
/* Prepend "\??\" */
|
|
pustrNtPathName->Length = 0;
|
|
Status = RtlAppendUnicodeToString(pustrNtPathName, L"\\??\\");
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Append the dos name */
|
|
Status = RtlAppendUnicodeToString(pustrNtPathName, pwszDosPathName);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
NTAPI
|
|
W32kOpenFile(PCWSTR pwszFileName, DWORD dwDesiredAccess)
|
|
{
|
|
UNICODE_STRING ustrFile;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("W32kOpenFile(%S)\n", pwszFileName);
|
|
|
|
RtlInitUnicodeString(&ustrFile, pwszFileName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes, &ustrFile, 0, NULL, NULL);
|
|
|
|
Status = ZwCreateFile(&hFile,
|
|
dwDesiredAccess,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE,
|
|
NULL,
|
|
0);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
hFile = NULL;
|
|
}
|
|
|
|
DPRINT("Leaving W32kOpenFile, Status=0x%x, hFile=0x%x\n", Status, hFile);
|
|
return hFile;
|
|
}
|
|
|
|
HANDLE
|
|
NTAPI
|
|
W32kCreateFileSection(HANDLE hFile,
|
|
ULONG flAllocation,
|
|
DWORD flPageProtection,
|
|
ULONGLONG ullMaxSize)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE hSection = NULL;
|
|
ACCESS_MASK amDesiredAccess;
|
|
|
|
/* Set access mask */
|
|
amDesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
|
|
|
|
/* Check if write access is requested */
|
|
if (flPageProtection == PAGE_READWRITE)
|
|
{
|
|
/* Add it to access mask */
|
|
amDesiredAccess |= SECTION_MAP_WRITE;
|
|
}
|
|
|
|
/* Now create the actual section */
|
|
Status = ZwCreateSection(&hSection,
|
|
amDesiredAccess,
|
|
NULL,
|
|
NULL,
|
|
flPageProtection,
|
|
flAllocation,
|
|
hFile);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
}
|
|
|
|
DPRINT("Leaving W32kCreateFileSection, Status=0x%x, hSection=0x%x\n", Status, hSection);
|
|
|
|
/* Return section handle */
|
|
return hSection;
|
|
}
|
|
|
|
PVOID
|
|
NTAPI
|
|
W32kMapViewOfSection(
|
|
HANDLE hSection,
|
|
DWORD dwPageProtect,
|
|
ULONG_PTR ulSectionOffset)
|
|
{
|
|
NTSTATUS Status;
|
|
LARGE_INTEGER liSectionOffset;
|
|
ULONG_PTR ulViewSize;
|
|
PVOID pvBase = 0;
|
|
|
|
ulViewSize =
|
|
liSectionOffset.QuadPart = ulSectionOffset;
|
|
Status = ZwMapViewOfSection(hSection,
|
|
NtCurrentProcess(),
|
|
&pvBase,
|
|
0,
|
|
0,
|
|
&liSectionOffset,
|
|
&ulViewSize,
|
|
ViewShare,
|
|
0,
|
|
dwPageProtect);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SetLastNtError(Status);
|
|
}
|
|
|
|
DPRINT("Leaving W32kMapViewOfSection, Status=0x%x, pvBase=0x%x\n", Status, pvBase);
|
|
|
|
return pvBase;
|
|
}
|
|
|
|
typedef struct tagBITMAPV5INFO
|
|
{
|
|
BITMAPV5HEADER bmiHeader;
|
|
RGBQUAD bmiColors[256];
|
|
} BITMAPV5INFO, *PBITMAPV5INFO;
|
|
|
|
// FIXME: this should go to dibobj.c
|
|
NTSTATUS
|
|
ProbeAndConvertBitmapInfo(
|
|
OUT BITMAPV5HEADER *pbmhDst,
|
|
OUT RGBQUAD *pbmiColorsDst,
|
|
ULONG cColors,
|
|
IN PBITMAPINFO pbmiUnsafe)
|
|
{
|
|
DWORD dwSize;
|
|
RGBQUAD *pbmiColors;
|
|
ULONG ulWidthBytes;
|
|
|
|
/* Get the size and probe */
|
|
ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
|
|
dwSize = pbmiUnsafe->bmiHeader.biSize;
|
|
ProbeForRead(pbmiUnsafe, dwSize, 1);
|
|
|
|
/* Check the size */
|
|
// FIXME: are intermediate sizes allowed? As what are they interpreted?
|
|
// make sure we don't use a too big dwSize later
|
|
if (dwSize != sizeof(BITMAPCOREHEADER) &&
|
|
dwSize != sizeof(BITMAPINFOHEADER) &&
|
|
dwSize != sizeof(BITMAPV4HEADER) &&
|
|
dwSize != sizeof(BITMAPV5HEADER))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
pbmiColors = (RGBQUAD*)((PCHAR)pbmiUnsafe + dwSize);
|
|
|
|
pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
|
|
|
|
if (dwSize == sizeof(BITMAPCOREHEADER))
|
|
{
|
|
PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
|
|
|
|
/* Manually copy the fields that are present */
|
|
pbmhDst->bV5Width = pbch->bcWidth;
|
|
pbmhDst->bV5Height = pbch->bcHeight;
|
|
pbmhDst->bV5Planes = pbch->bcPlanes;
|
|
pbmhDst->bV5BitCount = pbch->bcBitCount;
|
|
|
|
/* Set some default values */
|
|
pbmhDst->bV5Compression = BI_RGB;
|
|
pbmhDst->bV5SizeImage = 0;
|
|
pbmhDst->bV5XPelsPerMeter = 72;
|
|
pbmhDst->bV5YPelsPerMeter = 72;
|
|
pbmhDst->bV5ClrUsed = 0;
|
|
pbmhDst->bV5ClrImportant = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Copy valid fields */
|
|
memcpy(pbmhDst, pbmiUnsafe, dwSize);
|
|
|
|
/* Zero out the rest of the V5 header */
|
|
memset((char*)pbmhDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
|
|
}
|
|
|
|
|
|
if (dwSize < sizeof(BITMAPV4HEADER))
|
|
{
|
|
if (pbmhDst->bV5Compression == BI_BITFIELDS)
|
|
{
|
|
DWORD *pMasks = (DWORD*)pbmiColors;
|
|
pbmhDst->bV5RedMask = pMasks[0];
|
|
pbmhDst->bV5GreenMask = pMasks[1];
|
|
pbmhDst->bV5BlueMask = pMasks[2];
|
|
pbmhDst->bV5AlphaMask = 0;
|
|
pbmhDst->bV5ClrUsed = 0;
|
|
}
|
|
|
|
// pbmhDst->bV5CSType;
|
|
// pbmhDst->bV5Endpoints;
|
|
// pbmhDst->bV5GammaRed;
|
|
// pbmhDst->bV5GammaGreen;
|
|
// pbmhDst->bV5GammaBlue;
|
|
}
|
|
|
|
if (dwSize < sizeof(BITMAPV5HEADER))
|
|
{
|
|
// pbmhDst->bV5Intent;
|
|
// pbmhDst->bV5ProfileData;
|
|
// pbmhDst->bV5ProfileSize;
|
|
// pbmhDst->bV5Reserved;
|
|
}
|
|
|
|
ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
|
|
pbmhDst->bV5BitCount + 31) & ~31) / 8;
|
|
|
|
if (pbmhDst->bV5SizeImage == 0)
|
|
pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
|
|
|
|
if (pbmhDst->bV5ClrUsed == 0)
|
|
pbmhDst->bV5ClrUsed = pbmhDst->bV5BitCount == 1 ? 2 :
|
|
(pbmhDst->bV5BitCount == 4 ? 16 :
|
|
(pbmhDst->bV5BitCount == 8 ? 256 : 0));
|
|
|
|
if (pbmhDst->bV5Planes != 1)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
|
|
pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
|
|
pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
|
|
pbmhDst->bV5BitCount != 32)
|
|
{
|
|
DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((pbmhDst->bV5BitCount == 0 &&
|
|
pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
|
|
{
|
|
DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pbmhDst->bV5Compression == BI_BITFIELDS &&
|
|
pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
|
|
{
|
|
DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Copy Colors */
|
|
cColors = min(cColors, pbmhDst->bV5ClrUsed);
|
|
memcpy(pbmiColorsDst, pbmiColors, cColors * sizeof(RGBQUAD));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
HBITMAP
|
|
NTAPI
|
|
UserLoadImage(PCWSTR pwszName)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE hFile, hSection;
|
|
BITMAPFILEHEADER *pbmfh;
|
|
LPBITMAPINFO pbmi;
|
|
ULONG cjInfoSize;
|
|
PVOID pvBits;
|
|
HBITMAP hbmp = 0;
|
|
BITMAPV5INFO bmiLocal;
|
|
|
|
/* Open the file */
|
|
hFile = W32kOpenFile(pwszName, FILE_READ_DATA);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return NULL;
|
|
|
|
/* Create a section */
|
|
hSection = W32kCreateFileSection(hFile, SEC_COMMIT, PAGE_READONLY, 0);
|
|
ZwClose(hFile);
|
|
if (!hSection)
|
|
return NULL;
|
|
|
|
/* Map the section */
|
|
pbmfh = W32kMapViewOfSection(hSection, PAGE_READONLY, 0);
|
|
ZwClose(hSection);
|
|
if (!pbmfh)
|
|
return NULL;
|
|
|
|
/* Get a pointer to the BITMAPINFO */
|
|
pbmi = (LPBITMAPINFO)(pbmfh + 1);
|
|
|
|
/* Create a normalized local BITMAPINFO */
|
|
_SEH2_TRY
|
|
{
|
|
Status = ProbeAndConvertBitmapInfo(&bmiLocal.bmiHeader,
|
|
bmiLocal.bmiColors,
|
|
256,
|
|
pbmi);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Status = _SEH2_GetExceptionCode();
|
|
}
|
|
_SEH2_END
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
cjInfoSize = bmiLocal.bmiHeader.bV5Size +
|
|
bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD);
|
|
pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
|
|
|
|
// FIXME: use Gre... so that the BITMAPINFO doesn't get probed
|
|
hbmp = NtGdiCreateDIBitmapInternal(NULL,
|
|
bmiLocal.bmiHeader.bV5Width,
|
|
bmiLocal.bmiHeader.bV5Height,
|
|
CBM_INIT,
|
|
pvBits,
|
|
pbmi,
|
|
DIB_RGB_COLORS,
|
|
bmiLocal.bmiHeader.bV5Size,
|
|
bmiLocal.bmiHeader.bV5SizeImage,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
/* Unmap our section, we don't need it anymore */
|
|
ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);
|
|
|
|
DPRINT("Leaving UserLoadImage, hbmp = %p\n", hbmp);
|
|
return hbmp;
|
|
}
|