Author: cfinck Date: Tue Jul 7 17:06:48 2015 New Revision: 68375
URL: http://svn.reactos.org/svn/reactos?rev=68375&view=rev Log: [LOCALSPL] - Initialize all Print Monitors on startup and keep a list of them. - Implement LocalEnumMonitors and LocalEnumPorts. - Check the result of the initialization functions.
[SPOOLSS] - Implement support for multiple Print Providers. Initialize them on startup and keep a list here as well. - Implement all functions that had simple stubs in the C code. This still needs to be done for the remaining functions stubbed in the .spec file. But generally spoken, this always boils down to 3 cases: * Forward the call to the Local Spooler (for general functions like GetPrintProcessorDirectory). * Forward the call to the Print Provider we used for OpenPrinter (for functions like SetJob). * Forward the call to all Print Providers and collect the results (for functions like EnumPrinters).
Added: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/monitors.c (with props) branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/monitors.c (with props) branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/ports.c (with props) Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/CMakeLists.txt branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/jobs.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/main.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/memory.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/ports.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/precomp.h branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printers.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printprocessors.c branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/spoolss.spec branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/CMakeLists.txt [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/CMakeLists.txt [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -6,6 +6,7 @@ jobs.c main.c memory.c + monitors.c ports.c precomp.h printers.c
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/jobs.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/jobs.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/jobs.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -8,31 +8,76 @@ #include "precomp.h"
BOOL WINAPI -AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded) +AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) { - return LocalSplFuncs.fpAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded); + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded); }
BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - return LocalSplFuncs.fpEnumJobs(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); }
BOOL WINAPI -GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded) +GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded) { - return LocalSplFuncs.fpGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); }
BOOL WINAPI ScheduleJob(HANDLE hPrinter, DWORD dwJobID) { - return LocalSplFuncs.fpScheduleJob(hPrinter, dwJobID); + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpScheduleJob(pHandle->hPrinter, dwJobID); }
BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) { - return LocalSplFuncs.fpSetJob(hPrinter, JobId, Level, pJobInfo, Command); + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpSetJob(pHandle->hPrinter, JobId, Level, pJobInfo, Command); }
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/main.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/main.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/main.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -7,9 +7,179 @@
#include "precomp.h"
+// Global Variables HANDLE hProcessHeap; -PRINTPROVIDOR LocalSplFuncs; - +LIST_ENTRY PrintProviderList; + + +static DWORD +_AddPrintProviderToList(PCWSTR pwszFileName) +{ + DWORD dwErrorCode; + HINSTANCE hinstPrintProvider; + PInitializePrintProvidor pfnInitializePrintProvidor; + PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL; + + // Try to load it. + hinstPrintProvider = LoadLibraryW(pwszFileName); + if (!hinstPrintProvider) + { + dwErrorCode = GetLastError(); + ERR("LoadLibraryW failed for "%S" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Get the initialization routine. + pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstPrintProvider, "InitializePrintProvidor"); + if (!pfnInitializePrintProvidor) + { + dwErrorCode = GetLastError(); + ERR("GetProcAddress failed for "%S" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Create a new SPOOLSS_PRINT_PROVIDER structure for it. + pPrintProvider = DllAllocSplMem(sizeof(SPOOLSS_PRINT_PROVIDER)); + if (!pPrintProvider) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Call the Print Provider initialization function. + if (!pfnInitializePrintProvidor(&pPrintProvider->PrintProvider, sizeof(PRINTPROVIDOR), NULL)) + { + dwErrorCode = GetLastError(); + ERR("InitializePrintProvidor failed for "%S" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Add this Print Provider to the list. + InsertTailList(&PrintProviderList, &pPrintProvider->Entry); + + // Don't let the cleanup routine free this. + pPrintProvider = NULL; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pPrintProvider) + DllFreeSplMem(pPrintProvider); + + return dwErrorCode; +} + +static BOOL +_InitializePrintProviderList() +{ + DWORD cbFileName; + DWORD cchMaxSubKey; + DWORD cchPrintProviderName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + PWSTR pwszPrintProviderName = NULL; + WCHAR wszFileName[MAX_PATH]; + + // Initialize an empty list for our Print Providers. + InitializeListHead(&PrintProviderList); + + // First add the Local Spooler. + // This one must exist and must be the first one in the list. + dwErrorCode = _AddPrintProviderToList(L"localspl"); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("The Local Spooler could not be loaded!\n"); + goto Cleanup; + } + + // Now add additional Print Providers from the registry. + // First of all, open the key containing print providers. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\CurrentControlSet\Control\Print\Providers", 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Providers and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Allocate a temporary buffer for the Print Provider names. + pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pwszPrintProviderName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Loop through all available Print Providers. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubKey) + { + RegCloseKey(hSubKey); + hSubKey = NULL; + } + + // Get the name of this Print Provider. + cchPrintProviderName = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pwszPrintProviderName, &cchPrintProviderName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); + continue; + } + + // Open this Print Provider's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pwszPrintProviderName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Provider "%S" with status %lu!\n", pwszPrintProviderName, dwErrorCode); + continue; + } + + // Get the file name of the Print Provider. + cbFileName = MAX_PATH * sizeof(WCHAR); + dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode); + continue; + } + + // Load and add it to the list. + dwErrorCode = _AddPrintProviderToList(wszFileName); + if (dwErrorCode != ERROR_SUCCESS) + continue; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + // Outside the loop + if (pwszPrintProviderName) + DllFreeSplMem(pwszPrintProviderName); + + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) @@ -18,7 +188,7 @@ { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); - hProcessHeap = GetProcessHeap(); + hProcessHeap = GetProcessHeap(); break; }
@@ -28,32 +198,7 @@ BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle) { - HINSTANCE hinstLocalSpl; - PInitializePrintProvidor pfnInitializePrintProvidor; - - // Only initialize localspl.dll for now. - // This function should later look for all available print providers in the registry and initialize all of them. - hinstLocalSpl = LoadLibraryW(L"localspl"); - if (!hinstLocalSpl) - { - ERR("LoadLibraryW for localspl failed with error %lu!\n", GetLastError()); - return FALSE; - } - - pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstLocalSpl, "InitializePrintProvidor"); - if (!pfnInitializePrintProvidor) - { - ERR("GetProcAddress failed with error %lu!\n", GetLastError()); - return FALSE; - } - - if (!pfnInitializePrintProvidor(&LocalSplFuncs, sizeof(PRINTPROVIDOR), NULL)) - { - ERR("InitializePrintProvidor failed for localspl with error %lu!\n", GetLastError()); - return FALSE; - } - - return TRUE; + return _InitializePrintProviderList(); }
BOOL WINAPI
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/memory.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/memory.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/memory.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -9,17 +9,17 @@
/** -* @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. -*/ + * @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) {
Added: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/monitors.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/monitors.c (added) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/monitors.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -0,0 +1,68 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck colin@reactos.org + */ + +#include "precomp.h" + +BOOL WINAPI +EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pMonitors; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Check if this Print Provider provides an EnumMonitors function. + if (!pPrintProvider->PrintProvider.fpEnumMonitors) + continue; + + // Call the EnumMonitors function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + + // Check if we shall not ask other Print Providers. + if (bReturnValue == ROUTER_STOP_ROUTING) + break; + } + + return bReturnValue; +}
Propchange: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/monitors.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/ports.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/ports.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/ports.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -1,7 +1,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 ports + * PURPOSE: Functions related to Ports of the Print Monitors * COPYRIGHT: Copyright 2015 Colin Finck colin@reactos.org */
@@ -10,5 +10,55 @@ BOOL WINAPI EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - return FALSE; + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPorts; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Call the EnumPorts function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + + // Check if we shall not ask other Print Providers. + if (bReturnValue == ROUTER_STOP_ROUTING) + break; + } + + return bReturnValue; }
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/precomp.h URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/precomp.h [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/precomp.h [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -15,17 +15,40 @@ #include <winreg.h> #include <winspool.h> #include <winsplp.h> +#include <ndk/rtlfuncs.h>
#include <spoolss.h>
#include <wine/debug.h> WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
-// Function pointer to InitializePrintProvidor of a provider DLL +// Function pointers typedef BOOL (WINAPI *PInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR); + +// Structures +/** + * Describes a Print Provider. + */ +typedef struct _SPOOLSS_PRINT_PROVIDER +{ + LIST_ENTRY Entry; + PRINTPROVIDOR PrintProvider; +} +SPOOLSS_PRINT_PROVIDER, *PSPOOLSS_PRINT_PROVIDER; + +/* + * Describes a handle returned by OpenPrinterW. + * We can't just pass the handle returned by the Print Provider, because spoolss has to remember which Print Provider opened this handle. + */ +typedef struct _SPOOLSS_PRINTER_HANDLE +{ + PSPOOLSS_PRINT_PROVIDER pPrintProvider; /** Pointer to the Print Provider that opened this printer. */ + HANDLE hPrinter; /** The handle returned by fpOpenPrinter of the Print Provider and passed to subsequent Print Provider functions. */ +} +SPOOLSS_PRINTER_HANDLE, *PSPOOLSS_PRINTER_HANDLE;
// main.c extern HANDLE hProcessHeap; -extern PRINTPROVIDOR LocalSplFuncs; +extern LIST_ENTRY PrintProviderList;
#endif
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printers.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printers.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printers.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -11,71 +11,262 @@ BOOL WINAPI ClosePrinter(HANDLE hPrinter) { + BOOL bReturnValue; + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // FIXME: Call FindClosePrinterChangeNotification for all created change notifications (according to MSDN). + + // Call CloseHandle of the Print Provider. + bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter); + + // Free our handle information. + DllFreeSplMem(pHandle); + + return bReturnValue; +} + +BOOL WINAPI +EndDocPrinter(HANDLE hPrinter) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter); +} + +BOOL WINAPI +EndPagePrinter(HANDLE hPrinter) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter); +} + +BOOL WINAPI +EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + 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; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPrinterEnum; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Call the EnumPrinters function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + } + + return bReturnValue; +} + +BOOL WINAPI +GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); +} + +BOOL WINAPI +GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded); +} + +BOOL WINAPI +OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault) +{ + BOOL bReturnValue; + HANDLE hPrinter; + PLIST_ENTRY pEntry; + PSPOOLSS_PRINTER_HANDLE pHandle; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + + // Sanity checks. + if (!pPrinterName || !phPrinter) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Loop through all Print Providers to find one able to open this Printer. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault); + if (bReturnValue == ROUTER_SUCCESS) + { + // This Print Provider has opened this Printer. + // Store this information and return a handle. + pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE)); + if (!pHandle) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return FALSE; + } + + pHandle->pPrintProvider = pPrintProvider; + pHandle->hPrinter = hPrinter; + *phPrinter = (HANDLE)pHandle; + + SetLastError(ERROR_SUCCESS); + return TRUE; + } + else if (bReturnValue == ROUTER_STOP_ROUTING) + { + ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer "%S"!\n", pPrinterName); + return FALSE; + } + } + + // We found no Print Provider able to open this Printer. return FALSE; }
BOOL WINAPI -EndDocPrinter(HANDLE hPrinter) -{ - return FALSE; -} - -BOOL WINAPI -EndPagePrinter(HANDLE hPrinter) -{ - return FALSE; -} - -BOOL WINAPI -EnumPrintersW(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - return LocalSplFuncs.fpEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned); -} - -BOOL WINAPI -GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) -{ - return FALSE; -} - -BOOL WINAPI -GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded) -{ - return FALSE; -} - -BOOL WINAPI -OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault) -{ - return LocalSplFuncs.fpOpenPrinter(pPrinterName, phPrinter, pDefault); -} - -BOOL WINAPI ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead) { - return FALSE; + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead); }
DWORD WINAPI -StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo) -{ - return 0; +StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo); }
BOOL WINAPI StartPagePrinter(HANDLE hPrinter) { - return FALSE; -} - -BOOL WINAPI -WritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten) -{ - return FALSE; + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter); +} + +BOOL WINAPI +WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten); }
BOOL WINAPI XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus) { - return FALSE; -} + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus); +}
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printprocessors.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printprocessors.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/printprocessors.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -8,19 +8,25 @@ #include "precomp.h"
BOOL WINAPI -EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - return LocalSplFuncs.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); }
BOOL WINAPI -EnumPrintProcessorsW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) { - return LocalSplFuncs.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned); + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned); }
BOOL WINAPI -GetPrintProcessorDirectoryW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded) +GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded) { - return LocalSplFuncs.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded); + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded); }
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/spoolss.spec URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/spoolss.spec [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/base/spoolss/spoolss.spec [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -60,16 +60,16 @@ @ stdcall EndPagePrinter(long) @ stub EnumFormsW @ stdcall EnumJobsW(long long long long ptr long ptr ptr) -@ stub EnumMonitorsW +@ stdcall EnumMonitorsW(wstr long ptr long ptr ptr) @ stub EnumPerMachineConnectionsW -@ stdcall EnumPortsW(ptr long ptr long ptr ptr) +@ stdcall EnumPortsW(wstr long ptr long ptr ptr) @ stub EnumPrinterDataExW @ stub EnumPrinterDataW @ stub EnumPrinterDriversW @ stub EnumPrinterKeyW -@ stdcall EnumPrintersW(long ptr long ptr long ptr ptr) -@ stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr) -@ stdcall EnumPrintProcessorsW(ptr ptr long ptr long ptr ptr) +@ stdcall EnumPrintersW(long wstr long ptr long ptr ptr) +@ stdcall EnumPrintProcessorDatatypesW(wstr wstr long ptr long ptr ptr) +@ stdcall EnumPrintProcessorsW(wstr wstr long ptr long ptr ptr) @ stub FindClosePrinterChangeNotification @ stub FlushPrinter @ stub FormatPrinterForRegistryKey
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -6,6 +6,8 @@ list(APPEND SOURCE jobs.c main.c + monitors.c + ports.c precomp.h printers.c printprocessors.c
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -102,7 +102,7 @@ return TRUE; }
-void +BOOL InitializeGlobalJobList() { const WCHAR wszPath[] = L"\PRINTERS\?????.SHD"; @@ -110,6 +110,7 @@ const DWORD cchFolders = sizeof("\PRINTERS\") - 1; const DWORD cchPattern = sizeof("?????") - 1;
+ DWORD dwErrorCode; DWORD dwJobID; HANDLE hFind; PLOCAL_JOB pJob = NULL; @@ -133,6 +134,7 @@ if (hFind == INVALID_HANDLE_VALUE) { // No unfinished jobs found. + dwErrorCode = ERROR_SUCCESS; goto Cleanup; }
@@ -159,6 +161,7 @@ // Add it to the Global Job List. if (!InsertElementSkiplist(&GlobalJobList, pJob)) { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID); goto Cleanup; } @@ -166,16 +169,22 @@ // Add it to the Printer's Job List. if (!InsertElementSkiplist(&pJob->pPrinter->JobList, pJob)) { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("InsertElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID); goto Cleanup; } } while (FindNextFileW(hFind, &FindData)); + + dwErrorCode = ERROR_SUCCESS;
Cleanup: // Outside the loop if (hFind) FindClose(hFind); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
void
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -22,6 +22,8 @@ #else #error Unsupported architecture #endif + +const DWORD cbCurrentEnvironment = sizeof(wszCurrentEnvironment);
const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
@@ -70,8 +72,8 @@ NULL, // fpGetForm NULL, // fpSetForm NULL, // fpEnumForms - NULL, // fpEnumMonitors - NULL, // fpEnumPorts + LocalEnumMonitors, // fpEnumMonitors + LocalEnumPorts, // fpEnumPorts NULL, // fpAddPort NULL, // fpConfigurePort NULL, // fpDeletePort @@ -142,13 +144,15 @@ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); _GetSpoolDirectory(); - InitializePrintProcessorList(); - InitializePrinterList(); - InitializeGlobalJobList(); - break; + + return InitializePrintMonitorList() && + InitializePrintProcessorList() && + InitializePrinterList() && + InitializeGlobalJobList(); + + default: + return TRUE; } - - return TRUE; }
BOOL WINAPI
Added: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/monitors.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/monitors.c (added) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/monitors.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -0,0 +1,314 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck colin@reactos.org + */ + +#include "precomp.h" + +// Local Variables +LIST_ENTRY PrintMonitorList; + +BOOL +InitializePrintMonitorList() +{ + const WCHAR wszMonitorsPath[] = L"SYSTEM\CurrentControlSet\Control\Print\Monitors"; + const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1; + + DWORD cchMaxSubKey; + DWORD cchPrintMonitorName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HINSTANCE hinstPrintMonitor = NULL; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + MONITORINIT MonitorInit; + PInitializePrintMonitor pfnInitializePrintMonitor; + PInitializePrintMonitor2 pfnInitializePrintMonitor2; + PLOCAL_PRINT_MONITOR pPrintMonitor = NULL; + PWSTR pwszRegistryPath = NULL; + + // Initialize an empty list for our Print Monitors. + InitializeListHead(&PrintMonitorList); + + // Open the key containing Print Monitors. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszMonitorsPath, 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Providers and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Loop through all available Print Providers. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubKey) + { + RegCloseKey(hSubKey); + hSubKey = NULL; + } + + if (pwszRegistryPath) + { + DllFreeSplMem(pwszRegistryPath); + pwszRegistryPath = NULL; + } + + if (pPrintMonitor) + { + if (pPrintMonitor->pwszFileName) + DllFreeSplMem(pPrintMonitor->pwszFileName); + + if (pPrintMonitor->pwszName) + DllFreeSplMem(pPrintMonitor->pwszName); + + DllFreeSplMem(pPrintMonitor); + pPrintMonitor = NULL; + } + + // Create a new LOCAL_PRINT_MONITOR structure for it. + pPrintMonitor = DllAllocSplMem(sizeof(LOCAL_PRINT_MONITOR)); + if (!pPrintMonitor) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Allocate memory for the Print Monitor Name. + pPrintMonitor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pPrintMonitor->pwszName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the name of this Print Monitor. + cchPrintMonitorName = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pPrintMonitor->pwszName, &cchPrintMonitorName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); + continue; + } + + // Open this Print Monitor's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pPrintMonitor->pwszName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Provider "%S" with status %lu!\n", pPrintMonitor->pwszName, dwErrorCode); + continue; + } + + // Get the file name of the Print Monitor. + pPrintMonitor->pwszFileName = AllocAndRegQueryWSZ(hSubKey, L"Driver"); + if (!pPrintMonitor->pwszFileName) + continue; + + // Try to load it. + hinstPrintMonitor = LoadLibraryW(pPrintMonitor->pwszFileName); + if (!hinstPrintMonitor) + { + ERR("LoadLibraryW failed for "%S" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + + // Try to find a Level 2 initialization routine first. + pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2"); + if (pfnInitializePrintMonitor2) + { + // Prepare a MONITORINIT structure. + MonitorInit.cbSize = sizeof(MONITORINIT); + MonitorInit.bLocal = TRUE; + + // TODO: Fill the other fields. + + // Call the Level 2 initialization routine. + pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor); + if (!pPrintMonitor->pMonitor) + { + ERR("InitializePrintMonitor2 failed for "%S" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + + pPrintMonitor->bIsLevel2 = TRUE; + } + else + { + // Try to find a Level 1 initialization routine then. + pfnInitializePrintMonitor = (PInitializePrintMonitor)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor"); + if (pfnInitializePrintMonitor) + { + // Construct the registry path. + pwszRegistryPath = DllAllocSplMem((cchMonitorsPath + 1 + cchPrintMonitorName + 1) * sizeof(WCHAR)); + if (!pwszRegistryPath) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszRegistryPath, wszMonitorsPath, cchMonitorsPath * sizeof(WCHAR)); + pwszRegistryPath[cchMonitorsPath] = L'\'; + CopyMemory(&pwszRegistryPath[cchMonitorsPath + 1], pPrintMonitor->pwszName, (cchPrintMonitorName + 1) * sizeof(WCHAR)); + + // Call the Level 1 initialization routine. + pPrintMonitor->pMonitor = (LPMONITOREX)pfnInitializePrintMonitor(pwszRegistryPath); + if (!pPrintMonitor->pMonitor) + { + ERR("InitializePrintMonitor failed for "%S" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + } + else + { + ERR("No initialization routine found for "%S"!\n", pPrintMonitor->pwszFileName); + continue; + } + } + + // Add this Print Monitor to the list. + InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry); + + // Don't let the cleanup routine free this. + pPrintMonitor = NULL; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + if (pwszRegistryPath) + DllFreeSplMem(pwszRegistryPath); + + if (pPrintMonitor) + { + if (pPrintMonitor->pwszFileName) + DllFreeSplMem(pPrintMonitor->pwszFileName); + + if (pPrintMonitor->pwszName) + DllFreeSplMem(pPrintMonitor->pwszName); + + DllFreeSplMem(pPrintMonitor); + } + + // Outside the loop + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD cbFileName; + DWORD cbMonitorName; + DWORD dwErrorCode; + PBYTE pStart; + PBYTE pEnd; + PLIST_ENTRY pEntry; + PLOCAL_PRINT_MONITOR pPrintMonitor; + MONITOR_INFO_2W MonitorInfo2; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W, so we can handle both in one function here. + + // Sanity checks. + if (Level > 2) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // Count the required buffer size and the number of monitors. + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR); + cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR); + + if (Level == 1) + *pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName; + else + *pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings at the end of the buffer. + pStart = pMonitors; + pEnd = &pMonitors[cbBuf]; + + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + // Copy the monitor name. + cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR); + pEnd -= cbMonitorName; + MonitorInfo2.pName = (PWSTR)pEnd; + CopyMemory(pEnd, pPrintMonitor->pwszName, cbMonitorName); + + if (Level == 1) + { + // Finally copy the structure. + CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_1W)); + pStart += sizeof(MONITOR_INFO_1W); + } + else + { + // Copy the environment. + pEnd -= cbCurrentEnvironment; + MonitorInfo2.pEnvironment = (PWSTR)pEnd; + CopyMemory(pEnd, wszCurrentEnvironment, cbCurrentEnvironment); + + // Copy the file name. + cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR); + pEnd -= cbFileName; + MonitorInfo2.pDLLName = (PWSTR)pEnd; + CopyMemory(pEnd, pPrintMonitor->pwszFileName, cbFileName); + + // Finally copy the structure. + CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_2W)); + pStart += sizeof(MONITOR_INFO_2W); + } + + (*pcReturned)++; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +}
Propchange: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/monitors.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/ports.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/ports.c (added) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/ports.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -0,0 +1,64 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Ports of the Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck colin@reactos.org + */ + +#include "precomp.h" + + +BOOL WINAPI +LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PLOCAL_PRINT_MONITOR pPrintMonitor; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPorts; + + // Loop through all Print Monitors. + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + // Call the EnumPorts function of this Print Monitor. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + } + + return bReturnValue; +}
Propchange: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/ports.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -45,6 +45,8 @@ typedef DWORD (WINAPI *PGetPrintProcessorCapabilities)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); typedef HANDLE (WINAPI *POpenPrintProcessor)(LPWSTR, PPRINTPROCESSOROPENDATA); typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR); +typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR); +typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE);
// Structures /** @@ -141,6 +143,21 @@ PVOID pSpecificHandle; } LOCAL_HANDLE, *PLOCAL_HANDLE; + +/** + * Describes a Print Monitor. + */ +typedef struct _LOCAL_PRINT_MONITOR +{ + LIST_ENTRY Entry; + PWSTR pwszName; /** Name of the Print Monitor as read from the registry. */ + PWSTR pwszFileName; /** DLL File Name of the Print Monitor. */ + BOOL bIsLevel2; /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */ + PVOID pMonitor; /** For bIsLevel2 == TRUE: LPMONITOR2 pointer returned by InitializePrintMonitor2. + For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */ + HANDLE hMonitor; /** Only used when bIsLevel2 == TRUE: Handle returned by InitializePrintMonitor2. */ +} +LOCAL_PRINT_MONITOR, *PLOCAL_PRINT_MONITOR;
/** * Describes the header of a print job serialized into a shadow file (.SHD) @@ -184,7 +201,7 @@ // jobs.c extern SKIPLIST GlobalJobList; BOOL GetNextJobID(PDWORD dwJobID); -void InitializeGlobalJobList(); +BOOL InitializeGlobalJobList(); void InitializePrinterJobList(PLOCAL_PRINTER pPrinter); BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded); BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); @@ -196,14 +213,23 @@
// main.c extern const WCHAR wszCurrentEnvironment[]; +extern const DWORD cbCurrentEnvironment; extern const WCHAR wszDefaultDocumentName[]; extern const WCHAR* wszPrintProviderInfo[3]; extern WCHAR wszSpoolDirectory[MAX_PATH]; extern DWORD cchSpoolDirectory;
+// monitors.c +extern LIST_ENTRY PrintMonitorList; +BOOL InitializePrintMonitorList(); +BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned); + +// ports.c +BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned); + // printers.c extern SKIPLIST PrinterList; -void InitializePrinterList(); +BOOL InitializePrinterList(); BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault); DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo); @@ -216,7 +242,7 @@ // printprocessors.c BOOL FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype); PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PWSTR pwszName); -void InitializePrintProcessorList(); +BOOL InitializePrintProcessorList(); BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded);
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -33,18 +33,18 @@ * The list is searchable by name and returns information about the printers, including their job queues. * During this process, the job queues are also initialized. */ -void +BOOL InitializePrinterList() { const WCHAR wszPrintersKey[] = L"SYSTEM\CurrentControlSet\Control\Print\Printers";
DWORD cbData; DWORD cchPrinterName; + DWORD dwErrorCode; DWORD dwSubKeys; DWORD i; HKEY hKey = NULL; HKEY hSubKey = NULL; - LONG lStatus; PLOCAL_PRINTER pPrinter = NULL; PLOCAL_PRINT_PROCESSOR pPrintProcessor; PWSTR pwszPrintProcessor = NULL; @@ -54,18 +54,18 @@ InitializeSkiplist(&PrinterList, DllAllocSplMem, _PrinterListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
// Open our printers registry key. Each subkey is a local printer there. - lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszPrintersKey, 0, KEY_READ, &hKey); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegOpenKeyExW failed with status %ld!\n", lStatus); + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszPrintersKey, 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); goto Cleanup; }
// Get the number of subkeys. - lStatus = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegQueryInfoKeyW failed with status %ld!\n", lStatus); + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); goto Cleanup; }
@@ -105,23 +105,23 @@
// Get the name of this printer. cchPrinterName = _countof(wszPrinterName); - lStatus = RegEnumKeyExW(hKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL); - if (lStatus == ERROR_MORE_DATA) + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL); + if (dwErrorCode == ERROR_MORE_DATA) { // This printer name exceeds the maximum length and is invalid. continue; } - else if (lStatus != ERROR_SUCCESS) - { - ERR("RegEnumKeyExW failed for iteration %lu with status %ld!\n", i, lStatus); + else if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); continue; }
// Open this Printer's registry key. - lStatus = RegOpenKeyExW(hKey, wszPrinterName, 0, KEY_READ, &hSubKey); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegOpenKeyExW failed for Printer "%S" with status %ld!\n", wszPrinterName, lStatus); + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, wszPrinterName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Printer "%S" with status %lu!\n", wszPrinterName, dwErrorCode); continue; }
@@ -142,6 +142,7 @@ pPrinter = DllAllocSplMem(sizeof(LOCAL_PRINTER)); if (!pPrinter) { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); goto Cleanup; } @@ -174,28 +175,28 @@
// Get the default DevMode. cbData = sizeof(DEVMODEW); - lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbData); - if (lStatus != ERROR_SUCCESS || cbData != sizeof(DEVMODEW)) - { - ERR("Couldn't query a valid DevMode for Printer "%S", status is %ld, cbData is %lu!\n", wszPrinterName, lStatus, cbData); + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbData); + if (dwErrorCode != ERROR_SUCCESS || cbData != sizeof(DEVMODEW)) + { + ERR("Couldn't query a valid DevMode for Printer "%S", status is %lu, cbData is %lu!\n", wszPrinterName, dwErrorCode, cbData); continue; }
// Get the Attributes. cbData = sizeof(DWORD); - lStatus = RegQueryValueExW(hSubKey, L"Attributes", NULL, NULL, (PBYTE)&pPrinter->dwAttributes, &cbData); - if (lStatus != ERROR_SUCCESS) - { - ERR("Couldn't query Attributes for Printer "%S", status is %ld!\n", wszPrinterName, lStatus); + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Attributes", NULL, NULL, (PBYTE)&pPrinter->dwAttributes, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query Attributes for Printer "%S", status is %lu!\n", wszPrinterName, dwErrorCode); continue; }
// Get the Status. cbData = sizeof(DWORD); - lStatus = RegQueryValueExW(hSubKey, L"Status", NULL, NULL, (PBYTE)&pPrinter->dwStatus, &cbData); - if (lStatus != ERROR_SUCCESS) - { - ERR("Couldn't query Status for Printer "%S", status is %ld!\n", wszPrinterName, lStatus); + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Status", NULL, NULL, (PBYTE)&pPrinter->dwStatus, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query Status for Printer "%S", status is %lu!\n", wszPrinterName, dwErrorCode); continue; }
@@ -209,6 +210,8 @@ // Don't let the cleanup routines free this. pPrinter = NULL; } + + dwErrorCode = ERROR_SUCCESS;
Cleanup: // Inside the loop @@ -238,6 +241,9 @@ // Outside the loop if (hKey) RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
Modified: branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c URL: http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/reac... ============================================================================== --- branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1] (original) +++ branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1] Tue Jul 7 17:06:48 2015 @@ -111,7 +111,7 @@ * * Initializes a singly linked list of locally available Print Processors. */ -void +BOOL InitializePrintProcessorList() { DWORD cbDatatypes; @@ -119,15 +119,14 @@ DWORD cchPrintProcessorPath; DWORD cchMaxSubKey; DWORD cchPrintProcessorName; + DWORD dwErrorCode; DWORD dwSubKeys; DWORD i; HINSTANCE hinstPrintProcessor; HKEY hKey = NULL; HKEY hSubKey = NULL; HKEY hSubSubKey = NULL; - LONG lStatus; PLOCAL_PRINT_PROCESSOR pPrintProcessor = NULL; - PWSTR pwszPrintProcessorName = NULL; WCHAR wszFileName[MAX_PATH]; WCHAR wszPrintProcessorPath[MAX_PATH];
@@ -136,36 +135,32 @@
// Prepare the path to the Print Processor directory. if (!LocalGetPrintProcessorDirectory(NULL, NULL, 1, (PBYTE)wszPrintProcessorPath, sizeof(wszPrintProcessorPath), &cchPrintProcessorPath)) - goto Cleanup; + { + dwErrorCode = GetLastError(); + goto Cleanup; + }
cchPrintProcessorPath /= sizeof(WCHAR); wszPrintProcessorPath[cchPrintProcessorPath++] = L'\';
// Open the environment registry key. - if (_OpenEnvironment(NULL, &hKey) != ERROR_SUCCESS) + dwErrorCode = _OpenEnvironment(NULL, &hKey); + if (dwErrorCode != ERROR_SUCCESS) goto Cleanup;
// Open the "Print Processors" subkey. - lStatus = RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegOpenKeyExW failed with status %ld!\n", lStatus); + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); goto Cleanup; }
// Get the number of Print Processors and maximum sub key length. - lStatus = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegQueryInfoKeyW failed with status %ld!\n", lStatus); - goto Cleanup; - } - - // Allocate a temporary buffer for the Print Processor names. - pwszPrintProcessorName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); - if (!pwszPrintProcessorName) - { - ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); goto Cleanup; }
@@ -191,36 +186,54 @@ pPrintProcessor = NULL; }
+ // Create a new LOCAL_PRINT_PROCESSOR structure for it. + pPrintProcessor = DllAllocSplMem(sizeof(LOCAL_PRINT_PROCESSOR)); + if (!pPrintProcessor) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Allocate memory for the Print Monitor Name. + pPrintProcessor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pPrintProcessor->pwszName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + // Get the name of this Print Processor. cchPrintProcessorName = cchMaxSubKey + 1; - lStatus = RegEnumKeyExW(hSubKey, i, pwszPrintProcessorName, &cchPrintProcessorName, NULL, NULL, NULL, NULL); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegEnumKeyExW failed with status %ld!\n", lStatus); + dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pPrintProcessor->pwszName, &cchPrintProcessorName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed with status %ld!\n", dwErrorCode); continue; }
// Open this Print Processor's registry key. - lStatus = RegOpenKeyExW(hSubKey, pwszPrintProcessorName, 0, KEY_READ, &hSubSubKey); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegOpenKeyExW failed for Print Processor "%S" with status %ld!\n", pwszPrintProcessorName, lStatus); + dwErrorCode = (DWORD)RegOpenKeyExW(hSubKey, pPrintProcessor->pwszName, 0, KEY_READ, &hSubSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Processor "%S" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode); continue; }
// Get the file name of the Print Processor. cbFileName = sizeof(wszFileName); - lStatus = RegQueryValueExW(hSubSubKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); - if (lStatus != ERROR_SUCCESS) - { - ERR("RegQueryValueExW failed for Print Processor "%S" with status %ld!\n", pwszPrintProcessorName, lStatus); + dwErrorCode = (DWORD)RegQueryValueExW(hSubSubKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed for Print Processor "%S" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode); continue; }
// Verify that our buffer is large enough. if (cchPrintProcessorPath + cbFileName / sizeof(WCHAR) > MAX_PATH) { - ERR("Print Processor directory "%S" for Print Processor "%S" is too long!\n", wszFileName, pwszPrintProcessorName); + ERR("Print Processor directory "%S" for Print Processor "%S" is too long!\n", wszFileName, pPrintProcessor->pwszName); continue; }
@@ -229,15 +242,11 @@
// Try to load it. hinstPrintProcessor = LoadLibraryW(wszPrintProcessorPath); - if (lStatus != ERROR_SUCCESS) + if (!hinstPrintProcessor) { ERR("LoadLibraryW failed for "%S" with error %lu!\n", wszPrintProcessorPath, GetLastError()); continue; } - - // Create a new LOCAL_PRINT_PROCESSOR structure for it. - pPrintProcessor = DllAllocSplMem(sizeof(LOCAL_PRINT_PROCESSOR)); - pPrintProcessor->pwszName = AllocSplStr(pwszPrintProcessorName);
// Get and verify all its function pointers. pPrintProcessor->pfnClosePrintProcessor = (PClosePrintProcessor)GetProcAddress(hinstPrintProcessor, "ClosePrintProcessor"); @@ -287,6 +296,7 @@ pPrintProcessor->pDatatypesInfo1 = DllAllocSplMem(cbDatatypes); if (!pPrintProcessor->pDatatypesInfo1) { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); goto Cleanup; } @@ -303,6 +313,8 @@ // Don't let the cleanup routines free this. pPrintProcessor = NULL; } + + dwErrorCode = ERROR_SUCCESS;
Cleanup: // Inside the loop @@ -321,14 +333,14 @@ }
// Outside the loop - if (pwszPrintProcessorName) - DllFreeSplStr(pwszPrintProcessorName); - if (hSubKey) RegCloseKey(hSubKey);
if (hKey) RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); }
/**