mirror of
https://github.com/reactos/reactos.git
synced 2025-01-07 06:45:24 +00:00
[CLIPBRD]: Complete the read support from .clp clipboard files to be actually able to read files saved with the Windows 2k3 clipboard.
There actually exist two clipboard file formats, so-called "Win3.1" and a "WinNT" formats. Strangely enough Win2k (and Win2k3) clipboard viewer always save the files under the "Win3.1" format, whichever one you select. I discovered the subtle difference between those two formats by looking at a very old MSDN sample program "EMFDCODE (Enhanced Metafile Decoder)" by Dennis Crain (see https://web.archive.org/web/20080406095812/http://msdn.microsoft.com/archive/en-us/dnargdi/html/msdn_emfdcode.asp? ) that still can be found on the Internet... CORE-10550 #comment Read support fixed in r70730. svn path=/trunk/; revision=70730
This commit is contained in:
parent
3ef979d4d3
commit
8b028fbdc8
4 changed files with 195 additions and 58 deletions
|
@ -318,18 +318,18 @@ static void ClipboardPaintHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CF_ENHMETAFILE:
|
|
||||||
{
|
|
||||||
PlayEnhMetaFileFromClipboard(hdc, &rc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case CF_METAFILEPICT:
|
case CF_METAFILEPICT:
|
||||||
{
|
{
|
||||||
PlayMetaFileFromClipboard(hdc, &rc);
|
PlayMetaFileFromClipboard(hdc, &rc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case CF_ENHMETAFILE:
|
||||||
|
{
|
||||||
|
PlayEnhMetaFileFromClipboard(hdc, &rc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
|
DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* FILE: base/applications/clipbrd/fileutils.c
|
* FILE: base/applications/clipbrd/fileutils.c
|
||||||
* PURPOSE: Clipboard file format helper functions.
|
* PURPOSE: Clipboard file format helper functions.
|
||||||
* PROGRAMMERS: Ricardo Hanke
|
* PROGRAMMERS: Ricardo Hanke
|
||||||
|
* Hermes Belusca-Maito
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
@ -16,9 +17,7 @@ static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLe
|
||||||
|
|
||||||
hData = GlobalAlloc(GHND, dwLength);
|
hData = GlobalAlloc(GHND, dwLength);
|
||||||
if (!hData)
|
if (!hData)
|
||||||
{
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
lpData = GlobalLock(hData);
|
lpData = GlobalLock(hData);
|
||||||
if (!lpData)
|
if (!lpData)
|
||||||
|
@ -46,20 +45,22 @@ static HGLOBAL ClipboardReadMemoryBlock(HANDLE hFile, DWORD dwOffset, DWORD dwLe
|
||||||
return hData;
|
return hData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, LPCWSTR lpFormatName)
|
static BOOL ClipboardReadMemory(HANDLE hFile, DWORD dwFormat, DWORD dwOffset, DWORD dwLength, WORD FileIdentifier, PVOID lpFormatName)
|
||||||
{
|
{
|
||||||
HGLOBAL hData;
|
HGLOBAL hData;
|
||||||
DWORD dwTemp;
|
DWORD dwTemp;
|
||||||
|
|
||||||
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
|
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
|
||||||
if (!hData)
|
if (!hData)
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF))
|
if ((dwFormat >= 0xC000) && (dwFormat <= 0xFFFF))
|
||||||
{
|
{
|
||||||
dwTemp = RegisterClipboardFormatW(lpFormatName);
|
if (FileIdentifier == CLIP_FMT_31)
|
||||||
|
dwTemp = RegisterClipboardFormatA((LPCSTR)lpFormatName);
|
||||||
|
else if ((FileIdentifier == CLIP_FMT_NT) || (FileIdentifier == CLIP_FMT_BK))
|
||||||
|
dwTemp = RegisterClipboardFormatW((LPCWSTR)lpFormatName);
|
||||||
|
|
||||||
if (!dwTemp)
|
if (!dwTemp)
|
||||||
{
|
{
|
||||||
GlobalFree(hData);
|
GlobalFree(hData);
|
||||||
|
@ -120,6 +121,45 @@ static BOOL ClipboardReadPalette(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL ClipboardReadMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
|
||||||
|
{
|
||||||
|
HMETAFILE hMf;
|
||||||
|
HGLOBAL hData;
|
||||||
|
LPVOID lpData;
|
||||||
|
|
||||||
|
hData = ClipboardReadMemoryBlock(hFile, dwOffset, dwLength);
|
||||||
|
if (!hData)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lpData = GlobalLock(hData);
|
||||||
|
if (!lpData)
|
||||||
|
{
|
||||||
|
GlobalFree(hData);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hMf = SetMetaFileBitsEx(dwLength, lpData);
|
||||||
|
|
||||||
|
GlobalUnlock(hData);
|
||||||
|
GlobalFree(hData);
|
||||||
|
|
||||||
|
if (!hMf)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_OUTOFMEMORY);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetClipboardData(CF_METAFILEPICT, hMf))
|
||||||
|
{
|
||||||
|
DeleteMetaFile(hMf);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
|
static BOOL ClipboardReadEnhMetafile(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
|
||||||
{
|
{
|
||||||
HENHMETAFILE hEmf;
|
HENHMETAFILE hEmf;
|
||||||
|
@ -202,13 +242,27 @@ static BOOL ClipboardReadBitmap(HANDLE hFile, DWORD dwOffset, DWORD dwLength)
|
||||||
|
|
||||||
void ReadClipboardFile(LPCWSTR lpFileName)
|
void ReadClipboardFile(LPCWSTR lpFileName)
|
||||||
{
|
{
|
||||||
CLIPBOARDFILEHEADER cfhFileHeader;
|
CLIPFILEHEADER ClipFileHeader;
|
||||||
CLIPBOARDFORMATHEADER *cfhFormatArray = NULL;
|
CLIPFORMATHEADER ClipFormatArray;
|
||||||
|
NTCLIPFILEHEADER NtClipFileHeader;
|
||||||
|
NTCLIPFORMATHEADER NtClipFormatArray;
|
||||||
|
PVOID pClipFileHeader;
|
||||||
|
PVOID pClipFormatArray;
|
||||||
|
DWORD SizeOfFileHeader, SizeOfFormatHeader;
|
||||||
|
|
||||||
|
WORD wFileIdentifier;
|
||||||
|
WORD wFormatCount;
|
||||||
|
DWORD dwFormatID;
|
||||||
|
DWORD dwLenData;
|
||||||
|
DWORD dwOffData;
|
||||||
|
PVOID szName;
|
||||||
|
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
DWORD dwBytesRead;
|
DWORD dwBytesRead;
|
||||||
BOOL bResult;
|
BOOL bResult;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Open the file */
|
||||||
hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
hFile = CreateFileW(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
@ -216,39 +270,99 @@ void ReadClipboardFile(LPCWSTR lpFileName)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReadFile(hFile, &cfhFileHeader, sizeof(cfhFileHeader), &dwBytesRead, NULL))
|
/* Just read enough bytes to get the clipboard file format ID */
|
||||||
|
if (!ReadFile(hFile, &wFileIdentifier, sizeof(wFileIdentifier), &dwBytesRead, NULL))
|
||||||
|
{
|
||||||
|
ShowLastWin32Error(Globals.hMainWnd);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||||||
|
|
||||||
|
/* Set data according to the clipboard file format ID */
|
||||||
|
switch (wFileIdentifier)
|
||||||
|
{
|
||||||
|
case CLIP_FMT_31:
|
||||||
|
SizeOfFileHeader = sizeof(CLIPFILEHEADER);
|
||||||
|
SizeOfFormatHeader = sizeof(CLIPFORMATHEADER);
|
||||||
|
pClipFileHeader = &ClipFileHeader;
|
||||||
|
pClipFormatArray = &ClipFormatArray;
|
||||||
|
MessageBox(Globals.hMainWnd, L"We have a Win3.11 clipboard file!", L"File format", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLIP_FMT_NT:
|
||||||
|
case CLIP_FMT_BK:
|
||||||
|
SizeOfFileHeader = sizeof(NTCLIPFILEHEADER);
|
||||||
|
SizeOfFormatHeader = sizeof(NTCLIPFORMATHEADER);
|
||||||
|
pClipFileHeader = &NtClipFileHeader;
|
||||||
|
pClipFormatArray = &NtClipFormatArray;
|
||||||
|
MessageBox(Globals.hMainWnd, L"We have a WinNT clipboard file!", L"File format", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completely read the header */
|
||||||
|
if (!ReadFile(hFile, pClipFileHeader, SizeOfFileHeader, &dwBytesRead, NULL) ||
|
||||||
|
dwBytesRead != SizeOfFileHeader)
|
||||||
{
|
{
|
||||||
ShowLastWin32Error(Globals.hMainWnd);
|
ShowLastWin32Error(Globals.hMainWnd);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_NT) && (cfhFileHeader.wFileIdentifier != CLIPBOARD_FORMAT_BK))
|
/* Get header data */
|
||||||
|
switch (wFileIdentifier)
|
||||||
{
|
{
|
||||||
MessageBoxRes(Globals.hMainWnd, Globals.hInstance, ERROR_INVALID_FILE_FORMAT, 0, MB_ICONSTOP | MB_OK);
|
case CLIP_FMT_31:
|
||||||
goto done;
|
assert(wFileIdentifier == ((CLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
|
||||||
|
wFormatCount = ((CLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLIP_FMT_NT:
|
||||||
|
case CLIP_FMT_BK:
|
||||||
|
assert(wFileIdentifier == ((NTCLIPFILEHEADER*)pClipFileHeader)->wFileIdentifier);
|
||||||
|
wFormatCount = ((NTCLIPFILEHEADER*)pClipFileHeader)->wFormatCount;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfhFormatArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER));
|
/* Loop through the data array */
|
||||||
if (!cfhFormatArray)
|
for (i = 0; i < wFormatCount; i++)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_OUTOFMEMORY);
|
if (SetFilePointer(hFile, SizeOfFileHeader + i * SizeOfFormatHeader, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||||
ShowLastWin32Error(Globals.hMainWnd);
|
{
|
||||||
goto done;
|
ShowLastWin32Error(Globals.hMainWnd);
|
||||||
}
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ReadFile(hFile, cfhFormatArray, cfhFileHeader.wFormatCount * sizeof(CLIPBOARDFORMATHEADER), &dwBytesRead, NULL))
|
if (!ReadFile(hFile, pClipFormatArray, SizeOfFormatHeader, &dwBytesRead, NULL))
|
||||||
{
|
{
|
||||||
ShowLastWin32Error(Globals.hMainWnd);
|
ShowLastWin32Error(Globals.hMainWnd);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < cfhFileHeader.wFormatCount; i++)
|
/* Get format data */
|
||||||
{
|
switch (wFileIdentifier)
|
||||||
switch (cfhFormatArray[i].dwFormatID)
|
{
|
||||||
|
case CLIP_FMT_31:
|
||||||
|
dwFormatID = ((CLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
|
||||||
|
dwLenData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
|
||||||
|
dwOffData = ((CLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
|
||||||
|
szName = ((CLIPFORMATHEADER*)pClipFormatArray)->szName;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CLIP_FMT_NT:
|
||||||
|
case CLIP_FMT_BK:
|
||||||
|
dwFormatID = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwFormatID;
|
||||||
|
dwLenData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwLenData;
|
||||||
|
dwOffData = ((NTCLIPFORMATHEADER*)pClipFormatArray)->dwOffData;
|
||||||
|
szName = ((NTCLIPFORMATHEADER*)pClipFormatArray)->szName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (dwFormatID)
|
||||||
{
|
{
|
||||||
case CF_OWNERDISPLAY:
|
case CF_OWNERDISPLAY:
|
||||||
case CF_DSPMETAFILEPICT:
|
|
||||||
case CF_METAFILEPICT:
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -256,49 +370,47 @@ void ReadClipboardFile(LPCWSTR lpFileName)
|
||||||
case CF_BITMAP:
|
case CF_BITMAP:
|
||||||
case CF_DSPBITMAP:
|
case CF_DSPBITMAP:
|
||||||
{
|
{
|
||||||
bResult = ClipboardReadBitmap(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
|
bResult = ClipboardReadBitmap(hFile, dwOffData, dwLenData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CF_DSPENHMETAFILE:
|
case CF_METAFILEPICT:
|
||||||
case CF_ENHMETAFILE:
|
case CF_DSPMETAFILEPICT:
|
||||||
{
|
{
|
||||||
bResult = ClipboardReadEnhMetafile(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
|
bResult = ClipboardReadMetafile(hFile, dwOffData, dwLenData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CF_ENHMETAFILE:
|
||||||
|
case CF_DSPENHMETAFILE:
|
||||||
|
{
|
||||||
|
bResult = ClipboardReadEnhMetafile(hFile, dwOffData, dwLenData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CF_PALETTE:
|
case CF_PALETTE:
|
||||||
{
|
{
|
||||||
bResult = ClipboardReadPalette(hFile, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData);
|
bResult = ClipboardReadPalette(hFile, dwOffData, dwLenData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if ((cfhFormatArray[i].dwFormatID < CF_PRIVATEFIRST) || (cfhFormatArray[i].dwFormatID > CF_PRIVATELAST))
|
if ((dwFormatID < CF_PRIVATEFIRST) || (dwFormatID > CF_PRIVATELAST))
|
||||||
{
|
{
|
||||||
bResult = ClipboardReadMemory(hFile, cfhFormatArray[i].dwFormatID, cfhFormatArray[i].dwOffData, cfhFormatArray[i].dwLenData, cfhFormatArray[i].szName);
|
bResult = ClipboardReadMemory(hFile, dwFormatID, dwOffData, dwLenData, wFileIdentifier, szName);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bResult)
|
if (!bResult)
|
||||||
{
|
|
||||||
ShowLastWin32Error(Globals.hMainWnd);
|
ShowLastWin32Error(Globals.hMainWnd);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
{
|
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
}
|
|
||||||
|
|
||||||
if (cfhFormatArray)
|
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(), 0, cfhFormatArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,26 +4,49 @@
|
||||||
* FILE: base/applications/clipbrd/fileutils.h
|
* FILE: base/applications/clipbrd/fileutils.h
|
||||||
* PURPOSE: Clipboard file format helper functions.
|
* PURPOSE: Clipboard file format helper functions.
|
||||||
* PROGRAMMERS: Ricardo Hanke
|
* PROGRAMMERS: Ricardo Hanke
|
||||||
|
* Hermes Belusca-Maito
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CLIPBOARD_FORMAT_31 0xC350
|
#define CLIP_FMT_31 0xC350
|
||||||
#define CLIPBOARD_FORMAT_NT 0xC351
|
#define CLIP_FMT_NT 0xC351
|
||||||
#define CLIPBOARD_FORMAT_BK 0xC352
|
#define CLIP_FMT_BK 0xC352
|
||||||
#define MAX_FMT_NAME_LEN 79
|
#define MAX_FMT_NAME_LEN 79
|
||||||
|
|
||||||
typedef struct _CLIPBOARDFILEHEADER
|
/*
|
||||||
|
* Win3.1 Clipboard File Format (default)
|
||||||
|
*/
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct _CLIPFILEHEADER
|
||||||
{
|
{
|
||||||
WORD wFileIdentifier;
|
WORD wFileIdentifier;
|
||||||
WORD wFormatCount;
|
WORD wFormatCount;
|
||||||
} CLIPBOARDFILEHEADER;
|
} CLIPFILEHEADER;
|
||||||
|
|
||||||
typedef struct _CLIPBOARDFORMATHEADER
|
typedef struct _CLIPFORMATHEADER
|
||||||
|
{
|
||||||
|
WORD dwFormatID;
|
||||||
|
DWORD dwLenData;
|
||||||
|
DWORD dwOffData;
|
||||||
|
CHAR szName[MAX_FMT_NAME_LEN];
|
||||||
|
} CLIPFORMATHEADER;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NT Clipboard File Format
|
||||||
|
*/
|
||||||
|
typedef struct _NTCLIPFILEHEADER
|
||||||
|
{
|
||||||
|
WORD wFileIdentifier;
|
||||||
|
WORD wFormatCount;
|
||||||
|
} NTCLIPFILEHEADER;
|
||||||
|
|
||||||
|
typedef struct _NTCLIPFORMATHEADER
|
||||||
{
|
{
|
||||||
DWORD dwFormatID;
|
DWORD dwFormatID;
|
||||||
DWORD dwLenData;
|
DWORD dwLenData;
|
||||||
DWORD dwOffData;
|
DWORD dwOffData;
|
||||||
WCHAR szName[MAX_FMT_NAME_LEN];
|
WCHAR szName[MAX_FMT_NAME_LEN];
|
||||||
} CLIPBOARDFORMATHEADER;
|
} NTCLIPFORMATHEADER;
|
||||||
|
|
||||||
void ReadClipboardFile(LPCWSTR lpFileName);
|
void ReadClipboardFile(LPCWSTR lpFileName);
|
||||||
void WriteClipboardFile(LPCWSTR lpFileName);
|
void WriteClipboardFile(LPCWSTR lpFileName);
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <windef.h>
|
#include <windef.h>
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
|
|
Loading…
Reference in a new issue