- 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).
svn path=/branches/colins-printing-for-freedom/; revision=68375
jobs.c
main.c
memory.c
+ monitors.c
ports.c
precomp.h
printers.c
#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);
}
#include "precomp.h"
+// Global Variables
HANDLE hProcessHeap;
-PRINTPROVIDOR LocalSplFuncs;
+LIST_ENTRY PrintProviderList;
-BOOL WINAPI
-DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+static DWORD
+_AddPrintProviderToList(PCWSTR pwszFileName)
{
- switch (fdwReason)
+ DWORD dwErrorCode;
+ HINSTANCE hinstPrintProvider;
+ PInitializePrintProvidor pfnInitializePrintProvidor;
+ PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL;
+
+ // Try to load it.
+ hinstPrintProvider = LoadLibraryW(pwszFileName);
+ if (!hinstPrintProvider)
{
- case DLL_PROCESS_ATTACH:
- DisableThreadLibraryCalls(hinstDLL);
- hProcessHeap = GetProcessHeap();
- break;
+ dwErrorCode = GetLastError();
+ ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
+ goto Cleanup;
}
- return TRUE;
+ // 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;
}
-BOOL WINAPI
-InitializeRouter(HANDLE SpoolerStatusHandle)
+static BOOL
+_InitializePrintProviderList()
{
- HINSTANCE hinstLocalSpl;
- PInitializePrintProvidor pfnInitializePrintProvidor;
+ 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;
+ }
- // 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)
+ // 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("LoadLibraryW for localspl failed with error %lu!\n", GetLastError());
- return FALSE;
+ ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
+ goto Cleanup;
}
- pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstLocalSpl, "InitializePrintProvidor");
- if (!pfnInitializePrintProvidor)
+ // 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("GetProcAddress failed with error %lu!\n", GetLastError());
- return FALSE;
+ ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
+ goto Cleanup;
}
- if (!pfnInitializePrintProvidor(&LocalSplFuncs, sizeof(PRINTPROVIDOR), NULL))
+ // Allocate a temporary buffer for the Print Provider names.
+ pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
+ if (!pwszPrintProviderName)
{
- ERR("InitializePrintProvidor failed for localspl with error %lu!\n", GetLastError());
- return FALSE;
+ 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)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+ hProcessHeap = GetProcessHeap();
+ break;
}
return TRUE;
}
+BOOL WINAPI
+InitializeRouter(HANDLE SpoolerStatusHandle)
+{
+ return _InitializePrintProviderList();
+}
+
BOOL WINAPI
SplInitializeWinSpoolDrv(PVOID* pTable)
{
/**
-* @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)
{
--- /dev/null
+/*
+ * 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;
+}
/*
* 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>
*/
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;
}
#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
BOOL WINAPI
ClosePrinter(HANDLE hPrinter)
{
- return FALSE;
+ 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)
{
- return FALSE;
+ 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)
{
- return FALSE;
+ 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, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
+EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
- return LocalSplFuncs.fpEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, 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, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
+GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
{
- return FALSE;
+ 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, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
+GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
{
- return FALSE;
+ 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(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
+OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
{
- return LocalSplFuncs.fpOpenPrinter(pPrinterName, phPrinter, 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
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)
+StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
{
- return 0;
+ 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;
+ 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, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten)
+WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD 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.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);
}
#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);
}
@ 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
list(APPEND SOURCE
jobs.c
main.c
+ monitors.c
+ ports.c
precomp.h
printers.c
printprocessors.c
return TRUE;
}
-void
+BOOL
InitializeGlobalJobList()
{
const WCHAR wszPath[] = L"\\PRINTERS\\?????.SHD";
const DWORD cchFolders = sizeof("\\PRINTERS\\") - 1;
const DWORD cchPattern = sizeof("?????") - 1;
+ DWORD dwErrorCode;
DWORD dwJobID;
HANDLE hFind;
PLOCAL_JOB pJob = NULL;
if (hFind == INVALID_HANDLE_VALUE)
{
// No unfinished jobs found.
+ dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
// 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;
}
// 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
#error Unsupported architecture
#endif
+const DWORD cbCurrentEnvironment = sizeof(wszCurrentEnvironment);
+
const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
const WCHAR* wszPrintProviderInfo[3] = {
NULL, // fpGetForm
NULL, // fpSetForm
NULL, // fpEnumForms
- NULL, // fpEnumMonitors
- NULL, // fpEnumPorts
+ LocalEnumMonitors, // fpEnumMonitors
+ LocalEnumPorts, // fpEnumPorts
NULL, // fpAddPort
NULL, // fpConfigurePort
NULL, // fpDeletePort
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
_GetSpoolDirectory();
- InitializePrintProcessorList();
- InitializePrinterList();
- InitializeGlobalJobList();
- break;
- }
- return TRUE;
+ return InitializePrintMonitorList() &&
+ InitializePrintProcessorList() &&
+ InitializePrinterList() &&
+ InitializeGlobalJobList();
+
+ default:
+ return TRUE;
+ }
}
BOOL WINAPI
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}
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
/**
}
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)
* Documented in http://www.undocprint.org/formats/winspool/shd
// 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);
// 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);
// 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);
* 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;
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)
+ dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszPrintersKey, 0, KEY_READ, &hKey);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
+ 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)
+ dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegQueryInfoKeyW failed with status %ld!\n", lStatus);
+ ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
// 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)
+ else if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegEnumKeyExW failed for iteration %lu with status %ld!\n", i, lStatus);
+ 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)
+ dwErrorCode = (DWORD)RegOpenKeyExW(hKey, wszPrinterName, 0, KEY_READ, &hSubKey);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegOpenKeyExW failed for Printer \"%S\" with status %ld!\n", wszPrinterName, lStatus);
+ ERR("RegOpenKeyExW failed for Printer \"%S\" with status %lu!\n", wszPrinterName, dwErrorCode);
continue;
}
pPrinter = DllAllocSplMem(sizeof(LOCAL_PRINTER));
if (!pPrinter)
{
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
goto Cleanup;
}
// 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))
+ 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 %ld, cbData is %lu!\n", wszPrinterName, lStatus, cbData);
+ 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)
+ 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 %ld!\n", wszPrinterName, lStatus);
+ 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)
+ 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 %ld!\n", wszPrinterName, lStatus);
+ ERR("Couldn't query Status for Printer \"%S\", status is %lu!\n", wszPrinterName, dwErrorCode);
continue;
}
pPrinter = NULL;
}
+ dwErrorCode = ERROR_SUCCESS;
+
Cleanup:
// Inside the loop
if (hSubKey)
// Outside the loop
if (hKey)
RegCloseKey(hKey);
+
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
*
* Initializes a singly linked list of locally available Print Processors.
*/
-void
+BOOL
InitializePrintProcessorList()
{
DWORD cbDatatypes;
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];
// Prepare the path to the Print Processor directory.
if (!LocalGetPrintProcessorDirectory(NULL, NULL, 1, (PBYTE)wszPrintProcessorPath, sizeof(wszPrintProcessorPath), &cchPrintProcessorPath))
+ {
+ 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)
+ dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
+ 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)
+ dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+ ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
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)
+ dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pPrintProcessor->pwszName, &cchPrintProcessorName, NULL, NULL, NULL, NULL);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegEnumKeyExW failed with status %ld!\n", lStatus);
+ 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)
+ dwErrorCode = (DWORD)RegOpenKeyExW(hSubKey, pPrintProcessor->pwszName, 0, KEY_READ, &hSubSubKey);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegOpenKeyExW failed for Print Processor \"%S\" with status %ld!\n", pwszPrintProcessorName, lStatus);
+ 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)
+ dwErrorCode = (DWORD)RegQueryValueExW(hSubSubKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName);
+ if (dwErrorCode != ERROR_SUCCESS)
{
- ERR("RegQueryValueExW failed for Print Processor \"%S\" with status %ld!\n", pwszPrintProcessorName, lStatus);
+ 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;
}
// 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");
if (!pPrintProcessor->pfnClosePrintProcessor)
pPrintProcessor->pDatatypesInfo1 = DllAllocSplMem(cbDatatypes);
if (!pPrintProcessor->pDatatypesInfo1)
{
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
goto Cleanup;
}
pPrintProcessor = NULL;
}
+ dwErrorCode = ERROR_SUCCESS;
+
Cleanup:
// Inside the loop
if (hSubSubKey)
}
// Outside the loop
- if (pwszPrintProcessorName)
- DllFreeSplStr(pwszPrintProcessorName);
-
if (hSubKey)
RegCloseKey(hSubKey);
if (hKey)
RegCloseKey(hKey);
+
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
}
/**