https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7bffb703530d89e2c20f10...
commit 7bffb703530d89e2c20f1091d93c8d1f8325448d Author: James Tabor james.tabor@reactos.org AuthorDate: Mon Aug 3 21:07:58 2020 -0500 Commit: James Tabor james.tabor@reactos.org CommitDate: Mon Aug 3 21:07:58 2020 -0500
[Printing] Fix ups and Implementations.
WinSpool : Implement missing API. Sync/Port from wine. Setting it to fast track for needed testing of the later GDI code. Leaving Fix-me debug prints on. Local tree has WinSpool_winetest turned on. So no debug noise during normal ReactOS operation.
SpoolSS : Reordered header types. Have more Spl function to be added while SpoolSV is being coded to forward to LocalSpl.
Based on wine and old research from the GDI code. --- win32ss/printing/base/printui/printui.spec | 2 +- win32ss/printing/base/spoolss/memory.c | 5 +- win32ss/printing/base/spoolss/precomp.h | 8 - win32ss/printing/base/spoolsv/precomp.h | 23 - win32ss/printing/base/spoolsv/spoolfile.c | 8 +- win32ss/printing/base/winspool/CMakeLists.txt | 3 +- win32ss/printing/base/winspool/devmode.c | 58 +- win32ss/printing/base/winspool/forms.c | 441 +++- win32ss/printing/base/winspool/jobs.c | 347 ++- win32ss/printing/base/winspool/main.c | 9 +- win32ss/printing/base/winspool/monitors.c | 292 ++- win32ss/printing/base/winspool/ports.c | 528 ++++- win32ss/printing/base/winspool/precomp.h | 57 +- win32ss/printing/base/winspool/printerdata.c | 220 +- win32ss/printing/base/winspool/printerdrivers.c | 947 +++++++- win32ss/printing/base/winspool/printers.c | 2260 +++++++++++++++----- win32ss/printing/base/winspool/printprocessors.c | 184 +- win32ss/printing/base/winspool/printproviders.c | 137 +- win32ss/printing/base/winspool/spoolfile.c | 154 ++ win32ss/printing/base/winspool/utils.c | 278 +++ win32ss/printing/base/winspool/winspool.rc | 30 + win32ss/printing/base/winspool/winspool.spec | 62 +- win32ss/printing/include/marshalling/forms.h | 31 + .../printing/include/marshalling/printerdrivers.h | 50 +- win32ss/printing/include/spoolss.h | 10 + win32ss/printing/providers/localspl/spoolfile.c | 2 +- 26 files changed, 5442 insertions(+), 704 deletions(-)
diff --git a/win32ss/printing/base/printui/printui.spec b/win32ss/printing/base/printui/printui.spec index 2f2db27e1a6..e6ff2fd85da 100644 --- a/win32ss/printing/base/printui/printui.spec +++ b/win32ss/printing/base/printui/printui.spec @@ -1,6 +1,6 @@ @ stub ConnectToPrinterDlg @ stub ConnectToPrinterPropertyPage -@ stub ConstructPrinterFriendlyName +@ stdcall -stub ConstructPrinterFriendlyName(wstr wstr ptr) @ stub -private DllCanUnloadNow @ stub -private DllGetClassObject @ stub DocumentPropertiesWrap diff --git a/win32ss/printing/base/spoolss/memory.c b/win32ss/printing/base/spoolss/memory.c index 2eeed654886..d7f64d290c2 100644 --- a/win32ss/printing/base/spoolss/memory.c +++ b/win32ss/printing/base/spoolss/memory.c @@ -111,6 +111,7 @@ DllAllocSplMem(DWORD dwBytes) BOOL WINAPI DllFreeSplMem(PVOID pMem) { + if ( !pMem ) return TRUE; return HeapFree(hProcessHeap, 0, pMem); }
@@ -128,7 +129,9 @@ DllFreeSplMem(PVOID pMem) BOOL WINAPI DllFreeSplStr(PWSTR pwszString) { - return HeapFree(hProcessHeap, 0, pwszString); + if ( pwszString ) + return HeapFree(hProcessHeap, 0, pwszString); + return FALSE; }
/** diff --git a/win32ss/printing/base/spoolss/precomp.h b/win32ss/printing/base/spoolss/precomp.h index ee373e267d3..3a859aa2d7c 100644 --- a/win32ss/printing/base/spoolss/precomp.h +++ b/win32ss/printing/base/spoolss/precomp.h @@ -52,12 +52,4 @@ SPOOLSS_PRINTER_HANDLE, *PSPOOLSS_PRINTER_HANDLE; extern HANDLE hProcessHeap; extern LIST_ENTRY PrintProviderList;
-// spoolfile.c -typedef struct _FILE_INFO_1 -{ - BOOL bInheritHandle; - HANDLE hSpoolFileHandle; - DWORD dwOptions; -} FILE_INFO_1, *PFILE_INFO_1; - #endif diff --git a/win32ss/printing/base/spoolsv/precomp.h b/win32ss/printing/base/spoolsv/precomp.h index 79febdd6392..5ab518a43c6 100644 --- a/win32ss/printing/base/spoolsv/precomp.h +++ b/win32ss/printing/base/spoolsv/precomp.h @@ -28,27 +28,4 @@ WINE_DEFAULT_DEBUG_CHANNEL(spoolsv); // rpcserver.c DWORD WINAPI LrpcThreadProc(LPVOID lpParameter);
-// spoolfile.c -BOOL WINAPI -SplGetSpoolFileInfo( - HANDLE hPrinter, - HANDLE hProcessHandle, - DWORD Level, - WINSPOOL_FILE_INFO_1 *pFileInfo, - DWORD dwSize, - DWORD* dwNeeded ); - -BOOL WINAPI -SplCommitSpoolData( - HANDLE hPrinter, - HANDLE hProcessHandle, - DWORD cbCommit, - DWORD Level, - WINSPOOL_FILE_INFO_1 *pFileInfo, - DWORD dwSize, - DWORD* dwNeeded ); - -BOOL WINAPI -SplCloseSpoolFileHandle( HANDLE hPrinter ); - #endif diff --git a/win32ss/printing/base/spoolsv/spoolfile.c b/win32ss/printing/base/spoolsv/spoolfile.c index 67e808525d0..fee89ecf14b 100644 --- a/win32ss/printing/base/spoolsv/spoolfile.c +++ b/win32ss/printing/base/spoolsv/spoolfile.c @@ -19,7 +19,7 @@ _RpcGetSpoolFileInfo( WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_HANDLE hProcess return dwErrorCode; }
- if (!SplGetSpoolFileInfo( hPrinter, hProcessHandle, Level, pFileInfo, dwSize, dwNeeded ) ) + if (!SplGetSpoolFileInfo( hPrinter, hProcessHandle, Level, (FILE_INFO_1*)pFileInfo, dwSize, dwNeeded ) ) dwErrorCode = GetLastError();
RpcRevertToSelf(); @@ -38,7 +38,7 @@ _RpcCommitSpoolData( WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_HANDLE hProcessH return dwErrorCode; }
- if (!SplCommitSpoolData( hPrinter, hProcessHandle, cbCommit, Level, pFileInfo, dwSize, dwNeeded ) ) + if (!SplCommitSpoolData( hPrinter, hProcessHandle, cbCommit, Level, (FILE_INFO_1*)pFileInfo, dwSize, dwNeeded ) ) dwErrorCode = GetLastError();
RpcRevertToSelf(); @@ -61,7 +61,7 @@ _RpcGetSpoolFileInfo2( WINSPOOL_PRINTER_HANDLE hPrinter, DWORD dwProcessId, DWOR hProcessHandle = OpenProcess( PROCESS_DUP_HANDLE, FALSE, dwProcessId );
- if (!SplGetSpoolFileInfo( hPrinter, hProcessHandle, Level, pFileInfoContainer->FileInfo.pFileInfo1, sizeof(WINSPOOL_FILE_INFO_1), &dwNeeded ) ) + if (!SplGetSpoolFileInfo( hPrinter, hProcessHandle, Level, (FILE_INFO_1*)pFileInfoContainer->FileInfo.pFileInfo1, sizeof(FILE_INFO_1), &dwNeeded ) ) dwErrorCode = GetLastError();
if ( hProcessHandle ) @@ -88,7 +88,7 @@ _RpcCommitSpoolData2( WINSPOOL_PRINTER_HANDLE hPrinter, DWORD dwProcessId, DWORD
hProcessHandle = OpenProcess( PROCESS_DUP_HANDLE, FALSE, dwProcessId );
- if (!SplCommitSpoolData( hPrinter, hProcessHandle, cbCommit, Level, pFileInfoContainer->FileInfo.pFileInfo1, sizeof(WINSPOOL_FILE_INFO_1), &dwNeeded ) ) + if (!SplCommitSpoolData( hPrinter, hProcessHandle, cbCommit, Level, (FILE_INFO_1*)pFileInfoContainer->FileInfo.pFileInfo1, sizeof(FILE_INFO_1), &dwNeeded ) ) dwErrorCode = GetLastError();
if ( hProcessHandle ) diff --git a/win32ss/printing/base/winspool/CMakeLists.txt b/win32ss/printing/base/winspool/CMakeLists.txt index b557db8d0df..a0a838857cb 100644 --- a/win32ss/printing/base/winspool/CMakeLists.txt +++ b/win32ss/printing/base/winspool/CMakeLists.txt @@ -16,6 +16,7 @@ list(APPEND SOURCE printers.c printprocessors.c printproviders.c + spoolfile.c utils.c ${CMAKE_CURRENT_BINARY_DIR}/winspool_c.c)
@@ -31,6 +32,6 @@ add_library(winspool MODULE set_target_properties(winspool PROPERTIES SUFFIX ".drv") set_module_type(winspool win32dll UNICODE) target_link_libraries(winspool wine ${PSEH_LIB}) -add_importlibs(winspool advapi32 gdi32 rpcrt4 msvcrt kernel32 ntdll) +add_importlibs(winspool advapi32 gdi32 user32 rpcrt4 msvcrt kernel32 ntdll) add_pch(winspool precomp.h "${PCH_SKIP_SOURCE}") add_cd_file(TARGET winspool DESTINATION reactos/system32 FOR all) diff --git a/win32ss/printing/base/winspool/devmode.c b/win32ss/printing/base/winspool/devmode.c index c97f0e9ff58..fd1a615e3f4 100644 --- a/win32ss/printing/base/winspool/devmode.c +++ b/win32ss/printing/base/winspool/devmode.c @@ -234,7 +234,55 @@ Failure: return FALSE; }
-void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput) +BOOL WINAPI +IsValidDevmodeNoSizeW(PDEVMODEW pDevmode) +{ + PMINIMUM_SIZE_TABLE pTable = MinimumSizeW; + WORD wRequiredSize; + + TRACE("IsValidDevmodeNoSizeW(%p)\n", pDevmode); + + // Check if a Devmode was given at all. + if (!pDevmode) + goto Failure; + + // If the structure has private members, the public structure must be 32-bit packed. + if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4) + goto Failure; + + // Now determine the minimum possible dmSize based on the given fields in dmFields. + wRequiredSize = FIELD_OFFSET(DEVMODEW, dmFields) + RTL_FIELD_SIZE(DEVMODEW, dmFields); + + while (pTable->dwField) + { + if (pDevmode->dmFields & pTable->dwField) + { + wRequiredSize = pTable->wSize; + break; + } + + pTable++; + } + + // Verify that the value in dmSize is big enough for the used fields. + if (pDevmode->dmSize < wRequiredSize) + goto Failure; + + // Check if dmDeviceName and (if used) dmFormName are null-terminated. + // Fix this if they aren't. + _FixStringW(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName)); + if (pDevmode->dmFields & DM_FORMNAME) + _FixStringW(pDevmode->dmFormName, sizeof(pDevmode->dmFormName)); + + // Return success without setting the error code. + return TRUE; + +Failure: + SetLastError(ERROR_INVALID_DATA); + return FALSE; +} + +void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput) { // FIXME: This function should become ConvertAnsiDevModeToUnicodeDevmode when its parameters are known!
@@ -242,7 +290,7 @@ void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pD if (!pDevModeInput || !pDevModeOutput) return;
- pDevModeOutput = GdiConvertToDevmodeW(pDevModeInput); + *pDevModeOutput = GdiConvertToDevmodeW(pDevModeInput); }
// Internal counterpart to GdiConvertToDevmodeW from gdi32 @@ -304,11 +352,15 @@ _ConvertToDevmodeA(const DEVMODEW *dmW)
void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput) { + PDEVMODEA pTmp; + // 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); + pTmp = _ConvertToDevmodeA(pDevModeInput); + memcpy( pDevModeOutput, pTmp, pTmp->dmSize + pTmp->dmDriverExtra); // Copy into a Wide char (Larger) buffer. + HeapFree(hProcessHeap, 0, pTmp); } diff --git a/win32ss/printing/base/winspool/forms.c b/win32ss/printing/base/winspool/forms.c index 50ce5613387..7d8a0e65d9e 100644 --- a/win32ss/printing/base/winspool/forms.c +++ b/win32ss/printing/base/winspool/forms.c @@ -6,83 +6,486 @@ */
#include "precomp.h" +#include <marshalling/forms.h>
BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, PBYTE pForm) { + FORM_INFO_2W pfi2W; + PFORM_INFO_2A pfi2A; + DWORD len; + BOOL res; + + pfi2A = (PFORM_INFO_2A)pForm; + TRACE("AddFormA(%p, %lu, %p)\n", hPrinter, Level, pForm); - UNIMPLEMENTED; - return FALSE; + + if ((Level < 1) || (Level > 2)) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + if (!pfi2A) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W)); + + if (pfi2A->pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0); + pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len); + } + + pfi2W.Flags = pfi2A->Flags; + pfi2W.Size = pfi2A->Size; + pfi2W.ImageableArea = pfi2A->ImageableArea; + + if (Level > 1) + { + if (pfi2A->pKeyword) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0); + pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len); + } + + if (pfi2A->pMuiDll) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0); + pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len); + } + + if (pfi2A->pDisplayName) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0); + pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len); + } + pfi2W.StringType = pfi2A->StringType; + pfi2W.dwResourceId = pfi2A->dwResourceId; + pfi2W.wLangId = pfi2A->wLangId; + } + + res = AddFormW( hPrinter, Level, (PBYTE)&pfi2W ); + + if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName); + if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword); + if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll); + if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName); + + return res; }
BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, PBYTE pForm) { + DWORD dwErrorCode; + WINSPOOL_FORM_CONTAINER FormInfoContainer; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("AddFormW(%p, %lu, %p)\n", hPrinter, Level, pForm); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + return FALSE; + } + + if ((Level < 1) || (Level > 2)) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm; + FormInfoContainer.Level = Level; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcAddForm(pHandle->hPrinter, &FormInfoContainer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcAddForm failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI DeleteFormA(HANDLE hPrinter, PSTR pFormName) { + UNICODE_STRING FormNameW; + BOOL Ret; + TRACE("DeleteFormA(%p, %s)\n", hPrinter, pFormName); - UNIMPLEMENTED; - return FALSE; + + AsciiToUnicode(&FormNameW, pFormName); + + Ret = DeleteFormW( hPrinter, FormNameW.Buffer ); + + RtlFreeUnicodeString(&FormNameW); + + return Ret; }
BOOL WINAPI DeleteFormW(HANDLE hPrinter, PWSTR pFormName) { + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("DeleteFormW(%p, %S)\n", hPrinter, pFormName); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + return FALSE; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcDeleteForm(pHandle->hPrinter, pFormName); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcDeleteForm failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI EnumFormsA(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { + DWORD dwErrorCode, i; + PFORM_INFO_2W pfi2w = (PFORM_INFO_2W)pForm; + TRACE("EnumFormsA(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; + + if ( EnumFormsW( hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned ) ) + { + for ( i = 0; i < *pcReturned; i++ ) + { + switch ( Level ) + { + case 2: + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pKeyword); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pMuiDll); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w[i].pDisplayName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + // Fall through... + case 1: + dwErrorCode = UnicodeToAnsiInPlace(pfi2w[i].pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + } + return TRUE; + } +Cleanup: return FALSE; }
BOOL WINAPI EnumFormsW(HANDLE hPrinter, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("EnumFormsW(%p, %lu, %p, %lu, %p, %p)\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if ((Level < 1) || (Level > 2)) + { + ERR("Level = %d, unsupported!\n", Level); + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumForms(pHandle->hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumForms failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + ASSERT(Level >= 1 && Level <= 2); + MarshallUpStructuresArray(cbBuf, pForm, *pcReturned, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE); + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI GetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded) { + DWORD dwErrorCode, len; + LPWSTR FormNameW = NULL; + FORM_INFO_2W* pfi2w = (FORM_INFO_2W*)pForm; + TRACE("GetFormA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); - UNIMPLEMENTED; - return FALSE; + + if (pFormName) + { + len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0); + FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len); + } + + if ( GetFormW( hPrinter, FormNameW, Level, pForm, cbBuf, pcbNeeded ) ) + { + switch ( Level ) + { + case 2: + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pKeyword); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pMuiDll); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace((LPWSTR)pfi2w->pDisplayName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + // Fall through... + case 1: + dwErrorCode = UnicodeToAnsiInPlace(pfi2w->pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + break; + + default: + ERR("Level = %d, unsupported!\n", Level); + dwErrorCode = ERROR_INVALID_HANDLE; + SetLastError(dwErrorCode); + break; + } + } +Cleanup: + if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI GetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm, DWORD cbBuf, PDWORD pcbNeeded) { + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("GetFormW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Dismiss invalid levels already at this point. + if ((Level < 1) || (Level > 2)) + { + ERR("Level = %d, unsupported!\n", Level); + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (cbBuf && pForm) + ZeroMemory(pForm, cbBuf); + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcGetForm(pHandle->hPrinter, pFormName, Level, pForm, cbBuf, pcbNeeded); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcGetForm failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + ASSERT(Level >= 1 && Level <= 2); + MarshallUpStructure(cbBuf, pForm, pFormInfoMarshalling[Level]->pInfo, pFormInfoMarshalling[Level]->cbStructureSize, TRUE); + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI SetFormA(HANDLE hPrinter, PSTR pFormName, DWORD Level, PBYTE pForm) { + FORM_INFO_2W pfi2W; + FORM_INFO_2A * pfi2A; + LPWSTR FormNameW = NULL; + DWORD len; + BOOL res; + + pfi2A = (FORM_INFO_2A *) pForm; + TRACE("SetFormA(%p, %s, %lu, %p)\n", hPrinter, pFormName, Level, pForm); - UNIMPLEMENTED; - return FALSE; + + if ((Level < 1) || (Level > 2)) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + if (!pfi2A) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (pFormName) + { + len = MultiByteToWideChar(CP_ACP, 0, pFormName, -1, NULL, 0); + FormNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pFormName, -1, FormNameW, len); + } + + ZeroMemory(&pfi2W, sizeof(FORM_INFO_2W)); + + if (pfi2A->pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, NULL, 0); + pfi2W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pName, -1, pfi2W.pName, len); + } + + pfi2W.Flags = pfi2A->Flags; + pfi2W.Size = pfi2A->Size; + pfi2W.ImageableArea = pfi2A->ImageableArea; + + if (Level > 1) + { + if (pfi2A->pKeyword) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, NULL, 0); + pfi2W.pKeyword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pKeyword, -1, (LPWSTR)pfi2W.pKeyword, len); + } + + if (pfi2A->pMuiDll) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, NULL, 0); + pfi2W.pMuiDll = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pMuiDll, -1, (LPWSTR)pfi2W.pMuiDll, len); + } + + if (pfi2A->pDisplayName) + { + len = MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, NULL, 0); + pfi2W.pDisplayName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pfi2A->pDisplayName, -1, (LPWSTR)pfi2W.pDisplayName, len); + } + pfi2W.StringType = pfi2A->StringType; + pfi2W.dwResourceId = pfi2A->dwResourceId; + pfi2W.wLangId = pfi2A->wLangId; + } + + res = SetFormW( hPrinter, FormNameW, Level, (PBYTE)&pfi2W ); + + if (FormNameW) HeapFree(GetProcessHeap(), 0, FormNameW); + if (pfi2W.pName) HeapFree(GetProcessHeap(), 0, pfi2W.pName); + if (pfi2W.pKeyword) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pKeyword); + if (pfi2W.pMuiDll) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pMuiDll); + if (pfi2W.pDisplayName) HeapFree(GetProcessHeap(), 0, (LPWSTR)pfi2W.pDisplayName); + + return res; }
BOOL WINAPI SetFormW(HANDLE hPrinter, PWSTR pFormName, DWORD Level, PBYTE pForm) { + DWORD dwErrorCode; + WINSPOOL_FORM_CONTAINER FormInfoContainer; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("SetFormW(%p, %S, %lu, %p)\n", hPrinter, pFormName, Level, pForm); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + ERR("Level = %d, unsupported!\n", Level); + dwErrorCode = ERROR_INVALID_HANDLE; + return FALSE; + } + + FormInfoContainer.FormInfo.pFormInfo1 = (WINSPOOL_FORM_INFO_1*)pForm; + FormInfoContainer.Level = Level; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcSetForm(pHandle->hPrinter, pFormName, &FormInfoContainer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); } diff --git a/win32ss/printing/base/winspool/jobs.c b/win32ss/printing/base/winspool/jobs.c index e3cea6500cc..7cc17d40470 100644 --- a/win32ss/printing/base/winspool/jobs.c +++ b/win32ss/printing/base/winspool/jobs.c @@ -11,9 +11,30 @@ BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) { - TRACE("AddJobA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded); - UNIMPLEMENTED; - return FALSE; + BOOL ret; + + FIXME("AddJobA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded); + + if (Level != 1) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + ret = AddJobW(hPrinter, Level, pData, cbBuf, pcbNeeded); + + if (ret) + { + DWORD dwErrorCode; + ADDJOB_INFO_1W *addjobW = (ADDJOB_INFO_1W*)pData; + dwErrorCode = UnicodeToAnsiInPlace(addjobW->Path); + if (dwErrorCode != ERROR_SUCCESS) + { + ret = FALSE; + } + } + return ret; }
BOOL WINAPI @@ -22,7 +43,7 @@ AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded DWORD dwErrorCode; PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
- TRACE("AddJobW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded); + FIXME("AddJobW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded);
if (!pHandle) { @@ -46,6 +67,8 @@ AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded { // Replace relative offset addresses in the output by absolute pointers. MarshallUpStructure(cbBuf, pData, AddJobInfo1Marshalling.pInfo, AddJobInfo1Marshalling.cbStructureSize, TRUE); + pHandle->bJob = TRUE; + FIXME("Notify Tray Icon\n"); }
Cleanup: @@ -56,8 +79,118 @@ Cleanup: BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { + DWORD dwErrorCode, i; + JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pJob; + JOB_INFO_2A* pji2a = (JOB_INFO_2A*)pJob; + JOB_INFO_2W* pji2w = (JOB_INFO_2W*)pJob; + TRACE("EnumJobsA(%p, %lu, %lu, %lu, %p, %lu, %p, %p)\n", hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; + + if ( Level == 3 ) + return EnumJobsW( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned ); + + if ( EnumJobsW( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned ) ) + { + switch ( Level ) + { + case 1: + { + for ( i = 0; i < *pcReturned; i++ ) + { + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pPrinterName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pMachineName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pUserName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pDocument); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pDatatype); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pStatus); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + } + break; + + case 2: + { + for ( i = 0; i < *pcReturned; i++ ) + { + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pPrinterName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pMachineName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pUserName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pDocument); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pNotifyName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pDatatype); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pPrintProcessor); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pParameters); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pStatus); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + if ( pji2w[i].pDevMode ) + { + RosConvertUnicodeDevModeToAnsiDevmode( pji2w[i].pDevMode, pji2a[i].pDevMode ); + } + } + } + break; + } + return TRUE; + } +Cleanup: return FALSE; }
@@ -105,8 +238,108 @@ Cleanup: BOOL WINAPI GetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded) { - TRACE("GetJobA(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); - UNIMPLEMENTED; + DWORD dwErrorCode; + JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pJob; + JOB_INFO_2A* pji2a = (JOB_INFO_2A*)pJob; + JOB_INFO_2W* pji2w = (JOB_INFO_2W*)pJob; + + FIXME("GetJobA(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); + + if ( Level == 3 ) + return GetJobW( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded ); + + if ( GetJobW( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded ) ) + { + switch ( Level ) + { + case 1: + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pPrinterName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pMachineName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pUserName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pDocument); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pDatatype); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji1w->pStatus); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + break; + + case 2: + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pPrinterName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pMachineName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pUserName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pDocument); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pNotifyName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pDatatype); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pPrintProcessor); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pParameters); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pji2w->pStatus); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + if ( pji2w->pDevMode ) + { + RosConvertUnicodeDevModeToAnsiDevmode( pji2w->pDevMode, pji2a->pDevMode ); + } + break; + } + return TRUE; + } +Cleanup: return FALSE; }
@@ -116,7 +349,7 @@ GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWO DWORD dwErrorCode; PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
- TRACE("GetJobW(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); + FIXME("GetJobW(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
if (!pHandle) { @@ -174,6 +407,9 @@ ScheduleJob(HANDLE hPrinter, DWORD dwJobID) } RpcEndExcept;
+ if ( dwErrorCode == ERROR_SUCCESS ) + pHandle->bJob = FALSE; + Cleanup: SetLastError(dwErrorCode); return (dwErrorCode == ERROR_SUCCESS); @@ -182,9 +418,100 @@ Cleanup: BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) { + BOOL ret; + LPBYTE JobW; + UNICODE_STRING usBuffer; + TRACE("SetJobA(%p, %lu, %lu, %p, %lu)\n", hPrinter, JobId, Level, pJobInfo, Command); - UNIMPLEMENTED; - return FALSE; + + /* JobId, pPrinterName, pMachineName, pDriverName, Size, Submitted, Time and TotalPages + are all ignored by SetJob, so we don't bother copying them */ + switch(Level) + { + case 0: + JobW = NULL; + break; + case 1: + { + JOB_INFO_1W *info1W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info1W)); + ZeroMemory( info1W, sizeof(JOB_INFO_1W) ); + JOB_INFO_1A *info1A = (JOB_INFO_1A*)pJobInfo; + + JobW = (LPBYTE)info1W; + info1W->pUserName = AsciiToUnicode(&usBuffer, info1A->pUserName); + info1W->pDocument = AsciiToUnicode(&usBuffer, info1A->pDocument); + info1W->pDatatype = AsciiToUnicode(&usBuffer, info1A->pDatatype); + info1W->pStatus = AsciiToUnicode(&usBuffer, info1A->pStatus); + info1W->Status = info1A->Status; + info1W->Priority = info1A->Priority; + info1W->Position = info1A->Position; + info1W->PagesPrinted = info1A->PagesPrinted; + break; + } + case 2: + { + JOB_INFO_2W *info2W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info2W)); + ZeroMemory( info2W, sizeof(JOB_INFO_2W) ); + JOB_INFO_2A *info2A = (JOB_INFO_2A*)pJobInfo; + + JobW = (LPBYTE)info2W; + info2W->pUserName = AsciiToUnicode(&usBuffer, info2A->pUserName); + info2W->pDocument = AsciiToUnicode(&usBuffer, info2A->pDocument); + info2W->pNotifyName = AsciiToUnicode(&usBuffer, info2A->pNotifyName); + info2W->pDatatype = AsciiToUnicode(&usBuffer, info2A->pDatatype); + info2W->pPrintProcessor = AsciiToUnicode(&usBuffer, info2A->pPrintProcessor); + info2W->pParameters = AsciiToUnicode(&usBuffer, info2A->pParameters); + info2W->pDevMode = info2A->pDevMode ? GdiConvertToDevmodeW(info2A->pDevMode) : NULL; + info2W->pStatus = AsciiToUnicode(&usBuffer, info2A->pStatus); + info2W->pSecurityDescriptor = info2A->pSecurityDescriptor; + info2W->Status = info2A->Status; + info2W->Priority = info2A->Priority; + info2W->Position = info2A->Position; + info2W->StartTime = info2A->StartTime; + info2W->UntilTime = info2A->UntilTime; + info2W->PagesPrinted = info2A->PagesPrinted; + break; + } + case 3: + JobW = HeapAlloc(GetProcessHeap(), 0, sizeof(JOB_INFO_3)); + memcpy(JobW, pJobInfo, sizeof(JOB_INFO_3)); + break; + default: + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + ret = SetJobW(hPrinter, JobId, Level, JobW, Command); + + switch(Level) + { + case 1: + { + JOB_INFO_1W *info1W = (JOB_INFO_1W*)JobW; + HeapFree(GetProcessHeap(), 0, info1W->pUserName); + HeapFree(GetProcessHeap(), 0, info1W->pDocument); + HeapFree(GetProcessHeap(), 0, info1W->pDatatype); + HeapFree(GetProcessHeap(), 0, info1W->pStatus); + break; + } + case 2: + { + JOB_INFO_2W *info2W = (JOB_INFO_2W*)JobW; + HeapFree(GetProcessHeap(), 0, info2W->pUserName); + HeapFree(GetProcessHeap(), 0, info2W->pDocument); + HeapFree(GetProcessHeap(), 0, info2W->pNotifyName); + HeapFree(GetProcessHeap(), 0, info2W->pDatatype); + HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor); + HeapFree(GetProcessHeap(), 0, info2W->pParameters); + HeapFree(GetProcessHeap(), 0, info2W->pDevMode); + HeapFree(GetProcessHeap(), 0, info2W->pStatus); + break; + } + } + HeapFree(GetProcessHeap(), 0, JobW); + + return ret; }
BOOL WINAPI diff --git a/win32ss/printing/base/winspool/main.c b/win32ss/printing/base/winspool/main.c index c4f6f77ad1c..d9c66eb16d4 100644 --- a/win32ss/printing/base/winspool/main.c +++ b/win32ss/printing/base/winspool/main.c @@ -9,7 +9,8 @@
// Global Variables HANDLE hProcessHeap; - +HINSTANCE hinstWinSpool = NULL; +CRITICAL_SECTION rtlCritSec;
handle_t __RPC_USER WINSPOOL_HANDLE_bind(WINSPOOL_HANDLE wszName) @@ -79,6 +80,12 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); hProcessHeap = GetProcessHeap(); + hinstWinSpool = hinstDLL; + InitializeCriticalSection(&rtlCritSec); + break; + + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&rtlCritSec); break; }
diff --git a/win32ss/printing/base/winspool/monitors.c b/win32ss/printing/base/winspool/monitors.c index 18c6fd1d697..720d3537334 100644 --- a/win32ss/printing/base/winspool/monitors.c +++ b/win32ss/printing/base/winspool/monitors.c @@ -11,41 +11,298 @@ BOOL WINAPI AddMonitorA(PSTR pName, DWORD Level, PBYTE pMonitors) { - TRACE("AddMonitorA(%s, %lu, %p)\n", pName, Level, pMonitors); - UNIMPLEMENTED; - return FALSE; + LPWSTR nameW = NULL; + INT len; + BOOL res; + LPMONITOR_INFO_2A mi2a; + MONITOR_INFO_2W mi2w; + + mi2a = (LPMONITOR_INFO_2A) pMonitors; + TRACE("AddMonitorA(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors, + debugstr_a(mi2a ? mi2a->pName : NULL), + debugstr_a(mi2a ? mi2a->pEnvironment : NULL), + debugstr_a(mi2a ? mi2a->pDLLName : NULL)); + + if (Level != 2) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + /* XP: unchanged, win9x: ERROR_INVALID_ENVIRONMENT */ + if (mi2a == NULL) + { + return FALSE; + } + + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + memset(&mi2w, 0, sizeof(MONITOR_INFO_2W)); + if (mi2a->pName) + { + len = MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, NULL, 0); + mi2w.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, mi2a->pName, -1, mi2w.pName, len); + } + if (mi2a->pEnvironment) + { + len = MultiByteToWideChar(CP_ACP, 0, mi2a->pEnvironment, -1, NULL, 0); + mi2w.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, mi2a->pEnvironment, -1, mi2w.pEnvironment, len); + } + if (mi2a->pDLLName) + { + len = MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, NULL, 0); + mi2w.pDLLName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, mi2a->pDLLName, -1, mi2w.pDLLName, len); + } + + res = AddMonitorW(nameW, Level, (LPBYTE) &mi2w); + + HeapFree(GetProcessHeap(), 0, mi2w.pName); + HeapFree(GetProcessHeap(), 0, mi2w.pEnvironment); + HeapFree(GetProcessHeap(), 0, mi2w.pDLLName); + HeapFree(GetProcessHeap(), 0, nameW); + + return (res); }
BOOL WINAPI AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors) { + DWORD dwErrorCode; + WINSPOOL_MONITOR_CONTAINER MonitorInfoContainer; TRACE("AddMonitorW(%S, %lu, %p)\n", pName, Level, pMonitors); - UNIMPLEMENTED; - return FALSE; + + if (Level != 2) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + MonitorInfoContainer.MonitorInfo.pMonitorInfo2 = (WINSPOOL_MONITOR_INFO_2*)pMonitors; + MonitorInfoContainer.Level = Level; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcAddMonitor(pName, &MonitorInfoContainer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcAddMonitor failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI DeleteMonitorA(PSTR pName, PSTR pEnvironment, PSTR pMonitorName) { + LPWSTR nameW = NULL; + LPWSTR EnvironmentW = NULL; + LPWSTR MonitorNameW = NULL; + BOOL res; + INT len; + TRACE("DeleteMonitorA(%s, %s, %s)\n", pName, pEnvironment, pMonitorName); - UNIMPLEMENTED; - return FALSE; + + if (pName) { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + if (pEnvironment) { + len = MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, NULL, 0); + EnvironmentW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, EnvironmentW, len); + } + if (pMonitorName) { + len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0); + MonitorNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, MonitorNameW, len); + } + + res = DeleteMonitorW(nameW, EnvironmentW, MonitorNameW); + + HeapFree(GetProcessHeap(), 0, MonitorNameW); + HeapFree(GetProcessHeap(), 0, EnvironmentW); + HeapFree(GetProcessHeap(), 0, nameW); + + return (res); }
BOOL WINAPI DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName) { + DWORD dwErrorCode; + TRACE("DeleteMonitorW(%S, %S, %S)\n", pName, pEnvironment, pMonitorName); - UNIMPLEMENTED; - return FALSE; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcDeleteMonitor(pName, pEnvironment, pMonitorName); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcDeleteMonitor failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); + }
BOOL WINAPI EnumMonitorsA(PSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - TRACE("EnumMonitorsA(%s, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; - return FALSE; + BOOL res; + LPBYTE bufferW = NULL; + LPWSTR nameW = NULL; + DWORD needed = 0; + DWORD numentries = 0; + INT len; + + FIXME("EnumMonitorsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pMonitors, cbBuf, pcbNeeded, pcReturned); + + if ( Level < 1 || Level > 2 ) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError( ERROR_INVALID_LEVEL ); + return FALSE; + } + + /* convert servername to unicode */ + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the monitors */ + needed = cbBuf * sizeof(WCHAR); + if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed); + res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); + + if(!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + if (pcbNeeded) needed = *pcbNeeded; + /* HeapReAlloc return NULL, when bufferW was NULL */ + bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) : + HeapAlloc(GetProcessHeap(), 0, needed); + + /* Try again with the large Buffer */ + res = EnumMonitorsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); + } + numentries = pcReturned ? *pcReturned : 0; + needed = 0; + /* + W2k require the buffersize from EnumMonitorsW also for EnumMonitorsA. + We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps. + */ + if (res) + { + /* EnumMonitorsW collected all Data. Parse them to calculate ANSI-Size */ + DWORD entrysize = 0; + DWORD index; + LPSTR ptr; + LPMONITOR_INFO_2W mi2w; + LPMONITOR_INFO_2A mi2a; + + /* MONITOR_INFO_*W and MONITOR_INFO_*A have the same size */ + entrysize = (Level == 1) ? sizeof(MONITOR_INFO_1A) : sizeof(MONITOR_INFO_2A); + + /* First pass: calculate the size for all Entries */ + mi2w = (LPMONITOR_INFO_2W) bufferW; + mi2a = (LPMONITOR_INFO_2A) pMonitors; + index = 0; + while (index < numentries) + { + index++; + needed += entrysize; /* MONITOR_INFO_?A */ + TRACE("%p: parsing #%d (%s)\n", mi2w, index, debugstr_w(mi2w->pName)); + + needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1, + NULL, 0, NULL, NULL); + if (Level > 1) + { + needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1, + NULL, 0, NULL, NULL); + needed += WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1, + NULL, 0, NULL, NULL); + } + /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */ + mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize); + mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize); + } + + /* check for errors and quit on failure */ + if (cbBuf < needed) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + res = FALSE; + goto emA_cleanup; + } + len = entrysize * numentries; /* room for all MONITOR_INFO_?A */ + ptr = (LPSTR) &pMonitors[len]; /* room for strings */ + cbBuf -= len ; /* free Bytes in the user-Buffer */ + mi2w = (LPMONITOR_INFO_2W) bufferW; + mi2a = (LPMONITOR_INFO_2A) pMonitors; + index = 0; + /* Second Pass: Fill the User Buffer (if we have one) */ + while ((index < numentries) && pMonitors) + { + index++; + TRACE("%p: writing MONITOR_INFO_%dA #%d\n", mi2a, Level, index); + mi2a->pName = ptr; + len = WideCharToMultiByte(CP_ACP, 0, mi2w->pName, -1, + ptr, cbBuf , NULL, NULL); + ptr += len; + cbBuf -= len; + if (Level > 1) + { + mi2a->pEnvironment = ptr; + len = WideCharToMultiByte(CP_ACP, 0, mi2w->pEnvironment, -1, + ptr, cbBuf, NULL, NULL); + ptr += len; + cbBuf -= len; + + mi2a->pDLLName = ptr; + len = WideCharToMultiByte(CP_ACP, 0, mi2w->pDLLName, -1, + ptr, cbBuf, NULL, NULL); + ptr += len; + cbBuf -= len; + } + /* use LPBYTE with entrysize to avoid double code (MONITOR_INFO_1 + MONITOR_INFO_2) */ + mi2w = (LPMONITOR_INFO_2W) (((LPBYTE)mi2w) + entrysize); + mi2a = (LPMONITOR_INFO_2A) (((LPBYTE)mi2a) + entrysize); + } + } +emA_cleanup: + if (pcbNeeded) *pcbNeeded = needed; + if (pcReturned) *pcReturned = (res) ? numentries : 0; + + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, bufferW); + + FIXME("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries); + + return (res); + }
BOOL WINAPI @@ -53,7 +310,14 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb { DWORD dwErrorCode;
- TRACE("EnumMonitorsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned); + FIXME("EnumMonitorsW(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned); + + if ( Level < 1 || Level > 2 ) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError( ERROR_INVALID_LEVEL ); + return FALSE; + }
// Do the RPC call RpcTryExcept @@ -63,7 +327,7 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb RpcExcept(EXCEPTION_EXECUTE_HANDLER) { dwErrorCode = RpcExceptionCode(); - ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode); + ERR("_RpcEnumMonitors failed with exception code %lu!\n", dwErrorCode); } RpcEndExcept;
diff --git a/win32ss/printing/base/winspool/ports.c b/win32ss/printing/base/winspool/ports.c index f243567407e..80854ab23cf 100644 --- a/win32ss/printing/base/winspool/ports.c +++ b/win32ss/printing/base/winspool/ports.c @@ -8,76 +8,475 @@ #include "precomp.h" #include <marshalling/ports.h>
+typedef struct _PORTTHREADINFO +{ + LPWSTR pName; + HWND hWnd; + LPWSTR pPortName; + FARPROC fpFunction; + DWORD dwErrorCode; + HANDLE hEvent; +} PORTTHREADINFO, *PPORTTHREADINFO; + +VOID WINAPI +IntPortThread( PPORTTHREADINFO pPortThreadInfo ) +{ + // Do the RPC call + RpcTryExcept + { + pPortThreadInfo->dwErrorCode = (*pPortThreadInfo->fpFunction)( pPortThreadInfo->pName, pPortThreadInfo->hWnd, pPortThreadInfo->pPortName); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + pPortThreadInfo->dwErrorCode = RpcExceptionCode(); + } + RpcEndExcept; + + SetEvent( pPortThreadInfo->hEvent ); +} + +// +// Start a thread to wait on a printer port. +// BOOL WINAPI -AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName) +StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction ) { - TRACE("AddPortA(%s, %p, %s)\n", pName, hWnd, pMonitorName); - UNIMPLEMENTED; - return FALSE; + PORTTHREADINFO PortThreadInfo; + HANDLE htHandle; + MSG Msg; + DWORD tid; + + if ( hWnd ) EnableWindow( hWnd, FALSE ); + + PortThreadInfo.pName = pName; + PortThreadInfo.hWnd = hWnd; + PortThreadInfo.pPortName = pPortName; + PortThreadInfo.fpFunction = fpFunction; + PortThreadInfo.dwErrorCode = ERROR_SUCCESS; + PortThreadInfo.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); + + htHandle = CreateThread( NULL, + 32*1024, + (LPTHREAD_START_ROUTINE)IntPortThread, + &PortThreadInfo, + 0, + &tid ); + + CloseHandle( htHandle ); + + while ( MsgWaitForMultipleObjects( 1, &PortThreadInfo.hEvent, FALSE, INFINITE, QS_SENDMESSAGE|QS_ALLEVENTS ) == 1 ) + { + while ( PeekMessageW( &Msg, NULL, 0, 0, PM_REMOVE ) ) + { + TranslateMessage( &Msg ); + DispatchMessageW( &Msg ); + } + } + + CloseHandle( PortThreadInfo.hEvent ); + + if ( hWnd ) + { + EnableWindow(hWnd, TRUE); + SetForegroundWindow(hWnd); + SetFocus(hWnd); + } + + SetLastError(PortThreadInfo.dwErrorCode); + return (PortThreadInfo.dwErrorCode == ERROR_SUCCESS); }
+ BOOL WINAPI -AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName) +AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName) { - TRACE("AddPortExA(%s, %lu, %p, %s)\n", pName, Level, lpBuffer, lpMonitorName); - UNIMPLEMENTED; - return FALSE; + LPWSTR nameW = NULL; + LPWSTR monitorW = NULL; + DWORD len; + BOOL res; + + TRACE("AddPortA(%s, %p, %s)\n",debugstr_a(pName), hWnd, debugstr_a(pMonitorName)); + + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + if (pMonitorName) + { + len = MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, NULL, 0); + monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pMonitorName, -1, monitorW, len); + } + + res = AddPortW(nameW, hWnd, monitorW); + + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, monitorW); + + return res; }
BOOL WINAPI AddPortExW(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName) { - TRACE("AddPortExA(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName); - UNIMPLEMENTED; - return FALSE; + DWORD dwErrorCode; + WINSPOOL_PORT_CONTAINER PortInfoContainer; + WINSPOOL_PORT_VAR_CONTAINER PortVarContainer; + WINSPOOL_PORT_INFO_FF *pPortInfoFF; + + TRACE("AddPortExW(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName); + + switch (Level) + { + case 1: + // FIXME!!!! Only Level 1 is supported? See note in wine winspool test info.c : line 575. + PortInfoContainer.PortInfo.pPortInfo1 = (WINSPOOL_PORT_INFO_1*)lpBuffer; + PortInfoContainer.Level = Level; + PortVarContainer.cbMonitorData = 0; + PortVarContainer.pMonitorData = NULL; + break; + + case 0xFFFFFFFF: + pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer; + PortInfoContainer.PortInfo.pPortInfoFF = pPortInfoFF; + PortInfoContainer.Level = Level; + PortVarContainer.cbMonitorData = pPortInfoFF->cbMonitorData; + PortVarContainer.pMonitorData = pPortInfoFF->pMonitorData; + break; + + default: + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcAddPortEx(pName, &PortInfoContainer, &PortVarContainer, lpMonitorName); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName) +{ + PORT_INFO_1W pi1W; + PORT_INFO_1A * pi1A; + LPWSTR nameW = NULL; + LPWSTR monitorW = NULL; + DWORD len; + BOOL res = FALSE; + WINSPOOL_PORT_INFO_FF *pPortInfoFF, PortInfoFF; + + pi1A = (PORT_INFO_1A *)lpBuffer; + pPortInfoFF = (WINSPOOL_PORT_INFO_FF*)lpBuffer; + + TRACE("AddPortExA(%s, %d, %p, %s): %s\n", debugstr_a(pName), Level, lpBuffer, debugstr_a(lpMonitorName), debugstr_a(pi1A ? pi1A->pName : NULL)); + + if ( !lpBuffer || !lpMonitorName ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + if (lpMonitorName) + { + len = MultiByteToWideChar(CP_ACP, 0, lpMonitorName, -1, NULL, 0); + monitorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, lpMonitorName, -1, monitorW, len); + } + + pi1W.pName = NULL; + ZeroMemory( &PortInfoFF, sizeof(WINSPOOL_PORT_INFO_FF)); + + switch ( Level ) + { + case 1: + if ( pi1A->pName ) + { + len = MultiByteToWideChar(CP_ACP, 0, pi1A->pName, -1, NULL, 0); + pi1W.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pi1A->pName, -1, pi1W.pName, len); + } + break; + + case 0xFFFFFFFF: + // + // Remember the calling parameter is Ansi. + // + if ( !pPortInfoFF->pPortName || !(PCHAR)pPortInfoFF->pPortName ) + { + SetLastError(ERROR_INVALID_PARAMETER); + goto Cleanup; + } + + len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pPortInfoFF->pPortName, -1, NULL, 0); + PortInfoFF.pPortName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pPortInfoFF->pPortName, -1, (LPWSTR)PortInfoFF.pPortName, len); + + PortInfoFF.cbMonitorData = pPortInfoFF->cbMonitorData; + PortInfoFF.pMonitorData = pPortInfoFF->pMonitorData; + break; + + default: + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + goto Cleanup; + } + + res = AddPortExW( nameW, Level, Level == 1 ? (PBYTE)&pi1W : (PBYTE)&PortInfoFF, monitorW ); + +Cleanup: + if (nameW) HeapFree(GetProcessHeap(), 0, nameW); + if (monitorW) HeapFree(GetProcessHeap(), 0, monitorW); + if (pi1W.pName) HeapFree(GetProcessHeap(), 0, pi1W.pName); + if (PortInfoFF.pPortName) HeapFree(GetProcessHeap(), 0, PortInfoFF.pPortName); + + return res; }
BOOL WINAPI AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName) { TRACE("AddPortW(%S, %p, %S)\n", pName, hWnd, pMonitorName); - UNIMPLEMENTED; - return FALSE; + return StartPortThread(pName, hWnd, pMonitorName, (FARPROC)_RpcAddPort); }
BOOL WINAPI ConfigurePortA(PSTR pName, HWND hWnd, PSTR pPortName) { - TRACE("ConfigurePortA(%s, %p, %s)\n", pName, hWnd, pPortName); - UNIMPLEMENTED; - return FALSE; + LPWSTR nameW = NULL; + LPWSTR portW = NULL; + INT len; + DWORD res; + + TRACE("ConfigurePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName)); + + /* convert servername to unicode */ + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + /* convert portname to unicode */ + if (pPortName) + { + len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0); + portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len); + } + + res = ConfigurePortW(nameW, hWnd, portW); + + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, portW); + + return res; }
BOOL WINAPI ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName) { TRACE("ConfigurePortW(%S, %p, %S)\n", pName, hWnd, pPortName); - UNIMPLEMENTED; - return FALSE; + return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcConfigurePort); }
BOOL WINAPI DeletePortA(PSTR pName, HWND hWnd, PSTR pPortName) { - TRACE("DeletePortA(%s, %p, %s)\n", pName, hWnd, pPortName); - UNIMPLEMENTED; - return FALSE; + LPWSTR nameW = NULL; + LPWSTR portW = NULL; + INT len; + DWORD res; + + TRACE("DeletePortA(%s, %p, %s)\n", debugstr_a(pName), hWnd, debugstr_a(pPortName)); + + /* convert servername to unicode */ + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + /* convert portname to unicode */ + if (pPortName) + { + len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0); + portW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPortName, -1, portW, len); + } + + res = DeletePortW(nameW, hWnd, portW); + + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, portW); + + return res; }
BOOL WINAPI DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName) { TRACE("DeletePortW(%S, %p, %S)\n", pName, hWnd, pPortName); - UNIMPLEMENTED; - return FALSE; + return StartPortThread(pName, hWnd, pPortName, (FARPROC)_RpcDeletePort); }
BOOL WINAPI EnumPortsA(PSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - TRACE("EnumPortsA(%s, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; - return FALSE; + BOOL res; + LPBYTE bufferW = NULL; + LPWSTR nameW = NULL; + DWORD needed = 0; + DWORD numentries = 0; + INT len; + + TRACE("EnumPortsA(%s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), Level, pPorts, cbBuf, pcbNeeded, pcReturned); + + /* convert servername to unicode */ + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + /* alloc (userbuffersize*sizeof(WCHAR) and try to enum the Ports */ + needed = cbBuf * sizeof(WCHAR); + if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed); + res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); + + if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + if (pcbNeeded) needed = *pcbNeeded; + /* HeapReAlloc return NULL, when bufferW was NULL */ + bufferW = (bufferW) ? HeapReAlloc(GetProcessHeap(), 0, bufferW, needed) : + HeapAlloc(GetProcessHeap(), 0, needed); + + /* Try again with the large Buffer */ + res = EnumPortsW(nameW, Level, bufferW, needed, pcbNeeded, pcReturned); + } + needed = pcbNeeded ? *pcbNeeded : 0; + numentries = pcReturned ? *pcReturned : 0; + + /* + W2k require the buffersize from EnumPortsW also for EnumPortsA. + We use the smaller Ansi-Size to avoid conflicts with fixed Buffers of old Apps. + */ + if (res) + { + /* EnumPortsW collected all Data. Parse them to calculate ANSI-Size */ + DWORD entrysize = 0; + DWORD index; + LPSTR ptr; + LPPORT_INFO_2W pi2w; + LPPORT_INFO_2A pi2a; + + needed = 0; + entrysize = (Level == 1) ? sizeof(PORT_INFO_1A) : sizeof(PORT_INFO_2A); + + /* First pass: calculate the size for all Entries */ + pi2w = (LPPORT_INFO_2W) bufferW; + pi2a = (LPPORT_INFO_2A) pPorts; + index = 0; + while (index < numentries) + { + index++; + needed += entrysize; /* PORT_INFO_?A */ + TRACE("%p: parsing #%d (%s)\n", pi2w, index, debugstr_w(pi2w->pPortName)); + + needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1, + NULL, 0, NULL, NULL); + if (Level > 1) + { + needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1, + NULL, 0, NULL, NULL); + needed += WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1, + NULL, 0, NULL, NULL); + } + /* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */ + pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize); + pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize); + } + + /* check for errors and quit on failure */ + if (cbBuf < needed) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + res = FALSE; + goto cleanup; + } + len = entrysize * numentries; /* room for all PORT_INFO_?A */ + ptr = (LPSTR) &pPorts[len]; /* room for strings */ + cbBuf -= len ; /* free Bytes in the user-Buffer */ + pi2w = (LPPORT_INFO_2W) bufferW; + pi2a = (LPPORT_INFO_2A) pPorts; + index = 0; + /* Second Pass: Fill the User Buffer (if we have one) */ + while ((index < numentries) && pPorts) + { + index++; + TRACE("%p: writing PORT_INFO_%dA #%d\n", pi2a, Level, index); + pi2a->pPortName = ptr; + len = WideCharToMultiByte(CP_ACP, 0, pi2w->pPortName, -1, + ptr, cbBuf , NULL, NULL); + ptr += len; + cbBuf -= len; + if (Level > 1) + { + pi2a->pMonitorName = ptr; + len = WideCharToMultiByte(CP_ACP, 0, pi2w->pMonitorName, -1, + ptr, cbBuf, NULL, NULL); + ptr += len; + cbBuf -= len; + + pi2a->pDescription = ptr; + len = WideCharToMultiByte(CP_ACP, 0, pi2w->pDescription, -1, + ptr, cbBuf, NULL, NULL); + ptr += len; + cbBuf -= len; + + pi2a->fPortType = pi2w->fPortType; + pi2a->Reserved = 0; /* documented: "must be zero" */ + + } + /* use LPBYTE with entrysize to avoid double code (PORT_INFO_1 + PORT_INFO_2) */ + pi2w = (LPPORT_INFO_2W) (((LPBYTE)pi2w) + entrysize); + pi2a = (LPPORT_INFO_2A) (((LPBYTE)pi2a) + entrysize); + } + } + +cleanup: + if (pcbNeeded) *pcbNeeded = needed; + if (pcReturned) *pcReturned = (res) ? numentries : 0; + + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, bufferW); + + TRACE("returning %d with %d (%d byte for %d of %d entries)\n", + (res), GetLastError(), needed, (res)? numentries : 0, numentries); + + return (res); }
BOOL WINAPI @@ -113,15 +512,84 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded BOOL WINAPI SetPortA(PSTR pName, PSTR pPortName, DWORD dwLevel, PBYTE pPortInfo) { + LPWSTR NameW = NULL; + LPWSTR PortNameW = NULL; + PORT_INFO_3W pi3W; + PORT_INFO_3A *pi3A; + DWORD len; + BOOL res; + TRACE("SetPortA(%s, %s, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo); - UNIMPLEMENTED; - return FALSE; + + if ( dwLevel != 3 ) + { + ERR("Level = %d, unsupported!\n", dwLevel); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + NameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, NameW, len); + } + + if (pPortName) + { + len = MultiByteToWideChar(CP_ACP, 0, pPortName, -1, NULL, 0); + PortNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pPortName, -1, PortNameW, len); + } + + if (pi3A->pszStatus) + { + len = MultiByteToWideChar(CP_ACP, 0, pi3A->pszStatus, -1, NULL, 0); + pi3W.pszStatus = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pi3A->pszStatus, -1, pi3W.pszStatus, len); + } + + pi3W.dwStatus = pi3A->dwStatus; + pi3W.dwSeverity = pi3A->dwSeverity; + + res = SetPortW( NameW, PortNameW, dwLevel, (PBYTE)&pi3W ); + + if (NameW) HeapFree(GetProcessHeap(), 0, NameW); + if (PortNameW) HeapFree(GetProcessHeap(), 0, PortNameW); + if (pi3W.pszStatus) HeapFree(GetProcessHeap(), 0, pi3W.pszStatus); + + return res; }
BOOL WINAPI SetPortW(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo) { + DWORD dwErrorCode; + WINSPOOL_PORT_CONTAINER PortInfoContainer; + TRACE("SetPortW(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo); - UNIMPLEMENTED; - return FALSE; + + if ( dwLevel != 3 ) + { + ERR("Level = %d, unsupported!\n", dwLevel); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + PortInfoContainer.PortInfo.pPortInfo3 = (WINSPOOL_PORT_INFO_3*)pPortInfo; + PortInfoContainer.Level = dwLevel; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcSetPort(pName, pPortName, &PortInfoContainer); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); } diff --git a/win32ss/printing/base/winspool/precomp.h b/win32ss/printing/base/winspool/precomp.h index e5a857b34e0..05eb85098b2 100644 --- a/win32ss/printing/base/winspool/precomp.h +++ b/win32ss/printing/base/winspool/precomp.h @@ -11,10 +11,12 @@ #define WIN32_NO_STATUS #include <windef.h> #include <winbase.h> +#include <winuser.h> #include <wingdi.h> #include <winreg.h> #include <winspool.h> #include <winspool_c.h> +#include <winsplp.h> #include <winddiui.h> #include <ndk/rtlfuncs.h> #include <strsafe.h> @@ -25,28 +27,79 @@ #include <wine/debug.h> WINE_DEFAULT_DEBUG_CHANNEL(winspool);
+#define SPOOLER_HANDLE_SIG 'gg' + // Structures /* - * Describes a handle returned by OpenPrinterW. + * Describes a handle returned by AddPrinterW or OpenPrinterW. */ typedef struct _SPOOLER_HANDLE { + DWORD_PTR Sig; BOOL bStartedDoc : 1; + BOOL bJob : 1; + BOOL bAnsi : 1; + BOOL bDocEvent : 1; + BOOL bTrayIcon : 1; + BOOL bNoColorProfile : 1; + BOOL bShared : 1; + BOOL bClosed : 1; DWORD dwJobID; HANDLE hPrinter; HANDLE hSPLFile; + DWORD cCount; + HANDLE hSpoolFileHandle; + DWORD dwOptions; } SPOOLER_HANDLE, *PSPOOLER_HANDLE;
// main.c extern HANDLE hProcessHeap; +extern CRITICAL_SECTION rtlCritSec;
// utils.c DWORD UnicodeToAnsiInPlace(PWSTR pwszField); +DWORD UnicodeToAnsiZZInPlace(PWSTR pwszzField); +SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size ); +LONG WINAPI IntProtectHandle(HANDLE,BOOL); +BOOL WINAPI IntUnprotectHandle(HANDLE);
// devmode.c -extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput); +extern void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput);
extern void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput);
+// RC + +#define IDS_CAPTION 10 +#define IDS_FILE_EXISTS 11 +#define IDS_CANNOT_OPEN 12 +#define FILENAME_DIALOG 100 +#define EDITBOX 201 + +// +// [MS-EMF] 2.2.27 UniversalFontId Object +// +typedef struct _UNIVERSAL_FONT_ID +{ + ULONG CheckSum; + ULONG Index; +} UNIVERSAL_FONT_ID, *PUNIVERSAL_FONT_ID; + +BOOL WINAPI IsValidDevmodeNoSizeW(PDEVMODEW pDevmode); + +/* RtlCreateUnicodeStringFromAsciiz will return an empty string in the buffer + if passed a NULL string. This returns NULLs to the result. +*/ +static inline PWSTR AsciiToUnicode( UNICODE_STRING * usBufferPtr, LPCSTR src ) +{ + if ( (src) ) + { + RtlCreateUnicodeStringFromAsciiz(usBufferPtr, src); + return usBufferPtr->Buffer; + } + usBufferPtr->Buffer = NULL; /* so that RtlFreeUnicodeString won't barf */ + return NULL; +} + #endif diff --git a/win32ss/printing/base/winspool/printerdata.c b/win32ss/printing/base/winspool/printerdata.c index aefa944872f..7e574e95d9e 100644 --- a/win32ss/printing/base/winspool/printerdata.c +++ b/win32ss/printing/base/winspool/printerdata.c @@ -7,6 +7,22 @@
#include "precomp.h"
+LONG WINAPI +AdvancedSetupDialog(HWND hWnd, INT Unknown, PDEVMODEA pDevModeInput, PDEVMODEA pDevModeOutput) +{ + HANDLE hPrinter; + LONG Ret = -1; + + TRACE("AdvancedSetupDialog(%p, %d, %p, %p)\n", hWnd, Unknown, pDevModeOutput, pDevModeInput); + + if ( OpenPrinterA( (LPSTR)pDevModeInput->dmDeviceName, &hPrinter, NULL ) ) + { + Ret = AdvancedDocumentPropertiesA( hWnd, hPrinter, (PSTR)pDevModeInput->dmDeviceName, pDevModeOutput, pDevModeInput ); + ClosePrinter(hPrinter); + } + return Ret; +} + LONG WINAPI AdvancedDocumentPropertiesA(HWND hWnd, HANDLE hPrinter, PSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput) { @@ -26,17 +42,57 @@ AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVM DWORD WINAPI DeletePrinterDataA(HANDLE hPrinter, PSTR pValueName) { + LPWSTR valuenameW = NULL; + INT len; + DWORD res; + TRACE("DeletePrinterDataA(%p, %s)\n", hPrinter, pValueName); - UNIMPLEMENTED; - return ERROR_NOT_SUPPORTED; + + if (pValueName) + { + len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); + valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); + } + + res = DeletePrinterDataW( hPrinter, valuenameW ); + + HeapFree(GetProcessHeap(), 0, valuenameW); + + return res; + }
DWORD WINAPI DeletePrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PCSTR pValueName) { + LPWSTR keynameW = NULL; + LPWSTR valuenameW = NULL; + INT len; + DWORD res; + TRACE("DeletePrinterDataExA(%p, %s, %s)\n", hPrinter, pKeyName, pValueName); - UNIMPLEMENTED; - return ERROR_NOT_SUPPORTED; + + if (pKeyName) + { + len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); + keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); + } + + if (pValueName) + { + len = MultiByteToWideChar(CP_ACP, 0, pValueName, -1, NULL, 0); + valuenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pValueName, -1, valuenameW, len); + } + + res = DeletePrinterDataExW( hPrinter, keynameW, valuenameW ); + + HeapFree(GetProcessHeap(), 0, keynameW); + HeapFree(GetProcessHeap(), 0, valuenameW); + + return res; }
DWORD WINAPI @@ -58,9 +114,24 @@ DeletePrinterDataW(HANDLE hPrinter, PWSTR pValueName) DWORD WINAPI DeletePrinterKeyA(HANDLE hPrinter, PCSTR pKeyName) { + LPWSTR keynameW = NULL; + INT len; + DWORD res; + TRACE("DeletePrinterKeyA(%p, %s)\n", hPrinter, pKeyName); - UNIMPLEMENTED; - return ERROR_NOT_SUPPORTED; + + if (pKeyName) + { + len = MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, NULL, 0); + keynameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pKeyName, -1, keynameW, len); + } + + res = DeletePrinterKeyW( hPrinter, keynameW ); + + HeapFree(GetProcessHeap(), 0, keynameW); + + return res; }
DWORD WINAPI @@ -82,9 +153,142 @@ EnumPrinterDataA(HANDLE hPrinter, DWORD dwIndex, PSTR pValueName, DWORD cbValueN DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, PCSTR pKeyName, PBYTE pEnumValues, DWORD cbEnumValues, PDWORD pcbEnumValues, PDWORD pnEnumValues) { + INT len; + LPWSTR pKeyNameW; + DWORD ret, dwIndex, dwBufSize; + HANDLE hHeap; + LPSTR pBuffer; + TRACE("EnumPrinterDataExA(%p, %s, %p, %lu, %p, %p)\n", hPrinter, pKeyName, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); - UNIMPLEMENTED; - return ERROR_NOT_SUPPORTED; + + if (pKeyName == NULL || *pKeyName == 0) + return ERROR_INVALID_PARAMETER; + + len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0); + if (len == 0) + { + ret = GetLastError (); + ERR ("MultiByteToWideChar failed with code %i\n", ret); + return ret; + } + + hHeap = GetProcessHeap (); + if (hHeap == NULL) + { + ERR ("GetProcessHeap failed\n"); + return ERROR_OUTOFMEMORY; + } + + pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR)); + if (pKeyNameW == NULL) + { + ERR ("Failed to allocate %i bytes from process heap\n", + (LONG)(len * sizeof (WCHAR))); + return ERROR_OUTOFMEMORY; + } + + if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0) + { + ret = GetLastError (); + ERR ("MultiByteToWideChar failed with code %i\n", ret); + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + WARN ("HeapFree failed with code %i\n", GetLastError ()); + return ret; + } + + ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, pcbEnumValues, pnEnumValues); + + if (ret != ERROR_SUCCESS) + { + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + WARN ("HeapFree failed with code %i\n", GetLastError ()); + TRACE ("EnumPrinterDataExW returned %i\n", ret); + return ret; + } + + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %i\n", ret); + return ret; + } + + if (*pnEnumValues == 0) /* empty key */ + return ERROR_SUCCESS; + + dwBufSize = 0; + for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) + { + PPRINTER_ENUM_VALUESW ppev = + &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; + + if (dwBufSize < ppev->cbValueName) + dwBufSize = ppev->cbValueName; + + if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ || + ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ)) + dwBufSize = ppev->cbData; + } + + TRACE ("Largest Unicode name or value is %i bytes\n", dwBufSize); + + pBuffer = HeapAlloc (hHeap, 0, dwBufSize); + if (pBuffer == NULL) + { + ERR ("Failed to allocate %i bytes from process heap\n", dwBufSize); + return ERROR_OUTOFMEMORY; + } + + for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) + { + PPRINTER_ENUM_VALUESW ppev = + &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; + + len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName, + ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL, + NULL); + if (len == 0) + { + ret = GetLastError (); + ERR ("WideCharToMultiByte failed with code %i\n", ret); + if (HeapFree (hHeap, 0, pBuffer) == 0) + WARN ("HeapFree failed with code %i\n", GetLastError ()); + return ret; + } + + memcpy (ppev->pValueName, pBuffer, len); + + TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); + + if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ && + ppev->dwType != REG_MULTI_SZ) + continue; + + len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData, + ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL); + if (len == 0) + { + ret = GetLastError (); + ERR ("WideCharToMultiByte failed with code %i\n", ret); + if (HeapFree (hHeap, 0, pBuffer) == 0) + WARN ("HeapFree failed with code %i\n", GetLastError ()); + return ret; + } + + memcpy (ppev->pData, pBuffer, len); + + TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); + TRACE (" (only first string of REG_MULTI_SZ printed)\n"); + } + + if (HeapFree (hHeap, 0, pBuffer) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %i\n", ret); + return ret; + } + + return ERROR_SUCCESS; }
DWORD WINAPI diff --git a/win32ss/printing/base/winspool/printerdrivers.c b/win32ss/printing/base/winspool/printerdrivers.c index 07ba18c1311..a30b611820c 100644 --- a/win32ss/printing/base/winspool/printerdrivers.c +++ b/win32ss/printing/base/winspool/printerdrivers.c @@ -6,99 +6,994 @@ */
#include "precomp.h" +#include <marshalling/printerdrivers.h> +extern const WCHAR wszCurrentEnvironment[]; + +static int multi_sz_lenA(const char *str) +{ + const char *ptr = str; + if(!str) return 0; + do + { + ptr += lstrlenA(ptr) + 1; + } while(*ptr); + + return ptr - str + 1; +} + +static int multi_sz_lenW(const WCHAR *str) +{ + const WCHAR *ptr = str; + if (!str) return 0; + do + { + ptr += lstrlenW(ptr) + 1; + } while (*ptr); + + return (ptr - str + 1); +}
BOOL WINAPI AddPrinterDriverA(PSTR pName, DWORD Level, PBYTE pDriverInfo) { TRACE("AddPrinterDriverA(%s, %lu, %p)\n", pName, Level, pDriverInfo); - UNIMPLEMENTED; - return FALSE; + return AddPrinterDriverExA(pName, Level, pDriverInfo, APD_COPY_NEW_FILES); }
BOOL WINAPI AddPrinterDriverExA(PSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags) { - TRACE("AddPrinterDriverExA(%s, %lu, %p, %lu)\n", pName, Level, pDriverInfo, dwFileCopyFlags); - UNIMPLEMENTED; - return FALSE; + PDRIVER_INFO_8A pdiA; + DRIVER_INFO_8W diW; + LPWSTR nameW = NULL; + DWORD lenA; + DWORD len; + BOOL res = FALSE; + + TRACE("AddPrinterDriverExA(%s, %d, %p, 0x%x)\n", debugstr_a(pName), Level, pDriverInfo, dwFileCopyFlags); + + pdiA = (DRIVER_INFO_8A *) pDriverInfo; + ZeroMemory(&diW, sizeof(diW)); + + if (Level < 2 || Level == 5 || Level == 7 || Level > 8) + { + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + if (pdiA == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* convert servername to unicode */ + if (pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pName, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pName, -1, nameW, len); + } + + /* common fields */ + diW.cVersion = pdiA->cVersion; + + if (pdiA->pName) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pName, -1, NULL, 0); + diW.pName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pName, -1, diW.pName, len); + } + + if (pdiA->pEnvironment) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pEnvironment, -1, NULL, 0); + diW.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pEnvironment, -1, diW.pEnvironment, len); + } + + if (pdiA->pDriverPath) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDriverPath, -1, NULL, 0); + diW.pDriverPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pDriverPath, -1, diW.pDriverPath, len); + } + + if (pdiA->pDataFile) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDataFile, -1, NULL, 0); + diW.pDataFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pDataFile, -1, diW.pDataFile, len); + } + + if (pdiA->pConfigFile) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pConfigFile, -1, NULL, 0); + diW.pConfigFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pConfigFile, -1, diW.pConfigFile, len); + } + + if ((Level > 2) && pdiA->pHelpFile) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pHelpFile, -1, NULL, 0); + diW.pHelpFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pHelpFile, -1, diW.pHelpFile, len); + } + + if ((Level > 2) && pdiA->pDependentFiles) + { + lenA = multi_sz_lenA(pdiA->pDependentFiles); + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDependentFiles, lenA, NULL, 0); + diW.pDependentFiles = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pDependentFiles, lenA, diW.pDependentFiles, len); + } + + if ((Level > 2) && pdiA->pMonitorName) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pMonitorName, -1, NULL, 0); + diW.pMonitorName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pMonitorName, -1, diW.pMonitorName, len); + } + + if ((Level > 2) && pdiA->pDefaultDataType) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pDefaultDataType, -1, NULL, 0); + diW.pDefaultDataType = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pDefaultDataType, -1, diW.pDefaultDataType, len); + } + + if ((Level > 3) && pdiA->pszzPreviousNames) + { + lenA = multi_sz_lenA(pdiA->pszzPreviousNames); + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzPreviousNames, lenA, NULL, 0); + diW.pszzPreviousNames = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszzPreviousNames, lenA, diW.pszzPreviousNames, len); + } + + if (Level > 5) + { + diW.ftDriverDate = pdiA->ftDriverDate; + diW.dwlDriverVersion = pdiA->dwlDriverVersion; + } + + if ((Level > 5) && pdiA->pszMfgName) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszMfgName, -1, NULL, 0); + diW.pszMfgName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszMfgName, -1, diW.pszMfgName, len); + } + + if ((Level > 5) && pdiA->pszOEMUrl) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszOEMUrl, -1, NULL, 0); + diW.pszOEMUrl = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszOEMUrl, -1, diW.pszOEMUrl, len); + } + + if ((Level > 5) && pdiA->pszHardwareID) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszHardwareID, -1, NULL, 0); + diW.pszHardwareID = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszHardwareID, -1, diW.pszHardwareID, len); + } + + if ((Level > 5) && pdiA->pszProvider) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszProvider, -1, NULL, 0); + diW.pszProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszProvider, -1, diW.pszProvider, len); + } + + if ((Level > 7) && pdiA->pszPrintProcessor) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszPrintProcessor, -1, NULL, 0); + diW.pszPrintProcessor = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszPrintProcessor, -1, diW.pszPrintProcessor, len); + } + + if ((Level > 7) && pdiA->pszVendorSetup) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszVendorSetup, -1, NULL, 0); + diW.pszVendorSetup = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszVendorSetup, -1, diW.pszVendorSetup, len); + } + + if ((Level > 7) && pdiA->pszzColorProfiles) + { + lenA = multi_sz_lenA(pdiA->pszzColorProfiles); + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzColorProfiles, lenA, NULL, 0); + diW.pszzColorProfiles = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszzColorProfiles, lenA, diW.pszzColorProfiles, len); + } + + if ((Level > 7) && pdiA->pszInfPath) + { + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszInfPath, -1, NULL, 0); + diW.pszInfPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszInfPath, -1, diW.pszInfPath, len); + } + + if ((Level > 7) && pdiA->pszzCoreDriverDependencies) + { + lenA = multi_sz_lenA(pdiA->pszzCoreDriverDependencies); + len = MultiByteToWideChar(CP_ACP, 0, pdiA->pszzCoreDriverDependencies, lenA, NULL, 0); + diW.pszzCoreDriverDependencies = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, pdiA->pszzCoreDriverDependencies, lenA, diW.pszzCoreDriverDependencies, len); + } + + if (Level > 7) + { + diW.dwPrinterDriverAttributes = pdiA->dwPrinterDriverAttributes; + diW.ftMinInboxDriverVerDate = pdiA->ftMinInboxDriverVerDate; + diW.dwlMinInboxDriverVerVersion = pdiA->dwlMinInboxDriverVerVersion; + } + + res = AddPrinterDriverExW(nameW, Level, (LPBYTE) &diW, dwFileCopyFlags); + + TRACE("got %u with %u\n", res, GetLastError()); + HeapFree(GetProcessHeap(), 0, nameW); + HeapFree(GetProcessHeap(), 0, diW.pName); + HeapFree(GetProcessHeap(), 0, diW.pEnvironment); + HeapFree(GetProcessHeap(), 0, diW.pDriverPath); + HeapFree(GetProcessHeap(), 0, diW.pDataFile); + HeapFree(GetProcessHeap(), 0, diW.pConfigFile); + HeapFree(GetProcessHeap(), 0, diW.pHelpFile); + HeapFree(GetProcessHeap(), 0, diW.pDependentFiles); + HeapFree(GetProcessHeap(), 0, diW.pMonitorName); + HeapFree(GetProcessHeap(), 0, diW.pDefaultDataType); + HeapFree(GetProcessHeap(), 0, diW.pszzPreviousNames); + HeapFree(GetProcessHeap(), 0, diW.pszMfgName); + HeapFree(GetProcessHeap(), 0, diW.pszOEMUrl); + HeapFree(GetProcessHeap(), 0, diW.pszHardwareID); + HeapFree(GetProcessHeap(), 0, diW.pszProvider); + HeapFree(GetProcessHeap(), 0, diW.pszPrintProcessor); + HeapFree(GetProcessHeap(), 0, diW.pszVendorSetup); + HeapFree(GetProcessHeap(), 0, diW.pszzColorProfiles); + HeapFree(GetProcessHeap(), 0, diW.pszInfPath); + HeapFree(GetProcessHeap(), 0, diW.pszzCoreDriverDependencies); + + TRACE("=> %u with %u\n", res, GetLastError()); + return res; }
BOOL WINAPI AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags) { + DWORD dwErrorCode; + WINSPOOL_DRIVER_INFO_8 * pdi = NULL; + WINSPOOL_DRIVER_CONTAINER pDriverContainer; + TRACE("AddPrinterDriverExW(%S, %lu, %p, %lu)\n", pName, Level, pDriverInfo, dwFileCopyFlags); - UNIMPLEMENTED; - return FALSE; + + pDriverContainer.Level = Level; + + switch (Level) + { + case 8: + { + PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo; + pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_8)); + + pdi->pPrintProcessor = pdi8w->pszPrintProcessor; + pdi->pVendorSetup = pdi8w->pszVendorSetup; + + pdi->pszzColorProfiles = pdi8w->pszzColorProfiles; + pdi->cchColorProfiles = 0; + if ( pdi8w->pszzColorProfiles && *pdi8w->pszzColorProfiles ) + { + pdi->cchColorProfiles = multi_sz_lenW( pdi8w->pszzColorProfiles ); + } + + pdi->pInfPath = pdi8w->pszInfPath; + + pdi->pszzCoreDriverDependencies = pdi8w->pszzCoreDriverDependencies; + pdi->cchCoreDependencies = 0; + if ( pdi8w->pszzCoreDriverDependencies && *pdi8w->pszzCoreDriverDependencies ) + { + pdi->cchCoreDependencies = multi_sz_lenW( pdi8w->pszzCoreDriverDependencies ); + } + + pdi->ftMinInboxDriverVerDate = pdi8w->ftMinInboxDriverVerDate; + pdi->dwlMinInboxDriverVerVersion = pdi8w->dwlMinInboxDriverVerVersion; + } + case 6: + { + PDRIVER_INFO_6W pdi6w = (PDRIVER_INFO_6W)pDriverInfo; + if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_6)); + + pdi->pMfgName = pdi6w->pszMfgName; + pdi->pOEMUrl = pdi6w->pszOEMUrl; + pdi->pHardwareID = pdi6w->pszHardwareID; + pdi->pProvider = pdi6w->pszProvider; + pdi->ftDriverDate = pdi6w->ftDriverDate; + pdi->dwlDriverVersion = pdi6w->dwlDriverVersion; + } + case 4: + { + + PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo; + if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_4)); + + pdi->pszzPreviousNames = pdi4w->pszzPreviousNames; + pdi->cchPreviousNames = 0; + if ( pdi4w->pDependentFiles && *pdi4w->pDependentFiles ) + { + pdi->cchPreviousNames = multi_sz_lenW( pdi4w->pDependentFiles ); + } + } + case 3: + { + PDRIVER_INFO_3W pdi3w = (PDRIVER_INFO_3W)pDriverInfo; + if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_3)); + + pdi->pHelpFile = pdi3w->pHelpFile; + pdi->pDependentFiles = pdi3w->pDependentFiles; + pdi->pMonitorName = pdi3w->pMonitorName; + pdi->pDefaultDataType = pdi3w->pDefaultDataType; + + pdi->pDependentFiles = pdi3w->pDependentFiles; + pdi->cchDependentFiles = 0; + if ( pdi3w->pDependentFiles && *pdi3w->pDependentFiles ) + { + pdi->cchDependentFiles = multi_sz_lenW( pdi3w->pDependentFiles ); + } + } + case 2: + { + PDRIVER_INFO_2W pdi2w = (PDRIVER_INFO_2W)pDriverInfo; + if ( pdi == NULL ) pdi = HeapAlloc(hProcessHeap, 0, sizeof(WINSPOOL_DRIVER_INFO_2)); + + pdi->pName = pdi2w->pName; + + pdi->pEnvironment = pdi2w->pEnvironment; + if ( !pdi2w->pEnvironment || !*pdi2w->pEnvironment ) + { + pdi2w->pEnvironment = (PWSTR)wszCurrentEnvironment; + } + + pdi->pDriverPath = pdi2w->pDriverPath; + pdi->pDataFile = pdi2w->pDataFile; + pdi->pConfigFile = pdi2w->pConfigFile; + } + break; + + default: + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + pDriverContainer.DriverInfo.Level8 = pdi; + + RpcTryExcept + { + dwErrorCode = _RpcAddPrinterDriverEx( pName, &pDriverContainer, dwFileCopyFlags ); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcAddPrinterDriverEx failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if ( pdi ) HeapFree( GetProcessHeap(), 0, pdi ); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo) { TRACE("AddPrinterDriverW(%S, %lu, %p)\n", pName, Level, pDriverInfo); - UNIMPLEMENTED; - return FALSE; + return AddPrinterDriverExW(pName, Level, pDriverInfo, APD_COPY_NEW_FILES); }
BOOL WINAPI DeletePrinterDriverA(PSTR pName, PSTR pEnvironment, PSTR pDriverName) { TRACE("DeletePrinterDriverA(%s, %s, %s)\n", pName, pEnvironment, pDriverName); - UNIMPLEMENTED; - return FALSE; + return DeletePrinterDriverExA(pName, pEnvironment, pDriverName, 0, 0); }
BOOL WINAPI DeletePrinterDriverExA(PSTR pName, PSTR pEnvironment, PSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag) { + UNICODE_STRING NameW, EnvW, DriverW; + BOOL ret; + TRACE("DeletePrinterDriverExA(%s, %s, %s, %lu, %lu)\n", pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag); - UNIMPLEMENTED; - return FALSE; + + AsciiToUnicode(&NameW, pName); + AsciiToUnicode(&EnvW, pEnvironment); + AsciiToUnicode(&DriverW, pDriverName); + + ret = DeletePrinterDriverExW(NameW.Buffer, EnvW.Buffer, DriverW.Buffer, dwDeleteFlag, dwVersionFlag); + + RtlFreeUnicodeString(&DriverW); + RtlFreeUnicodeString(&EnvW); + RtlFreeUnicodeString(&NameW); + + return ret; }
BOOL WINAPI DeletePrinterDriverExW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag) { + DWORD dwErrorCode; + TRACE("DeletePrinterDriverExW(%S, %S, %S, %lu, %lu)\n", pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag); - UNIMPLEMENTED; - return FALSE; + + if ( !pDriverName || !*pDriverName ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ( !pEnvironment || !*pEnvironment ) + { + pEnvironment = (PWSTR)wszCurrentEnvironment; + } + + // Do the RPC call. + RpcTryExcept + { + dwErrorCode = _RpcDeletePrinterDriverEx(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcDeletePrinterDriverEx failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); + }
BOOL WINAPI DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName) { TRACE("DeletePrinterDriverW(%S, %S, %S)\n", pName, pEnvironment, pDriverName); - UNIMPLEMENTED; - return FALSE; + return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0); }
BOOL WINAPI EnumPrinterDriversA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { + BOOL ret; + DWORD dwErrorCode, i; + UNICODE_STRING pNameW, pEnvironmentW; + PWSTR pwstrNameW, pwstrEnvironmentW; + PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo; + PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo; + TRACE("EnumPrinterDriversA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; - return FALSE; + + pwstrNameW = AsciiToUnicode(&pNameW, pName); + pwstrEnvironmentW = AsciiToUnicode(&pEnvironmentW, pEnvironment); + + ret = EnumPrinterDriversW( pwstrNameW, pwstrEnvironmentW, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned ); + + if (ret) + { + for ( i = 0; i < *pcReturned; i++ ) + { + switch (Level) + { + case 1: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi1w[i].pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + break; + } + case 8: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszPrintProcessor); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszVendorSetup); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzColorProfiles); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszInfPath); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzCoreDriverDependencies); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 6: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszMfgName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszOEMUrl); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszHardwareID); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pszProvider); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 4: + { + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pszzPreviousNames); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 3: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pHelpFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w[i].pDependentFiles); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pMonitorName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDefaultDataType); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 2: + case 5: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pEnvironment); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDriverPath); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pDataFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w[i].pConfigFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + } + } + } +Cleanup: + RtlFreeUnicodeString(&pNameW); + RtlFreeUnicodeString(&pEnvironmentW); + + return ret; }
BOOL WINAPI EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { + DWORD dwErrorCode; + TRACE("EnumPrinterDriversW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned); - UNIMPLEMENTED; - return FALSE; + + // Dismiss invalid levels already at this point. + if (Level > 8 || Level == 7 || Level < 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if ( !pEnvironment || !*pEnvironment ) + { + pEnvironment = (PWSTR)wszCurrentEnvironment; + } + + if (cbBuf && pDriverInfo) + ZeroMemory(pDriverInfo, cbBuf); + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumPrinterDrivers( pName, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, pcReturned ); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPrinterDrivers failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + ASSERT(Level <= 6 || Level == 8); + MarshallUpStructuresArray(cbBuf, pDriverInfo, *pcReturned, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE); + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); + +} + +BOOL WINAPI +GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) +{ + DWORD dwErrorCode; + /* + * We are mapping multiple different pointers to the same pDriverInfo pointer here so that + * we can use the same incoming pointer for different Levels + */ + PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo; + PDRIVER_INFO_8W pdi8w = (PDRIVER_INFO_8W)pDriverInfo; + + DWORD cch; + PWSTR pwszEnvironment = NULL; + + TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); + + // Check for invalid levels here for early error return. Should be 1-6 & 8. + if (Level < 1 || Level == 7 || Level > 8) + { + dwErrorCode = ERROR_INVALID_LEVEL; + ERR("Invalid Level!\n"); + goto Cleanup; + } + + if (pEnvironment) + { + // Convert pEnvironment to a Unicode string pwszEnvironment. + cch = strlen(pEnvironment); + + pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!pwszEnvironment) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("HeapAlloc failed!\n"); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1); + } + + if (!GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded)) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // Do Unicode to ANSI conversions for strings based on Level + switch (Level) + { + case 1: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi1w->pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + break; + } + case 8: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszPrintProcessor); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszVendorSetup); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzColorProfiles); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszInfPath); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzCoreDriverDependencies); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 6: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszMfgName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszOEMUrl); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszHardwareID); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pszProvider); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 4: + { + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pszzPreviousNames); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 3: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pHelpFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiZZInPlace(pdi8w->pDependentFiles); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pMonitorName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDefaultDataType); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + case 2: + case 5: + { + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pName); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pEnvironment); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDriverPath); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pDataFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + + dwErrorCode = UnicodeToAnsiInPlace(pdi8w->pConfigFile); + if (dwErrorCode != ERROR_SUCCESS) + { + goto Cleanup; + } + } + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pwszEnvironment) + { + HeapFree(hProcessHeap, 0, pwszEnvironment); + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Dismiss invalid levels already at this point. + if (Level > 8 || Level == 7 || Level < 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if ( !pEnvironment || !*pEnvironment ) + { + pEnvironment = (PWSTR)wszCurrentEnvironment; + } + + if (cbBuf && pDriverInfo) + ZeroMemory(pDriverInfo, cbBuf); + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcGetPrinterDriver failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + ASSERT(Level <= 6 || Level == 8); + MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE); + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
BOOL WINAPI GetPrinterDriverDirectoryA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded) { - TRACE("GetPrinterDriverDirectoryA(%s, %s, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded); - UNIMPLEMENTED; - return FALSE; + UNICODE_STRING nameW, environmentW; + BOOL ret; + DWORD pcbNeededW; + INT len = cbBuf * sizeof(WCHAR)/sizeof(CHAR); + WCHAR *driverDirectoryW = NULL; + + TRACE("GetPrinterDriverDirectoryA(%s, %s, %d, %p, %d, %p)\n", debugstr_a(pName), debugstr_a(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); + + if (len) driverDirectoryW = HeapAlloc( GetProcessHeap(), 0, len ); + + if (pName) + { + RtlCreateUnicodeStringFromAsciiz(&nameW, pName); + } + else + { + nameW.Buffer = NULL; + } + if (pEnvironment) + { + RtlCreateUnicodeStringFromAsciiz(&environmentW, pEnvironment); + } + else + { + environmentW.Buffer = NULL; + } + + ret = GetPrinterDriverDirectoryW( nameW.Buffer, environmentW.Buffer, Level, (LPBYTE)driverDirectoryW, len, &pcbNeededW ); + + if (ret) + { + DWORD needed = WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1, (LPSTR)pDriverDirectory, cbBuf, NULL, NULL); + + if ( pcbNeeded ) + *pcbNeeded = needed; + + ret = needed <= cbBuf; + } + else + { + if (pcbNeeded) *pcbNeeded = pcbNeededW * sizeof(CHAR)/sizeof(WCHAR); + } + + TRACE("required: 0x%x/%d\n", pcbNeeded ? *pcbNeeded : 0, pcbNeeded ? *pcbNeeded : 0); + + HeapFree( GetProcessHeap(), 0, driverDirectoryW ); + RtlFreeUnicodeString(&environmentW); + RtlFreeUnicodeString(&nameW); + + return ret; }
BOOL WINAPI GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded) { + DWORD dwErrorCode; + TRACE("GetPrinterDriverDirectoryW(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded); - UNIMPLEMENTED; - return FALSE; + + if ( !pEnvironment || !*pEnvironment ) + { + pEnvironment = (PWSTR)wszCurrentEnvironment; + } + + // Do the RPC call. + RpcTryExcept + { + dwErrorCode = _RpcGetPrinterDriverDirectory(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcGetPrinterDriverDirectory failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); } diff --git a/win32ss/printing/base/winspool/printers.c b/win32ss/printing/base/winspool/printers.c index 249d41256bd..12c299ade01 100644 --- a/win32ss/printing/base/winspool/printers.c +++ b/win32ss/printing/base/winspool/printers.c @@ -7,9 +7,53 @@
#include "precomp.h" #include <marshalling/printers.h> -#include <marshalling/printerdrivers.h> +//#include <marshalling/printerdrivers.h> #include <strsafe.h>
+extern HINSTANCE hinstWinSpool; +// +// See winddiui.h, ReactOS version is limited. +// Loading from XyzUI.dll part of XyzDRV.dll set. example TTYUI.DLL or UniDrvUI.DLL. +// +typedef DWORD (WINAPI *DEVICECAPABILITIES) (HANDLE,PWSTR,WORD,PVOID,PDEVMODEW); +static DEVICECAPABILITIES fpDeviceCapabilities; + +typedef LONG (WINAPI *DEVICEPROPERTYSHEETS) (PPROPSHEETUI_INFO,LPARAM); +static DEVICEPROPERTYSHEETS fpDevicePropertySheets; +typedef LONG (WINAPI *DOCUMENTPROPERTYSHEETS) (PPROPSHEETUI_INFO,LPARAM); +static DOCUMENTPROPERTYSHEETS fpDocumentPropertySheets; + +typedef LONG (WINAPI *COMMONPROPERTYSHEETUIW) (HWND,PFNPROPSHEETUI,LPARAM,LPDWORD); +static COMMONPROPERTYSHEETUIW fpCommonPropertySheetUIW; + +typedef LONG (WINAPI *QUERYCOLORPROFILE) (HANDLE,PDEVMODEW,ULONG,PVOID,ULONG*,FLONG*); +static QUERYCOLORPROFILE fpQueryColorProfile; + +typedef BOOL (WINAPI *SPOOLERPRINTEREVENT) (LPWSTR,int,DWORD,LPARAM); +static SPOOLERPRINTEREVENT fpPrinterEvent; + +typedef BOOL (WINAPI *DEVQUERYPRINT) (HANDLE,LPDEVMODEW,DWORD*); +static DEVQUERYPRINT fpDevQueryPrint; + +typedef BOOL (WINAPI *DEVQUERYPRINTEX) (PDEVQUERYPRINT_INFO); +static DEVQUERYPRINTEX fpDevQueryPrintEx; + +// +// PrintUI.dll +// +LONG WINAPI ConstructPrinterFriendlyName( PWSTR, PVOID, LPDWORD Size ); +typedef LONG (WINAPI *CONSTRUCTPRINTERFRIENDLYNAME) (PWSTR,PVOID,LPDWORD); +static CONSTRUCTPRINTERFRIENDLYNAME fpConstructPrinterFriendlyName; + +// +// CompstUI User Data +// +typedef struct _COMPUI_USERDATA +{ + HMODULE hModule; + LPWSTR pszPrinterName; +} COMPUI_USERDATA, *PCOMPUI_USERDATA; + // Local Constants
/** And the award for the most confusingly named setting goes to "Device", for storing the default printer of the current user. @@ -110,25 +154,257 @@ _StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1) BOOL WINAPI AbortPrinter(HANDLE hPrinter) { + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("AbortPrinter(%p)\n", hPrinter); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pHandle->bTrayIcon = pHandle->bStartedDoc = FALSE; + + if ( pHandle->hSPLFile != INVALID_HANDLE_VALUE && pHandle->bJob ) + { + // Close any open file handle. + CloseHandle( pHandle->hSPLFile ); + pHandle->hSPLFile = INVALID_HANDLE_VALUE; + + SetJobW( hPrinter, pHandle->dwJobID, 0, NULL, JOB_CONTROL_DELETE ); + + return ScheduleJob( hPrinter, pHandle->dwJobID ); + } + + // Do the RPC call. + RpcTryExcept + { + dwErrorCode = _RpcAbortPrinter(&pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcAbortPrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
HANDLE WINAPI AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter) { - TRACE("AddPrinterA(%s, %lu, %p)\n", pName, Level, pPrinter); - UNIMPLEMENTED; - return NULL; + UNICODE_STRING pNameW, usBuffer; + PWSTR pwstrNameW; + PRINTER_INFO_2W *ppi2w = (PRINTER_INFO_2W*)pPrinter; + PRINTER_INFO_2A *ppi2a = (PRINTER_INFO_2A*)pPrinter; + HANDLE ret = NULL; + PWSTR pwszPrinterName = NULL; + PWSTR pwszServerName = NULL; + PWSTR pwszShareName = NULL; + PWSTR pwszPortName = NULL; + PWSTR pwszDriverName = NULL; + PWSTR pwszComment = NULL; + PWSTR pwszLocation = NULL; + PWSTR pwszSepFile = NULL; + PWSTR pwszPrintProcessor = NULL; + PWSTR pwszDatatype = NULL; + PWSTR pwszParameters = NULL; + PDEVMODEW pdmw = NULL; + + TRACE("AddPrinterA(%s, %d, %p)\n", debugstr_a(pName), Level, pPrinter); + + if(Level != 2) + { + ERR("Level = %d, unsupported!\n", Level); + SetLastError(ERROR_INVALID_LEVEL); + return NULL; + } + + pwstrNameW = AsciiToUnicode(&pNameW,pName); + + if (ppi2a->pShareName) + { + pwszShareName = AsciiToUnicode(&usBuffer, ppi2a->pShareName); + if (!(ppi2w->pShareName = pwszShareName)) goto Cleanup; + } + if (ppi2a->pPortName) + { + pwszPortName = AsciiToUnicode(&usBuffer, ppi2a->pPortName); + if (!(ppi2w->pPortName = pwszPortName)) goto Cleanup; + } + if (ppi2a->pDriverName) + { + pwszDriverName = AsciiToUnicode(&usBuffer, ppi2a->pDriverName); + if (!(ppi2w->pDriverName = pwszDriverName)) goto Cleanup; + } + if (ppi2a->pComment) + { + pwszComment = AsciiToUnicode(&usBuffer, ppi2a->pComment); + if (!(ppi2w->pComment = pwszComment)) goto Cleanup; + } + if (ppi2a->pLocation) + { + pwszLocation = AsciiToUnicode(&usBuffer, ppi2a->pLocation); + if (!(ppi2w->pLocation = pwszLocation)) goto Cleanup; + } + if (ppi2a->pSepFile) + { + pwszSepFile = AsciiToUnicode(&usBuffer, ppi2a->pSepFile); + if (!(ppi2w->pSepFile = pwszSepFile)) goto Cleanup; + } + if (ppi2a->pServerName) + { + pwszPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor); + if (!(ppi2w->pPrintProcessor = pwszPrintProcessor)) goto Cleanup; + } + if (ppi2a->pDatatype) + { + pwszDatatype = AsciiToUnicode(&usBuffer, ppi2a->pDatatype); + if (!(ppi2w->pDatatype = pwszDatatype)) goto Cleanup; + } + if (ppi2a->pParameters) + { + pwszParameters = AsciiToUnicode(&usBuffer, ppi2a->pParameters); + if (!(ppi2w->pParameters = pwszParameters)) goto Cleanup; + } + if ( ppi2a->pDevMode ) + { + RosConvertAnsiDevModeToUnicodeDevmode( ppi2a->pDevMode, &pdmw ); + ppi2w->pDevMode = pdmw; + } + if (ppi2a->pServerName) + { + pwszServerName = AsciiToUnicode(&usBuffer, ppi2a->pServerName); + if (!(ppi2w->pPrinterName = pwszServerName)) goto Cleanup; + } + if (ppi2a->pPrinterName) + { + pwszPrinterName = AsciiToUnicode(&usBuffer, ppi2a->pPrinterName); + if (!(ppi2w->pPrinterName = pwszPrinterName)) goto Cleanup; + } + + ret = AddPrinterW(pwstrNameW, Level, (LPBYTE)ppi2w); + +Cleanup: + if (pdmw) HeapFree(hProcessHeap, 0, pdmw); + if (pwszPrinterName) HeapFree(hProcessHeap, 0, pwszPrinterName); + if (pwszServerName) HeapFree(hProcessHeap, 0, pwszServerName); + if (pwszShareName) HeapFree(hProcessHeap, 0, pwszShareName); + if (pwszPortName) HeapFree(hProcessHeap, 0, pwszPortName); + if (pwszDriverName) HeapFree(hProcessHeap, 0, pwszDriverName); + if (pwszComment) HeapFree(hProcessHeap, 0, pwszComment); + if (pwszLocation) HeapFree(hProcessHeap, 0, pwszLocation); + if (pwszSepFile) HeapFree(hProcessHeap, 0, pwszSepFile); + if (pwszPrintProcessor) HeapFree(hProcessHeap, 0, pwszPrintProcessor); + if (pwszDatatype) HeapFree(hProcessHeap, 0, pwszDatatype); + if (pwszParameters) HeapFree(hProcessHeap, 0, pwszParameters); + + RtlFreeUnicodeString(&pNameW); + return ret; }
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter) { + DWORD dwErrorCode; + WINSPOOL_PRINTER_CONTAINER PrinterContainer; + WINSPOOL_DEVMODE_CONTAINER DevModeContainer; + WINSPOOL_SECURITY_CONTAINER SecurityContainer; + SECURITY_DESCRIPTOR *sd = NULL; + DWORD size; + HANDLE hPrinter = NULL, hHandle = NULL; + PSPOOLER_HANDLE pHandle = NULL; + TRACE("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter); - UNIMPLEMENTED; - return NULL; + + DevModeContainer.cbBuf = 0; + DevModeContainer.pDevMode = NULL; + + SecurityContainer.cbBuf = 0; + SecurityContainer.pSecurity = NULL; + + if ( Level != 2 ) + { + FIXME( "Unsupported level %d\n", Level ); + SetLastError( ERROR_INVALID_LEVEL ); + return hHandle; + } + else + { + PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter; + if ( pi2w ) + { + if ( pi2w->pDevMode ) + { + if ( IsValidDevmodeNoSizeW( pi2w->pDevMode ) ) + { + DevModeContainer.cbBuf = pi2w->pDevMode->dmSize + pi2w->pDevMode->dmDriverExtra; + DevModeContainer.pDevMode = (PBYTE)pi2w->pDevMode; + } + } + + if ( pi2w->pSecurityDescriptor ) + { + sd = get_sd( pi2w->pSecurityDescriptor, &size ); + if ( sd ) + { + SecurityContainer.cbBuf = size; + SecurityContainer.pSecurity = (PBYTE)sd; + } + } + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + return hHandle; + } + } + + PrinterContainer.PrinterInfo.pPrinterInfo1 = (WINSPOOL_PRINTER_INFO_1*)pPrinter; + PrinterContainer.Level = Level; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcAddPrinter( pName, &PrinterContainer, &DevModeContainer, &SecurityContainer, &hPrinter ); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + } + RpcEndExcept; + + if (hPrinter) + { + // Create a new SPOOLER_HANDLE structure. + pHandle = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(SPOOLER_HANDLE)); + if (!pHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("HeapAlloc failed!\n"); + _RpcDeletePrinter(hPrinter); + _RpcClosePrinter(hPrinter); + goto Cleanup; + } + + pHandle->Sig = SPOOLER_HANDLE_SIG; + pHandle->hPrinter = hPrinter; + pHandle->hSPLFile = INVALID_HANDLE_VALUE; + pHandle->hSpoolFileHandle = INVALID_HANDLE_VALUE; + hHandle = (HANDLE)pHandle; + } + +Cleanup: + if ( sd ) HeapFree( GetProcessHeap(), 0, sd ); + + SetLastError(dwErrorCode); + return hHandle; }
BOOL WINAPI @@ -140,7 +416,7 @@ ClosePrinter(HANDLE hPrinter) TRACE("ClosePrinter(%p)\n", hPrinter);
// Sanity checks. - if (!pHandle) + if ( IntProtectHandle( hPrinter, TRUE ) ) { dwErrorCode = ERROR_INVALID_HANDLE; goto Cleanup; @@ -162,6 +438,8 @@ ClosePrinter(HANDLE hPrinter) if (pHandle->hSPLFile != INVALID_HANDLE_VALUE) CloseHandle(pHandle->hSPLFile);
+ pHandle->Sig = -1; + // Free the memory for the handle. HeapFree(hProcessHeap, 0, pHandle);
@@ -173,25 +451,207 @@ Cleanup: BOOL WINAPI DeletePrinter(HANDLE hPrinter) { + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + TRACE("DeletePrinter(%p)\n", hPrinter); - UNIMPLEMENTED; - return FALSE; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call. + RpcTryExcept + { + dwErrorCode = _RpcDeletePrinter(&pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcDeletePrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +// +// Based on GDI32:printdrv.c:IntGetPrinterDriver. +// +HMODULE +WINAPI +LoadPrinterDriver( HANDLE hspool ) +{ + INT iTries = 0; + DWORD Size = (sizeof(WCHAR) * MAX_PATH) * 2; // DRIVER_INFO_5W + plus strings. + PDRIVER_INFO_5W pdi = NULL; + HMODULE hLibrary = NULL; + + do + { + ++iTries; + + pdi = RtlAllocateHeap( GetProcessHeap(), 0, Size); + + if ( !pdi ) + break; + + if ( GetPrinterDriverW(hspool, NULL, 5, (LPBYTE)pdi, Size, &Size) ) + { + TRACE("Level 5 Size %d\n",Size); + + // Name and load configure library (for example, C:\DRIVERS\Pscrptui.dll). Not printui.dll! + + hLibrary = LoadLibrary(pdi->pConfigFile); + + FIXME("IGPD : Get Printer Driver %S\n",pdi->pConfigFile); + + RtlFreeHeap( GetProcessHeap(), 0, pdi); + return hLibrary; + } + + if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) + ++iTries; + + RtlFreeHeap( GetProcessHeap(), 0, pdi); + } + while ( iTries < 2 ); + ERR("No Printer Driver Error %d\n",GetLastError()); + return NULL; }
DWORD WINAPI DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode) { - TRACE("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode); - UNIMPLEMENTED; - return 0; + PWSTR pwszDeviceName = NULL; + PDEVMODEW pdmwInput = NULL; + BOOL bReturnValue = GDI_ERROR; + DWORD cch; + + FIXME("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode); + + if (pDevice) + { + // Convert pName to a Unicode string pwszDeviceName. + cch = strlen(pDevice); + + 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, pDevice, -1, pwszDeviceName, cch + 1); + } + + if (pDevMode) + { + RosConvertAnsiDevModeToUnicodeDevmode((PDEVMODEA)pDevMode, &pdmwInput); + } + + // pPort is ignored so no need to pass it. + bReturnValue = DeviceCapabilitiesW( pwszDeviceName, NULL, fwCapability, (LPWSTR)pOutput, (const DEVMODEW*) pdmwInput ); + +Cleanup: + if(pwszDeviceName) + HeapFree(hProcessHeap, 0, pwszDeviceName); + + if (pdmwInput) + HeapFree(hProcessHeap, 0, pdmwInput); + + return bReturnValue; }
DWORD WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode) { - TRACE("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode); - UNIMPLEMENTED; - return 0; + HANDLE hPrinter; + HMODULE hLibrary; + DWORD iDevCap = GDI_ERROR; + + FIXME("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode); + + if ( pDevMode ) + { + if (!IsValidDevmodeNoSizeW( (PDEVMODEW)pDevMode ) ) + { + ERR("DeviceCapabilitiesW : Devode Invalid"); + return -1; + } + } + + if ( OpenPrinterW( (LPWSTR)pDevice, &hPrinter, NULL ) ) + { + hLibrary = LoadPrinterDriver( hPrinter ); + + if ( hLibrary ) + { + fpDeviceCapabilities = (PVOID)GetProcAddress( hLibrary, "DrvDeviceCapabilities" ); + + if ( fpDeviceCapabilities ) + { + iDevCap = fpDeviceCapabilities( hPrinter, (PWSTR)pDevice, fwCapability, pOutput, (PDEVMODE)pDevMode ); + } + + FreeLibrary(hLibrary); + } + + ClosePrinter( hPrinter ); + } + + return iDevCap; +} + +BOOL +WINAPI +DevQueryPrint( HANDLE hPrinter, LPDEVMODEW pDevMode, DWORD *pResID) +{ + HMODULE hLibrary; + BOOL Ret = FALSE; + + hLibrary = LoadPrinterDriver( hPrinter ); + + if ( hLibrary ) + { + fpDevQueryPrint = (PVOID)GetProcAddress( hLibrary, "DevQueryPrint" ); + + if ( fpDevQueryPrint ) + { + Ret = fpDevQueryPrint( hPrinter, pDevMode, pResID ); + } + + FreeLibrary(hLibrary); + } + return Ret; +} + +BOOL WINAPI +DevQueryPrintEx( PDEVQUERYPRINT_INFO pDQPInfo ) +{ + HMODULE hLibrary; + BOOL Ret = FALSE; + + hLibrary = LoadPrinterDriver( pDQPInfo->hPrinter ); + + if ( hLibrary ) + { + fpDevQueryPrintEx = (PVOID)GetProcAddress( hLibrary, "DevQueryPrintEx" ); + + if ( fpDevQueryPrintEx ) + { + Ret = fpDevQueryPrintEx( pDQPInfo ); + } + + FreeLibrary(hLibrary); + } + return Ret; }
INT WINAPI @@ -211,7 +671,7 @@ DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDe BOOL bReturnValue = -1; DWORD cch;
- TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode); + FIXME("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
if (pDeviceName) { @@ -232,30 +692,32 @@ DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDe 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); + RosConvertAnsiDevModeToUnicodeDevmode(pDevModeInput, &pdmwInput); }
if (pDevModeOutput) { // Create working buffer for output from DocumentPropertiesW. - pdmwOutput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW)); - if (!pdmwOutput) + + // Do it RIGHT! Get the F...ing Size! + LONG Size = DocumentPropertiesW( hWnd, hPrinter, pwszDeviceName, NULL, NULL, 0 ); + + if ( Size < 0 ) { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - ERR("HeapAlloc failed!\n"); + goto Cleanup; + } + + pdmwOutput = HeapAlloc(hProcessHeap, 0, Size); + 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); + FIXME("bReturnValue from DocumentPropertiesW is '%ld'.\n", bReturnValue);
if (pwszDeviceName) { @@ -264,7 +726,7 @@ DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDe
if (bReturnValue < 0) { - TRACE("DocumentPropertiesW failed!\n"); + FIXME("DocumentPropertiesW failed!\n"); goto Cleanup; }
@@ -286,7 +748,7 @@ Cleanup: return bReturnValue; }
-static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn) +PRINTER_INFO_9W * get_devmodeW(HANDLE hprn) { PRINTER_INFO_9W *pi9 = NULL; DWORD needed = 0; @@ -307,65 +769,470 @@ static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn) return NULL; }
-LONG WINAPI -DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode) +BOOL +FASTCALL +CreateUIUserData( ULONG_PTR *puserdata, HANDLE hPrinter ) { - HANDLE hUseHandle = NULL; - PRINTER_INFO_9W *pi9 = NULL; - LONG Result = -1, Length; + PCOMPUI_USERDATA pcui_ud = DllAllocSplMem( sizeof(COMPUI_USERDATA) );
- TRACE("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode); - if (hPrinter) + *puserdata = (ULONG_PTR)pcui_ud; + FIXME("CreateUIUserData\n"); + if ( pcui_ud ) { - hUseHandle = hPrinter; + pcui_ud->hModule = LoadPrinterDriver( hPrinter ); + + if ( !pcui_ud->hModule ) + { + DllFreeSplMem( pcui_ud ); + *puserdata = 0; + } } - else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL)) + return *puserdata != 0; +} + +VOID +FASTCALL +DestroyUIUserData( ULONG_PTR *puserdata ) +{ + PCOMPUI_USERDATA pcui_ud = (PCOMPUI_USERDATA)*puserdata; + FIXME("DestroyUIUserData\n"); + if ( pcui_ud ) { - ERR("No handle, and no usable printer name passed in\n"); - return -1; + if ( pcui_ud->hModule ) + { + FreeLibrary( pcui_ud->hModule ); + pcui_ud->hModule = NULL; + } + + if ( pcui_ud->pszPrinterName ) + { + DllFreeSplMem( pcui_ud->pszPrinterName ); + pcui_ud->pszPrinterName = NULL; + } + + DllFreeSplMem( pcui_ud ); + *puserdata = 0; + } +} + +BOOL +FASTCALL +IntFixUpDevModeNames( PDOCUMENTPROPERTYHEADER pdphdr ) +{ + PRINTER_INFO_2W *pi2 = NULL; + DWORD needed = 0; + BOOL res; + + if (!(pdphdr->fMode & DM_OUT_BUFFER) || + pdphdr->fMode & DM_NOPERMISSION || // Do not allow the user to modify properties on the displayed property sheet pages. + !pdphdr->pdmOut ) + { + return FALSE; + } + + res = GetPrinterW( pdphdr->hPrinter, 2, NULL, 0, &needed); + if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + pi2 = HeapAlloc(hProcessHeap, 0, needed); + res = GetPrinterW( pdphdr->hPrinter, 2, (LPBYTE)pi2, needed, &needed); + } + + if (res) + { + FIXME("IFUDMN : Get Printer Name %S\n",pi2->pPrinterName); + StringCchCopyW( pdphdr->pdmOut->dmDeviceName, CCHDEVICENAME-1, pi2->pPrinterName ); + pdphdr->pdmOut->dmDeviceName[CCHDEVICENAME-1] = 0; + } + else + { + ERR("IFUDMN : GetPrinterW failed with %u\n", GetLastError()); + } + HeapFree(hProcessHeap, 0, pi2); + return res; +} + +LONG +WINAPI +CreatePrinterFriendlyName( PCOMPUI_USERDATA pcui_ud, LPWSTR pszPrinterName ) +{ + LONG Result = 0; + DWORD Size = 0; + HMODULE hLibrary = NULL; + + hLibrary = LoadLibraryA( "printui.dll" ); + + if ( hLibrary ) + { + fpConstructPrinterFriendlyName = (PVOID)GetProcAddress( hLibrary, "ConstructPrinterFriendlyName" ); + + if ( fpConstructPrinterFriendlyName ) + { + if ( !fpConstructPrinterFriendlyName( pszPrinterName, NULL, &Size ) ) + { + if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) + { + PWSTR pwstr = DllAllocSplMem( (Size + 1) * sizeof(WCHAR) ); + + pcui_ud->pszPrinterName = pwstr; + + if ( pwstr ) + Result = fpConstructPrinterFriendlyName( pszPrinterName, pwstr, &Size ); + } + } + } + FreeLibrary( hLibrary ); + } + + if ( !Result ) + { + DllFreeSplMem( pcui_ud->pszPrinterName ); + pcui_ud->pszPrinterName = AllocSplStr( pszPrinterName ); }
- pi9 = get_devmodeW(hUseHandle); + return Result; +} + +// +// Tested with XP CompstUI as a callback and works. Fails perfectly. +// +LONG +WINAPI +DocumentPropertySheets( PPROPSHEETUI_INFO pCPSUIInfo, LPARAM lparam ) +{ + LONG Result = -1; + PDOCUMENTPROPERTYHEADER pdphdr; + + FIXME("DocumentPropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam);
- if (pi9) + // If pPSUIInfo is NULL, and if either lParam -> fMode is zero or lParam -> pdmOut is NULL, + // this function should return the size, in bytes, of the printer's DEVMODEW structure. + if ( !pCPSUIInfo && lparam ) { - Length = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra; - // See wineps.drv PSDRV_ExtDeviceMode - if (fMode) + pdphdr = (PDOCUMENTPROPERTYHEADER)lparam; + + if ( pdphdr->cbSize >= sizeof(PDOCUMENTPROPERTYHEADER) && + !(pdphdr->fMode & DM_PROMPT) ) { - Result = 1; /* IDOK */ + HMODULE hLibrary = LoadPrinterDriver( pdphdr->hPrinter );
- if (fMode & DM_IN_BUFFER) + if ( hLibrary ) { - FIXME("Merge pDevModeInput with pi9, write back to driver!\n"); - // See wineps.drv PSDRV_MergeDevmodes - } + fpDocumentPropertySheets = (PVOID)GetProcAddress( hLibrary, "DrvDocumentPropertySheets" ); + + if ( fpDocumentPropertySheets ) + { + Result = fpDocumentPropertySheets( pCPSUIInfo, lparam ); + } + else + { + // + // ReactOS backup!!! Currently no supporting UI driver. + // + PRINTER_INFO_9W * pi9 = get_devmodeW( pdphdr->hPrinter ); + if ( pi9 ) + { + Result = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra; + FIXME("IDPS : Using ReactOS backup!!! DevMode Size %d\n",Result); + HeapFree(hProcessHeap, 0, pi9); + } + } + + FreeLibrary(hLibrary);
- if (fMode & DM_IN_PROMPT) + if ( Result > 0 ) + { + IntFixUpDevModeNames( pdphdr ); + } + + return Result; + } + else { - FIXME("Show property sheet!\n"); - Result = 2; /* IDCANCEL */ + SetLastError(ERROR_INVALID_HANDLE); } + } + else + { + SetLastError(ERROR_INVALID_PARAMETER); + } + return Result; + } + + Result = 0; + + if ( pCPSUIInfo ) + { + PSETRESULT_INFO psri; + PPROPSHEETUI_INFO_HEADER ppsuiihdr; + PCOMPUI_USERDATA pcui_ud; + pdphdr = (PDOCUMENTPROPERTYHEADER)pCPSUIInfo->lParamInit;
- if (fMode & (DM_OUT_BUFFER | DM_OUT_DEFAULT)) + if ( pdphdr->cbSize < sizeof(PDOCUMENTPROPERTYHEADER) ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return Result; + } + + switch ( pCPSUIInfo->Reason ) + { + case PROPSHEETUI_REASON_INIT: { - if (pDevModeOutput) + FIXME("DocPS : PROPSHEETUI_REASON_INIT\n"); + if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) ) + { + pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData; + + fpDocumentPropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDocumentPropertySheets" ); + + if ( fpDocumentPropertySheets ) + { + pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet, + CPSFUNC_SET_FUSION_CONTEXT, + -3, // What type of handle is this? + 0 ); // Not used, must be zero. + + Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet, + CPSFUNC_ADD_PFNPROPSHEETUIW, + (LPARAM)fpDocumentPropertySheets, + pCPSUIInfo->lParamInit ); + break; + } + FIXME("DocPS : PROPSHEETUI_REASON_INIT Fail\n"); + DestroyUIUserData( &pCPSUIInfo->UserData ); + } + } + break; + + case PROPSHEETUI_REASON_GET_INFO_HEADER: + FIXME("DocPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n"); + + ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam; + + pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData; + + CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName ); + + ppsuiihdr->Flags = PSUIHDRF_NOAPPLYNOW|PSUIHDRF_PROPTITLE; + ppsuiihdr->pTitle = pcui_ud->pszPrinterName; + ppsuiihdr->hInst = hinstWinSpool; + ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT; + + Result = CPSUI_OK; + break; + + case PROPSHEETUI_REASON_DESTROY: + FIXME("DocPS : PROPSHEETUI_REASON_DESTROY\n"); + DestroyUIUserData( &pCPSUIInfo->UserData ); + Result = CPSUI_OK; + break; + + case PROPSHEETUI_REASON_SET_RESULT: + FIXME("DocPS : PROPSHEETUI_REASON_SET_RESULT\n"); + + psri = (PSETRESULT_INFO)lparam; + + pCPSUIInfo->Result = psri->Result; + if ( pCPSUIInfo->Result > 0 ) { - memcpy(pDevModeOutput, pi9->pDevMode, pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra); + IntFixUpDevModeNames( pdphdr ); } - else + Result = CPSUI_OK; + break; + } + } + return Result; +} + +LONG +WINAPI +DevicePropertySheets( PPROPSHEETUI_INFO pCPSUIInfo, LPARAM lparam ) +{ + LONG Result = 0; + PDEVICEPROPERTYHEADER pdphdr; + + FIXME("DevicePropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam); + + if ( pCPSUIInfo ) + { + PSETRESULT_INFO psri; + PPROPSHEETUI_INFO_HEADER ppsuiihdr; + PCOMPUI_USERDATA pcui_ud; + pdphdr = (PDEVICEPROPERTYHEADER)pCPSUIInfo->lParamInit; + + if ( pdphdr->cbSize < sizeof(DEVICEPROPERTYHEADER) ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return Result; + } + + switch ( pCPSUIInfo->Reason ) + { + case PROPSHEETUI_REASON_INIT: + { + FIXME("DevPS : PROPSHEETUI_REASON_INIT\n"); + if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) ) { - ERR("No pDevModeOutput\n"); - Result = -1; + pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData; + + fpDevicePropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDevicePropertySheets" ); + + if ( fpDevicePropertySheets ) + { + pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet, + CPSFUNC_SET_FUSION_CONTEXT, + -3, // What type of handle is this? + 0 ); // Not used, must be zero. + + Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet, + CPSFUNC_ADD_PFNPROPSHEETUIW, + (LPARAM)fpDevicePropertySheets, + pCPSUIInfo->lParamInit ); + break; + } + FIXME("DevPS : PROPSHEETUI_REASON_INIT Fail\n"); + DestroyUIUserData( &pCPSUIInfo->UserData ); } } + break; + + case PROPSHEETUI_REASON_GET_INFO_HEADER: + FIXME("DevPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n"); + + ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam; + + pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData; + + CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName ); + + ppsuiihdr->Flags = PSUIHDRF_NOAPPLYNOW|PSUIHDRF_PROPTITLE; + ppsuiihdr->pTitle = pcui_ud->pszPrinterName; + ppsuiihdr->hInst = hinstWinSpool; + ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT; + + Result = CPSUI_OK; + break; + + case PROPSHEETUI_REASON_DESTROY: + FIXME("DevPS : PROPSHEETUI_REASON_DESTROY\n"); + DestroyUIUserData( &pCPSUIInfo->UserData ); + Result = CPSUI_OK; + break; + + case PROPSHEETUI_REASON_SET_RESULT: + FIXME("DevPS : PROPSHEETUI_REASON_SET_RESULT\n"); + psri = (PSETRESULT_INFO)lparam; + pCPSUIInfo->Result = psri->Result; + Result = CPSUI_OK; + break; } - else + } + return Result; +} + +LONG +WINAPI +CallCommonPropertySheetUI(HWND hWnd, PFNPROPSHEETUI pfnPropSheetUI, LPARAM lparam, LPDWORD pResult) +{ + HMODULE hLibrary = NULL; + LONG Ret = ERR_CPSUI_GETLASTERROR; + + FIXME("CallCommonPropertySheetUI(%p, %p, 0x%lx, %p)\n", hWnd, pfnPropSheetUI, lparam, pResult); + + if ( ( hLibrary = LoadLibraryA( "compstui.dll" ) ) ) + { + fpCommonPropertySheetUIW = (PVOID) GetProcAddress(hLibrary, "CommonPropertySheetUIW"); + + if ( fpCommonPropertySheetUIW ) + { + Ret = fpCommonPropertySheetUIW( hWnd, pfnPropSheetUI, lparam, pResult ); + } + + FreeLibrary(hLibrary); + } + return Ret; +} + +LONG WINAPI +DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode) +{ + HANDLE hUseHandle = NULL; + DOCUMENTPROPERTYHEADER docprophdr; + LONG Result = IDOK; + + FIXME("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode); + + if (hPrinter) + { + hUseHandle = hPrinter; + } + else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL)) + { + ERR("No handle, and no usable printer name passed in\n"); + return -1; + } + + if ( !(fMode & DM_IN_BUFFER ) || + ( ( pDevModeInput && !IsValidDevmodeNoSizeW( (PDEVMODEW)pDevModeInput ) ) ) ) + { + pDevModeInput = NULL; + fMode &= ~DM_IN_BUFFER; + } + + docprophdr.cbSize = sizeof(DOCUMENTPROPERTYHEADER); + docprophdr.Reserved = 0; + docprophdr.hPrinter = hUseHandle; + docprophdr.pszPrinterName = pDeviceName; + docprophdr.cbOut = 0; + + if ( pDevModeOutput ) + { + docprophdr.pdmIn = NULL; + docprophdr.pdmOut = NULL; + docprophdr.fMode = 0; + FIXME("DPW : Call DocumentPropertySheets with pDevModeOutput %p\n",pDevModeOutput); + docprophdr.cbOut = DocumentPropertySheets( NULL, (LPARAM)&docprophdr ); + } + + docprophdr.pdmIn = pDevModeInput; + docprophdr.pdmOut = pDevModeOutput; + docprophdr.fMode = fMode; + + if ( fMode & DM_IN_PROMPT ) + { + Result = CPSUI_CANCEL; + + // + // Now call the Property Sheet for Print > Properties. + // + if ( CallCommonPropertySheetUI( hWnd, (PFNPROPSHEETUI)DocumentPropertySheets, (LPARAM)&docprophdr, (LPDWORD)&Result ) < 0 ) { - Result = Length; + FIXME("CallCommonPropertySheetUI return error\n"); + Result = ERR_CPSUI_GETLASTERROR; } + else + Result = (Result == CPSUI_OK) ? IDOK : IDCANCEL; + FIXME("CallCommonPropertySheetUI returned\n"); + } + else + { + FIXME("DPW : CallDocumentPropertySheets\n"); + Result = DocumentPropertySheets( NULL, (LPARAM)&docprophdr ); + }
- HeapFree(hProcessHeap, 0, pi9); + if ( Result != ERR_CPSUI_GETLASTERROR || Result != ERR_CPSUI_ALLOCMEM_FAILED ) + { + if ( pDevModeOutput ) + { + if ( !IsValidDevmodeNoSizeW( pDevModeOutput ) ) + { + ERR("DPW : Improper pDevModeOutput size.\n"); + Result = -1; + } + } + else + { + ERR("No pDevModeOutput\n"); + } }
if (hUseHandle && !hPrinter) @@ -373,6 +1240,56 @@ DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pD return Result; }
+BOOL +WINAPI +PrinterProperties( HWND hWnd, HANDLE hPrinter ) +{ + PRINTER_INFO_2W *pi2 = NULL; + DWORD needed = 0; + LONG Ret, Result = 0; + BOOL res; + DEVICEPROPERTYHEADER devprophdr; + + FIXME("PrinterProperties(%p, %p)\n", hWnd, hPrinter); + + devprophdr.cbSize = sizeof(DEVICEPROPERTYHEADER); + devprophdr.Flags = DPS_NOPERMISSION; + devprophdr.hPrinter = hPrinter; + devprophdr.pszPrinterName = NULL; + + res = GetPrinterW( hPrinter, 2, NULL, 0, &needed); + if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) + { + pi2 = HeapAlloc(hProcessHeap, 0, needed); + res = GetPrinterW(hPrinter, 2, (LPBYTE)pi2, needed, &needed); + } + + // + // Above can fail, still process w/o printer name. + // + if ( res ) devprophdr.pszPrinterName = pi2->pPrinterName; + + needed = 1; + + if ( ( SetPrinterDataW( hPrinter, L"PrinterPropertiesPermission", REG_DWORD, (LPBYTE)&needed, sizeof(DWORD) ) == ERROR_SUCCESS ) ) + { + devprophdr.Flags &= ~DPS_NOPERMISSION; + } + + Ret = CallCommonPropertySheetUI( hWnd, (PFNPROPSHEETUI)DevicePropertySheets, (LPARAM)&devprophdr, (LPDWORD)&Result ); + + res = (Ret >= 0); + + if (!res) + { + FIXME("PrinterProperties fail ICPSUI\n"); + } + + if (pi2) HeapFree(hProcessHeap, 0, pi2); + + return res; +} + BOOL WINAPI EndDocPrinter(HANDLE hPrinter) { @@ -421,7 +1338,7 @@ EndDocPrinter(HANDLE hPrinter) }
// A new document can now be started again. - pHandle->bStartedDoc = FALSE; + pHandle->bTrayIcon = pHandle->bJob = pHandle->bStartedDoc = FALSE;
Cleanup: SetLastError(dwErrorCode); @@ -823,8 +1740,11 @@ EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbB
HeapFree(hProcessHeap, 0, pszParameters); } + if ( ppi2w[i].pDevMode ) + { + RosConvertUnicodeDevModeToAnsiDevmode( ppi2w[i].pDevMode, ppi2a[i].pDevMode ); + } break; - }
case 4: @@ -1089,7 +2009,7 @@ GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer) *pcchBuffer = pwszComma - pwszDevice + 1;
// Check if the supplied buffer is large enough. - if (cchInputBuffer < *pcchBuffer) + if ( !pszBuffer || cchInputBuffer < *pcchBuffer) { dwErrorCode = ERROR_INSUFFICIENT_BUFFER; goto Cleanup; @@ -1126,6 +2046,8 @@ GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD PPRINTER_INFO_5W ppi5w = (PPRINTER_INFO_5W)pPrinter; PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter; PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter; + PPRINTER_INFO_9A ppi9a = (PPRINTER_INFO_9A)pPrinter; + PPRINTER_INFO_9W ppi9w = (PPRINTER_INFO_9W)pPrinter; DWORD cch;
TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded); @@ -1445,6 +2367,10 @@ GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD
HeapFree(hProcessHeap, 0, pszParameters); } + if ( ppi2w->pDevMode ) + { + RosConvertUnicodeDevModeToAnsiDevmode( ppi2w->pDevMode, ppi2a->pDevMode ); + } break; }
@@ -1562,8 +2488,12 @@ GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD
HeapFree(hProcessHeap, 0, pszaObjectGUID); } - break; } + break; + case 8: + case 9: + RosConvertUnicodeDevModeToAnsiDevmode(ppi9w->pDevMode, ppi9a->pDevMode); + break; } // switch
dwErrorCode = ERROR_SUCCESS; @@ -1574,431 +2504,24 @@ Cleanup: }
BOOL WINAPI -GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) -{ +GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded) +{ DWORD dwErrorCode; - /* - * We are mapping multiple different pointers to the same pDriverInfo pointer here so that - * we can use the same incoming pointer for different Levels - */ - PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo; - PDRIVER_INFO_2W pdi2w = (PDRIVER_INFO_2W)pDriverInfo; - PDRIVER_INFO_3W pdi3w = (PDRIVER_INFO_3W)pDriverInfo; - PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo; - PDRIVER_INFO_5W pdi5w = (PDRIVER_INFO_5W)pDriverInfo; - PDRIVER_INFO_6W pdi6w = (PDRIVER_INFO_6W)pDriverInfo; - - DWORD cch; - PWSTR pwszEnvironment = NULL; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
- TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); + TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
- // Check for invalid levels here for early error return. Should be 1-6. - if (Level < 1 || Level > 6) + // Sanity checks. + if (!pHandle) { - dwErrorCode = ERROR_INVALID_LEVEL; - ERR("Invalid Level!\n"); + dwErrorCode = ERROR_INVALID_HANDLE; goto Cleanup; }
- if (pEnvironment) - { - // Convert pEnvironment to a Unicode string pwszEnvironment. - cch = strlen(pEnvironment); - - pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); - if (!pwszEnvironment) - { - dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; - ERR("HeapAlloc failed!\n"); - goto Cleanup; - } - - MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1); - } - - if (!GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded)) + // Dismiss invalid levels already at this point. + if (Level > 9) { - dwErrorCode = GetLastError(); - goto Cleanup; - } - - // Do Unicode to ANSI conversions for strings based on Level - switch (Level) - { - case 1: - { - dwErrorCode = UnicodeToAnsiInPlace(pdi1w->pName); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - break; - } - - case 2: - { - dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pName); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pEnvironment); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pDriverPath); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pDataFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi2w->pConfigFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - break; - } - - case 3: - { - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pName); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pEnvironment); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDriverPath); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDataFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pConfigFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pHelpFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDependentFiles); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pMonitorName); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi3w->pDefaultDataType); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - break; - } - - case 4: - { - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pName); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pEnvironment); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDriverPath); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pDataFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pConfigFile); - if (dwErrorCode != ERROR_SUCCESS) - { - goto Cleanup; - } - - dwErrorCode = UnicodeToAnsiInPlace(pdi4w->pHelpFile); ... 2225 lines suppressed ...