- Create IDirectSound and IDirectSound8 objects using the
[wine/gsoc_dplay.git] / dlls / dplayx / dplayx_global.c
blobba37e9169a285977265e1f1cd03c88e536b3d531
1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTES:
22 * o Implementation of all things which are associated with dplay on
23 * the computer - ie shared resources and such. Methods in this
24 * compilation unit should not call anything out side this unit
25 * excepting base windows services and an interface to start the
26 * messaging thread.
27 * o Methods that begin with DPLAYX_ are used for dealing with
28 * dplayx.dll data which is accessible from all processes.
32 #include <stdarg.h>
33 #include <string.h>
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41 #include "wine/unicode.h"
43 #include "wingdi.h"
44 #include "winuser.h"
46 #include "dplayx_global.h"
47 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
49 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
51 /* FIXME: Need to do all that fun other dll referencing type of stuff */
53 /* Static data for all processes */
54 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
55 static HANDLE hDplayxSema;
57 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
58 static HANDLE hDplayxSharedMem;
60 static LPVOID lpSharedStaticData = NULL;
63 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
64 WaitForSingleObject( hDplayxSema, INFINITE );\
65 TRACE( "Through wait\n" )
67 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
68 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
71 /* HACK for simple global data right now */
72 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
73 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
74 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
77 /* FIXME: Is there no easier way? */
79 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
80 * Each block has 4 bytes which are 0 unless used */
81 #define dwBlockSize 512
82 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
84 typedef struct
86 DWORD used;
87 DWORD data[dwBlockSize-sizeof(DWORD)];
88 } DPLAYX_MEM_SLICE;
90 static DPLAYX_MEM_SLICE* lpMemArea;
92 void DPLAYX_PrivHeapFree( LPVOID addr );
93 void DPLAYX_PrivHeapFree( LPVOID addr )
95 LPVOID lpAddrStart;
96 DWORD dwBlockUsed;
98 /* Handle getting passed a NULL */
99 if( addr == NULL )
101 return;
104 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
105 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
107 lpMemArea[ dwBlockUsed ].used = 0;
110 /* FIXME: This should be static, but is being used for a hack right now */
111 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
112 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
114 LPVOID lpvArea = NULL;
115 UINT uBlockUsed;
117 if( size > (dwBlockSize - sizeof(DWORD)) )
119 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
120 size = dwBlockSize - sizeof(DWORD);
123 /* Find blank area */
124 uBlockUsed = 0;
125 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
127 if( uBlockUsed <= dwMaxBlock )
129 /* Set the area used */
130 lpMemArea[ uBlockUsed ].used = 1;
131 lpvArea = &(lpMemArea[ uBlockUsed ].data);
133 else
135 ERR( "No free block found\n" );
136 return NULL;
139 if( flags & HEAP_ZERO_MEMORY )
141 ZeroMemory( lpvArea, size );
144 return lpvArea;
147 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
148 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
150 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
151 if(p) {
152 strcpy( p, str );
154 return p;
157 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
158 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
160 INT len = strlenW(str) + 1;
161 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
162 if(p) {
163 strcpyW( p, str );
165 return p;
169 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
170 typedef struct tagDPLAYX_LOBBYDATA
172 /* Points to lpConn + block of contiguous extra memory for dynamic parts
173 * of the struct directly following
175 LPDPLCONNECTION lpConn;
177 /* Information for dplobby interfaces */
178 DWORD dwAppID;
179 DWORD dwAppLaunchedFromID;
181 /* Should this lobby app send messages to creator at important life
182 * stages
184 HANDLE hInformOnAppStart;
185 HANDLE hInformOnAppDeath;
186 HANDLE hInformOnSettingRead;
188 /* Sundries */
189 BOOL bWaitForConnectionSettings;
190 DWORD dwLobbyMsgThreadId;
193 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
195 static DPLAYX_LOBBYDATA* lobbyData = NULL;
196 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
198 static DPSESSIONDESC2* sessionData = NULL;
199 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
201 /* Function prototypes */
202 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
203 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
204 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
205 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
206 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
207 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
208 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
209 LPCDPSESSIONDESC2 lpSessionSrc );
213 /***************************************************************************
214 * Called to initialize the global data. This will only be used on the
215 * loading of the dll
216 ***************************************************************************/
217 BOOL DPLAYX_ConstructData(void)
219 SECURITY_ATTRIBUTES s_attrib;
220 BOOL bInitializeSharedMemory = FALSE;
221 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
222 HANDLE hInformOnStart;
224 TRACE( "DPLAYX dll loaded - construct called\n" );
226 /* Create a semaphore to block access to DPLAYX global data structs */
228 s_attrib.bInheritHandle = TRUE;
229 s_attrib.lpSecurityDescriptor = NULL;
230 s_attrib.nLength = sizeof(s_attrib);
232 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
234 /* First instance creates the semaphore. Others just use it */
235 if( GetLastError() == ERROR_SUCCESS )
237 TRACE( "Semaphore %p created\n", hDplayxSema );
239 /* The semaphore creator will also build the shared memory */
240 bInitializeSharedMemory = TRUE;
242 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
244 TRACE( "Found semaphore handle %p\n", hDplayxSema );
246 else
248 ERR( ": semaphore error %ld\n", GetLastError() );
249 return FALSE;
252 SetLastError( ERROR_SUCCESS );
254 DPLAYX_AquireSemaphore();
256 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
257 &s_attrib,
258 PAGE_READWRITE | SEC_COMMIT,
260 dwTotalSharedSize,
261 lpszDplayxFileMapping );
263 if( GetLastError() == ERROR_SUCCESS )
265 TRACE( "File mapped %p created\n", hDplayxSharedMem );
267 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
269 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
271 else
273 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
274 return FALSE;
277 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
278 FILE_MAP_WRITE,
279 0, 0, 0, lpDesiredMemoryMapStart );
281 if( lpSharedStaticData == NULL )
283 ERR( ": unable to map static data into process memory space (%ld)\n",
284 GetLastError() );
285 return FALSE;
287 else
289 if( lpDesiredMemoryMapStart == lpSharedStaticData )
291 TRACE( "File mapped to %p\n", lpSharedStaticData );
293 else
295 /* Presently the shared data structures use pointers. If the
296 * files are no mapped into the same area, the pointers will no
297 * longer make any sense :(
298 * FIXME: In the future make the shared data structures have some
299 * sort of fixup to make them independent between data spaces.
300 * This will also require a rework of the session data stuff.
302 ERR( "File mapped to %p (not %p). Expect failure\n",
303 lpSharedStaticData, lpDesiredMemoryMapStart );
307 /* Dynamic area starts just after the static area */
308 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
310 /* FIXME: Crude hack */
311 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
312 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
314 /* Initialize shared data segments. */
315 if( bInitializeSharedMemory )
317 UINT i;
319 TRACE( "Initializing shared memory\n" );
321 /* Set all lobbies to be "empty" */
322 for( i=0; i < numSupportedLobbies; i++ )
324 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
327 /* Set all sessions to be "empty" */
328 for( i=0; i < numSupportedSessions; i++ )
330 sessionData[i].dwSize = 0;
333 /* Zero out the dynmaic area */
334 ZeroMemory( lpMemArea, dwDynamicSharedSize );
336 /* Just for fun sync the whole data area */
337 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
340 DPLAYX_ReleaseSemaphore();
342 /* Everything was created correctly. Signal the lobby client that
343 * we started up correctly
345 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
346 hInformOnStart
349 BOOL bSuccess;
350 bSuccess = SetEvent( hInformOnStart );
351 TRACE( "Signalling lobby app start event %p %s\n",
352 hInformOnStart, bSuccess ? "succeed" : "failed" );
354 /* Close out handle */
355 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
358 return TRUE;
361 /***************************************************************************
362 * Called to destroy all global data. This will only be used on the
363 * unloading of the dll
364 ***************************************************************************/
365 BOOL DPLAYX_DestructData(void)
367 HANDLE hInformOnDeath;
369 TRACE( "DPLAYX dll unloaded - destruct called\n" );
371 /* If required, inform that this app is dying */
372 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
373 hInformOnDeath
376 BOOL bSuccess;
377 bSuccess = SetEvent( hInformOnDeath );
378 TRACE( "Signalling lobby app death event %p %s\n",
379 hInformOnDeath, bSuccess ? "succeed" : "failed" );
381 /* Close out handle */
382 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
385 /* DO CLEAN UP (LAST) */
387 /* Delete the semaphore */
388 CloseHandle( hDplayxSema );
390 /* Delete shared memory file mapping */
391 UnmapViewOfFile( lpSharedStaticData );
392 CloseHandle( hDplayxSharedMem );
394 return FALSE;
398 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
400 ZeroMemory( lpData, sizeof( *lpData ) );
403 /* NOTE: This must be called with the semaphore aquired.
404 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
405 * is only valid if TRUE is returned.
407 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
409 UINT i;
411 *lplpDplData = NULL;
413 if( dwAppID == 0 )
415 dwAppID = GetCurrentProcessId();
416 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
419 for( i=0; i < numSupportedLobbies; i++ )
421 if( lobbyData[ i ].dwAppID == dwAppID )
423 /* This process is lobbied */
424 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
425 *lplpDplData = &lobbyData[ i ];
426 return TRUE;
430 return FALSE;
433 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
434 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
436 UINT i;
438 /* 0 is the marker for unused application data slots */
439 if( dwAppID == 0 )
441 return FALSE;
444 DPLAYX_AquireSemaphore();
446 /* Find an empty space in the list and insert the data */
447 for( i=0; i < numSupportedLobbies; i++ )
449 if( lobbyData[ i ].dwAppID == 0 )
451 /* This process is now lobbied */
452 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
453 i, dwAppID, GetCurrentProcessId() );
455 lobbyData[ i ].dwAppID = dwAppID;
456 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
458 /* FIXME: Where is the best place for this? In interface or here? */
459 lobbyData[ i ].hInformOnAppStart = 0;
460 lobbyData[ i ].hInformOnAppDeath = 0;
461 lobbyData[ i ].hInformOnSettingRead = 0;
463 DPLAYX_ReleaseSemaphore();
464 return TRUE;
468 ERR( "No empty lobbies\n" );
470 DPLAYX_ReleaseSemaphore();
471 return FALSE;
474 /* I'm not sure when I'm going to need this, but here it is */
475 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
477 UINT i;
479 DPLAYX_AquireSemaphore();
481 /* Find an empty space in the list and insert the data */
482 for( i=0; i < numSupportedLobbies; i++ )
484 if( lobbyData[ i ].dwAppID == dwAppID )
486 /* FIXME: Should free up anything unused. Tisk tisk :0 */
487 /* Mark this entry unused */
488 TRACE( "Marking lobbyData[%u] unused\n", i );
489 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
491 DPLAYX_ReleaseSemaphore();
492 return TRUE;
496 DPLAYX_ReleaseSemaphore();
497 ERR( "Unable to find global entry for application\n" );
498 return FALSE;
501 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
502 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
504 LPDPLAYX_LOBBYDATA lpLData;
506 /* Need to explictly give lobby application. Can't set for yourself */
507 if( dwAppID == 0 )
509 return FALSE;
512 DPLAYX_AquireSemaphore();
514 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
516 DPLAYX_ReleaseSemaphore();
517 return FALSE;
520 lpLData->hInformOnAppStart = hStart;
521 lpLData->hInformOnAppDeath = hDeath;
522 lpLData->hInformOnSettingRead = hConnRead;
524 DPLAYX_ReleaseSemaphore();
526 return TRUE;
529 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
530 LPHANDLE lphDeath,
531 LPHANDLE lphConnRead,
532 BOOL bClearSetHandles )
534 LPDPLAYX_LOBBYDATA lpLData;
536 DPLAYX_AquireSemaphore();
538 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
540 DPLAYX_ReleaseSemaphore();
541 return FALSE;
544 if( lphStart != NULL )
546 if( lpLData->hInformOnAppStart == 0 )
548 DPLAYX_ReleaseSemaphore();
549 return FALSE;
552 *lphStart = lpLData->hInformOnAppStart;
554 if( bClearSetHandles )
556 CloseHandle( lpLData->hInformOnAppStart );
557 lpLData->hInformOnAppStart = 0;
561 if( lphDeath != NULL )
563 if( lpLData->hInformOnAppDeath == 0 )
565 DPLAYX_ReleaseSemaphore();
566 return FALSE;
569 *lphDeath = lpLData->hInformOnAppDeath;
571 if( bClearSetHandles )
573 CloseHandle( lpLData->hInformOnAppDeath );
574 lpLData->hInformOnAppDeath = 0;
578 if( lphConnRead != NULL )
580 if( lpLData->hInformOnSettingRead == 0 )
582 DPLAYX_ReleaseSemaphore();
583 return FALSE;
586 *lphConnRead = lpLData->hInformOnSettingRead;
588 if( bClearSetHandles )
590 CloseHandle( lpLData->hInformOnSettingRead );
591 lpLData->hInformOnSettingRead = 0;
595 DPLAYX_ReleaseSemaphore();
597 return TRUE;
601 HRESULT DPLAYX_GetConnectionSettingsA
602 ( DWORD dwAppID,
603 LPVOID lpData,
604 LPDWORD lpdwDataSize )
606 LPDPLAYX_LOBBYDATA lpDplData;
607 DWORD dwRequiredDataSize = 0;
608 HANDLE hInformOnSettingRead;
610 DPLAYX_AquireSemaphore();
612 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
614 DPLAYX_ReleaseSemaphore();
616 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
617 return DPERR_NOTLOBBIED;
620 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
622 /* Do they want to know the required buffer size or is the provided buffer
623 * big enough?
625 if ( ( lpData == NULL ) ||
626 ( *lpdwDataSize < dwRequiredDataSize )
629 DPLAYX_ReleaseSemaphore();
631 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
633 return DPERR_BUFFERTOOSMALL;
636 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
638 DPLAYX_ReleaseSemaphore();
640 /* They have gotten the information - signal the event if required */
641 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
642 hInformOnSettingRead
645 BOOL bSuccess;
646 bSuccess = SetEvent( hInformOnSettingRead );
647 TRACE( "Signalling setting read event %p %s\n",
648 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
650 /* Close out handle */
651 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
654 return DP_OK;
657 /* Assumption: Enough contiguous space was allocated at dest */
658 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
660 BYTE* lpStartOfFreeSpace;
662 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
664 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
666 /* Copy the LPDPSESSIONDESC2 structure if it exists */
667 if( src->lpSessionDesc )
669 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
670 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
671 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
673 /* Session names may or may not exist */
674 if( src->lpSessionDesc->u1.lpszSessionNameA )
676 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
677 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
678 lpStartOfFreeSpace +=
679 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
682 if( src->lpSessionDesc->u2.lpszPasswordA )
684 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
685 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
686 lpStartOfFreeSpace +=
687 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
691 /* DPNAME structure is optional */
692 if( src->lpPlayerName )
694 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
695 lpStartOfFreeSpace += sizeof( DPNAME );
696 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
698 if( src->lpPlayerName->u1.lpszShortNameA )
700 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
701 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
702 lpStartOfFreeSpace +=
703 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
706 if( src->lpPlayerName->u2.lpszLongNameA )
708 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
709 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
710 lpStartOfFreeSpace +=
711 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
716 /* Copy address if it exists */
717 if( src->lpAddress )
719 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
720 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
721 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
725 HRESULT DPLAYX_GetConnectionSettingsW
726 ( DWORD dwAppID,
727 LPVOID lpData,
728 LPDWORD lpdwDataSize )
730 LPDPLAYX_LOBBYDATA lpDplData;
731 DWORD dwRequiredDataSize = 0;
732 HANDLE hInformOnSettingRead;
734 DPLAYX_AquireSemaphore();
736 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
738 DPLAYX_ReleaseSemaphore();
739 return DPERR_NOTLOBBIED;
742 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
744 /* Do they want to know the required buffer size or is the provided buffer
745 * big enough?
747 if ( ( lpData == NULL ) ||
748 ( *lpdwDataSize < dwRequiredDataSize )
751 DPLAYX_ReleaseSemaphore();
753 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
755 return DPERR_BUFFERTOOSMALL;
758 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
760 DPLAYX_ReleaseSemaphore();
762 /* They have gotten the information - signal the event if required */
763 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
764 hInformOnSettingRead
767 BOOL bSuccess;
768 bSuccess = SetEvent( hInformOnSettingRead );
769 TRACE( "Signalling setting read event %p %s\n",
770 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
772 /* Close out handle */
773 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
776 return DP_OK;
779 /* Assumption: Enough contiguous space was allocated at dest */
780 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
782 BYTE* lpStartOfFreeSpace;
784 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
786 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
788 /* Copy the LPDPSESSIONDESC2 structure if it exists */
789 if( src->lpSessionDesc )
791 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
792 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
793 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
795 /* Session names may or may not exist */
796 if( src->lpSessionDesc->u1.lpszSessionName )
798 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
799 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
800 lpStartOfFreeSpace += sizeof(WCHAR) *
801 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
804 if( src->lpSessionDesc->u2.lpszPassword )
806 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
807 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
808 lpStartOfFreeSpace += sizeof(WCHAR) *
809 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
813 /* DPNAME structure is optional */
814 if( src->lpPlayerName )
816 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
817 lpStartOfFreeSpace += sizeof( DPNAME );
818 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
820 if( src->lpPlayerName->u1.lpszShortName )
822 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
823 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
824 lpStartOfFreeSpace += sizeof(WCHAR) *
825 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
828 if( src->lpPlayerName->u2.lpszLongName )
830 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
831 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
832 lpStartOfFreeSpace += sizeof(WCHAR) *
833 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
838 /* Copy address if it exists */
839 if( src->lpAddress )
841 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
842 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
843 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
848 /* Store the structure into the shared data structre. Ensure that allocs for
849 * variable length strings come from the shared data structure.
850 * FIXME: We need to free information as well
852 HRESULT DPLAYX_SetConnectionSettingsA
853 ( DWORD dwFlags,
854 DWORD dwAppID,
855 LPDPLCONNECTION lpConn )
857 LPDPLAYX_LOBBYDATA lpDplData;
859 /* Parameter check */
860 if( dwFlags || !lpConn )
862 ERR("invalid parameters.\n");
863 return DPERR_INVALIDPARAMS;
866 /* Store information */
867 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
869 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
870 lpConn->dwSize, sizeof( DPLCONNECTION ) );
872 return DPERR_INVALIDPARAMS;
875 DPLAYX_AquireSemaphore();
877 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
879 DPLAYX_ReleaseSemaphore();
881 return DPERR_NOTLOBBIED;
884 if( (!lpConn->lpSessionDesc ) ||
885 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
888 DPLAYX_ReleaseSemaphore();
890 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
891 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
893 return DPERR_INVALIDPARAMS;
896 /* Free the existing memory */
897 DPLAYX_PrivHeapFree( lpDplData->lpConn );
899 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
900 DPLAYX_SizeOfLobbyDataA( lpConn ) );
902 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
905 DPLAYX_ReleaseSemaphore();
907 /* FIXME: Send a message - I think */
909 return DP_OK;
912 /* Store the structure into the shared data structre. Ensure that allocs for
913 * variable length strings come from the shared data structure.
914 * FIXME: We need to free information as well
916 HRESULT DPLAYX_SetConnectionSettingsW
917 ( DWORD dwFlags,
918 DWORD dwAppID,
919 LPDPLCONNECTION lpConn )
921 LPDPLAYX_LOBBYDATA lpDplData;
923 /* Parameter check */
924 if( dwFlags || !lpConn )
926 ERR("invalid parameters.\n");
927 return DPERR_INVALIDPARAMS;
930 /* Store information */
931 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
933 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
934 lpConn->dwSize, sizeof( DPLCONNECTION ) );
936 return DPERR_INVALIDPARAMS;
939 DPLAYX_AquireSemaphore();
941 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
943 DPLAYX_ReleaseSemaphore();
945 return DPERR_NOTLOBBIED;
948 /* Free the existing memory */
949 DPLAYX_PrivHeapFree( lpDplData->lpConn );
951 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
952 DPLAYX_SizeOfLobbyDataW( lpConn ) );
954 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
957 DPLAYX_ReleaseSemaphore();
959 /* FIXME: Send a message - I think */
961 return DP_OK;
964 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
966 DWORD dwTotalSize = sizeof( DPLCONNECTION );
968 /* Just a safety check */
969 if( lpConn == NULL )
971 ERR( "lpConn is NULL\n" );
972 return 0;
975 if( lpConn->lpSessionDesc != NULL )
977 dwTotalSize += sizeof( DPSESSIONDESC2 );
979 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
981 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
984 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
986 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
990 if( lpConn->lpPlayerName != NULL )
992 dwTotalSize += sizeof( DPNAME );
994 if( lpConn->lpPlayerName->u1.lpszShortNameA )
996 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
999 if( lpConn->lpPlayerName->u2.lpszLongNameA )
1001 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
1006 dwTotalSize += lpConn->dwAddressSize;
1008 return dwTotalSize;
1011 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
1013 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1015 /* Just a safety check */
1016 if( lpConn == NULL )
1018 ERR( "lpConn is NULL\n" );
1019 return 0;
1022 if( lpConn->lpSessionDesc != NULL )
1024 dwTotalSize += sizeof( DPSESSIONDESC2 );
1026 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1032 if( lpConn->lpSessionDesc->u2.lpszPassword )
1034 dwTotalSize += sizeof( WCHAR ) *
1035 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1039 if( lpConn->lpPlayerName != NULL )
1041 dwTotalSize += sizeof( DPNAME );
1043 if( lpConn->lpPlayerName->u1.lpszShortName )
1045 dwTotalSize += sizeof( WCHAR ) *
1046 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1049 if( lpConn->lpPlayerName->u2.lpszLongName )
1051 dwTotalSize += sizeof( WCHAR ) *
1052 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1057 dwTotalSize += lpConn->dwAddressSize;
1059 return dwTotalSize;
1064 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1066 LPDPSESSIONDESC2 lpSessionDest =
1067 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1068 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1069 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1071 return lpSessionDest;
1074 /* Copy an ANSI session desc structure to the given buffer */
1075 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1076 LPCDPSESSIONDESC2 lpSessionSrc )
1078 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1080 if( lpSessionSrc->u1.lpszSessionNameA )
1082 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1083 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1084 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1086 if( lpSessionSrc->u2.lpszPasswordA )
1088 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1089 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1090 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1093 return TRUE;
1096 /* Start the index at 0. index will be updated to equal that which should
1097 be passed back into this function for the next element */
1098 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1100 for( ; (*index) < numSupportedSessions; (*index)++ )
1102 if( sessionData[(*index)].dwSize != 0 )
1104 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1108 /* No more sessions */
1109 return NULL;
1112 /* Start the index at 0. index will be updated to equal that which should
1113 be passed back into this function for the next element */
1114 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1116 for( ; (*index) < numSupportedSessions; (*index)++ )
1118 if( sessionData[(*index)].dwSize != 0 )
1120 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1124 /* No more sessions */
1125 return FALSE;
1128 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1130 UINT i;
1132 /* FIXME: Is this an error if it exists already? */
1134 /* Crude/wrong implementation for now. Just always add to first empty spot */
1135 for( i=0; i < numSupportedSessions; i++ )
1137 /* Is this one empty? */
1138 if( sessionData[i].dwSize == 0 )
1140 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1141 break;
1147 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1149 LPDPLAYX_LOBBYDATA lpLobbyData;
1151 DPLAYX_AquireSemaphore();
1153 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1155 DPLAYX_ReleaseSemaphore();
1156 return FALSE;
1159 lpLobbyData->bWaitForConnectionSettings = bWait;
1161 DPLAYX_ReleaseSemaphore();
1163 return TRUE;
1166 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1168 UINT i;
1169 BOOL bFound = FALSE;
1171 DPLAYX_AquireSemaphore();
1173 for( i=0; i < numSupportedLobbies; i++ )
1175 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1176 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1179 bFound = TRUE;
1180 break;
1184 DPLAYX_ReleaseSemaphore();
1186 return bFound;
1189 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1191 LPDPLAYX_LOBBYDATA lpLobbyData;
1193 DPLAYX_AquireSemaphore();
1195 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1197 DPLAYX_ReleaseSemaphore();
1198 return FALSE;
1201 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1203 DPLAYX_ReleaseSemaphore();
1205 return TRUE;
1208 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1209 with the correct string printed in the case where the HRESULT is not
1210 known. You'll just get the last hr passed in printed. This can change
1211 over time if this method is used alot :) */
1212 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1214 static char szTempStr[12];
1216 switch (hr)
1218 case DP_OK:
1219 return "DP_OK";
1220 case DPERR_ALREADYINITIALIZED:
1221 return "DPERR_ALREADYINITIALIZED";
1222 case DPERR_ACCESSDENIED:
1223 return "DPERR_ACCESSDENIED";
1224 case DPERR_ACTIVEPLAYERS:
1225 return "DPERR_ACTIVEPLAYERS";
1226 case DPERR_BUFFERTOOSMALL:
1227 return "DPERR_BUFFERTOOSMALL";
1228 case DPERR_CANTADDPLAYER:
1229 return "DPERR_CANTADDPLAYER";
1230 case DPERR_CANTCREATEGROUP:
1231 return "DPERR_CANTCREATEGROUP";
1232 case DPERR_CANTCREATEPLAYER:
1233 return "DPERR_CANTCREATEPLAYER";
1234 case DPERR_CANTCREATESESSION:
1235 return "DPERR_CANTCREATESESSION";
1236 case DPERR_CAPSNOTAVAILABLEYET:
1237 return "DPERR_CAPSNOTAVAILABLEYET";
1238 case DPERR_EXCEPTION:
1239 return "DPERR_EXCEPTION";
1240 case DPERR_GENERIC:
1241 return "DPERR_GENERIC";
1242 case DPERR_INVALIDFLAGS:
1243 return "DPERR_INVALIDFLAGS";
1244 case DPERR_INVALIDOBJECT:
1245 return "DPERR_INVALIDOBJECT";
1246 case DPERR_INVALIDPARAMS:
1247 return "DPERR_INVALIDPARAMS";
1248 case DPERR_INVALIDPLAYER:
1249 return "DPERR_INVALIDPLAYER";
1250 case DPERR_INVALIDGROUP:
1251 return "DPERR_INVALIDGROUP";
1252 case DPERR_NOCAPS:
1253 return "DPERR_NOCAPS";
1254 case DPERR_NOCONNECTION:
1255 return "DPERR_NOCONNECTION";
1256 case DPERR_OUTOFMEMORY:
1257 return "DPERR_OUTOFMEMORY";
1258 case DPERR_NOMESSAGES:
1259 return "DPERR_NOMESSAGES";
1260 case DPERR_NONAMESERVERFOUND:
1261 return "DPERR_NONAMESERVERFOUND";
1262 case DPERR_NOPLAYERS:
1263 return "DPERR_NOPLAYERS";
1264 case DPERR_NOSESSIONS:
1265 return "DPERR_NOSESSIONS";
1266 case DPERR_PENDING:
1267 return "DPERR_PENDING";
1268 case DPERR_SENDTOOBIG:
1269 return "DPERR_SENDTOOBIG";
1270 case DPERR_TIMEOUT:
1271 return "DPERR_TIMEOUT";
1272 case DPERR_UNAVAILABLE:
1273 return "DPERR_UNAVAILABLE";
1274 case DPERR_UNSUPPORTED:
1275 return "DPERR_UNSUPPORTED";
1276 case DPERR_BUSY:
1277 return "DPERR_BUSY";
1278 case DPERR_USERCANCEL:
1279 return "DPERR_USERCANCEL";
1280 case DPERR_NOINTERFACE:
1281 return "DPERR_NOINTERFACE";
1282 case DPERR_CANNOTCREATESERVER:
1283 return "DPERR_CANNOTCREATESERVER";
1284 case DPERR_PLAYERLOST:
1285 return "DPERR_PLAYERLOST";
1286 case DPERR_SESSIONLOST:
1287 return "DPERR_SESSIONLOST";
1288 case DPERR_UNINITIALIZED:
1289 return "DPERR_UNINITIALIZED";
1290 case DPERR_NONEWPLAYERS:
1291 return "DPERR_NONEWPLAYERS";
1292 case DPERR_INVALIDPASSWORD:
1293 return "DPERR_INVALIDPASSWORD";
1294 case DPERR_CONNECTING:
1295 return "DPERR_CONNECTING";
1296 case DPERR_CONNECTIONLOST:
1297 return "DPERR_CONNECTIONLOST";
1298 case DPERR_UNKNOWNMESSAGE:
1299 return "DPERR_UNKNOWNMESSAGE";
1300 case DPERR_CANCELFAILED:
1301 return "DPERR_CANCELFAILED";
1302 case DPERR_INVALIDPRIORITY:
1303 return "DPERR_INVALIDPRIORITY";
1304 case DPERR_NOTHANDLED:
1305 return "DPERR_NOTHANDLED";
1306 case DPERR_CANCELLED:
1307 return "DPERR_CANCELLED";
1308 case DPERR_ABORTED:
1309 return "DPERR_ABORTED";
1310 case DPERR_BUFFERTOOLARGE:
1311 return "DPERR_BUFFERTOOLARGE";
1312 case DPERR_CANTCREATEPROCESS:
1313 return "DPERR_CANTCREATEPROCESS";
1314 case DPERR_APPNOTSTARTED:
1315 return "DPERR_APPNOTSTARTED";
1316 case DPERR_INVALIDINTERFACE:
1317 return "DPERR_INVALIDINTERFACE";
1318 case DPERR_NOSERVICEPROVIDER:
1319 return "DPERR_NOSERVICEPROVIDER";
1320 case DPERR_UNKNOWNAPPLICATION:
1321 return "DPERR_UNKNOWNAPPLICATION";
1322 case DPERR_NOTLOBBIED:
1323 return "DPERR_NOTLOBBIED";
1324 case DPERR_SERVICEPROVIDERLOADED:
1325 return "DPERR_SERVICEPROVIDERLOADED";
1326 case DPERR_ALREADYREGISTERED:
1327 return "DPERR_ALREADYREGISTERED";
1328 case DPERR_NOTREGISTERED:
1329 return "DPERR_NOTREGISTERED";
1330 case DPERR_AUTHENTICATIONFAILED:
1331 return "DPERR_AUTHENTICATIONFAILED";
1332 case DPERR_CANTLOADSSPI:
1333 return "DPERR_CANTLOADSSPI";
1334 case DPERR_ENCRYPTIONFAILED:
1335 return "DPERR_ENCRYPTIONFAILED";
1336 case DPERR_SIGNFAILED:
1337 return "DPERR_SIGNFAILED";
1338 case DPERR_CANTLOADSECURITYPACKAGE:
1339 return "DPERR_CANTLOADSECURITYPACKAGE";
1340 case DPERR_ENCRYPTIONNOTSUPPORTED:
1341 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1342 case DPERR_CANTLOADCAPI:
1343 return "DPERR_CANTLOADCAPI";
1344 case DPERR_NOTLOGGEDIN:
1345 return "DPERR_NOTLOGGEDIN";
1346 case DPERR_LOGONDENIED:
1347 return "DPERR_LOGONDENIED";
1348 default:
1349 /* For errors not in the list, return HRESULT as a string
1350 This part is not thread safe */
1351 WARN( "Unknown error 0x%08lx\n", hr );
1352 wsprintfA( szTempStr, "0x%08lx", hr );
1353 return szTempStr;