1 /* 2 * PROJECT: ReactOS Local Spooler API Tests Injected DLL 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Main functions 5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #define __ROS_LONG64__ 9 10 #define STANDALONE 11 #include <apitest.h> 12 13 #define WIN32_NO_STATUS 14 #include <io.h> 15 #include <windef.h> 16 #include <winbase.h> 17 #include <wingdi.h> 18 #include <winreg.h> 19 #include <winspool.h> 20 #include <winsplp.h> 21 22 #include "../localspl_apitest.h" 23 24 //#define NDEBUG 25 #include <debug.h> 26 27 // Test list 28 extern void func_fpEnumPrinters(void); 29 extern void func_fpGetPrintProcessorDirectory(void); 30 extern void func_fpSetJob(void); 31 32 const struct test winetest_testlist[] = 33 { 34 { "fpEnumPrinters", func_fpEnumPrinters }, 35 { "fpGetPrintProcessorDirectory", func_fpGetPrintProcessorDirectory }, 36 { "fpSetJob", func_fpSetJob }, 37 { 0, 0 } 38 }; 39 40 /** 41 * We don't link against winspool, so we don't have GetDefaultPrinterW. 42 * We can easily implement a similar function ourselves though. 43 */ 44 PWSTR 45 GetDefaultPrinterFromRegistry(VOID) 46 { 47 static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; 48 static const WCHAR wszDeviceValue[] = L"Device"; 49 50 DWORD cbNeeded; 51 DWORD dwErrorCode; 52 HKEY hWindowsKey = NULL; 53 PWSTR pwszDevice; 54 PWSTR pwszComma; 55 PWSTR pwszReturnValue = NULL; 56 57 // Open the registry key where the default printer for the current user is stored. 58 dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey); 59 if (dwErrorCode != ERROR_SUCCESS) 60 { 61 skip("RegOpenKeyExW failed with status %u!\n", dwErrorCode); 62 goto Cleanup; 63 } 64 65 // Determine the size of the required buffer. 66 dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded); 67 if (dwErrorCode != ERROR_SUCCESS) 68 { 69 skip("RegQueryValueExW failed with status %u!\n", dwErrorCode); 70 goto Cleanup; 71 } 72 73 // Allocate it. 74 pwszDevice = HeapAlloc(GetProcessHeap(), 0, cbNeeded); 75 if (!pwszDevice) 76 { 77 skip("HeapAlloc failed!\n"); 78 goto Cleanup; 79 } 80 81 // Now get the actual value. 82 dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded); 83 if (dwErrorCode != ERROR_SUCCESS) 84 { 85 skip("RegQueryValueExW failed with status %u!\n", dwErrorCode); 86 goto Cleanup; 87 } 88 89 // We get a string "<Printer Name>,winspool,<Port>:". 90 // Extract the printer name from it. 91 pwszComma = wcschr(pwszDevice, L','); 92 if (!pwszComma) 93 { 94 skip("Found no or invalid default printer: %S!\n", pwszDevice); 95 goto Cleanup; 96 } 97 98 // Return the default printer. 99 *pwszComma = 0; 100 pwszReturnValue = pwszDevice; 101 102 Cleanup: 103 if (hWindowsKey) 104 RegCloseKey(hWindowsKey); 105 106 return pwszReturnValue; 107 } 108 109 BOOL 110 GetLocalsplFuncs(LPPRINTPROVIDOR pp) 111 { 112 HMODULE hLocalspl; 113 PInitializePrintProvidor pfnInitializePrintProvidor; 114 115 // Get us a handle to the loaded localspl.dll. 116 hLocalspl = GetModuleHandleW(L"localspl"); 117 if (!hLocalspl) 118 { 119 skip("GetModuleHandleW failed with error %u!\n", GetLastError()); 120 return FALSE; 121 } 122 123 // Get a pointer to its InitializePrintProvidor function. 124 pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hLocalspl, "InitializePrintProvidor"); 125 if (!pfnInitializePrintProvidor) 126 { 127 skip("GetProcAddress failed with error %u!\n", GetLastError()); 128 return FALSE; 129 } 130 131 // Get localspl's function pointers. 132 if (!pfnInitializePrintProvidor(pp, sizeof(PRINTPROVIDOR), NULL)) 133 { 134 skip("pfnInitializePrintProvidor failed with error %u!\n", GetLastError()); 135 return FALSE; 136 } 137 138 return TRUE; 139 } 140 141 PVOID 142 GetSpoolssFunc(const char* FunctionName) 143 { 144 HMODULE hSpoolss; 145 146 // Get us a handle to the loaded spoolss.dll. 147 hSpoolss = GetModuleHandleW(L"spoolss"); 148 if (!hSpoolss) 149 { 150 skip("GetModuleHandleW failed with error %u!\n", GetLastError()); 151 return FALSE; 152 } 153 154 return GetProcAddress(hSpoolss, FunctionName); 155 } 156 157 // Running the tests from the injected DLL and redirecting their output to the pipe. 158 BOOL WINAPI 159 DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 160 { 161 char szTestName[150]; 162 DWORD cbRead; 163 FILE* fpStdout; 164 HANDLE hCommandPipe; 165 int iOldStdout; 166 167 // We only want to run our test once when the DLL is injected to the process. 168 if (fdwReason != DLL_PROCESS_ATTACH) 169 return TRUE; 170 171 // Read the test to run from the command pipe. 172 hCommandPipe = CreateFileW(COMMAND_PIPE_NAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 173 if (hCommandPipe == INVALID_HANDLE_VALUE) 174 { 175 DPRINT("DLL: CreateFileW failed for the command pipe with error %lu!\n", GetLastError()); 176 return FALSE; 177 } 178 179 if (!ReadFile(hCommandPipe, szTestName, sizeof(szTestName), &cbRead, NULL)) 180 { 181 DPRINT("DLL: ReadFile failed for the command pipe with error %lu!\n", GetLastError()); 182 return FALSE; 183 } 184 185 CloseHandle(hCommandPipe); 186 187 // Check if the test name is valid. 188 if (!find_test(szTestName)) 189 { 190 DPRINT("DLL: Got invalid test name \"%s\"!\n", szTestName); 191 return FALSE; 192 } 193 194 // Backup our current stdout and set it to the output pipe. 195 iOldStdout = _dup(_fileno(stdout)); 196 fpStdout = _wfreopen(OUTPUT_PIPE_NAME, L"w", stdout); 197 setbuf(stdout, NULL); 198 199 // Run the test. 200 run_test(szTestName); 201 202 // Restore stdout to the previous value. 203 fclose(fpStdout); 204 _dup2(iOldStdout, _fileno(stdout)); 205 206 // Return FALSE so that our DLL is immediately unloaded. 207 return FALSE; 208 } 209