1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
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
22 * o Implementation of all things which are associated with dplay on
23 * the computer - i.e. shared resources and such. Methods in this
24 * compilation unit should not call anything outside of this unit
25 * except base windows services and an interface to start the
27 * o Methods that begin with DPLAYX_ are used for dealing with
28 * dplayx.dll data which is accessible from all processes.
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
41 #include "wine/unicode.h"
46 #include "dplayx_global.h"
47 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
49 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
51 /* FIXME: Need to do all that fun other dll referencing type of stuff */
53 /* Static data for all processes */
54 static const char lpszDplayxSemaName[] = "WINE_DPLAYX_SM";
55 static HANDLE hDplayxSema;
57 static const char lpszDplayxFileMapping[] = "WINE_DPLAYX_FM";
58 static HANDLE hDplayxSharedMem;
60 static LPVOID lpSharedStaticData = NULL;
63 #define DPLAYX_AcquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
64 WaitForSingleObject( hDplayxSema, INFINITE );\
65 TRACE( "Through wait\n" )
67 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
68 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
71 /* HACK for simple global data right now */
72 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
73 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
74 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
77 /* FIXME: Is there no easier way? */
79 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
80 * Each block has 4 bytes which are 0 unless used */
81 #define dwBlockSize 512
82 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
87 DWORD data[dwBlockSize-sizeof(DWORD)];
90 static DPLAYX_MEM_SLICE* lpMemArea;
92 void DPLAYX_PrivHeapFree( LPVOID addr );
93 void DPLAYX_PrivHeapFree( LPVOID addr )
98 /* Handle getting passed a NULL */
104 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
105 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
107 lpMemArea[ dwBlockUsed ].used = 0;
110 /* FIXME: This should be static, but is being used for a hack right now */
111 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
112 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
114 LPVOID lpvArea = NULL;
117 if( size > (dwBlockSize - sizeof(DWORD)) )
119 FIXME( "Size exceeded. Request of 0x%08x\n", size );
120 size = dwBlockSize - sizeof(DWORD);
123 /* Find blank area */
125 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
127 if( uBlockUsed <= dwMaxBlock )
129 /* Set the area used */
130 lpMemArea[ uBlockUsed ].used = 1;
131 lpvArea = &(lpMemArea[ uBlockUsed ].data);
135 ERR( "No free block found\n" );
139 if( flags & HEAP_ZERO_MEMORY )
141 ZeroMemory( lpvArea, size );
147 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
148 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
150 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
157 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
158 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
160 INT len = strlenW(str) + 1;
161 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
169 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
170 typedef struct tagDPLAYX_LOBBYDATA
172 /* Points to lpConn + block of contiguous extra memory for dynamic parts
173 * of the struct directly following
175 LPDPLCONNECTION lpConn;
177 /* Information for dplobby interfaces */
179 DWORD dwAppLaunchedFromID;
181 /* Should this lobby app send messages to creator at important life
184 HANDLE hInformOnAppStart;
185 HANDLE hInformOnAppDeath;
186 HANDLE hInformOnSettingRead;
189 BOOL bWaitForConnectionSettings;
190 DWORD dwLobbyMsgThreadId;
193 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
195 static DPLAYX_LOBBYDATA* lobbyData = NULL;
196 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
198 static DPSESSIONDESC2* sessionData = NULL;
199 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
201 /* Function prototypes */
202 static DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpDplData );
203 static DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpDplData );
204 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src );
205 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src );
206 static BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
207 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
208 static BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
209 LPCDPSESSIONDESC2 lpSessionSrc );
210 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart, LPHANDLE lphDeath,
211 LPHANDLE lphConnRead, BOOL bClearSetHandles );
215 /***************************************************************************
216 * Called to initialize the global data. This will only be used on the
218 ***************************************************************************/
219 BOOL DPLAYX_ConstructData(void)
221 SECURITY_ATTRIBUTES s_attrib;
222 BOOL bInitializeSharedMemory = FALSE;
223 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
224 HANDLE hInformOnStart;
226 TRACE( "DPLAYX dll loaded - construct called\n" );
228 /* Create a semaphore to block access to DPLAYX global data structs */
230 s_attrib.bInheritHandle = TRUE;
231 s_attrib.lpSecurityDescriptor = NULL;
232 s_attrib.nLength = sizeof(s_attrib);
234 hDplayxSema = CreateSemaphoreA( &s_attrib, 0, 1, lpszDplayxSemaName );
236 /* First instance creates the semaphore. Others just use it */
237 if( GetLastError() == ERROR_SUCCESS )
239 TRACE( "Semaphore %p created\n", hDplayxSema );
241 /* The semaphore creator will also build the shared memory */
242 bInitializeSharedMemory = TRUE;
244 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
246 TRACE( "Found semaphore handle %p\n", hDplayxSema );
247 DPLAYX_AcquireSemaphore();
251 ERR( ": semaphore error %d\n", GetLastError() );
255 SetLastError( ERROR_SUCCESS );
257 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
259 PAGE_READWRITE | SEC_COMMIT,
262 lpszDplayxFileMapping );
264 if( GetLastError() == ERROR_SUCCESS )
266 TRACE( "File mapped %p created\n", hDplayxSharedMem );
268 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
270 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
274 ERR( ": unable to create shared memory (%d)\n", GetLastError() );
275 DPLAYX_ReleaseSemaphore();
279 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
281 0, 0, 0, lpDesiredMemoryMapStart );
283 if( lpSharedStaticData == NULL )
285 ERR( ": unable to map static data into process memory space (%d)\n",
287 DPLAYX_ReleaseSemaphore();
292 if( lpDesiredMemoryMapStart == lpSharedStaticData )
294 TRACE( "File mapped to %p\n", lpSharedStaticData );
298 /* Presently the shared data structures use pointers. If the
299 * files are no mapped into the same area, the pointers will no
300 * longer make any sense :(
301 * FIXME: In the future make the shared data structures have some
302 * sort of fixup to make them independent between data spaces.
303 * This will also require a rework of the session data stuff.
305 ERR( "File mapped to %p (not %p). Expect failure\n",
306 lpSharedStaticData, lpDesiredMemoryMapStart );
310 /* Dynamic area starts just after the static area */
311 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
313 /* FIXME: Crude hack */
314 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
315 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
317 /* Initialize shared data segments. */
318 if( bInitializeSharedMemory )
322 TRACE( "Initializing shared memory\n" );
324 /* Set all lobbies to be "empty" */
325 for( i=0; i < numSupportedLobbies; i++ )
327 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
330 /* Set all sessions to be "empty" */
331 for( i=0; i < numSupportedSessions; i++ )
333 sessionData[i].dwSize = 0;
336 /* Zero out the dynamic area */
337 ZeroMemory( lpMemArea, dwDynamicSharedSize );
339 /* Just for fun sync the whole data area */
340 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
343 DPLAYX_ReleaseSemaphore();
345 /* Everything was created correctly. Signal the lobby client that
346 * we started up correctly
348 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
353 bSuccess = SetEvent( hInformOnStart );
354 TRACE( "Signalling lobby app start event %p %s\n",
355 hInformOnStart, bSuccess ? "succeed" : "failed" );
357 /* Close out handle */
358 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
364 /***************************************************************************
365 * Called to destroy all global data. This will only be used on the
366 * unloading of the dll
367 ***************************************************************************/
368 BOOL DPLAYX_DestructData(void)
370 HANDLE hInformOnDeath;
372 TRACE( "DPLAYX dll unloaded - destruct called\n" );
374 /* If required, inform that this app is dying */
375 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
380 bSuccess = SetEvent( hInformOnDeath );
381 TRACE( "Signalling lobby app death event %p %s\n",
382 hInformOnDeath, bSuccess ? "succeed" : "failed" );
384 /* Close out handle */
385 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
388 /* DO CLEAN UP (LAST) */
390 /* Delete the semaphore */
391 CloseHandle( hDplayxSema );
393 /* Delete shared memory file mapping */
394 UnmapViewOfFile( lpSharedStaticData );
395 CloseHandle( hDplayxSharedMem );
401 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
403 ZeroMemory( lpData, sizeof( *lpData ) );
406 /* NOTE: This must be called with the semaphore acquired.
407 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
408 * is only valid if TRUE is returned.
410 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
418 dwAppID = GetCurrentProcessId();
419 TRACE( "Translated dwAppID == 0 into 0x%08x\n", dwAppID );
422 for( i=0; i < numSupportedLobbies; i++ )
424 if( lobbyData[ i ].dwAppID == dwAppID )
426 /* This process is lobbied */
427 TRACE( "Found 0x%08x @ %u\n", dwAppID, i );
428 *lplpDplData = &lobbyData[ i ];
436 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
437 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
441 /* 0 is the marker for unused application data slots */
447 DPLAYX_AcquireSemaphore();
449 /* Find an empty space in the list and insert the data */
450 for( i=0; i < numSupportedLobbies; i++ )
452 if( lobbyData[ i ].dwAppID == 0 )
454 /* This process is now lobbied */
455 TRACE( "Setting lobbyData[%u] for (0x%08x,0x%08x)\n",
456 i, dwAppID, GetCurrentProcessId() );
458 lobbyData[ i ].dwAppID = dwAppID;
459 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
461 /* FIXME: Where is the best place for this? In interface or here? */
462 lobbyData[ i ].hInformOnAppStart = 0;
463 lobbyData[ i ].hInformOnAppDeath = 0;
464 lobbyData[ i ].hInformOnSettingRead = 0;
466 DPLAYX_ReleaseSemaphore();
471 ERR( "No empty lobbies\n" );
473 DPLAYX_ReleaseSemaphore();
477 /* I'm not sure when I'm going to need this, but here it is */
478 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
482 DPLAYX_AcquireSemaphore();
484 /* Find an empty space in the list and insert the data */
485 for( i=0; i < numSupportedLobbies; i++ )
487 if( lobbyData[ i ].dwAppID == dwAppID )
489 /* FIXME: Should free up anything unused. Tisk tisk :0 */
490 /* Mark this entry unused */
491 TRACE( "Marking lobbyData[%u] unused\n", i );
492 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
494 DPLAYX_ReleaseSemaphore();
499 DPLAYX_ReleaseSemaphore();
500 ERR( "Unable to find global entry for application\n" );
504 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
505 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
507 LPDPLAYX_LOBBYDATA lpLData;
509 /* Need to explicitly give lobby application. Can't set for yourself */
515 DPLAYX_AcquireSemaphore();
517 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
519 DPLAYX_ReleaseSemaphore();
523 lpLData->hInformOnAppStart = hStart;
524 lpLData->hInformOnAppDeath = hDeath;
525 lpLData->hInformOnSettingRead = hConnRead;
527 DPLAYX_ReleaseSemaphore();
532 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
534 LPHANDLE lphConnRead,
535 BOOL bClearSetHandles )
537 LPDPLAYX_LOBBYDATA lpLData;
539 DPLAYX_AcquireSemaphore();
541 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
543 DPLAYX_ReleaseSemaphore();
547 if( lphStart != NULL )
549 if( lpLData->hInformOnAppStart == 0 )
551 DPLAYX_ReleaseSemaphore();
555 *lphStart = lpLData->hInformOnAppStart;
557 if( bClearSetHandles )
559 CloseHandle( lpLData->hInformOnAppStart );
560 lpLData->hInformOnAppStart = 0;
564 if( lphDeath != NULL )
566 if( lpLData->hInformOnAppDeath == 0 )
568 DPLAYX_ReleaseSemaphore();
572 *lphDeath = lpLData->hInformOnAppDeath;
574 if( bClearSetHandles )
576 CloseHandle( lpLData->hInformOnAppDeath );
577 lpLData->hInformOnAppDeath = 0;
581 if( lphConnRead != NULL )
583 if( lpLData->hInformOnSettingRead == 0 )
585 DPLAYX_ReleaseSemaphore();
589 *lphConnRead = lpLData->hInformOnSettingRead;
591 if( bClearSetHandles )
593 CloseHandle( lpLData->hInformOnSettingRead );
594 lpLData->hInformOnSettingRead = 0;
598 DPLAYX_ReleaseSemaphore();
604 HRESULT DPLAYX_GetConnectionSettingsA
607 LPDWORD lpdwDataSize )
609 LPDPLAYX_LOBBYDATA lpDplData;
610 DWORD dwRequiredDataSize = 0;
611 HANDLE hInformOnSettingRead;
613 DPLAYX_AcquireSemaphore();
615 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
617 DPLAYX_ReleaseSemaphore();
619 TRACE( "Application 0x%08x is not lobbied\n", dwAppID );
620 return DPERR_NOTLOBBIED;
623 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
625 /* Do they want to know the required buffer size or is the provided buffer
628 if ( ( lpData == NULL ) ||
629 ( *lpdwDataSize < dwRequiredDataSize )
632 DPLAYX_ReleaseSemaphore();
634 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
636 return DPERR_BUFFERTOOSMALL;
639 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
641 DPLAYX_ReleaseSemaphore();
643 /* They have gotten the information - signal the event if required */
644 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
649 bSuccess = SetEvent( hInformOnSettingRead );
650 TRACE( "Signalling setting read event %p %s\n",
651 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
653 /* Close out handle */
654 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
660 /* Assumption: Enough contiguous space was allocated at dest */
661 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src )
663 BYTE* lpStartOfFreeSpace;
667 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
669 /* Copy the LPDPSESSIONDESC2 structure if it exists */
670 if( src->lpSessionDesc )
672 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
673 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
674 *dest->lpSessionDesc = *src->lpSessionDesc;
676 /* Session names may or may not exist */
677 if( src->lpSessionDesc->u1.lpszSessionNameA )
679 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
680 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
681 lpStartOfFreeSpace +=
682 strlen( dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
685 if( src->lpSessionDesc->u2.lpszPasswordA )
687 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
688 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
689 lpStartOfFreeSpace +=
690 strlen( dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
694 /* DPNAME structure is optional */
695 if( src->lpPlayerName )
697 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
698 lpStartOfFreeSpace += sizeof( DPNAME );
699 *dest->lpPlayerName = *src->lpPlayerName;
701 if( src->lpPlayerName->u1.lpszShortNameA )
703 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
704 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
705 lpStartOfFreeSpace +=
706 strlen( dest->lpPlayerName->u1.lpszShortNameA ) + 1;
709 if( src->lpPlayerName->u2.lpszLongNameA )
711 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
712 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
713 lpStartOfFreeSpace +=
714 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
719 /* Copy address if it exists */
722 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
723 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
724 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
728 HRESULT DPLAYX_GetConnectionSettingsW
731 LPDWORD lpdwDataSize )
733 LPDPLAYX_LOBBYDATA lpDplData;
734 DWORD dwRequiredDataSize = 0;
735 HANDLE hInformOnSettingRead;
737 DPLAYX_AcquireSemaphore();
739 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
741 DPLAYX_ReleaseSemaphore();
742 return DPERR_NOTLOBBIED;
745 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
747 /* Do they want to know the required buffer size or is the provided buffer
750 if ( ( lpData == NULL ) ||
751 ( *lpdwDataSize < dwRequiredDataSize )
754 DPLAYX_ReleaseSemaphore();
756 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
758 return DPERR_BUFFERTOOSMALL;
761 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
763 DPLAYX_ReleaseSemaphore();
765 /* They have gotten the information - signal the event if required */
766 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
771 bSuccess = SetEvent( hInformOnSettingRead );
772 TRACE( "Signalling setting read event %p %s\n",
773 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
775 /* Close out handle */
776 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
782 /* Assumption: Enough contiguous space was allocated at dest */
783 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src )
785 BYTE* lpStartOfFreeSpace;
789 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
791 /* Copy the LPDPSESSIONDESC2 structure if it exists */
792 if( src->lpSessionDesc )
794 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
795 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
796 *dest->lpSessionDesc = *src->lpSessionDesc;
798 /* Session names may or may not exist */
799 if( src->lpSessionDesc->u1.lpszSessionName )
801 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionName );
802 dest->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
803 lpStartOfFreeSpace += sizeof(WCHAR) *
804 ( strlenW( dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
807 if( src->lpSessionDesc->u2.lpszPassword )
809 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
810 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
811 lpStartOfFreeSpace += sizeof(WCHAR) *
812 ( strlenW( dest->lpSessionDesc->u2.lpszPassword ) + 1 );
816 /* DPNAME structure is optional */
817 if( src->lpPlayerName )
819 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
820 lpStartOfFreeSpace += sizeof( DPNAME );
821 *dest->lpPlayerName = *src->lpPlayerName;
823 if( src->lpPlayerName->u1.lpszShortName )
825 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
826 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
827 lpStartOfFreeSpace += sizeof(WCHAR) *
828 ( strlenW( dest->lpPlayerName->u1.lpszShortName ) + 1 );
831 if( src->lpPlayerName->u2.lpszLongName )
833 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
834 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
835 lpStartOfFreeSpace += sizeof(WCHAR) *
836 ( strlenW( dest->lpPlayerName->u2.lpszLongName ) + 1 );
841 /* Copy address if it exists */
844 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
845 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
846 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
851 /* Store the structure into the shared data structure. Ensure that allocs for
852 * variable length strings come from the shared data structure.
853 * FIXME: We need to free information as well.
855 HRESULT DPLAYX_SetConnectionSettingsA
858 const DPLCONNECTION *lpConn )
860 LPDPLAYX_LOBBYDATA lpDplData;
862 /* Parameter check */
863 if( dwFlags || !lpConn )
865 ERR("invalid parameters.\n");
866 return DPERR_INVALIDPARAMS;
869 /* Store information */
870 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
872 ERR(": old/new DPLCONNECTION type? Size=%08x\n", lpConn->dwSize );
874 return DPERR_INVALIDPARAMS;
877 DPLAYX_AcquireSemaphore();
879 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
881 DPLAYX_ReleaseSemaphore();
883 return DPERR_NOTLOBBIED;
886 if( (!lpConn->lpSessionDesc ) ||
887 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
890 DPLAYX_ReleaseSemaphore();
892 ERR("DPSESSIONDESC passed in? Size=%u\n", lpConn->lpSessionDesc->dwSize );
894 return DPERR_INVALIDPARAMS;
897 /* Free the existing memory */
898 DPLAYX_PrivHeapFree( lpDplData->lpConn );
900 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
901 DPLAYX_SizeOfLobbyDataA( lpConn ) );
903 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
906 DPLAYX_ReleaseSemaphore();
908 /* FIXME: Send a message - I think */
913 /* Store the structure into the shared data structure. Ensure that allocs for
914 * variable length strings come from the shared data structure.
915 * FIXME: We need to free information as well
917 HRESULT DPLAYX_SetConnectionSettingsW
920 const DPLCONNECTION *lpConn )
922 LPDPLAYX_LOBBYDATA lpDplData;
924 /* Parameter check */
925 if( dwFlags || !lpConn )
927 ERR("invalid parameters.\n");
928 return DPERR_INVALIDPARAMS;
931 /* Store information */
932 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
934 ERR(": old/new DPLCONNECTION type? Size=%u\n", lpConn->dwSize );
936 return DPERR_INVALIDPARAMS;
939 DPLAYX_AcquireSemaphore();
941 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
943 DPLAYX_ReleaseSemaphore();
945 return DPERR_NOTLOBBIED;
948 /* Free the existing memory */
949 DPLAYX_PrivHeapFree( lpDplData->lpConn );
951 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
952 DPLAYX_SizeOfLobbyDataW( lpConn ) );
954 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
957 DPLAYX_ReleaseSemaphore();
959 /* FIXME: Send a message - I think */
964 DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpConn )
966 DWORD dwTotalSize = sizeof( DPLCONNECTION );
968 /* Just a safety check */
971 ERR( "lpConn is NULL\n" );
975 if( lpConn->lpSessionDesc != NULL )
977 dwTotalSize += sizeof( DPSESSIONDESC2 );
979 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
981 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
984 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
986 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
990 if( lpConn->lpPlayerName != NULL )
992 dwTotalSize += sizeof( DPNAME );
994 if( lpConn->lpPlayerName->u1.lpszShortNameA )
996 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
999 if( lpConn->lpPlayerName->u2.lpszLongNameA )
1001 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
1006 dwTotalSize += lpConn->dwAddressSize;
1011 DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpConn )
1013 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1015 /* Just a safety check */
1016 if( lpConn == NULL )
1018 ERR( "lpConn is NULL\n" );
1022 if( lpConn->lpSessionDesc != NULL )
1024 dwTotalSize += sizeof( DPSESSIONDESC2 );
1026 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1032 if( lpConn->lpSessionDesc->u2.lpszPassword )
1034 dwTotalSize += sizeof( WCHAR ) *
1035 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1039 if( lpConn->lpPlayerName != NULL )
1041 dwTotalSize += sizeof( DPNAME );
1043 if( lpConn->lpPlayerName->u1.lpszShortName )
1045 dwTotalSize += sizeof( WCHAR ) *
1046 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1049 if( lpConn->lpPlayerName->u2.lpszLongName )
1051 dwTotalSize += sizeof( WCHAR ) *
1052 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1057 dwTotalSize += lpConn->dwAddressSize;
1064 static LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1066 LPDPSESSIONDESC2 lpSessionDest =
1067 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1068 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1070 return lpSessionDest;
1073 /* Copy an ANSI session desc structure to the given buffer */
1074 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1075 LPCDPSESSIONDESC2 lpSessionSrc )
1077 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1079 if( lpSessionSrc->u1.lpszSessionNameA )
1081 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1082 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1083 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1085 if( lpSessionSrc->u2.lpszPasswordA )
1087 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1088 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1089 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1095 /* Start the index at 0. index will be updated to equal that which should
1096 be passed back into this function for the next element */
1097 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1099 for( ; (*index) < numSupportedSessions; (*index)++ )
1101 if( sessionData[(*index)].dwSize != 0 )
1103 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1107 /* No more sessions */
1111 /* Start the index at 0. index will be updated to equal that which should
1112 be passed back into this function for the next element */
1113 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1115 for( ; (*index) < numSupportedSessions; (*index)++ )
1117 if( sessionData[(*index)].dwSize != 0 )
1119 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1123 /* No more sessions */
1127 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1131 /* FIXME: Is this an error if it exists already? */
1133 /* Crude/wrong implementation for now. Just always add to first empty spot */
1134 for( i=0; i < numSupportedSessions; i++ )
1136 /* Is this one empty? */
1137 if( sessionData[i].dwSize == 0 )
1139 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1146 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1148 LPDPLAYX_LOBBYDATA lpLobbyData;
1150 DPLAYX_AcquireSemaphore();
1152 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1154 DPLAYX_ReleaseSemaphore();
1158 lpLobbyData->bWaitForConnectionSettings = bWait;
1160 DPLAYX_ReleaseSemaphore();
1165 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1168 BOOL bFound = FALSE;
1170 DPLAYX_AcquireSemaphore();
1172 for( i=0; i < numSupportedLobbies; i++ )
1174 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1175 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1183 DPLAYX_ReleaseSemaphore();
1188 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1190 LPDPLAYX_LOBBYDATA lpLobbyData;
1192 DPLAYX_AcquireSemaphore();
1194 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1196 DPLAYX_ReleaseSemaphore();
1200 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1202 DPLAYX_ReleaseSemaphore();
1207 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1208 with the correct string printed in the case where the HRESULT is not
1209 known. You will just get the last hr passed in. This can change
1210 over time if this method is used a lot :) */
1211 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1213 static char szTempStr[12];
1219 case DPERR_ALREADYINITIALIZED:
1220 return "DPERR_ALREADYINITIALIZED";
1221 case DPERR_ACCESSDENIED:
1222 return "DPERR_ACCESSDENIED";
1223 case DPERR_ACTIVEPLAYERS:
1224 return "DPERR_ACTIVEPLAYERS";
1225 case DPERR_BUFFERTOOSMALL:
1226 return "DPERR_BUFFERTOOSMALL";
1227 case DPERR_CANTADDPLAYER:
1228 return "DPERR_CANTADDPLAYER";
1229 case DPERR_CANTCREATEGROUP:
1230 return "DPERR_CANTCREATEGROUP";
1231 case DPERR_CANTCREATEPLAYER:
1232 return "DPERR_CANTCREATEPLAYER";
1233 case DPERR_CANTCREATESESSION:
1234 return "DPERR_CANTCREATESESSION";
1235 case DPERR_CAPSNOTAVAILABLEYET:
1236 return "DPERR_CAPSNOTAVAILABLEYET";
1237 case DPERR_EXCEPTION:
1238 return "DPERR_EXCEPTION";
1240 return "DPERR_GENERIC";
1241 case DPERR_INVALIDFLAGS:
1242 return "DPERR_INVALIDFLAGS";
1243 case DPERR_INVALIDOBJECT:
1244 return "DPERR_INVALIDOBJECT";
1245 case DPERR_INVALIDPARAMS:
1246 return "DPERR_INVALIDPARAMS";
1247 case DPERR_INVALIDPLAYER:
1248 return "DPERR_INVALIDPLAYER";
1249 case DPERR_INVALIDGROUP:
1250 return "DPERR_INVALIDGROUP";
1252 return "DPERR_NOCAPS";
1253 case DPERR_NOCONNECTION:
1254 return "DPERR_NOCONNECTION";
1255 case DPERR_OUTOFMEMORY:
1256 return "DPERR_OUTOFMEMORY";
1257 case DPERR_NOMESSAGES:
1258 return "DPERR_NOMESSAGES";
1259 case DPERR_NONAMESERVERFOUND:
1260 return "DPERR_NONAMESERVERFOUND";
1261 case DPERR_NOPLAYERS:
1262 return "DPERR_NOPLAYERS";
1263 case DPERR_NOSESSIONS:
1264 return "DPERR_NOSESSIONS";
1266 return "DPERR_PENDING";
1267 case DPERR_SENDTOOBIG:
1268 return "DPERR_SENDTOOBIG";
1270 return "DPERR_TIMEOUT";
1271 case DPERR_UNAVAILABLE:
1272 return "DPERR_UNAVAILABLE";
1273 case DPERR_UNSUPPORTED:
1274 return "DPERR_UNSUPPORTED";
1276 return "DPERR_BUSY";
1277 case DPERR_USERCANCEL:
1278 return "DPERR_USERCANCEL";
1279 case DPERR_NOINTERFACE:
1280 return "DPERR_NOINTERFACE";
1281 case DPERR_CANNOTCREATESERVER:
1282 return "DPERR_CANNOTCREATESERVER";
1283 case DPERR_PLAYERLOST:
1284 return "DPERR_PLAYERLOST";
1285 case DPERR_SESSIONLOST:
1286 return "DPERR_SESSIONLOST";
1287 case DPERR_UNINITIALIZED:
1288 return "DPERR_UNINITIALIZED";
1289 case DPERR_NONEWPLAYERS:
1290 return "DPERR_NONEWPLAYERS";
1291 case DPERR_INVALIDPASSWORD:
1292 return "DPERR_INVALIDPASSWORD";
1293 case DPERR_CONNECTING:
1294 return "DPERR_CONNECTING";
1295 case DPERR_CONNECTIONLOST:
1296 return "DPERR_CONNECTIONLOST";
1297 case DPERR_UNKNOWNMESSAGE:
1298 return "DPERR_UNKNOWNMESSAGE";
1299 case DPERR_CANCELFAILED:
1300 return "DPERR_CANCELFAILED";
1301 case DPERR_INVALIDPRIORITY:
1302 return "DPERR_INVALIDPRIORITY";
1303 case DPERR_NOTHANDLED:
1304 return "DPERR_NOTHANDLED";
1305 case DPERR_CANCELLED:
1306 return "DPERR_CANCELLED";
1308 return "DPERR_ABORTED";
1309 case DPERR_BUFFERTOOLARGE:
1310 return "DPERR_BUFFERTOOLARGE";
1311 case DPERR_CANTCREATEPROCESS:
1312 return "DPERR_CANTCREATEPROCESS";
1313 case DPERR_APPNOTSTARTED:
1314 return "DPERR_APPNOTSTARTED";
1315 case DPERR_INVALIDINTERFACE:
1316 return "DPERR_INVALIDINTERFACE";
1317 case DPERR_NOSERVICEPROVIDER:
1318 return "DPERR_NOSERVICEPROVIDER";
1319 case DPERR_UNKNOWNAPPLICATION:
1320 return "DPERR_UNKNOWNAPPLICATION";
1321 case DPERR_NOTLOBBIED:
1322 return "DPERR_NOTLOBBIED";
1323 case DPERR_SERVICEPROVIDERLOADED:
1324 return "DPERR_SERVICEPROVIDERLOADED";
1325 case DPERR_ALREADYREGISTERED:
1326 return "DPERR_ALREADYREGISTERED";
1327 case DPERR_NOTREGISTERED:
1328 return "DPERR_NOTREGISTERED";
1329 case DPERR_AUTHENTICATIONFAILED:
1330 return "DPERR_AUTHENTICATIONFAILED";
1331 case DPERR_CANTLOADSSPI:
1332 return "DPERR_CANTLOADSSPI";
1333 case DPERR_ENCRYPTIONFAILED:
1334 return "DPERR_ENCRYPTIONFAILED";
1335 case DPERR_SIGNFAILED:
1336 return "DPERR_SIGNFAILED";
1337 case DPERR_CANTLOADSECURITYPACKAGE:
1338 return "DPERR_CANTLOADSECURITYPACKAGE";
1339 case DPERR_ENCRYPTIONNOTSUPPORTED:
1340 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1341 case DPERR_CANTLOADCAPI:
1342 return "DPERR_CANTLOADCAPI";
1343 case DPERR_NOTLOGGEDIN:
1344 return "DPERR_NOTLOGGEDIN";
1345 case DPERR_LOGONDENIED:
1346 return "DPERR_LOGONDENIED";
1348 /* For errors not in the list, return HRESULT as a string
1349 This part is not thread safe */
1350 WARN( "Unknown error 0x%08x\n", hr );
1351 wsprintfA( szTempStr, "0x%08lx", hr );