/* * Copyright 2016 Alistair Leslie-Hughes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define WIN32_LEAN_AND_MEAN #include <stdio.h> #include <dplay8.h> #include "wine/test.h" #include "dpnet_test.h" static const GUID appguid = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } }; static int cnt_thread_create = 0; static int cnt_thread_destroy = 0; static int cnt_complete = 0; static HANDLE enumevent = NULL; static HRESULT WINAPI DirectPlayThreadHandler(void *context, DWORD message_id, void *buffer) { switch(message_id) { case DPN_MSGID_CREATE_THREAD: cnt_thread_create++; break; case DPN_MSGID_DESTROY_THREAD: cnt_thread_destroy++; break; case DPN_MSGID_ASYNC_OP_COMPLETE: cnt_complete++; if(cnt_complete >= 2) SetEvent(enumevent); default: trace("DirectPlayThreadHandler: 0x%08x\n", message_id); } return S_OK; } static void create_threadpool(void) { HRESULT hr; IDirectPlay8ThreadPool *pool1 = NULL; IDirectPlay8ThreadPool *pool2 = NULL; DWORD threadcnt = 10; hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool1); ok(hr == S_OK, "got 0x%08x\n", hr); hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool2); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, NULL, 0); ok(hr == DPNERR_INVALIDPARAM, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, &DirectPlayThreadHandler, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool2, NULL, &DirectPlayThreadHandler, 0); ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); ok(threadcnt == 0, "got %d\n", threadcnt); hr = IDirectPlay8ThreadPool_SetThreadCount(pool1, -1, 5, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(cnt_thread_create == 5, "got %d\n", threadcnt); hr = IDirectPlay8ThreadPool_SetThreadCount(pool2, -1, 5, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(cnt_thread_create == 5, "got %d\n", threadcnt); /* Thead count must be zero before DoWork can be called. */ hr = IDirectPlay8ThreadPool_DoWork(pool1, 100, 0); todo_wine ok(hr == DPNERR_NOTREADY, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(threadcnt == 5, "got %d\n", threadcnt); hr = IDirectPlay8ThreadPool_SetThreadCount(pool1, -1, 0, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(cnt_thread_destroy == 5, "got %d\n", threadcnt); hr = IDirectPlay8ThreadPool_DoWork(pool1, 100, 0); ok(hr == DPN_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Close(pool1, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Close(pool2, 0); ok(hr == DPNERR_UNINITIALIZED, "got 0x%08x\n", hr); IDirectPlay8ThreadPool_Release(pool1); IDirectPlay8ThreadPool_Release(pool2); } static void test_enum_hosts(void) { HRESULT hr; IDirectPlay8Client* client = NULL; IDirectPlay8Address *host = NULL; IDirectPlay8Address *local = NULL; IDirectPlay8ThreadPool *pool1 = NULL; DPN_APPLICATION_DESC appdesc; DPNHANDLE async = 0, async2 = 0; static const WCHAR localhost[] = {'1','2','7','.','0','.','0','.','1',0}; DWORD threadcnt, threadorig; enumevent = CreateEventA( NULL, TRUE, FALSE, NULL); memset( &appdesc, 0, sizeof(DPN_APPLICATION_DESC) ); appdesc.dwSize = sizeof( DPN_APPLICATION_DESC ); appdesc.guidApplication = appguid; hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool1); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, &DirectPlayThreadHandler, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, &DirectPlayThreadHandler, 0); ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); ok(threadcnt == 0, "got %d\n", threadcnt); hr = CoCreateInstance(&CLSID_DirectPlay8Client, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectPlay8Client, (void **)&client); ok(hr == S_OK, "CoCreateInstance failed with 0x%x\n", hr); hr = IDirectPlay8Client_Initialize(client, NULL, DirectPlayThreadHandler, 0); ok(hr == S_OK, "IDirectPlay8Client_Initialize failed with %x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(threadcnt == 1, "got %d\n", threadcnt); hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (LPVOID*)&local); ok(hr == S_OK, "IDirectPlay8Address failed with 0x%08x\n", hr); hr = IDirectPlay8Address_SetSP(local, &CLSID_DP8SP_TCPIP); ok(hr == S_OK, "IDirectPlay8Address_SetSP failed with 0x%08x\n", hr); hr = CoCreateInstance( &CLSID_DirectPlay8Address, NULL, CLSCTX_ALL, &IID_IDirectPlay8Address, (LPVOID*)&host); ok(hr == S_OK, "IDirectPlay8Address failed with 0x%08x\n", hr); hr = IDirectPlay8Address_SetSP(host, &CLSID_DP8SP_TCPIP); ok(hr == S_OK, "IDirectPlay8Address_SetSP failed with 0x%08x\n", hr); hr = IDirectPlay8Address_AddComponent(host, DPNA_KEY_HOSTNAME, localhost, sizeof(localhost), DPNA_DATATYPE_STRING); ok(hr == S_OK, "IDirectPlay8Address failed with 0x%08x\n", hr); hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, INFINITE, 0, INFINITE, NULL, &async, 0); ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); todo_wine ok(async, "No Handle returned\n"); /* The first EnumHosts call will increase the thread count */ hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadorig, 0); ok(hr == S_OK, "got 0x%08x\n", hr); todo_wine ok(threadorig > 1, "got %d\n", threadorig); hr = IDirectPlay8Client_EnumHosts(client, &appdesc, host, local, NULL, 0, INFINITE, 0, INFINITE, NULL, &async2, 0); ok(hr == DPNSUCCESS_PENDING, "IDirectPlay8Client_EnumHosts failed with 0x%08x\n", hr); WaitForSingleObject(enumevent, 1000); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); ok(threadcnt == threadorig, "got %d\n", threadcnt); hr = IDirectPlay8Client_CancelAsyncOperation(client, async, 0); ok(hr == S_OK, "IDirectPlay8Client_CancelAsyncOperation failed with 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); ok(threadcnt == threadorig, "got %d\n", threadcnt); hr = IDirectPlay8Client_CancelAsyncOperation(client, async2, 0); ok(hr == S_OK, "IDirectPlay8Client_CancelAsyncOperation failed with 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_GetThreadCount(pool1, -1, &threadcnt, 0); ok(hr == S_OK, "got 0x%08x\n", hr); ok(threadcnt == threadorig, "got %d\n", threadcnt); IDirectPlay8Address_Release(local); IDirectPlay8Address_Release(host); hr = IDirectPlay8ThreadPool_Close(pool1, 0); ok(hr == S_OK, "got 0x%08x\n", hr); IDirectPlay8Client_Release(client); IDirectPlay8ThreadPool_Release(pool1); CloseHandle(enumevent); } static void test_singleton(void) { HRESULT hr; IDirectPlay8ThreadPool *pool1, *pool2; hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool1); ok(hr == S_OK, "got 0x%08x\n", hr); hr = CoCreateInstance( &CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_ALL, &IID_IDirectPlay8ThreadPool, (void**)&pool2); ok(hr == S_OK, "got 0x%08x\n", hr); ok(pool1 != pool2, "same pointer returned.\n"); hr = IDirectPlay8ThreadPool_Initialize(pool1, NULL, &DirectPlayThreadHandler, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Initialize(pool2, NULL, &DirectPlayThreadHandler, 0); ok(hr == DPNERR_ALREADYINITIALIZED, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Close(pool1, 0); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDirectPlay8ThreadPool_Close(pool2, 0); ok(hr == DPNERR_UNINITIALIZED, "got 0x%08x\n", hr); IDirectPlay8ThreadPool_Release(pool1); IDirectPlay8ThreadPool_Release(pool2); } START_TEST(thread) { HRESULT hr; BOOL firewall_enabled; char path[MAX_PATH]; if(!GetSystemDirectoryA(path, MAX_PATH)) { skip("Failed to get systems directory\n"); return; } strcat(path, "\\dpnet.dll"); if (!winetest_interactive && is_stub_dll(path)) { win_skip("dpnet is a stub dll, skipping tests\n"); return; } if ((firewall_enabled = is_firewall_enabled()) && !is_process_elevated()) { skip("no privileges, skipping tests to avoid firewall dialog\n"); return; } if (firewall_enabled) { HRESULT hr = set_firewall(APP_ADD); if (hr != S_OK) { skip("can't authorize app in firewall %08x\n", hr); return; } } hr = CoInitialize(0); ok(hr == S_OK, "failed to init com\n"); if(hr != S_OK) return; create_threadpool(); test_enum_hosts(); test_singleton(); CoUninitialize(); }