mirror of
https://github.com/reactos/reactos.git
synced 2025-05-19 17:14:32 +00:00
[WINSPOOL] Implement DocumentPropertiesA including DEVMODE conversions (#2339)
Co-authored-by: Doug Lyons <douglyons@douglyons.com> Co-authored-by: Colin Finck <colin@reactos.org>
This commit is contained in:
parent
1e60116563
commit
3077c0e43e
3 changed files with 162 additions and 2 deletions
|
@ -233,3 +233,82 @@ Failure:
|
||||||
SetLastError(ERROR_INVALID_DATA);
|
SetLastError(ERROR_INVALID_DATA);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput)
|
||||||
|
{
|
||||||
|
// FIXME: This function should become ConvertAnsiDevModeToUnicodeDevmode when its parameters are known!
|
||||||
|
|
||||||
|
// Check if a pDevModeInput and pDevModeOutput are both not NULL.
|
||||||
|
if (!pDevModeInput || !pDevModeOutput)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pDevModeOutput = GdiConvertToDevmodeW(pDevModeInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal counterpart to GdiConvertToDevmodeW from gdi32
|
||||||
|
static __inline DEVMODEA*
|
||||||
|
_ConvertToDevmodeA(const DEVMODEW *dmW)
|
||||||
|
{
|
||||||
|
DEVMODEA *dmA;
|
||||||
|
WORD dmA_size, dmW_size;
|
||||||
|
size_t BytesToCopy;
|
||||||
|
|
||||||
|
dmW_size = dmW->dmSize;
|
||||||
|
|
||||||
|
/* this is the minimal dmSize that XP accepts */
|
||||||
|
if (dmW_size < FIELD_OFFSET(DEVMODEW, dmFields))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Guard against callers that set dmSize incorrectly.
|
||||||
|
if (dmW_size > sizeof(DEVMODEW))
|
||||||
|
dmW_size = sizeof(DEVMODEW);
|
||||||
|
|
||||||
|
// dmA_size must become dmW_size without the additional 1 byte per character for each Unicode string (dmDeviceName and dmFormName).
|
||||||
|
dmA_size = dmW_size - CCHDEVICENAME;
|
||||||
|
if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
|
||||||
|
dmA_size -= CCHFORMNAME;
|
||||||
|
|
||||||
|
// Allocate the required bytes, that is dmSize for the ANSI DEVMODEA structure plus any extra bytes requested through dmDriverExtra.
|
||||||
|
dmA = HeapAlloc(GetProcessHeap(), 0, dmA_size + dmW->dmDriverExtra);
|
||||||
|
if (!dmA) return NULL;
|
||||||
|
|
||||||
|
// Every valid DEVMODEW has a dmDeviceName, which we convert to ANSI here.
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
|
||||||
|
|
||||||
|
// Copy everything up to dmFormName or the remaining dmW_size, whatever is smaller.
|
||||||
|
BytesToCopy = min(FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion), dmW_size - CCHDEVICENAME * sizeof(WCHAR));
|
||||||
|
memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion, BytesToCopy);
|
||||||
|
|
||||||
|
// Handle dmFormName if the input DEVMODEW is large enough to contain one.
|
||||||
|
if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
if (dmW->dmFields & DM_FORMNAME)
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
|
||||||
|
else
|
||||||
|
dmA->dmFormName[0] = 0;
|
||||||
|
|
||||||
|
// Copy the remaining fields.
|
||||||
|
if (dmW_size > FIELD_OFFSET(DEVMODEW, dmLogPixels))
|
||||||
|
memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW_size - FIELD_OFFSET(DEVMODEW, dmLogPixels));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append dmDriverExtra if required.
|
||||||
|
if (dmW->dmDriverExtra)
|
||||||
|
memcpy((char *)dmA + dmA_size, (const char *)dmW + dmW_size, dmW->dmDriverExtra);
|
||||||
|
|
||||||
|
// Set the corrected dmSize and we are done.
|
||||||
|
dmA->dmSize = dmA_size;
|
||||||
|
|
||||||
|
return dmA;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput)
|
||||||
|
{
|
||||||
|
// FIXME: This function should become ConvertUnicodeDevModeToAnsiDevmode when its parameters are known!
|
||||||
|
|
||||||
|
// Check if a pDevModeInput and pDevModeOutput are both not NULL.
|
||||||
|
if (!pDevModeInput || !pDevModeOutput)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pDevModeOutput = _ConvertToDevmodeA(pDevModeInput);
|
||||||
|
}
|
||||||
|
|
|
@ -44,4 +44,9 @@ extern HANDLE hProcessHeap;
|
||||||
// utils.c
|
// utils.c
|
||||||
extern BOOL UnicodeToAnsiInPlace(PWSTR pwszField);
|
extern BOOL UnicodeToAnsiInPlace(PWSTR pwszField);
|
||||||
|
|
||||||
|
// devmode.c
|
||||||
|
extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput);
|
||||||
|
|
||||||
|
extern void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -205,9 +205,85 @@ DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG
|
||||||
LONG WINAPI
|
LONG WINAPI
|
||||||
DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
|
DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
|
||||||
{
|
{
|
||||||
|
PWSTR pwszDeviceName = NULL;
|
||||||
|
PDEVMODEW pdmwInput = NULL;
|
||||||
|
PDEVMODEW pdmwOutput = NULL;
|
||||||
|
BOOL bReturnValue = -1;
|
||||||
|
DWORD cch;
|
||||||
|
|
||||||
TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
|
TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
|
||||||
UNIMPLEMENTED;
|
|
||||||
return -1;
|
if (pDeviceName)
|
||||||
|
{
|
||||||
|
// Convert pName to a Unicode string pwszDeviceName.
|
||||||
|
cch = strlen(pDeviceName);
|
||||||
|
|
||||||
|
pwszDeviceName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
||||||
|
if (!pwszDeviceName)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
ERR("HeapAlloc failed!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiByteToWideChar(CP_ACP, 0, pDeviceName, -1, pwszDeviceName, cch + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevModeInput)
|
||||||
|
{
|
||||||
|
// Create working buffer for input to DocumentPropertiesW.
|
||||||
|
pdmwInput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
|
||||||
|
if (!pdmwInput)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
ERR("HeapAlloc failed!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
RosConvertAnsiDevModeToUnicodeDevmode(pDevModeInput, pdmwInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevModeOutput)
|
||||||
|
{
|
||||||
|
// Create working buffer for output from DocumentPropertiesW.
|
||||||
|
pdmwOutput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
|
||||||
|
if (!pdmwOutput)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
ERR("HeapAlloc failed!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bReturnValue = DocumentPropertiesW(hWnd, hPrinter, pwszDeviceName, pdmwOutput, pdmwInput, fMode);
|
||||||
|
TRACE("bReturnValue from DocumentPropertiesW is '%ld'.\n", bReturnValue);
|
||||||
|
|
||||||
|
if (pwszDeviceName)
|
||||||
|
{
|
||||||
|
HeapFree(hProcessHeap, 0, pwszDeviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bReturnValue < 0)
|
||||||
|
{
|
||||||
|
TRACE("DocumentPropertiesW failed!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdmwOutput)
|
||||||
|
{
|
||||||
|
RosConvertUnicodeDevModeToAnsiDevmode(pdmwOutput, pDevModeOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if(pwszDeviceName)
|
||||||
|
HeapFree(hProcessHeap, 0, pwszDeviceName);
|
||||||
|
|
||||||
|
if (pdmwInput)
|
||||||
|
HeapFree(hProcessHeap, 0, pdmwInput);
|
||||||
|
|
||||||
|
if (pdmwOutput)
|
||||||
|
HeapFree(hProcessHeap, 0, pdmwOutput);
|
||||||
|
|
||||||
|
return bReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
|
static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
|
||||||
|
|
Loading…
Reference in a new issue