Increase debug buffer size up to 1024 bytes.
[wine.git] / dlls / dplayx / dplayx_global.c
blobd9b6fa58dfc3dc1f5978f4096df13b037355816a
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"
18 #include "heap.h"
20 #include "wingdi.h"
21 #include "winuser.h"
23 #include "dplayx_global.h"
24 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
26 DEFAULT_DEBUG_CHANNEL(dplay);
28 /* FIXME: Need to do all that fun other dll referencing type of stuff */
30 /* Static data for all processes */
31 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
32 static HANDLE hDplayxSema;
34 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
35 static HANDLE hDplayxSharedMem;
37 static LPVOID lpSharedStaticData = NULL;
40 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
41 WaitForSingleObject( hDplayxSema, INFINITE );\
42 TRACE( "Through wait\n" )
44 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
45 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
48 /* HACK for simple global data right now */
49 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
50 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
51 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
54 /* FIXME: Is there no easier way? */
56 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
57 * Each block has 4 bytes which are 0 unless used */
58 #define dwBlockSize 512
59 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
61 typedef struct
63 DWORD used;
64 DWORD data[dwBlockSize-sizeof(DWORD)];
65 } DPLAYX_MEM_SLICE;
67 static DPLAYX_MEM_SLICE* lpMemArea;
69 void DPLAYX_PrivHeapFree( LPVOID addr );
70 void DPLAYX_PrivHeapFree( LPVOID addr )
72 LPVOID lpAddrStart;
73 DWORD dwBlockUsed;
75 /* Handle getting passed a NULL */
76 if( addr == NULL )
78 return;
81 lpAddrStart = addr - sizeof(DWORD); /* Find block header */
82 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
84 lpMemArea[ dwBlockUsed ].used = 0;
87 /* FIXME: This should be static, but is being used for a hack right now */
88 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
89 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
91 LPVOID lpvArea = NULL;
92 UINT uBlockUsed;
94 if( size > (dwBlockSize - sizeof(DWORD)) )
96 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
97 size = dwBlockSize - sizeof(DWORD);
100 /* Find blank area */
101 uBlockUsed = 0;
102 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
104 if( uBlockUsed <= dwMaxBlock )
106 /* Set the area used */
107 lpMemArea[ uBlockUsed ].used = 1;
108 lpvArea = &(lpMemArea[ uBlockUsed ].data);
110 else
112 ERR( "No free block found\n" );
113 return NULL;
116 if( flags & HEAP_ZERO_MEMORY )
118 ZeroMemory( lpvArea, size );
121 return lpvArea;
124 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
125 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
127 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
128 if(p) {
129 strcpy( p, str );
131 return p;
134 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
135 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
137 INT len = strlenW(str) + 1;
138 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
139 if(p) {
140 strcpyW( p, str );
142 return p;
146 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
147 typedef struct tagDPLAYX_LOBBYDATA
149 /* Points to lpConn + block of contiguous extra memory for dynamic parts
150 * of the struct directly following
152 LPDPLCONNECTION lpConn;
154 /* Information for dplobby interfaces */
155 DWORD dwAppID;
156 DWORD dwAppLaunchedFromID;
158 /* Should this lobby app send messages to creator at important life
159 * stages
161 HANDLE hInformOnAppStart;
162 HANDLE hInformOnAppDeath;
163 HANDLE hInformOnSettingRead;
165 /* Sundries */
166 BOOL bWaitForConnectionSettings;
167 DWORD dwLobbyMsgThreadId;
170 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
172 static DPLAYX_LOBBYDATA* lobbyData = NULL;
173 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
175 static DPSESSIONDESC2* sessionData = NULL;
176 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
178 /* Function prototypes */
179 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
180 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
181 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
182 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
183 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
184 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
185 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
186 LPCDPSESSIONDESC2 lpSessionSrc );
190 /***************************************************************************
191 * Called to initialize the global data. This will only be used on the
192 * loading of the dll
193 ***************************************************************************/
194 BOOL DPLAYX_ConstructData(void)
196 SECURITY_ATTRIBUTES s_attrib;
197 BOOL bInitializeSharedMemory = FALSE;
198 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
199 HANDLE hInformOnStart;
201 TRACE( "DPLAYX dll loaded - construct called\n" );
203 /* Create a semaphore to block access to DPLAYX global data structs */
205 s_attrib.bInheritHandle = TRUE;
206 s_attrib.lpSecurityDescriptor = NULL;
207 s_attrib.nLength = sizeof(s_attrib);
209 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
211 /* First instance creates the semaphore. Others just use it */
212 if( GetLastError() == ERROR_SUCCESS )
214 TRACE( "Semaphore %u created\n", hDplayxSema );
216 /* The semaphore creator will also build the shared memory */
217 bInitializeSharedMemory = TRUE;
219 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
221 TRACE( "Found semaphore handle %u\n", hDplayxSema );
223 else
225 ERR( ": semaphore error 0x%08lx\n", GetLastError() );
226 return FALSE;
229 SetLastError( ERROR_SUCCESS );
231 DPLAYX_AquireSemaphore();
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 %u created\n", hDplayxSharedMem );
244 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
246 TRACE( "Found FileMapping handle %u\n", hDplayxSharedMem );
248 else
250 ERR( ": unable to create shared memory 0x%08lx\n", GetLastError() );
251 return FALSE;
254 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
255 FILE_MAP_WRITE,
256 0, 0, 0, lpDesiredMemoryMapStart );
258 if( lpSharedStaticData == NULL )
260 ERR( ": unable to map static data into process memory space: 0x%08lx\n",
261 GetLastError() );
262 return FALSE;
264 else
266 if( lpDesiredMemoryMapStart == lpSharedStaticData )
268 TRACE( "File mapped to %p\n", lpSharedStaticData );
270 else
272 /* Presently the shared data structures use pointers. If the
273 * files are no mapped into the same area, the pointers will no
274 * longer make any sense :(
275 * FIXME: In the future make the shared data structures have some
276 * sort of fixup to make them independent between data spaces.
277 * This will also require a rework of the session data stuff.
279 ERR( "File mapped to %p (not %p). Expect failure\n",
280 lpSharedStaticData, lpDesiredMemoryMapStart );
284 /* Dynamic area starts just after the static area */
285 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
287 /* FIXME: Crude hack */
288 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
289 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
291 /* Initialize shared data segments. */
292 if( bInitializeSharedMemory )
294 UINT i;
296 TRACE( "Initializing shared memory\n" );
298 /* Set all lobbies to be "empty" */
299 for( i=0; i < numSupportedLobbies; i++ )
301 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
304 /* Set all sessions to be "empty" */
305 for( i=0; i < numSupportedSessions; i++ )
307 sessionData[i].dwSize = 0;
310 /* Zero out the dynmaic area */
311 ZeroMemory( lpMemArea, dwDynamicSharedSize );
313 /* Just for fun sync the whole data area */
314 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
317 DPLAYX_ReleaseSemaphore();
319 /* Everything was created correctly. Signal the lobby client that
320 * we started up correctly
322 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
323 hInformOnStart
326 BOOL bSuccess;
327 bSuccess = SetEvent( hInformOnStart );
328 TRACE( "Signalling lobby app start event %u %s\n",
329 hInformOnStart, bSuccess ? "succeed" : "failed" );
331 /* Close out handle */
332 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
335 return TRUE;
338 /***************************************************************************
339 * Called to destroy all global data. This will only be used on the
340 * unloading of the dll
341 ***************************************************************************/
342 BOOL DPLAYX_DestructData(void)
344 HANDLE hInformOnDeath;
346 TRACE( "DPLAYX dll unloaded - destruct called\n" );
348 /* If required, inform that this app is dying */
349 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
350 hInformOnDeath
353 BOOL bSuccess;
354 bSuccess = SetEvent( hInformOnDeath );
355 TRACE( "Signalling lobby app death event %u %s\n",
356 hInformOnDeath, bSuccess ? "succeed" : "failed" );
358 /* Close out handle */
359 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
362 /* DO CLEAN UP (LAST) */
364 /* Delete the semaphore */
365 CloseHandle( hDplayxSema );
367 /* Delete shared memory file mapping */
368 UnmapViewOfFile( lpSharedStaticData );
369 CloseHandle( hDplayxSharedMem );
371 return FALSE;
375 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
377 ZeroMemory( lpData, sizeof( *lpData ) );
380 /* NOTE: This must be called with the semaphore aquired.
381 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
382 * is only valid if TRUE is returned.
384 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
386 UINT i;
388 *lplpDplData = NULL;
390 if( dwAppID == 0 )
392 dwAppID = GetCurrentProcessId();
393 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
396 for( i=0; i < numSupportedLobbies; i++ )
398 if( lobbyData[ i ].dwAppID == dwAppID )
400 /* This process is lobbied */
401 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
402 *lplpDplData = &lobbyData[ i ];
403 return TRUE;
407 return FALSE;
410 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
411 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
413 UINT i;
415 /* 0 is the marker for unused application data slots */
416 if( dwAppID == 0 )
418 return FALSE;
421 DPLAYX_AquireSemaphore();
423 /* Find an empty space in the list and insert the data */
424 for( i=0; i < numSupportedLobbies; i++ )
426 if( lobbyData[ i ].dwAppID == 0 )
428 /* This process is now lobbied */
429 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
430 i, dwAppID, GetCurrentProcessId() );
432 lobbyData[ i ].dwAppID = dwAppID;
433 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
435 /* FIXME: Where is the best place for this? In interface or here? */
436 lobbyData[ i ].hInformOnAppStart = 0;
437 lobbyData[ i ].hInformOnAppDeath = 0;
438 lobbyData[ i ].hInformOnSettingRead = 0;
440 DPLAYX_ReleaseSemaphore();
441 return TRUE;
445 ERR( "No empty lobbies\n" );
447 DPLAYX_ReleaseSemaphore();
448 return FALSE;
451 /* I'm not sure when I'm going to need this, but here it is */
452 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
454 UINT i;
456 DPLAYX_AquireSemaphore();
458 /* Find an empty space in the list and insert the data */
459 for( i=0; i < numSupportedLobbies; i++ )
461 if( lobbyData[ i ].dwAppID == dwAppID )
463 /* FIXME: Should free up anything unused. Tisk tisk :0 */
464 /* Mark this entry unused */
465 TRACE( "Marking lobbyData[%u] unused\n", i );
466 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
468 DPLAYX_ReleaseSemaphore();
469 return TRUE;
473 DPLAYX_ReleaseSemaphore();
474 ERR( "Unable to find global entry for application\n" );
475 return FALSE;
478 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
479 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
481 LPDPLAYX_LOBBYDATA lpLData;
483 /* Need to explictly give lobby application. Can't set for yourself */
484 if( dwAppID == 0 )
486 return FALSE;
489 DPLAYX_AquireSemaphore();
491 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
493 DPLAYX_ReleaseSemaphore();
494 return FALSE;
497 lpLData->hInformOnAppStart = hStart;
498 lpLData->hInformOnAppDeath = hDeath;
499 lpLData->hInformOnSettingRead = hConnRead;
501 DPLAYX_ReleaseSemaphore();
503 return TRUE;
506 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
507 LPHANDLE lphDeath,
508 LPHANDLE lphConnRead,
509 BOOL bClearSetHandles )
511 LPDPLAYX_LOBBYDATA lpLData;
513 DPLAYX_AquireSemaphore();
515 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
517 DPLAYX_ReleaseSemaphore();
518 return FALSE;
521 if( lphStart != NULL )
523 if( lpLData->hInformOnAppStart == 0 )
525 DPLAYX_ReleaseSemaphore();
526 return FALSE;
529 *lphStart = lpLData->hInformOnAppStart;
531 if( bClearSetHandles )
533 CloseHandle( lpLData->hInformOnAppStart );
534 lpLData->hInformOnAppStart = 0;
538 if( lphDeath != NULL )
540 if( lpLData->hInformOnAppDeath == 0 )
542 DPLAYX_ReleaseSemaphore();
543 return FALSE;
546 *lphDeath = lpLData->hInformOnAppDeath;
548 if( bClearSetHandles )
550 CloseHandle( lpLData->hInformOnAppDeath );
551 lpLData->hInformOnAppDeath = 0;
555 if( lphConnRead != NULL )
557 if( lpLData->hInformOnSettingRead == 0 )
559 DPLAYX_ReleaseSemaphore();
560 return FALSE;
563 *lphConnRead = lpLData->hInformOnSettingRead;
565 if( bClearSetHandles )
567 CloseHandle( lpLData->hInformOnSettingRead );
568 lpLData->hInformOnSettingRead = 0;
572 DPLAYX_ReleaseSemaphore();
574 return TRUE;
578 HRESULT DPLAYX_GetConnectionSettingsA
579 ( DWORD dwAppID,
580 LPVOID lpData,
581 LPDWORD lpdwDataSize )
583 LPDPLAYX_LOBBYDATA lpDplData;
584 DWORD dwRequiredDataSize = 0;
585 HANDLE hInformOnSettingRead;
587 DPLAYX_AquireSemaphore();
589 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
591 DPLAYX_ReleaseSemaphore();
593 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
594 return DPERR_NOTLOBBIED;
597 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
599 /* Do they want to know the required buffer size or is the provided buffer
600 * big enough?
602 if ( ( lpData == NULL ) ||
603 ( *lpdwDataSize < dwRequiredDataSize )
606 DPLAYX_ReleaseSemaphore();
608 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
610 return DPERR_BUFFERTOOSMALL;
613 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
615 DPLAYX_ReleaseSemaphore();
617 /* They have gotten the information - signal the event if required */
618 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
619 hInformOnSettingRead
622 BOOL bSuccess;
623 bSuccess = SetEvent( hInformOnSettingRead );
624 TRACE( "Signalling setting read event %u %s\n",
625 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
627 /* Close out handle */
628 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
631 return DP_OK;
634 /* Assumption: Enough contiguous space was allocated at dest */
635 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
637 BYTE* lpStartOfFreeSpace;
639 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
641 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
643 /* Copy the LPDPSESSIONDESC2 structure if it exists */
644 if( src->lpSessionDesc )
646 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
647 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
648 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
650 /* Session names may or may not exist */
651 if( src->lpSessionDesc->u1.lpszSessionNameA )
653 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
654 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
655 lpStartOfFreeSpace +=
656 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
659 if( src->lpSessionDesc->u2.lpszPasswordA )
661 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
662 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
663 lpStartOfFreeSpace +=
664 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
668 /* DPNAME structure is optional */
669 if( src->lpPlayerName )
671 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
672 lpStartOfFreeSpace += sizeof( DPNAME );
673 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
675 if( src->lpPlayerName->u1.lpszShortNameA )
677 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
678 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
679 lpStartOfFreeSpace +=
680 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
683 if( src->lpPlayerName->u2.lpszLongNameA )
685 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
686 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
687 lpStartOfFreeSpace +=
688 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
693 /* Copy address if it exists */
694 if( src->lpAddress )
696 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
697 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
698 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
702 HRESULT DPLAYX_GetConnectionSettingsW
703 ( DWORD dwAppID,
704 LPVOID lpData,
705 LPDWORD lpdwDataSize )
707 LPDPLAYX_LOBBYDATA lpDplData;
708 DWORD dwRequiredDataSize = 0;
709 HANDLE hInformOnSettingRead;
711 DPLAYX_AquireSemaphore();
713 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
715 DPLAYX_ReleaseSemaphore();
716 return DPERR_NOTLOBBIED;
719 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
721 /* Do they want to know the required buffer size or is the provided buffer
722 * big enough?
724 if ( ( lpData == NULL ) ||
725 ( *lpdwDataSize < dwRequiredDataSize )
728 DPLAYX_ReleaseSemaphore();
730 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
732 return DPERR_BUFFERTOOSMALL;
735 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
737 DPLAYX_ReleaseSemaphore();
739 /* They have gotten the information - signal the event if required */
740 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
741 hInformOnSettingRead
744 BOOL bSuccess;
745 bSuccess = SetEvent( hInformOnSettingRead );
746 TRACE( "Signalling setting read event %u %s\n",
747 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
749 /* Close out handle */
750 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
753 return DP_OK;
756 /* Assumption: Enough contiguous space was allocated at dest */
757 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
759 BYTE* lpStartOfFreeSpace;
761 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
763 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
765 /* Copy the LPDPSESSIONDESC2 structure if it exists */
766 if( src->lpSessionDesc )
768 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
769 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
770 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
772 /* Session names may or may not exist */
773 if( src->lpSessionDesc->u1.lpszSessionName )
775 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
776 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
777 lpStartOfFreeSpace += sizeof(WCHAR) *
778 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
781 if( src->lpSessionDesc->u2.lpszPassword )
783 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
784 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
785 lpStartOfFreeSpace += sizeof(WCHAR) *
786 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
790 /* DPNAME structure is optional */
791 if( src->lpPlayerName )
793 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
794 lpStartOfFreeSpace += sizeof( DPNAME );
795 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
797 if( src->lpPlayerName->u1.lpszShortName )
799 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
800 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
801 lpStartOfFreeSpace += sizeof(WCHAR) *
802 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
805 if( src->lpPlayerName->u2.lpszLongName )
807 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
808 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
809 lpStartOfFreeSpace += sizeof(WCHAR) *
810 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
815 /* Copy address if it exists */
816 if( src->lpAddress )
818 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
819 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
820 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
825 /* Store the structure into the shared data structre. Ensure that allocs for
826 * variable length strings come from the shared data structure.
827 * FIXME: We need to free information as well
829 HRESULT DPLAYX_SetConnectionSettingsA
830 ( DWORD dwFlags,
831 DWORD dwAppID,
832 LPDPLCONNECTION lpConn )
834 LPDPLAYX_LOBBYDATA lpDplData;
836 /* Paramater check */
837 if( dwFlags || !lpConn )
839 ERR("invalid parameters.\n");
840 return DPERR_INVALIDPARAMS;
843 /* Store information */
844 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
846 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
847 lpConn->dwSize, sizeof( DPLCONNECTION ) );
849 return DPERR_INVALIDPARAMS;
852 DPLAYX_AquireSemaphore();
854 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
856 DPLAYX_ReleaseSemaphore();
858 return DPERR_NOTLOBBIED;
861 if( (!lpConn->lpSessionDesc ) ||
862 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
865 DPLAYX_ReleaseSemaphore();
867 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
868 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
870 return DPERR_INVALIDPARAMS;
873 /* Free the existing memory */
874 DPLAYX_PrivHeapFree( lpDplData->lpConn );
876 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
877 DPLAYX_SizeOfLobbyDataA( lpConn ) );
879 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
882 DPLAYX_ReleaseSemaphore();
884 /* FIXME: Send a message - I think */
886 return DP_OK;
889 /* Store the structure into the shared data structre. Ensure that allocs for
890 * variable length strings come from the shared data structure.
891 * FIXME: We need to free information as well
893 HRESULT DPLAYX_SetConnectionSettingsW
894 ( DWORD dwFlags,
895 DWORD dwAppID,
896 LPDPLCONNECTION lpConn )
898 LPDPLAYX_LOBBYDATA lpDplData;
900 /* Paramater check */
901 if( dwFlags || !lpConn )
903 ERR("invalid parameters.\n");
904 return DPERR_INVALIDPARAMS;
907 /* Store information */
908 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
910 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
911 lpConn->dwSize, sizeof( DPLCONNECTION ) );
913 return DPERR_INVALIDPARAMS;
916 DPLAYX_AquireSemaphore();
918 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
920 DPLAYX_ReleaseSemaphore();
922 return DPERR_NOTLOBBIED;
925 /* Free the existing memory */
926 DPLAYX_PrivHeapFree( lpDplData->lpConn );
928 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
929 DPLAYX_SizeOfLobbyDataW( lpConn ) );
931 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
934 DPLAYX_ReleaseSemaphore();
936 /* FIXME: Send a message - I think */
938 return DP_OK;
941 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
943 DWORD dwTotalSize = sizeof( DPLCONNECTION );
945 /* Just a safety check */
946 if( lpConn == NULL )
948 ERR( "lpConn is NULL\n" );
949 return 0;
952 if( lpConn->lpSessionDesc != NULL )
954 dwTotalSize += sizeof( DPSESSIONDESC2 );
956 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
958 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
961 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
963 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
967 if( lpConn->lpPlayerName != NULL )
969 dwTotalSize += sizeof( DPNAME );
971 if( lpConn->lpPlayerName->u1.lpszShortNameA )
973 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
976 if( lpConn->lpPlayerName->u2.lpszLongNameA )
978 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
983 dwTotalSize += lpConn->dwAddressSize;
985 return dwTotalSize;
988 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
990 DWORD dwTotalSize = sizeof( DPLCONNECTION );
992 /* Just a safety check */
993 if( lpConn == NULL )
995 ERR( "lpConn is NULL\n" );
996 return 0;
999 if( lpConn->lpSessionDesc != NULL )
1001 dwTotalSize += sizeof( DPSESSIONDESC2 );
1003 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1005 dwTotalSize += sizeof( WCHAR ) *
1006 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1009 if( lpConn->lpSessionDesc->u2.lpszPassword )
1011 dwTotalSize += sizeof( WCHAR ) *
1012 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1016 if( lpConn->lpPlayerName != NULL )
1018 dwTotalSize += sizeof( DPNAME );
1020 if( lpConn->lpPlayerName->u1.lpszShortName )
1022 dwTotalSize += sizeof( WCHAR ) *
1023 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1026 if( lpConn->lpPlayerName->u2.lpszLongName )
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1034 dwTotalSize += lpConn->dwAddressSize;
1036 return dwTotalSize;
1041 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1043 LPDPSESSIONDESC2 lpSessionDest =
1044 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1045 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1046 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1048 return lpSessionDest;
1051 /* Copy an ANSI session desc structure to the given buffer */
1052 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1053 LPCDPSESSIONDESC2 lpSessionSrc )
1055 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1057 if( lpSessionSrc->u1.lpszSessionNameA )
1059 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1060 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1061 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1063 if( lpSessionSrc->u2.lpszPasswordA )
1065 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1066 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1067 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1070 return TRUE;
1073 /* Start the index at 0. index will be updated to equal that which should
1074 be passed back into this function for the next element */
1075 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1077 for( ; (*index) < numSupportedSessions; (*index)++ )
1079 if( sessionData[(*index)].dwSize != 0 )
1081 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1085 /* No more sessions */
1086 return NULL;
1089 /* Start the index at 0. index will be updated to equal that which should
1090 be passed back into this function for the next element */
1091 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1093 for( ; (*index) < numSupportedSessions; (*index)++ )
1095 if( sessionData[(*index)].dwSize != 0 )
1097 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1101 /* No more sessions */
1102 return FALSE;
1105 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1107 UINT i;
1109 /* FIXME: Is this an error if it exists already? */
1111 /* Crude/wrong implementation for now. Just always add to first empty spot */
1112 for( i=0; i < numSupportedSessions; i++ )
1114 /* Is this one empty? */
1115 if( sessionData[i].dwSize == 0 )
1117 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1118 break;
1124 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1126 LPDPLAYX_LOBBYDATA lpLobbyData;
1128 DPLAYX_AquireSemaphore();
1130 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1132 DPLAYX_ReleaseSemaphore();
1133 return FALSE;
1136 lpLobbyData->bWaitForConnectionSettings = bWait;
1138 DPLAYX_ReleaseSemaphore();
1140 return TRUE;
1143 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1145 UINT i;
1146 BOOL bFound = FALSE;
1148 DPLAYX_AquireSemaphore();
1150 for( i=0; i < numSupportedLobbies; i++ )
1152 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1153 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1156 bFound = TRUE;
1157 break;
1161 DPLAYX_ReleaseSemaphore();
1163 return bFound;
1166 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1168 LPDPLAYX_LOBBYDATA lpLobbyData;
1170 DPLAYX_AquireSemaphore();
1172 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1174 DPLAYX_ReleaseSemaphore();
1175 return FALSE;
1178 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1180 DPLAYX_ReleaseSemaphore();
1182 return TRUE;
1185 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1186 with the correct string printed in the case where the HRESULT is not
1187 known. You'll just get the last hr passed in printed. This can change
1188 over time if this method is used alot :) */
1189 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1191 static char szTempStr[12];
1193 switch (hr)
1195 case DP_OK:
1196 return "DP_OK";
1197 case DPERR_ALREADYINITIALIZED:
1198 return "DPERR_ALREADYINITIALIZED";
1199 case DPERR_ACCESSDENIED:
1200 return "DPERR_ACCESSDENIED";
1201 case DPERR_ACTIVEPLAYERS:
1202 return "DPERR_ACTIVEPLAYERS";
1203 case DPERR_BUFFERTOOSMALL:
1204 return "DPERR_BUFFERTOOSMALL";
1205 case DPERR_CANTADDPLAYER:
1206 return "DPERR_CANTADDPLAYER";
1207 case DPERR_CANTCREATEGROUP:
1208 return "DPERR_CANTCREATEGROUP";
1209 case DPERR_CANTCREATEPLAYER:
1210 return "DPERR_CANTCREATEPLAYER";
1211 case DPERR_CANTCREATESESSION:
1212 return "DPERR_CANTCREATESESSION";
1213 case DPERR_CAPSNOTAVAILABLEYET:
1214 return "DPERR_CAPSNOTAVAILABLEYET";
1215 case DPERR_EXCEPTION:
1216 return "DPERR_EXCEPTION";
1217 case DPERR_GENERIC:
1218 return "DPERR_GENERIC";
1219 case DPERR_INVALIDFLAGS:
1220 return "DPERR_INVALIDFLAGS";
1221 case DPERR_INVALIDOBJECT:
1222 return "DPERR_INVALIDOBJECT";
1223 case DPERR_INVALIDPARAMS:
1224 return "DPERR_INVALIDPARAMS";
1225 case DPERR_INVALIDPLAYER:
1226 return "DPERR_INVALIDPLAYER";
1227 case DPERR_INVALIDGROUP:
1228 return "DPERR_INVALIDGROUP";
1229 case DPERR_NOCAPS:
1230 return "DPERR_NOCAPS";
1231 case DPERR_NOCONNECTION:
1232 return "DPERR_NOCONNECTION";
1233 case DPERR_OUTOFMEMORY:
1234 return "DPERR_OUTOFMEMORY";
1235 case DPERR_NOMESSAGES:
1236 return "DPERR_NOMESSAGES";
1237 case DPERR_NONAMESERVERFOUND:
1238 return "DPERR_NONAMESERVERFOUND";
1239 case DPERR_NOPLAYERS:
1240 return "DPERR_NOPLAYERS";
1241 case DPERR_NOSESSIONS:
1242 return "DPERR_NOSESSIONS";
1243 /* This one isn't defined yet in WINE sources. I don't know the value
1244 case DPERR_PENDING:
1245 return "DPERR_PENDING";
1247 case DPERR_SENDTOOBIG:
1248 return "DPERR_SENDTOOBIG";
1249 case DPERR_TIMEOUT:
1250 return "DPERR_TIMEOUT";
1251 case DPERR_UNAVAILABLE:
1252 return "DPERR_UNAVAILABLE";
1253 case DPERR_UNSUPPORTED:
1254 return "DPERR_UNSUPPORTED";
1255 case DPERR_BUSY:
1256 return "DPERR_BUSY";
1257 case DPERR_USERCANCEL:
1258 return "DPERR_USERCANCEL";
1259 case DPERR_NOINTERFACE:
1260 return "DPERR_NOINTERFACE";
1261 case DPERR_CANNOTCREATESERVER:
1262 return "DPERR_CANNOTCREATESERVER";
1263 case DPERR_PLAYERLOST:
1264 return "DPERR_PLAYERLOST";
1265 case DPERR_SESSIONLOST:
1266 return "DPERR_SESSIONLOST";
1267 case DPERR_UNINITIALIZED:
1268 return "DPERR_UNINITIALIZED";
1269 case DPERR_NONEWPLAYERS:
1270 return "DPERR_NONEWPLAYERS";
1271 case DPERR_INVALIDPASSWORD:
1272 return "DPERR_INVALIDPASSWORD";
1273 case DPERR_CONNECTING:
1274 return "DPERR_CONNECTING";
1275 case DPERR_CONNECTIONLOST:
1276 return "DPERR_CONNECTIONLOST";
1277 case DPERR_UNKNOWNMESSAGE:
1278 return "DPERR_UNKNOWNMESSAGE";
1279 case DPERR_CANCELFAILED:
1280 return "DPERR_CANCELFAILED";
1281 case DPERR_INVALIDPRIORITY:
1282 return "DPERR_INVALIDPRIORITY";
1283 case DPERR_NOTHANDLED:
1284 return "DPERR_NOTHANDLED";
1285 case DPERR_CANCELLED:
1286 return "DPERR_CANCELLED";
1287 case DPERR_ABORTED:
1288 return "DPERR_ABORTED";
1289 case DPERR_BUFFERTOOLARGE:
1290 return "DPERR_BUFFERTOOLARGE";
1291 case DPERR_CANTCREATEPROCESS:
1292 return "DPERR_CANTCREATEPROCESS";
1293 case DPERR_APPNOTSTARTED:
1294 return "DPERR_APPNOTSTARTED";
1295 case DPERR_INVALIDINTERFACE:
1296 return "DPERR_INVALIDINTERFACE";
1297 case DPERR_NOSERVICEPROVIDER:
1298 return "DPERR_NOSERVICEPROVIDER";
1299 case DPERR_UNKNOWNAPPLICATION:
1300 return "DPERR_UNKNOWNAPPLICATION";
1301 case DPERR_NOTLOBBIED:
1302 return "DPERR_NOTLOBBIED";
1303 case DPERR_SERVICEPROVIDERLOADED:
1304 return "DPERR_SERVICEPROVIDERLOADED";
1305 case DPERR_ALREADYREGISTERED:
1306 return "DPERR_ALREADYREGISTERED";
1307 case DPERR_NOTREGISTERED:
1308 return "DPERR_NOTREGISTERED";
1309 case DPERR_AUTHENTICATIONFAILED:
1310 return "DPERR_AUTHENTICATIONFAILED";
1311 case DPERR_CANTLOADSSPI:
1312 return "DPERR_CANTLOADSSPI";
1313 case DPERR_ENCRYPTIONFAILED:
1314 return "DPERR_ENCRYPTIONFAILED";
1315 case DPERR_SIGNFAILED:
1316 return "DPERR_SIGNFAILED";
1317 case DPERR_CANTLOADSECURITYPACKAGE:
1318 return "DPERR_CANTLOADSECURITYPACKAGE";
1319 case DPERR_ENCRYPTIONNOTSUPPORTED:
1320 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1321 case DPERR_CANTLOADCAPI:
1322 return "DPERR_CANTLOADCAPI";
1323 case DPERR_NOTLOGGEDIN:
1324 return "DPERR_NOTLOGGEDIN";
1325 case DPERR_LOGONDENIED:
1326 return "DPERR_LOGONDENIED";
1327 default:
1328 /* For errors not in the list, return HRESULT as a string
1329 This part is not thread safe */
1330 WARN( "Unknown error 0x%08lx\n", hr );
1331 wsprintfA( szTempStr, "0x%08lx", hr );
1332 return szTempStr;