1 /* 2 * PROJECT: ReactOS Local Spooler API Tests Injected DLL 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Tests for fpGetPrintProcessorDirectory 5 * COPYRIGHT: Copyright 2016-2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #include <apitest.h> 9 10 #define WIN32_NO_STATUS 11 #include <windef.h> 12 #include <winbase.h> 13 #include <wingdi.h> 14 #include <winreg.h> 15 #include <winspool.h> 16 #include <winsplp.h> 17 18 #include "../localspl_apitest.h" 19 #include <spoolss.h> 20 21 typedef BOOL (WINAPI *PGetPrintProcessorDirectoryW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); 22 extern BOOL GetLocalsplFuncs(LPPRINTPROVIDOR pp); 23 extern PVOID GetSpoolssFunc(const char* FunctionName); 24 25 START_TEST(fpGetPrintProcessorDirectory) 26 { 27 DWORD cbNeeded; 28 DWORD cbTemp; 29 //DWORD dwReturned; 30 PGetPrintProcessorDirectoryW pGetPrintProcessorDirectoryW; 31 PRINTPROVIDOR pp; 32 PWSTR pwszBuffer; 33 34 if (!GetLocalsplFuncs(&pp)) 35 return; 36 37 pGetPrintProcessorDirectoryW = GetSpoolssFunc("GetPrintProcessorDirectoryW"); 38 if (!pGetPrintProcessorDirectoryW) 39 return; 40 41 // In contrast to GetPrintProcessorDirectoryW, fpGetPrintProcessorDirectory needs an environment and doesn't just accept NULL. 42 SetLastError(0xDEADBEEF); 43 ok(!pp.fpGetPrintProcessorDirectory(NULL, NULL, 0, NULL, 0, NULL), "fpGetPrintProcessorDirectory returns TRUE!\n"); 44 ok(GetLastError() == ERROR_INVALID_ENVIRONMENT, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); 45 46 // Try with an invalid environment as well. 47 SetLastError(0xDEADBEEF); 48 ok(!pp.fpGetPrintProcessorDirectory(NULL, L"invalid", 0, NULL, 0, NULL), "fpGetPrintProcessorDirectory returns TRUE!\n"); 49 ok(GetLastError() == ERROR_INVALID_ENVIRONMENT, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); 50 51 // This test corrupts something inside spoolsv so that it's only runnable once without restarting spoolsv. Therefore it's disabled. 52 #if 0 53 // Now provide a valid environment and prove that it is checked case-insensitively. 54 // In contrast to GetPrintProcessorDirectoryW, the level isn't the next thing checked here, but fpGetPrintProcessorDirectory 55 // already tries to access the non-supplied pcbNeeded variable. 56 _SEH2_TRY 57 { 58 dwReturned = 0; 59 pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 0, NULL, 0, NULL); 60 } 61 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 62 { 63 dwReturned = _SEH2_GetExceptionCode(); 64 } 65 _SEH2_END; 66 67 ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu!\n", dwReturned); 68 #endif 69 70 // fpGetPrintProcessorDirectory doesn't care about the supplied level at all. Prove this here. 71 // With no buffer given, this needs to fail with ERROR_INSUFFICIENT_BUFFER. 72 SetLastError(0xDEADBEEF); 73 cbNeeded = 0; 74 ok(!pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1337, NULL, 0, &cbNeeded), "fpGetPrintProcessorDirectory returns TRUE!\n"); 75 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); 76 ok(cbNeeded > 0, "cbNeeded is %lu!\n", cbNeeded); 77 78 // This test corrupts something inside spoolsv so that it's only runnable once without restarting spoolsv. Therefore it's disabled. 79 #if 0 80 // Now provide the demanded size, but no buffer. 81 // Unlike GetPrintProcessorDirectoryW, fpGetPrintProcessorDirectory doesn't check for this case and tries to access the buffer. 82 _SEH2_TRY 83 { 84 dwReturned = 0; 85 pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1, NULL, cbNeeded, &cbTemp); 86 } 87 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 88 { 89 dwReturned = _SEH2_GetExceptionCode(); 90 } 91 _SEH2_END; 92 93 ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu!\n", dwReturned); 94 #endif 95 96 // Prove that this check is implemented in spoolss' GetPrintProcessorDirectoryW instead. 97 // In contrast to winspool's GetPrintProcessorDirectoryW, cbTemp is left untouched though. This comes from the fact that RPC isn't involved here. 98 SetLastError(0xDEADBEEF); 99 cbTemp = 0xDEADBEEF; 100 ok(!pGetPrintProcessorDirectoryW(NULL, L"wIndows nt x86", 1, NULL, cbNeeded, &cbTemp), "pGetPrintProcessorDirectoryW returns TRUE!\n"); 101 ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "pGetPrintProcessorDirectoryW returns error %lu!\n", GetLastError()); 102 ok(cbTemp == 0xDEADBEEF, "cbTemp is %lu!\n", cbTemp); 103 104 // Finally use the function as intended and aim for success! 105 // We only check success by the boolean return value though. GetLastError doesn't return anything meaningful here. 106 pwszBuffer = DllAllocSplMem(cbNeeded); 107 SetLastError(0xDEADBEEF); 108 ok(pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1, (PBYTE)pwszBuffer, cbNeeded, &cbTemp), "fpGetPrintProcessorDirectory returns FALSE!\n"); 109 ok(wcslen(pwszBuffer) == cbNeeded / sizeof(WCHAR) - 1, "fpGetPrintProcessorDirectory string is %Iu characters long, but %lu characters expected!\n", wcslen(pwszBuffer), cbNeeded / sizeof(WCHAR) - 1); 110 DllFreeSplMem(pwszBuffer); 111 } 112