/* * PROJECT: ReactOS Local Spooler API Tests Injected DLL * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation * PURPOSE: Tests for fpGetPrintProcessorDirectory * COPYRIGHT: Copyright 2016 Colin Finck */ #include #define WIN32_NO_STATUS #include #include #include #include #include #include #include "../localspl_apitest.h" #include typedef BOOL (WINAPI *PGetPrintProcessorDirectoryW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); extern BOOL GetLocalsplFuncs(LPPRINTPROVIDOR pp); extern PVOID GetSpoolssFunc(const char* FunctionName); START_TEST(fpGetPrintProcessorDirectory) { DWORD cbNeeded; DWORD cbTemp; DWORD dwReturned; PGetPrintProcessorDirectoryW pGetPrintProcessorDirectoryW; PRINTPROVIDOR pp; PWSTR pwszBuffer; if (!GetLocalsplFuncs(&pp)) return; pGetPrintProcessorDirectoryW = GetSpoolssFunc("GetPrintProcessorDirectoryW"); if (!pGetPrintProcessorDirectoryW) return; // In contrast to GetPrintProcessorDirectoryW, fpGetPrintProcessorDirectory needs an environment and doesn't just accept NULL. SetLastError(0xDEADBEEF); ok(!pp.fpGetPrintProcessorDirectory(NULL, NULL, 0, NULL, 0, NULL), "fpGetPrintProcessorDirectory returns TRUE!\n"); ok(GetLastError() == ERROR_INVALID_ENVIRONMENT, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); // Try with an invalid environment as well. SetLastError(0xDEADBEEF); ok(!pp.fpGetPrintProcessorDirectory(NULL, L"invalid", 0, NULL, 0, NULL), "fpGetPrintProcessorDirectory returns TRUE!\n"); ok(GetLastError() == ERROR_INVALID_ENVIRONMENT, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); // Now provide a valid environment and prove that it is checked case-insensitively. // In contrast to GetPrintProcessorDirectoryW, the level isn't the next thing checked here, but fpGetPrintProcessorDirectory // already tries to access the non-supplied pcbNeeded variable. _SEH2_TRY { dwReturned = 0; pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 0, NULL, 0, NULL); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { dwReturned = _SEH2_GetExceptionCode(); } _SEH2_END; ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu!\n", dwReturned); // fpGetPrintProcessorDirectory doesn't care about the supplied level at all. Prove this here. // With no buffer given, this needs to fail with ERROR_INSUFFICIENT_BUFFER. SetLastError(0xDEADBEEF); cbNeeded = 0; ok(!pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1337, NULL, 0, &cbNeeded), "fpGetPrintProcessorDirectory returns TRUE!\n"); ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpGetPrintProcessorDirectory returns error %lu!\n", GetLastError()); ok(cbNeeded > 0, "cbNeeded is %lu!\n", cbNeeded); // Now provide the demanded size, but no buffer. // Unlike GetPrintProcessorDirectoryW, fpGetPrintProcessorDirectory doesn't check for this case and tries to access the buffer. _SEH2_TRY { dwReturned = 0; pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1, NULL, cbNeeded, &cbTemp); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { dwReturned = _SEH2_GetExceptionCode(); } _SEH2_END; ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu!\n", dwReturned); // Prove that this check is implemented in spoolss' GetPrintProcessorDirectoryW instead. // In contrast to winspool's GetPrintProcessorDirectoryW, cbTemp is left untouched though. This comes from the fact that RPC isn't involved here. SetLastError(0xDEADBEEF); cbTemp = 0xDEADBEEF; ok(!pGetPrintProcessorDirectoryW(NULL, L"wIndows nt x86", 1, NULL, cbNeeded, &cbTemp), "pGetPrintProcessorDirectoryW returns TRUE!\n"); ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "pGetPrintProcessorDirectoryW returns error %lu!\n", GetLastError()); ok(cbTemp == 0xDEADBEEF, "cbTemp is %lu!\n", cbTemp); // Finally use the function as intended and aim for success! // We only check success by the boolean return value though. GetLastError doesn't return anything meaningful here. pwszBuffer = DllAllocSplMem(cbNeeded); SetLastError(0xDEADBEEF); ok(pp.fpGetPrintProcessorDirectory(NULL, L"wIndows nt x86", 1, (PBYTE)pwszBuffer, cbNeeded, &cbTemp), "fpGetPrintProcessorDirectory returns FALSE!\n"); ok(wcslen(pwszBuffer) == cbNeeded / sizeof(WCHAR) - 1, "fpGetPrintProcessorDirectory string is %Iu characters long, but %lu characters expected!\n", wcslen(pwszBuffer), cbNeeded / sizeof(WCHAR) - 1); DllFreeSplMem(pwszBuffer); }