Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1081 lines
41 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Interface to Xbox 360 system functions. Helps deal with the async system and Live
  4. // functions by either providing a handle for the caller to check results or handling
  5. // automatic cleanup of the async data when the caller doesn't care about the results.
  6. //
  7. //=====================================================================================//
  8. #include "host.h"
  9. #include "tier3/tier3.h"
  10. #include "vgui/ILocalize.h"
  11. #include "ixboxsystem.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. static wchar_t g_szModSaveContainerDisplayName[XCONTENT_MAX_DISPLAYNAME_LENGTH] = L"";
  15. static char g_szModSaveContainerName[XCONTENT_MAX_FILENAME_LENGTH] = "";
  16. //-----------------------------------------------------------------------------
  17. // Implementation of IXboxSystem interface
  18. //-----------------------------------------------------------------------------
  19. class CXboxSystem : public IXboxSystem
  20. {
  21. public:
  22. CXboxSystem( void );
  23. virtual ~CXboxSystem( void );
  24. virtual AsyncHandle_t CreateAsyncHandle( void );
  25. virtual void ReleaseAsyncHandle( AsyncHandle_t handle );
  26. virtual int GetOverlappedResult( AsyncHandle_t handle, uint *pResultCode, bool bWait );
  27. virtual void CancelOverlappedOperation( AsyncHandle_t handle );
  28. // Save/Load
  29. virtual void GetModSaveContainerNames( const char *pchModName, const wchar_t **ppchDisplayName, const char **ppchName );
  30. virtual uint GetContainerRemainingSpace( void );
  31. virtual bool DeviceCapacityAdequate( DWORD nDeviceID, const char *pModName );
  32. virtual DWORD DiscoverUserData( DWORD nUserID, const char *pModName );
  33. // XUI
  34. virtual bool ShowDeviceSelector( bool bForce, uint *pStorageID, AsyncHandle_t *pHandle );
  35. virtual void ShowSigninUI( uint nPanes, uint nFlags );
  36. // Rich Presence and Matchmaking
  37. virtual int UserSetContext( uint nUserIdx, uint nContextID, uint nContextValue, bool bAsync, AsyncHandle_t *pHandle);
  38. virtual int UserSetProperty( uint nUserIndex, uint nPropertyId, uint nBytes, const void *pvValue, bool bAsync, AsyncHandle_t *pHandle );
  39. // Matchmaking
  40. virtual int CreateSession( uint nFlags, uint nUserIdx, uint nMaxPublicSlots, uint nMaxPrivateSlots, uint64 *pNonce, void *pSessionInfo, XboxHandle_t *pSessionHandle, bool bAsync, AsyncHandle_t *pAsyncHandle );
  41. virtual uint DeleteSession( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL );
  42. virtual uint SessionSearch( uint nProcedureIndex, uint nUserIndex, uint nNumResults, uint nNumUsers, uint nNumProperties, uint nNumContexts, XUSER_PROPERTY *pSearchProperties, XUSER_CONTEXT *pSearchContexts, uint *pcbResultsBuffer, XSESSION_SEARCHRESULT_HEADER *pSearchResults, bool bAsync, AsyncHandle_t *pAsyncHandle );
  43. virtual uint SessionStart( XboxHandle_t hSession, uint nFlags, bool bAsync, AsyncHandle_t *pAsyncHandle );
  44. virtual uint SessionEnd( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle );
  45. virtual int SessionJoinLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle );
  46. virtual int SessionJoinRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, const bool *pPrivateSlot, bool bAsync, AsyncHandle_t *pAsyncHandle );
  47. virtual int SessionLeaveLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, bool bAsync, AsyncHandle_t *pAsyncHandle );
  48. virtual int SessionLeaveRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, bool bAsync, AsyncHandle_t *pAsyncHandle );
  49. virtual int SessionMigrate( XboxHandle_t hSession, uint nUserIndex, void *pSessionInfo, bool bAsync, AsyncHandle_t *pAsyncHandle );
  50. virtual int SessionArbitrationRegister( XboxHandle_t hSession, uint nFlags, uint64 nonce, uint *pBytes, void *pBuffer, bool bAsync, AsyncHandle_t *pAsyncHandle );
  51. // Stats
  52. virtual int WriteStats( XboxHandle_t hSession, XUID xuid, uint nViews, void* pViews, bool bAsync, AsyncHandle_t *pAsyncHandle );
  53. // Achievements
  54. virtual int EnumerateAchievements( uint nUserIdx, uint64 xuid, uint nStartingIdx, uint nCount, void *pBuffer, uint nBufferBytes, bool bAsync, AsyncHandle_t *pAsyncHandle );
  55. virtual void AwardAchievement( uint nUserIdx, uint nAchievementId );
  56. virtual void FinishContainerWrites( void );
  57. virtual uint GetContainerOpenResult( void );
  58. virtual uint OpenContainers( void );
  59. virtual void CloseContainers( void );
  60. private:
  61. virtual uint CreateSavegameContainer( uint nCreationFlags );
  62. virtual uint CreateUserSettingsContainer( uint nCreationFlags );
  63. uint m_OpenContainerResult;
  64. };
  65. static CXboxSystem s_XboxSystem;
  66. IXboxSystem *g_pXboxSystem = &s_XboxSystem;
  67. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CXboxSystem, IXboxSystem, XBOXSYSTEM_INTERFACE_VERSION, s_XboxSystem );
  68. #define ASYNC_RESULT(ph) ((AsyncResult_t*)*ph);
  69. #if defined( _X360 )
  70. //-----------------------------------------------------------------------------
  71. // Holds the overlapped object and any persistent data for async system calls
  72. //-----------------------------------------------------------------------------
  73. typedef struct AsyncResult_s
  74. {
  75. XOVERLAPPED overlapped;
  76. bool bAutoRelease;
  77. void *pInputData;
  78. AsyncResult_s *pNext;
  79. } AsyncResult_t;
  80. static AsyncResult_t * g_pAsyncResultHead = NULL;
  81. //-----------------------------------------------------------------------------
  82. // Purpose: Remove an AsyncResult_t from the list
  83. //-----------------------------------------------------------------------------
  84. static void ReleaseAsyncResult( AsyncResult_t *pAsyncResult )
  85. {
  86. if ( pAsyncResult == g_pAsyncResultHead )
  87. {
  88. g_pAsyncResultHead = pAsyncResult->pNext;
  89. free( pAsyncResult->pInputData );
  90. delete pAsyncResult;
  91. return;
  92. }
  93. AsyncResult_t *pNode = g_pAsyncResultHead;
  94. while ( pNode->pNext )
  95. {
  96. if ( pNode->pNext == pAsyncResult )
  97. {
  98. pNode->pNext = pAsyncResult->pNext;
  99. free( pAsyncResult->pInputData );
  100. delete pAsyncResult;
  101. return;
  102. }
  103. pNode = pNode->pNext;
  104. }
  105. Warning( "AsyncResult_t not found in ReleaseAsyncResult.\n" );
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Purpose: Remove an AsyncResult_t from the list
  109. //-----------------------------------------------------------------------------
  110. static void ReleaseAsyncResult( XOVERLAPPED *pOverlapped )
  111. {
  112. AsyncResult_t *pResult = g_pAsyncResultHead;
  113. while ( pResult )
  114. {
  115. if ( &pResult->overlapped == pOverlapped )
  116. {
  117. ReleaseAsyncResult( pResult );
  118. return;
  119. }
  120. }
  121. Warning( "XOVERLAPPED couldn't be found in ReleaseAsyncResult.\n" );
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Purpose: Release async results that were marked for auto-release.
  125. //-----------------------------------------------------------------------------
  126. static void CleanupFinishedAsyncResults()
  127. {
  128. AsyncResult_t *pResult = g_pAsyncResultHead;
  129. AsyncResult_t *pNext;
  130. while( pResult )
  131. {
  132. pNext = pResult->pNext;
  133. if ( pResult->bAutoRelease )
  134. {
  135. if ( XHasOverlappedIoCompleted( &pResult->overlapped ) )
  136. {
  137. ReleaseAsyncResult( pResult );
  138. }
  139. }
  140. pResult = pNext;
  141. }
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: Add a new AsyncResult_t object to the list
  145. //-----------------------------------------------------------------------------
  146. static AsyncResult_t *CreateAsyncResult( bool bAutoRelease )
  147. {
  148. // Take this opportunity to clean up finished operations
  149. CleanupFinishedAsyncResults();
  150. AsyncResult_t *pAsyncResult = new AsyncResult_t;
  151. memset( pAsyncResult, 0, sizeof( AsyncResult_t ) );
  152. pAsyncResult->pNext = g_pAsyncResultHead;
  153. g_pAsyncResultHead = pAsyncResult;
  154. if ( bAutoRelease )
  155. {
  156. pAsyncResult->bAutoRelease = true;
  157. }
  158. return pAsyncResult;
  159. }
  160. //-----------------------------------------------------------------------------
  161. // Purpose: Return an AsyncResult_t object to the pool
  162. //-----------------------------------------------------------------------------
  163. static void InitializeAsyncHandle( AsyncHandle_t *pHandle )
  164. {
  165. XOVERLAPPED *pOverlapped = &((AsyncResult_t *)*pHandle)->overlapped;
  166. memset( pOverlapped, 0, sizeof( XOVERLAPPED ) );
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Purpose: Initialize or create and async handle
  170. //-----------------------------------------------------------------------------
  171. static AsyncResult_t *InitializeAsyncResult( AsyncHandle_t **ppAsyncHandle )
  172. {
  173. AsyncResult_t *pResult = NULL;
  174. if ( *ppAsyncHandle )
  175. {
  176. InitializeAsyncHandle( *ppAsyncHandle );
  177. pResult = ASYNC_RESULT( *ppAsyncHandle );
  178. }
  179. else
  180. {
  181. // No handle provided, create one
  182. pResult = CreateAsyncResult( true );
  183. }
  184. return pResult;
  185. }
  186. CXboxSystem::CXboxSystem( void ) : m_OpenContainerResult( ERROR_SUCCESS )
  187. {
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: Force overlapped operations to finish and clean up
  191. //-----------------------------------------------------------------------------
  192. CXboxSystem::~CXboxSystem()
  193. {
  194. // Force async operations to finish.
  195. AsyncResult_t *pResult = g_pAsyncResultHead;
  196. while ( pResult )
  197. {
  198. AsyncResult_t *pNext = pResult->pNext;
  199. GetOverlappedResult( (AsyncHandle_t)pResult, NULL, true );
  200. pResult = pNext;
  201. }
  202. // Release any remaining handles - should have been released by the client that created them.
  203. int ct = 0;
  204. while ( g_pAsyncResultHead )
  205. {
  206. ReleaseAsyncResult( g_pAsyncResultHead );
  207. ++ct;
  208. }
  209. if ( ct )
  210. {
  211. Warning( "Released %d async handles\n", ct );
  212. }
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Purpose: Check on the result of an overlapped operation
  216. //-----------------------------------------------------------------------------
  217. int CXboxSystem::GetOverlappedResult( AsyncHandle_t handle, uint *pResultCode, bool bWait )
  218. {
  219. if ( !handle )
  220. return ERROR_INVALID_HANDLE;
  221. return XGetOverlappedResult( &((AsyncResult_t*)handle)->overlapped, (DWORD*)pResultCode, bWait );
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose: Cancel an overlapped operation
  225. //-----------------------------------------------------------------------------
  226. void CXboxSystem::CancelOverlappedOperation( AsyncHandle_t handle )
  227. {
  228. XCancelOverlapped( &((AsyncResult_t*)handle)->overlapped );
  229. }
  230. //-----------------------------------------------------------------------------
  231. // Purpose: Create a new AsyncHandle_t
  232. //-----------------------------------------------------------------------------
  233. AsyncHandle_t CXboxSystem::CreateAsyncHandle( void )
  234. {
  235. return (AsyncHandle_t)CreateAsyncResult( false );
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Purpose: Delete an AsyncHandle_t
  239. //-----------------------------------------------------------------------------
  240. void CXboxSystem::ReleaseAsyncHandle( AsyncHandle_t handle )
  241. {
  242. ReleaseAsyncResult( (AsyncResult_t*)handle );
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose: Close the open containers
  246. //-----------------------------------------------------------------------------
  247. void CXboxSystem::CloseContainers( void )
  248. {
  249. XContentClose( GetCurrentMod(), NULL );
  250. XContentClose( XBX_USER_SETTINGS_CONTAINER_DRIVE, NULL );
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Purpose:
  254. //-----------------------------------------------------------------------------
  255. uint CXboxSystem::OpenContainers( void )
  256. {
  257. // Close the containers (force dismount)
  258. CloseContainers();
  259. m_OpenContainerResult = ERROR_SUCCESS;
  260. // Open the save games
  261. if ( ( m_OpenContainerResult = CreateUserSettingsContainer( XCONTENTFLAG_OPENALWAYS ) ) != ERROR_SUCCESS )
  262. return m_OpenContainerResult;
  263. // If we're TF, we don't care about save game space
  264. if ( !Q_stricmp( GetCurrentMod(), "tf" ) )
  265. return m_OpenContainerResult;
  266. // Open the user settings
  267. if ( ( m_OpenContainerResult = CreateSavegameContainer( XCONTENTFLAG_OPENALWAYS ) ) != ERROR_SUCCESS )
  268. {
  269. CloseContainers();
  270. return m_OpenContainerResult;
  271. }
  272. return m_OpenContainerResult;
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Purpose: Returns the results from the last container opening
  276. //-----------------------------------------------------------------------------
  277. uint CXboxSystem::GetContainerOpenResult( void )
  278. {
  279. return m_OpenContainerResult;
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Purpose: Open the save game container for the current mod
  283. //-----------------------------------------------------------------------------
  284. uint CXboxSystem::CreateSavegameContainer( uint nCreationFlags )
  285. {
  286. if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED )
  287. return ERROR_INVALID_HANDLE;
  288. // Don't allow any of our saves or user data to be transferred to another user
  289. nCreationFlags |= XCONTENTFLAG_NOPROFILE_TRANSFER;
  290. const wchar_t *pchContainerDisplayName;
  291. const char *pchContainerName;
  292. g_pXboxSystem->GetModSaveContainerNames( GetCurrentMod(), &pchContainerDisplayName, &pchContainerName );
  293. XCONTENT_DATA contentData;
  294. contentData.DeviceID = XBX_GetStorageDeviceId();
  295. contentData.dwContentType = XCONTENTTYPE_SAVEDGAME;
  296. Q_wcsncpy( contentData.szDisplayName, pchContainerDisplayName, sizeof ( contentData.szDisplayName ) );
  297. Q_snprintf( contentData.szFileName, sizeof( contentData.szFileName ), pchContainerName );
  298. SIZE_T dwFileCacheSize = 0; // Use the smallest size (default)
  299. ULARGE_INTEGER ulSize;
  300. ulSize.QuadPart = XBX_PERSISTENT_BYTES_NEEDED;
  301. int nRet = XContentCreateEx( XBX_GetPrimaryUserId(), GetCurrentMod(), &contentData, nCreationFlags, NULL, NULL, dwFileCacheSize, ulSize, NULL );
  302. if ( nRet == ERROR_SUCCESS )
  303. {
  304. BOOL bUserIsCreator = false;
  305. XContentGetCreator( XBX_GetPrimaryUserId(), &contentData, &bUserIsCreator, NULL, NULL );
  306. if( bUserIsCreator == false )
  307. {
  308. XContentClose( GetCurrentMod(), NULL );
  309. return ERROR_ACCESS_DENIED;
  310. }
  311. }
  312. return nRet;
  313. }
  314. //-----------------------------------------------------------------------------
  315. // Purpose: Open the user settings container for the current mod
  316. //-----------------------------------------------------------------------------
  317. uint CXboxSystem::CreateUserSettingsContainer( uint nCreationFlags )
  318. {
  319. if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED )
  320. return ERROR_INVALID_HANDLE;
  321. // Don't allow any of our saves or user data to be transferred to another user
  322. nCreationFlags |= XCONTENTFLAG_NOPROFILE_TRANSFER;
  323. XCONTENT_DATA contentData;
  324. contentData.DeviceID = XBX_GetStorageDeviceId();
  325. contentData.dwContentType = XCONTENTTYPE_SAVEDGAME;
  326. Q_wcsncpy( contentData.szDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_UserSettings" ), sizeof( contentData.szDisplayName ) );
  327. Q_snprintf( contentData.szFileName, sizeof( contentData.szFileName ), "UserSettings" );
  328. SIZE_T dwFileCacheSize = 0; // Use the smallest size (default)
  329. ULARGE_INTEGER ulSize;
  330. ulSize.QuadPart = XBX_USER_SETTINGS_BYTES;
  331. int nRet = XContentCreateEx( XBX_GetPrimaryUserId(), XBX_USER_SETTINGS_CONTAINER_DRIVE, &contentData, nCreationFlags, NULL, NULL, dwFileCacheSize, ulSize, NULL );
  332. if ( nRet == ERROR_SUCCESS )
  333. {
  334. BOOL bUserIsCreator = false;
  335. XContentGetCreator( XBX_GetPrimaryUserId(), &contentData, &bUserIsCreator, NULL, NULL );
  336. if( bUserIsCreator == false )
  337. {
  338. XContentClose( XBX_USER_SETTINGS_CONTAINER_DRIVE, NULL );
  339. return ERROR_ACCESS_DENIED;
  340. }
  341. }
  342. return nRet;
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose:
  346. //-----------------------------------------------------------------------------
  347. void CXboxSystem::FinishContainerWrites( void )
  348. {
  349. // Finish all writes
  350. XContentFlush( GetCurrentMod(), NULL );
  351. XContentFlush( XBX_USER_SETTINGS_CONTAINER_DRIVE, NULL );
  352. }
  353. //-----------------------------------------------------------------------------
  354. // Purpose: Retrieve the names used for our save game container
  355. // Input : *pchModName - Name of the mod we're running (tf, hl2, etc)
  356. // **ppchDisplayName - Display name that will be presented to users by the console
  357. // **ppchName - Filename of the container
  358. //-----------------------------------------------------------------------------
  359. void CXboxSystem::GetModSaveContainerNames( const char *pchModName, const wchar_t **ppchDisplayName, const char **ppchName )
  360. {
  361. // If the strings haven't been setup
  362. if ( g_szModSaveContainerDisplayName[ 0 ] == '\0' )
  363. {
  364. if ( Q_stricmp( pchModName, "episodic" ) == 0 )
  365. {
  366. Q_wcsncpy( g_szModSaveContainerDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_Ep1_Saves" ), sizeof( g_szModSaveContainerDisplayName ) );
  367. }
  368. else if ( Q_stricmp( pchModName, "ep2" ) == 0 )
  369. {
  370. Q_wcsncpy( g_szModSaveContainerDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_Ep2_Saves" ), sizeof( g_szModSaveContainerDisplayName ) );
  371. }
  372. else if ( Q_stricmp( pchModName, "portal" ) == 0 )
  373. {
  374. Q_wcsncpy( g_szModSaveContainerDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_Portal_Saves" ), sizeof( g_szModSaveContainerDisplayName ) );
  375. }
  376. else if ( Q_stricmp( pchModName, "tf" ) == 0 )
  377. {
  378. Q_wcsncpy( g_szModSaveContainerDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_TF2_Saves" ), sizeof( g_szModSaveContainerDisplayName ) );
  379. }
  380. else
  381. {
  382. Q_wcsncpy( g_szModSaveContainerDisplayName, g_pVGuiLocalize->Find( "#GameUI_Console_HL2_Saves" ), sizeof( g_szModSaveContainerDisplayName ) );
  383. }
  384. // Create a filename with the format "mod_saves"
  385. Q_snprintf( g_szModSaveContainerName, sizeof( g_szModSaveContainerName ), "%s_saves", pchModName );
  386. }
  387. // Return pointers to these internally kept strings
  388. *ppchDisplayName = g_szModSaveContainerDisplayName;
  389. *ppchName = g_szModSaveContainerName;
  390. }
  391. //-----------------------------------------------------------------------------
  392. // Purpose: Search the device and find out if we have adequate space to start a game
  393. // Input : nStorageID - Device to check
  394. // *pModName - Name of the mod we want to check for
  395. //-----------------------------------------------------------------------------
  396. bool CXboxSystem::DeviceCapacityAdequate( DWORD nStorageID, const char *pModName )
  397. {
  398. // If we don't have a valid user id, we can't poll the device
  399. if ( XBX_GetPrimaryUserId() == XBX_INVALID_USER_ID )
  400. return false;
  401. // Must be a valid storage device to poll
  402. if ( nStorageID == XBX_INVALID_STORAGE_ID )
  403. return false;
  404. // Get the actual amount on the drive
  405. XDEVICE_DATA deviceData;
  406. if ( XContentGetDeviceData( nStorageID, &deviceData ) != ERROR_SUCCESS )
  407. return false;
  408. const ULONGLONG nSaveGameSize = XContentCalculateSize( XBX_PERSISTENT_BYTES_NEEDED, 1 );
  409. const ULONGLONG nUserSettingsSize = XContentCalculateSize( XBX_USER_SETTINGS_BYTES, 1 );
  410. bool bIsTF2 = ( !Q_stricmp( pModName, "tf" ) );
  411. ULONGLONG nTotalSpaceNeeded = ( bIsTF2 ) ? nUserSettingsSize : ( nSaveGameSize + nUserSettingsSize );
  412. ULONGLONG nAvailableSpace = deviceData.ulDeviceFreeBytes; // Take the first device's free space to compare this against
  413. // If they've already got enough space, early out
  414. if ( nAvailableSpace >= nTotalSpaceNeeded )
  415. return true;
  416. const int nNumItemsToRetrieve = 1;
  417. const int fContentFlags = XCONTENTFLAG_ENUM_EXCLUDECOMMON;
  418. // Save for queries against the storage devices
  419. const wchar_t *pchContainerDisplayName;
  420. const char *pchContainerName;
  421. GetModSaveContainerNames( pModName, &pchContainerDisplayName, &pchContainerName );
  422. // Look for a user settings block for all products
  423. DWORD nBufferSize;
  424. HANDLE hEnumerator;
  425. if ( XContentCreateEnumerator( XBX_GetPrimaryUserId(),
  426. nStorageID,
  427. XCONTENTTYPE_SAVEDGAME,
  428. fContentFlags,
  429. nNumItemsToRetrieve,
  430. &nBufferSize,
  431. &hEnumerator ) == ERROR_SUCCESS )
  432. {
  433. // Allocate a buffer of the correct size
  434. BYTE *pBuffer = new BYTE[nBufferSize];
  435. if ( pBuffer == NULL )
  436. return XBX_INVALID_STORAGE_ID;
  437. char szFilename[XCONTENT_MAX_FILENAME_LENGTH+1];
  438. szFilename[XCONTENT_MAX_FILENAME_LENGTH] = 0;
  439. XCONTENT_DATA *pData = NULL;
  440. // Step through all items, looking for ones we care about
  441. DWORD nNumItems;
  442. while ( XEnumerate( hEnumerator, pBuffer, nBufferSize, &nNumItems, NULL ) == ERROR_SUCCESS )
  443. {
  444. // Grab the item in question
  445. pData = (XCONTENT_DATA *) pBuffer;
  446. // Safely store this away (null-termination is not guaranteed by the API!)
  447. memcpy( szFilename, pData->szFileName, XCONTENT_MAX_FILENAME_LENGTH );
  448. // See if this is our user settings file
  449. if ( !Q_stricmp( szFilename, "UserSettings" ) )
  450. {
  451. nTotalSpaceNeeded -= nUserSettingsSize;
  452. }
  453. else if ( bIsTF2 == false && !Q_stricmp( szFilename, pchContainerName ) )
  454. {
  455. nTotalSpaceNeeded -= nSaveGameSize;
  456. }
  457. }
  458. // Clean up
  459. delete[] pBuffer;
  460. CloseHandle( hEnumerator );
  461. }
  462. // Finally, check its complete size
  463. if ( nTotalSpaceNeeded <= nAvailableSpace )
  464. return true;
  465. return false;
  466. }
  467. //-----------------------------------------------------------------------------
  468. // Purpose: Enumerate all devices and search for game data already present. If only one device has it, we return it
  469. // Input : nUserID - User whose data we're searching for
  470. // *pModName - Name of the mod we're searching for
  471. // Output : Device ID which contains our data (-1 if no data was found, or data resided on multiple devices)
  472. //-----------------------------------------------------------------------------
  473. DWORD CXboxSystem::DiscoverUserData( DWORD nUserID, const char *pModName )
  474. {
  475. // If we're entering this function without a storage device, then we must pop the UI anyway to choose it!
  476. Assert( nUserID != XBX_INVALID_USER_ID );
  477. if ( nUserID == XBX_INVALID_USER_ID )
  478. return XBX_INVALID_STORAGE_ID;
  479. const int nNumItemsToRetrieve = 1;
  480. const int fContentFlags = XCONTENTFLAG_ENUM_EXCLUDECOMMON;
  481. DWORD nFoundDevice = XBX_INVALID_STORAGE_ID;
  482. // Save for queries against the storage devices
  483. const wchar_t *pchContainerDisplayName;
  484. const char *pchContainerName;
  485. GetModSaveContainerNames( pModName, &pchContainerDisplayName, &pchContainerName );
  486. const ULONGLONG nSaveGameSize = XContentCalculateSize( XBX_PERSISTENT_BYTES_NEEDED, 1 );
  487. const ULONGLONG nUserSettingsSize = XContentCalculateSize( XBX_USER_SETTINGS_BYTES, 1 );
  488. ULONGLONG nTotalSpaceNeeded = ( nSaveGameSize + nUserSettingsSize );
  489. ULONGLONG nAvailableSpace = 0; // Take the first device's free space to compare this against
  490. // Look for a user settings block for all products
  491. DWORD nBufferSize;
  492. HANDLE hEnumerator;
  493. if ( XContentCreateEnumerator( nUserID,
  494. XCONTENTDEVICE_ANY, // All devices we know about
  495. XCONTENTTYPE_SAVEDGAME,
  496. fContentFlags,
  497. nNumItemsToRetrieve,
  498. &nBufferSize,
  499. &hEnumerator ) == ERROR_SUCCESS )
  500. {
  501. // Allocate a buffer of the correct size
  502. BYTE *pBuffer = new BYTE[nBufferSize];
  503. if ( pBuffer == NULL )
  504. return XBX_INVALID_STORAGE_ID;
  505. char szFilename[XCONTENT_MAX_FILENAME_LENGTH+1];
  506. szFilename[XCONTENT_MAX_FILENAME_LENGTH] = 0;
  507. XCONTENT_DATA *pData = NULL;
  508. // Step through all items, looking for ones we care about
  509. DWORD nNumItems;
  510. while ( XEnumerate( hEnumerator, pBuffer, nBufferSize, &nNumItems, NULL ) == ERROR_SUCCESS )
  511. {
  512. // Grab the item in question
  513. pData = (XCONTENT_DATA *) pBuffer;
  514. // If they have multiple devices installed, then we must ask
  515. if ( nFoundDevice != XBX_INVALID_STORAGE_ID && nFoundDevice != pData->DeviceID )
  516. {
  517. // Clean up
  518. delete[] pBuffer;
  519. CloseHandle( hEnumerator );
  520. return XBX_INVALID_STORAGE_ID;
  521. }
  522. // Hold on to this device ID
  523. if ( nFoundDevice != pData->DeviceID )
  524. {
  525. nFoundDevice = pData->DeviceID;
  526. XDEVICE_DATA deviceData;
  527. if ( XContentGetDeviceData( nFoundDevice, &deviceData ) != ERROR_SUCCESS )
  528. continue;
  529. nAvailableSpace = deviceData.ulDeviceFreeBytes;
  530. }
  531. // Safely store this away (null-termination is not guaranteed by the API!)
  532. memcpy( szFilename, pData->szFileName, XCONTENT_MAX_FILENAME_LENGTH );
  533. // See if this is our user settings file
  534. if ( !Q_stricmp( szFilename, "UserSettings" ) )
  535. {
  536. nTotalSpaceNeeded -= nUserSettingsSize;
  537. }
  538. else if ( !Q_stricmp( szFilename, pchContainerName ) )
  539. {
  540. nTotalSpaceNeeded -= nSaveGameSize;
  541. }
  542. }
  543. // Clean up
  544. delete[] pBuffer;
  545. CloseHandle( hEnumerator );
  546. }
  547. // If we found nothing, then give up
  548. if ( nFoundDevice == XBX_INVALID_STORAGE_ID )
  549. return nFoundDevice;
  550. // Finally, check its complete size
  551. if ( nTotalSpaceNeeded <= nAvailableSpace )
  552. return nFoundDevice;
  553. return XBX_INVALID_STORAGE_ID;
  554. }
  555. //-----------------------------------------------------------------------------
  556. // Purpose: Space free on the current device
  557. //-----------------------------------------------------------------------------
  558. uint CXboxSystem::GetContainerRemainingSpace( void )
  559. {
  560. XDEVICE_DATA deviceData;
  561. if ( XContentGetDeviceData( XBX_GetStorageDeviceId(), &deviceData ) != ERROR_SUCCESS )
  562. return 0;
  563. return deviceData.ulDeviceFreeBytes;
  564. }
  565. //-----------------------------------------------------------------------------
  566. // Purpose: Show the storage device selector
  567. //-----------------------------------------------------------------------------
  568. bool CXboxSystem::ShowDeviceSelector( bool bForce, uint *pStorageID, AsyncHandle_t *pAsyncHandle )
  569. {
  570. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  571. // We validate the size outside of this because we want to look inside our packages to see what's really free
  572. ULARGE_INTEGER bytes;
  573. bytes.QuadPart = XContentCalculateSize( XBX_PERSISTENT_BYTES_NEEDED + XBX_USER_SETTINGS_BYTES, 1 );
  574. DWORD showFlags = bForce ? XCONTENTFLAG_FORCE_SHOW_UI : 0;
  575. showFlags |= XCONTENTFLAG_MANAGESTORAGE;
  576. DWORD ret = XShowDeviceSelectorUI( XBX_GetPrimaryUserId(),
  577. XCONTENTTYPE_SAVEDGAME,
  578. showFlags,
  579. bytes,
  580. (DWORD*) pStorageID,
  581. &pResult->overlapped
  582. );
  583. if ( ret != ERROR_IO_PENDING )
  584. {
  585. Msg( "Error showing device Selector UI\n" );
  586. return false;
  587. }
  588. return true;
  589. }
  590. //-----------------------------------------------------------------------------
  591. // Purpose: Show the user sign in screen
  592. //-----------------------------------------------------------------------------
  593. void CXboxSystem::ShowSigninUI( uint nPanes, uint nFlags )
  594. {
  595. XShowSigninUI( nPanes, nFlags );
  596. }
  597. //-----------------------------------------------------------------------------
  598. // Purpose: Set a user context
  599. //-----------------------------------------------------------------------------
  600. int CXboxSystem::UserSetContext( uint nUserIdx, uint nContextID, uint nContextValue, bool bAsync, AsyncHandle_t *pAsyncHandle )
  601. {
  602. XOVERLAPPED *pOverlapped = NULL;
  603. if ( bAsync )
  604. {
  605. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  606. pOverlapped = &pResult->overlapped;
  607. }
  608. return XUserSetContextEx( nUserIdx, nContextID, nContextValue, pOverlapped );
  609. }
  610. //-----------------------------------------------------------------------------
  611. // Purpose: Set a user property
  612. //-----------------------------------------------------------------------------
  613. int CXboxSystem::UserSetProperty( uint nUserIndex, uint nPropertyId, uint nBytes, const void *pvValue, bool bAsync, AsyncHandle_t *pAsyncHandle )
  614. {
  615. XOVERLAPPED *pOverlapped = NULL;
  616. const void *pData = pvValue;
  617. if ( bAsync )
  618. {
  619. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  620. if ( nBytes && pvValue )
  621. {
  622. pResult->pInputData = malloc( nBytes );
  623. memcpy( pResult->pInputData, pvValue, nBytes );
  624. }
  625. else
  626. {
  627. nBytes = 0;
  628. }
  629. pOverlapped = &pResult->overlapped;
  630. pData = pResult->pInputData;
  631. }
  632. return XUserSetPropertyEx( nUserIndex, nPropertyId, nBytes, pData, pOverlapped );
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Purpose: Create a matchmaking session
  636. //-----------------------------------------------------------------------------
  637. int CXboxSystem::CreateSession( uint nFlags,
  638. uint nUserIdx,
  639. uint nMaxPublicSlots,
  640. uint nMaxPrivateSlots,
  641. uint64 *pNonce,
  642. void *pSessionInfo,
  643. XboxHandle_t *pSessionHandle,
  644. bool bAsync,
  645. AsyncHandle_t *pAsyncHandle
  646. )
  647. {
  648. XOVERLAPPED *pOverlapped = NULL;
  649. if ( bAsync )
  650. {
  651. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  652. pOverlapped = &pResult->overlapped;
  653. }
  654. // Create the session
  655. return XSessionCreate( nFlags, nUserIdx, nMaxPublicSlots, nMaxPrivateSlots, pNonce, (XSESSION_INFO*)pSessionInfo, pOverlapped, pSessionHandle );
  656. }
  657. //-----------------------------------------------------------------------------
  658. // Purpose: Destroy a matchmaking session
  659. //-----------------------------------------------------------------------------
  660. uint CXboxSystem::DeleteSession( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle )
  661. {
  662. XOVERLAPPED *pOverlapped = NULL;
  663. if ( bAsync )
  664. {
  665. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  666. pOverlapped = &pResult->overlapped;
  667. }
  668. // Delete the session
  669. uint ret = XSessionDelete( hSession, pOverlapped );
  670. CloseHandle( hSession );
  671. return ret;
  672. }
  673. //-----------------------------------------------------------------------------
  674. // Purpose: Create a matchmaking session
  675. //-----------------------------------------------------------------------------
  676. uint CXboxSystem::SessionSearch( uint nProcedureIndex,
  677. uint nUserIndex,
  678. uint nNumResults,
  679. uint nNumUsers,
  680. uint nNumProperties,
  681. uint nNumContexts,
  682. XUSER_PROPERTY *pSearchProperties,
  683. XUSER_CONTEXT *pSearchContexts,
  684. uint *pcbResultsBuffer,
  685. XSESSION_SEARCHRESULT_HEADER *pSearchResults,
  686. bool bAsync,
  687. AsyncHandle_t *pAsyncHandle
  688. )
  689. {
  690. XOVERLAPPED *pOverlapped = NULL;
  691. if ( bAsync )
  692. {
  693. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  694. pOverlapped = &pResult->overlapped;
  695. }
  696. // Search for the session
  697. return XSessionSearchEx( nProcedureIndex, nUserIndex, nNumResults, nNumUsers, nNumProperties, nNumContexts, pSearchProperties, pSearchContexts, (DWORD*)pcbResultsBuffer, pSearchResults, pOverlapped );
  698. }
  699. //-----------------------------------------------------------------------------
  700. // Purpose: Starting a multiplayer game
  701. //-----------------------------------------------------------------------------
  702. uint CXboxSystem::SessionStart( XboxHandle_t hSession, uint nFlags, bool bAsync, AsyncHandle_t *pAsyncHandle )
  703. {
  704. XOVERLAPPED *pOverlapped = NULL;
  705. if ( bAsync )
  706. {
  707. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  708. pOverlapped = &pResult->overlapped;
  709. }
  710. return XSessionStart( hSession, nFlags, pOverlapped );
  711. }
  712. //-----------------------------------------------------------------------------
  713. // Purpose: Finished a multiplayer game
  714. //-----------------------------------------------------------------------------
  715. uint CXboxSystem::SessionEnd( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle )
  716. {
  717. XOVERLAPPED *pOverlapped = NULL;
  718. if ( bAsync )
  719. {
  720. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  721. pOverlapped = &pResult->overlapped;
  722. }
  723. return XSessionEnd( hSession, pOverlapped );
  724. }
  725. //-----------------------------------------------------------------------------
  726. // Purpose: Join local users to a session
  727. //-----------------------------------------------------------------------------
  728. int CXboxSystem::SessionJoinLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle )
  729. {
  730. XOVERLAPPED *pOverlapped = NULL;
  731. if ( bAsync )
  732. {
  733. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  734. pOverlapped = &pResult->overlapped;
  735. }
  736. return XSessionJoinLocal( hSession, nUserCount, (DWORD*)pUserIndexes, (BOOL*)pPrivateSlots, pOverlapped );
  737. }
  738. //-----------------------------------------------------------------------------
  739. // Purpose: Join remote users to a session
  740. //-----------------------------------------------------------------------------
  741. int CXboxSystem::SessionJoinRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle )
  742. {
  743. XOVERLAPPED *pOverlapped = NULL;
  744. if ( bAsync )
  745. {
  746. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  747. pOverlapped = &pResult->overlapped;
  748. }
  749. return XSessionJoinRemote( hSession, nUserCount, pXuids, (BOOL*)pPrivateSlots, pOverlapped );
  750. }
  751. //-----------------------------------------------------------------------------
  752. // Purpose: Remove local users from a session
  753. //-----------------------------------------------------------------------------
  754. int CXboxSystem::SessionLeaveLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, bool bAsync, AsyncHandle_t *pAsyncHandle )
  755. {
  756. XOVERLAPPED *pOverlapped = NULL;
  757. if ( bAsync )
  758. {
  759. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  760. pOverlapped = &pResult->overlapped;
  761. }
  762. return XSessionLeaveLocal( hSession, nUserCount, (DWORD*)pUserIndexes, pOverlapped );
  763. }
  764. //-----------------------------------------------------------------------------
  765. // Purpose: Remove remote users from a session
  766. //-----------------------------------------------------------------------------
  767. int CXboxSystem::SessionLeaveRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, bool bAsync, AsyncHandle_t *pAsyncHandle )
  768. {
  769. XOVERLAPPED *pOverlapped = NULL;
  770. if ( bAsync )
  771. {
  772. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  773. pOverlapped = &pResult->overlapped;
  774. }
  775. return XSessionLeaveRemote( hSession, nUserCount, pXuids, pOverlapped );
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Purpose: Migrate a session to a new host
  779. //-----------------------------------------------------------------------------
  780. int CXboxSystem::SessionMigrate( XboxHandle_t hSession, uint nUserIndex, void *pSessionInfo, bool bAsync, AsyncHandle_t *pAsyncHandle )
  781. {
  782. XOVERLAPPED *pOverlapped = NULL;
  783. if ( bAsync )
  784. {
  785. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  786. pOverlapped = &pResult->overlapped;
  787. }
  788. return XSessionMigrateHost( hSession, nUserIndex, (XSESSION_INFO*)pSessionInfo, pOverlapped );
  789. }
  790. //-----------------------------------------------------------------------------
  791. // Purpose: Register for arbitration
  792. //-----------------------------------------------------------------------------
  793. int CXboxSystem::SessionArbitrationRegister( XboxHandle_t hSession, uint nFlags, uint64 nonce, uint *pBytes, void *pBuffer, bool bAsync, AsyncHandle_t *pAsyncHandle )
  794. {
  795. XOVERLAPPED *pOverlapped = NULL;
  796. if ( bAsync )
  797. {
  798. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  799. pOverlapped = &pResult->overlapped;
  800. }
  801. return XSessionArbitrationRegister( hSession, nFlags, nonce, (DWORD*)pBytes, (XSESSION_REGISTRATION_RESULTS*)pBuffer, pOverlapped );
  802. }
  803. //-----------------------------------------------------------------------------
  804. // Purpose: Upload player stats to Xbox Live
  805. //-----------------------------------------------------------------------------
  806. int CXboxSystem::WriteStats( XboxHandle_t hSession, XUID xuid, uint nViews, void* pViews, bool bAsync, AsyncHandle_t *pAsyncHandle )
  807. {
  808. XOVERLAPPED *pOverlapped = NULL;
  809. if ( bAsync )
  810. {
  811. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  812. pOverlapped = &pResult->overlapped;
  813. }
  814. return XSessionWriteStats( hSession, xuid, nViews, (XSESSION_VIEW_PROPERTIES*)pViews, pOverlapped );
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Purpose: Enumerate a player's achievements
  818. //-----------------------------------------------------------------------------
  819. int CXboxSystem::EnumerateAchievements( uint nUserIdx,
  820. uint64 xuid,
  821. uint nStartingIdx,
  822. uint nCount,
  823. void *pBuffer,
  824. uint nBufferBytes,
  825. bool bAsync,
  826. AsyncHandle_t *pAsyncHandle
  827. )
  828. {
  829. HANDLE hEnumerator = INVALID_HANDLE_VALUE;
  830. DWORD ret = XUserCreateAchievementEnumerator( 0, nUserIdx, xuid, XACHIEVEMENT_DETAILS_ALL, nStartingIdx, nCount, (DWORD*)pBuffer, &hEnumerator );
  831. // Just looking for the buffer size needed
  832. if ( ret != ERROR_SUCCESS || nBufferBytes == 0 )
  833. {
  834. CloseHandle( hEnumerator );
  835. return ret;
  836. }
  837. if ( nBufferBytes < *(uint*)pBuffer )
  838. {
  839. Warning( "EnumerateAchievements: Buffer provided not large enough to hold results" );
  840. return ERROR_NOT_ENOUGH_MEMORY;
  841. }
  842. XOVERLAPPED *pOverlapped = NULL;
  843. if ( bAsync )
  844. {
  845. AsyncResult_t *pResult = InitializeAsyncResult( &pAsyncHandle );
  846. pOverlapped = &pResult->overlapped;
  847. }
  848. DWORD items;
  849. ret = XEnumerate( hEnumerator, pBuffer, nBufferBytes, &items, pOverlapped );
  850. if ( ret != ERROR_SUCCESS )
  851. {
  852. Warning( "XEnumerate failed in EnumerateAchievements.\n" );
  853. }
  854. CloseHandle( hEnumerator );
  855. return items;
  856. }
  857. //-----------------------------------------------------------------------------
  858. // Purpose: Award an achievement to the current user
  859. //-----------------------------------------------------------------------------
  860. void CXboxSystem::AwardAchievement( uint nUserIdx, uint nAchievementId )
  861. {
  862. AsyncResult_t *pResult = CreateAsyncResult( true );
  863. XUSER_ACHIEVEMENT ach;
  864. ach.dwUserIndex = nUserIdx;
  865. ach.dwAchievementId = nAchievementId;
  866. pResult->pInputData = malloc( sizeof( ach ) );
  867. Q_memcpy( pResult->pInputData, &ach, sizeof( ach ) );
  868. DWORD ret = XUserWriteAchievements( 1, (XUSER_ACHIEVEMENT*)pResult->pInputData, &pResult->overlapped );
  869. if ( ret != ERROR_IO_PENDING )
  870. {
  871. Warning( "XUserWriteAchievments failed.\n" );
  872. }
  873. }
  874. #else
  875. // Stubbed interface for win32
  876. CXboxSystem::~CXboxSystem( void ) {}
  877. CXboxSystem::CXboxSystem( void ) {}
  878. AsyncHandle_t CXboxSystem::CreateAsyncHandle( void ) { return NULL; }
  879. void CXboxSystem::ReleaseAsyncHandle( AsyncHandle_t handle ) {}
  880. int CXboxSystem::GetOverlappedResult( AsyncHandle_t handle, uint *pResultCode, bool bWait ) { return 0; }
  881. void CXboxSystem::CancelOverlappedOperation( AsyncHandle_t handle ) {};
  882. void CXboxSystem::GetModSaveContainerNames( const char *pchModName, const wchar_t **ppchDisplayName, const char **ppchName )
  883. {
  884. *ppchDisplayName = g_szModSaveContainerDisplayName;
  885. *ppchName = g_szModSaveContainerName;
  886. }
  887. DWORD CXboxSystem::DiscoverUserData( DWORD nUserID, const char *pModName ) { return ((DWORD)-1); }
  888. bool CXboxSystem::DeviceCapacityAdequate( DWORD nDeviceID, const char *pModName ) { return true; }
  889. uint CXboxSystem::GetContainerRemainingSpace( void ) { return 0; }
  890. bool CXboxSystem::ShowDeviceSelector( bool bForce, uint *pStorageID, AsyncHandle_t *pHandle ) { return false; }
  891. void CXboxSystem::ShowSigninUI( uint nPanes, uint nFlags ) {}
  892. int CXboxSystem::UserSetContext( uint nUserIdx, uint nContextID, uint nContextValue, bool bAsync, AsyncHandle_t *pHandle) { return 0; }
  893. int CXboxSystem::UserSetProperty( uint nUserIndex, uint nPropertyId, uint nBytes, const void *pvValue, bool bAsync, AsyncHandle_t *pHandle ) { return 0; }
  894. int CXboxSystem::CreateSession( uint nFlags, uint nUserIdx, uint nMaxPublicSlots, uint nMaxPrivateSlots, uint64 *pNonce, void *pSessionInfo, XboxHandle_t *pSessionHandle, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  895. uint CXboxSystem::DeleteSession( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  896. uint CXboxSystem::SessionSearch( uint nProcedureIndex, uint nUserIndex, uint nNumResults, uint nNumUsers, uint nNumProperties, uint nNumContexts, XUSER_PROPERTY *pSearchProperties, XUSER_CONTEXT *pSearchContexts, uint *pcbResultsBuffer, XSESSION_SEARCHRESULT_HEADER *pSearchResults, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  897. uint CXboxSystem::SessionStart( XboxHandle_t hSession, uint nFlags, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; };
  898. uint CXboxSystem::SessionEnd( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; };
  899. int CXboxSystem::SessionJoinLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  900. int CXboxSystem::SessionJoinRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, const bool *pPrivateSlot, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  901. int CXboxSystem::SessionLeaveLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  902. int CXboxSystem::SessionLeaveRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  903. int CXboxSystem::SessionMigrate( XboxHandle_t hSession, uint nUserIndex, void *pSessionInfo, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  904. int CXboxSystem::SessionArbitrationRegister( XboxHandle_t hSession, uint nFlags, uint64 nonce, uint *pBytes, void *pBuffer, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  905. int CXboxSystem::WriteStats( XboxHandle_t hSession, XUID xuid, uint nViews, void* pViews, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  906. int CXboxSystem::EnumerateAchievements( uint nUserIdx, uint64 xuid, uint nStartingIdx, uint nCount, void *pBuffer, uint nBufferBytes, bool bAsync, AsyncHandle_t *pAsyncHandle ) { return 0; }
  907. void CXboxSystem::AwardAchievement( uint nUserIdx, uint nAchievementId ) {}
  908. void CXboxSystem::FinishContainerWrites( void ) {}
  909. uint CXboxSystem::GetContainerOpenResult( void ) { return 0; }
  910. uint CXboxSystem::OpenContainers( void ) { return 0; }
  911. void CXboxSystem::CloseContainers( void ) {}
  912. uint CXboxSystem::CreateSavegameContainer( uint nCreationFlags ) { return 0; }
  913. uint CXboxSystem::CreateUserSettingsContainer( uint nCreationFlags ) { return 0; }
  914. #endif // defined _X360