1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
9 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with
10 * dplayx.dll data which is accessible from all processes.
13 #include "debugtools.h"
16 #include "wine/unicode.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)
63 DWORD data[dwBlockSize-sizeof(DWORD)];
66 static DPLAYX_MEM_SLICE* lpMemArea;
68 void DPLAYX_PrivHeapFree( LPVOID addr );
69 void DPLAYX_PrivHeapFree( LPVOID addr )
74 /* Handle getting passed a NULL */
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;
93 if( size > (dwBlockSize - sizeof(DWORD)) )
95 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
96 size = dwBlockSize - sizeof(DWORD);
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);
111 ERR( "No free block found\n" );
115 if( flags & HEAP_ZERO_MEMORY )
117 ZeroMemory( lpvArea, size );
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 );
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) );
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 */
155 DWORD dwAppLaunchedFromID;
157 /* Should this lobby app send messages to creator at important life
160 HANDLE hInformOnAppStart;
161 HANDLE hInformOnAppDeath;
162 HANDLE hInformOnSettingRead;
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
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 );
224 ERR( ": semaphore error 0x%08lx\n", GetLastError() );
228 SetLastError( ERROR_SUCCESS );
230 DPLAYX_AquireSemaphore();
232 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
234 PAGE_READWRITE | SEC_COMMIT,
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 );
249 ERR( ": unable to create shared memory 0x%08lx\n", GetLastError() );
253 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
255 0, 0, 0, lpDesiredMemoryMapStart );
257 if( lpSharedStaticData == NULL )
259 ERR( ": unable to map static data into process memory space: 0x%08lx\n",
265 if( lpDesiredMemoryMapStart == lpSharedStaticData )
267 TRACE( "File mapped to %p\n", lpSharedStaticData );
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 )
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 ) &&
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 );
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 ) &&
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 );
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 )
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 ];
409 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
410 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
414 /* 0 is the marker for unused application data slots */
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();
444 ERR( "No empty lobbies\n" );
446 DPLAYX_ReleaseSemaphore();
450 /* I'm not sure when I'm going to need this, but here it is */
451 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
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();
472 DPLAYX_ReleaseSemaphore();
473 ERR( "Unable to find global entry for application\n" );
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 */
488 DPLAYX_AquireSemaphore();
490 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
492 DPLAYX_ReleaseSemaphore();
496 lpLData->hInformOnAppStart = hStart;
497 lpLData->hInformOnAppDeath = hDeath;
498 lpLData->hInformOnSettingRead = hConnRead;
500 DPLAYX_ReleaseSemaphore();
505 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
507 LPHANDLE lphConnRead,
508 BOOL bClearSetHandles )
510 LPDPLAYX_LOBBYDATA lpLData;
512 DPLAYX_AquireSemaphore();
514 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
516 DPLAYX_ReleaseSemaphore();
520 if( lphStart != NULL )
522 if( lpLData->hInformOnAppStart == 0 )
524 DPLAYX_ReleaseSemaphore();
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();
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();
562 *lphConnRead = lpLData->hInformOnSettingRead;
564 if( bClearSetHandles )
566 CloseHandle( lpLData->hInformOnSettingRead );
567 lpLData->hInformOnSettingRead = 0;
571 DPLAYX_ReleaseSemaphore();
577 HRESULT DPLAYX_GetConnectionSettingsA
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
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 ) &&
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 );
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 */
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
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
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 ) &&
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 );
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 */
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
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 */
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
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 */
940 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
942 DWORD dwTotalSize = sizeof( DPLCONNECTION );
944 /* Just a safety check */
947 ERR( "lpConn is NULL\n" );
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;
987 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
989 DWORD dwTotalSize = sizeof( DPLCONNECTION );
991 /* Just a safety check */
994 ERR( "lpConn is NULL\n" );
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;
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 );
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 */
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 */
1104 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
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 );
1123 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1125 LPDPLAYX_LOBBYDATA lpLobbyData;
1127 DPLAYX_AquireSemaphore();
1129 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1131 DPLAYX_ReleaseSemaphore();
1135 lpLobbyData->bWaitForConnectionSettings = bWait;
1137 DPLAYX_ReleaseSemaphore();
1142 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
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 */
1160 DPLAYX_ReleaseSemaphore();
1165 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1167 LPDPLAYX_LOBBYDATA lpLobbyData;
1169 DPLAYX_AquireSemaphore();
1171 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1173 DPLAYX_ReleaseSemaphore();
1177 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1179 DPLAYX_ReleaseSemaphore();
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];
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";
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";
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 /* This one isn't defined yet in WINE sources. I don't know the value
1244 return "DPERR_PENDING";
1246 case DPERR_SENDTOOBIG:
1247 return "DPERR_SENDTOOBIG";
1249 return "DPERR_TIMEOUT";
1250 case DPERR_UNAVAILABLE:
1251 return "DPERR_UNAVAILABLE";
1252 case DPERR_UNSUPPORTED:
1253 return "DPERR_UNSUPPORTED";
1255 return "DPERR_BUSY";
1256 case DPERR_USERCANCEL:
1257 return "DPERR_USERCANCEL";
1258 case DPERR_NOINTERFACE:
1259 return "DPERR_NOINTERFACE";
1260 case DPERR_CANNOTCREATESERVER:
1261 return "DPERR_CANNOTCREATESERVER";
1262 case DPERR_PLAYERLOST:
1263 return "DPERR_PLAYERLOST";
1264 case DPERR_SESSIONLOST:
1265 return "DPERR_SESSIONLOST";
1266 case DPERR_UNINITIALIZED:
1267 return "DPERR_UNINITIALIZED";
1268 case DPERR_NONEWPLAYERS:
1269 return "DPERR_NONEWPLAYERS";
1270 case DPERR_INVALIDPASSWORD:
1271 return "DPERR_INVALIDPASSWORD";
1272 case DPERR_CONNECTING:
1273 return "DPERR_CONNECTING";
1274 case DPERR_CONNECTIONLOST:
1275 return "DPERR_CONNECTIONLOST";
1276 case DPERR_UNKNOWNMESSAGE:
1277 return "DPERR_UNKNOWNMESSAGE";
1278 case DPERR_CANCELFAILED:
1279 return "DPERR_CANCELFAILED";
1280 case DPERR_INVALIDPRIORITY:
1281 return "DPERR_INVALIDPRIORITY";
1282 case DPERR_NOTHANDLED:
1283 return "DPERR_NOTHANDLED";
1284 case DPERR_CANCELLED:
1285 return "DPERR_CANCELLED";
1287 return "DPERR_ABORTED";
1288 case DPERR_BUFFERTOOLARGE:
1289 return "DPERR_BUFFERTOOLARGE";
1290 case DPERR_CANTCREATEPROCESS:
1291 return "DPERR_CANTCREATEPROCESS";
1292 case DPERR_APPNOTSTARTED:
1293 return "DPERR_APPNOTSTARTED";
1294 case DPERR_INVALIDINTERFACE:
1295 return "DPERR_INVALIDINTERFACE";
1296 case DPERR_NOSERVICEPROVIDER:
1297 return "DPERR_NOSERVICEPROVIDER";
1298 case DPERR_UNKNOWNAPPLICATION:
1299 return "DPERR_UNKNOWNAPPLICATION";
1300 case DPERR_NOTLOBBIED:
1301 return "DPERR_NOTLOBBIED";
1302 case DPERR_SERVICEPROVIDERLOADED:
1303 return "DPERR_SERVICEPROVIDERLOADED";
1304 case DPERR_ALREADYREGISTERED:
1305 return "DPERR_ALREADYREGISTERED";
1306 case DPERR_NOTREGISTERED:
1307 return "DPERR_NOTREGISTERED";
1308 case DPERR_AUTHENTICATIONFAILED:
1309 return "DPERR_AUTHENTICATIONFAILED";
1310 case DPERR_CANTLOADSSPI:
1311 return "DPERR_CANTLOADSSPI";
1312 case DPERR_ENCRYPTIONFAILED:
1313 return "DPERR_ENCRYPTIONFAILED";
1314 case DPERR_SIGNFAILED:
1315 return "DPERR_SIGNFAILED";
1316 case DPERR_CANTLOADSECURITYPACKAGE:
1317 return "DPERR_CANTLOADSECURITYPACKAGE";
1318 case DPERR_ENCRYPTIONNOTSUPPORTED:
1319 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1320 case DPERR_CANTLOADCAPI:
1321 return "DPERR_CANTLOADCAPI";
1322 case DPERR_NOTLOGGEDIN:
1323 return "DPERR_NOTLOGGEDIN";
1324 case DPERR_LOGONDENIED:
1325 return "DPERR_LOGONDENIED";
1327 /* For errors not in the list, return HRESULT as a string
1328 This part is not thread safe */
1329 WARN( "Unknown error 0x%08lx\n", hr );
1330 wsprintfA( szTempStr, "0x%08lx", hr );