gameux/tests: Add a trailing '\n' to an ok() call.
[wine.git] / dlls / gameux / tests / gameexplorer.c
blob05c2a1104f0f53a6a8ebff0bc83d36e487adfb78
1 /*
2 * IGameExplorer and IGameExplorer2 tests
4 * Copyright (C) 2010 Mariusz PluciƄski
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "windows.h"
24 #include "ole2.h"
25 #include "objsafe.h"
26 #include "objbase.h"
27 #include "shlwapi.h"
28 #include "sddl.h"
29 #include "shobjidl.h"
31 #include "initguid.h"
32 #include "gameux.h"
34 #include "wine/test.h"
36 /*******************************************************************************
37 * Pointers used instead of direct calls. These procedures are not available on
38 * older system, which causes problem while loading test binary.
40 static BOOL WINAPI (*_ConvertSidToStringSidW)(PSID,LPWSTR*);
41 static LONG WINAPI (*_RegGetValueW)(HKEY,LPCWSTR,LPCWSTR,DWORD,LPDWORD,PVOID,LPDWORD);
43 /*******************************************************************************
44 *_loadDynamicRoutines
46 * Helper function, prepares pointers to system procedures which may be not
47 * available on older operating systems.
49 * Returns:
50 * TRUE procedures were loaded successfully
51 * FALSE procedures were not loaded successfully
53 static BOOL _loadDynamicRoutines(void)
55 HMODULE hAdvapiModule = GetModuleHandleA( "advapi32.dll" );
57 _ConvertSidToStringSidW = (LPVOID)GetProcAddress(hAdvapiModule, "ConvertSidToStringSidW");
58 if (!_ConvertSidToStringSidW) return FALSE;
59 _RegGetValueW = (LPVOID)GetProcAddress(hAdvapiModule, "RegGetValueW");
60 if (!_RegGetValueW) return FALSE;
61 return TRUE;
64 /*******************************************************************************
65 * _buildGameRegistryPath
67 * Helper function, builds registry path to key, where game's data are stored
69 * Parameters:
70 * installScope [I] the scope which was used in AddGame/InstallGame call
71 * gameInstanceId [I] game instance GUID. If NULL, then only
72 * path to scope is returned
73 * lpRegistryPath [O] pointer which will receive address to string
74 * containing expected registry path. Path
75 * is relative to HKLM registry key. It
76 * must be freed by calling CoTaskMemFree
78 static HRESULT _buildGameRegistryPath(GAME_INSTALL_SCOPE installScope,
79 LPCGUID gameInstanceId,
80 LPWSTR* lpRegistryPath)
82 static const WCHAR sGameUxRegistryPath[] = {'S','O','F','T','W','A','R','E','\\',
83 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
84 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','G','a','m','e','U','X',0};
85 static const WCHAR sGames[] = {'G','a','m','e','s',0};
86 static const WCHAR sBackslash[] = {'\\',0};
88 HRESULT hr = S_OK;
89 HANDLE hToken = NULL;
90 PTOKEN_USER pTokenUser = NULL;
91 DWORD dwLength;
92 LPWSTR lpSID = NULL;
93 WCHAR sInstanceId[40];
94 WCHAR sRegistryPath[8192];
96 lstrcpyW(sRegistryPath, sGameUxRegistryPath);
97 lstrcatW(sRegistryPath, sBackslash);
99 if(installScope == GIS_CURRENT_USER)
101 /* build registry path containing user's SID */
102 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
103 hr = HRESULT_FROM_WIN32(GetLastError());
105 if(SUCCEEDED(hr))
107 if(!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) &&
108 GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
109 hr = HRESULT_FROM_WIN32(GetLastError());
111 if(SUCCEEDED(hr))
113 pTokenUser = CoTaskMemAlloc(dwLength);
114 if(!pTokenUser)
115 hr = E_OUTOFMEMORY;
118 if(SUCCEEDED(hr))
119 if(!GetTokenInformation(hToken, TokenUser, (LPVOID)pTokenUser, dwLength, &dwLength))
120 hr = HRESULT_FROM_WIN32(GetLastError());
122 if(SUCCEEDED(hr))
123 if(!_ConvertSidToStringSidW(pTokenUser->User.Sid, &lpSID))
124 hr = HRESULT_FROM_WIN32(GetLastError());
126 if(SUCCEEDED(hr))
128 lstrcatW(sRegistryPath, lpSID);
129 LocalFree(lpSID);
132 CoTaskMemFree(pTokenUser);
133 CloseHandle(hToken);
136 else if(installScope == GIS_ALL_USERS)
137 /* build registry path without SID */
138 lstrcatW(sRegistryPath, sGames);
139 else
140 hr = E_INVALIDARG;
142 /* put game's instance id on the end of path, but only if id was passes */
143 if(gameInstanceId)
145 if(SUCCEEDED(hr))
146 hr = (StringFromGUID2(gameInstanceId, sInstanceId, sizeof(sInstanceId)/sizeof(sInstanceId[0])) ? S_OK : E_FAIL);
148 if(SUCCEEDED(hr))
150 lstrcatW(sRegistryPath, sBackslash);
151 lstrcatW(sRegistryPath, sInstanceId);
155 if(SUCCEEDED(hr))
157 *lpRegistryPath = CoTaskMemAlloc((lstrlenW(sRegistryPath)+1)*sizeof(WCHAR));
158 if(!*lpRegistryPath)
159 hr = E_OUTOFMEMORY;
162 if(SUCCEEDED(hr))
163 lstrcpyW(*lpRegistryPath, sRegistryPath);
165 return hr;
167 /*******************************************************************************
168 * _validateRegistryValue
170 * Helper function, verifies single registry value with expected
172 * Parameters:
173 * hKey [I] handle to game's key. Key must be opened
174 * keyPath [I] string with path to game's key. Used only
175 * to display more useful message on test fail
176 * valueName [I] name of value to check
177 * dwExpectedType [I] expected type of value. It should be
178 * one of RRF_RT_* flags
179 * lpExpectedContent [I] expected content of value. It should be
180 * pointer to variable with same type as
181 * passed in dwExpectedType
183 * Returns:
184 * S_OK value exists and contains expected data
185 * S_FALSE value exists, but contains other data
186 * than expected
187 * E_OUTOFMEMORY allocation problem
188 * HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
189 * value does not exist
191 * Note: this function returns error codes instead of failing test case, because
192 * it is sometimes expected that given value may not exist on some systems, or
193 * contain other data.
195 static HRESULT _validateRegistryValue(
196 HKEY hKey,
197 LPCWSTR keyPath,
198 LPCWSTR valueName,
199 DWORD dwExpectedType,
200 LPCVOID lpExpectedContent)
202 HRESULT hr;
203 DWORD dwType, dwSize;
204 LPVOID lpData = NULL;
206 hr = HRESULT_FROM_WIN32(_RegGetValueW(hKey, NULL, valueName, dwExpectedType, &dwType, NULL, &dwSize));
207 if(FAILED(hr)) trace("registry value cannot be opened\n"
208 " key: %s\n"
209 " value: %s\n"
210 " expected type: 0x%x\n"
211 " found type: 0x%x\n"
212 " result code: 0x%0x\n",
213 wine_dbgstr_w(keyPath),
214 wine_dbgstr_w(valueName),
215 dwExpectedType,
216 dwType,
217 hr);
219 if(SUCCEEDED(hr))
221 lpData = CoTaskMemAlloc(dwSize);
222 if(!lpData)
223 hr = E_OUTOFMEMORY;
226 if(SUCCEEDED(hr))
227 hr = HRESULT_FROM_WIN32(_RegGetValueW(hKey, NULL, valueName, dwExpectedType, &dwType, lpData, &dwSize));
229 if(SUCCEEDED(hr))
231 if(memcmp(lpData, lpExpectedContent, dwSize)==0)
232 hr = S_OK;
233 else
235 if(dwExpectedType == RRF_RT_REG_SZ)
236 /* if value type is REG_SZ, display expected and found values */
237 trace("not expected content of registry value\n"
238 " key: %s\n"
239 " value: %s\n"
240 " expected REG_SZ content: %s\n"
241 " found REG_SZ content: %s\n",
242 wine_dbgstr_w(keyPath),
243 wine_dbgstr_w(valueName),
244 wine_dbgstr_w(lpExpectedContent),
245 wine_dbgstr_w(lpData));
246 else
247 /* in the other case, do not display content */
248 trace("not expected content of registry value\n"
249 " key: %s\n"
250 " value: %s\n"
251 " value type: 0x%x\n",
252 wine_dbgstr_w(keyPath),
253 wine_dbgstr_w(valueName),
254 dwType);
256 hr = S_FALSE;
260 CoTaskMemFree(lpData);
261 return hr;
263 /*******************************************************************************
264 * _validateGameRegistryValues
266 * Helper function, verifies values in game's registry key
268 * Parameters:
269 * line [I] place of original call. Used only to display
270 * more useful message on test fail
271 * hKey [I] handle to game's key. Key must be opened
272 * with KEY_READ access permission
273 * keyPath [I] string with path to game's key. Used only
274 * to display more useful message on test fail
275 * gameApplicationId [I] game application identifier
276 * gameExePath [I] directory where game executable is stored
277 * gameExeName [I] full path to executable, including directory and file name
279 static void _validateGameRegistryValues(int line,
280 HKEY hKey,
281 LPCWSTR keyPath,
282 LPCGUID gameApplicationId,
283 LPCWSTR gameExePath,
284 LPCWSTR gameExeName)
286 static const WCHAR sApplicationId[] = {'A','p','p','l','i','c','a','t','i','o','n','I','d',0};
287 static const WCHAR sConfigApplicationPath[] = {'C','o','n','f','i','g','A','p','p','l','i','c','a','t','i','o','n','P','a','t','h',0};
288 static const WCHAR sConfigGDFBinaryPath[] = {'C','o','n','f','i','g','G','D','F','B','i','n','a','r','y','P','a','t','h',0};
289 static const WCHAR sDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
290 static const WCHAR sExampleGame[] = {'E','x','a','m','p','l','e',' ','G','a','m','e',0};
291 static const WCHAR sGameDescription[] = {'G','a','m','e',' ','D','e','s','c','r','i','p','t','i','o','n',0};
292 static const WCHAR sTitle[] = {'T','i','t','l','e',0};
294 HRESULT hr;
295 WCHAR sGameApplicationId[40];
297 hr = (StringFromGUID2(gameApplicationId, sGameApplicationId, sizeof(sGameApplicationId)/sizeof(sGameApplicationId[0])) ? S_OK : E_FAIL);
298 ok_(__FILE__, line)(hr == S_OK, "cannot convert game application id to string\n");
300 /* these values exist up from Vista */
301 hr = _validateRegistryValue(hKey, keyPath, sApplicationId, RRF_RT_REG_SZ, sGameApplicationId);
302 ok_(__FILE__, line)(hr==S_OK, "failed while checking registry value (error 0x%x)\n", hr);
303 hr = _validateRegistryValue(hKey, keyPath, sConfigApplicationPath, RRF_RT_REG_SZ, gameExePath);
304 ok_(__FILE__, line)(hr==S_OK, "failed while checking registry value (error 0x%x)\n", hr);
305 hr = _validateRegistryValue(hKey, keyPath, sConfigGDFBinaryPath, RRF_RT_REG_SZ, gameExeName);
306 ok_(__FILE__, line)(hr==S_OK, "failed while checking registry value (error 0x%x)\n", hr);
307 hr = _validateRegistryValue(hKey, keyPath, sTitle, RRF_RT_REG_SZ, sExampleGame);
308 ok_(__FILE__, line)(hr==S_OK, "failed while checking registry value (error 0x%x)\n", hr);
310 /* this value exists up from Win7 */
311 hr = _validateRegistryValue(hKey, keyPath, sDescription, RRF_RT_REG_SZ, sGameDescription);
312 ok_(__FILE__, line)(hr==S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)), "failed while checking registry value (error 0x%x)\n", hr);
314 /*******************************************************************************
315 * _validateGameKey
317 * Helper function, verifies current state of game's registry key with expected.
319 * Parameters:
320 * line [I] place of original call. Used only to display
321 * more useful message on test fail
322 * installScope [I] the scope which was used in AddGame/InstallGame call
323 * gameInstanceId [I] game instance identifier
324 * gameApplicationId [I] game application identifier
325 * gameExePath [I] directory where game executable is stored
326 * gameExeName [I] full path to executable, including directory and file name
327 * presenceExpected [I] is it expected that game should be currently
328 * registered or not. Should be TRUE if checking
329 * after using AddGame/InstallGame, and FALSE
330 * if checking after RemoveGame/UninstallGame
332 static void _validateGameRegistryKey(int line,
333 GAME_INSTALL_SCOPE installScope,
334 LPCGUID gameInstanceId,
335 LPCGUID gameApplicationId,
336 LPCWSTR gameExePath,
337 LPCWSTR gameExeName,
338 BOOL presenceExpected)
340 HRESULT hr;
341 LPWSTR lpRegistryPath = NULL;
342 HKEY hKey;
344 /* check key presence */
345 hr = _buildGameRegistryPath(installScope, gameInstanceId, &lpRegistryPath);
347 if(SUCCEEDED(hr))
349 hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE, lpRegistryPath, 0,
350 KEY_READ | KEY_WOW64_64KEY, &hKey));
352 if(presenceExpected)
353 ok_(__FILE__, line)(hr == S_OK,
354 "problem while trying to open registry key (HKLM): %s, error: 0x%x\n", wine_dbgstr_w(lpRegistryPath), hr);
355 else
356 ok_(__FILE__, line)(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
357 "other than expected (FILE_NOT_FOUND) error while trying to open registry key (HKLM): %s, error: 0x%x\n", wine_dbgstr_w(lpRegistryPath), hr);
360 if(SUCCEEDED(hr))
362 if(presenceExpected)
363 /* if the key exists and we expected it, let's verify its content */
364 _validateGameRegistryValues(line, hKey, lpRegistryPath, gameApplicationId, gameExePath, gameExeName);
366 RegCloseKey(hKey);
369 CoTaskMemFree(lpRegistryPath);
372 /*******************************************************************************
373 * _LoadRegistryString
375 * Helper function, loads string from registry value and allocates buffer for it
377 * Parameters:
378 * hRootKey [I] base key for reading. Should be opened
379 * with KEY_READ permission
380 * lpRegistryKey [I] name of registry key, subkey of root key
381 * lpRegistryValue [I] name of registry value
382 * lpValue [O] pointer where address of received
383 * value will be stored. Value should be
384 * freed by CoTaskMemFree call
386 static HRESULT _LoadRegistryString(HKEY hRootKey,
387 LPCWSTR lpRegistryKey,
388 LPCWSTR lpRegistryValue,
389 LPWSTR* lpValue)
391 HRESULT hr;
392 DWORD dwSize;
394 *lpValue = NULL;
396 hr = HRESULT_FROM_WIN32(_RegGetValueW(hRootKey, lpRegistryKey, lpRegistryValue,
397 RRF_RT_REG_SZ, NULL, NULL, &dwSize));
399 if(SUCCEEDED(hr))
401 *lpValue = CoTaskMemAlloc(dwSize);
402 if(!*lpValue)
403 hr = E_OUTOFMEMORY;
405 if(SUCCEEDED(hr))
406 hr = HRESULT_FROM_WIN32(_RegGetValueW(hRootKey, lpRegistryKey, lpRegistryValue,
407 RRF_RT_REG_SZ, NULL, *lpValue, &dwSize));
409 return hr;
411 /*******************************************************************************
412 * _findGameInstanceId
414 * Helper function. Searches for instance identifier of given game in given
415 * installation scope.
417 * Parameters:
418 * line [I] line to display messages
419 * sGDFBinaryPath [I] path to binary containing GDF
420 * installScope [I] game install scope to search in
421 * pInstanceId [O] instance identifier of given game
423 static void _findGameInstanceId(int line,
424 LPWSTR sGDFBinaryPath,
425 GAME_INSTALL_SCOPE installScope,
426 GUID* pInstanceId)
428 static const WCHAR sConfigGDFBinaryPath[] =
429 {'C','o','n','f','i','g','G','D','F','B','i','n','a','r','y','P','a','t','h',0};
431 HRESULT hr;
432 BOOL found = FALSE;
433 LPWSTR lpRegistryPath = NULL;
434 HKEY hRootKey;
435 DWORD dwSubKeys, dwSubKeyLen, dwMaxSubKeyLen, i;
436 LPWSTR lpName = NULL, lpValue = NULL;
438 hr = _buildGameRegistryPath(installScope, NULL, &lpRegistryPath);
439 ok_(__FILE__, line)(SUCCEEDED(hr), "cannot get registry path to given scope: %d\n", installScope);
441 if(SUCCEEDED(hr))
442 /* enumerate all subkeys of received one and search them for value "ConfigGGDFBinaryPath" */
443 hr = HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
444 lpRegistryPath, 0, KEY_READ | KEY_WOW64_64KEY, &hRootKey));
445 ok_(__FILE__, line)(SUCCEEDED(hr), "cannot open key registry key: %s\n", wine_dbgstr_w(lpRegistryPath));
447 if(SUCCEEDED(hr))
449 hr = HRESULT_FROM_WIN32(RegQueryInfoKeyW(hRootKey, NULL, NULL, NULL,
450 &dwSubKeys, &dwMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL));
452 if(SUCCEEDED(hr))
454 ++dwMaxSubKeyLen; /* for string terminator */
455 lpName = CoTaskMemAlloc(dwMaxSubKeyLen*sizeof(WCHAR));
456 if(!lpName) hr = E_OUTOFMEMORY;
457 ok_(__FILE__, line)(SUCCEEDED(hr), "cannot allocate memory for key name\n");
460 if(SUCCEEDED(hr))
462 for(i=0; i<dwSubKeys && !found; ++i)
464 dwSubKeyLen = dwMaxSubKeyLen;
465 hr = HRESULT_FROM_WIN32(RegEnumKeyExW(hRootKey, i, lpName, &dwSubKeyLen,
466 NULL, NULL, NULL, NULL));
468 if(SUCCEEDED(hr))
469 hr = _LoadRegistryString(hRootKey, lpName,
470 sConfigGDFBinaryPath, &lpValue);
472 if(SUCCEEDED(hr))
473 if(lstrcmpW(lpValue, sGDFBinaryPath)==0)
475 /* key found, let's copy instance id and exit */
476 hr = CLSIDFromString(lpName, pInstanceId);
477 ok(SUCCEEDED(hr), "cannot convert subkey to guid: %s\n",
478 wine_dbgstr_w(lpName));
480 found = TRUE;
482 CoTaskMemFree(lpValue);
486 CoTaskMemFree(lpName);
487 RegCloseKey(hRootKey);
490 CoTaskMemFree(lpRegistryPath);
491 ok_(__FILE__, line)(found==TRUE, "cannot find game with GDF path %s in scope %d\n",
492 wine_dbgstr_w(sGDFBinaryPath), installScope);
494 /*******************************************************************************
495 * Test routines
497 static void test_create(BOOL* gameExplorerAvailable, BOOL* gameExplorer2Available)
499 HRESULT hr;
501 IGameExplorer* ge = NULL;
502 IGameExplorer2* ge2 = NULL;
504 /* interface available up from Vista */
505 hr = CoCreateInstance( &CLSID_GameExplorer, NULL, CLSCTX_INPROC_SERVER, &IID_IGameExplorer, (LPVOID*)&ge);
506 if(ge)
508 ok(hr == S_OK, "IGameExplorer creating failed (result false)\n");
509 *gameExplorerAvailable = TRUE;
510 IGameExplorer_Release(ge);
512 else
513 win_skip("IGameExplorer cannot be created\n");
515 /* interface available up from Win7 */
516 hr = CoCreateInstance( &CLSID_GameExplorer, NULL, CLSCTX_INPROC_SERVER, &IID_IGameExplorer2, (LPVOID*)&ge2);
517 if(ge2)
519 ok( hr == S_OK, "IGameExplorer2 creating failed (result false)\n");
520 *gameExplorer2Available = TRUE;
521 IGameExplorer2_Release(ge2);
523 else
524 win_skip("IGameExplorer2 cannot be created\n");
527 static void test_add_remove_game(void)
529 static const GUID defaultGUID = {0x01234567, 0x89AB, 0xCDEF,
530 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}};
531 static const GUID applicationId = { 0x17A6558E, 0x60BE, 0x4078,
532 { 0xB6, 0x6F, 0x9C, 0x3A, 0xDA, 0x2A, 0x32, 0xE6 }};
534 HRESULT hr;
536 IGameExplorer* ge = NULL;
537 WCHAR sExeName[MAX_PATH];
538 WCHAR sExePath[MAX_PATH];
539 BSTR bstrExeName = NULL, bstrExePath = NULL;
540 DWORD dwExeNameLen;
541 GUID guid;
543 hr = CoCreateInstance(&CLSID_GameExplorer, NULL, CLSCTX_INPROC_SERVER, &IID_IGameExplorer, (LPVOID*) & ge);
544 ok(ge != NULL, "cannot create coclass IGameExplorer\n");
545 ok(hr == S_OK, "cannot create coclass IGameExplorer\n");
547 if(ge)
549 /* prepare path to binary */
550 dwExeNameLen = GetModuleFileNameW(NULL, sExeName, sizeof (sExeName) / sizeof (sExeName[0]));
551 ok(dwExeNameLen != 0, "GetModuleFileNameW returned invalid value\n");
552 lstrcpynW(sExePath, sExeName, StrRChrW(sExeName, NULL, '\\') - sExeName + 1);
553 bstrExeName = SysAllocString(sExeName);
554 ok(bstrExeName != NULL, "cannot allocate string for exe name\n");
555 bstrExePath = SysAllocString(sExePath);
556 ok(bstrExePath != NULL, "cannot allocate string for exe path\n");
558 if(bstrExeName && bstrExePath)
560 trace("prepared EXE name: %s\n", wine_dbgstr_w(bstrExeName));
561 trace("prepared EXE path: %s\n", wine_dbgstr_w(bstrExePath));
564 /* try to register game with provided guid */
565 memcpy(&guid, &defaultGUID, sizeof (guid));
567 hr = IGameExplorer_AddGame(ge, bstrExeName, bstrExePath, GIS_CURRENT_USER, &guid);
568 ok(SUCCEEDED(hr), "IGameExplorer::AddGame failed (error 0x%08x)\n", hr);
569 ok(memcmp(&guid, &defaultGUID, sizeof (guid)) == 0, "AddGame unexpectedly modified GUID\n");
571 if(SUCCEEDED(hr))
573 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, TRUE);
575 hr = IGameExplorer_RemoveGame(ge, guid);
576 ok(SUCCEEDED(hr), "IGameExplorer::RemoveGame failed (error 0x%08x)\n", hr);
579 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, FALSE);
582 /* try to register game with empty guid */
583 memcpy(&guid, &GUID_NULL, sizeof (guid));
585 hr = IGameExplorer_AddGame(ge, bstrExeName, bstrExePath, GIS_CURRENT_USER, &guid);
586 ok(SUCCEEDED(hr), "IGameExplorer::AddGame failed (error 0x%08x)\n", hr);
587 ok(memcmp(&guid, &GUID_NULL, sizeof (guid)) != 0, "AddGame did not modify GUID\n");
589 if(SUCCEEDED(hr))
591 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, TRUE);
593 hr = IGameExplorer_RemoveGame(ge, guid);
594 ok(SUCCEEDED(hr), "IGameExplorer::RemoveGame failed (error 0x%08x)\n", hr);
597 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, FALSE);
600 /* free allocated resources */
601 SysFreeString(bstrExePath);
602 SysFreeString(bstrExeName);
604 IGameExplorer_Release(ge);
608 static void test_install_uninstall_game(void)
610 static const GUID applicationId = { 0x17A6558E, 0x60BE, 0x4078,
611 { 0xB6, 0x6F, 0x9C, 0x3A, 0xDA, 0x2A, 0x32, 0xE6 }};
613 HRESULT hr;
615 IGameExplorer2* ge2 = NULL;
616 WCHAR sExeName[MAX_PATH];
617 WCHAR sExePath[MAX_PATH];
618 DWORD dwExeNameLen;
619 GUID guid;
621 hr = CoCreateInstance(&CLSID_GameExplorer, NULL, CLSCTX_INPROC_SERVER, &IID_IGameExplorer2, (LPVOID*)&ge2);
622 ok(ge2 != NULL, "cannot create coclass IGameExplorer2\n");
623 ok(hr == S_OK, "cannot create coclass IGameExplorer2\n");
625 if(ge2)
627 /* prepare path to binary */
628 dwExeNameLen = GetModuleFileNameW(NULL, sExeName, sizeof (sExeName) / sizeof (sExeName[0]));
629 ok(dwExeNameLen != 0, "GetModuleFileNameW returned invalid value\n");
630 lstrcpynW(sExePath, sExeName, StrRChrW(sExeName, NULL, '\\') - sExeName + 1);
632 trace("prepared EXE name: %s\n", wine_dbgstr_w(sExeName));
633 trace("prepared EXE path: %s\n", wine_dbgstr_w(sExePath));
636 hr = IGameExplorer2_InstallGame(ge2, sExeName, sExePath, GIS_CURRENT_USER);
637 ok(SUCCEEDED(hr), "IGameExplorer2::InstallGame failed (error 0x%08x)\n", hr);
638 /* in comparison to AddGame, InstallGame does not return instance ID,
639 * so we need to find it manually */
640 _findGameInstanceId(__LINE__, sExeName, GIS_CURRENT_USER, &guid);
642 if(SUCCEEDED(hr))
644 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, TRUE);
646 hr = IGameExplorer2_UninstallGame(ge2, sExeName);
647 ok(SUCCEEDED(hr), "IGameExplorer2::UninstallGame failed (error 0x%08x)\n", hr);
650 _validateGameRegistryKey(__LINE__, GIS_CURRENT_USER, &guid, &applicationId, sExePath, sExeName, FALSE);
652 IGameExplorer2_Release(ge2);
656 static void run_tests(void)
658 BOOL gameExplorerAvailable = FALSE;
659 BOOL gameExplorer2Available = FALSE;
661 test_create(&gameExplorerAvailable, &gameExplorer2Available);
663 if(gameExplorerAvailable)
664 test_add_remove_game();
666 if(gameExplorer2Available)
667 test_install_uninstall_game();
670 START_TEST(gameexplorer)
672 if(_loadDynamicRoutines())
674 HRESULT hr;
676 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
677 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
678 trace("Running multithreaded tests.\n");
679 run_tests();
680 if(SUCCEEDED(hr))
681 CoUninitialize();
683 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
684 ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
685 trace("Running apartment threaded tests.\n");
686 run_tests();
687 if(SUCCEEDED(hr))
688 CoUninitialize();
690 else
691 /* this is not a failure, because both procedures loaded by address
692 * are always available on systems which has gameux.dll */
693 win_skip("too old system, cannot load required dynamic procedures\n");