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
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 /*******************************************************************************
46 * Helper function, prepares pointers to system procedures which may be not
47 * available on older operating systems.
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
;
64 /*******************************************************************************
65 * _buildGameRegistryPath
67 * Helper function, builds registry path to key, where game's data are stored
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};
90 PTOKEN_USER pTokenUser
= 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());
107 if(!GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) &&
108 GetLastError()!=ERROR_INSUFFICIENT_BUFFER
)
109 hr
= HRESULT_FROM_WIN32(GetLastError());
113 pTokenUser
= CoTaskMemAlloc(dwLength
);
119 if(!GetTokenInformation(hToken
, TokenUser
, (LPVOID
)pTokenUser
, dwLength
, &dwLength
))
120 hr
= HRESULT_FROM_WIN32(GetLastError());
123 if(!_ConvertSidToStringSidW(pTokenUser
->User
.Sid
, &lpSID
))
124 hr
= HRESULT_FROM_WIN32(GetLastError());
128 lstrcatW(sRegistryPath
, lpSID
);
132 CoTaskMemFree(pTokenUser
);
136 else if(installScope
== GIS_ALL_USERS
)
137 /* build registry path without SID */
138 lstrcatW(sRegistryPath
, sGames
);
142 /* put game's instance id on the end of path, but only if id was passes */
146 hr
= (StringFromGUID2(gameInstanceId
, sInstanceId
, sizeof(sInstanceId
)/sizeof(sInstanceId
[0])) ? S_OK
: E_FAIL
);
150 lstrcatW(sRegistryPath
, sBackslash
);
151 lstrcatW(sRegistryPath
, sInstanceId
);
157 *lpRegistryPath
= CoTaskMemAlloc((lstrlenW(sRegistryPath
)+1)*sizeof(WCHAR
));
163 lstrcpyW(*lpRegistryPath
, sRegistryPath
);
167 /*******************************************************************************
168 * _validateRegistryValue
170 * Helper function, verifies single registry value with expected
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
184 * S_OK value exists and contains expected data
185 * S_FALSE value exists, but contains other data
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(
199 DWORD dwExpectedType
,
200 LPCVOID lpExpectedContent
)
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"
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
),
221 lpData
= CoTaskMemAlloc(dwSize
);
227 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hKey
, NULL
, valueName
, dwExpectedType
, &dwType
, lpData
, &dwSize
));
231 if(memcmp(lpData
, lpExpectedContent
, dwSize
)==0)
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"
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
));
247 /* in the other case, do not display content */
248 trace("not expected content of registry value\n"
251 " value type: 0x%x\n",
252 wine_dbgstr_w(keyPath
),
253 wine_dbgstr_w(valueName
),
260 CoTaskMemFree(lpData
);
263 /*******************************************************************************
264 * _validateGameRegistryValues
266 * Helper function, verifies values in game's registry key
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
,
282 LPCGUID gameApplicationId
,
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};
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 /*******************************************************************************
317 * Helper function, verifies current state of game's registry key with expected.
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
,
338 BOOL presenceExpected
)
341 LPWSTR lpRegistryPath
= NULL
;
344 /* check key presence */
345 hr
= _buildGameRegistryPath(installScope
, gameInstanceId
, &lpRegistryPath
);
349 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, lpRegistryPath
, 0,
350 KEY_READ
| KEY_WOW64_64KEY
, &hKey
));
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
);
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
);
363 /* if the key exists and we expected it, let's verify its content */
364 _validateGameRegistryValues(line
, hKey
, lpRegistryPath
, gameApplicationId
, gameExePath
, gameExeName
);
369 CoTaskMemFree(lpRegistryPath
);
372 /*******************************************************************************
373 * _LoadRegistryString
375 * Helper function, loads string from registry value and allocates buffer for it
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
,
396 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hRootKey
, lpRegistryKey
, lpRegistryValue
,
397 RRF_RT_REG_SZ
, NULL
, NULL
, &dwSize
));
401 *lpValue
= CoTaskMemAlloc(dwSize
);
406 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hRootKey
, lpRegistryKey
, lpRegistryValue
,
407 RRF_RT_REG_SZ
, NULL
, *lpValue
, &dwSize
));
411 /*******************************************************************************
412 * _findGameInstanceId
414 * Helper function. Searches for instance identifier of given game in given
415 * installation scope.
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
,
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};
433 LPWSTR lpRegistryPath
= NULL
;
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
);
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
));
449 hr
= HRESULT_FROM_WIN32(RegQueryInfoKeyW(hRootKey
, NULL
, NULL
, NULL
,
450 &dwSubKeys
, &dwMaxSubKeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
));
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");
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
));
469 hr
= _LoadRegistryString(hRootKey
, lpName
,
470 sConfigGDFBinaryPath
, &lpValue
);
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
));
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 /*******************************************************************************
497 static void test_create(BOOL
* gameExplorerAvailable
, BOOL
* gameExplorer2Available
)
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
);
508 ok(hr
== S_OK
, "IGameExplorer creating failed (result false)\n");
509 *gameExplorerAvailable
= TRUE
;
510 IGameExplorer_Release(ge
);
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
);
519 ok( hr
== S_OK
, "IGameExplorer2 creating failed (result false)\n");
520 *gameExplorer2Available
= TRUE
;
521 IGameExplorer2_Release(ge2
);
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 }};
536 IGameExplorer
* ge
= NULL
;
537 WCHAR sExeName
[MAX_PATH
];
538 WCHAR sExePath
[MAX_PATH
];
539 BSTR bstrExeName
= NULL
, bstrExePath
= NULL
;
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");
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");
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");
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 }};
615 IGameExplorer2
* ge2
= NULL
;
616 WCHAR sExeName
[MAX_PATH
];
617 WCHAR sExePath
[MAX_PATH
];
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");
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
);
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())
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");
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");
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");