1 /* 2 * PROJECT: ReactOS Spooler Router 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Functions related to Printer Configuration Data 5 * COPYRIGHT: Copyright 2020 ReactOS 6 */ 7 8 #include "precomp.h" 9 10 BOOL WINAPI 11 AddPrinterDriverExW(PWSTR pName, DWORD Level, PBYTE pDriverInfo, DWORD dwFileCopyFlags) 12 { 13 BOOL bReturnValue; 14 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME; 15 PLIST_ENTRY pEntry; 16 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 17 18 // Loop through all Print Providers. 19 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 20 { 21 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 22 23 bReturnValue = pPrintProvider->PrintProvider.fpAddPrinterDriverEx(pName, Level, pDriverInfo, dwFileCopyFlags); 24 25 if (bReturnValue == ROUTER_SUCCESS) 26 { 27 dwErrorCode = ERROR_SUCCESS; 28 goto Cleanup; 29 } 30 else if (bReturnValue == ROUTER_STOP_ROUTING) 31 { 32 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName); 33 dwErrorCode = GetLastError(); 34 goto Cleanup; 35 } 36 } 37 38 Cleanup: 39 // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know. 40 if (dwErrorCode == ERROR_INVALID_NAME) 41 dwErrorCode = ERROR_INVALID_PRINTER_NAME; 42 43 SetLastError(dwErrorCode); 44 return (dwErrorCode == ERROR_SUCCESS); 45 } 46 47 BOOL WINAPI 48 AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo) 49 { 50 TRACE("AddPrinterDriverW(%S, %lu, %p)\n", pName, Level, pDriverInfo); 51 return AddPrinterDriverExW(pName, Level, pDriverInfo, APD_COPY_NEW_FILES); 52 } 53 54 BOOL WINAPI 55 DeletePrinterDriverExW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName, DWORD dwDeleteFlag, DWORD dwVersionFlag) 56 { 57 BOOL bReturnValue; 58 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME; 59 PLIST_ENTRY pEntry; 60 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 61 62 // Loop through all Print Providers. 63 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 64 { 65 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 66 67 bReturnValue = pPrintProvider->PrintProvider.fpDeletePrinterDriverEx(pName, pEnvironment, pDriverName, dwDeleteFlag, dwVersionFlag); 68 69 if (bReturnValue == ROUTER_SUCCESS) 70 { 71 dwErrorCode = ERROR_SUCCESS; 72 goto Cleanup; 73 } 74 else if (bReturnValue == ROUTER_STOP_ROUTING) 75 { 76 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName); 77 dwErrorCode = GetLastError(); 78 goto Cleanup; 79 } 80 } 81 82 Cleanup: 83 // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know. 84 if (dwErrorCode == ERROR_INVALID_NAME) 85 dwErrorCode = ERROR_INVALID_PRINTER_NAME; 86 87 SetLastError(dwErrorCode); 88 return (dwErrorCode == ERROR_SUCCESS); 89 } 90 91 BOOL WINAPI 92 DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName) 93 { 94 TRACE("DeletePrinterDriverW(%S, %S, %S)\n", pName, pEnvironment, pDriverName); 95 return DeletePrinterDriverExW(pName, pEnvironment, pDriverName, 0, 0); 96 } 97 98 BOOL WINAPI 99 EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) 100 { 101 DWORD cbCallBuffer; 102 DWORD cbNeeded; 103 DWORD dwErrorCode = MAXDWORD; 104 DWORD dwReturned; 105 PBYTE pCallBuffer; 106 BOOL Ret = FALSE; 107 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 108 PLIST_ENTRY pEntry; 109 110 // Begin counting. 111 *pcbNeeded = 0; 112 *pcReturned = 0; 113 114 if ( cbBuf && !pDriverInfo ) 115 { 116 dwErrorCode = ERROR_INVALID_USER_BUFFER; 117 goto Cleanup; 118 } 119 120 // At the beginning, we have the full buffer available. 121 cbCallBuffer = cbBuf; 122 pCallBuffer = pDriverInfo; 123 124 // Loop through all Print Providers. 125 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 126 { 127 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 128 129 // Call the EnumPrinters function of this Print Provider. 130 cbNeeded = 0; 131 dwReturned = 0; 132 133 Ret = pPrintProvider->PrintProvider.fpEnumPrinterDrivers( pName, pEnvironment, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); 134 135 if ( !Ret ) 136 { 137 dwErrorCode = GetLastError(); 138 } 139 140 // Add the returned counts to the total values. 141 *pcbNeeded += cbNeeded; 142 *pcReturned += dwReturned; 143 144 // Reduce the available buffer size for the next call without risking an underflow. 145 if (cbNeeded < cbCallBuffer) 146 cbCallBuffer -= cbNeeded; 147 else 148 cbCallBuffer = 0; 149 150 // Advance the buffer if the caller provided it. 151 if (pCallBuffer) 152 pCallBuffer += cbNeeded; 153 154 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded. 155 if (dwErrorCode != ERROR_SUCCESS) 156 dwErrorCode = GetLastError(); 157 } 158 159 Cleanup: 160 SetLastError(dwErrorCode); 161 return (dwErrorCode == ERROR_SUCCESS); 162 } 163 164 BOOL WINAPI 165 GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded) 166 { 167 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; 168 169 // Sanity checks. 170 if (!pHandle) 171 { 172 SetLastError(ERROR_INVALID_PARAMETER); 173 return FALSE; 174 } 175 176 return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); 177 } 178 179 180 BOOL WINAPI 181 GetPrinterDriverExW( 182 HANDLE hPrinter, 183 LPWSTR pEnvironment, 184 DWORD Level, 185 LPBYTE pDriverInfo, 186 DWORD cbBuf, 187 LPDWORD pcbNeeded, 188 DWORD dwClientMajorVersion, 189 DWORD dwClientMinorVersion, 190 PDWORD pdwServerMajorVersion, 191 PDWORD pdwServerMinorVersion ) 192 { 193 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; 194 195 FIXME("GetPrinterDriverExW(%p, %lu, %lu, %p, %lu, %p, %lu, %lu, %p, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion); 196 197 // Sanity checks. 198 if (!pHandle) 199 { 200 SetLastError(ERROR_INVALID_PARAMETER); 201 return FALSE; 202 } 203 204 if ( cbBuf && !pDriverInfo ) 205 { 206 SetLastError(ERROR_INVALID_USER_BUFFER); 207 return FALSE; 208 } 209 210 return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriverEx(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded, dwClientMajorVersion, dwClientMinorVersion, pdwServerMajorVersion, pdwServerMinorVersion); 211 } 212 213 BOOL WINAPI 214 GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded) 215 { 216 BOOL bReturnValue; 217 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME; 218 PLIST_ENTRY pEntry; 219 PSPOOLSS_PRINT_PROVIDER pPrintProvider; 220 221 if ( cbBuf && !pDriverDirectory ) 222 { 223 SetLastError(ERROR_INVALID_USER_BUFFER); 224 return FALSE; 225 } 226 227 // Loop through all Print Providers. 228 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) 229 { 230 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); 231 232 bReturnValue = pPrintProvider->PrintProvider.fpGetPrinterDriverDirectory(pName, pEnvironment, Level, pDriverDirectory, cbBuf, pcbNeeded); 233 234 if (bReturnValue == ROUTER_SUCCESS) 235 { 236 dwErrorCode = ERROR_SUCCESS; 237 goto Cleanup; 238 } 239 else if (bReturnValue == ROUTER_STOP_ROUTING) 240 { 241 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pName); 242 dwErrorCode = GetLastError(); 243 goto Cleanup; 244 } 245 } 246 247 Cleanup: 248 // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know. 249 if (dwErrorCode == ERROR_INVALID_NAME) 250 dwErrorCode = ERROR_INVALID_PRINTER_NAME; 251 252 SetLastError(dwErrorCode); 253 return (dwErrorCode == ERROR_SUCCESS); 254 } 255