push e7552b73e75828caa36d732caa646c0c70d8de9d
[wine/hacks.git] / dlls / dplayx / dplayx_global.c
blob938ade98082ee6838d2a701455ae17db5123e366
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
21 * NOTES:
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
26 * messaging thread.
27 * o Methods that begin with DPLAYX_ are used for dealing with
28 * dplayx.dll data which is accessible from all processes.
32 #include <stdarg.h>
33 #include <string.h>
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41 #include "wine/unicode.h"
43 #include "wingdi.h"
44 #include "winuser.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)
84 typedef struct
86 DWORD used;
87 DWORD data[dwBlockSize-sizeof(DWORD)];
88 } DPLAYX_MEM_SLICE;
90 static DPLAYX_MEM_SLICE* lpMemArea;
92 static void DPLAYX_PrivHeapFree( LPVOID addr )
94 LPVOID lpAddrStart;
95 DWORD dwBlockUsed;
97 /* Handle getting passed a NULL */
98 if( addr == NULL )
100 return;
103 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
104 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
106 lpMemArea[ dwBlockUsed ].used = 0;
109 static LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
111 LPVOID lpvArea = NULL;
112 UINT uBlockUsed;
114 if( size > (dwBlockSize - sizeof(DWORD)) )
116 FIXME( "Size exceeded. Request of 0x%08x\n", size );
117 size = dwBlockSize - sizeof(DWORD);
120 /* Find blank area */
121 uBlockUsed = 0;
122 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
124 if( uBlockUsed <= dwMaxBlock )
126 /* Set the area used */
127 lpMemArea[ uBlockUsed ].used = 1;
128 lpvArea = lpMemArea[ uBlockUsed ].data;
130 else
132 ERR( "No free block found\n" );
133 return NULL;
136 if( flags & HEAP_ZERO_MEMORY )
138 ZeroMemory( lpvArea, size );
141 return lpvArea;
145 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
146 typedef struct tagDPLAYX_LOBBYDATA
148 /* Points to lpConn + block of contiguous extra memory for dynamic parts
149 * of the struct directly following
151 LPDPLCONNECTION lpConn;
153 /* Information for dplobby interfaces */
154 DWORD dwAppID;
155 DWORD dwAppLaunchedFromID;
157 /* Should this lobby app send messages to creator at important life
158 * stages
160 HANDLE hInformOnAppStart;
161 HANDLE hInformOnAppDeath;
162 HANDLE hInformOnSettingRead;
164 /* Sundries */
165 BOOL bWaitForConnectionSettings;
166 DWORD dwLobbyMsgThreadId;
169 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
171 static DPLAYX_LOBBYDATA* lobbyData = NULL;
172 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
174 static DPSESSIONDESC2* sessionData = NULL;
175 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
177 /* Function prototypes */
178 static DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpDplData );
179 static DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpDplData );
180 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src );
181 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src );
182 static BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
183 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
184 static BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
185 LPCDPSESSIONDESC2 lpSessionSrc );
186 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart, LPHANDLE lphDeath,
187 LPHANDLE lphConnRead, BOOL bClearSetHandles );
191 /***************************************************************************
192 * Called to initialize the global data. This will only be used on the
193 * loading of the dll
194 ***************************************************************************/
195 BOOL DPLAYX_ConstructData(void)
197 SECURITY_ATTRIBUTES s_attrib;
198 BOOL bInitializeSharedMemory = FALSE;
199 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
200 HANDLE hInformOnStart;
202 TRACE( "DPLAYX dll loaded - construct called\n" );
204 /* Create a semaphore to block access to DPLAYX global data structs */
206 s_attrib.bInheritHandle = TRUE;
207 s_attrib.lpSecurityDescriptor = NULL;
208 s_attrib.nLength = sizeof(s_attrib);
210 hDplayxSema = CreateSemaphoreA( &s_attrib, 0, 1, lpszDplayxSemaName );
212 /* First instance creates the semaphore. Others just use it */
213 if( GetLastError() == ERROR_SUCCESS )
215 TRACE( "Semaphore %p created\n", hDplayxSema );
217 /* The semaphore creator will also build the shared memory */
218 bInitializeSharedMemory = TRUE;
220 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
222 TRACE( "Found semaphore handle %p\n", hDplayxSema );
223 DPLAYX_AcquireSemaphore();
225 else
227 ERR( ": semaphore error %d\n", GetLastError() );
228 return FALSE;
231 SetLastError( ERROR_SUCCESS );
233 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
234 &s_attrib,
235 PAGE_READWRITE | SEC_COMMIT,
237 dwTotalSharedSize,
238 lpszDplayxFileMapping );
240 if( GetLastError() == ERROR_SUCCESS )
242 TRACE( "File mapped %p created\n", hDplayxSharedMem );
244 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
246 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
248 else
250 ERR( ": unable to create shared memory (%d)\n", GetLastError() );
251 DPLAYX_ReleaseSemaphore();
252 return FALSE;
255 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
256 FILE_MAP_WRITE,
257 0, 0, 0, lpDesiredMemoryMapStart );
259 if( lpSharedStaticData == NULL )
261 ERR( ": unable to map static data into process memory space (%d)\n",
262 GetLastError() );
263 DPLAYX_ReleaseSemaphore();
264 return FALSE;
266 else
268 if( lpDesiredMemoryMapStart == lpSharedStaticData )
270 TRACE( "File mapped to %p\n", lpSharedStaticData );
272 else
274 /* Presently the shared data structures use pointers. If the
275 * files are no mapped into the same area, the pointers will no
276 * longer make any sense :(
277 * FIXME: In the future make the shared data structures have some
278 * sort of fixup to make them independent between data spaces.
279 * This will also require a rework of the session data stuff.
281 ERR( "File mapped to %p (not %p). Expect failure\n",
282 lpSharedStaticData, lpDesiredMemoryMapStart );
286 /* Dynamic area starts just after the static area */
287 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
289 /* FIXME: Crude hack */
290 lobbyData = lpSharedStaticData;
291 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
293 /* Initialize shared data segments. */
294 if( bInitializeSharedMemory )
296 UINT i;
298 TRACE( "Initializing shared memory\n" );
300 /* Set all lobbies to be "empty" */
301 for( i=0; i < numSupportedLobbies; i++ )
303 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
306 /* Set all sessions to be "empty" */
307 for( i=0; i < numSupportedSessions; i++ )
309 sessionData[i].dwSize = 0;
312 /* Zero out the dynamic area */
313 ZeroMemory( lpMemArea, dwDynamicSharedSize );
315 /* Just for fun sync the whole data area */
316 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
319 DPLAYX_ReleaseSemaphore();
321 /* Everything was created correctly. Signal the lobby client that
322 * we started up correctly
324 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
325 hInformOnStart
328 BOOL bSuccess;
329 bSuccess = SetEvent( hInformOnStart );
330 TRACE( "Signalling lobby app start event %p %s\n",
331 hInformOnStart, bSuccess ? "succeed" : "failed" );
333 /* Close out handle */
334 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
337 return TRUE;
340 /***************************************************************************
341 * Called to destroy all global data. This will only be used on the
342 * unloading of the dll
343 ***************************************************************************/
344 BOOL DPLAYX_DestructData(void)
346 HANDLE hInformOnDeath;
348 TRACE( "DPLAYX dll unloaded - destruct called\n" );
350 /* If required, inform that this app is dying */
351 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
352 hInformOnDeath
355 BOOL bSuccess;
356 bSuccess = SetEvent( hInformOnDeath );
357 TRACE( "Signalling lobby app death event %p %s\n",
358 hInformOnDeath, bSuccess ? "succeed" : "failed" );
360 /* Close out handle */
361 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
364 /* DO CLEAN UP (LAST) */
366 /* Delete the semaphore */
367 CloseHandle( hDplayxSema );
369 /* Delete shared memory file mapping */
370 UnmapViewOfFile( lpSharedStaticData );
371 CloseHandle( hDplayxSharedMem );
373 return FALSE;
377 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
379 ZeroMemory( lpData, sizeof( *lpData ) );
382 /* NOTE: This must be called with the semaphore acquired.
383 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
384 * is only valid if TRUE is returned.
386 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
388 UINT i;
390 *lplpDplData = NULL;
392 if( dwAppID == 0 )
394 dwAppID = GetCurrentProcessId();
395 TRACE( "Translated dwAppID == 0 into 0x%08x\n", dwAppID );
398 for( i=0; i < numSupportedLobbies; i++ )
400 if( lobbyData[ i ].dwAppID == dwAppID )
402 /* This process is lobbied */
403 TRACE( "Found 0x%08x @ %u\n", dwAppID, i );
404 *lplpDplData = &lobbyData[ i ];
405 return TRUE;
409 return FALSE;
412 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
413 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
415 UINT i;
417 /* 0 is the marker for unused application data slots */
418 if( dwAppID == 0 )
420 return FALSE;
423 DPLAYX_AcquireSemaphore();
425 /* Find an empty space in the list and insert the data */
426 for( i=0; i < numSupportedLobbies; i++ )
428 if( lobbyData[ i ].dwAppID == 0 )
430 /* This process is now lobbied */
431 TRACE( "Setting lobbyData[%u] for (0x%08x,0x%08x)\n",
432 i, dwAppID, GetCurrentProcessId() );
434 lobbyData[ i ].dwAppID = dwAppID;
435 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
437 /* FIXME: Where is the best place for this? In interface or here? */
438 lobbyData[ i ].hInformOnAppStart = 0;
439 lobbyData[ i ].hInformOnAppDeath = 0;
440 lobbyData[ i ].hInformOnSettingRead = 0;
442 DPLAYX_ReleaseSemaphore();
443 return TRUE;
447 ERR( "No empty lobbies\n" );
449 DPLAYX_ReleaseSemaphore();
450 return FALSE;
453 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
454 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
456 LPDPLAYX_LOBBYDATA lpLData;
458 /* Need to explicitly give lobby application. Can't set for yourself */
459 if( dwAppID == 0 )
461 return FALSE;
464 DPLAYX_AcquireSemaphore();
466 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
468 DPLAYX_ReleaseSemaphore();
469 return FALSE;
472 lpLData->hInformOnAppStart = hStart;
473 lpLData->hInformOnAppDeath = hDeath;
474 lpLData->hInformOnSettingRead = hConnRead;
476 DPLAYX_ReleaseSemaphore();
478 return TRUE;
481 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
482 LPHANDLE lphDeath,
483 LPHANDLE lphConnRead,
484 BOOL bClearSetHandles )
486 LPDPLAYX_LOBBYDATA lpLData;
488 DPLAYX_AcquireSemaphore();
490 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
492 DPLAYX_ReleaseSemaphore();
493 return FALSE;
496 if( lphStart != NULL )
498 if( lpLData->hInformOnAppStart == 0 )
500 DPLAYX_ReleaseSemaphore();
501 return FALSE;
504 *lphStart = lpLData->hInformOnAppStart;
506 if( bClearSetHandles )
508 CloseHandle( lpLData->hInformOnAppStart );
509 lpLData->hInformOnAppStart = 0;
513 if( lphDeath != NULL )
515 if( lpLData->hInformOnAppDeath == 0 )
517 DPLAYX_ReleaseSemaphore();
518 return FALSE;
521 *lphDeath = lpLData->hInformOnAppDeath;
523 if( bClearSetHandles )
525 CloseHandle( lpLData->hInformOnAppDeath );
526 lpLData->hInformOnAppDeath = 0;
530 if( lphConnRead != NULL )
532 if( lpLData->hInformOnSettingRead == 0 )
534 DPLAYX_ReleaseSemaphore();
535 return FALSE;
538 *lphConnRead = lpLData->hInformOnSettingRead;
540 if( bClearSetHandles )
542 CloseHandle( lpLData->hInformOnSettingRead );
543 lpLData->hInformOnSettingRead = 0;
547 DPLAYX_ReleaseSemaphore();
549 return TRUE;
553 HRESULT DPLAYX_GetConnectionSettingsA
554 ( DWORD dwAppID,
555 LPVOID lpData,
556 LPDWORD lpdwDataSize )
558 LPDPLAYX_LOBBYDATA lpDplData;
559 DWORD dwRequiredDataSize = 0;
560 HANDLE hInformOnSettingRead;
562 DPLAYX_AcquireSemaphore();
564 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
566 DPLAYX_ReleaseSemaphore();
568 TRACE( "Application 0x%08x is not lobbied\n", dwAppID );
569 return DPERR_NOTLOBBIED;
572 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
574 /* Do they want to know the required buffer size or is the provided buffer
575 * big enough?
577 if ( ( lpData == NULL ) ||
578 ( *lpdwDataSize < dwRequiredDataSize )
581 DPLAYX_ReleaseSemaphore();
583 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
585 return DPERR_BUFFERTOOSMALL;
588 DPLAYX_CopyConnStructA( lpData, lpDplData->lpConn );
590 DPLAYX_ReleaseSemaphore();
592 /* They have gotten the information - signal the event if required */
593 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
594 hInformOnSettingRead
597 BOOL bSuccess;
598 bSuccess = SetEvent( hInformOnSettingRead );
599 TRACE( "Signalling setting read event %p %s\n",
600 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
602 /* Close out handle */
603 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
606 return DP_OK;
609 /* Assumption: Enough contiguous space was allocated at dest */
610 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src )
612 BYTE* lpStartOfFreeSpace;
614 *dest = *src;
616 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
618 /* Copy the LPDPSESSIONDESC2 structure if it exists */
619 if( src->lpSessionDesc )
621 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
622 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
623 *dest->lpSessionDesc = *src->lpSessionDesc;
625 /* Session names may or may not exist */
626 if( src->lpSessionDesc->u1.lpszSessionNameA )
628 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
629 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
630 lpStartOfFreeSpace +=
631 strlen( dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
634 if( src->lpSessionDesc->u2.lpszPasswordA )
636 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
637 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
638 lpStartOfFreeSpace +=
639 strlen( dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
643 /* DPNAME structure is optional */
644 if( src->lpPlayerName )
646 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
647 lpStartOfFreeSpace += sizeof( DPNAME );
648 *dest->lpPlayerName = *src->lpPlayerName;
650 if( src->lpPlayerName->u1.lpszShortNameA )
652 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
653 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
654 lpStartOfFreeSpace +=
655 strlen( dest->lpPlayerName->u1.lpszShortNameA ) + 1;
658 if( src->lpPlayerName->u2.lpszLongNameA )
660 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
661 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
662 lpStartOfFreeSpace +=
663 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
668 /* Copy address if it exists */
669 if( src->lpAddress )
671 dest->lpAddress = lpStartOfFreeSpace;
672 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
673 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
677 HRESULT DPLAYX_GetConnectionSettingsW
678 ( DWORD dwAppID,
679 LPVOID lpData,
680 LPDWORD lpdwDataSize )
682 LPDPLAYX_LOBBYDATA lpDplData;
683 DWORD dwRequiredDataSize = 0;
684 HANDLE hInformOnSettingRead;
686 DPLAYX_AcquireSemaphore();
688 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
690 DPLAYX_ReleaseSemaphore();
691 return DPERR_NOTLOBBIED;
694 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
696 /* Do they want to know the required buffer size or is the provided buffer
697 * big enough?
699 if ( ( lpData == NULL ) ||
700 ( *lpdwDataSize < dwRequiredDataSize )
703 DPLAYX_ReleaseSemaphore();
705 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
707 return DPERR_BUFFERTOOSMALL;
710 DPLAYX_CopyConnStructW( lpData, lpDplData->lpConn );
712 DPLAYX_ReleaseSemaphore();
714 /* They have gotten the information - signal the event if required */
715 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
716 hInformOnSettingRead
719 BOOL bSuccess;
720 bSuccess = SetEvent( hInformOnSettingRead );
721 TRACE( "Signalling setting read event %p %s\n",
722 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
724 /* Close out handle */
725 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
728 return DP_OK;
731 /* Assumption: Enough contiguous space was allocated at dest */
732 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src )
734 BYTE* lpStartOfFreeSpace;
736 *dest = *src;
738 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
740 /* Copy the LPDPSESSIONDESC2 structure if it exists */
741 if( src->lpSessionDesc )
743 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
744 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
745 *dest->lpSessionDesc = *src->lpSessionDesc;
747 /* Session names may or may not exist */
748 if( src->lpSessionDesc->u1.lpszSessionName )
750 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionName );
751 dest->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
752 lpStartOfFreeSpace += sizeof(WCHAR) *
753 ( strlenW( dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
756 if( src->lpSessionDesc->u2.lpszPassword )
758 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
759 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
760 lpStartOfFreeSpace += sizeof(WCHAR) *
761 ( strlenW( dest->lpSessionDesc->u2.lpszPassword ) + 1 );
765 /* DPNAME structure is optional */
766 if( src->lpPlayerName )
768 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
769 lpStartOfFreeSpace += sizeof( DPNAME );
770 *dest->lpPlayerName = *src->lpPlayerName;
772 if( src->lpPlayerName->u1.lpszShortName )
774 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
775 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
776 lpStartOfFreeSpace += sizeof(WCHAR) *
777 ( strlenW( dest->lpPlayerName->u1.lpszShortName ) + 1 );
780 if( src->lpPlayerName->u2.lpszLongName )
782 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
783 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
784 lpStartOfFreeSpace += sizeof(WCHAR) *
785 ( strlenW( dest->lpPlayerName->u2.lpszLongName ) + 1 );
790 /* Copy address if it exists */
791 if( src->lpAddress )
793 dest->lpAddress = lpStartOfFreeSpace;
794 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
795 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
800 /* Store the structure into the shared data structure. Ensure that allocs for
801 * variable length strings come from the shared data structure.
802 * FIXME: We need to free information as well.
804 HRESULT DPLAYX_SetConnectionSettingsA
805 ( DWORD dwFlags,
806 DWORD dwAppID,
807 const DPLCONNECTION *lpConn )
809 LPDPLAYX_LOBBYDATA lpDplData;
811 /* Parameter check */
812 if( dwFlags || !lpConn )
814 ERR("invalid parameters.\n");
815 return DPERR_INVALIDPARAMS;
818 /* Store information */
819 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
821 ERR(": old/new DPLCONNECTION type? Size=%08x\n", lpConn->dwSize );
823 return DPERR_INVALIDPARAMS;
826 DPLAYX_AcquireSemaphore();
828 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
830 DPLAYX_ReleaseSemaphore();
832 return DPERR_NOTLOBBIED;
835 if( (!lpConn->lpSessionDesc ) ||
836 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
839 DPLAYX_ReleaseSemaphore();
841 ERR("DPSESSIONDESC passed in? Size=%u\n",
842 lpConn->lpSessionDesc?lpConn->lpSessionDesc->dwSize:0 );
844 return DPERR_INVALIDPARAMS;
847 /* Free the existing memory */
848 DPLAYX_PrivHeapFree( lpDplData->lpConn );
850 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
851 DPLAYX_SizeOfLobbyDataA( lpConn ) );
853 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
856 DPLAYX_ReleaseSemaphore();
858 /* FIXME: Send a message - I think */
860 return DP_OK;
863 /* Store the structure into the shared data structure. Ensure that allocs for
864 * variable length strings come from the shared data structure.
865 * FIXME: We need to free information as well
867 HRESULT DPLAYX_SetConnectionSettingsW
868 ( DWORD dwFlags,
869 DWORD dwAppID,
870 const DPLCONNECTION *lpConn )
872 LPDPLAYX_LOBBYDATA lpDplData;
874 /* Parameter check */
875 if( dwFlags || !lpConn )
877 ERR("invalid parameters.\n");
878 return DPERR_INVALIDPARAMS;
881 /* Store information */
882 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
884 ERR(": old/new DPLCONNECTION type? Size=%u\n", lpConn->dwSize );
886 return DPERR_INVALIDPARAMS;
889 DPLAYX_AcquireSemaphore();
891 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
893 DPLAYX_ReleaseSemaphore();
895 return DPERR_NOTLOBBIED;
898 /* Free the existing memory */
899 DPLAYX_PrivHeapFree( lpDplData->lpConn );
901 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
902 DPLAYX_SizeOfLobbyDataW( lpConn ) );
904 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
907 DPLAYX_ReleaseSemaphore();
909 /* FIXME: Send a message - I think */
911 return DP_OK;
914 DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpConn )
916 DWORD dwTotalSize = sizeof( DPLCONNECTION );
918 /* Just a safety check */
919 if( lpConn == NULL )
921 ERR( "lpConn is NULL\n" );
922 return 0;
925 if( lpConn->lpSessionDesc != NULL )
927 dwTotalSize += sizeof( DPSESSIONDESC2 );
929 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
931 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
934 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
936 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
940 if( lpConn->lpPlayerName != NULL )
942 dwTotalSize += sizeof( DPNAME );
944 if( lpConn->lpPlayerName->u1.lpszShortNameA )
946 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
949 if( lpConn->lpPlayerName->u2.lpszLongNameA )
951 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
956 dwTotalSize += lpConn->dwAddressSize;
958 return dwTotalSize;
961 DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpConn )
963 DWORD dwTotalSize = sizeof( DPLCONNECTION );
965 /* Just a safety check */
966 if( lpConn == NULL )
968 ERR( "lpConn is NULL\n" );
969 return 0;
972 if( lpConn->lpSessionDesc != NULL )
974 dwTotalSize += sizeof( DPSESSIONDESC2 );
976 if( lpConn->lpSessionDesc->u1.lpszSessionName )
978 dwTotalSize += sizeof( WCHAR ) *
979 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
982 if( lpConn->lpSessionDesc->u2.lpszPassword )
984 dwTotalSize += sizeof( WCHAR ) *
985 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
989 if( lpConn->lpPlayerName != NULL )
991 dwTotalSize += sizeof( DPNAME );
993 if( lpConn->lpPlayerName->u1.lpszShortName )
995 dwTotalSize += sizeof( WCHAR ) *
996 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
999 if( lpConn->lpPlayerName->u2.lpszLongName )
1001 dwTotalSize += sizeof( WCHAR ) *
1002 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1007 dwTotalSize += lpConn->dwAddressSize;
1009 return dwTotalSize;
1014 /* Copy an ANSI session desc structure to the given buffer */
1015 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1016 LPCDPSESSIONDESC2 lpSessionSrc )
1018 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1020 if( lpSessionSrc->u1.lpszSessionNameA )
1022 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1023 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1024 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1026 if( lpSessionSrc->u2.lpszPasswordA )
1028 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1029 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1030 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1033 return TRUE;
1036 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1038 UINT i;
1040 /* FIXME: Is this an error if it exists already? */
1042 /* Crude/wrong implementation for now. Just always add to first empty spot */
1043 for( i=0; i < numSupportedSessions; i++ )
1045 /* Is this one empty? */
1046 if( sessionData[i].dwSize == 0 )
1048 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1049 break;
1055 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1057 LPDPLAYX_LOBBYDATA lpLobbyData;
1059 DPLAYX_AcquireSemaphore();
1061 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1063 DPLAYX_ReleaseSemaphore();
1064 return FALSE;
1067 lpLobbyData->bWaitForConnectionSettings = bWait;
1069 DPLAYX_ReleaseSemaphore();
1071 return TRUE;
1074 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1076 UINT i;
1077 BOOL bFound = FALSE;
1079 DPLAYX_AcquireSemaphore();
1081 for( i=0; i < numSupportedLobbies; i++ )
1083 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1084 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1087 bFound = TRUE;
1088 break;
1092 DPLAYX_ReleaseSemaphore();
1094 return bFound;
1097 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1099 LPDPLAYX_LOBBYDATA lpLobbyData;
1101 DPLAYX_AcquireSemaphore();
1103 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1105 DPLAYX_ReleaseSemaphore();
1106 return FALSE;
1109 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1111 DPLAYX_ReleaseSemaphore();
1113 return TRUE;
1116 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1117 with the correct string printed in the case where the HRESULT is not
1118 known. You will just get the last hr passed in. This can change
1119 over time if this method is used a lot :) */
1120 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1122 static char szTempStr[12];
1124 switch (hr)
1126 case DP_OK:
1127 return "DP_OK";
1128 case DPERR_ALREADYINITIALIZED:
1129 return "DPERR_ALREADYINITIALIZED";
1130 case DPERR_ACCESSDENIED:
1131 return "DPERR_ACCESSDENIED";
1132 case DPERR_ACTIVEPLAYERS:
1133 return "DPERR_ACTIVEPLAYERS";
1134 case DPERR_BUFFERTOOSMALL:
1135 return "DPERR_BUFFERTOOSMALL";
1136 case DPERR_CANTADDPLAYER:
1137 return "DPERR_CANTADDPLAYER";
1138 case DPERR_CANTCREATEGROUP:
1139 return "DPERR_CANTCREATEGROUP";
1140 case DPERR_CANTCREATEPLAYER:
1141 return "DPERR_CANTCREATEPLAYER";
1142 case DPERR_CANTCREATESESSION:
1143 return "DPERR_CANTCREATESESSION";
1144 case DPERR_CAPSNOTAVAILABLEYET:
1145 return "DPERR_CAPSNOTAVAILABLEYET";
1146 case DPERR_EXCEPTION:
1147 return "DPERR_EXCEPTION";
1148 case DPERR_GENERIC:
1149 return "DPERR_GENERIC";
1150 case DPERR_INVALIDFLAGS:
1151 return "DPERR_INVALIDFLAGS";
1152 case DPERR_INVALIDOBJECT:
1153 return "DPERR_INVALIDOBJECT";
1154 case DPERR_INVALIDPARAMS:
1155 return "DPERR_INVALIDPARAMS";
1156 case DPERR_INVALIDPLAYER:
1157 return "DPERR_INVALIDPLAYER";
1158 case DPERR_INVALIDGROUP:
1159 return "DPERR_INVALIDGROUP";
1160 case DPERR_NOCAPS:
1161 return "DPERR_NOCAPS";
1162 case DPERR_NOCONNECTION:
1163 return "DPERR_NOCONNECTION";
1164 case DPERR_OUTOFMEMORY:
1165 return "DPERR_OUTOFMEMORY";
1166 case DPERR_NOMESSAGES:
1167 return "DPERR_NOMESSAGES";
1168 case DPERR_NONAMESERVERFOUND:
1169 return "DPERR_NONAMESERVERFOUND";
1170 case DPERR_NOPLAYERS:
1171 return "DPERR_NOPLAYERS";
1172 case DPERR_NOSESSIONS:
1173 return "DPERR_NOSESSIONS";
1174 case DPERR_PENDING:
1175 return "DPERR_PENDING";
1176 case DPERR_SENDTOOBIG:
1177 return "DPERR_SENDTOOBIG";
1178 case DPERR_TIMEOUT:
1179 return "DPERR_TIMEOUT";
1180 case DPERR_UNAVAILABLE:
1181 return "DPERR_UNAVAILABLE";
1182 case DPERR_UNSUPPORTED:
1183 return "DPERR_UNSUPPORTED";
1184 case DPERR_BUSY:
1185 return "DPERR_BUSY";
1186 case DPERR_USERCANCEL:
1187 return "DPERR_USERCANCEL";
1188 case DPERR_NOINTERFACE:
1189 return "DPERR_NOINTERFACE";
1190 case DPERR_CANNOTCREATESERVER:
1191 return "DPERR_CANNOTCREATESERVER";
1192 case DPERR_PLAYERLOST:
1193 return "DPERR_PLAYERLOST";
1194 case DPERR_SESSIONLOST:
1195 return "DPERR_SESSIONLOST";
1196 case DPERR_UNINITIALIZED:
1197 return "DPERR_UNINITIALIZED";
1198 case DPERR_NONEWPLAYERS:
1199 return "DPERR_NONEWPLAYERS";
1200 case DPERR_INVALIDPASSWORD:
1201 return "DPERR_INVALIDPASSWORD";
1202 case DPERR_CONNECTING:
1203 return "DPERR_CONNECTING";
1204 case DPERR_CONNECTIONLOST:
1205 return "DPERR_CONNECTIONLOST";
1206 case DPERR_UNKNOWNMESSAGE:
1207 return "DPERR_UNKNOWNMESSAGE";
1208 case DPERR_CANCELFAILED:
1209 return "DPERR_CANCELFAILED";
1210 case DPERR_INVALIDPRIORITY:
1211 return "DPERR_INVALIDPRIORITY";
1212 case DPERR_NOTHANDLED:
1213 return "DPERR_NOTHANDLED";
1214 case DPERR_CANCELLED:
1215 return "DPERR_CANCELLED";
1216 case DPERR_ABORTED:
1217 return "DPERR_ABORTED";
1218 case DPERR_BUFFERTOOLARGE:
1219 return "DPERR_BUFFERTOOLARGE";
1220 case DPERR_CANTCREATEPROCESS:
1221 return "DPERR_CANTCREATEPROCESS";
1222 case DPERR_APPNOTSTARTED:
1223 return "DPERR_APPNOTSTARTED";
1224 case DPERR_INVALIDINTERFACE:
1225 return "DPERR_INVALIDINTERFACE";
1226 case DPERR_NOSERVICEPROVIDER:
1227 return "DPERR_NOSERVICEPROVIDER";
1228 case DPERR_UNKNOWNAPPLICATION:
1229 return "DPERR_UNKNOWNAPPLICATION";
1230 case DPERR_NOTLOBBIED:
1231 return "DPERR_NOTLOBBIED";
1232 case DPERR_SERVICEPROVIDERLOADED:
1233 return "DPERR_SERVICEPROVIDERLOADED";
1234 case DPERR_ALREADYREGISTERED:
1235 return "DPERR_ALREADYREGISTERED";
1236 case DPERR_NOTREGISTERED:
1237 return "DPERR_NOTREGISTERED";
1238 case DPERR_AUTHENTICATIONFAILED:
1239 return "DPERR_AUTHENTICATIONFAILED";
1240 case DPERR_CANTLOADSSPI:
1241 return "DPERR_CANTLOADSSPI";
1242 case DPERR_ENCRYPTIONFAILED:
1243 return "DPERR_ENCRYPTIONFAILED";
1244 case DPERR_SIGNFAILED:
1245 return "DPERR_SIGNFAILED";
1246 case DPERR_CANTLOADSECURITYPACKAGE:
1247 return "DPERR_CANTLOADSECURITYPACKAGE";
1248 case DPERR_ENCRYPTIONNOTSUPPORTED:
1249 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1250 case DPERR_CANTLOADCAPI:
1251 return "DPERR_CANTLOADCAPI";
1252 case DPERR_NOTLOGGEDIN:
1253 return "DPERR_NOTLOGGEDIN";
1254 case DPERR_LOGONDENIED:
1255 return "DPERR_LOGONDENIED";
1256 default:
1257 /* For errors not in the list, return HRESULT as a string
1258 This part is not thread safe */
1259 WARN( "Unknown error 0x%08x\n", hr );
1260 wsprintfA( szTempStr, "0x%08lx", hr );
1261 return szTempStr;