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 /* function from Shell32, not defined in header */
37 extern BOOL WINAPI
GUIDFromStringW(LPCWSTR psz
, LPGUID pguid
);
39 /*******************************************************************************
40 * Pointers used instead of direct calls. These procedures are not available on
41 * older system, which causes problem while loading test binary.
43 static BOOL
WINAPI (*_ConvertSidToStringSidW
)(PSID
,LPWSTR
*);
44 static LONG
WINAPI (*_RegGetValueW
)(HKEY
,LPCWSTR
,LPCWSTR
,DWORD
,LPDWORD
,PVOID
,LPDWORD
);
46 /*******************************************************************************
49 * Helper function, prepares pointers to system procedures which may be not
50 * available on older operating systems.
53 * TRUE procedures were loaded successfully
54 * FALSE procedures were not loaded successfully
56 static BOOL
_loadDynamicRoutines(void)
58 HMODULE hAdvapiModule
= GetModuleHandleA( "advapi32.dll" );
60 _ConvertSidToStringSidW
= (LPVOID
)GetProcAddress(hAdvapiModule
, "ConvertSidToStringSidW");
61 if (!_ConvertSidToStringSidW
) return FALSE
;
62 _RegGetValueW
= (LPVOID
)GetProcAddress(hAdvapiModule
, "RegGetValueW");
63 if (!_RegGetValueW
) return FALSE
;
67 /*******************************************************************************
68 * _buildGameRegistryPath
70 * Helper function, builds registry path to key, where game's data are stored
73 * installScope [I] the scope which was used in AddGame/InstallGame call
74 * gameInstanceId [I] game instance GUID. If NULL, then only
75 * path to scope is returned
76 * lpRegistryPath [O] pointer which will receive address to string
77 * containing expected registry path. Path
78 * is relative to HKLM registry key. It
79 * must be freed by calling CoTaskMemFree
81 static HRESULT
_buildGameRegistryPath(GAME_INSTALL_SCOPE installScope
,
82 LPCGUID gameInstanceId
,
83 LPWSTR
* lpRegistryPath
)
85 static const WCHAR sGameUxRegistryPath
[] = {'S','O','F','T','W','A','R','E','\\',
86 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
87 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','G','a','m','e','U','X',0};
88 static const WCHAR sGames
[] = {'G','a','m','e','s',0};
89 static const WCHAR sBackslash
[] = {'\\',0};
93 PTOKEN_USER pTokenUser
= NULL
;
96 WCHAR sInstanceId
[40];
97 WCHAR sRegistryPath
[8192];
99 lstrcpyW(sRegistryPath
, sGameUxRegistryPath
);
100 lstrcatW(sRegistryPath
, sBackslash
);
102 if(installScope
== GIS_CURRENT_USER
)
104 /* build registry path containing user's SID */
105 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
106 hr
= HRESULT_FROM_WIN32(GetLastError());
110 if(!GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwLength
) &&
111 GetLastError()!=ERROR_INSUFFICIENT_BUFFER
)
112 hr
= HRESULT_FROM_WIN32(GetLastError());
116 pTokenUser
= CoTaskMemAlloc(dwLength
);
122 if(!GetTokenInformation(hToken
, TokenUser
, (LPVOID
)pTokenUser
, dwLength
, &dwLength
))
123 hr
= HRESULT_FROM_WIN32(GetLastError());
126 if(!_ConvertSidToStringSidW(pTokenUser
->User
.Sid
, &lpSID
))
127 hr
= HRESULT_FROM_WIN32(GetLastError());
131 lstrcatW(sRegistryPath
, lpSID
);
135 CoTaskMemFree(pTokenUser
);
139 else if(installScope
== GIS_ALL_USERS
)
140 /* build registry path without SID */
141 lstrcatW(sRegistryPath
, sGames
);
145 /* put game's instance id on the end of path, but only if id was passes */
149 hr
= (StringFromGUID2(gameInstanceId
, sInstanceId
, sizeof(sInstanceId
)/sizeof(sInstanceId
[0])) ? S_OK
: E_FAIL
);
153 lstrcatW(sRegistryPath
, sBackslash
);
154 lstrcatW(sRegistryPath
, sInstanceId
);
160 *lpRegistryPath
= CoTaskMemAlloc((lstrlenW(sRegistryPath
)+1)*sizeof(WCHAR
));
166 lstrcpyW(*lpRegistryPath
, sRegistryPath
);
170 /*******************************************************************************
171 * _validateRegistryValue
173 * Helper function, verifies single registry value with expected
176 * hKey [I] handle to game's key. Key must be opened
177 * keyPath [I] string with path to game's key. Used only
178 * to display more useful message on test fail
179 * valueName [I] name of value to check
180 * dwExpectedType [I] expected type of value. It should be
181 * one of RRF_RT_* flags
182 * lpExpectedContent [I] expected content of value. It should be
183 * pointer to variable with same type as
184 * passed in dwExpectedType
187 * S_OK value exists and contains expected data
188 * S_FALSE value exists, but contains other data
190 * E_OUTOFMEMORY allocation problem
191 * HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
192 * value does not exist
194 * Note: this function returns error codes instead of failing test case, because
195 * it is sometimes expected that given value may not exist on some systems, or
196 * contain other data.
198 static HRESULT
_validateRegistryValue(
202 DWORD dwExpectedType
,
203 LPCVOID lpExpectedContent
)
206 DWORD dwType
, dwSize
;
207 LPVOID lpData
= NULL
;
209 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hKey
, NULL
, valueName
, dwExpectedType
, &dwType
, NULL
, &dwSize
));
210 if(FAILED(hr
)) trace("registry value cannot be opened\n"
213 " expected type: 0x%x\n"
214 " found type: 0x%x\n"
215 " result code: 0x%0x\n",
216 wine_dbgstr_w(keyPath
),
217 wine_dbgstr_w(valueName
),
224 lpData
= CoTaskMemAlloc(dwSize
);
230 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hKey
, NULL
, valueName
, dwExpectedType
, &dwType
, lpData
, &dwSize
));
234 if(memcmp(lpData
, lpExpectedContent
, dwSize
)==0)
238 if(dwExpectedType
== RRF_RT_REG_SZ
)
239 /* if value type is REG_SZ, display expected and found values */
240 trace("not expected content of registry value\n"
243 " expected REG_SZ content: %s\n"
244 " found REG_SZ content: %s\n",
245 wine_dbgstr_w(keyPath
),
246 wine_dbgstr_w(valueName
),
247 wine_dbgstr_w(lpExpectedContent
),
248 wine_dbgstr_w(lpData
));
250 /* in the other case, do not display content */
251 trace("not expected content of registry value\n"
254 " value type: 0x%x\n",
255 wine_dbgstr_w(keyPath
),
256 wine_dbgstr_w(valueName
),
263 CoTaskMemFree(lpData
);
266 /*******************************************************************************
267 * _validateGameRegistryValues
269 * Helper function, verifies values in game's registry key
272 * line [I] place of original call. Used only to display
273 * more useful message on test fail
274 * hKey [I] handle to game's key. Key must be opened
275 * with KEY_READ access permission
276 * keyPath [I] string with path to game's key. Used only
277 * to display more useful message on test fail
278 * gameApplicationId [I] game application identifier
279 * gameExePath [I] directory where game executable is stored
280 * gameExeName [I] full path to executable, including directory and file name
282 static void _validateGameRegistryValues(int line
,
285 LPCGUID gameApplicationId
,
289 static const WCHAR sApplicationId
[] = {'A','p','p','l','i','c','a','t','i','o','n','I','d',0};
290 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};
291 static const WCHAR sConfigGDFBinaryPath
[] = {'C','o','n','f','i','g','G','D','F','B','i','n','a','r','y','P','a','t','h',0};
292 static const WCHAR sDescription
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
293 static const WCHAR sExampleGame
[] = {'E','x','a','m','p','l','e',' ','G','a','m','e',0};
294 static const WCHAR sGameDescription
[] = {'G','a','m','e',' ','D','e','s','c','r','i','p','t','i','o','n',0};
295 static const WCHAR sTitle
[] = {'T','i','t','l','e',0};
298 WCHAR sGameApplicationId
[40];
300 hr
= (StringFromGUID2(gameApplicationId
, sGameApplicationId
, sizeof(sGameApplicationId
)/sizeof(sGameApplicationId
[0])) ? S_OK
: E_FAIL
);
301 ok_(__FILE__
, line
)(hr
== S_OK
, "cannot convert game application id to string\n");
303 /* these values exist up from Vista */
304 hr
= _validateRegistryValue(hKey
, keyPath
, sApplicationId
, RRF_RT_REG_SZ
, sGameApplicationId
);
305 ok_(__FILE__
, line
)(hr
==S_OK
, "failed while checking registry value (error 0x%x)\n", hr
);
306 hr
= _validateRegistryValue(hKey
, keyPath
, sConfigApplicationPath
, RRF_RT_REG_SZ
, gameExePath
);
307 ok_(__FILE__
, line
)(hr
==S_OK
, "failed while checking registry value (error 0x%x)\n", hr
);
308 hr
= _validateRegistryValue(hKey
, keyPath
, sConfigGDFBinaryPath
, RRF_RT_REG_SZ
, gameExeName
);
309 ok_(__FILE__
, line
)(hr
==S_OK
, "failed while checking registry value (error 0x%x)\n", hr
);
310 hr
= _validateRegistryValue(hKey
, keyPath
, sTitle
, RRF_RT_REG_SZ
, sExampleGame
);
311 ok_(__FILE__
, line
)(hr
==S_OK
, "failed while checking registry value (error 0x%x)\n", hr
);
313 /* this value exists up from Win7 */
314 hr
= _validateRegistryValue(hKey
, keyPath
, sDescription
, RRF_RT_REG_SZ
, sGameDescription
);
315 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
);
317 /*******************************************************************************
320 * Helper function, verifies current state of game's registry key with expected.
323 * line [I] place of original call. Used only to display
324 * more useful message on test fail
325 * installScope [I] the scope which was used in AddGame/InstallGame call
326 * gameInstanceId [I] game instance identifier
327 * gameApplicationId [I] game application identifier
328 * gameExePath [I] directory where game executable is stored
329 * gameExeName [I] full path to executable, including directory and file name
330 * presenceExpected [I] is it expected that game should be currently
331 * registered or not. Should be TRUE if checking
332 * after using AddGame/InstallGame, and FALSE
333 * if checking after RemoveGame/UninstallGame
335 static void _validateGameRegistryKey(int line
,
336 GAME_INSTALL_SCOPE installScope
,
337 LPCGUID gameInstanceId
,
338 LPCGUID gameApplicationId
,
341 BOOL presenceExpected
)
344 LPWSTR lpRegistryPath
= NULL
;
347 /* check key presence */
348 hr
= _buildGameRegistryPath(installScope
, gameInstanceId
, &lpRegistryPath
);
352 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, lpRegistryPath
, 0,
353 KEY_READ
| KEY_WOW64_64KEY
, &hKey
));
356 ok_(__FILE__
, line
)(hr
== S_OK
,
357 "problem while trying to open registry key (HKLM): %s, error: 0x%x\n", wine_dbgstr_w(lpRegistryPath
), hr
);
359 ok_(__FILE__
, line
)(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
),
360 "other than expected (FILE_NOT_FOUND) error while trying to open registry key (HKLM): %s, error: 0x%x\n", wine_dbgstr_w(lpRegistryPath
), hr
);
366 /* if the key exists and we expected it, let's verify it's content */
367 _validateGameRegistryValues(line
, hKey
, lpRegistryPath
, gameApplicationId
, gameExePath
, gameExeName
);
372 CoTaskMemFree(lpRegistryPath
);
375 /*******************************************************************************
376 * _LoadRegistryString
378 * Helper function, loads string from registry value and allocates buffer for it
381 * hRootKey [I] base key for reading. Should be opened
382 * with KEY_READ permission
383 * lpRegistryKey [I] name of registry key, subkey of root key
384 * lpRegistryValue [I] name of registry value
385 * lpValue [O] pointer where address of received
386 * value will be stored. Value should be
387 * freed by CoTaskMemFree call
389 static HRESULT
_LoadRegistryString(HKEY hRootKey
,
390 LPCWSTR lpRegistryKey
,
391 LPCWSTR lpRegistryValue
,
399 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hRootKey
, lpRegistryKey
, lpRegistryValue
,
400 RRF_RT_REG_SZ
, NULL
, NULL
, &dwSize
));
404 *lpValue
= CoTaskMemAlloc(dwSize
);
409 hr
= HRESULT_FROM_WIN32(_RegGetValueW(hRootKey
, lpRegistryKey
, lpRegistryValue
,
410 RRF_RT_REG_SZ
, NULL
, *lpValue
, &dwSize
));
414 /*******************************************************************************
415 * _findGameInstanceId
417 * Helper function. Searches for instance identifier of given game in given
418 * installation scope.
421 * line [I] line to display messages
422 * sGDFBinaryPath [I] path to binary containing GDF
423 * installScope [I] game install scope to search in
424 * pInstanceId [O] instance identifier of given game
426 static void _findGameInstanceId(int line
,
427 LPWSTR sGDFBinaryPath
,
428 GAME_INSTALL_SCOPE installScope
,
431 static const WCHAR sConfigGDFBinaryPath
[] =
432 {'C','o','n','f','i','g','G','D','F','B','i','n','a','r','y','P','a','t','h',0};
436 LPWSTR lpRegistryPath
= NULL
;
438 DWORD dwSubKeys
, dwSubKeyLen
, dwMaxSubKeyLen
, i
;
439 LPWSTR lpName
= NULL
, lpValue
= NULL
;
441 hr
= _buildGameRegistryPath(installScope
, NULL
, &lpRegistryPath
);
442 ok_(__FILE__
, line
)(SUCCEEDED(hr
), "cannot get registry path to given scope: %d\n", installScope
);
445 /* enumerate all subkeys of received one and search them for value "ConfigGGDFBinaryPath" */
446 hr
= HRESULT_FROM_WIN32(RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
447 lpRegistryPath
, 0, KEY_READ
| KEY_WOW64_64KEY
, &hRootKey
));
448 ok_(__FILE__
, line
)(SUCCEEDED(hr
), "cannot open key registry key: %s\n", wine_dbgstr_w(lpRegistryPath
));
452 hr
= HRESULT_FROM_WIN32(RegQueryInfoKeyW(hRootKey
, NULL
, NULL
, NULL
,
453 &dwSubKeys
, &dwMaxSubKeyLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
));
457 ++dwMaxSubKeyLen
; /* for string terminator */
458 lpName
= CoTaskMemAlloc(dwMaxSubKeyLen
*sizeof(WCHAR
));
459 if(!lpName
) hr
= E_OUTOFMEMORY
;
460 ok_(__FILE__
, line
)(SUCCEEDED(hr
), "cannot allocate memory for key name");
465 for(i
=0; i
<dwSubKeys
&& !found
; ++i
)
467 dwSubKeyLen
= dwMaxSubKeyLen
;
468 hr
= HRESULT_FROM_WIN32(RegEnumKeyExW(hRootKey
, i
, lpName
, &dwSubKeyLen
,
469 NULL
, NULL
, NULL
, NULL
));
472 hr
= _LoadRegistryString(hRootKey
, lpName
,
473 sConfigGDFBinaryPath
, &lpValue
);
476 if(lstrcmpW(lpValue
, sGDFBinaryPath
)==0)
478 /* key found, let's copy instance id and exit */
479 hr
= (GUIDFromStringW(lpName
, pInstanceId
) ? S_OK
: E_FAIL
);
480 ok(SUCCEEDED(hr
), "cannot convert subkey to guid: %s\n",
481 wine_dbgstr_w(lpName
));
485 CoTaskMemFree(lpValue
);
489 CoTaskMemFree(lpName
);
490 RegCloseKey(hRootKey
);
493 CoTaskMemFree(lpRegistryPath
);
494 ok_(__FILE__
, line
)(found
==TRUE
, "cannot find game with GDF path %s in scope %d\n",
495 wine_dbgstr_w(sGDFBinaryPath
), installScope
);
497 /*******************************************************************************
500 static void test_create(BOOL
* gameExplorerAvailable
, BOOL
* gameExplorer2Available
)
504 IGameExplorer
* ge
= NULL
;
505 IGameExplorer2
* ge2
= NULL
;
507 /* interface available up from Vista */
508 hr
= CoCreateInstance( &CLSID_GameExplorer
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGameExplorer
, (LPVOID
*)&ge
);
511 ok(hr
== S_OK
, "IGameExplorer creating failed (result false)\n");
512 *gameExplorerAvailable
= TRUE
;
513 IGameExplorer_Release(ge
);
516 win_skip("IGameExplorer cannot be created\n");
518 /* interface available up from Win7 */
519 hr
= CoCreateInstance( &CLSID_GameExplorer
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGameExplorer2
, (LPVOID
*)&ge2
);
522 ok( hr
== S_OK
, "IGameExplorer2 creating failed (result false)\n");
523 *gameExplorer2Available
= TRUE
;
524 IGameExplorer2_Release(ge2
);
527 win_skip("IGameExplorer2 cannot be created\n");
530 static void test_add_remove_game(void)
532 static const GUID defaultGUID
= {0x01234567, 0x89AB, 0xCDEF,
533 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}};
534 static const GUID applicationId
= { 0x17A6558E, 0x60BE, 0x4078,
535 { 0xB6, 0x6F, 0x9C, 0x3A, 0xDA, 0x2A, 0x32, 0xE6 }};
539 IGameExplorer
* ge
= NULL
;
540 WCHAR sExeName
[MAX_PATH
];
541 WCHAR sExePath
[MAX_PATH
];
542 BSTR bstrExeName
= NULL
, bstrExePath
= NULL
;
546 hr
= CoCreateInstance(&CLSID_GameExplorer
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGameExplorer
, (LPVOID
*) & ge
);
547 ok(ge
!= NULL
, "cannot create coclass IGameExplorer\n");
548 ok(hr
== S_OK
, "cannot create coclass IGameExplorer\n");
552 /* prepare path to binary */
553 dwExeNameLen
= GetModuleFileNameW(NULL
, sExeName
, sizeof (sExeName
) / sizeof (sExeName
[0]));
554 ok(dwExeNameLen
!= 0, "GetModuleFileNameW returned invalid value\n");
555 lstrcpynW(sExePath
, sExeName
, StrRChrW(sExeName
, NULL
, '\\') - sExeName
+ 1);
556 bstrExeName
= SysAllocString(sExeName
);
557 ok(bstrExeName
!= NULL
, "cannot allocate string for exe name\n");
558 bstrExePath
= SysAllocString(sExePath
);
559 ok(bstrExePath
!= NULL
, "cannot allocate string for exe path\n");
561 if(bstrExeName
&& bstrExePath
)
563 trace("prepared EXE name: %s\n", wine_dbgstr_w(bstrExeName
));
564 trace("prepared EXE path: %s\n", wine_dbgstr_w(bstrExePath
));
567 /* try to register game with provided guid */
568 memcpy(&guid
, &defaultGUID
, sizeof (guid
));
570 hr
= IGameExplorer_AddGame(ge
, bstrExeName
, bstrExePath
, GIS_CURRENT_USER
, &guid
);
571 ok(SUCCEEDED(hr
), "IGameExplorer::AddGame failed (error 0x%08x)\n", hr
);
572 ok(memcmp(&guid
, &defaultGUID
, sizeof (guid
)) == 0, "AddGame unexpectedly modified GUID\n");
576 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, TRUE
);
578 hr
= IGameExplorer_RemoveGame(ge
, guid
);
579 ok(SUCCEEDED(hr
), "IGameExplorer::RemoveGame failed (error 0x%08x)\n", hr
);
582 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, FALSE
);
585 /* try to register game with empty guid */
586 memcpy(&guid
, &GUID_NULL
, sizeof (guid
));
588 hr
= IGameExplorer_AddGame(ge
, bstrExeName
, bstrExePath
, GIS_CURRENT_USER
, &guid
);
589 ok(SUCCEEDED(hr
), "IGameExplorer::AddGame failed (error 0x%08x)\n", hr
);
590 ok(memcmp(&guid
, &GUID_NULL
, sizeof (guid
)) != 0, "AddGame did not modify GUID\n");
594 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, TRUE
);
596 hr
= IGameExplorer_RemoveGame(ge
, guid
);
597 ok(SUCCEEDED(hr
), "IGameExplorer::RemoveGame failed (error 0x%08x)\n", hr
);
600 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, FALSE
);
603 /* free allocated resources */
604 SysFreeString(bstrExePath
);
605 SysFreeString(bstrExeName
);
607 IGameExplorer_Release(ge
);
611 static void test_install_uninstall_game(void)
613 static const GUID applicationId
= { 0x17A6558E, 0x60BE, 0x4078,
614 { 0xB6, 0x6F, 0x9C, 0x3A, 0xDA, 0x2A, 0x32, 0xE6 }};
618 IGameExplorer2
* ge2
= NULL
;
619 WCHAR sExeName
[MAX_PATH
];
620 WCHAR sExePath
[MAX_PATH
];
624 hr
= CoCreateInstance(&CLSID_GameExplorer
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGameExplorer2
, (LPVOID
*)&ge2
);
625 ok(ge2
!= NULL
, "cannot create coclass IGameExplorer2\n");
626 ok(hr
== S_OK
, "cannot create coclass IGameExplorer2\n");
630 /* prepare path to binary */
631 dwExeNameLen
= GetModuleFileNameW(NULL
, sExeName
, sizeof (sExeName
) / sizeof (sExeName
[0]));
632 ok(dwExeNameLen
!= 0, "GetModuleFileNameW returned invalid value\n");
633 lstrcpynW(sExePath
, sExeName
, StrRChrW(sExeName
, NULL
, '\\') - sExeName
+ 1);
635 trace("prepared EXE name: %s\n", wine_dbgstr_w(sExeName
));
636 trace("prepared EXE path: %s\n", wine_dbgstr_w(sExePath
));
639 hr
= IGameExplorer2_InstallGame(ge2
, sExeName
, sExePath
, GIS_CURRENT_USER
);
640 ok(SUCCEEDED(hr
), "IGameExplorer2::InstallGame failed (error 0x%08x)\n", hr
);
641 /* in comparison to AddGame, InstallGame does not return instance ID,
642 * so we need to find it manually */
643 _findGameInstanceId(__LINE__
, sExeName
, GIS_CURRENT_USER
, &guid
);
647 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, TRUE
);
649 hr
= IGameExplorer2_UninstallGame(ge2
, sExeName
);
650 ok(SUCCEEDED(hr
), "IGameExplorer2::UninstallGame failed (error 0x%08x)\n", hr
);
653 _validateGameRegistryKey(__LINE__
, GIS_CURRENT_USER
, &guid
, &applicationId
, sExePath
, sExeName
, FALSE
);
655 IGameExplorer2_Release(ge2
);
659 static void run_tests(void)
661 BOOL gameExplorerAvailable
= FALSE
;
662 BOOL gameExplorer2Available
= FALSE
;
664 test_create(&gameExplorerAvailable
, &gameExplorer2Available
);
666 if(gameExplorerAvailable
)
667 test_add_remove_game();
669 if(gameExplorer2Available
)
670 test_install_uninstall_game();
673 START_TEST(gameexplorer
)
675 if(_loadDynamicRoutines())
679 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
680 ok(hr
== S_OK
, "Failed to initialize COM, hr %#x.\n", hr
);
681 trace("Running apartment threaded tests.\n");
686 hr
= CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
687 ok(hr
== S_OK
, "Failed to initialize COM, hr %#x.\n", hr
);
688 trace("Running multithreaded tests.\n");
694 /* this is not a failure, because both procedures loaded by address
695 * are always available on systems which has gameux.dll */
696 win_skip("too old system, cannot load required dynamic procedures\n");