Author: cfinck
Date: Sun Apr 16 14:12:01 2017
New Revision: 74324
URL:
http://svn.reactos.org/svn/reactos?rev=74324&view=rev
Log:
[LOCALSPL]
- Refactor LocalEnumPrinters to make it ready for supporting additional levels.
- Correctly handle all passed flags for Level 1 queries to the Local Print Provider.
- Introduce strsafe functions to LocalEnumPrinters in a way that actually makes the code
smaller. To be done in other parts too.
- Use PackStrings in LocalEnumPrinters to simplify the code.
- Return the correct 3 strings in the Description field of Level 1 queries. That also
introduces the "Location" field.
- Remove debug spam in _OpenEnvironment.
[SPOOLSV]
- Make use of the newly implemented AlignRpcPtr/UndoAlignRpcPtr. Fixes a test.
[WINSPOOL]
- Dismiss invalid levels already in EnumPrintersW and zero the input buffer here (but not
in localspl). Verified by a test.
EnumPrintersW for Level 1 should be fully supported now.
Modified:
trunk/reactos/boot/bootdata/hivesys.inf
trunk/reactos/win32ss/printing/base/spoolss/printers.c
trunk/reactos/win32ss/printing/base/spoolsv/precomp.h
trunk/reactos/win32ss/printing/base/spoolsv/printers.c
trunk/reactos/win32ss/printing/base/winspool/printers.c
trunk/reactos/win32ss/printing/include/spoolss.h
trunk/reactos/win32ss/printing/providers/localspl/main.c
trunk/reactos/win32ss/printing/providers/localspl/precomp.h
trunk/reactos/win32ss/printing/providers/localspl/printers.c
trunk/reactos/win32ss/printing/providers/localspl/printprocessors.c
trunk/rostests/apitests/localspl/dll/fpEnumPrinters.c
trunk/rostests/apitests/winspool/EnumPrinters.c
Modified: trunk/reactos/boot/bootdata/hivesys.inf
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/hivesys.inf?…
==============================================================================
--- trunk/reactos/boot/bootdata/hivesys.inf [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/hivesys.inf [iso-8859-1] Sun Apr 16 14:12:01 2017
@@ -1277,6 +1277,7 @@
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
+HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On
LPT1","Location",,"At Home"
HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On
LPT1","Port",,"LPT1:"
HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On
LPT1","Print Processor",,"winprint"
HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On
LPT1","Printer Driver",,"Dummy Printer Driver"
Modified: trunk/reactos/win32ss/printing/base/spoolss/printers.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/base/spoo…
==============================================================================
--- trunk/reactos/win32ss/printing/base/spoolss/printers.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/base/spoolss/printers.c [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Spooler Router
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software
Foundation
* PURPOSE: Functions related to Printers and printing
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include "precomp.h"
@@ -68,27 +68,27 @@
BOOL bReturnValue;
DWORD cbCallBuffer;
DWORD cbNeeded;
+ DWORD dwErrorCode = 0xFFFFFFFF;
DWORD dwReturned;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
- // Sanity checks.
- if ((cbBuf && !pPrinterEnum) || !pcbNeeded || !pcReturned)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
+ if (cbBuf && !pPrinterEnum)
+ {
+ dwErrorCode = ERROR_INVALID_USER_BUFFER;
+ goto Cleanup;
+ }
+
// At the beginning, we have the full buffer available.
cbCallBuffer = cbBuf;
pCallBuffer = pPrinterEnum;
- // Loop through all Print Provider.
+ // Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry =
pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
@@ -109,9 +109,15 @@
// Advance the buffer if the caller provided it.
if (pCallBuffer)
pCallBuffer += cbNeeded;
- }
-
- return bReturnValue;
+
+ // dwErrorCode shall not be overwritten if a previous EnumPrinters call already
succeeded.
+ if (dwErrorCode != ERROR_SUCCESS)
+ dwErrorCode = GetLastError();
+ }
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
@@ -148,6 +154,7 @@
OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
{
BOOL bReturnValue;
+ DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
HANDLE hPrinter;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINTER_HANDLE pHandle;
@@ -156,8 +163,8 @@
// Sanity checks.
if (!pPrinterName || !phPrinter)
{
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
+ dwErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
}
// Loop through all Print Providers to find one able to open this Printer.
@@ -173,27 +180,33 @@
pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
if (!pHandle)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ERR("DllAllocSplMem failed with error %lu!\n",
GetLastError());
- return FALSE;
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
}
pHandle->pPrintProvider = pPrintProvider;
pHandle->hPrinter = hPrinter;
*phPrinter = (HANDLE)pHandle;
- SetLastError(ERROR_SUCCESS);
- return TRUE;
+ dwErrorCode = ERROR_SUCCESS;
+ goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer
\"%S\"!\n", pPrinterName);
- return FALSE;
+ dwErrorCode = GetLastError();
+ goto Cleanup;
}
}
- // We found no Print Provider able to open this Printer.
- return FALSE;
+ // ERROR_INVALID_NAME by the Print Provider is translated to
ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
+ if (dwErrorCode == ERROR_INVALID_NAME)
+ dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
Modified: trunk/reactos/win32ss/printing/base/spoolsv/precomp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/base/spoo…
==============================================================================
--- trunk/reactos/win32ss/printing/base/spoolsv/precomp.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/base/spoolsv/precomp.h [iso-8859-1] Sun Apr 16 14:12:01
2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software
Foundation
* PURPOSE: Precompiled Header for all source files
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#ifndef _PRECOMP_H
@@ -18,14 +18,12 @@
#include <winsplp.h>
#include <winspool_s.h>
+#include <spoolss.h>
+
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(spoolsv);
// rpcserver.c
DWORD WINAPI LrpcThreadProc(LPVOID lpParameter);
-// Undocumented spoolss
-BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle);
-DWORD WINAPI SpoolerInit();
-
#endif
Modified: trunk/reactos/win32ss/printing/base/spoolsv/printers.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/base/spoo…
==============================================================================
--- trunk/reactos/win32ss/printing/base/spoolsv/printers.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/base/spoolsv/printers.c [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software
Foundation
* PURPOSE: Functions related to Printers and printing
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include "precomp.h"
@@ -137,21 +137,24 @@
_RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterEnum,
DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
DWORD dwErrorCode;
- DWORD i;
- PBYTE p = pPrinterEnum;
-
- dwErrorCode = RpcImpersonateClient(NULL);
- if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
- return dwErrorCode;
- }
-
- EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
+ PBYTE pPrinterEnumAligned;
+
+ dwErrorCode = RpcImpersonateClient(NULL);
+ if (dwErrorCode != ERROR_SUCCESS)
+ {
+ ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode);
+ return dwErrorCode;
+ }
+
+ pPrinterEnumAligned = AlignRpcPtr(pPrinterEnum, &cbBuf);
+ EnumPrintersW(Flags, Name, Level, pPrinterEnumAligned, cbBuf, pcbNeeded,
pcReturned);
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_SUCCESS)
{
+ DWORD i;
+ PBYTE p = pPrinterEnumAligned;
+
// Replace absolute pointer addresses in the output by relative offsets.
for (i = 0; i < *pcReturned; i++)
{
@@ -165,6 +168,8 @@
}
RpcRevertToSelf();
+ UndoAlignRpcPtr(pPrinterEnum, pPrinterEnumAligned, cbBuf, pcbNeeded);
+
return dwErrorCode;
}
Modified: trunk/reactos/win32ss/printing/base/winspool/printers.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/base/wins…
==============================================================================
--- trunk/reactos/win32ss/printing/base/winspool/printers.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/base/winspool/printers.c [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Spooler API
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software
Foundation
* PURPOSE: Functions related to Printers and printing
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include "precomp.h"
@@ -309,6 +309,16 @@
DWORD i;
PBYTE p = pPrinterEnum;
+ // Dismiss invalid levels already at this point.
+ if (Level == 3 || Level > 5)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ }
+
+ if (cbBuf && pPrinterEnum)
+ ZeroMemory(pPrinterEnum, cbBuf);
+
// Do the RPC call
RpcTryExcept
{
@@ -335,6 +345,7 @@
}
}
+Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
Modified: trunk/reactos/win32ss/printing/include/spoolss.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/include/s…
==============================================================================
--- trunk/reactos/win32ss/printing/include/spoolss.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/include/spoolss.h [iso-8859-1] Sun Apr 16 14:12:01
2017
@@ -24,11 +24,13 @@
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
BOOL WINAPI DllFreeSplMem(PVOID pMem);
BOOL WINAPI DllFreeSplStr(PWSTR pwszString);
+BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle);
BOOL WINAPI MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters,
DWORD cbStructureSize, BOOL bSomeBoolean);
PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE
pEnd);
PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew);
BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);
BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable);
+DWORD WINAPI SpoolerInit();
PDWORD WINAPI UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD
cbBuffer, PDWORD pcbNeeded);
#endif
Modified: trunk/reactos/win32ss/printing/providers/localspl/main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/providers…
==============================================================================
--- trunk/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Local Spooler
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software
Foundation
* PURPOSE: Main functions
- * COPYRIGHT: Copyright 2015-2016 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include "precomp.h"
@@ -18,8 +18,8 @@
const WCHAR* wszPrintProviderInfo[3] = {
L"Windows NT Local Print Providor", // Name
- L"Windows NT Local Printers", // Description
- L"Locally connected Printers" // Comment
+ L"Locally connected Printers", // Comment
+ L"Windows NT Local Printers" // Description
};
// Local Constants
Modified: trunk/reactos/win32ss/printing/providers/localspl/precomp.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/providers…
==============================================================================
--- trunk/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -15,6 +15,7 @@
#include <lmcons.h>
#include <rpc.h>
+#include <strsafe.h>
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
@@ -114,6 +115,7 @@
DWORD dwAttributes;
DWORD dwStatus;
+ PWSTR pwszLocation;
PWSTR pwszPrinterDriver;
PWSTR pwszDescription;
PWSTR pwszDefaultDatatype;
Modified: trunk/reactos/win32ss/printing/providers/localspl/printers.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/providers…
==============================================================================
--- trunk/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1] Sun Apr 16
14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Local Spooler
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software
Foundation
* PURPOSE: Functions related to Printers and printing
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include "precomp.h"
@@ -10,6 +10,13 @@
// Global Variables
SKIPLIST PrinterList;
+// Local Constants
+static DWORD dwPrinterInfo1Offsets[] = {
+ FIELD_OFFSET(PRINTER_INFO_1W, pName),
+ FIELD_OFFSET(PRINTER_INFO_1W, pComment),
+ FIELD_OFFSET(PRINTER_INFO_1W, pDescription),
+ MAXDWORD
+};
/**
* @name _PrinterListCompareRoutine
@@ -170,6 +177,11 @@
pPrinter->pPort = pPort;
InitializePrinterJobList(pPrinter);
+ // Get the location.
+ pPrinter->pwszLocation = AllocAndRegQueryWSZ(hSubKey, L"Location");
+ if (!pPrinter->pwszLocation)
+ continue;
+
// Get the printer driver.
pPrinter->pwszPrinterDriver = AllocAndRegQueryWSZ(hSubKey, L"Printer
Driver");
if (!pPrinter->pwszPrinterDriver)
@@ -284,9 +296,93 @@
return (dwErrorCode == ERROR_SUCCESS);
}
-
-DWORD
-_LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cbBuf,
LPDWORD pcbNeeded, LPDWORD pcReturned)
+/**
+ * @name _IsLocalComputerName
+ *
+ * Checks if the given Computer Name matches the local Computer Name.
+ *
+ * @param Name
+ * Computer Name prepended with two backslashes to check.
+ *
+ * @param pwszComputerName
+ * Pointer to a string able to hold 2 + MAX_COMPUTERNAME_LENGTH + 1 + 1 characters.
+ * Will contain a string "\\COMPUTERNAME\" on success that can be prepended in
EnumPrinters.
+ *
+ * @param pcchComputerName
+ * On success, this pointer receives the length in characters of pwszComputerName.
+ *
+ * @return
+ * ERROR_SUCCESS on success or an error code on failure.
+ */
+static DWORD
+_IsLocalComputerName(PCWSTR Name, PWSTR pwszComputerName, PDWORD pcchComputerName)
+{
+ DWORD dwErrorCode;
+
+ // Prepend slashes to the computer name.
+ pwszComputerName[0] = L'\\';
+ pwszComputerName[1] = L'\\';
+
+ // Get the local computer name for comparison.
+ *pcchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
+ if (!GetComputerNameW(&pwszComputerName[2], pcchComputerName))
+ {
+ dwErrorCode = GetLastError();
+ ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
+ goto Cleanup;
+ }
+
+ // Add the leading slashes to the total length.
+ *pcchComputerName += 2;
+
+ // Now compare this with the local computer name and reject it with
ERROR_INVALID_NAME if it doesn't match.
+ if (wcsicmp(&Name[2], &pwszComputerName[2]) != 0)
+ {
+ dwErrorCode = ERROR_INVALID_NAME;
+ goto Cleanup;
+ }
+
+ // Add a trailing backslash to pwszComputerName, which will later be prepended in
front of the printer names.
+ pwszComputerName[(*pcchComputerName)++] = L'\\';
+ pwszComputerName[*pcchComputerName] = 0;
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ return dwErrorCode;
+}
+
+static DWORD
+_DumpLevel1PrintProviderInformation(PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded,
PDWORD pcReturned)
+{
+ int i;
+
+ // Count the needed bytes for Print Provider information.
+ *pcbNeeded = sizeof(PRINTER_INFO_1W);
+
+ for (i = 0; i < 3; i++)
+ *pcbNeeded += (wcslen(wszPrintProviderInfo[i]) + 1) * sizeof(WCHAR);
+
+ // Check if the supplied buffer is large enough.
+ if (cbBuf < *pcbNeeded)
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ // Copy over the Print Provider information.
+ ((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
+ PackStrings(wszPrintProviderInfo, pPrinterEnum, dwPrinterInfo1Offsets,
&pPrinterEnum[*pcbNeeded]);
+ *pcReturned = 1;
+
+ return ERROR_SUCCESS;
+}
+
+static DWORD
+_LocalEnumPrintersLevel0(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf,
PDWORD pcbNeeded, PDWORD pcReturned)
+{
+ return ERROR_INVALID_LEVEL;
+}
+
+static DWORD
+_LocalEnumPrintersLevel1(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf,
PDWORD pcbNeeded, PDWORD pcReturned)
{
const WCHAR wszComma[] = L",";
@@ -297,57 +393,28 @@
DWORD dwErrorCode;
DWORD i;
PBYTE pPrinterInfo;
- PBYTE pPrinterString;
+ PBYTE pPrinterStrings;
PSKIPLIST_NODE pNode;
PLOCAL_PRINTER pPrinter;
- PRINTER_INFO_1W PrinterInfo1;
- WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1];
-
- DWORD dwOffsets[] = {
- FIELD_OFFSET(PRINTER_INFO_1W, pName),
- FIELD_OFFSET(PRINTER_INFO_1W, pDescription),
- FIELD_OFFSET(PRINTER_INFO_1W, pComment),
- MAXDWORD
- };
+ PWSTR p;
+ PWSTR pwszStrings[3];
+ WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
if (Flags & PRINTER_ENUM_NAME)
{
if (Name)
{
// The user supplied a Computer Name (with leading double backslashes) or
Print Provider Name.
- // Only process what's directed at us and dismiss every other request
with ERROR_INVALID_NAME.
+ // Only process what's directed at us.
if (Name[0] == L'\\' && Name[1] == L'\\')
{
- // Prepend slashes to the computer name.
- wszComputerName[0] = L'\\';
- wszComputerName[1] = L'\\';
-
- // Get the local computer name for comparison.
- cchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
- if (!GetComputerNameW(&wszComputerName[2], &cchComputerName))
- {
- dwErrorCode = GetLastError();
- ERR("GetComputerNameW failed with error %lu!\n",
dwErrorCode);
+ dwErrorCode = _IsLocalComputerName(Name, wszComputerName,
&cchComputerName);
+ if (dwErrorCode != ERROR_SUCCESS)
goto Cleanup;
- }
-
- // Add the leading slashes to the total length.
- cchComputerName += 2;
-
- // Now compare this with the local computer name and reject if it
doesn't match.
- if (wcsicmp(&Name[2], &wszComputerName[2]) != 0)
- {
- dwErrorCode = ERROR_INVALID_NAME;
- goto Cleanup;
- }
-
- // Add a trailing backslash to wszComputerName, which will later be
prepended in front of the printer names.
- wszComputerName[cchComputerName++] = L'\\';
- wszComputerName[cchComputerName] = 0;
}
else if (wcsicmp(Name, wszPrintProviderInfo[0]) != 0)
{
- // The user supplied a name that cannot be processed by the local print
provider.
+ // The user supplied a name that cannot be processed by the Local Print
Provider.
dwErrorCode = ERROR_INVALID_NAME;
goto Cleanup;
}
@@ -356,23 +423,7 @@
{
// The caller wants information about this Print Provider.
// spoolss packs this into an array of information about all Print
Providers.
- *pcbNeeded = sizeof(PRINTER_INFO_1W);
-
- for (i = 0; i < 3; i++)
- *pcbNeeded += (wcslen(wszPrintProviderInfo[i]) + 1) * sizeof(WCHAR);
-
- // Check if the supplied buffer is large enough.
- if (cbBuf < *pcbNeeded)
- {
- dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
- goto Cleanup;
- }
-
- // Copy over the print processor information.
- ((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
- PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets,
&pPrinterEnum[*pcbNeeded]);
- *pcReturned = 1;
- dwErrorCode = ERROR_SUCCESS;
+ dwErrorCode = _DumpLevel1PrintProviderInformation(pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
goto Cleanup;
}
}
@@ -384,14 +435,17 @@
{
pPrinter = (PLOCAL_PRINTER)pNode->Element;
- // This looks wrong, but is totally right. PRINTER_INFO_1W has three members
pName, pComment and pDescription.
- // But pComment equals the "Description" registry value while
pDescription is concatenated out of pName and pComment.
+ // 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 = (wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
+ cbName = (cchComputerName + wcslen(pPrinter->pwszPrinterName) + 1) *
sizeof(WCHAR);
cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR);
- cbDescription = cchComputerName * sizeof(WCHAR) + cbName + cbComment +
sizeof(WCHAR);
-
- *pcbNeeded += sizeof(PRINTER_INFO_1W) + cchComputerName * sizeof(WCHAR) + cbName
+ cbComment + cbDescription;
+ cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 +
wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
+
+ *pcbNeeded += sizeof(PRINTER_INFO_1W) + cbName + cbComment + cbDescription;
i++;
}
@@ -402,49 +456,53 @@
goto Cleanup;
}
- // Put the strings right after the last PRINTER_INFO_1W structure.
- // Due to all the required string processing, we can't just use PackStrings here
:(
+ // Initialize the variables for filling the output buffer using PackStrings.
pPrinterInfo = pPrinterEnum;
- pPrinterString = pPrinterEnum + i * sizeof(PRINTER_INFO_1W);
-
- // Copy over the printer information.
+ pPrinterStrings = &pPrinterEnum[*pcbNeeded];
+
+ // Copy over the Printer information.
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
{
pPrinter = (PLOCAL_PRINTER)pNode->Element;
- // FIXME: As for now, the Flags member returns no information.
- PrinterInfo1.Flags = 0;
-
- // Copy the printer name.
- PrinterInfo1.pName = (PWSTR)pPrinterString;
- CopyMemory(pPrinterString, wszComputerName, cchComputerName * sizeof(WCHAR));
- pPrinterString += cchComputerName * sizeof(WCHAR);
- cbName = (wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
- CopyMemory(pPrinterString, pPrinter->pwszPrinterName, cbName);
- pPrinterString += cbName;
-
- // Copy the printer comment (equals the "Description" registry value).
- PrinterInfo1.pComment = (PWSTR)pPrinterString;
+ // 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);
- CopyMemory(pPrinterString, pPrinter->pwszDescription, cbComment);
- pPrinterString += cbComment;
-
- // Copy the description, which for PRINTER_INFO_1W has the form
"Name,Comment,"
- PrinterInfo1.pDescription = (PWSTR)pPrinterString;
- CopyMemory(pPrinterString, wszComputerName, cchComputerName * sizeof(WCHAR));
- pPrinterString += cchComputerName * sizeof(WCHAR);
- CopyMemory(pPrinterString, pPrinter->pwszPrinterName, cbName -
sizeof(WCHAR));
- pPrinterString += cbName - sizeof(WCHAR);
- CopyMemory(pPrinterString, wszComma, sizeof(WCHAR));
- pPrinterString += sizeof(WCHAR);
- CopyMemory(pPrinterString, pPrinter->pwszDescription, cbComment -
sizeof(WCHAR));
- pPrinterString += cbComment - sizeof(WCHAR);
- CopyMemory(pPrinterString, wszComma, sizeof(wszComma));
- pPrinterString += sizeof(wszComma);
-
+ cbDescription = cbName + (wcslen(pPrinter->pwszPrinterDriver) + 1 +
wcslen(pPrinter->pwszLocation) + 1) * sizeof(WCHAR);
+
+ // 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.
- CopyMemory(pPrinterInfo, &PrinterInfo1, sizeof(PRINTER_INFO_1W));
+ 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;
@@ -452,6 +510,24 @@
Cleanup:
return dwErrorCode;
+}
+
+static DWORD
+_LocalEnumPrintersLevel2(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf,
PDWORD pcbNeeded, PDWORD pcReturned)
+{
+ return ERROR_INVALID_LEVEL;
+}
+
+static DWORD
+_LocalEnumPrintersLevel4(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf,
PDWORD pcbNeeded, PDWORD pcReturned)
+{
+ return ERROR_INVALID_LEVEL;
+}
+
+static DWORD
+_LocalEnumPrintersLevel5(DWORD Flags, PCWSTR Name, PBYTE pPrinterEnum, DWORD cbBuf,
PDWORD pcbNeeded, PDWORD pcReturned)
+{
+ return ERROR_INVALID_LEVEL;
}
BOOL WINAPI
@@ -465,24 +541,47 @@
*pcbNeeded = 0;
*pcReturned = 0;
- // Think positive :)
- // Treat it as success if the caller queried no information and we don't need to
return any.
- dwErrorCode = ERROR_SUCCESS;
-
- if (Flags & PRINTER_ENUM_LOCAL)
- {
- // The function behaves quite differently for each level.
- if (Level == 1)
- {
- dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
- }
- else
- {
- // TODO: Handle other levels.
- // The caller supplied an invalid level.
- dwErrorCode = ERROR_INVALID_LEVEL;
- goto Cleanup;
- }
+ if (Flags & PRINTER_ENUM_CONNECTIONS || Flags & PRINTER_ENUM_REMOTE || Flags
& PRINTER_ENUM_NETWORK)
+ {
+ // If the flags for the Network Print Provider are given, bail out with
ERROR_INVALID_NAME.
+ // This is the internal way for a Print Provider to signal that it doesn't
handle this request.
+ dwErrorCode = ERROR_INVALID_NAME;
+ goto Cleanup;
+ }
+
+ if (!(Flags & PRINTER_ENUM_LOCAL || Flags & PRINTER_ENUM_NAME))
+ {
+ // The Local Print Provider is the right destination for the request, but without
any of these flags,
+ // there is no information that can be returned.
+ // So just signal a successful request.
+ dwErrorCode = ERROR_SUCCESS;
+ goto Cleanup;
+ }
+
+ if (Level == 0)
+ {
+ dwErrorCode = _LocalEnumPrintersLevel0(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
+ }
+ else if (Level == 1)
+ {
+ dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
+ }
+ else if (Level == 2)
+ {
+ dwErrorCode = _LocalEnumPrintersLevel2(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
+ }
+ else if (Level == 4)
+ {
+ dwErrorCode = _LocalEnumPrintersLevel4(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
+ }
+ else if (Level == 5)
+ {
+ dwErrorCode = _LocalEnumPrintersLevel5(Flags, Name, pPrinterEnum, cbBuf,
pcbNeeded, pcReturned);
+ }
+ else
+ {
+ // The caller supplied an invalid level.
+ dwErrorCode = ERROR_INVALID_LEVEL;
}
Cleanup:
Modified: trunk/reactos/win32ss/printing/providers/localspl/printprocessors.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/printing/providers…
==============================================================================
--- trunk/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1]
(original)
+++ trunk/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1] Sun
Apr 16 14:12:01 2017
@@ -160,10 +160,7 @@
// Open the environment registry key.
dwErrorCode = _OpenEnvironment(wszCurrentEnvironment, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode);
- goto Cleanup;
- }
+ goto Cleanup;
// Open the "Print Processors" subkey.
dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ,
&hSubKey);
@@ -494,10 +491,7 @@
// We use the registry and not the PrintProcessorList here, because the caller may
request information about a different environment.
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
- {
- ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode);
- goto Cleanup;
- }
+ goto Cleanup;
// Open the "Print Processors" subkey.
dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ,
&hSubKey);
Modified: trunk/rostests/apitests/localspl/dll/fpEnumPrinters.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/localspl/dll/fpE…
==============================================================================
--- trunk/rostests/apitests/localspl/dll/fpEnumPrinters.c [iso-8859-1] (original)
+++ trunk/rostests/apitests/localspl/dll/fpEnumPrinters.c [iso-8859-1] Sun Apr 16 14:12:01
2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Local Spooler API Tests Injected DLL
* LICENSE: GNU GPLv2 or any later version as published by the Free Software
Foundation
* PURPOSE: Tests for fpEnumPrinters
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include <apitest.h>
@@ -22,6 +22,8 @@
START_TEST(fpEnumPrinters)
{
+ BYTE TempBuffer[50];
+ BYTE ZeroBuffer[50];
DWORD cbNeeded;
DWORD cbTemp;
DWORD dwReturned;
@@ -33,18 +35,30 @@
if (!GetLocalsplFuncs(&pp))
return;
+ // Verify that fpEnumPrinters returns success and zeros cbNeeded and dwReturned (but
not TempBuffer!) if no flag has been specified.
+ memset(TempBuffer, 0xDE, sizeof(TempBuffer));
+ memset(ZeroBuffer, 0, sizeof(ZeroBuffer));
+ cbNeeded = 0xDEADBEEF;
+ dwReturned = 0xDEADBEEF;
+ SetLastError(0xDEADBEEF);
+ ok(pp.fpEnumPrinters(0, NULL, 1, TempBuffer, sizeof(TempBuffer), &cbNeeded,
&dwReturned), "fpEnumPrinters returns FALSE\n");
+ ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu!\n",
GetLastError());
+ ok(memcmp(TempBuffer, ZeroBuffer, sizeof(TempBuffer)) != 0, "TempBuffer has been
zeroed!\n");
+ ok(cbNeeded == 0, "cbNeeded is %lu!\n", cbNeeded);
+ ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
+
// Verify that localspl only returns information about a single print provider
(namely itself).
cbNeeded = 0xDEADBEEF;
dwReturned = 0xDEADBEEF;
SetLastError(0xDEADBEEF);
- ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME, NULL, 1, NULL, 0,
&cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE\n");
+ ok(!pp.fpEnumPrinters(PRINTER_ENUM_NAME, NULL, 1, NULL, 0, &cbNeeded,
&dwReturned), "fpEnumPrinters returns TRUE\n");
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error
%lu!\n", GetLastError());
ok(cbNeeded > 0, "cbNeeded is 0!\n");
ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
SetLastError(0xDEADBEEF);
pPrinterInfo1 = HeapAlloc(GetProcessHeap(), 0, cbNeeded);
- ok(pp.fpEnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME, NULL, 1,
(PBYTE)pPrinterInfo1, cbNeeded, &cbNeeded, &dwReturned), "fpEnumPrinters
returns FALSE\n");
+ ok(pp.fpEnumPrinters(PRINTER_ENUM_NAME, NULL, 1, (PBYTE)pPrinterInfo1, cbNeeded,
&cbNeeded, &dwReturned), "fpEnumPrinters returns FALSE\n");
ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu!\n",
GetLastError());
ok(cbNeeded > 0, "cbNeeded is 0!\n");
ok(dwReturned == 1, "dwReturned is %lu!\n", dwReturned);
Modified: trunk/rostests/apitests/winspool/EnumPrinters.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/winspool/EnumPri…
==============================================================================
--- trunk/rostests/apitests/winspool/EnumPrinters.c [iso-8859-1] (original)
+++ trunk/rostests/apitests/winspool/EnumPrinters.c [iso-8859-1] Sun Apr 16 14:12:01 2017
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Print Spooler DLL API Tests
* LICENSE: GNU GPLv2 or any later version as published by the Free Software
Foundation
* PURPOSE: Tests for EnumPrintersA/EnumPrintersW
- * COPYRIGHT: Copyright 2015 Colin Finck <colin(a)reactos.org>
+ * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin(a)reactos.org>
*/
#include <apitest.h>
@@ -15,12 +15,25 @@
START_TEST(EnumPrinters)
{
+ BYTE TempBuffer[50];
+ BYTE ZeroBuffer[50] = { 0 };
DWORD cbNeeded;
DWORD cbTemp;
DWORD dwReturned;
PVOID pMem;
DWORD i;
DWORD dwValidLevels[] = { 0, 1, 2, 4, 5 };
+
+ // Verify that EnumPrintersW returns success and zeroes all input variables even
though no flag has been specified.
+ memset(TempBuffer, 0xDE, sizeof(TempBuffer));
+ cbNeeded = 0xDEADBEEF;
+ dwReturned = 0xDEADBEEF;
+ SetLastError(0xDEADBEEF);
+ ok(EnumPrintersW(0, NULL, 1, TempBuffer, sizeof(TempBuffer), &cbNeeded,
&dwReturned), "EnumPrintersW returns FALSE\n");
+ ok(GetLastError() == ERROR_SUCCESS, "EnumPrintersW returns error %lu!\n",
GetLastError());
+ ok(memcmp(TempBuffer, ZeroBuffer, sizeof(TempBuffer)) == 0, "TempBuffer has not
been zeroed!\n");
+ ok(cbNeeded == 0, "cbNeeded is %lu!\n", cbNeeded);
+ ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
// Level 5 is the highest supported under Windows Server 2003. Higher levels need to
fail and leave the variables untouched!
cbNeeded = 0xDEADBEEF;
@@ -69,7 +82,7 @@
ok(cbNeeded > 0, "cbNeeded is 0 for Level %lu!\n",
dwValidLevels[i]);
ok(dwReturned == 0, "dwReturned is %lu for Level %lu!\n", dwReturned,
dwValidLevels[i]);
- // Same error has to occur with a size to small.
+ // Same error has to occur with no buffer, but a size < 4 (AlignRpcPtr comes
into play here).
SetLastError(0xDEADBEEF);
ok(!EnumPrintersW(PRINTER_ENUM_LOCAL, NULL, dwValidLevels[i], NULL, 1,
&cbNeeded, &dwReturned), "EnumPrintersW returns TRUE for Level %lu!\n",
dwValidLevels[i]);
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "EnumPrintersW returns error
%lu for Level %lu!\n", GetLastError(), dwValidLevels[i]);