/** * CTest for winpr's SetLastError/GetLastError * * Copyright 2013 Marc-Andre Moreau * Copyright 2013 Thincast Technologies GmbH * Copyright 2013 Norbert Federa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include static int status = 0; static LONG* pLoopCount = nullptr; static BOOL bStopTest = FALSE; static UINT32 prand(UINT32 max) { UINT32 tmp = 0; if (max <= 1) return 1; if (winpr_RAND(&tmp, sizeof(tmp)) < 0) { (void)fprintf(stderr, "winpr_RAND failing, retry...\n"); // NOLINTNEXTLINE(concurrency-mt-unsafe) exit(-1); } return tmp % (max - 1) + 1; } static DWORD WINAPI test_error_thread(LPVOID arg) { int id = 0; DWORD dwErrorSet = 0; DWORD dwErrorGet = 0; id = (int)(size_t)arg; do { dwErrorSet = prand(UINT32_MAX - 1) + 1; SetLastError(dwErrorSet); if ((dwErrorGet = GetLastError()) != dwErrorSet) { printf("GetLastError() failure (thread %d): Expected: 0x%08" PRIX32 ", Actual: 0x%08" PRIX32 "\n", id, dwErrorSet, dwErrorGet); if (!status) status = -1; break; } InterlockedIncrement(pLoopCount); } while (!status && !bStopTest); return 0; } int TestErrorSetLastError(int argc, char* argv[]) { DWORD error = 0; HANDLE threads[4]; WINPR_UNUSED(argc); WINPR_UNUSED(argv); /* We must initialize WLog here. It will check for settings * in the environment and if the variables are not set, the last * error state is changed... */ WLog_GetRoot(); SetLastError(ERROR_ACCESS_DENIED); error = GetLastError(); if (error != ERROR_ACCESS_DENIED) { printf("GetLastError() failure: Expected: 0x%08X, Actual: 0x%08" PRIX32 "\n", ERROR_ACCESS_DENIED, error); return -1; } pLoopCount = winpr_aligned_malloc(sizeof(LONG), sizeof(LONG)); if (!pLoopCount) { printf("Unable to allocate memory\n"); return -1; } *pLoopCount = 0; for (int i = 0; i < 4; i++) { if (!(threads[i] = CreateThread(nullptr, 0, test_error_thread, (void*)(size_t)0, 0, nullptr))) { printf("Failed to create thread #%d\n", i); return -1; } } // let the threads run for at least 0.2 seconds Sleep(200); bStopTest = TRUE; (void)WaitForSingleObject(threads[0], INFINITE); (void)WaitForSingleObject(threads[1], INFINITE); (void)WaitForSingleObject(threads[2], INFINITE); (void)WaitForSingleObject(threads[3], INFINITE); (void)CloseHandle(threads[0]); (void)CloseHandle(threads[1]); (void)CloseHandle(threads[2]); (void)CloseHandle(threads[3]); error = GetLastError(); if (error != ERROR_ACCESS_DENIED) { printf("GetLastError() failure: Expected: 0x%08X, Actual: 0x%08" PRIX32 "\n", ERROR_ACCESS_DENIED, error); return -1; } if (*pLoopCount < 4) { printf("Error: unexpected loop count\n"); return -1; } printf("Completed %" PRId32 " iterations.\n", *pLoopCount); winpr_aligned_free(pLoopCount); return status; }