https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7bffb703530d89e2c20f1…
commit 7bffb703530d89e2c20f1091d93c8d1f8325448d
Author: James Tabor <james.tabor(a)reactos.org>
AuthorDate: Mon Aug 3 21:07:58 2020 -0500
Commit: James Tabor <james.tabor(a)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 ...