1 /* 2 * PROJECT: ReactOS Spooler Router 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions related to Print Monitors 5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 BOOL WINAPI 11 AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors) 12 { 13 BOOL bReturnValue = TRUE; 14 DWORD dwErrorCode = MAXDWORD; 15 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 16 PLIST_ENTRY pEntry; 17 18 // Loop through all Print Provider. 19 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 20 { 21 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 22 23 // Check if this Print Provider provides the function. 24 if (!pPrintProvider->PrintProvider.fpAddMonitor) 25 continue; 26 27 bReturnValue = pPrintProvider->PrintProvider.fpAddMonitor(pName, Level, pMonitors); 28 29 if ( !bReturnValue ) 30 { 31 dwErrorCode = GetLastError(); 32 } 33 34 // dwErrorCode shall not be overwritten if a previous call already succeeded. 35 if (dwErrorCode != ERROR_SUCCESS) 36 dwErrorCode = GetLastError(); 37 } 38 39 SetLastError(dwErrorCode); 40 return (dwErrorCode == ERROR_SUCCESS); 41 } 42 43 BOOL WINAPI 44 DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName) 45 { 46 BOOL bReturnValue = TRUE; 47 DWORD dwErrorCode = MAXDWORD; 48 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 49 PLIST_ENTRY pEntry; 50 51 // Loop through all Print Provider. 52 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 53 { 54 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 55 56 // Check if this Print Provider provides the function. 57 if (!pPrintProvider->PrintProvider.fpDeleteMonitor) 58 continue; 59 60 bReturnValue = pPrintProvider->PrintProvider.fpDeleteMonitor(pName, pEnvironment, pMonitorName); 61 62 if ( !bReturnValue ) 63 { 64 dwErrorCode = GetLastError(); 65 } 66 67 // dwErrorCode shall not be overwritten if a previous call already succeeded. 68 if (dwErrorCode != ERROR_SUCCESS) 69 dwErrorCode = GetLastError(); 70 } 71 72 SetLastError(dwErrorCode); 73 return (dwErrorCode == ERROR_SUCCESS); 74 } 75 76 BOOL WINAPI 77 EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) 78 { 79 BOOL bReturnValue = TRUE; 80 DWORD cbCallBuffer; 81 DWORD cbNeeded; 82 DWORD dwReturned; 83 DWORD dwErrorCode = MAXDWORD; 84 PBYTE pCallBuffer; 85 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 86 PLIST_ENTRY pEntry; 87 88 // Sanity checks. 89 if (cbBuf && !pMonitors) 90 { 91 SetLastError(ERROR_INVALID_USER_BUFFER); 92 return FALSE; 93 } 94 95 // Begin counting. 96 *pcbNeeded = 0; 97 *pcReturned = 0; 98 99 // At the beginning, we have the full buffer available. 100 cbCallBuffer = cbBuf; 101 pCallBuffer = pMonitors; 102 103 // Loop through all Print Provider. 104 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 105 { 106 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 107 108 // Check if this Print Provider provides an EnumMonitors function. 109 if (!pPrintProvider->PrintProvider.fpEnumMonitors) 110 continue; 111 112 // Call the EnumMonitors function of this Print Provider. 113 cbNeeded = 0; 114 dwReturned = 0; 115 bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); 116 117 if ( !bReturnValue ) 118 { 119 dwErrorCode = GetLastError(); 120 } 121 122 // Add the returned counts to the total values. 123 *pcbNeeded += cbNeeded; 124 *pcReturned += dwReturned; 125 126 // Reduce the available buffer size for the next call without risking an underflow. 127 if (cbNeeded < cbCallBuffer) 128 cbCallBuffer -= cbNeeded; 129 else 130 cbCallBuffer = 0; 131 132 // Advance the buffer if the caller provided it. 133 if (pCallBuffer) 134 pCallBuffer += cbNeeded; 135 136 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded. 137 if (dwErrorCode != ERROR_SUCCESS) 138 dwErrorCode = GetLastError(); 139 } 140 141 SetLastError(dwErrorCode); 142 return (dwErrorCode == ERROR_SUCCESS); 143 } 144