diff --git a/reactos/subsystems/win32/win32k/include/dc.h b/reactos/subsystems/win32/win32k/include/dc.h index e1019f6de77..542a19de282 100644 --- a/reactos/subsystems/win32/win32k/include/dc.h +++ b/reactos/subsystems/win32/win32k/include/dc.h @@ -121,6 +121,10 @@ typedef struct _DC HPALETTE PalIndexed; WIN_DC_INFO w; + + HANDLE hFile; + LPENHMETAHEADER emh; + } DC, *PDC; typedef struct _GDIPOINTER /* should stay private to ENG */ diff --git a/reactos/subsystems/win32/win32k/objects/metafile.c b/reactos/subsystems/win32/win32k/objects/metafile.c index aa7e02f6f0a..9c832ba371e 100644 --- a/reactos/subsystems/win32/win32k/objects/metafile.c +++ b/reactos/subsystems/win32/win32k/objects/metafile.c @@ -64,10 +64,172 @@ NtGdiCreateEnhMetaFile(HDC hDCRef, CONST LPRECT Rect, LPCWSTR Description) { - UNIMPLEMENTED; - return 0; + PDC Dc; + HDC ret = NULL; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + DWORD length = 0; + HDC tempHDC; + DWORD MemSize; + + tempHDC = hDCRef; + if (hDCRef == NULL) + { + /* FIXME ?? + * Shall we create hdc NtGdiHdcCompatible hdc ?? + */ + UNICODE_STRING DriverName; + RtlInitUnicodeString(&DriverName, L"DISPLAY"); + tempHDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); + } + + + Dc = DC_LockDc(tempHDC); + if (Dc == NULL) + { + if (hDCRef == NULL) + { + NtGdiDeleteObjectApp(tempHDC); + } + SetLastWin32Error(ERROR_INVALID_HANDLE); + return NULL; + } + + if(Description) + { + length = wcslen(Description); + length += wcslen(Description + length + 1); + length += 3; + length *= 2; + } + + MemSize = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4; + + if (!(Dc->emh = EngAllocMem(FL_ZERO_MEMORY, MemSize, 0))) + { + DC_UnlockDc(Dc); + if (hDCRef == NULL) + { + NtGdiDeleteObjectApp(tempHDC); + } + SetLastWin32Error(ERROR_INVALID_HANDLE); + return NULL; + } + + Dc->emh->iType = EMR_HEADER; + Dc->emh->nSize = MemSize; + + Dc->emh->rclBounds.left = Dc->emh->rclBounds.top = 0; + Dc->emh->rclBounds.right = Dc->emh->rclBounds.bottom = -1; + + if(Rect) + { + Dc->emh->rclFrame.left = Rect->left; + Dc->emh->rclFrame.top = Rect->top; + Dc->emh->rclFrame.right = Rect->right; + Dc->emh->rclFrame.bottom = Rect->bottom; + } + else + { + /* Set this to {0,0 - -1,-1} and update it at the end */ + Dc->emh->rclFrame.left = Dc->emh->rclFrame.top = 0; + Dc->emh->rclFrame.right = Dc->emh->rclFrame.bottom = -1; + } + + Dc->emh->dSignature = ENHMETA_SIGNATURE; + Dc->emh->nVersion = 0x10000; + Dc->emh->nBytes = Dc->emh->nSize; + Dc->emh->nRecords = 1; + Dc->emh->nHandles = 1; + + Dc->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */ + Dc->emh->nDescription = length / 2; + + Dc->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0; + + Dc->emh->nPalEntries = 0; /* I guess this should start at 0 */ + + /* Size in pixels */ + Dc->emh->szlDevice.cx = NtGdiGetDeviceCaps(tempHDC, HORZRES); + Dc->emh->szlDevice.cy = NtGdiGetDeviceCaps(tempHDC, VERTRES); + + /* Size in millimeters */ + Dc->emh->szlMillimeters.cx = NtGdiGetDeviceCaps(tempHDC, HORZSIZE); + Dc->emh->szlMillimeters.cy = NtGdiGetDeviceCaps(tempHDC, VERTSIZE); + + /* Size in micrometers */ + Dc->emh->szlMicrometers.cx = Dc->emh->szlMillimeters.cx * 1000; + Dc->emh->szlMicrometers.cy = Dc->emh->szlMillimeters.cy * 1000; + + if(Description) + { + memcpy((char *)Dc->emh + sizeof(ENHMETAHEADER), Description, length); + } + + ret = tempHDC; + + DPRINT1("File cretae unimplement in NtGdiCreateEnhMetaFile\n"); + if (File) + { + + + + /* disk based metafile */ + + /* FIXME + if ((Dc->hFile = CreateFileW(File, GENERIC_WRITE | GENERIC_READ, 0, + NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) + { + DC_UnLockDc(Dc); + if (hDCRef == NULL) + { + NtGdiDeleteObjectApp(tempHDC); + } + return 0; + } + */ + + Status = NtWriteFile(Dc->hFile, NULL, NULL, NULL, &Iosb, (PVOID)&Dc->emh, Dc->emh->nSize, NULL, NULL); + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(Dc->hFile,FALSE,NULL); + if (NT_SUCCESS(Status)) + { + Status = Iosb.Status; + } + } + + if (NT_SUCCESS(Status)) + { + //ret = Dc->hSelf; + ret = tempHDC; + DC_UnlockDc(Dc); + } + else + { + Dc->hFile = NULL; + /* FIXME use SetLastErrorByStatus */ + //SetLastErrorByStatus(Status); + SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); + ret = NULL; + DC_UnlockDc(Dc); + if (hDCRef == NULL) + { + NtGdiDeleteObjectApp(tempHDC); + } + } + } + else + { + DC_UnlockDc(Dc); + } + + return ret; } + + + HDC STDCALL NtGdiCreateMetaFile(LPCWSTR File)