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.
14 #include "debugtools.h"
18 #include "dplayx_global.h"
19 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
21 DEFAULT_DEBUG_CHANNEL(dplay);
23 /* FIXME: Need to do all that fun other dll referencing type of stuff */
25 /* Static data for all processes */
26 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
27 static HANDLE hDplayxSema;
29 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
30 static HANDLE hDplayxSharedMem;
32 static LPVOID lpSharedStaticData = NULL;
35 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
36 WaitForSingleObject( hDplayxSema, INFINITE );\
37 TRACE( "Through wait\n" )
39 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
40 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
43 /* HACK for simple global data right now */
44 #define dwStaticSharedSize (128 * 1024) /* FIXME: Way too much */
45 #define dwDynamicSharedSize (128 * 1024) /* FIXME: Enough? */
46 #define dwTotalSharedSize (dwStaticSharedSize + dwDynamicSharedSize)
49 /* FIXME: Is there no easier way? */
51 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
52 * Each block has 4 bytes which are 0 unless used */
53 #define dwBlockSize 512
54 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
60 DWORD data[dwBlockSize-sizeof(DWORD)];
63 DPLAYX_MEM_SLICE* lpMemArea;
65 void DPLAYX_PrivHeapFree( LPVOID addr );
66 void DPLAYX_PrivHeapFree( LPVOID addr )
71 /* Handle getting passed a NULL */
77 lpAddrStart = addr - sizeof(DWORD); /* Find block header */
78 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
80 lpMemArea[ dwBlockUsed ].used = 0;
83 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
84 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
86 LPVOID lpvArea = NULL;
89 if( size > (dwBlockSize - sizeof(DWORD)) )
91 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
92 size = dwBlockSize - sizeof(DWORD);
97 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
99 if( uBlockUsed <= dwMaxBlock )
101 /* Set the area used */
102 lpMemArea[ uBlockUsed ].used = 1;
103 lpvArea = &(lpMemArea[ uBlockUsed ].data);
107 ERR( "No free block found\n" );
111 if( flags & HEAP_ZERO_MEMORY )
113 ZeroMemory( lpvArea, size );
119 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
120 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
122 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
129 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
130 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
132 INT len = lstrlenW(str) + 1;
133 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
141 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
142 typedef struct tagDPLAYX_LOBBYDATA
144 /* Points to lpConn + block of contiguous extra memory for dynamic parts
145 * of the struct directly following
147 LPDPLCONNECTION lpConn;
149 /* Information for dplobby interfaces */
151 HANDLE hReceiveEvent;
152 DWORD dwAppLaunchedFromID;
154 /* Should this lobby app send messages to creator at important life
157 BOOL bInformOnConnect; /* FIXME: Not used yet */
158 BOOL bInformOnSettingRead;
159 BOOL bInformOnAppDeath; /* FIXME: Not used yet */
161 BOOL bWaitForConnectionSettings;
163 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
165 static DPLAYX_LOBBYDATA* lobbyData = NULL;
166 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
168 static DPSESSIONDESC2* sessionData = NULL;
169 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
171 /* Function prototypes */
172 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
173 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
174 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
175 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
176 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
177 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
178 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
179 LPCDPSESSIONDESC2 lpSessionSrc );
183 /***************************************************************************
184 * Called to initialize the global data. This will only be used on the
186 ***************************************************************************/
187 BOOL DPLAYX_ConstructData(void)
189 SECURITY_ATTRIBUTES s_attrib;
190 BOOL bInitializeSharedMemory = FALSE;
191 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
193 TRACE( "DPLAYX dll loaded - construct called\n" );
195 /* Create a semaphore to block access to DPLAYX global data structs */
197 s_attrib.bInheritHandle = TRUE;
198 s_attrib.lpSecurityDescriptor = NULL;
199 s_attrib.nLength = sizeof(s_attrib);
201 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
203 /* First instance creates the semaphore. Others just use it */
204 if( GetLastError() == ERROR_SUCCESS )
206 TRACE( "Semaphore %u created\n", hDplayxSema );
208 /* The semaphore creator will also build the shared memory */
209 bInitializeSharedMemory = TRUE;
211 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
213 TRACE( "Found semaphore handle %u\n", hDplayxSema );
217 ERR( ": semaphore error 0x%08lx\n", GetLastError() );
221 SetLastError( ERROR_SUCCESS );
223 DPLAYX_AquireSemaphore();
225 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
227 PAGE_READWRITE | SEC_COMMIT,
230 lpszDplayxFileMapping );
232 if( GetLastError() == ERROR_SUCCESS )
234 TRACE( "File mapped %u created\n", hDplayxSharedMem );
236 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
238 TRACE( "Found FileMapping handle %u\n", hDplayxSharedMem );
242 ERR( ": unable to create shared memory 0x%08lx\n", GetLastError() );
246 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
248 0, 0, 0, lpDesiredMemoryMapStart );
250 if( lpSharedStaticData == NULL )
252 ERR( ": unable to map static data into process memory space: 0x%08lx\n",
258 if( lpDesiredMemoryMapStart == lpSharedStaticData )
260 TRACE( "File mapped to %p\n", lpSharedStaticData );
264 /* Presently the shared data structures use pointers. If the
265 * files are no mapped into the same area, the pointers will no
266 * longer make any sense :(
267 * FIXME: In the future make the shared data structures have some
268 * sort of fixup to make them independent between data spaces.
269 * This will also require a rework of the session data stuff.
271 ERR( "File mapped to %p (not %p). Expect failure\n",
272 lpSharedStaticData, lpDesiredMemoryMapStart );
276 /* Dynamic area starts just after the static area */
277 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
279 /* FIXME: Crude hack */
280 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
281 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
283 /* Initialize shared data segments. */
284 if( bInitializeSharedMemory )
288 TRACE( "Initializing shared memory\n" );
290 /* Set all lobbies to be "empty" */
291 for( i=0; i < numSupportedLobbies; i++ )
293 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
296 /* Set all sessions to be "empty" */
297 for( i=0; i < numSupportedSessions; i++ )
299 sessionData[i].dwSize = 0;
302 /* Zero out the dynmaic area */
303 ZeroMemory( lpMemArea, dwDynamicSharedSize );
305 /* Just for fun sync the whole data area */
306 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
309 DPLAYX_ReleaseSemaphore();
314 /***************************************************************************
315 * Called to destroy all global data. This will only be used on the
316 * unloading of the dll
317 ***************************************************************************/
318 BOOL DPLAYX_DestructData(void)
320 TRACE( "DPLAYX dll unloaded - destruct called\n" );
322 /* Delete the semaphore */
323 CloseHandle( hDplayxSema );
325 /* Delete shared memory file mapping */
326 UnmapViewOfFile( lpSharedStaticData );
327 CloseHandle( hDplayxSharedMem );
333 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
335 ZeroMemory( lpData, sizeof( *lpData ) );
337 /* Set the handle to a better invalid value */
338 lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
341 /* NOTE: This must be called with the semaphore aquired.
342 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
343 * is only valid if TRUE is returned.
345 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
353 dwAppID = GetCurrentProcessId();
354 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
357 for( i=0; i < numSupportedLobbies; i++ )
359 if( lobbyData[ i ].dwAppID == dwAppID )
361 /* This process is lobbied */
362 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
363 *lplpDplData = &lobbyData[ i ];
371 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
372 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
376 /* 0 is the marker for unused application data slots */
382 DPLAYX_AquireSemaphore();
384 /* Find an empty space in the list and insert the data */
385 for( i=0; i < numSupportedLobbies; i++ )
387 if( lobbyData[ i ].dwAppID == 0 )
389 /* This process is now lobbied */
390 TRACE( "Setting lobbyData[%u] for (0x%08lx,%u,0x%08lx)\n",
391 i, dwAppID, hReceiveEvent, GetCurrentProcessId() );
393 lobbyData[ i ].dwAppID = dwAppID;
394 lobbyData[ i ].hReceiveEvent = hReceiveEvent;
395 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
397 lobbyData[ i ].bInformOnConnect = TRUE;
398 lobbyData[ i ].bInformOnSettingRead = TRUE;
399 lobbyData[ i ].bInformOnAppDeath = TRUE;
401 DPLAYX_ReleaseSemaphore();
406 ERR( "No empty lobbies\n" );
408 DPLAYX_ReleaseSemaphore();
412 /* I'm not sure when I'm going to need this, but here it is */
413 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
417 DPLAYX_AquireSemaphore();
419 /* Find an empty space in the list and insert the data */
420 for( i=0; i < numSupportedLobbies; i++ )
422 if( lobbyData[ i ].dwAppID == dwAppID )
424 /* FIXME: Should free up anything unused. Tisk tisk :0 */
425 /* Mark this entry unused */
426 TRACE( "Marking lobbyData[%u] unused\n", i );
427 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
429 DPLAYX_ReleaseSemaphore();
434 DPLAYX_ReleaseSemaphore();
435 ERR( "Unable to find global entry for application\n" );
439 HRESULT DPLAYX_GetConnectionSettingsA
442 LPDWORD lpdwDataSize,
443 LPBOOL lpbSendHaveReadMessage )
445 LPDPLAYX_LOBBYDATA lpDplData;
446 DWORD dwRequiredDataSize = 0;
448 DPLAYX_AquireSemaphore();
450 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
452 DPLAYX_ReleaseSemaphore();
454 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
455 return DPERR_NOTLOBBIED;
458 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
460 /* Do they want to know the required buffer size or is the provided buffer
463 if ( ( lpData == NULL ) ||
464 ( *lpdwDataSize < dwRequiredDataSize )
467 DPLAYX_ReleaseSemaphore();
469 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
471 return DPERR_BUFFERTOOSMALL;
474 /* They have gotten the information */
475 *lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
476 lpDplData->bInformOnSettingRead = FALSE;
478 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
480 DPLAYX_ReleaseSemaphore();
485 /* Assumption: Enough contiguous space was allocated at dest */
486 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
488 BYTE* lpStartOfFreeSpace;
490 memcpy( dest, src, sizeof( DPLCONNECTION ) );
492 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
494 /* Copy the LPDPSESSIONDESC2 structure if it exists */
495 if( src->lpSessionDesc )
497 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
498 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
499 memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
501 /* Session names may or may not exist */
502 if( src->lpSessionDesc->sess.lpszSessionNameA )
504 lstrcpyA( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->sess.lpszSessionNameA );
505 dest->lpSessionDesc->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
506 lpStartOfFreeSpace +=
507 lstrlenA( (LPSTR)dest->lpSessionDesc->sess.lpszSessionName ) + 1;
510 if( src->lpSessionDesc->pass.lpszPasswordA )
512 lstrcpyA( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->pass.lpszPasswordA );
513 dest->lpSessionDesc->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
514 lpStartOfFreeSpace +=
515 lstrlenA( (LPSTR)dest->lpSessionDesc->pass.lpszPasswordA ) + 1;
519 /* DPNAME structure is optional */
520 if( src->lpPlayerName )
522 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
523 lpStartOfFreeSpace += sizeof( DPNAME );
524 memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
526 if( src->lpPlayerName->psn.lpszShortNameA )
528 lstrcpyA( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->psn.lpszShortNameA );
529 dest->lpPlayerName->psn.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
530 lpStartOfFreeSpace +=
531 lstrlenA( (LPSTR)dest->lpPlayerName->psn.lpszShortNameA ) + 1;
534 if( src->lpPlayerName->pln.lpszLongNameA )
536 lstrcpyA( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->pln.lpszLongNameA );
537 dest->lpPlayerName->pln.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
538 lpStartOfFreeSpace +=
539 lstrlenA( (LPSTR)dest->lpPlayerName->pln.lpszLongName ) + 1 ;
544 /* Copy address if it exists */
547 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
548 memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
549 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
553 HRESULT DPLAYX_GetConnectionSettingsW
556 LPDWORD lpdwDataSize,
557 LPBOOL lpbSendHaveReadMessage )
559 LPDPLAYX_LOBBYDATA lpDplData;
560 DWORD dwRequiredDataSize = 0;
562 DPLAYX_AquireSemaphore();
564 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
566 DPLAYX_ReleaseSemaphore();
567 return DPERR_NOTLOBBIED;
570 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
572 /* Do they want to know the required buffer size or is the provided buffer
575 if ( ( lpData == NULL ) ||
576 ( *lpdwDataSize < dwRequiredDataSize )
579 DPLAYX_ReleaseSemaphore();
581 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
583 return DPERR_BUFFERTOOSMALL;
586 /* They have gotten the information */
587 *lpbSendHaveReadMessage = lpDplData->bInformOnSettingRead;
588 lpDplData->bInformOnSettingRead = FALSE;
590 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
592 DPLAYX_ReleaseSemaphore();
597 /* Assumption: Enough contiguous space was allocated at dest */
598 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
600 BYTE* lpStartOfFreeSpace;
602 memcpy( dest, src, sizeof( DPLCONNECTION ) );
604 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
606 /* Copy the LPDPSESSIONDESC2 structure if it exists */
607 if( src->lpSessionDesc )
609 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
610 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
611 memcpy( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
613 /* Session names may or may not exist */
614 if( src->lpSessionDesc->sess.lpszSessionName )
616 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->sess.lpszSessionName );
617 src->lpSessionDesc->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
618 lpStartOfFreeSpace += sizeof(WCHAR) *
619 ( lstrlenW( (LPWSTR)dest->lpSessionDesc->sess.lpszSessionName ) + 1 );
622 if( src->lpSessionDesc->pass.lpszPassword )
624 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->pass.lpszPassword );
625 dest->lpSessionDesc->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
626 lpStartOfFreeSpace += sizeof(WCHAR) *
627 ( lstrlenW( (LPWSTR)dest->lpSessionDesc->pass.lpszPassword ) + 1 );
631 /* DPNAME structure is optional */
632 if( src->lpPlayerName )
634 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
635 lpStartOfFreeSpace += sizeof( DPNAME );
636 memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
638 if( src->lpPlayerName->psn.lpszShortName )
640 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->psn.lpszShortName );
641 dest->lpPlayerName->psn.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
642 lpStartOfFreeSpace += sizeof(WCHAR) *
643 ( lstrlenW( (LPWSTR)dest->lpPlayerName->psn.lpszShortName ) + 1 );
646 if( src->lpPlayerName->pln.lpszLongName )
648 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->pln.lpszLongName );
649 dest->lpPlayerName->pln.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
650 lpStartOfFreeSpace += sizeof(WCHAR) *
651 ( lstrlenW( (LPWSTR)dest->lpPlayerName->pln.lpszLongName ) + 1 );
656 /* Copy address if it exists */
659 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
660 memcpy( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
661 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
666 /* Store the structure into the shared data structre. Ensure that allocs for
667 * variable length strings come from the shared data structure.
668 * FIXME: We need to free information as well
670 HRESULT DPLAYX_SetConnectionSettingsA
673 LPDPLCONNECTION lpConn )
675 LPDPLAYX_LOBBYDATA lpDplData;
677 /* Paramater check */
678 if( dwFlags || !lpConn )
680 ERR("invalid parameters.\n");
681 return DPERR_INVALIDPARAMS;
684 /* Store information */
685 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
687 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
688 lpConn->dwSize, sizeof( DPLCONNECTION ) );
690 return DPERR_INVALIDPARAMS;
693 DPLAYX_AquireSemaphore();
695 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
697 DPLAYX_ReleaseSemaphore();
699 return DPERR_NOTLOBBIED;
702 if( (!lpConn->lpSessionDesc ) ||
703 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
706 DPLAYX_ReleaseSemaphore();
708 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
709 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
711 return DPERR_INVALIDPARAMS;
714 /* Free the existing memory */
715 DPLAYX_PrivHeapFree( lpDplData->lpConn );
717 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
718 DPLAYX_SizeOfLobbyDataA( lpConn ) );
720 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
723 DPLAYX_ReleaseSemaphore();
725 /* FIXME: Send a message - I think */
730 /* Store the structure into the shared data structre. Ensure that allocs for
731 * variable length strings come from the shared data structure.
732 * FIXME: We need to free information as well
734 HRESULT DPLAYX_SetConnectionSettingsW
737 LPDPLCONNECTION lpConn )
739 LPDPLAYX_LOBBYDATA lpDplData;
741 /* Paramater check */
742 if( dwFlags || !lpConn )
744 ERR("invalid parameters.\n");
745 return DPERR_INVALIDPARAMS;
748 /* Store information */
749 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
751 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
752 lpConn->dwSize, sizeof( DPLCONNECTION ) );
754 return DPERR_INVALIDPARAMS;
757 DPLAYX_AquireSemaphore();
759 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
761 DPLAYX_ReleaseSemaphore();
763 return DPERR_NOTLOBBIED;
766 /* Free the existing memory */
767 DPLAYX_PrivHeapFree( lpDplData->lpConn );
769 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
770 DPLAYX_SizeOfLobbyDataW( lpConn ) );
772 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
775 DPLAYX_ReleaseSemaphore();
777 /* FIXME: Send a message - I think */
782 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
784 DWORD dwTotalSize = sizeof( DPLCONNECTION );
786 /* Just a safety check */
789 ERR( "lpConn is NULL\n" );
793 if( lpConn->lpSessionDesc != NULL )
795 dwTotalSize += sizeof( DPSESSIONDESC2 );
797 if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
799 dwTotalSize += lstrlenA( lpConn->lpSessionDesc->sess.lpszSessionNameA ) + 1;
802 if( lpConn->lpSessionDesc->pass.lpszPasswordA )
804 dwTotalSize += lstrlenA( lpConn->lpSessionDesc->pass.lpszPasswordA ) + 1;
808 if( lpConn->lpPlayerName != NULL )
810 dwTotalSize += sizeof( DPNAME );
812 if( lpConn->lpPlayerName->psn.lpszShortNameA )
814 dwTotalSize += lstrlenA( lpConn->lpPlayerName->psn.lpszShortNameA ) + 1;
817 if( lpConn->lpPlayerName->pln.lpszLongNameA )
819 dwTotalSize += lstrlenA( lpConn->lpPlayerName->pln.lpszLongNameA ) + 1;
824 dwTotalSize += lpConn->dwAddressSize;
829 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
831 DWORD dwTotalSize = sizeof( DPLCONNECTION );
833 /* Just a safety check */
836 ERR( "lpConn is NULL\n" );
840 if( lpConn->lpSessionDesc != NULL )
842 dwTotalSize += sizeof( DPSESSIONDESC2 );
844 if( lpConn->lpSessionDesc->sess.lpszSessionName )
846 dwTotalSize += sizeof( WCHAR ) *
847 ( lstrlenW( lpConn->lpSessionDesc->sess.lpszSessionName ) + 1 );
850 if( lpConn->lpSessionDesc->pass.lpszPassword )
852 dwTotalSize += sizeof( WCHAR ) *
853 ( lstrlenW( lpConn->lpSessionDesc->pass.lpszPassword ) + 1 );
857 if( lpConn->lpPlayerName != NULL )
859 dwTotalSize += sizeof( DPNAME );
861 if( lpConn->lpPlayerName->psn.lpszShortName )
863 dwTotalSize += sizeof( WCHAR ) *
864 ( lstrlenW( lpConn->lpPlayerName->psn.lpszShortName ) + 1 );
867 if( lpConn->lpPlayerName->pln.lpszLongName )
869 dwTotalSize += sizeof( WCHAR ) *
870 ( lstrlenW( lpConn->lpPlayerName->pln.lpszLongName ) + 1 );
875 dwTotalSize += lpConn->dwAddressSize;
882 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
884 LPDPSESSIONDESC2 lpSessionDest =
885 (LPDPSESSIONDESC2)DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
886 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
888 return lpSessionDest;
891 /* Copy an ANSI session desc structure to the given buffer */
892 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
893 LPCDPSESSIONDESC2 lpSessionSrc )
895 memcpy( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
897 if( lpSessionSrc->sess.lpszSessionNameA )
899 lpSessionDest->sess.lpszSessionNameA =
900 DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
902 if( lpSessionSrc->pass.lpszPasswordA )
904 lpSessionDest->pass.lpszPasswordA =
905 DPLAYX_strdupA( HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
911 /* Start the index at 0. index will be updated to equal that which should
912 be passed back into this function for the next element */
913 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
915 for( ; (*index) < numSupportedSessions; (*index)++ )
917 if( sessionData[(*index)].dwSize != 0 )
919 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
923 /* No more sessions */
927 /* Start the index at 0. index will be updated to equal that which should
928 be passed back into this function for the next element */
929 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
931 for( ; (*index) < numSupportedSessions; (*index)++ )
933 if( sessionData[(*index)].dwSize != 0 )
935 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
939 /* No more sessions */
943 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
947 /* FIXME: Is this an error if it exists already? */
949 /* Crude/wrong implementation for now. Just always add to first empty spot */
950 for( i=0; i < numSupportedSessions; i++ )
952 /* Is this one empty? */
953 if( sessionData[i].dwSize == 0 )
955 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
962 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
964 LPDPLAYX_LOBBYDATA lpLobbyData;
966 DPLAYX_AquireSemaphore();
968 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
970 DPLAYX_ReleaseSemaphore();
974 lpLobbyData->bWaitForConnectionSettings = bWait;
976 DPLAYX_ReleaseSemaphore();
981 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
986 DPLAYX_AquireSemaphore();
988 for( i=0; i < numSupportedLobbies; i++ )
990 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
991 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
999 DPLAYX_ReleaseSemaphore();
1005 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1006 with the correct string printed in the case where the HRESULT is not
1007 known. You'll just get the last hr passed in printed. This can change
1008 over time if this method is used alot :) */
1009 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1011 static char szTempStr[12];
1017 case DPERR_ALREADYINITIALIZED:
1018 return "DPERR_ALREADYINITIALIZED";
1019 case DPERR_ACCESSDENIED:
1020 return "DPERR_ACCESSDENIED";
1021 case DPERR_ACTIVEPLAYERS:
1022 return "DPERR_ACTIVEPLAYERS";
1023 case DPERR_BUFFERTOOSMALL:
1024 return "DPERR_BUFFERTOOSMALL";
1025 case DPERR_CANTADDPLAYER:
1026 return "DPERR_CANTADDPLAYER";
1027 case DPERR_CANTCREATEGROUP:
1028 return "DPERR_CANTCREATEGROUP";
1029 case DPERR_CANTCREATEPLAYER:
1030 return "DPERR_CANTCREATEPLAYER";
1031 case DPERR_CANTCREATESESSION:
1032 return "DPERR_CANTCREATESESSION";
1033 case DPERR_CAPSNOTAVAILABLEYET:
1034 return "DPERR_CAPSNOTAVAILABLEYET";
1035 case DPERR_EXCEPTION:
1036 return "DPERR_EXCEPTION";
1038 return "DPERR_GENERIC";
1039 case DPERR_INVALIDFLAGS:
1040 return "DPERR_INVALIDFLAGS";
1041 case DPERR_INVALIDOBJECT:
1042 return "DPERR_INVALIDOBJECT";
1043 case DPERR_INVALIDPARAMS:
1044 return "DPERR_INVALIDPARAMS";
1045 case DPERR_INVALIDPLAYER:
1046 return "DPERR_INVALIDPLAYER";
1047 case DPERR_INVALIDGROUP:
1048 return "DPERR_INVALIDGROUP";
1050 return "DPERR_NOCAPS";
1051 case DPERR_NOCONNECTION:
1052 return "DPERR_NOCONNECTION";
1053 case DPERR_OUTOFMEMORY:
1054 return "DPERR_OUTOFMEMORY";
1055 case DPERR_NOMESSAGES:
1056 return "DPERR_NOMESSAGES";
1057 case DPERR_NONAMESERVERFOUND:
1058 return "DPERR_NONAMESERVERFOUND";
1059 case DPERR_NOPLAYERS:
1060 return "DPERR_NOPLAYERS";
1061 case DPERR_NOSESSIONS:
1062 return "DPERR_NOSESSIONS";
1063 /* This one isn't defined yet in WINE sources. I don't know the value
1065 return "DPERR_PENDING";
1067 case DPERR_SENDTOOBIG:
1068 return "DPERR_SENDTOOBIG";
1070 return "DPERR_TIMEOUT";
1071 case DPERR_UNAVAILABLE:
1072 return "DPERR_UNAVAILABLE";
1073 case DPERR_UNSUPPORTED:
1074 return "DPERR_UNSUPPORTED";
1076 return "DPERR_BUSY";
1077 case DPERR_USERCANCEL:
1078 return "DPERR_USERCANCEL";
1079 case DPERR_NOINTERFACE:
1080 return "DPERR_NOINTERFACE";
1081 case DPERR_CANNOTCREATESERVER:
1082 return "DPERR_CANNOTCREATESERVER";
1083 case DPERR_PLAYERLOST:
1084 return "DPERR_PLAYERLOST";
1085 case DPERR_SESSIONLOST:
1086 return "DPERR_SESSIONLOST";
1087 case DPERR_UNINITIALIZED:
1088 return "DPERR_UNINITIALIZED";
1089 case DPERR_NONEWPLAYERS:
1090 return "DPERR_NONEWPLAYERS";
1091 case DPERR_INVALIDPASSWORD:
1092 return "DPERR_INVALIDPASSWORD";
1093 case DPERR_CONNECTING:
1094 return "DPERR_CONNECTING";
1095 case DPERR_CONNECTIONLOST:
1096 return "DPERR_CONNECTIONLOST";
1097 case DPERR_UNKNOWNMESSAGE:
1098 return "DPERR_UNKNOWNMESSAGE";
1099 case DPERR_CANCELFAILED:
1100 return "DPERR_CANCELFAILED";
1101 case DPERR_INVALIDPRIORITY:
1102 return "DPERR_INVALIDPRIORITY";
1103 case DPERR_NOTHANDLED:
1104 return "DPERR_NOTHANDLED";
1105 case DPERR_CANCELLED:
1106 return "DPERR_CANCELLED";
1108 return "DPERR_ABORTED";
1109 case DPERR_BUFFERTOOLARGE:
1110 return "DPERR_BUFFERTOOLARGE";
1111 case DPERR_CANTCREATEPROCESS:
1112 return "DPERR_CANTCREATEPROCESS";
1113 case DPERR_APPNOTSTARTED:
1114 return "DPERR_APPNOTSTARTED";
1115 case DPERR_INVALIDINTERFACE:
1116 return "DPERR_INVALIDINTERFACE";
1117 case DPERR_NOSERVICEPROVIDER:
1118 return "DPERR_NOSERVICEPROVIDER";
1119 case DPERR_UNKNOWNAPPLICATION:
1120 return "DPERR_UNKNOWNAPPLICATION";
1121 case DPERR_NOTLOBBIED:
1122 return "DPERR_NOTLOBBIED";
1123 case DPERR_SERVICEPROVIDERLOADED:
1124 return "DPERR_SERVICEPROVIDERLOADED";
1125 case DPERR_ALREADYREGISTERED:
1126 return "DPERR_ALREADYREGISTERED";
1127 case DPERR_NOTREGISTERED:
1128 return "DPERR_NOTREGISTERED";
1129 case DPERR_AUTHENTICATIONFAILED:
1130 return "DPERR_AUTHENTICATIONFAILED";
1131 case DPERR_CANTLOADSSPI:
1132 return "DPERR_CANTLOADSSPI";
1133 case DPERR_ENCRYPTIONFAILED:
1134 return "DPERR_ENCRYPTIONFAILED";
1135 case DPERR_SIGNFAILED:
1136 return "DPERR_SIGNFAILED";
1137 case DPERR_CANTLOADSECURITYPACKAGE:
1138 return "DPERR_CANTLOADSECURITYPACKAGE";
1139 case DPERR_ENCRYPTIONNOTSUPPORTED:
1140 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1141 case DPERR_CANTLOADCAPI:
1142 return "DPERR_CANTLOADCAPI";
1143 case DPERR_NOTLOGGEDIN:
1144 return "DPERR_NOTLOGGEDIN";
1145 case DPERR_LOGONDENIED:
1146 return "DPERR_LOGONDENIED";
1148 /* For errors not in the list, return HRESULT as a string
1149 This part is not thread safe */
1150 WARN( "Unknown error 0x%08lx\n", hr );
1151 sprintf( szTempStr, "0x%08lx", hr );