Don't return from overlapped ReadFile on EAGAIN and other non-fatal
[wine/gsoc_dplay.git] / dlls / dplayx / dplayx_global.c
blob58261bd6d0ea380016c1d535b87d313da26a4794
1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 */
9 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with
10 * dplayx.dll data which is accessible from all processes.
11 */
13 #include <string.h>
14 #include "debugtools.h"
15 #include "winbase.h"
16 #include "winerror.h"
17 #include "wine/unicode.h"
19 #include "wingdi.h"
20 #include "winuser.h"
22 #include "dplayx_global.h"
23 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
25 DEFAULT_DEBUG_CHANNEL(dplay);
27 /* FIXME: Need to do all that fun other dll referencing type of stuff */
29 /* Static data for all processes */
30 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
31 static HANDLE hDplayxSema;
33 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
34 static HANDLE hDplayxSharedMem;
36 static LPVOID lpSharedStaticData = NULL;
39 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
40 WaitForSingleObject( hDplayxSema, INFINITE );\
41 TRACE( "Through wait\n" )
43 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
44 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
47 /* HACK for simple global data right now */
48 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
49 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
50 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
53 /* FIXME: Is there no easier way? */
55 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
56 * Each block has 4 bytes which are 0 unless used */
57 #define dwBlockSize 512
58 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
60 typedef struct
62 DWORD used;
63 DWORD data[dwBlockSize-sizeof(DWORD)];
64 } DPLAYX_MEM_SLICE;
66 static DPLAYX_MEM_SLICE* lpMemArea;
68 void DPLAYX_PrivHeapFree( LPVOID addr );
69 void DPLAYX_PrivHeapFree( LPVOID addr )
71 LPVOID lpAddrStart;
72 DWORD dwBlockUsed;
74 /* Handle getting passed a NULL */
75 if( addr == NULL )
77 return;
80 lpAddrStart = addr - sizeof(DWORD); /* Find block header */
81 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
83 lpMemArea[ dwBlockUsed ].used = 0;
86 /* FIXME: This should be static, but is being used for a hack right now */
87 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
88 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
90 LPVOID lpvArea = NULL;
91 UINT uBlockUsed;
93 if( size > (dwBlockSize - sizeof(DWORD)) )
95 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
96 size = dwBlockSize - sizeof(DWORD);
99 /* Find blank area */
100 uBlockUsed = 0;
101 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
103 if( uBlockUsed <= dwMaxBlock )
105 /* Set the area used */
106 lpMemArea[ uBlockUsed ].used = 1;
107 lpvArea = &(lpMemArea[ uBlockUsed ].data);
109 else
111 ERR( "No free block found\n" );
112 return NULL;
115 if( flags & HEAP_ZERO_MEMORY )
117 ZeroMemory( lpvArea, size );
120 return lpvArea;
123 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
124 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
126 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
127 if(p) {
128 strcpy( p, str );
130 return p;
133 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
134 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
136 INT len = strlenW(str) + 1;
137 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
138 if(p) {
139 strcpyW( p, str );
141 return p;
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 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
179 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
180 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
181 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
182 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
183 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
184 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
185 LPCDPSESSIONDESC2 lpSessionSrc );
189 /***************************************************************************
190 * Called to initialize the global data. This will only be used on the
191 * loading of the dll
192 ***************************************************************************/
193 BOOL DPLAYX_ConstructData(void)
195 SECURITY_ATTRIBUTES s_attrib;
196 BOOL bInitializeSharedMemory = FALSE;
197 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
198 HANDLE hInformOnStart;
200 TRACE( "DPLAYX dll loaded - construct called\n" );
202 /* Create a semaphore to block access to DPLAYX global data structs */
204 s_attrib.bInheritHandle = TRUE;
205 s_attrib.lpSecurityDescriptor = NULL;
206 s_attrib.nLength = sizeof(s_attrib);
208 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
210 /* First instance creates the semaphore. Others just use it */
211 if( GetLastError() == ERROR_SUCCESS )
213 TRACE( "Semaphore %u created\n", hDplayxSema );
215 /* The semaphore creator will also build the shared memory */
216 bInitializeSharedMemory = TRUE;
218 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
220 TRACE( "Found semaphore handle %u\n", hDplayxSema );
222 else
224 ERR( ": semaphore error %ld\n", GetLastError() );
225 return FALSE;
228 SetLastError( ERROR_SUCCESS );
230 DPLAYX_AquireSemaphore();
232 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
233 &s_attrib,
234 PAGE_READWRITE | SEC_COMMIT,
236 dwTotalSharedSize,
237 lpszDplayxFileMapping );
239 if( GetLastError() == ERROR_SUCCESS )
241 TRACE( "File mapped %u created\n", hDplayxSharedMem );
243 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
245 TRACE( "Found FileMapping handle %u\n", hDplayxSharedMem );
247 else
249 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
250 return FALSE;
253 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
254 FILE_MAP_WRITE,
255 0, 0, 0, lpDesiredMemoryMapStart );
257 if( lpSharedStaticData == NULL )
259 ERR( ": unable to map static data into process memory space (%ld)\n",
260 GetLastError() );
261 return FALSE;
263 else
265 if( lpDesiredMemoryMapStart == lpSharedStaticData )
267 TRACE( "File mapped to %p\n", lpSharedStaticData );
269 else
271 /* Presently the shared data structures use pointers. If the
272 * files are no mapped into the same area, the pointers will no
273 * longer make any sense :(
274 * FIXME: In the future make the shared data structures have some
275 * sort of fixup to make them independent between data spaces.
276 * This will also require a rework of the session data stuff.
278 ERR( "File mapped to %p (not %p). Expect failure\n",
279 lpSharedStaticData, lpDesiredMemoryMapStart );
283 /* Dynamic area starts just after the static area */
284 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
286 /* FIXME: Crude hack */
287 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
288 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
290 /* Initialize shared data segments. */
291 if( bInitializeSharedMemory )
293 UINT i;
295 TRACE( "Initializing shared memory\n" );
297 /* Set all lobbies to be "empty" */
298 for( i=0; i < numSupportedLobbies; i++ )
300 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
303 /* Set all sessions to be "empty" */
304 for( i=0; i < numSupportedSessions; i++ )
306 sessionData[i].dwSize = 0;
309 /* Zero out the dynmaic area */
310 ZeroMemory( lpMemArea, dwDynamicSharedSize );
312 /* Just for fun sync the whole data area */
313 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
316 DPLAYX_ReleaseSemaphore();
318 /* Everything was created correctly. Signal the lobby client that
319 * we started up correctly
321 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
322 hInformOnStart
325 BOOL bSuccess;
326 bSuccess = SetEvent( hInformOnStart );
327 TRACE( "Signalling lobby app start event %u %s\n",
328 hInformOnStart, bSuccess ? "succeed" : "failed" );
330 /* Close out handle */
331 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
334 return TRUE;
337 /***************************************************************************
338 * Called to destroy all global data. This will only be used on the
339 * unloading of the dll
340 ***************************************************************************/
341 BOOL DPLAYX_DestructData(void)
343 HANDLE hInformOnDeath;
345 TRACE( "DPLAYX dll unloaded - destruct called\n" );
347 /* If required, inform that this app is dying */
348 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
349 hInformOnDeath
352 BOOL bSuccess;
353 bSuccess = SetEvent( hInformOnDeath );
354 TRACE( "Signalling lobby app death event %u %s\n",
355 hInformOnDeath, bSuccess ? "succeed" : "failed" );
357 /* Close out handle */
358 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
361 /* DO CLEAN UP (LAST) */
363 /* Delete the semaphore */
364 CloseHandle( hDplayxSema );
366 /* Delete shared memory file mapping */
367 UnmapViewOfFile( lpSharedStaticData );
368 CloseHandle( hDplayxSharedMem );
370 return FALSE;
374 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
376 ZeroMemory( lpData, sizeof( *lpData ) );
379 /* NOTE: This must be called with the semaphore aquired.
380 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
381 * is only valid if TRUE is returned.
383 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
385 UINT i;
387 *lplpDplData = NULL;
389 if( dwAppID == 0 )
391 dwAppID = GetCurrentProcessId();
392 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
395 for( i=0; i < numSupportedLobbies; i++ )
397 if( lobbyData[ i ].dwAppID == dwAppID )
399 /* This process is lobbied */
400 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
401 *lplpDplData = &lobbyData[ i ];
402 return TRUE;
406 return FALSE;
409 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
410 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
412 UINT i;
414 /* 0 is the marker for unused application data slots */
415 if( dwAppID == 0 )
417 return FALSE;
420 DPLAYX_AquireSemaphore();
422 /* Find an empty space in the list and insert the data */
423 for( i=0; i < numSupportedLobbies; i++ )
425 if( lobbyData[ i ].dwAppID == 0 )
427 /* This process is now lobbied */
428 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
429 i, dwAppID, GetCurrentProcessId() );
431 lobbyData[ i ].dwAppID = dwAppID;
432 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
434 /* FIXME: Where is the best place for this? In interface or here? */
435 lobbyData[ i ].hInformOnAppStart = 0;
436 lobbyData[ i ].hInformOnAppDeath = 0;
437 lobbyData[ i ].hInformOnSettingRead = 0;
439 DPLAYX_ReleaseSemaphore();
440 return TRUE;
444 ERR( "No empty lobbies\n" );
446 DPLAYX_ReleaseSemaphore();
447 return FALSE;
450 /* I'm not sure when I'm going to need this, but here it is */
451 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
453 UINT i;
455 DPLAYX_AquireSemaphore();
457 /* Find an empty space in the list and insert the data */
458 for( i=0; i < numSupportedLobbies; i++ )
460 if( lobbyData[ i ].dwAppID == dwAppID )
462 /* FIXME: Should free up anything unused. Tisk tisk :0 */
463 /* Mark this entry unused */
464 TRACE( "Marking lobbyData[%u] unused\n", i );
465 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
467 DPLAYX_ReleaseSemaphore();
468 return TRUE;
472 DPLAYX_ReleaseSemaphore();
473 ERR( "Unable to find global entry for application\n" );
474 return FALSE;
477 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
478 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
480 LPDPLAYX_LOBBYDATA lpLData;
482 /* Need to explictly give lobby application. Can't set for yourself */
483 if( dwAppID == 0 )
485 return FALSE;
488 DPLAYX_AquireSemaphore();
490 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
492 DPLAYX_ReleaseSemaphore();
493 return FALSE;
496 lpLData->hInformOnAppStart = hStart;
497 lpLData->hInformOnAppDeath = hDeath;
498 lpLData->hInformOnSettingRead = hConnRead;
500 DPLAYX_ReleaseSemaphore();
502 return TRUE;
505 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
506 LPHANDLE lphDeath,
507 LPHANDLE lphConnRead,
508 BOOL bClearSetHandles )
510 LPDPLAYX_LOBBYDATA lpLData;
512 DPLAYX_AquireSemaphore();
514 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
516 DPLAYX_ReleaseSemaphore();
517 return FALSE;
520 if( lphStart != NULL )
522 if( lpLData->hInformOnAppStart == 0 )
524 DPLAYX_ReleaseSemaphore();
525 return FALSE;
528 *lphStart = lpLData->hInformOnAppStart;
530 if( bClearSetHandles )
532 CloseHandle( lpLData->hInformOnAppStart );
533 lpLData->hInformOnAppStart = 0;
537 if( lphDeath != NULL )
539 if( lpLData->hInformOnAppDeath == 0 )
541 DPLAYX_ReleaseSemaphore();
542 return FALSE;
545 *lphDeath = lpLData->hInformOnAppDeath;
547 if( bClearSetHandles )
549 CloseHandle( lpLData->hInformOnAppDeath );
550 lpLData->hInformOnAppDeath = 0;
554 if( lphConnRead != NULL )
556 if( lpLData->hInformOnSettingRead == 0 )
558 DPLAYX_ReleaseSemaphore();
559 return FALSE;
562 *lphConnRead = lpLData->hInformOnSettingRead;
564 if( bClearSetHandles )
566 CloseHandle( lpLData->hInformOnSettingRead );
567 lpLData->hInformOnSettingRead = 0;
571 DPLAYX_ReleaseSemaphore();
573 return TRUE;
577 HRESULT DPLAYX_GetConnectionSettingsA
578 ( DWORD dwAppID,
579 LPVOID lpData,
580 LPDWORD lpdwDataSize )
582 LPDPLAYX_LOBBYDATA lpDplData;
583 DWORD dwRequiredDataSize = 0;
584 HANDLE hInformOnSettingRead;
586 DPLAYX_AquireSemaphore();
588 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
590 DPLAYX_ReleaseSemaphore();
592 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
593 return DPERR_NOTLOBBIED;
596 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
598 /* Do they want to know the required buffer size or is the provided buffer
599 * big enough?
601 if ( ( lpData == NULL ) ||
602 ( *lpdwDataSize < dwRequiredDataSize )
605 DPLAYX_ReleaseSemaphore();
607 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
609 return DPERR_BUFFERTOOSMALL;
612 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
614 DPLAYX_ReleaseSemaphore();
616 /* They have gotten the information - signal the event if required */
617 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
618 hInformOnSettingRead
621 BOOL bSuccess;
622 bSuccess = SetEvent( hInformOnSettingRead );
623 TRACE( "Signalling setting read event %u %s\n",
624 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
626 /* Close out handle */
627 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
630 return DP_OK;
633 /* Assumption: Enough contiguous space was allocated at dest */
634 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
636 BYTE* lpStartOfFreeSpace;
638 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
640 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
642 /* Copy the LPDPSESSIONDESC2 structure if it exists */
643 if( src->lpSessionDesc )
645 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
646 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
647 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
649 /* Session names may or may not exist */
650 if( src->lpSessionDesc->u1.lpszSessionNameA )
652 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
653 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
654 lpStartOfFreeSpace +=
655 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
658 if( src->lpSessionDesc->u2.lpszPasswordA )
660 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
661 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
662 lpStartOfFreeSpace +=
663 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
667 /* DPNAME structure is optional */
668 if( src->lpPlayerName )
670 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
671 lpStartOfFreeSpace += sizeof( DPNAME );
672 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
674 if( src->lpPlayerName->u1.lpszShortNameA )
676 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
677 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
678 lpStartOfFreeSpace +=
679 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
682 if( src->lpPlayerName->u2.lpszLongNameA )
684 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
685 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
686 lpStartOfFreeSpace +=
687 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
692 /* Copy address if it exists */
693 if( src->lpAddress )
695 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
696 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
697 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
701 HRESULT DPLAYX_GetConnectionSettingsW
702 ( DWORD dwAppID,
703 LPVOID lpData,
704 LPDWORD lpdwDataSize )
706 LPDPLAYX_LOBBYDATA lpDplData;
707 DWORD dwRequiredDataSize = 0;
708 HANDLE hInformOnSettingRead;
710 DPLAYX_AquireSemaphore();
712 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
714 DPLAYX_ReleaseSemaphore();
715 return DPERR_NOTLOBBIED;
718 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
720 /* Do they want to know the required buffer size or is the provided buffer
721 * big enough?
723 if ( ( lpData == NULL ) ||
724 ( *lpdwDataSize < dwRequiredDataSize )
727 DPLAYX_ReleaseSemaphore();
729 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
731 return DPERR_BUFFERTOOSMALL;
734 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
736 DPLAYX_ReleaseSemaphore();
738 /* They have gotten the information - signal the event if required */
739 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
740 hInformOnSettingRead
743 BOOL bSuccess;
744 bSuccess = SetEvent( hInformOnSettingRead );
745 TRACE( "Signalling setting read event %u %s\n",
746 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
748 /* Close out handle */
749 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
752 return DP_OK;
755 /* Assumption: Enough contiguous space was allocated at dest */
756 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
758 BYTE* lpStartOfFreeSpace;
760 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
762 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
764 /* Copy the LPDPSESSIONDESC2 structure if it exists */
765 if( src->lpSessionDesc )
767 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
768 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
769 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
771 /* Session names may or may not exist */
772 if( src->lpSessionDesc->u1.lpszSessionName )
774 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
775 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
776 lpStartOfFreeSpace += sizeof(WCHAR) *
777 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
780 if( src->lpSessionDesc->u2.lpszPassword )
782 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
783 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
784 lpStartOfFreeSpace += sizeof(WCHAR) *
785 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
789 /* DPNAME structure is optional */
790 if( src->lpPlayerName )
792 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
793 lpStartOfFreeSpace += sizeof( DPNAME );
794 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
796 if( src->lpPlayerName->u1.lpszShortName )
798 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
799 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
800 lpStartOfFreeSpace += sizeof(WCHAR) *
801 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
804 if( src->lpPlayerName->u2.lpszLongName )
806 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
807 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
808 lpStartOfFreeSpace += sizeof(WCHAR) *
809 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
814 /* Copy address if it exists */
815 if( src->lpAddress )
817 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
818 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
819 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
824 /* Store the structure into the shared data structre. Ensure that allocs for
825 * variable length strings come from the shared data structure.
826 * FIXME: We need to free information as well
828 HRESULT DPLAYX_SetConnectionSettingsA
829 ( DWORD dwFlags,
830 DWORD dwAppID,
831 LPDPLCONNECTION lpConn )
833 LPDPLAYX_LOBBYDATA lpDplData;
835 /* Paramater check */
836 if( dwFlags || !lpConn )
838 ERR("invalid parameters.\n");
839 return DPERR_INVALIDPARAMS;
842 /* Store information */
843 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
845 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
846 lpConn->dwSize, sizeof( DPLCONNECTION ) );
848 return DPERR_INVALIDPARAMS;
851 DPLAYX_AquireSemaphore();
853 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
855 DPLAYX_ReleaseSemaphore();
857 return DPERR_NOTLOBBIED;
860 if( (!lpConn->lpSessionDesc ) ||
861 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
864 DPLAYX_ReleaseSemaphore();
866 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
867 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
869 return DPERR_INVALIDPARAMS;
872 /* Free the existing memory */
873 DPLAYX_PrivHeapFree( lpDplData->lpConn );
875 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
876 DPLAYX_SizeOfLobbyDataA( lpConn ) );
878 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
881 DPLAYX_ReleaseSemaphore();
883 /* FIXME: Send a message - I think */
885 return DP_OK;
888 /* Store the structure into the shared data structre. Ensure that allocs for
889 * variable length strings come from the shared data structure.
890 * FIXME: We need to free information as well
892 HRESULT DPLAYX_SetConnectionSettingsW
893 ( DWORD dwFlags,
894 DWORD dwAppID,
895 LPDPLCONNECTION lpConn )
897 LPDPLAYX_LOBBYDATA lpDplData;
899 /* Paramater check */
900 if( dwFlags || !lpConn )
902 ERR("invalid parameters.\n");
903 return DPERR_INVALIDPARAMS;
906 /* Store information */
907 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
909 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
910 lpConn->dwSize, sizeof( DPLCONNECTION ) );
912 return DPERR_INVALIDPARAMS;
915 DPLAYX_AquireSemaphore();
917 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
919 DPLAYX_ReleaseSemaphore();
921 return DPERR_NOTLOBBIED;
924 /* Free the existing memory */
925 DPLAYX_PrivHeapFree( lpDplData->lpConn );
927 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
928 DPLAYX_SizeOfLobbyDataW( lpConn ) );
930 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
933 DPLAYX_ReleaseSemaphore();
935 /* FIXME: Send a message - I think */
937 return DP_OK;
940 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
942 DWORD dwTotalSize = sizeof( DPLCONNECTION );
944 /* Just a safety check */
945 if( lpConn == NULL )
947 ERR( "lpConn is NULL\n" );
948 return 0;
951 if( lpConn->lpSessionDesc != NULL )
953 dwTotalSize += sizeof( DPSESSIONDESC2 );
955 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
957 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
960 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
962 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
966 if( lpConn->lpPlayerName != NULL )
968 dwTotalSize += sizeof( DPNAME );
970 if( lpConn->lpPlayerName->u1.lpszShortNameA )
972 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
975 if( lpConn->lpPlayerName->u2.lpszLongNameA )
977 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
982 dwTotalSize += lpConn->dwAddressSize;
984 return dwTotalSize;
987 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
989 DWORD dwTotalSize = sizeof( DPLCONNECTION );
991 /* Just a safety check */
992 if( lpConn == NULL )
994 ERR( "lpConn is NULL\n" );
995 return 0;
998 if( lpConn->lpSessionDesc != NULL )
1000 dwTotalSize += sizeof( DPSESSIONDESC2 );
1002 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1004 dwTotalSize += sizeof( WCHAR ) *
1005 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1008 if( lpConn->lpSessionDesc->u2.lpszPassword )
1010 dwTotalSize += sizeof( WCHAR ) *
1011 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1015 if( lpConn->lpPlayerName != NULL )
1017 dwTotalSize += sizeof( DPNAME );
1019 if( lpConn->lpPlayerName->u1.lpszShortName )
1021 dwTotalSize += sizeof( WCHAR ) *
1022 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1025 if( lpConn->lpPlayerName->u2.lpszLongName )
1027 dwTotalSize += sizeof( WCHAR ) *
1028 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1033 dwTotalSize += lpConn->dwAddressSize;
1035 return dwTotalSize;
1040 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1042 LPDPSESSIONDESC2 lpSessionDest =
1043 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1044 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1045 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1047 return lpSessionDest;
1050 /* Copy an ANSI session desc structure to the given buffer */
1051 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1052 LPCDPSESSIONDESC2 lpSessionSrc )
1054 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1056 if( lpSessionSrc->u1.lpszSessionNameA )
1058 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1059 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1060 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1062 if( lpSessionSrc->u2.lpszPasswordA )
1064 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1065 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1066 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1069 return TRUE;
1072 /* Start the index at 0. index will be updated to equal that which should
1073 be passed back into this function for the next element */
1074 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1076 for( ; (*index) < numSupportedSessions; (*index)++ )
1078 if( sessionData[(*index)].dwSize != 0 )
1080 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1084 /* No more sessions */
1085 return NULL;
1088 /* Start the index at 0. index will be updated to equal that which should
1089 be passed back into this function for the next element */
1090 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1092 for( ; (*index) < numSupportedSessions; (*index)++ )
1094 if( sessionData[(*index)].dwSize != 0 )
1096 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1100 /* No more sessions */
1101 return FALSE;
1104 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1106 UINT i;
1108 /* FIXME: Is this an error if it exists already? */
1110 /* Crude/wrong implementation for now. Just always add to first empty spot */
1111 for( i=0; i < numSupportedSessions; i++ )
1113 /* Is this one empty? */
1114 if( sessionData[i].dwSize == 0 )
1116 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1117 break;
1123 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1125 LPDPLAYX_LOBBYDATA lpLobbyData;
1127 DPLAYX_AquireSemaphore();
1129 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1131 DPLAYX_ReleaseSemaphore();
1132 return FALSE;
1135 lpLobbyData->bWaitForConnectionSettings = bWait;
1137 DPLAYX_ReleaseSemaphore();
1139 return TRUE;
1142 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1144 UINT i;
1145 BOOL bFound = FALSE;
1147 DPLAYX_AquireSemaphore();
1149 for( i=0; i < numSupportedLobbies; i++ )
1151 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1152 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1155 bFound = TRUE;
1156 break;
1160 DPLAYX_ReleaseSemaphore();
1162 return bFound;
1165 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1167 LPDPLAYX_LOBBYDATA lpLobbyData;
1169 DPLAYX_AquireSemaphore();
1171 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1173 DPLAYX_ReleaseSemaphore();
1174 return FALSE;
1177 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1179 DPLAYX_ReleaseSemaphore();
1181 return TRUE;
1184 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1185 with the correct string printed in the case where the HRESULT is not
1186 known. You'll just get the last hr passed in printed. This can change
1187 over time if this method is used alot :) */
1188 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1190 static char szTempStr[12];
1192 switch (hr)
1194 case DP_OK:
1195 return "DP_OK";
1196 case DPERR_ALREADYINITIALIZED:
1197 return "DPERR_ALREADYINITIALIZED";
1198 case DPERR_ACCESSDENIED:
1199 return "DPERR_ACCESSDENIED";
1200 case DPERR_ACTIVEPLAYERS:
1201 return "DPERR_ACTIVEPLAYERS";
1202 case DPERR_BUFFERTOOSMALL:
1203 return "DPERR_BUFFERTOOSMALL";
1204 case DPERR_CANTADDPLAYER:
1205 return "DPERR_CANTADDPLAYER";
1206 case DPERR_CANTCREATEGROUP:
1207 return "DPERR_CANTCREATEGROUP";
1208 case DPERR_CANTCREATEPLAYER:
1209 return "DPERR_CANTCREATEPLAYER";
1210 case DPERR_CANTCREATESESSION:
1211 return "DPERR_CANTCREATESESSION";
1212 case DPERR_CAPSNOTAVAILABLEYET:
1213 return "DPERR_CAPSNOTAVAILABLEYET";
1214 case DPERR_EXCEPTION:
1215 return "DPERR_EXCEPTION";
1216 case DPERR_GENERIC:
1217 return "DPERR_GENERIC";
1218 case DPERR_INVALIDFLAGS:
1219 return "DPERR_INVALIDFLAGS";
1220 case DPERR_INVALIDOBJECT:
1221 return "DPERR_INVALIDOBJECT";
1222 case DPERR_INVALIDPARAMS:
1223 return "DPERR_INVALIDPARAMS";
1224 case DPERR_INVALIDPLAYER:
1225 return "DPERR_INVALIDPLAYER";
1226 case DPERR_INVALIDGROUP:
1227 return "DPERR_INVALIDGROUP";
1228 case DPERR_NOCAPS:
1229 return "DPERR_NOCAPS";
1230 case DPERR_NOCONNECTION:
1231 return "DPERR_NOCONNECTION";
1232 case DPERR_OUTOFMEMORY:
1233 return "DPERR_OUTOFMEMORY";
1234 case DPERR_NOMESSAGES:
1235 return "DPERR_NOMESSAGES";
1236 case DPERR_NONAMESERVERFOUND:
1237 return "DPERR_NONAMESERVERFOUND";
1238 case DPERR_NOPLAYERS:
1239 return "DPERR_NOPLAYERS";
1240 case DPERR_NOSESSIONS:
1241 return "DPERR_NOSESSIONS";
1242 case DPERR_PENDING:
1243 return "DPERR_PENDING";
1244 case DPERR_SENDTOOBIG:
1245 return "DPERR_SENDTOOBIG";
1246 case DPERR_TIMEOUT:
1247 return "DPERR_TIMEOUT";
1248 case DPERR_UNAVAILABLE:
1249 return "DPERR_UNAVAILABLE";
1250 case DPERR_UNSUPPORTED:
1251 return "DPERR_UNSUPPORTED";
1252 case DPERR_BUSY:
1253 return "DPERR_BUSY";
1254 case DPERR_USERCANCEL:
1255 return "DPERR_USERCANCEL";
1256 case DPERR_NOINTERFACE:
1257 return "DPERR_NOINTERFACE";
1258 case DPERR_CANNOTCREATESERVER:
1259 return "DPERR_CANNOTCREATESERVER";
1260 case DPERR_PLAYERLOST:
1261 return "DPERR_PLAYERLOST";
1262 case DPERR_SESSIONLOST:
1263 return "DPERR_SESSIONLOST";
1264 case DPERR_UNINITIALIZED:
1265 return "DPERR_UNINITIALIZED";
1266 case DPERR_NONEWPLAYERS:
1267 return "DPERR_NONEWPLAYERS";
1268 case DPERR_INVALIDPASSWORD:
1269 return "DPERR_INVALIDPASSWORD";
1270 case DPERR_CONNECTING:
1271 return "DPERR_CONNECTING";
1272 case DPERR_CONNECTIONLOST:
1273 return "DPERR_CONNECTIONLOST";
1274 case DPERR_UNKNOWNMESSAGE:
1275 return "DPERR_UNKNOWNMESSAGE";
1276 case DPERR_CANCELFAILED:
1277 return "DPERR_CANCELFAILED";
1278 case DPERR_INVALIDPRIORITY:
1279 return "DPERR_INVALIDPRIORITY";
1280 case DPERR_NOTHANDLED:
1281 return "DPERR_NOTHANDLED";
1282 case DPERR_CANCELLED:
1283 return "DPERR_CANCELLED";
1284 case DPERR_ABORTED:
1285 return "DPERR_ABORTED";
1286 case DPERR_BUFFERTOOLARGE:
1287 return "DPERR_BUFFERTOOLARGE";
1288 case DPERR_CANTCREATEPROCESS:
1289 return "DPERR_CANTCREATEPROCESS";
1290 case DPERR_APPNOTSTARTED:
1291 return "DPERR_APPNOTSTARTED";
1292 case DPERR_INVALIDINTERFACE:
1293 return "DPERR_INVALIDINTERFACE";
1294 case DPERR_NOSERVICEPROVIDER:
1295 return "DPERR_NOSERVICEPROVIDER";
1296 case DPERR_UNKNOWNAPPLICATION:
1297 return "DPERR_UNKNOWNAPPLICATION";
1298 case DPERR_NOTLOBBIED:
1299 return "DPERR_NOTLOBBIED";
1300 case DPERR_SERVICEPROVIDERLOADED:
1301 return "DPERR_SERVICEPROVIDERLOADED";
1302 case DPERR_ALREADYREGISTERED:
1303 return "DPERR_ALREADYREGISTERED";
1304 case DPERR_NOTREGISTERED:
1305 return "DPERR_NOTREGISTERED";
1306 case DPERR_AUTHENTICATIONFAILED:
1307 return "DPERR_AUTHENTICATIONFAILED";
1308 case DPERR_CANTLOADSSPI:
1309 return "DPERR_CANTLOADSSPI";
1310 case DPERR_ENCRYPTIONFAILED:
1311 return "DPERR_ENCRYPTIONFAILED";
1312 case DPERR_SIGNFAILED:
1313 return "DPERR_SIGNFAILED";
1314 case DPERR_CANTLOADSECURITYPACKAGE:
1315 return "DPERR_CANTLOADSECURITYPACKAGE";
1316 case DPERR_ENCRYPTIONNOTSUPPORTED:
1317 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1318 case DPERR_CANTLOADCAPI:
1319 return "DPERR_CANTLOADCAPI";
1320 case DPERR_NOTLOGGEDIN:
1321 return "DPERR_NOTLOGGEDIN";
1322 case DPERR_LOGONDENIED:
1323 return "DPERR_LOGONDENIED";
1324 default:
1325 /* For errors not in the list, return HRESULT as a string
1326 This part is not thread safe */
1327 WARN( "Unknown error 0x%08lx\n", hr );
1328 wsprintfA( szTempStr, "0x%08lx", hr );
1329 return szTempStr;