[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.
This commit is contained in:
James Tabor 2020-08-03 21:07:58 -05:00
parent 89e716a7f7
commit 7bffb70353
26 changed files with 5427 additions and 689 deletions

View file

@ -1,6 +1,6 @@
@ stub ConnectToPrinterDlg
@ stub ConnectToPrinterPropertyPage
@ stub ConstructPrinterFriendlyName
@ stdcall -stub ConstructPrinterFriendlyName(wstr wstr ptr)
@ stub -private DllCanUnloadNow
@ stub -private DllGetClassObject
@ stub DocumentPropertiesWrap

View file

@ -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;
}
/**

View file

@ -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

View file

@ -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

View file

@ -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 )

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;

View file

@ -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
StartPortThread( LPWSTR pName, HWND hWnd, LPWSTR pPortName, FARPROC fpFunction )
{
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
AddPortA(PSTR pName, HWND hWnd, PSTR pMonitorName)
{
TRACE("AddPortA(%s, %p, %s)\n", pName, hWnd, pMonitorName);
UNIMPLEMENTED;
return FALSE;
}
LPWSTR nameW = NULL;
LPWSTR monitorW = NULL;
DWORD len;
BOOL res;
BOOL WINAPI
AddPortExA(PSTR pName, DWORD Level, PBYTE lpBuffer, PSTR lpMonitorName)
{
TRACE("AddPortExA(%s, %lu, %p, %s)\n", pName, Level, lpBuffer, lpMonitorName);
UNIMPLEMENTED;
return FALSE;
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);
}

View file

@ -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

View file

@ -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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -12,33 +12,89 @@
BOOL WINAPI
AddPrintProcessorA(PSTR pName, PSTR pEnvironment, PSTR pPathName, PSTR pPrintProcessorName)
{
UNICODE_STRING NameW, EnvW, PathW, ProcessorW;
BOOL Ret;
TRACE("AddPrintProcessorA(%s, %s, %s, %s)\n", pName, pEnvironment, pPathName, pPrintProcessorName);
UNIMPLEMENTED;
return FALSE;
AsciiToUnicode(&NameW, pName);
AsciiToUnicode(&EnvW, pEnvironment);
AsciiToUnicode(&PathW, pPathName);
AsciiToUnicode(&ProcessorW, pPrintProcessorName);
Ret = AddPrintProcessorW(NameW.Buffer, EnvW.Buffer, PathW.Buffer, ProcessorW.Buffer);
RtlFreeUnicodeString(&ProcessorW);
RtlFreeUnicodeString(&PathW);
RtlFreeUnicodeString(&EnvW);
RtlFreeUnicodeString(&NameW);
return Ret;
}
BOOL WINAPI
AddPrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPathName, PWSTR pPrintProcessorName)
{
DWORD dwErrorCode;
TRACE("AddPrintProcessorW(%S, %S, %S, %S)\n", pName, pEnvironment, pPathName, pPrintProcessorName);
UNIMPLEMENTED;
return FALSE;
RpcTryExcept
{
dwErrorCode = _RpcAddPrintProcessor( pName, pEnvironment, pPathName, pPrintProcessorName );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcPrintProcessor failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DeletePrintProcessorA(PSTR pName, PSTR pEnvironment, PSTR pPrintProcessorName)
{
UNICODE_STRING NameW, EnvW, ProcessorW;
BOOL Ret;
TRACE("DeletePrintProcessorA(%s, %s, %s)\n", pName, pEnvironment, pPrintProcessorName);
UNIMPLEMENTED;
return FALSE;
AsciiToUnicode(&NameW, pName);
AsciiToUnicode(&EnvW, pEnvironment);
AsciiToUnicode(&ProcessorW, pPrintProcessorName);
Ret = DeletePrintProcessorW(NameW.Buffer, EnvW.Buffer, ProcessorW.Buffer);
RtlFreeUnicodeString(&ProcessorW);
RtlFreeUnicodeString(&EnvW);
RtlFreeUnicodeString(&NameW);
return Ret;
}
BOOL WINAPI
DeletePrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProcessorName)
{
DWORD dwErrorCode;
TRACE("DeletePrintProcessorW(%S, %S, %S)\n", pName, pEnvironment, pPrintProcessorName);
UNIMPLEMENTED;
return FALSE;
RpcTryExcept
{
dwErrorCode = _RpcDeletePrintProcessor( pName, pEnvironment, pPrintProcessorName );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcDeletePrintProcessor failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
@ -89,9 +145,115 @@ Cleanup:
BOOL WINAPI
EnumPrintProcessorsA(PSTR pName, PSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
TRACE("EnumPrintProcessorsA(%s, %s, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
UNIMPLEMENTED;
return FALSE;
BOOL res;
LPBYTE bufferW = NULL;
LPWSTR nameW = NULL;
LPWSTR envW = NULL;
DWORD needed = 0;
DWORD numentries = 0;
INT len;
TRACE("EnumPrintProcessorsA(%s, %s, %d, %p, %d, %p, %p)\n", debugstr_a(pName), debugstr_a(pEnvironment), Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
/* convert names 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);
}
if (pEnvironment)
{
len = MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, NULL, 0);
envW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, envW, len);
}
/* alloc (userbuffersize*sizeof(WCHAR) and try to enum the monitors */
needed = cbBuf * sizeof(WCHAR);
if (needed) bufferW = HeapAlloc(GetProcessHeap(), 0, needed);
res = EnumPrintProcessorsW(nameW, envW, 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 = EnumPrintProcessorsW(nameW, envW, Level, bufferW, needed, pcbNeeded, pcReturned);
}
numentries = pcReturned ? *pcReturned : 0;
needed = 0;
if (res)
{
/* EnumPrintProcessorsW collected all Data. Parse them to calculate ANSI-Size */
DWORD index;
LPSTR ptr;
PPRINTPROCESSOR_INFO_1W ppiw;
PPRINTPROCESSOR_INFO_1A ppia;
/* First pass: calculate the size for all Entries */
ppiw = (PPRINTPROCESSOR_INFO_1W) bufferW;
ppia = (PPRINTPROCESSOR_INFO_1A) pPrintProcessorInfo;
index = 0;
while (index < numentries)
{
index++;
needed += sizeof(PRINTPROCESSOR_INFO_1A);
TRACE("%p: parsing #%d (%s)\n", ppiw, index, debugstr_w(ppiw->pName));
needed += WideCharToMultiByte(CP_ACP, 0, ppiw->pName, -1,
NULL, 0, NULL, NULL);
ppiw = (PPRINTPROCESSOR_INFO_1W) (((LPBYTE)ppiw) + sizeof(PRINTPROCESSOR_INFO_1W));
ppia = (PPRINTPROCESSOR_INFO_1A) (((LPBYTE)ppia) + sizeof(PRINTPROCESSOR_INFO_1A));
}
/* check for errors and quit on failure */
if (cbBuf < needed)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
res = FALSE;
goto epp_cleanup;
}
len = numentries * sizeof(PRINTPROCESSOR_INFO_1A); /* room for structs */
ptr = (LPSTR) &pPrintProcessorInfo[len]; /* start of strings */
cbBuf -= len ; /* free Bytes in the user-Buffer */
ppiw = (PPRINTPROCESSOR_INFO_1W) bufferW;
ppia = (PPRINTPROCESSOR_INFO_1A) pPrintProcessorInfo;
index = 0;
/* Second Pass: Fill the User Buffer (if we have one) */
while ((index < numentries) && pPrintProcessorInfo)
{
index++;
TRACE("%p: writing PRINTPROCESSOR_INFO_1A #%d\n", ppia, index);
ppia->pName = ptr;
len = WideCharToMultiByte(CP_ACP, 0, ppiw->pName, -1,
ptr, cbBuf , NULL, NULL);
ptr += len;
cbBuf -= len;
ppiw = (PPRINTPROCESSOR_INFO_1W) (((LPBYTE)ppiw) + sizeof(PRINTPROCESSOR_INFO_1W));
ppia = (PPRINTPROCESSOR_INFO_1A) (((LPBYTE)ppia) + sizeof(PRINTPROCESSOR_INFO_1A));
}
}
epp_cleanup:
if (pcbNeeded) *pcbNeeded = needed;
if (pcReturned) *pcReturned = (res) ? numentries : 0;
HeapFree(GetProcessHeap(), 0, nameW);
HeapFree(GetProcessHeap(), 0, envW);
HeapFree(GetProcessHeap(), 0, bufferW);
TRACE("returning %d with %d (%d byte for %d entries)\n", (res), GetLastError(), needed, numentries);
return (res);
}
BOOL WINAPI

View file

@ -10,31 +10,152 @@
BOOL WINAPI
AddPrintProvidorA(PSTR pName, DWORD Level, PBYTE pProviderInfo)
{
LPWSTR nameW = NULL;
PROVIDOR_INFO_1W pi1W;
PROVIDOR_INFO_2W pi2W;
DWORD len;
BOOL res;
PBYTE pPI = NULL;
TRACE("AddPrintProvidorA(%s, %lu, %p)\n", pName, Level, pProviderInfo);
UNIMPLEMENTED;
return FALSE;
ZeroMemory(&pi1W, sizeof(PROVIDOR_INFO_1W));
pi2W.pOrder = NULL;
switch (Level)
{
case 1:
{
PROVIDOR_INFO_1A *pi1A = (PROVIDOR_INFO_1A*)pProviderInfo;
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);
}
if (pi1A->pEnvironment)
{
len = MultiByteToWideChar(CP_ACP, 0, pi1A->pEnvironment, -1, NULL, 0);
pi1W.pEnvironment = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, pi1A->pEnvironment, -1, pi1W.pEnvironment, len);
}
if (pi1A->pDLLName)
{
len = MultiByteToWideChar(CP_ACP, 0, pi1A->pDLLName, -1, NULL, 0);
pi1W.pDLLName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, pi1A->pDLLName, -1, pi1W.pDLLName, len);
}
pPI = (PBYTE)&pi1W;
}
break;
case 2:
{
PROVIDOR_INFO_2A *pi2A = (PROVIDOR_INFO_2A*)pProviderInfo;
if (pi2A->pOrder)
{
len = MultiByteToWideChar(CP_ACP, 0, pi2A->pOrder, -1, NULL, 0);
pi2W.pOrder = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, pi2A->pOrder, -1, pi2W.pOrder, len);
}
pPI = (PBYTE)&pi2W;
}
break;
default:
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);
}
res = AddPrintProvidorW( nameW, Level, pPI );
if (pName) HeapFree(GetProcessHeap(), 0, nameW);
if (pi1W.pName) HeapFree(GetProcessHeap(), 0, pi1W.pName);
if (pi1W.pEnvironment) HeapFree(GetProcessHeap(), 0, pi1W.pEnvironment);
if (pi1W.pDLLName) HeapFree(GetProcessHeap(), 0, pi1W.pDLLName);
if (pi2W.pOrder) HeapFree(GetProcessHeap(), 0, pi2W.pOrder);
return res;
}
BOOL WINAPI
AddPrintProvidorW(PWSTR pName, DWORD Level, PBYTE pProviderInfo)
{
DWORD dwErrorCode;
WINSPOOL_PROVIDOR_CONTAINER ProvidorContainer;
TRACE("AddPrintProvidorW(%S, %lu, %p)\n", pName, Level, pProviderInfo);
UNIMPLEMENTED;
return FALSE;
if ((Level < 1) || (Level > 2))
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
ProvidorContainer.ProvidorInfo.pProvidorInfo1 = (WINSPOOL_PROVIDOR_INFO_1*)pProviderInfo;
ProvidorContainer.Level = Level;
RpcTryExcept
{
dwErrorCode = _RpcAddPrintProvidor( pName, &ProvidorContainer );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DeletePrintProvidorA(PSTR pName, PSTR pEnvironment, PSTR pPrintProviderName)
{
UNICODE_STRING NameW, EnvW, ProviderW;
BOOL Ret;
TRACE("DeletePrintProvidorW(%s, %s, %s)\n", pName, pEnvironment, pPrintProviderName);
UNIMPLEMENTED;
return FALSE;
AsciiToUnicode(&NameW, pName);
AsciiToUnicode(&EnvW, pEnvironment);
AsciiToUnicode(&ProviderW, pPrintProviderName);
Ret = DeletePrintProvidorW(NameW.Buffer, EnvW.Buffer, ProviderW.Buffer);
RtlFreeUnicodeString(&ProviderW);
RtlFreeUnicodeString(&EnvW);
RtlFreeUnicodeString(&NameW);
return Ret;
}
BOOL WINAPI
DeletePrintProvidorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProviderName)
{
DWORD dwErrorCode;
TRACE("DeletePrintProvidorW(%S, %S, %S)\n", pName, pEnvironment, pPrintProviderName);
UNIMPLEMENTED;
return FALSE;
RpcTryExcept
{
dwErrorCode = _RpcDeletePrintProvidor( pName, pEnvironment, pPrintProviderName );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -0,0 +1,154 @@
/*
* PROJECT: ReactOS Spooler API
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Spool Files and printing
* COPYRIGHT: Copyright 1998-2020 ReactOS
*/
#include "precomp.h"
HANDLE WINAPI
GetSpoolFileHandle( HANDLE hPrinter )
{
DWORD dwErrorCode, cpid;
WINSPOOL_FILE_INFO_CONTAINER FileInfoContainer;
WINSPOOL_FILE_INFO_1 wsplfi;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
HANDLE hHandle = NULL;
FIXME("GetSpoolFileHandle(%p)\n", hPrinter);
if ( IntProtectHandle( hPrinter, FALSE ) )
{
dwErrorCode = ERROR_INVALID_HANDLE;
}
else
{
if ( pHandle->hSpoolFileHandle != INVALID_HANDLE_VALUE )
{
hHandle = pHandle->hSpoolFileHandle;
}
else
{
cpid = GetCurrentProcessId();
FileInfoContainer.Level = 1;
FileInfoContainer.FileInfo.pFileInfo1 = &wsplfi;
// Do the RPC call.
RpcTryExcept
{
dwErrorCode = _RpcGetSpoolFileInfo2( &pHandle->hPrinter, cpid, 1, &FileInfoContainer );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcGetSpoolFileInfo failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
if (dwErrorCode == ERROR_SUCCESS)
{
pHandle->hSpoolFileHandle = wsplfi.hSpoolFileHandle;
pHandle->dwOptions = wsplfi.dwOptions;
hHandle = pHandle->hSpoolFileHandle;
}
}
IntUnprotectHandle(pHandle);
}
SetLastError(dwErrorCode);
return hHandle;
}
HANDLE WINAPI
CommitSpoolData( HANDLE hPrinter, HANDLE hSpoolFile, DWORD cbCommit )
{
DWORD dwErrorCode, cpid;
WINSPOOL_FILE_INFO_CONTAINER FileInfoContainer;
WINSPOOL_FILE_INFO_1 wsplfi;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
HANDLE hHandle = INVALID_HANDLE_VALUE;
FIXME("CommitSpoolData(%p, %p, %d)\n", hPrinter,hSpoolFile,cbCommit);
if ( IntProtectHandle( hPrinter, FALSE ) )
{
return hHandle;
}
if ( pHandle->hSpoolFileHandle == INVALID_HANDLE_VALUE || pHandle->hSpoolFileHandle != hSpoolFile )
{
dwErrorCode = ERROR_INVALID_HANDLE;
}
else
{
cpid = GetCurrentProcessId();
FileInfoContainer.Level = 1;
FileInfoContainer.FileInfo.pFileInfo1 = &wsplfi;
// Do the RPC call.
RpcTryExcept
{
dwErrorCode = _RpcCommitSpoolData2( &pHandle->hPrinter, cpid, cbCommit, 1, &FileInfoContainer );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcCommitSpoolData failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
if (dwErrorCode == ERROR_SUCCESS)
{
if ( wsplfi.hSpoolFileHandle != INVALID_HANDLE_VALUE )
{
CloseHandle( pHandle->hSpoolFileHandle );
pHandle->hSpoolFileHandle = wsplfi.hSpoolFileHandle;
}
hHandle = pHandle->hSpoolFileHandle;
}
IntUnprotectHandle(pHandle);
}
SetLastError(dwErrorCode);
return hHandle;
}
BOOL WINAPI
CloseSpoolFileHandle( HANDLE hPrinter, HANDLE hSpoolFile )
{
DWORD dwErrorCode;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
FIXME("CloseSpoolFileHandle(%p, %p)\n", hPrinter,hSpoolFile);
if ( IntProtectHandle( hPrinter, FALSE ) )
{
return FALSE;
}
if ( pHandle->hSpoolFileHandle == hSpoolFile )
{
CloseHandle( pHandle->hSpoolFileHandle );
pHandle->hSpoolFileHandle = INVALID_HANDLE_VALUE;
// Do the RPC call.
RpcTryExcept
{
dwErrorCode = _RpcCloseSpoolFileHandle( &pHandle->hPrinter );
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
dwErrorCode = RpcExceptionCode();
ERR("_RpcloseSpoolFileHandle failed with exception code %lu!\n", dwErrorCode);
}
RpcEndExcept;
}
else
{
dwErrorCode = ERROR_INVALID_HANDLE;
}
IntUnprotectHandle(pHandle);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -52,3 +52,281 @@ DWORD UnicodeToAnsiInPlace(PWSTR pwszField)
return ERROR_SUCCESS;
}
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);// * sizeof(WCHAR); wine does this.
}
DWORD UnicodeToAnsiZZInPlace(PWSTR pwszzField)
{
PSTR pszTemp;
INT len, lenW;
PSTR pszField = (PSTR)pwszzField;
lenW = multi_sz_lenW(pwszzField);
if (lenW == 0)
{
return ERROR_SUCCESS;
}
len = WideCharToMultiByte(CP_ACP, 0, pwszzField, lenW, NULL, 0, NULL, NULL);
pszTemp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
WideCharToMultiByte(CP_ACP, 0, pwszzField, lenW, pszTemp, len, NULL, NULL);
StringCchCopyA(pszField, len, pszTemp);
HeapFree(hProcessHeap, 0, pszTemp);
return ERROR_SUCCESS;
}
//
// Implement and simplify later.
//
LONG WINAPI
IntProtectHandle( HANDLE hSpooler, BOOL Close )
{
BOOL Bad = TRUE;
LONG Ret;
PSPOOLER_HANDLE pHandle;
EnterCriticalSection(&rtlCritSec);
_SEH2_TRY
{
pHandle = (PSPOOLER_HANDLE)hSpooler;
if ( pHandle && pHandle->Sig == SPOOLER_HANDLE_SIG )
{
Bad = FALSE; // Not bad.
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
}
_SEH2_END;
Ret = Bad; // Set return Level to 1 if we are BAD.
if ( Bad )
{
SetLastError(ERROR_INVALID_HANDLE);
ERR("IPH : Printer Handle failed!\n");
}
else
{
if ( Close )
{
if ( pHandle->bShared || pHandle->cCount != 0 )
{
pHandle->bShared = TRUE;
Ret = 2; // Return a high level and we are shared.
FIXME("IPH Close : We are shared\n");
}
else
{
pHandle->bClosed = TRUE;
FIXME("IPH Close : closing.\n");
}
}
}
if ( !Ret ) // Need to be Level 0.
{
pHandle->cCount++;
FIXME("IPH : Count %d\n",pHandle->cCount);
}
LeaveCriticalSection(&rtlCritSec);
// Return Level:
// 2 : Close and/or shared
// 1 : Failed Handle
// 0 : In use.
return Ret;
}
//
// This one too.
//
BOOL WINAPI
IntUnprotectHandle( HANDLE hSpooler )
{
BOOL Ret = FALSE;
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hSpooler;
EnterCriticalSection(&rtlCritSec);
if ( pHandle->bShared && --pHandle->cCount == 0 )
{
pHandle->bClosed = TRUE;
pHandle->bShared = FALSE;
Ret = TRUE;
}
LeaveCriticalSection(&rtlCritSec);
FIXME("IUH : Count %d\n",pHandle->cCount);
if ( Ret )
{
// ClosePrinterWorker( pHandle );
}
return Ret;
}
/**
* @name AllocSplStr
*
* Allocates memory for a Unicode string and copies the input string into it.
* Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr.
*
* @param pwszInput
* The input string to copy
*
* @return
* Pointer to the copied string or NULL if no memory could be allocated.
*/
PWSTR WINAPI
AllocSplStr(PCWSTR pwszInput)
{
DWORD cbInput;
PWSTR pwszOutput;
// Sanity check
if (!pwszInput)
return NULL;
// Get the length of the input string.
cbInput = (wcslen(pwszInput) + 1) * sizeof(WCHAR);
// Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
pwszOutput = HeapAlloc(hProcessHeap, 0, cbInput);
if (!pwszOutput)
{
ERR("HeapAlloc failed!\n");
return NULL;
}
// Copy the string and return it.
CopyMemory(pwszOutput, pwszInput, cbInput);
return pwszOutput;
}
/**
* @name DllAllocSplMem
*
* Allocate a block of zeroed memory.
* Windows allocates from a separate spooler heap here while we just use the process heap.
*
* @param dwBytes
* Number of bytes to allocate.
*
* @return
* A pointer to the allocated memory or NULL in case of an error.
* You have to free this memory using DllFreeSplMem.
*/
PVOID WINAPI
DllAllocSplMem(DWORD dwBytes)
{
return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes);
}
/**
* @name DllFreeSplMem
*
* Frees the memory allocated with DllAllocSplMem.
*
* @param pMem
* Pointer to the allocated memory.
*
* @return
* TRUE in case of success, FALSE otherwise.
*/
BOOL WINAPI
DllFreeSplMem(PVOID pMem)
{
if ( !pMem ) return TRUE;
return HeapFree(hProcessHeap, 0, pMem);
}
/**
* @name DllFreeSplStr
*
* Frees the string allocated with AllocSplStr.
*
* @param pwszString
* Pointer to the allocated string.
*
* @return
* TRUE in case of success, FALSE otherwise.
*/
BOOL WINAPI
DllFreeSplStr(PWSTR pwszString)
{
if ( pwszString )
return HeapFree(hProcessHeap, 0, pwszString);
return FALSE;
}
SECURITY_DESCRIPTOR * get_sd( SECURITY_DESCRIPTOR *sd, DWORD *size )
{
PSID sid_group, sid_owner;
ACL *sacl, *dacl;
BOOL bSet = FALSE, bSetd = FALSE, bSets = FALSE;
PSECURITY_DESCRIPTOR absolute_sd, retsd;
if ( !IsValidSecurityDescriptor( sd ) )
{
return NULL;
}
InitializeSecurityDescriptor( &absolute_sd, SECURITY_DESCRIPTOR_REVISION );
if ( !GetSecurityDescriptorOwner( sd, &sid_owner, &bSet ) )
{
return NULL;
}
SetSecurityDescriptorOwner( &absolute_sd, sid_owner, bSet );
if ( !GetSecurityDescriptorGroup( sd, &sid_group, &bSet ) )
{
return NULL;
}
SetSecurityDescriptorGroup( &absolute_sd, sid_group, bSet );
if ( !GetSecurityDescriptorDacl( sd, &bSetd, &dacl, &bSet ) )
{
return NULL;
}
SetSecurityDescriptorDacl( &absolute_sd, bSetd, dacl, bSet );
if ( !GetSecurityDescriptorSacl( sd, &bSets, &sacl, &bSet ) )
{
return(NULL);
}
SetSecurityDescriptorSacl( &absolute_sd, bSets, sacl, bSet );
*size = GetSecurityDescriptorLength( &absolute_sd );
retsd = HeapAlloc( GetProcessHeap(), 0, *size );
if ( retsd )
{
if ( !MakeSelfRelativeSD( &absolute_sd, retsd, size ) )
{
HeapFree( GetProcessHeap(), 0, retsd );
retsd = NULL;
}
}
return retsd;
}

View file

@ -1,5 +1,35 @@
#include "precomp.h"
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Spooler API"
#define REACTOS_STR_INTERNAL_NAME "winspool"
#define REACTOS_STR_ORIGINAL_FILENAME "winspool.drv"
#include <reactos/version.rc>
#pragma makedep po
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
IDS_CAPTION "Local Port"
IDS_FILE_EXISTS "The output file already exists. Click OK to overwrite."
IDS_CANNOT_OPEN "Unable to create the output file."
}
FILENAME_DIALOG DIALOG 6, 18, 245, 47
STYLE DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION
CAPTION "Print to File"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "&Output File Name:", -1, 7, 13, 194, 13, WS_VISIBLE
EDITTEXT EDITBOX, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL
DEFPUSHBUTTON "OK", IDOK, 199, 10, 40, 14, WS_VISIBLE
PUSHBUTTON "Cancel", IDCANCEL, 199, 27, 40, 14, WS_VISIBLE
END
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/* @makedep: generic.ppd */
/*1 PPDFILE generic.ppd*/

View file

@ -5,7 +5,7 @@
104 stub PerfClose
105 stub PerfCollect
106 stub PerfOpen
107 stub ADVANCEDSETUPDIALOG
107 stdcall ADVANCEDSETUPDIALOG(ptr long ptr ptr) AdvancedSetupDialog
108 stdcall AbortPrinter(ptr)
109 stdcall AddFormA(ptr long ptr)
110 stdcall AddFormW(ptr long ptr)
@ -31,18 +31,18 @@
130 stdcall AddPrinterW(wstr long ptr)
131 stdcall AdvancedDocumentPropertiesA(ptr ptr str ptr ptr)
132 stdcall AdvancedDocumentPropertiesW(ptr ptr wstr ptr ptr)
133 stub AdvancedSetupDialog
133 stdcall AdvancedSetupDialog(ptr long ptr ptr)
134 stdcall ClosePrinter(ptr)
135 stub CloseSpoolFileHandle
136 stub CommitSpoolData
135 stdcall CloseSpoolFileHandle(ptr ptr)
136 stdcall CommitSpoolData(ptr ptr long)
137 stdcall ConfigurePortA(str ptr str)
138 stdcall ConfigurePortW(wstr ptr wstr)
139 stub ConnectToPrinterDlg
140 stub ConvertAnsiDevModeToUnicodeDevmode
141 stub ConvertUnicodeDevModeToAnsiDevmode
142 stub CreatePrinterIC
143 stub DEVICECAPABILITIES
144 stub DEVICEMODE
142 stdcall -stub CreatePrinterIC(ptr ptr)
143 stdcall DEVICECAPABILITIES(str str long ptr ptr) DeviceCapabilitiesA
144 stdcall DEVICEMODE(ptr ptr str ptr) DeviceMode
145 stdcall DeleteFormA(ptr str)
146 stdcall DeleteFormW(ptr wstr)
147 stdcall DeleteMonitorA(str str str)
@ -64,21 +64,21 @@
163 stdcall DeletePrinterDriverExA(str str str long long)
164 stdcall DeletePrinterDriverExW(wstr wstr wstr long long)
165 stdcall DeletePrinterDriverW(wstr wstr wstr)
166 stub DeletePrinterIC
166 stdcall -stub DeletePrinterIC(ptr)
167 stdcall DeletePrinterKeyA(ptr str)
168 stdcall DeletePrinterKeyW(ptr wstr)
169 stub DevQueryPrint
170 stub DevQueryPrintEx
171 stub DeviceCapabilities
169 stdcall DevQueryPrint(ptr ptr ptr)
170 stdcall DevQueryPrintEx(ptr)
171 stdcall DeviceCapabilities(str str long ptr ptr) DeviceCapabilitiesA
172 stdcall DeviceCapabilitiesA(str str long ptr ptr)
173 stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr)
174 stub DeviceMode
175 stub DevicePropertySheets
174 stdcall -stub DeviceMode(ptr ptr str ptr)
175 stdcall DevicePropertySheets(ptr long)
176 stdcall DocumentEvent(ptr ptr long long ptr long ptr)
177 stdcall DocumentPropertiesA(ptr ptr ptr ptr ptr long)
178 stdcall DocumentPropertiesW(ptr ptr ptr ptr ptr long)
179 stub DocumentPropertySheets
180 stub EXTDEVICEMODE
177 stdcall DocumentPropertiesA(ptr ptr str ptr ptr long)
178 stdcall DocumentPropertiesW(ptr ptr wstr ptr ptr long)
179 stdcall DocumentPropertySheets(ptr long)
180 stdcall EXTDEVICEMODE(ptr ptr ptr str str ptr str long) ExtDeviceMode
181 stdcall EndDocPrinter(ptr)
182 stdcall EndPagePrinter(ptr)
183 stdcall EnumFormsA(ptr long ptr long ptr ptr)
@ -110,13 +110,13 @@
209 stub -noname DeletePerMachineConnectionW
210 stub -noname EnumPerMachineConnectionsA
211 stub -noname EnumPerMachineConnectionsW
212 stub -noname LoadPrinterDriver
212 stdcall -noname LoadPrinterDriver(ptr)
213 stub -noname RefCntLoadDriver
214 stub -noname RefCntUnloadDriver
215 stub -noname ForceUnloadDriver
216 stub -noname PublishPrinterA
217 stub -noname PublishPrinterW
218 stub -noname CallCommonPropertySheetUI
218 stdcall -noname CallCommonPropertySheetUI(ptr ptr long ptr)
219 stub -noname PrintUIQueueCreate
220 stub -noname PrintUIPrinterPropPages
221 stub -noname PrintUIDocumentDefaults
@ -134,7 +134,7 @@
233 stdcall EnumPrinterKeyW(ptr wstr wstr long ptr)
234 stdcall EnumPrintersA(long ptr long ptr long ptr ptr)
235 stdcall EnumPrintersW(long ptr long ptr long ptr ptr)
236 stub ExtDeviceMode
236 stdcall -stub ExtDeviceMode(ptr ptr ptr str str ptr str long)
237 stub FindClosePrinterChangeNotification
238 stub FindFirstPrinterChangeNotification
239 stub FindNextPrinterChangeNotification
@ -156,18 +156,18 @@
255 stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr)
256 stdcall GetPrinterDriverW(ptr wstr long ptr long ptr)
257 stdcall GetPrinterW(ptr long ptr long ptr)
258 stub GetSpoolFileHandle
258 stdcall GetSpoolFileHandle(ptr)
259 stdcall IsValidDevmodeA(ptr long)
260 stdcall IsValidDevmodeW(ptr long)
261 stdcall OpenPrinterA(str ptr ptr)
262 stdcall OpenPrinterW(wstr ptr ptr)
263 stub PlayGdiScriptOnPrinterIC
264 stub PrinterMessageBoxA
265 stub PrinterMessageBoxW
266 stub PrinterProperties
267 stub QueryColorProfile
268 stub QueryRemoteFonts
269 stub QuerySpoolMode
263 stdcall -stub PlayGdiScriptOnPrinterIC(ptr ptr long ptr long long)
264 stdcall PrinterMessageBoxA(ptr long ptr str str long)
265 stdcall PrinterMessageBoxW(ptr long ptr wstr wstr long)
266 stdcall PrinterProperties(ptr ptr)
267 stdcall QueryColorProfile(ptr ptr long ptr ptr ptr)
268 stdcall QueryRemoteFonts(ptr ptr long)
269 stdcall QuerySpoolMode(ptr ptr ptr)
270 stdcall ReadPrinter(ptr ptr long ptr)
271 stdcall ResetPrinterA(ptr ptr)
272 stdcall ResetPrinterW(ptr ptr)
@ -189,9 +189,9 @@
288 stdcall SplDriverUnloadComplete(ptr)
289 stub SpoolerDevQueryPrintW
290 stdcall SpoolerInit()
291 stub SpoolerPrinterEvent
292 stub StartDocDlgA
293 stub StartDocDlgW
291 stdcall SpoolerPrinterEvent(wstr long long long)
292 stdcall StartDocDlgA(ptr ptr)
293 stdcall StartDocDlgW(ptr ptr)
294 stdcall StartDocPrinterA(ptr long ptr)
295 stdcall StartDocPrinterW(ptr long ptr)
296 stdcall StartPagePrinter(ptr)

View file

@ -0,0 +1,31 @@
/*
* PROJECT: ReactOS Printing Stack Marshalling Functions
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Marshalling definitions for FORM_INFO_*
* COPYRIGHT: Copyright 1998-2020 ReactOS
*/
static const MARSHALLING FormInfo1Marshalling = {
sizeof(FORM_INFO_1W),
{
{ FIELD_OFFSET(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), RTL_FIELD_SIZE(FORM_INFO_1W, pName), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING FormInfo2Marshalling = {
sizeof(FORM_INFO_2W),
{
{ FIELD_OFFSET(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), RTL_FIELD_SIZE(FORM_INFO_2W, pName), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), RTL_FIELD_SIZE(FORM_INFO_2W, pKeyword), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), RTL_FIELD_SIZE(FORM_INFO_2W, pMuiDll), TRUE },
{ FIELD_OFFSET(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), RTL_FIELD_SIZE(FORM_INFO_2W, pDisplayName), FALSE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING* pFormInfoMarshalling[] = {
NULL,
&FormInfo1Marshalling,
&FormInfo2Marshalling
};

View file

@ -53,7 +53,7 @@ static const MARSHALLING PrinterDriver4Marshalling = {
{ FIELD_OFFSET(DRIVER_INFO_4W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDependentFiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_4W, pMonitorName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pDefaultDataType), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_4W, pszzPreviousNames), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
@ -70,6 +70,52 @@ static const MARSHALLING PrinterDriver5Marshalling = {
}
};
static const MARSHALLING PrinterDriver6Marshalling = {
sizeof(DRIVER_INFO_6W),
{
{ FIELD_OFFSET(DRIVER_INFO_6W, pName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_6W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_6W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pConfigFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_6W, pHelpFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDependentFiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pMonitorName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_6W, pDefaultDataType), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszzPreviousNames), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pszMfgName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszMfgName), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszMfgName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pszOEMUrl), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszOEMUrl), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszOEMUrl), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pszHardwareID), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszHardwareID), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszHardwareID), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_6W, pszProvider), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszProvider), RTL_FIELD_SIZE(DRIVER_INFO_6W, pszProvider), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING PrinterDriver8Marshalling = {
sizeof(DRIVER_INFO_8W),
{
{ FIELD_OFFSET(DRIVER_INFO_8W, pName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_8W, pEnvironment), RTL_FIELD_SIZE(DRIVER_INFO_8W, pEnvironment), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDriverPath), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDriverPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDataFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDataFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pConfigFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pConfigFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pHelpFile), RTL_FIELD_SIZE(DRIVER_INFO_8W, pHelpFile), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDependentFiles), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDependentFiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pMonitorName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pMonitorName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDefaultDataType), RTL_FIELD_SIZE(DRIVER_INFO_8W, pDefaultDataType), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzPreviousNames), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzPreviousNames), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszMfgName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszMfgName), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszMfgName), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszOEMUrl), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszOEMUrl), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszOEMUrl), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszHardwareID), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszHardwareID), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszHardwareID), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszProvider), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszProvider), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszProvider), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszPrintProcessor), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszPrintProcessor), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszPrintProcessor), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszVendorSetup), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszVendorSetup), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszVendorSetup), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszzColorProfiles), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzColorProfiles), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzColorProfiles), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszInfPath), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszInfPath), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszInfPath), TRUE },
{ FIELD_OFFSET(DRIVER_INFO_8W, pszzCoreDriverDependencies), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzCoreDriverDependencies), RTL_FIELD_SIZE(DRIVER_INFO_8W, pszzCoreDriverDependencies), TRUE },
{ MAXDWORD, 0, 0, FALSE }
}
};
static const MARSHALLING* pPrinterDriverMarshalling[] = {
NULL,
@ -78,4 +124,6 @@ static const MARSHALLING* pPrinterDriverMarshalling[] = {
&PrinterDriver3Marshalling,
&PrinterDriver4Marshalling,
&PrinterDriver5Marshalling,
&PrinterDriver6Marshalling,
&PrinterDriver8Marshalling,
};

View file

@ -57,6 +57,13 @@ typedef struct _PRINTER_INFO_STRESS
}
PRINTER_INFO_STRESS, *PPRINTER_INFO_STRESS;
typedef struct _FILE_INFO_1
{
BOOL bInheritHandle;
HANDLE hSpoolFileHandle;
DWORD dwOptions;
} FILE_INFO_1, *PFILE_INFO_1;
PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
@ -69,5 +76,8 @@ BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);
BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable);
BOOL WINAPI SpoolerInit(VOID);
PDWORD WINAPI UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded);
BOOL WINAPI SplGetSpoolFileInfo(HANDLE hPrinter,HANDLE hProcessHandle,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded );
BOOL WINAPI SplCommitSpoolData(HANDLE hPrinter,HANDLE hProcessHandle,DWORD cbCommit,DWORD Level,FILE_INFO_1 *pFileInfo,DWORD dwSize,DWORD* dwNeeded);
BOOL WINAPI SplCloseSpoolFileHandle( HANDLE hPrinter );
#endif

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS Local Spooler
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Spool Files and printing
* COPYRIGHT: Copyright 1998-2020 ReactOS)
* COPYRIGHT: Copyright 1998-2020 ReactOS
*/
#include "precomp.h"