1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with
23 * dplayx.dll data which is accessible from all processes.
27 #include "wine/debug.h"
30 #include "wine/unicode.h"
35 #include "dplayx_global.h"
36 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
38 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
40 /* FIXME: Need to do all that fun other dll referencing type of stuff */
42 /* Static data for all processes */
43 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
44 static HANDLE hDplayxSema;
46 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
47 static HANDLE hDplayxSharedMem;
49 static LPVOID lpSharedStaticData = NULL;
52 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
53 WaitForSingleObject( hDplayxSema, INFINITE );\
54 TRACE( "Through wait\n" )
56 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
57 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
60 /* HACK for simple global data right now */
61 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
62 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
63 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
66 /* FIXME: Is there no easier way? */
68 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
69 * Each block has 4 bytes which are 0 unless used */
70 #define dwBlockSize 512
71 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
76 DWORD data[dwBlockSize-sizeof(DWORD)];
79 static DPLAYX_MEM_SLICE* lpMemArea;
81 void DPLAYX_PrivHeapFree( LPVOID addr );
82 void DPLAYX_PrivHeapFree( LPVOID addr )
87 /* Handle getting passed a NULL */
93 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
94 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
96 lpMemArea[ dwBlockUsed ].used = 0;
99 /* FIXME: This should be static, but is being used for a hack right now */
100 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
101 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
103 LPVOID lpvArea = NULL;
106 if( size > (dwBlockSize - sizeof(DWORD)) )
108 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
109 size = dwBlockSize - sizeof(DWORD);
112 /* Find blank area */
114 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
116 if( uBlockUsed <= dwMaxBlock )
118 /* Set the area used */
119 lpMemArea[ uBlockUsed ].used = 1;
120 lpvArea = &(lpMemArea[ uBlockUsed ].data);
124 ERR( "No free block found\n" );
128 if( flags & HEAP_ZERO_MEMORY )
130 ZeroMemory( lpvArea, size );
136 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
137 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
139 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
146 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
147 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
149 INT len = strlenW(str) + 1;
150 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
158 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
159 typedef struct tagDPLAYX_LOBBYDATA
161 /* Points to lpConn + block of contiguous extra memory for dynamic parts
162 * of the struct directly following
164 LPDPLCONNECTION lpConn;
166 /* Information for dplobby interfaces */
168 DWORD dwAppLaunchedFromID;
170 /* Should this lobby app send messages to creator at important life
173 HANDLE hInformOnAppStart;
174 HANDLE hInformOnAppDeath;
175 HANDLE hInformOnSettingRead;
178 BOOL bWaitForConnectionSettings;
179 DWORD dwLobbyMsgThreadId;
182 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
184 static DPLAYX_LOBBYDATA* lobbyData = NULL;
185 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
187 static DPSESSIONDESC2* sessionData = NULL;
188 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
190 /* Function prototypes */
191 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
192 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
193 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
194 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
195 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
196 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
197 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
198 LPCDPSESSIONDESC2 lpSessionSrc );
202 /***************************************************************************
203 * Called to initialize the global data. This will only be used on the
205 ***************************************************************************/
206 BOOL DPLAYX_ConstructData(void)
208 SECURITY_ATTRIBUTES s_attrib;
209 BOOL bInitializeSharedMemory = FALSE;
210 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
211 HANDLE hInformOnStart;
213 TRACE( "DPLAYX dll loaded - construct called\n" );
215 /* Create a semaphore to block access to DPLAYX global data structs */
217 s_attrib.bInheritHandle = TRUE;
218 s_attrib.lpSecurityDescriptor = NULL;
219 s_attrib.nLength = sizeof(s_attrib);
221 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
223 /* First instance creates the semaphore. Others just use it */
224 if( GetLastError() == ERROR_SUCCESS )
226 TRACE( "Semaphore %u created\n", hDplayxSema );
228 /* The semaphore creator will also build the shared memory */
229 bInitializeSharedMemory = TRUE;
231 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
233 TRACE( "Found semaphore handle %u\n", hDplayxSema );
237 ERR( ": semaphore error %ld\n", GetLastError() );
241 SetLastError( ERROR_SUCCESS );
243 DPLAYX_AquireSemaphore();
245 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
247 PAGE_READWRITE | SEC_COMMIT,
250 lpszDplayxFileMapping );
252 if( GetLastError() == ERROR_SUCCESS )
254 TRACE( "File mapped %u created\n", hDplayxSharedMem );
256 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
258 TRACE( "Found FileMapping handle %u\n", hDplayxSharedMem );
262 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
266 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
268 0, 0, 0, lpDesiredMemoryMapStart );
270 if( lpSharedStaticData == NULL )
272 ERR( ": unable to map static data into process memory space (%ld)\n",
278 if( lpDesiredMemoryMapStart == lpSharedStaticData )
280 TRACE( "File mapped to %p\n", lpSharedStaticData );
284 /* Presently the shared data structures use pointers. If the
285 * files are no mapped into the same area, the pointers will no
286 * longer make any sense :(
287 * FIXME: In the future make the shared data structures have some
288 * sort of fixup to make them independent between data spaces.
289 * This will also require a rework of the session data stuff.
291 ERR( "File mapped to %p (not %p). Expect failure\n",
292 lpSharedStaticData, lpDesiredMemoryMapStart );
296 /* Dynamic area starts just after the static area */
297 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
299 /* FIXME: Crude hack */
300 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
301 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
303 /* Initialize shared data segments. */
304 if( bInitializeSharedMemory )
308 TRACE( "Initializing shared memory\n" );
310 /* Set all lobbies to be "empty" */
311 for( i=0; i < numSupportedLobbies; i++ )
313 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
316 /* Set all sessions to be "empty" */
317 for( i=0; i < numSupportedSessions; i++ )
319 sessionData[i].dwSize = 0;
322 /* Zero out the dynmaic area */
323 ZeroMemory( lpMemArea, dwDynamicSharedSize );
325 /* Just for fun sync the whole data area */
326 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
329 DPLAYX_ReleaseSemaphore();
331 /* Everything was created correctly. Signal the lobby client that
332 * we started up correctly
334 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
339 bSuccess = SetEvent( hInformOnStart );
340 TRACE( "Signalling lobby app start event %u %s\n",
341 hInformOnStart, bSuccess ? "succeed" : "failed" );
343 /* Close out handle */
344 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
350 /***************************************************************************
351 * Called to destroy all global data. This will only be used on the
352 * unloading of the dll
353 ***************************************************************************/
354 BOOL DPLAYX_DestructData(void)
356 HANDLE hInformOnDeath;
358 TRACE( "DPLAYX dll unloaded - destruct called\n" );
360 /* If required, inform that this app is dying */
361 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
366 bSuccess = SetEvent( hInformOnDeath );
367 TRACE( "Signalling lobby app death event %u %s\n",
368 hInformOnDeath, bSuccess ? "succeed" : "failed" );
370 /* Close out handle */
371 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
374 /* DO CLEAN UP (LAST) */
376 /* Delete the semaphore */
377 CloseHandle( hDplayxSema );
379 /* Delete shared memory file mapping */
380 UnmapViewOfFile( lpSharedStaticData );
381 CloseHandle( hDplayxSharedMem );
387 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
389 ZeroMemory( lpData, sizeof( *lpData ) );
392 /* NOTE: This must be called with the semaphore aquired.
393 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
394 * is only valid if TRUE is returned.
396 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
404 dwAppID = GetCurrentProcessId();
405 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
408 for( i=0; i < numSupportedLobbies; i++ )
410 if( lobbyData[ i ].dwAppID == dwAppID )
412 /* This process is lobbied */
413 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
414 *lplpDplData = &lobbyData[ i ];
422 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
423 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
427 /* 0 is the marker for unused application data slots */
433 DPLAYX_AquireSemaphore();
435 /* Find an empty space in the list and insert the data */
436 for( i=0; i < numSupportedLobbies; i++ )
438 if( lobbyData[ i ].dwAppID == 0 )
440 /* This process is now lobbied */
441 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
442 i, dwAppID, GetCurrentProcessId() );
444 lobbyData[ i ].dwAppID = dwAppID;
445 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
447 /* FIXME: Where is the best place for this? In interface or here? */
448 lobbyData[ i ].hInformOnAppStart = 0;
449 lobbyData[ i ].hInformOnAppDeath = 0;
450 lobbyData[ i ].hInformOnSettingRead = 0;
452 DPLAYX_ReleaseSemaphore();
457 ERR( "No empty lobbies\n" );
459 DPLAYX_ReleaseSemaphore();
463 /* I'm not sure when I'm going to need this, but here it is */
464 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
468 DPLAYX_AquireSemaphore();
470 /* Find an empty space in the list and insert the data */
471 for( i=0; i < numSupportedLobbies; i++ )
473 if( lobbyData[ i ].dwAppID == dwAppID )
475 /* FIXME: Should free up anything unused. Tisk tisk :0 */
476 /* Mark this entry unused */
477 TRACE( "Marking lobbyData[%u] unused\n", i );
478 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
480 DPLAYX_ReleaseSemaphore();
485 DPLAYX_ReleaseSemaphore();
486 ERR( "Unable to find global entry for application\n" );
490 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
491 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
493 LPDPLAYX_LOBBYDATA lpLData;
495 /* Need to explictly give lobby application. Can't set for yourself */
501 DPLAYX_AquireSemaphore();
503 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
505 DPLAYX_ReleaseSemaphore();
509 lpLData->hInformOnAppStart = hStart;
510 lpLData->hInformOnAppDeath = hDeath;
511 lpLData->hInformOnSettingRead = hConnRead;
513 DPLAYX_ReleaseSemaphore();
518 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
520 LPHANDLE lphConnRead,
521 BOOL bClearSetHandles )
523 LPDPLAYX_LOBBYDATA lpLData;
525 DPLAYX_AquireSemaphore();
527 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
529 DPLAYX_ReleaseSemaphore();
533 if( lphStart != NULL )
535 if( lpLData->hInformOnAppStart == 0 )
537 DPLAYX_ReleaseSemaphore();
541 *lphStart = lpLData->hInformOnAppStart;
543 if( bClearSetHandles )
545 CloseHandle( lpLData->hInformOnAppStart );
546 lpLData->hInformOnAppStart = 0;
550 if( lphDeath != NULL )
552 if( lpLData->hInformOnAppDeath == 0 )
554 DPLAYX_ReleaseSemaphore();
558 *lphDeath = lpLData->hInformOnAppDeath;
560 if( bClearSetHandles )
562 CloseHandle( lpLData->hInformOnAppDeath );
563 lpLData->hInformOnAppDeath = 0;
567 if( lphConnRead != NULL )
569 if( lpLData->hInformOnSettingRead == 0 )
571 DPLAYX_ReleaseSemaphore();
575 *lphConnRead = lpLData->hInformOnSettingRead;
577 if( bClearSetHandles )
579 CloseHandle( lpLData->hInformOnSettingRead );
580 lpLData->hInformOnSettingRead = 0;
584 DPLAYX_ReleaseSemaphore();
590 HRESULT DPLAYX_GetConnectionSettingsA
593 LPDWORD lpdwDataSize )
595 LPDPLAYX_LOBBYDATA lpDplData;
596 DWORD dwRequiredDataSize = 0;
597 HANDLE hInformOnSettingRead;
599 DPLAYX_AquireSemaphore();
601 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
603 DPLAYX_ReleaseSemaphore();
605 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
606 return DPERR_NOTLOBBIED;
609 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
611 /* Do they want to know the required buffer size or is the provided buffer
614 if ( ( lpData == NULL ) ||
615 ( *lpdwDataSize < dwRequiredDataSize )
618 DPLAYX_ReleaseSemaphore();
620 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
622 return DPERR_BUFFERTOOSMALL;
625 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
627 DPLAYX_ReleaseSemaphore();
629 /* They have gotten the information - signal the event if required */
630 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
635 bSuccess = SetEvent( hInformOnSettingRead );
636 TRACE( "Signalling setting read event %u %s\n",
637 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
639 /* Close out handle */
640 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
646 /* Assumption: Enough contiguous space was allocated at dest */
647 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
649 BYTE* lpStartOfFreeSpace;
651 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
653 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
655 /* Copy the LPDPSESSIONDESC2 structure if it exists */
656 if( src->lpSessionDesc )
658 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
659 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
660 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
662 /* Session names may or may not exist */
663 if( src->lpSessionDesc->u1.lpszSessionNameA )
665 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
666 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
667 lpStartOfFreeSpace +=
668 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
671 if( src->lpSessionDesc->u2.lpszPasswordA )
673 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
674 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
675 lpStartOfFreeSpace +=
676 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
680 /* DPNAME structure is optional */
681 if( src->lpPlayerName )
683 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
684 lpStartOfFreeSpace += sizeof( DPNAME );
685 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
687 if( src->lpPlayerName->u1.lpszShortNameA )
689 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
690 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
691 lpStartOfFreeSpace +=
692 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
695 if( src->lpPlayerName->u2.lpszLongNameA )
697 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
698 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
699 lpStartOfFreeSpace +=
700 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
705 /* Copy address if it exists */
708 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
709 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
710 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
714 HRESULT DPLAYX_GetConnectionSettingsW
717 LPDWORD lpdwDataSize )
719 LPDPLAYX_LOBBYDATA lpDplData;
720 DWORD dwRequiredDataSize = 0;
721 HANDLE hInformOnSettingRead;
723 DPLAYX_AquireSemaphore();
725 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
727 DPLAYX_ReleaseSemaphore();
728 return DPERR_NOTLOBBIED;
731 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
733 /* Do they want to know the required buffer size or is the provided buffer
736 if ( ( lpData == NULL ) ||
737 ( *lpdwDataSize < dwRequiredDataSize )
740 DPLAYX_ReleaseSemaphore();
742 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
744 return DPERR_BUFFERTOOSMALL;
747 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
749 DPLAYX_ReleaseSemaphore();
751 /* They have gotten the information - signal the event if required */
752 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
757 bSuccess = SetEvent( hInformOnSettingRead );
758 TRACE( "Signalling setting read event %u %s\n",
759 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
761 /* Close out handle */
762 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
768 /* Assumption: Enough contiguous space was allocated at dest */
769 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
771 BYTE* lpStartOfFreeSpace;
773 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
775 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
777 /* Copy the LPDPSESSIONDESC2 structure if it exists */
778 if( src->lpSessionDesc )
780 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
781 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
782 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
784 /* Session names may or may not exist */
785 if( src->lpSessionDesc->u1.lpszSessionName )
787 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
788 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
789 lpStartOfFreeSpace += sizeof(WCHAR) *
790 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
793 if( src->lpSessionDesc->u2.lpszPassword )
795 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
796 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
797 lpStartOfFreeSpace += sizeof(WCHAR) *
798 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
802 /* DPNAME structure is optional */
803 if( src->lpPlayerName )
805 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
806 lpStartOfFreeSpace += sizeof( DPNAME );
807 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
809 if( src->lpPlayerName->u1.lpszShortName )
811 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
812 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
813 lpStartOfFreeSpace += sizeof(WCHAR) *
814 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
817 if( src->lpPlayerName->u2.lpszLongName )
819 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
820 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
821 lpStartOfFreeSpace += sizeof(WCHAR) *
822 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
827 /* Copy address if it exists */
830 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
831 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
832 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
837 /* Store the structure into the shared data structre. Ensure that allocs for
838 * variable length strings come from the shared data structure.
839 * FIXME: We need to free information as well
841 HRESULT DPLAYX_SetConnectionSettingsA
844 LPDPLCONNECTION lpConn )
846 LPDPLAYX_LOBBYDATA lpDplData;
848 /* Paramater check */
849 if( dwFlags || !lpConn )
851 ERR("invalid parameters.\n");
852 return DPERR_INVALIDPARAMS;
855 /* Store information */
856 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
858 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
859 lpConn->dwSize, sizeof( DPLCONNECTION ) );
861 return DPERR_INVALIDPARAMS;
864 DPLAYX_AquireSemaphore();
866 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
868 DPLAYX_ReleaseSemaphore();
870 return DPERR_NOTLOBBIED;
873 if( (!lpConn->lpSessionDesc ) ||
874 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
877 DPLAYX_ReleaseSemaphore();
879 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
880 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
882 return DPERR_INVALIDPARAMS;
885 /* Free the existing memory */
886 DPLAYX_PrivHeapFree( lpDplData->lpConn );
888 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
889 DPLAYX_SizeOfLobbyDataA( lpConn ) );
891 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
894 DPLAYX_ReleaseSemaphore();
896 /* FIXME: Send a message - I think */
901 /* Store the structure into the shared data structre. Ensure that allocs for
902 * variable length strings come from the shared data structure.
903 * FIXME: We need to free information as well
905 HRESULT DPLAYX_SetConnectionSettingsW
908 LPDPLCONNECTION lpConn )
910 LPDPLAYX_LOBBYDATA lpDplData;
912 /* Paramater check */
913 if( dwFlags || !lpConn )
915 ERR("invalid parameters.\n");
916 return DPERR_INVALIDPARAMS;
919 /* Store information */
920 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
922 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
923 lpConn->dwSize, sizeof( DPLCONNECTION ) );
925 return DPERR_INVALIDPARAMS;
928 DPLAYX_AquireSemaphore();
930 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
932 DPLAYX_ReleaseSemaphore();
934 return DPERR_NOTLOBBIED;
937 /* Free the existing memory */
938 DPLAYX_PrivHeapFree( lpDplData->lpConn );
940 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
941 DPLAYX_SizeOfLobbyDataW( lpConn ) );
943 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
946 DPLAYX_ReleaseSemaphore();
948 /* FIXME: Send a message - I think */
953 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
955 DWORD dwTotalSize = sizeof( DPLCONNECTION );
957 /* Just a safety check */
960 ERR( "lpConn is NULL\n" );
964 if( lpConn->lpSessionDesc != NULL )
966 dwTotalSize += sizeof( DPSESSIONDESC2 );
968 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
970 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
973 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
975 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
979 if( lpConn->lpPlayerName != NULL )
981 dwTotalSize += sizeof( DPNAME );
983 if( lpConn->lpPlayerName->u1.lpszShortNameA )
985 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
988 if( lpConn->lpPlayerName->u2.lpszLongNameA )
990 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
995 dwTotalSize += lpConn->dwAddressSize;
1000 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
1002 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1004 /* Just a safety check */
1005 if( lpConn == NULL )
1007 ERR( "lpConn is NULL\n" );
1011 if( lpConn->lpSessionDesc != NULL )
1013 dwTotalSize += sizeof( DPSESSIONDESC2 );
1015 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1017 dwTotalSize += sizeof( WCHAR ) *
1018 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1021 if( lpConn->lpSessionDesc->u2.lpszPassword )
1023 dwTotalSize += sizeof( WCHAR ) *
1024 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1028 if( lpConn->lpPlayerName != NULL )
1030 dwTotalSize += sizeof( DPNAME );
1032 if( lpConn->lpPlayerName->u1.lpszShortName )
1034 dwTotalSize += sizeof( WCHAR ) *
1035 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1038 if( lpConn->lpPlayerName->u2.lpszLongName )
1040 dwTotalSize += sizeof( WCHAR ) *
1041 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1046 dwTotalSize += lpConn->dwAddressSize;
1053 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1055 LPDPSESSIONDESC2 lpSessionDest =
1056 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1057 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1058 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1060 return lpSessionDest;
1063 /* Copy an ANSI session desc structure to the given buffer */
1064 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1065 LPCDPSESSIONDESC2 lpSessionSrc )
1067 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1069 if( lpSessionSrc->u1.lpszSessionNameA )
1071 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1072 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1073 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1075 if( lpSessionSrc->u2.lpszPasswordA )
1077 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1078 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1079 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1085 /* Start the index at 0. index will be updated to equal that which should
1086 be passed back into this function for the next element */
1087 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1089 for( ; (*index) < numSupportedSessions; (*index)++ )
1091 if( sessionData[(*index)].dwSize != 0 )
1093 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1097 /* No more sessions */
1101 /* Start the index at 0. index will be updated to equal that which should
1102 be passed back into this function for the next element */
1103 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1105 for( ; (*index) < numSupportedSessions; (*index)++ )
1107 if( sessionData[(*index)].dwSize != 0 )
1109 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1113 /* No more sessions */
1117 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1121 /* FIXME: Is this an error if it exists already? */
1123 /* Crude/wrong implementation for now. Just always add to first empty spot */
1124 for( i=0; i < numSupportedSessions; i++ )
1126 /* Is this one empty? */
1127 if( sessionData[i].dwSize == 0 )
1129 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1136 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1138 LPDPLAYX_LOBBYDATA lpLobbyData;
1140 DPLAYX_AquireSemaphore();
1142 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1144 DPLAYX_ReleaseSemaphore();
1148 lpLobbyData->bWaitForConnectionSettings = bWait;
1150 DPLAYX_ReleaseSemaphore();
1155 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1158 BOOL bFound = FALSE;
1160 DPLAYX_AquireSemaphore();
1162 for( i=0; i < numSupportedLobbies; i++ )
1164 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1165 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1173 DPLAYX_ReleaseSemaphore();
1178 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1180 LPDPLAYX_LOBBYDATA lpLobbyData;
1182 DPLAYX_AquireSemaphore();
1184 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1186 DPLAYX_ReleaseSemaphore();
1190 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1192 DPLAYX_ReleaseSemaphore();
1197 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1198 with the correct string printed in the case where the HRESULT is not
1199 known. You'll just get the last hr passed in printed. This can change
1200 over time if this method is used alot :) */
1201 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1203 static char szTempStr[12];
1209 case DPERR_ALREADYINITIALIZED:
1210 return "DPERR_ALREADYINITIALIZED";
1211 case DPERR_ACCESSDENIED:
1212 return "DPERR_ACCESSDENIED";
1213 case DPERR_ACTIVEPLAYERS:
1214 return "DPERR_ACTIVEPLAYERS";
1215 case DPERR_BUFFERTOOSMALL:
1216 return "DPERR_BUFFERTOOSMALL";
1217 case DPERR_CANTADDPLAYER:
1218 return "DPERR_CANTADDPLAYER";
1219 case DPERR_CANTCREATEGROUP:
1220 return "DPERR_CANTCREATEGROUP";
1221 case DPERR_CANTCREATEPLAYER:
1222 return "DPERR_CANTCREATEPLAYER";
1223 case DPERR_CANTCREATESESSION:
1224 return "DPERR_CANTCREATESESSION";
1225 case DPERR_CAPSNOTAVAILABLEYET:
1226 return "DPERR_CAPSNOTAVAILABLEYET";
1227 case DPERR_EXCEPTION:
1228 return "DPERR_EXCEPTION";
1230 return "DPERR_GENERIC";
1231 case DPERR_INVALIDFLAGS:
1232 return "DPERR_INVALIDFLAGS";
1233 case DPERR_INVALIDOBJECT:
1234 return "DPERR_INVALIDOBJECT";
1235 case DPERR_INVALIDPARAMS:
1236 return "DPERR_INVALIDPARAMS";
1237 case DPERR_INVALIDPLAYER:
1238 return "DPERR_INVALIDPLAYER";
1239 case DPERR_INVALIDGROUP:
1240 return "DPERR_INVALIDGROUP";
1242 return "DPERR_NOCAPS";
1243 case DPERR_NOCONNECTION:
1244 return "DPERR_NOCONNECTION";
1245 case DPERR_OUTOFMEMORY:
1246 return "DPERR_OUTOFMEMORY";
1247 case DPERR_NOMESSAGES:
1248 return "DPERR_NOMESSAGES";
1249 case DPERR_NONAMESERVERFOUND:
1250 return "DPERR_NONAMESERVERFOUND";
1251 case DPERR_NOPLAYERS:
1252 return "DPERR_NOPLAYERS";
1253 case DPERR_NOSESSIONS:
1254 return "DPERR_NOSESSIONS";
1256 return "DPERR_PENDING";
1257 case DPERR_SENDTOOBIG:
1258 return "DPERR_SENDTOOBIG";
1260 return "DPERR_TIMEOUT";
1261 case DPERR_UNAVAILABLE:
1262 return "DPERR_UNAVAILABLE";
1263 case DPERR_UNSUPPORTED:
1264 return "DPERR_UNSUPPORTED";
1266 return "DPERR_BUSY";
1267 case DPERR_USERCANCEL:
1268 return "DPERR_USERCANCEL";
1269 case DPERR_NOINTERFACE:
1270 return "DPERR_NOINTERFACE";
1271 case DPERR_CANNOTCREATESERVER:
1272 return "DPERR_CANNOTCREATESERVER";
1273 case DPERR_PLAYERLOST:
1274 return "DPERR_PLAYERLOST";
1275 case DPERR_SESSIONLOST:
1276 return "DPERR_SESSIONLOST";
1277 case DPERR_UNINITIALIZED:
1278 return "DPERR_UNINITIALIZED";
1279 case DPERR_NONEWPLAYERS:
1280 return "DPERR_NONEWPLAYERS";
1281 case DPERR_INVALIDPASSWORD:
1282 return "DPERR_INVALIDPASSWORD";
1283 case DPERR_CONNECTING:
1284 return "DPERR_CONNECTING";
1285 case DPERR_CONNECTIONLOST:
1286 return "DPERR_CONNECTIONLOST";
1287 case DPERR_UNKNOWNMESSAGE:
1288 return "DPERR_UNKNOWNMESSAGE";
1289 case DPERR_CANCELFAILED:
1290 return "DPERR_CANCELFAILED";
1291 case DPERR_INVALIDPRIORITY:
1292 return "DPERR_INVALIDPRIORITY";
1293 case DPERR_NOTHANDLED:
1294 return "DPERR_NOTHANDLED";
1295 case DPERR_CANCELLED:
1296 return "DPERR_CANCELLED";
1298 return "DPERR_ABORTED";
1299 case DPERR_BUFFERTOOLARGE:
1300 return "DPERR_BUFFERTOOLARGE";
1301 case DPERR_CANTCREATEPROCESS:
1302 return "DPERR_CANTCREATEPROCESS";
1303 case DPERR_APPNOTSTARTED:
1304 return "DPERR_APPNOTSTARTED";
1305 case DPERR_INVALIDINTERFACE:
1306 return "DPERR_INVALIDINTERFACE";
1307 case DPERR_NOSERVICEPROVIDER:
1308 return "DPERR_NOSERVICEPROVIDER";
1309 case DPERR_UNKNOWNAPPLICATION:
1310 return "DPERR_UNKNOWNAPPLICATION";
1311 case DPERR_NOTLOBBIED:
1312 return "DPERR_NOTLOBBIED";
1313 case DPERR_SERVICEPROVIDERLOADED:
1314 return "DPERR_SERVICEPROVIDERLOADED";
1315 case DPERR_ALREADYREGISTERED:
1316 return "DPERR_ALREADYREGISTERED";
1317 case DPERR_NOTREGISTERED:
1318 return "DPERR_NOTREGISTERED";
1319 case DPERR_AUTHENTICATIONFAILED:
1320 return "DPERR_AUTHENTICATIONFAILED";
1321 case DPERR_CANTLOADSSPI:
1322 return "DPERR_CANTLOADSSPI";
1323 case DPERR_ENCRYPTIONFAILED:
1324 return "DPERR_ENCRYPTIONFAILED";
1325 case DPERR_SIGNFAILED:
1326 return "DPERR_SIGNFAILED";
1327 case DPERR_CANTLOADSECURITYPACKAGE:
1328 return "DPERR_CANTLOADSECURITYPACKAGE";
1329 case DPERR_ENCRYPTIONNOTSUPPORTED:
1330 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1331 case DPERR_CANTLOADCAPI:
1332 return "DPERR_CANTLOADCAPI";
1333 case DPERR_NOTLOGGEDIN:
1334 return "DPERR_NOTLOGGEDIN";
1335 case DPERR_LOGONDENIED:
1336 return "DPERR_LOGONDENIED";
1338 /* For errors not in the list, return HRESULT as a string
1339 This part is not thread safe */
1340 WARN( "Unknown error 0x%08lx\n", hr );
1341 wsprintfA( szTempStr, "0x%08lx", hr );