mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 09:50:43 +00:00
[LOCALSPL] [SPOOLSV] [WINSPOOL]
- Refactor the code returning PRINTER_INFO_* yet another time to support both EnumPrinters and GetPrinter calls. - Implement support for PRINTER_INFO_1 through PRINTER_INFO_9 as well as the mostly unknown PRINTER_INFO_STRESS (level 0) structure and return as much information as we can. - Implement GetPrinterW / LocalGetPrinter. The Printers Shell folder in Explorer now shows our "Dummy Printer on LPT1" and we pass all 291 winspool:EnumPrinters API tests :) svn path=/trunk/; revision=74433
This commit is contained in:
parent
f10b1d9976
commit
30d5e8f413
7 changed files with 748 additions and 157 deletions
|
@ -8,23 +8,33 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_MarshallDownPrinterInfo(PBYTE pPrinterInfo, DWORD Level)
|
_MarshallDownPrinterInfo(PBYTE* ppPrinterInfo, DWORD Level)
|
||||||
{
|
{
|
||||||
PPRINTER_INFO_1W pPrinterInfo1;
|
|
||||||
PPRINTER_INFO_2W pPrinterInfo2;
|
|
||||||
|
|
||||||
// Replace absolute pointer addresses in the output by relative offsets.
|
// Replace absolute pointer addresses in the output by relative offsets.
|
||||||
if (Level == 1)
|
if (Level == 0)
|
||||||
{
|
{
|
||||||
pPrinterInfo1 = (PPRINTER_INFO_1W)pPrinterInfo;
|
PPRINTER_INFO_STRESS pPrinterInfo0 = (PPRINTER_INFO_STRESS)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo0->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo0->pPrinterName - (ULONG_PTR)pPrinterInfo0);
|
||||||
|
|
||||||
|
if (pPrinterInfo0->pServerName)
|
||||||
|
pPrinterInfo0->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo0->pServerName - (ULONG_PTR)pPrinterInfo0);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_STRESS);
|
||||||
|
}
|
||||||
|
else if (Level == 1)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_1W pPrinterInfo1 = (PPRINTER_INFO_1W)(*ppPrinterInfo);
|
||||||
|
|
||||||
pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName - (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName - (ULONG_PTR)pPrinterInfo1);
|
||||||
pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription - (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription - (ULONG_PTR)pPrinterInfo1);
|
||||||
pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment - (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment - (ULONG_PTR)pPrinterInfo1);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_1W);
|
||||||
}
|
}
|
||||||
else if (Level == 2)
|
else if (Level == 2)
|
||||||
{
|
{
|
||||||
pPrinterInfo2 = (PPRINTER_INFO_2W)pPrinterInfo;
|
PPRINTER_INFO_2W pPrinterInfo2 = (PPRINTER_INFO_2W)(*ppPrinterInfo);
|
||||||
|
|
||||||
pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName - (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName - (ULONG_PTR)pPrinterInfo2);
|
||||||
pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName - (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName - (ULONG_PTR)pPrinterInfo2);
|
||||||
|
@ -42,7 +52,66 @@ _MarshallDownPrinterInfo(PBYTE pPrinterInfo, DWORD Level)
|
||||||
pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName - (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName - (ULONG_PTR)pPrinterInfo2);
|
||||||
|
|
||||||
if (pPrinterInfo2->pSecurityDescriptor)
|
if (pPrinterInfo2->pSecurityDescriptor)
|
||||||
pPrinterInfo2->pSecurityDescriptor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor - (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor - (ULONG_PTR)pPrinterInfo2);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_2W);
|
||||||
|
}
|
||||||
|
else if (Level == 3)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_3 pPrinterInfo3 = (PPRINTER_INFO_3)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo3->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)((ULONG_PTR)pPrinterInfo3->pSecurityDescriptor - (ULONG_PTR)pPrinterInfo3);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_3);
|
||||||
|
}
|
||||||
|
else if (Level == 4)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_4W pPrinterInfo4 = (PPRINTER_INFO_4W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo4->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo4->pPrinterName - (ULONG_PTR)pPrinterInfo4);
|
||||||
|
|
||||||
|
if (pPrinterInfo4->pServerName)
|
||||||
|
pPrinterInfo4->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo4->pServerName - (ULONG_PTR)pPrinterInfo4);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_4W);
|
||||||
|
}
|
||||||
|
else if (Level == 5)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_5W pPrinterInfo5 = (PPRINTER_INFO_5W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo5->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo5->pPrinterName - (ULONG_PTR)pPrinterInfo5);
|
||||||
|
pPrinterInfo5->pPortName = (PWSTR)((ULONG_PTR)pPrinterInfo5->pPortName - (ULONG_PTR)pPrinterInfo5);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_5W);
|
||||||
|
}
|
||||||
|
else if (Level == 6)
|
||||||
|
{
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_6);
|
||||||
|
}
|
||||||
|
else if (Level == 7)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_7W pPrinterInfo7 = (PPRINTER_INFO_7W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
if (pPrinterInfo7->pszObjectGUID)
|
||||||
|
pPrinterInfo7->pszObjectGUID = (PWSTR)((ULONG_PTR)pPrinterInfo7->pszObjectGUID - (ULONG_PTR)pPrinterInfo7);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_7W);
|
||||||
|
}
|
||||||
|
else if (Level == 8)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_8W pPrinterInfo8 = (PPRINTER_INFO_8W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo8->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo8->pDevMode - (ULONG_PTR)pPrinterInfo8);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_8W);
|
||||||
|
}
|
||||||
|
else if (Level == 9)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_9W pPrinterInfo9 = (PPRINTER_INFO_9W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo9->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo9->pDevMode - (ULONG_PTR)pPrinterInfo9);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_9W);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,16 +224,8 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
|
||||||
DWORD i;
|
DWORD i;
|
||||||
PBYTE p = pPrinterEnumAligned;
|
PBYTE p = pPrinterEnumAligned;
|
||||||
|
|
||||||
// Replace absolute pointer addresses in the output by relative offsets.
|
|
||||||
for (i = 0; i < *pcReturned; i++)
|
for (i = 0; i < *pcReturned; i++)
|
||||||
{
|
_MarshallDownPrinterInfo(&p, Level);
|
||||||
_MarshallDownPrinterInfo(p, Level);
|
|
||||||
|
|
||||||
if (Level == 1)
|
|
||||||
p += sizeof(PRINTER_INFO_1W);
|
|
||||||
else if (Level == 2)
|
|
||||||
p += sizeof(PRINTER_INFO_2W);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
|
@ -183,8 +244,30 @@ _RpcFlushPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWOR
|
||||||
DWORD
|
DWORD
|
||||||
_RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pPrinter, DWORD cbBuf, DWORD* pcbNeeded)
|
_RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pPrinter, DWORD cbBuf, DWORD* pcbNeeded)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
DWORD dwErrorCode;
|
||||||
return ERROR_INVALID_FUNCTION;
|
PBYTE pPrinterAligned;
|
||||||
|
|
||||||
|
dwErrorCode = RpcImpersonateClient(NULL);
|
||||||
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
|
||||||
|
return dwErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPrinterAligned = AlignRpcPtr(pPrinter, &cbBuf);
|
||||||
|
GetPrinterW(hPrinter, Level, pPrinterAligned, cbBuf, pcbNeeded);
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
|
||||||
|
if (dwErrorCode == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
PBYTE p = pPrinterAligned;
|
||||||
|
_MarshallDownPrinterInfo(&p, Level);
|
||||||
|
}
|
||||||
|
|
||||||
|
RpcRevertToSelf();
|
||||||
|
UndoAlignRpcPtr(pPrinter, pPrinterAligned, cbBuf, pcbNeeded);
|
||||||
|
|
||||||
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Print Spooler API
|
* PROJECT: ReactOS Print Spooler API
|
||||||
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
|
||||||
* PURPOSE: Precompiled Header for all source files
|
* PURPOSE: Precompiled Header for all source files
|
||||||
* COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PRECOMP_H
|
#ifndef _PRECOMP_H
|
||||||
|
@ -16,6 +16,8 @@
|
||||||
#include <winspool.h>
|
#include <winspool.h>
|
||||||
#include <winspool_c.h>
|
#include <winspool_c.h>
|
||||||
|
|
||||||
|
#include <spoolss.h>
|
||||||
|
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winspool);
|
WINE_DEFAULT_DEBUG_CHANNEL(winspool);
|
||||||
|
|
||||||
|
|
|
@ -8,23 +8,33 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_MarshallUpPrinterInfo(PBYTE pPrinterInfo, DWORD Level)
|
_MarshallUpPrinterInfo(PBYTE* ppPrinterInfo, DWORD Level)
|
||||||
{
|
{
|
||||||
PPRINTER_INFO_1W pPrinterInfo1;
|
// Replace relative offset addresses in the output by absolute pointers and advance to the next structure.
|
||||||
PPRINTER_INFO_2W pPrinterInfo2;
|
if (Level == 0)
|
||||||
|
|
||||||
// Replace relative offset addresses in the output by absolute pointers.
|
|
||||||
if (Level == 1)
|
|
||||||
{
|
{
|
||||||
pPrinterInfo1 = (PPRINTER_INFO_1W)pPrinterInfo;
|
PPRINTER_INFO_STRESS pPrinterInfo0 = (PPRINTER_INFO_STRESS)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo0->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo0->pPrinterName + (ULONG_PTR)pPrinterInfo0);
|
||||||
|
|
||||||
|
if (pPrinterInfo0->pServerName)
|
||||||
|
pPrinterInfo0->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo0->pServerName + (ULONG_PTR)pPrinterInfo0);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_STRESS);
|
||||||
|
}
|
||||||
|
else if (Level == 1)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_1W pPrinterInfo1 = (PPRINTER_INFO_1W)(*ppPrinterInfo);
|
||||||
|
|
||||||
pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName + (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName + (ULONG_PTR)pPrinterInfo1);
|
||||||
pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription + (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription + (ULONG_PTR)pPrinterInfo1);
|
||||||
pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment + (ULONG_PTR)pPrinterInfo1);
|
pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment + (ULONG_PTR)pPrinterInfo1);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_1W);
|
||||||
}
|
}
|
||||||
else if (Level == 2)
|
else if (Level == 2)
|
||||||
{
|
{
|
||||||
pPrinterInfo2 = (PPRINTER_INFO_2W)pPrinterInfo;
|
PPRINTER_INFO_2W pPrinterInfo2 = (PPRINTER_INFO_2W)(*ppPrinterInfo);
|
||||||
|
|
||||||
pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName + (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName + (ULONG_PTR)pPrinterInfo2);
|
||||||
pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName + (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName + (ULONG_PTR)pPrinterInfo2);
|
||||||
|
@ -42,7 +52,66 @@ _MarshallUpPrinterInfo(PBYTE pPrinterInfo, DWORD Level)
|
||||||
pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName + (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName + (ULONG_PTR)pPrinterInfo2);
|
||||||
|
|
||||||
if (pPrinterInfo2->pSecurityDescriptor)
|
if (pPrinterInfo2->pSecurityDescriptor)
|
||||||
pPrinterInfo2->pSecurityDescriptor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor + (ULONG_PTR)pPrinterInfo2);
|
pPrinterInfo2->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor + (ULONG_PTR)pPrinterInfo2);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_2W);
|
||||||
|
}
|
||||||
|
else if (Level == 3)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_3 pPrinterInfo3 = (PPRINTER_INFO_3)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo3->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)((ULONG_PTR)pPrinterInfo3->pSecurityDescriptor + (ULONG_PTR)pPrinterInfo3);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_3);
|
||||||
|
}
|
||||||
|
else if (Level == 4)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_4W pPrinterInfo4 = (PPRINTER_INFO_4W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo4->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo4->pPrinterName + (ULONG_PTR)pPrinterInfo4);
|
||||||
|
|
||||||
|
if (pPrinterInfo4->pServerName)
|
||||||
|
pPrinterInfo4->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo4->pServerName + (ULONG_PTR)pPrinterInfo4);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_4W);
|
||||||
|
}
|
||||||
|
else if (Level == 5)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_5W pPrinterInfo5 = (PPRINTER_INFO_5W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo5->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo5->pPrinterName + (ULONG_PTR)pPrinterInfo5);
|
||||||
|
pPrinterInfo5->pPortName = (PWSTR)((ULONG_PTR)pPrinterInfo5->pPortName + (ULONG_PTR)pPrinterInfo5);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_5W);
|
||||||
|
}
|
||||||
|
else if (Level == 6)
|
||||||
|
{
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_6);
|
||||||
|
}
|
||||||
|
else if (Level == 7)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_7W pPrinterInfo7 = (PPRINTER_INFO_7W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
if (pPrinterInfo7->pszObjectGUID)
|
||||||
|
pPrinterInfo7->pszObjectGUID = (PWSTR)((ULONG_PTR)pPrinterInfo7->pszObjectGUID + (ULONG_PTR)pPrinterInfo7);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_7W);
|
||||||
|
}
|
||||||
|
else if (Level == 8)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_8W pPrinterInfo8 = (PPRINTER_INFO_8W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo8->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo8->pDevMode + (ULONG_PTR)pPrinterInfo8);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_8W);
|
||||||
|
}
|
||||||
|
else if (Level == 9)
|
||||||
|
{
|
||||||
|
PPRINTER_INFO_9W pPrinterInfo9 = (PPRINTER_INFO_9W)(*ppPrinterInfo);
|
||||||
|
|
||||||
|
pPrinterInfo9->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo9->pDevMode + (ULONG_PTR)pPrinterInfo9);
|
||||||
|
|
||||||
|
*ppPrinterInfo += sizeof(PRINTER_INFO_9W);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,8 +375,6 @@ BOOL WINAPI
|
||||||
EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
||||||
{
|
{
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
DWORD i;
|
|
||||||
PBYTE p = pPrinterEnum;
|
|
||||||
|
|
||||||
// Dismiss invalid levels already at this point.
|
// Dismiss invalid levels already at this point.
|
||||||
if (Level == 3 || Level > 5)
|
if (Level == 3 || Level > 5)
|
||||||
|
@ -333,16 +400,11 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
|
||||||
|
|
||||||
if (dwErrorCode == ERROR_SUCCESS)
|
if (dwErrorCode == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
// Replace relative offset addresses in the output by absolute pointers.
|
DWORD i;
|
||||||
for (i = 0; i < *pcReturned; i++)
|
PBYTE p = pPrinterEnum;
|
||||||
{
|
|
||||||
_MarshallUpPrinterInfo(p, Level);
|
|
||||||
|
|
||||||
if (Level == 1)
|
for (i = 0; i < *pcReturned; i++)
|
||||||
p += sizeof(PRINTER_INFO_1W);
|
_MarshallUpPrinterInfo(&p, Level);
|
||||||
else if (Level == 2)
|
|
||||||
p += sizeof(PRINTER_INFO_2W);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
|
@ -383,7 +445,39 @@ GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDri
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
|
GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
|
||||||
{
|
{
|
||||||
return FALSE;
|
DWORD dwErrorCode;
|
||||||
|
|
||||||
|
// Dismiss invalid levels already at this point.
|
||||||
|
if (Level > 9)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbBuf && pPrinter)
|
||||||
|
ZeroMemory(pPrinter, cbBuf);
|
||||||
|
|
||||||
|
// Do the RPC call
|
||||||
|
RpcTryExcept
|
||||||
|
{
|
||||||
|
dwErrorCode = _RpcGetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
|
||||||
|
}
|
||||||
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
dwErrorCode = RpcExceptionCode();
|
||||||
|
ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
|
||||||
|
}
|
||||||
|
RpcEndExcept;
|
||||||
|
|
||||||
|
if (dwErrorCode == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
PBYTE p = pPrinter;
|
||||||
|
_MarshallUpPrinterInfo(&p, Level);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
|
|
|
@ -19,6 +19,41 @@ typedef struct _MARSHALL_DOWN_INFO
|
||||||
}
|
}
|
||||||
MARSHALL_DOWN_INFO, *PMARSHALL_DOWN_INFO;
|
MARSHALL_DOWN_INFO, *PMARSHALL_DOWN_INFO;
|
||||||
|
|
||||||
|
/** From MS-RPRN, 2.2.1.10.1 */
|
||||||
|
typedef struct _PRINTER_INFO_STRESS
|
||||||
|
{
|
||||||
|
PWSTR pPrinterName;
|
||||||
|
PWSTR pServerName;
|
||||||
|
DWORD cJobs;
|
||||||
|
DWORD cTotalJobs;
|
||||||
|
DWORD cTotalBytes;
|
||||||
|
SYSTEMTIME stUpTime;
|
||||||
|
DWORD MaxcRef;
|
||||||
|
DWORD cTotalPagesPrinted;
|
||||||
|
DWORD dwGetVersion;
|
||||||
|
DWORD fFreeBuild;
|
||||||
|
DWORD cSpooling;
|
||||||
|
DWORD cMaxSpooling;
|
||||||
|
DWORD cRef;
|
||||||
|
DWORD cErrorOutOfPaper;
|
||||||
|
DWORD cErrorNotReady;
|
||||||
|
DWORD cJobError;
|
||||||
|
DWORD dwNumberOfProcessors;
|
||||||
|
DWORD dwProcessorType;
|
||||||
|
DWORD dwHighPartTotalBytes;
|
||||||
|
DWORD cChangeID;
|
||||||
|
DWORD dwLastError;
|
||||||
|
DWORD Status;
|
||||||
|
DWORD cEnumerateNetworkPrinters;
|
||||||
|
DWORD cAddNetPrinters;
|
||||||
|
USHORT wProcessorArchitecture;
|
||||||
|
USHORT wProcessorLevel;
|
||||||
|
DWORD cRefIC;
|
||||||
|
DWORD dwReserved2;
|
||||||
|
DWORD dwReserved3;
|
||||||
|
}
|
||||||
|
PRINTER_INFO_STRESS, *PPRINTER_INFO_STRESS;
|
||||||
|
|
||||||
PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
|
PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
|
||||||
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
|
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
|
||||||
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
|
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
|
||||||
|
|
|
@ -31,7 +31,7 @@ static const PRINTPROVIDOR _PrintProviderFunctions = {
|
||||||
NULL, // fpAddPrinter
|
NULL, // fpAddPrinter
|
||||||
NULL, // fpDeletePrinter
|
NULL, // fpDeletePrinter
|
||||||
NULL, // fpSetPrinter
|
NULL, // fpSetPrinter
|
||||||
NULL, // fpGetPrinter
|
LocalGetPrinter, // fpGetPrinter
|
||||||
LocalEnumPrinters, // fpEnumPrinters
|
LocalEnumPrinters, // fpEnumPrinters
|
||||||
NULL, // fpAddPrinterDriver
|
NULL, // fpAddPrinterDriver
|
||||||
NULL, // fpEnumPrinterDrivers
|
NULL, // fpEnumPrinterDrivers
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* PROJECT: ReactOS Local Spooler
|
* PROJECT: ReactOS Local Spooler
|
||||||
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
|
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
|
||||||
* PURPOSE: Precompiled Header for all source files
|
* PURPOSE: Precompiled Header for all source files
|
||||||
* COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck <colin@reactos.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PRECOMP_H
|
#ifndef _PRECOMP_H
|
||||||
|
@ -277,6 +277,7 @@ BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf,
|
||||||
extern SKIPLIST PrinterList;
|
extern SKIPLIST PrinterList;
|
||||||
BOOL InitializePrinterList();
|
BOOL InitializePrinterList();
|
||||||
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
|
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
|
||||||
|
BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded);
|
||||||
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
|
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
|
||||||
BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead);
|
BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead);
|
||||||
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo);
|
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo);
|
||||||
|
|
|
@ -10,7 +10,39 @@
|
||||||
// Global Variables
|
// Global Variables
|
||||||
SKIPLIST PrinterList;
|
SKIPLIST PrinterList;
|
||||||
|
|
||||||
|
// Forward Declarations
|
||||||
|
static void _LocalGetPrinterLevel0(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_STRESS* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel1(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_1W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel3(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_3* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel4(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_4W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel5(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_5W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel6(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_6* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel7(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_7W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel8(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_8W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
static void _LocalGetPrinterLevel9(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_9W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName);
|
||||||
|
|
||||||
// Local Constants
|
// Local Constants
|
||||||
|
typedef void (*PLocalGetPrinterLevelFunc)(PLOCAL_PRINTER, PVOID, PBYTE*, PDWORD, DWORD, PWSTR);
|
||||||
|
|
||||||
|
static const PLocalGetPrinterLevelFunc pfnGetPrinterLevels[] = {
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel0,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel1,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel2,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel3,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel4,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel5,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel6,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel7,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel8,
|
||||||
|
(PLocalGetPrinterLevelFunc)&_LocalGetPrinterLevel9
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD dwPrinterInfo0Offsets[] = {
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_STRESS, pPrinterName),
|
||||||
|
MAXDWORD
|
||||||
|
};
|
||||||
|
|
||||||
static DWORD dwPrinterInfo1Offsets[] = {
|
static DWORD dwPrinterInfo1Offsets[] = {
|
||||||
FIELD_OFFSET(PRINTER_INFO_1W, pName),
|
FIELD_OFFSET(PRINTER_INFO_1W, pName),
|
||||||
FIELD_OFFSET(PRINTER_INFO_1W, pComment),
|
FIELD_OFFSET(PRINTER_INFO_1W, pComment),
|
||||||
|
@ -18,6 +50,31 @@ static DWORD dwPrinterInfo1Offsets[] = {
|
||||||
MAXDWORD
|
MAXDWORD
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static DWORD dwPrinterInfo2Offsets[] = {
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pPrinterName),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pShareName),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pPortName),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pDriverName),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pComment),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pLocation),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pSepFile),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pPrintProcessor),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pDatatype),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_2W, pParameters),
|
||||||
|
MAXDWORD
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD dwPrinterInfo4Offsets[] = {
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_4W, pPrinterName),
|
||||||
|
MAXDWORD
|
||||||
|
};
|
||||||
|
|
||||||
|
static DWORD dwPrinterInfo5Offsets[] = {
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_5W, pPrinterName),
|
||||||
|
FIELD_OFFSET(PRINTER_INFO_5W, pPortName),
|
||||||
|
MAXDWORD
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name _PrinterListCompareRoutine
|
* @name _PrinterListCompareRoutine
|
||||||
*
|
*
|
||||||
|
@ -437,137 +494,378 @@ _DumpLevel1PrintProviderInformation(PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbN
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
static void
|
||||||
_LocalEnumPrintersLevel0(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned, DWORD cchComputerName, PWSTR wszComputerName)
|
_LocalGetPrinterLevel0(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_STRESS* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
{
|
{
|
||||||
return ERROR_INVALID_LEVEL;
|
size_t cbName;
|
||||||
|
PWSTR p;
|
||||||
|
PWSTR pwszStrings[1];
|
||||||
|
SYSTEM_INFO SystemInfo;
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_STRESS) + cbName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the general fields.
|
||||||
|
ZeroMemory(*ppPrinterInfo, sizeof(PRINTER_INFO_STRESS));
|
||||||
|
(*ppPrinterInfo)->cJobs = pPrinter->JobList.NodeCount;
|
||||||
|
(*ppPrinterInfo)->dwGetVersion = GetVersion();
|
||||||
|
(*ppPrinterInfo)->Status = pPrinter->dwStatus;
|
||||||
|
|
||||||
|
#if !defined(DBG)
|
||||||
|
(*ppPrinterInfo)->fFreeBuild = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GetSystemInfo(&SystemInfo);
|
||||||
|
(*ppPrinterInfo)->dwNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
|
||||||
|
(*ppPrinterInfo)->dwProcessorType = SystemInfo.dwProcessorType;
|
||||||
|
(*ppPrinterInfo)->wProcessorArchitecture = SystemInfo.wProcessorArchitecture;
|
||||||
|
(*ppPrinterInfo)->wProcessorLevel = SystemInfo.wProcessorLevel;
|
||||||
|
|
||||||
|
// Copy the Printer Name.
|
||||||
|
pwszStrings[0] = DllAllocSplMem(cbName);
|
||||||
|
p = pwszStrings[0];
|
||||||
|
StringCbCopyExW(p, cbName, wszComputerName, &p, &cbName, 0);
|
||||||
|
StringCbCopyExW(p, cbName, pPrinter->pwszPrinterName, &p, &cbName, 0);
|
||||||
|
|
||||||
|
// Finally copy the structure and advance to the next one in the output buffer.
|
||||||
|
*ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo0Offsets, *ppPrinterInfoEnd);
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
|
||||||
|
// Free the memory for temporary strings.
|
||||||
|
DllFreeSplMem(pwszStrings[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
static void
|
||||||
_LocalEnumPrintersLevel1(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned, DWORD cchComputerName, PWSTR wszComputerName)
|
_LocalGetPrinterLevel1(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_1W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
{
|
{
|
||||||
const WCHAR wszComma[] = L",";
|
const WCHAR wszComma[] = L",";
|
||||||
|
|
||||||
size_t cbName;
|
size_t cbName;
|
||||||
size_t cbComment;
|
size_t cbComment;
|
||||||
size_t cbDescription;
|
size_t cbDescription;
|
||||||
DWORD dwErrorCode;
|
|
||||||
DWORD i;
|
|
||||||
PBYTE pPrinterInfo;
|
|
||||||
PBYTE pPrinterStrings;
|
|
||||||
PSKIPLIST_NODE pNode;
|
|
||||||
PLOCAL_PRINTER pPrinter;
|
|
||||||
PWSTR p;
|
PWSTR p;
|
||||||
PWSTR pwszStrings[3];
|
PWSTR pwszStrings[3];
|
||||||
|
|
||||||
if (Flags & PRINTER_ENUM_NAME && !Name)
|
// Calculate the string lengths.
|
||||||
|
// Attention: pComment equals the "Description" registry value while pDescription is concatenated out of several strings.
|
||||||
|
// On top of this, the computer name is prepended to the printer name if the user supplied the local computer name during the query.
|
||||||
|
cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
|
cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
|
||||||
|
cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 + wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
{
|
{
|
||||||
// The caller wants information about this Print Provider.
|
|
||||||
// spoolss packs this into an array of information about all Print Providers.
|
|
||||||
dwErrorCode = _DumpLevel1PrintProviderInformation(pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count the required buffer size and the number of printers.
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
|
|
||||||
{
|
|
||||||
pPrinter = (PLOCAL_PRINTER)pNode->Element;
|
|
||||||
|
|
||||||
// TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
|
|
||||||
if (Flags & PRINTER_ENUM_SHARED)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Attention: pComment equals the "Description" registry value while pDescription is concatenated out of several strings.
|
|
||||||
// On top of this, the computer name is prepended to the printer name if the user supplied the local computer name during the query.
|
|
||||||
cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
|
||||||
cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
|
|
||||||
cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 + wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
|
|
||||||
|
|
||||||
*pcbNeeded += sizeof(PRINTER_INFO_1W) + cbName + cbComment + cbDescription;
|
*pcbNeeded += sizeof(PRINTER_INFO_1W) + cbName + cbComment + cbDescription;
|
||||||
i++;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the supplied buffer is large enough.
|
// Indicate that this is a Printer.
|
||||||
if (cbBuf < *pcbNeeded)
|
(*ppPrinterInfo)->Flags = PRINTER_ENUM_ICON8;
|
||||||
|
|
||||||
|
// Copy the Printer Name.
|
||||||
|
pwszStrings[0] = DllAllocSplMem(cbName);
|
||||||
|
p = pwszStrings[0];
|
||||||
|
StringCbCopyExW(p, cbName, wszComputerName, &p, &cbName, 0);
|
||||||
|
StringCbCopyExW(p, cbName, pPrinter->pwszPrinterName, &p, &cbName, 0);
|
||||||
|
|
||||||
|
// Copy the Printer comment (equals the "Description" registry value).
|
||||||
|
pwszStrings[1] = pPrinter->pwszDescription;
|
||||||
|
|
||||||
|
// Copy the description, which for PRINTER_INFO_1W has the form "Name,Printer Driver,Location"
|
||||||
|
pwszStrings[2] = DllAllocSplMem(cbDescription);
|
||||||
|
p = pwszStrings[2];
|
||||||
|
StringCbCopyExW(p, cbDescription, wszComputerName, &p, &cbDescription, 0);
|
||||||
|
StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterName, &p, &cbDescription, 0);
|
||||||
|
StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
|
||||||
|
StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterDriver, &p, &cbDescription, 0);
|
||||||
|
StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
|
||||||
|
StringCbCopyExW(p, cbDescription, pPrinter->pwszLocation, &p, &cbDescription, 0);
|
||||||
|
|
||||||
|
// Finally copy the structure and advance to the next one in the output buffer.
|
||||||
|
*ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo1Offsets, *ppPrinterInfoEnd);
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
|
||||||
|
// Free the memory for temporary strings.
|
||||||
|
DllFreeSplMem(pwszStrings[0]);
|
||||||
|
DllFreeSplMem(pwszStrings[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LocalGetPrinterLevel2(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_2W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
|
{
|
||||||
|
WCHAR wszEmpty[] = L"";
|
||||||
|
|
||||||
|
size_t cbDevMode;
|
||||||
|
size_t cbPrinterName;
|
||||||
|
size_t cbShareName;
|
||||||
|
size_t cbPortName;
|
||||||
|
size_t cbDriverName;
|
||||||
|
size_t cbComment;
|
||||||
|
size_t cbLocation;
|
||||||
|
size_t cbSepFile;
|
||||||
|
size_t cbPrintProcessor;
|
||||||
|
size_t cbDatatype;
|
||||||
|
size_t cbParameters;
|
||||||
|
PWSTR p;
|
||||||
|
PWSTR pwszStrings[10];
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
|
||||||
|
cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
{
|
{
|
||||||
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
// Attention: pComment equals the "Description" registry value.
|
||||||
goto Cleanup;
|
cbShareName = sizeof(wszEmpty);
|
||||||
}
|
cbPortName = (wcslen(pPrinter->pPort->pwszName) + 1) * sizeof(WCHAR);
|
||||||
|
cbDriverName = (wcslen(pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
|
||||||
// Initialize the variables for filling the output buffer using PackStrings.
|
|
||||||
pPrinterInfo = pPrinterEnum;
|
|
||||||
pPrinterStrings = &pPrinterEnum[*pcbNeeded];
|
|
||||||
|
|
||||||
// Copy over the Printer information.
|
|
||||||
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
|
|
||||||
{
|
|
||||||
pPrinter = (PLOCAL_PRINTER)pNode->Element;
|
|
||||||
|
|
||||||
// TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
|
|
||||||
if (Flags & PRINTER_ENUM_SHARED)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Indicate that this is a Printer.
|
|
||||||
((PPRINTER_INFO_1W)pPrinterInfo)->Flags = PRINTER_ENUM_ICON8;
|
|
||||||
|
|
||||||
// Calculate the string lengths.
|
|
||||||
cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
|
||||||
cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
|
cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
|
||||||
cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 + wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
|
cbLocation = (wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
|
||||||
|
cbSepFile = sizeof(wszEmpty);
|
||||||
|
cbPrintProcessor = (wcslen(pPrinter->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
|
||||||
|
cbDatatype = (wcslen(pPrinter->pwszDefaultDatatype) + 1) * sizeof(WCHAR);
|
||||||
|
cbParameters = sizeof(wszEmpty);
|
||||||
|
|
||||||
// Copy the Printer Name.
|
*pcbNeeded += sizeof(PRINTER_INFO_2W) + cbDevMode + cbPrinterName + cbShareName + cbPortName + cbDriverName + cbComment + cbLocation + cbSepFile + cbPrintProcessor + cbDatatype + cbParameters;
|
||||||
pwszStrings[0] = DllAllocSplMem(cbName);
|
return;
|
||||||
p = pwszStrings[0];
|
|
||||||
StringCbCopyExW(p, cbName, wszComputerName, &p, &cbName, 0);
|
|
||||||
StringCbCopyExW(p, cbName, pPrinter->pwszPrinterName, &p, &cbName, 0);
|
|
||||||
|
|
||||||
// Copy the Printer comment (equals the "Description" registry value).
|
|
||||||
pwszStrings[1] = pPrinter->pwszDescription;
|
|
||||||
|
|
||||||
// Copy the description, which for PRINTER_INFO_1W has the form "Name,Printer Driver,Location"
|
|
||||||
pwszStrings[2] = DllAllocSplMem(cbDescription);
|
|
||||||
p = pwszStrings[2];
|
|
||||||
StringCbCopyExW(p, cbDescription, wszComputerName, &p, &cbDescription, 0);
|
|
||||||
StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterName, &p, &cbDescription, 0);
|
|
||||||
StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
|
|
||||||
StringCbCopyExW(p, cbDescription, pPrinter->pwszPrinterDriver, &p, &cbDescription, 0);
|
|
||||||
StringCbCopyExW(p, cbDescription, wszComma, &p, &cbDescription, 0);
|
|
||||||
StringCbCopyExW(p, cbDescription, pPrinter->pwszLocation, &p, &cbDescription, 0);
|
|
||||||
|
|
||||||
// Finally copy the structure and advance to the next one in the output buffer.
|
|
||||||
pPrinterStrings = PackStrings(pwszStrings, pPrinterInfo, dwPrinterInfo1Offsets, pPrinterStrings);
|
|
||||||
pPrinterInfo += sizeof(PRINTER_INFO_1W);
|
|
||||||
|
|
||||||
// Free the memory for temporary strings.
|
|
||||||
DllFreeSplMem(pwszStrings[0]);
|
|
||||||
DllFreeSplMem(pwszStrings[2]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pcReturned = i;
|
// Set the general fields.
|
||||||
dwErrorCode = ERROR_SUCCESS;
|
ZeroMemory(*ppPrinterInfo, sizeof(PRINTER_INFO_2W));
|
||||||
|
(*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
|
||||||
|
(*ppPrinterInfo)->cJobs = pPrinter->JobList.NodeCount;
|
||||||
|
(*ppPrinterInfo)->Status = pPrinter->dwStatus;
|
||||||
|
|
||||||
Cleanup:
|
// Set the pDevMode field (and copy the DevMode).
|
||||||
return dwErrorCode;
|
*ppPrinterInfoEnd -= cbDevMode;
|
||||||
|
CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
|
||||||
|
(*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
|
||||||
|
|
||||||
|
// Set the pPrinterName field.
|
||||||
|
pwszStrings[0] = DllAllocSplMem(cbPrinterName);
|
||||||
|
p = pwszStrings[0];
|
||||||
|
StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
|
||||||
|
StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
|
||||||
|
|
||||||
|
// Set the pShareName field.
|
||||||
|
pwszStrings[1] = wszEmpty;
|
||||||
|
|
||||||
|
// Set the pPortName field.
|
||||||
|
pwszStrings[2] = pPrinter->pPort->pwszName;
|
||||||
|
|
||||||
|
// Set the pDriverName field.
|
||||||
|
pwszStrings[3] = pPrinter->pwszPrinterDriver;
|
||||||
|
|
||||||
|
// Set the pComment field ((equals the "Description" registry value).
|
||||||
|
pwszStrings[4] = pPrinter->pwszDescription;
|
||||||
|
|
||||||
|
// Set the pLocation field.
|
||||||
|
pwszStrings[5] = pPrinter->pwszLocation;
|
||||||
|
|
||||||
|
// Set the pSepFile field.
|
||||||
|
pwszStrings[6] = wszEmpty;
|
||||||
|
|
||||||
|
// Set the pPrintProcessor field.
|
||||||
|
pwszStrings[7] = pPrinter->pPrintProcessor->pwszName;
|
||||||
|
|
||||||
|
// Set the pDatatype field.
|
||||||
|
pwszStrings[8] = pPrinter->pwszDefaultDatatype;
|
||||||
|
|
||||||
|
// Set the pParameters field.
|
||||||
|
pwszStrings[9] = wszEmpty;
|
||||||
|
|
||||||
|
// Finally copy the structure and advance to the next one in the output buffer.
|
||||||
|
*ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo2Offsets, *ppPrinterInfoEnd);
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
|
||||||
|
// Free the memory for temporary strings.
|
||||||
|
DllFreeSplMem(pwszStrings[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
static void
|
||||||
_LocalEnumPrintersLevel2(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned, DWORD cchComputerName, PWSTR wszComputerName)
|
_LocalGetPrinterLevel3(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_3* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
{
|
{
|
||||||
return ERROR_INVALID_LEVEL;
|
SECURITY_DESCRIPTOR SecurityDescriptor = { 0 };
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_3) + sizeof(SECURITY_DESCRIPTOR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("Return a valid security descriptor for PRINTER_INFO_3\n");
|
||||||
|
|
||||||
|
// Set the pSecurityDescriptor field (and copy the Security Descriptor).
|
||||||
|
*ppPrinterInfoEnd -= sizeof(SECURITY_DESCRIPTOR);
|
||||||
|
CopyMemory(*ppPrinterInfoEnd, &SecurityDescriptor, sizeof(SECURITY_DESCRIPTOR));
|
||||||
|
(*ppPrinterInfo)->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)(*ppPrinterInfoEnd);
|
||||||
|
|
||||||
|
// Advance to the next structure.
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
static void
|
||||||
_LocalEnumPrintersLevel4(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned, DWORD cchComputerName, PWSTR wszComputerName)
|
_LocalGetPrinterLevel4(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_4W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
{
|
{
|
||||||
return ERROR_INVALID_LEVEL;
|
size_t cbPrinterName;
|
||||||
|
PWSTR p;
|
||||||
|
PWSTR pwszStrings[1];
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_4W) + cbPrinterName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the general fields.
|
||||||
|
(*ppPrinterInfo)->pServerName = NULL;
|
||||||
|
(*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
|
||||||
|
|
||||||
|
// Set the pPrinterName field.
|
||||||
|
pwszStrings[0] = DllAllocSplMem(cbPrinterName);
|
||||||
|
p = pwszStrings[0];
|
||||||
|
StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
|
||||||
|
StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
|
||||||
|
|
||||||
|
// Finally copy the structure and advance to the next one in the output buffer.
|
||||||
|
*ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo4Offsets, *ppPrinterInfoEnd);
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
|
||||||
|
// Free the memory for temporary strings.
|
||||||
|
DllFreeSplMem(pwszStrings[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD
|
static void
|
||||||
_LocalEnumPrintersLevel5(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned, DWORD cchComputerName, PWSTR wszComputerName)
|
_LocalGetPrinterLevel5(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_5W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
{
|
{
|
||||||
return ERROR_INVALID_LEVEL;
|
size_t cbPrinterName;
|
||||||
|
size_t cbPortName;
|
||||||
|
PWSTR p;
|
||||||
|
PWSTR pwszStrings[1];
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbPrinterName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
cbPortName = (wcslen(pPrinter->pPort->pwszName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_5W) + cbPrinterName + cbPortName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the general fields.
|
||||||
|
(*ppPrinterInfo)->Attributes = pPrinter->dwAttributes;
|
||||||
|
(*ppPrinterInfo)->DeviceNotSelectedTimeout = 0;
|
||||||
|
(*ppPrinterInfo)->TransmissionRetryTimeout = 0;
|
||||||
|
|
||||||
|
// Set the pPrinterName field.
|
||||||
|
pwszStrings[0] = DllAllocSplMem(cbPrinterName);
|
||||||
|
p = pwszStrings[0];
|
||||||
|
StringCbCopyExW(p, cbPrinterName, wszComputerName, &p, &cbPrinterName, 0);
|
||||||
|
StringCbCopyExW(p, cbPrinterName, pPrinter->pwszPrinterName, &p, &cbPrinterName, 0);
|
||||||
|
|
||||||
|
// Set the pPortName field.
|
||||||
|
pwszStrings[1] = pPrinter->pPort->pwszName;
|
||||||
|
|
||||||
|
// Finally copy the structure and advance to the next one in the output buffer.
|
||||||
|
*ppPrinterInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPrinterInfo), dwPrinterInfo5Offsets, *ppPrinterInfoEnd);
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
|
||||||
|
// Free the memory for temporary strings.
|
||||||
|
DllFreeSplMem(pwszStrings[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LocalGetPrinterLevel6(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_6* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
|
{
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the general fields.
|
||||||
|
(*ppPrinterInfo)->dwStatus = pPrinter->dwStatus;
|
||||||
|
|
||||||
|
// Advance to the next structure.
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LocalGetPrinterLevel7(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_7W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
|
{
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_7W);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("No Directory Support, returning DSPRINT_UNPUBLISH for PRINTER_INFO_7 all the time!\n");
|
||||||
|
|
||||||
|
// Set the general fields.
|
||||||
|
(*ppPrinterInfo)->dwAction = DSPRINT_UNPUBLISH;
|
||||||
|
(*ppPrinterInfo)->pszObjectGUID = NULL;
|
||||||
|
|
||||||
|
// Advance to the next structure.
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LocalGetPrinterLevel8(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_8W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
|
{
|
||||||
|
DWORD cbDevMode;
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_8W) + cbDevMode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the pDevMode field (and copy the DevMode).
|
||||||
|
*ppPrinterInfoEnd -= cbDevMode;
|
||||||
|
CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
|
||||||
|
(*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
|
||||||
|
|
||||||
|
// Advance to the next structure.
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_LocalGetPrinterLevel9(PLOCAL_PRINTER pPrinter, PPRINTER_INFO_9W* ppPrinterInfo, PBYTE* ppPrinterInfoEnd, PDWORD pcbNeeded, DWORD cchComputerName, PWSTR wszComputerName)
|
||||||
|
{
|
||||||
|
DWORD cbDevMode;
|
||||||
|
|
||||||
|
// Calculate the string lengths.
|
||||||
|
cbDevMode = pPrinter->pDefaultDevMode->dmSize + pPrinter->pDefaultDevMode->dmDriverExtra;
|
||||||
|
|
||||||
|
if (!ppPrinterInfo)
|
||||||
|
{
|
||||||
|
*pcbNeeded += sizeof(PRINTER_INFO_9W) + cbDevMode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("Per-user settings are not yet implemented, returning the global DevMode for PRINTER_INFO_9!\n");
|
||||||
|
|
||||||
|
// Set the pDevMode field (and copy the DevMode).
|
||||||
|
*ppPrinterInfoEnd -= cbDevMode;
|
||||||
|
CopyMemory(*ppPrinterInfoEnd, pPrinter->pDefaultDevMode, cbDevMode);
|
||||||
|
(*ppPrinterInfo)->pDevMode = (PDEVMODEW)(*ppPrinterInfoEnd);
|
||||||
|
|
||||||
|
// Advance to the next structure.
|
||||||
|
(*ppPrinterInfo)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
|
@ -575,7 +873,11 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
|
||||||
{
|
{
|
||||||
DWORD cchComputerName = 0;
|
DWORD cchComputerName = 0;
|
||||||
DWORD dwErrorCode;
|
DWORD dwErrorCode;
|
||||||
|
DWORD i;
|
||||||
|
PBYTE pPrinterInfoEnd;
|
||||||
|
PSKIPLIST_NODE pNode;
|
||||||
WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
|
WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
|
||||||
|
PLOCAL_PRINTER pPrinter;
|
||||||
|
|
||||||
ASSERT(pcbNeeded);
|
ASSERT(pcbNeeded);
|
||||||
ASSERT(pcReturned);
|
ASSERT(pcReturned);
|
||||||
|
@ -601,38 +903,112 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Level == 3 || Level > 5)
|
||||||
|
{
|
||||||
|
// The caller supplied an invalid level for EnumPrinters.
|
||||||
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Level == 1 && Flags & PRINTER_ENUM_NAME && !Name)
|
||||||
|
{
|
||||||
|
// The caller wants information about this Print Provider.
|
||||||
|
// spoolss packs this into an array of information about all Print Providers.
|
||||||
|
dwErrorCode = _DumpLevel1PrintProviderInformation(pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Check the supplied Name parameter (if any).
|
// Check the supplied Name parameter (if any).
|
||||||
// This may return a Computer Name string we later prepend to the output.
|
// This may return a Computer Name string we later prepend to the output.
|
||||||
dwErrorCode = _LocalEnumPrintersCheckName(Flags, Name, wszComputerName, &cchComputerName);
|
dwErrorCode = _LocalEnumPrintersCheckName(Flags, Name, wszComputerName, &cchComputerName);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
if (Level == 0)
|
// Count the required buffer size and the number of printers.
|
||||||
|
i = 0;
|
||||||
|
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
|
||||||
{
|
{
|
||||||
dwErrorCode = _LocalEnumPrintersLevel0(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned, cchComputerName, wszComputerName);
|
pPrinter = (PLOCAL_PRINTER)pNode->Element;
|
||||||
|
|
||||||
|
// TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
|
||||||
|
if (Flags & PRINTER_ENUM_SHARED)
|
||||||
|
{
|
||||||
|
FIXME("Printer Sharing is not supported yet, returning no printers!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfnGetPrinterLevels[Level](pPrinter, NULL, NULL, pcbNeeded, cchComputerName, wszComputerName);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
else if (Level == 1)
|
|
||||||
|
// Check if the supplied buffer is large enough.
|
||||||
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned, cchComputerName, wszComputerName);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
else if (Level == 2)
|
|
||||||
|
// Copy over the Printer information.
|
||||||
|
pPrinterInfoEnd = &pPrinterEnum[*pcbNeeded];
|
||||||
|
|
||||||
|
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
|
||||||
{
|
{
|
||||||
dwErrorCode = _LocalEnumPrintersLevel2(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned, cchComputerName, wszComputerName);
|
pPrinter = (PLOCAL_PRINTER)pNode->Element;
|
||||||
|
|
||||||
|
// TODO: If PRINTER_ENUM_SHARED is given, add this Printer if it's shared instead of just ignoring it.
|
||||||
|
if (Flags & PRINTER_ENUM_SHARED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pfnGetPrinterLevels[Level](pPrinter, &pPrinterEnum, &pPrinterInfoEnd, NULL, cchComputerName, wszComputerName);
|
||||||
}
|
}
|
||||||
else if (Level == 4)
|
|
||||||
|
*pcReturned = i;
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI
|
||||||
|
LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
|
||||||
|
{
|
||||||
|
DWORD dwErrorCode;
|
||||||
|
PBYTE pPrinterEnd;
|
||||||
|
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
|
||||||
|
// Check if this is a printer handle.
|
||||||
|
if (pHandle->HandleType != HandleType_Printer)
|
||||||
{
|
{
|
||||||
dwErrorCode = _LocalEnumPrintersLevel4(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned, cchComputerName, wszComputerName);
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
else if (Level == 5)
|
|
||||||
|
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
|
||||||
|
|
||||||
|
if (Level > 9)
|
||||||
{
|
{
|
||||||
dwErrorCode = _LocalEnumPrintersLevel5(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned, cchComputerName, wszComputerName);
|
// The caller supplied an invalid level for GetPrinter.
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The caller supplied an invalid level.
|
|
||||||
dwErrorCode = ERROR_INVALID_LEVEL;
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the required buffer size.
|
||||||
|
pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded, 0, NULL);
|
||||||
|
|
||||||
|
// Check if the supplied buffer is large enough.
|
||||||
|
if (cbBuf < *pcbNeeded)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over the Printer information.
|
||||||
|
pPrinterEnd = &pPrinter[*pcbNeeded];
|
||||||
|
pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, &pPrinter, &pPrinterEnd, NULL, 0, NULL);
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
SetLastError(dwErrorCode);
|
SetLastError(dwErrorCode);
|
||||||
return (dwErrorCode == ERROR_SUCCESS);
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
|
|
Loading…
Reference in a new issue