jscript: Implement the String.fixed() method.
[wine/hacks.git] / dlls / dplayx / dplayx_global.c
blob6bf9f3da0849da747d02304805be273ba45f00c0
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * NOTES:
22 * o Implementation of all things which are associated with dplay on
23 * the computer - i.e. shared resources and such. Methods in this
24 * compilation unit should not call anything outside of this unit
25 * except 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 const char lpszDplayxSemaName[] = "WINE_DPLAYX_SM";
55 static HANDLE hDplayxSema;
57 static const char lpszDplayxFileMapping[] = "WINE_DPLAYX_FM";
58 static HANDLE hDplayxSharedMem;
60 static LPVOID lpSharedStaticData = NULL;
63 #define DPLAYX_AcquireSemaphore() 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 static void DPLAYX_PrivHeapFree( LPVOID addr )
94 LPVOID lpAddrStart;
95 DWORD dwBlockUsed;
97 /* Handle getting passed a NULL */
98 if( addr == NULL )
100 return;
103 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
104 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
106 lpMemArea[ dwBlockUsed ].used = 0;
109 static LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
111 LPVOID lpvArea = NULL;
112 UINT uBlockUsed;
114 if( size > (dwBlockSize - sizeof(DWORD)) )
116 FIXME( "Size exceeded. Request of 0x%08x\n", size );
117 size = dwBlockSize - sizeof(DWORD);
120 /* Find blank area */
121 uBlockUsed = 0;
122 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
124 if( uBlockUsed <= dwMaxBlock )
126 /* Set the area used */
127 lpMemArea[ uBlockUsed ].used = 1;
128 lpvArea = lpMemArea[ uBlockUsed ].data;
130 else
132 ERR( "No free block found\n" );
133 return NULL;
136 if( flags & HEAP_ZERO_MEMORY )
138 ZeroMemory( lpvArea, size );
141 return lpvArea;
145 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
146 typedef struct tagDPLAYX_LOBBYDATA
148 /* Points to lpConn + block of contiguous extra memory for dynamic parts
149 * of the struct directly following
151 LPDPLCONNECTION lpConn;
153 /* Information for dplobby interfaces */
154 DWORD dwAppID;
155 DWORD dwAppLaunchedFromID;
157 /* Should this lobby app send messages to creator at important life
158 * stages
160 HANDLE hInformOnAppStart;
161 HANDLE hInformOnAppDeath;
162 HANDLE hInformOnSettingRead;
164 /* Sundries */
165 BOOL bWaitForConnectionSettings;
166 DWORD dwLobbyMsgThreadId;
169 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
171 static DPLAYX_LOBBYDATA* lobbyData = NULL;
172 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
174 static DPSESSIONDESC2* sessionData = NULL;
175 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
177 /* Function prototypes */
178 static DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpDplData );
179 static DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpDplData );
180 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src );
181 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src );
182 static BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
183 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
184 static BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
185 LPCDPSESSIONDESC2 lpSessionSrc );
186 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart, LPHANDLE lphDeath,
187 LPHANDLE lphConnRead, BOOL bClearSetHandles );
191 /***************************************************************************
192 * Called to initialize the global data. This will only be used on the
193 * loading of the dll
194 ***************************************************************************/
195 BOOL DPLAYX_ConstructData(void)
197 SECURITY_ATTRIBUTES s_attrib;
198 BOOL bInitializeSharedMemory = FALSE;
199 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
200 HANDLE hInformOnStart;
202 TRACE( "DPLAYX dll loaded - construct called\n" );
204 /* Create a semaphore to block access to DPLAYX global data structs */
206 s_attrib.bInheritHandle = TRUE;
207 s_attrib.lpSecurityDescriptor = NULL;
208 s_attrib.nLength = sizeof(s_attrib);
210 hDplayxSema = CreateSemaphoreA( &s_attrib, 0, 1, lpszDplayxSemaName );
212 /* First instance creates the semaphore. Others just use it */
213 if( GetLastError() == ERROR_SUCCESS )
215 TRACE( "Semaphore %p created\n", hDplayxSema );
217 /* The semaphore creator will also build the shared memory */
218 bInitializeSharedMemory = TRUE;
220 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
222 TRACE( "Found semaphore handle %p\n", hDplayxSema );
223 DPLAYX_AcquireSemaphore();
225 else
227 ERR( ": semaphore error %d\n", GetLastError() );
228 return FALSE;
231 SetLastError( ERROR_SUCCESS );
233 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
234 &s_attrib,
235 PAGE_READWRITE | SEC_COMMIT,
237 dwTotalSharedSize,
238 lpszDplayxFileMapping );
240 if( GetLastError() == ERROR_SUCCESS )
242 TRACE( "File mapped %p created\n", hDplayxSharedMem );
244 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
246 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
248 else
250 ERR( ": unable to create shared memory (%d)\n", GetLastError() );
251 DPLAYX_ReleaseSemaphore();
252 return FALSE;
255 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
256 FILE_MAP_WRITE,
257 0, 0, 0, lpDesiredMemoryMapStart );
259 if( lpSharedStaticData == NULL )
261 ERR( ": unable to map static data into process memory space (%d)\n",
262 GetLastError() );
263 DPLAYX_ReleaseSemaphore();
264 return FALSE;
266 else
268 if( lpDesiredMemoryMapStart == lpSharedStaticData )
270 TRACE( "File mapped to %p\n", lpSharedStaticData );
272 else
274 /* Presently the shared data structures use pointers. If the
275 * files are no mapped into the same area, the pointers will no
276 * longer make any sense :(
277 * FIXME: In the future make the shared data structures have some
278 * sort of fixup to make them independent between data spaces.
279 * This will also require a rework of the session data stuff.
281 ERR( "File mapped to %p (not %p). Expect failure\n",
282 lpSharedStaticData, lpDesiredMemoryMapStart );
286 /* Dynamic area starts just after the static area */
287 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
289 /* FIXME: Crude hack */
290 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
291 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
293 /* Initialize shared data segments. */
294 if( bInitializeSharedMemory )
296 UINT i;
298 TRACE( "Initializing shared memory\n" );
300 /* Set all lobbies to be "empty" */
301 for( i=0; i < numSupportedLobbies; i++ )
303 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
306 /* Set all sessions to be "empty" */
307 for( i=0; i < numSupportedSessions; i++ )
309 sessionData[i].dwSize = 0;
312 /* Zero out the dynamic area */
313 ZeroMemory( lpMemArea, dwDynamicSharedSize );
315 /* Just for fun sync the whole data area */
316 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
319 DPLAYX_ReleaseSemaphore();
321 /* Everything was created correctly. Signal the lobby client that
322 * we started up correctly
324 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
325 hInformOnStart
328 BOOL bSuccess;
329 bSuccess = SetEvent( hInformOnStart );
330 TRACE( "Signalling lobby app start event %p %s\n",
331 hInformOnStart, bSuccess ? "succeed" : "failed" );
333 /* Close out handle */
334 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
337 return TRUE;
340 /***************************************************************************
341 * Called to destroy all global data. This will only be used on the
342 * unloading of the dll
343 ***************************************************************************/
344 BOOL DPLAYX_DestructData(void)
346 HANDLE hInformOnDeath;
348 TRACE( "DPLAYX dll unloaded - destruct called\n" );
350 /* If required, inform that this app is dying */
351 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
352 hInformOnDeath
355 BOOL bSuccess;
356 bSuccess = SetEvent( hInformOnDeath );
357 TRACE( "Signalling lobby app death event %p %s\n",
358 hInformOnDeath, bSuccess ? "succeed" : "failed" );
360 /* Close out handle */
361 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
364 /* DO CLEAN UP (LAST) */
366 /* Delete the semaphore */
367 CloseHandle( hDplayxSema );
369 /* Delete shared memory file mapping */
370 UnmapViewOfFile( lpSharedStaticData );
371 CloseHandle( hDplayxSharedMem );
373 return FALSE;
377 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
379 ZeroMemory( lpData, sizeof( *lpData ) );
382 /* NOTE: This must be called with the semaphore acquired.
383 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
384 * is only valid if TRUE is returned.
386 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
388 UINT i;
390 *lplpDplData = NULL;
392 if( dwAppID == 0 )
394 dwAppID = GetCurrentProcessId();
395 TRACE( "Translated dwAppID == 0 into 0x%08x\n", dwAppID );
398 for( i=0; i < numSupportedLobbies; i++ )
400 if( lobbyData[ i ].dwAppID == dwAppID )
402 /* This process is lobbied */
403 TRACE( "Found 0x%08x @ %u\n", dwAppID, i );
404 *lplpDplData = &lobbyData[ i ];
405 return TRUE;
409 return FALSE;
412 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
413 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
415 UINT i;
417 /* 0 is the marker for unused application data slots */
418 if( dwAppID == 0 )
420 return FALSE;
423 DPLAYX_AcquireSemaphore();
425 /* Find an empty space in the list and insert the data */
426 for( i=0; i < numSupportedLobbies; i++ )
428 if( lobbyData[ i ].dwAppID == 0 )
430 /* This process is now lobbied */
431 TRACE( "Setting lobbyData[%u] for (0x%08x,0x%08x)\n",
432 i, dwAppID, GetCurrentProcessId() );
434 lobbyData[ i ].dwAppID = dwAppID;
435 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
437 /* FIXME: Where is the best place for this? In interface or here? */
438 lobbyData[ i ].hInformOnAppStart = 0;
439 lobbyData[ i ].hInformOnAppDeath = 0;
440 lobbyData[ i ].hInformOnSettingRead = 0;
442 DPLAYX_ReleaseSemaphore();
443 return TRUE;
447 ERR( "No empty lobbies\n" );
449 DPLAYX_ReleaseSemaphore();
450 return FALSE;
453 /* I'm not sure when I'm going to need this, but here it is */
454 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
456 UINT i;
458 DPLAYX_AcquireSemaphore();
460 /* Find an empty space in the list and insert the data */
461 for( i=0; i < numSupportedLobbies; i++ )
463 if( lobbyData[ i ].dwAppID == dwAppID )
465 /* FIXME: Should free up anything unused. Tisk tisk :0 */
466 /* Mark this entry unused */
467 TRACE( "Marking lobbyData[%u] unused\n", i );
468 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
470 DPLAYX_ReleaseSemaphore();
471 return TRUE;
475 DPLAYX_ReleaseSemaphore();
476 ERR( "Unable to find global entry for application\n" );
477 return FALSE;
480 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
481 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
483 LPDPLAYX_LOBBYDATA lpLData;
485 /* Need to explicitly give lobby application. Can't set for yourself */
486 if( dwAppID == 0 )
488 return FALSE;
491 DPLAYX_AcquireSemaphore();
493 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
495 DPLAYX_ReleaseSemaphore();
496 return FALSE;
499 lpLData->hInformOnAppStart = hStart;
500 lpLData->hInformOnAppDeath = hDeath;
501 lpLData->hInformOnSettingRead = hConnRead;
503 DPLAYX_ReleaseSemaphore();
505 return TRUE;
508 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
509 LPHANDLE lphDeath,
510 LPHANDLE lphConnRead,
511 BOOL bClearSetHandles )
513 LPDPLAYX_LOBBYDATA lpLData;
515 DPLAYX_AcquireSemaphore();
517 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
519 DPLAYX_ReleaseSemaphore();
520 return FALSE;
523 if( lphStart != NULL )
525 if( lpLData->hInformOnAppStart == 0 )
527 DPLAYX_ReleaseSemaphore();
528 return FALSE;
531 *lphStart = lpLData->hInformOnAppStart;
533 if( bClearSetHandles )
535 CloseHandle( lpLData->hInformOnAppStart );
536 lpLData->hInformOnAppStart = 0;
540 if( lphDeath != NULL )
542 if( lpLData->hInformOnAppDeath == 0 )
544 DPLAYX_ReleaseSemaphore();
545 return FALSE;
548 *lphDeath = lpLData->hInformOnAppDeath;
550 if( bClearSetHandles )
552 CloseHandle( lpLData->hInformOnAppDeath );
553 lpLData->hInformOnAppDeath = 0;
557 if( lphConnRead != NULL )
559 if( lpLData->hInformOnSettingRead == 0 )
561 DPLAYX_ReleaseSemaphore();
562 return FALSE;
565 *lphConnRead = lpLData->hInformOnSettingRead;
567 if( bClearSetHandles )
569 CloseHandle( lpLData->hInformOnSettingRead );
570 lpLData->hInformOnSettingRead = 0;
574 DPLAYX_ReleaseSemaphore();
576 return TRUE;
580 HRESULT DPLAYX_GetConnectionSettingsA
581 ( DWORD dwAppID,
582 LPVOID lpData,
583 LPDWORD lpdwDataSize )
585 LPDPLAYX_LOBBYDATA lpDplData;
586 DWORD dwRequiredDataSize = 0;
587 HANDLE hInformOnSettingRead;
589 DPLAYX_AcquireSemaphore();
591 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
593 DPLAYX_ReleaseSemaphore();
595 TRACE( "Application 0x%08x is not lobbied\n", dwAppID );
596 return DPERR_NOTLOBBIED;
599 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
601 /* Do they want to know the required buffer size or is the provided buffer
602 * big enough?
604 if ( ( lpData == NULL ) ||
605 ( *lpdwDataSize < dwRequiredDataSize )
608 DPLAYX_ReleaseSemaphore();
610 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
612 return DPERR_BUFFERTOOSMALL;
615 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
617 DPLAYX_ReleaseSemaphore();
619 /* They have gotten the information - signal the event if required */
620 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
621 hInformOnSettingRead
624 BOOL bSuccess;
625 bSuccess = SetEvent( hInformOnSettingRead );
626 TRACE( "Signalling setting read event %p %s\n",
627 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
629 /* Close out handle */
630 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
633 return DP_OK;
636 /* Assumption: Enough contiguous space was allocated at dest */
637 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src )
639 BYTE* lpStartOfFreeSpace;
641 *dest = *src;
643 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
645 /* Copy the LPDPSESSIONDESC2 structure if it exists */
646 if( src->lpSessionDesc )
648 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
649 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
650 *dest->lpSessionDesc = *src->lpSessionDesc;
652 /* Session names may or may not exist */
653 if( src->lpSessionDesc->u1.lpszSessionNameA )
655 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
656 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
657 lpStartOfFreeSpace +=
658 strlen( dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
661 if( src->lpSessionDesc->u2.lpszPasswordA )
663 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
664 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
665 lpStartOfFreeSpace +=
666 strlen( dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
670 /* DPNAME structure is optional */
671 if( src->lpPlayerName )
673 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
674 lpStartOfFreeSpace += sizeof( DPNAME );
675 *dest->lpPlayerName = *src->lpPlayerName;
677 if( src->lpPlayerName->u1.lpszShortNameA )
679 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
680 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
681 lpStartOfFreeSpace +=
682 strlen( dest->lpPlayerName->u1.lpszShortNameA ) + 1;
685 if( src->lpPlayerName->u2.lpszLongNameA )
687 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
688 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
689 lpStartOfFreeSpace +=
690 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
695 /* Copy address if it exists */
696 if( src->lpAddress )
698 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
699 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
700 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
704 HRESULT DPLAYX_GetConnectionSettingsW
705 ( DWORD dwAppID,
706 LPVOID lpData,
707 LPDWORD lpdwDataSize )
709 LPDPLAYX_LOBBYDATA lpDplData;
710 DWORD dwRequiredDataSize = 0;
711 HANDLE hInformOnSettingRead;
713 DPLAYX_AcquireSemaphore();
715 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
717 DPLAYX_ReleaseSemaphore();
718 return DPERR_NOTLOBBIED;
721 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
723 /* Do they want to know the required buffer size or is the provided buffer
724 * big enough?
726 if ( ( lpData == NULL ) ||
727 ( *lpdwDataSize < dwRequiredDataSize )
730 DPLAYX_ReleaseSemaphore();
732 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
734 return DPERR_BUFFERTOOSMALL;
737 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
739 DPLAYX_ReleaseSemaphore();
741 /* They have gotten the information - signal the event if required */
742 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
743 hInformOnSettingRead
746 BOOL bSuccess;
747 bSuccess = SetEvent( hInformOnSettingRead );
748 TRACE( "Signalling setting read event %p %s\n",
749 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
751 /* Close out handle */
752 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
755 return DP_OK;
758 /* Assumption: Enough contiguous space was allocated at dest */
759 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src )
761 BYTE* lpStartOfFreeSpace;
763 *dest = *src;
765 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
767 /* Copy the LPDPSESSIONDESC2 structure if it exists */
768 if( src->lpSessionDesc )
770 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
771 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
772 *dest->lpSessionDesc = *src->lpSessionDesc;
774 /* Session names may or may not exist */
775 if( src->lpSessionDesc->u1.lpszSessionName )
777 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionName );
778 dest->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
779 lpStartOfFreeSpace += sizeof(WCHAR) *
780 ( strlenW( dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
783 if( src->lpSessionDesc->u2.lpszPassword )
785 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
786 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
787 lpStartOfFreeSpace += sizeof(WCHAR) *
788 ( strlenW( dest->lpSessionDesc->u2.lpszPassword ) + 1 );
792 /* DPNAME structure is optional */
793 if( src->lpPlayerName )
795 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
796 lpStartOfFreeSpace += sizeof( DPNAME );
797 *dest->lpPlayerName = *src->lpPlayerName;
799 if( src->lpPlayerName->u1.lpszShortName )
801 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
802 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
803 lpStartOfFreeSpace += sizeof(WCHAR) *
804 ( strlenW( dest->lpPlayerName->u1.lpszShortName ) + 1 );
807 if( src->lpPlayerName->u2.lpszLongName )
809 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
810 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
811 lpStartOfFreeSpace += sizeof(WCHAR) *
812 ( strlenW( dest->lpPlayerName->u2.lpszLongName ) + 1 );
817 /* Copy address if it exists */
818 if( src->lpAddress )
820 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
821 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
822 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
827 /* Store the structure into the shared data structure. Ensure that allocs for
828 * variable length strings come from the shared data structure.
829 * FIXME: We need to free information as well.
831 HRESULT DPLAYX_SetConnectionSettingsA
832 ( DWORD dwFlags,
833 DWORD dwAppID,
834 const DPLCONNECTION *lpConn )
836 LPDPLAYX_LOBBYDATA lpDplData;
838 /* Parameter check */
839 if( dwFlags || !lpConn )
841 ERR("invalid parameters.\n");
842 return DPERR_INVALIDPARAMS;
845 /* Store information */
846 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
848 ERR(": old/new DPLCONNECTION type? Size=%08x\n", lpConn->dwSize );
850 return DPERR_INVALIDPARAMS;
853 DPLAYX_AcquireSemaphore();
855 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
857 DPLAYX_ReleaseSemaphore();
859 return DPERR_NOTLOBBIED;
862 if( (!lpConn->lpSessionDesc ) ||
863 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
866 DPLAYX_ReleaseSemaphore();
868 ERR("DPSESSIONDESC passed in? Size=%u\n",
869 lpConn->lpSessionDesc?lpConn->lpSessionDesc->dwSize:0 );
871 return DPERR_INVALIDPARAMS;
874 /* Free the existing memory */
875 DPLAYX_PrivHeapFree( lpDplData->lpConn );
877 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
878 DPLAYX_SizeOfLobbyDataA( lpConn ) );
880 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
883 DPLAYX_ReleaseSemaphore();
885 /* FIXME: Send a message - I think */
887 return DP_OK;
890 /* Store the structure into the shared data structure. Ensure that allocs for
891 * variable length strings come from the shared data structure.
892 * FIXME: We need to free information as well
894 HRESULT DPLAYX_SetConnectionSettingsW
895 ( DWORD dwFlags,
896 DWORD dwAppID,
897 const DPLCONNECTION *lpConn )
899 LPDPLAYX_LOBBYDATA lpDplData;
901 /* Parameter check */
902 if( dwFlags || !lpConn )
904 ERR("invalid parameters.\n");
905 return DPERR_INVALIDPARAMS;
908 /* Store information */
909 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
911 ERR(": old/new DPLCONNECTION type? Size=%u\n", lpConn->dwSize );
913 return DPERR_INVALIDPARAMS;
916 DPLAYX_AcquireSemaphore();
918 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
920 DPLAYX_ReleaseSemaphore();
922 return DPERR_NOTLOBBIED;
925 /* Free the existing memory */
926 DPLAYX_PrivHeapFree( lpDplData->lpConn );
928 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
929 DPLAYX_SizeOfLobbyDataW( lpConn ) );
931 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
934 DPLAYX_ReleaseSemaphore();
936 /* FIXME: Send a message - I think */
938 return DP_OK;
941 DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpConn )
943 DWORD dwTotalSize = sizeof( DPLCONNECTION );
945 /* Just a safety check */
946 if( lpConn == NULL )
948 ERR( "lpConn is NULL\n" );
949 return 0;
952 if( lpConn->lpSessionDesc != NULL )
954 dwTotalSize += sizeof( DPSESSIONDESC2 );
956 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
958 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
961 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
963 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
967 if( lpConn->lpPlayerName != NULL )
969 dwTotalSize += sizeof( DPNAME );
971 if( lpConn->lpPlayerName->u1.lpszShortNameA )
973 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
976 if( lpConn->lpPlayerName->u2.lpszLongNameA )
978 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
983 dwTotalSize += lpConn->dwAddressSize;
985 return dwTotalSize;
988 DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpConn )
990 DWORD dwTotalSize = sizeof( DPLCONNECTION );
992 /* Just a safety check */
993 if( lpConn == NULL )
995 ERR( "lpConn is NULL\n" );
996 return 0;
999 if( lpConn->lpSessionDesc != NULL )
1001 dwTotalSize += sizeof( DPSESSIONDESC2 );
1003 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1005 dwTotalSize += sizeof( WCHAR ) *
1006 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1009 if( lpConn->lpSessionDesc->u2.lpszPassword )
1011 dwTotalSize += sizeof( WCHAR ) *
1012 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1016 if( lpConn->lpPlayerName != NULL )
1018 dwTotalSize += sizeof( DPNAME );
1020 if( lpConn->lpPlayerName->u1.lpszShortName )
1022 dwTotalSize += sizeof( WCHAR ) *
1023 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1026 if( lpConn->lpPlayerName->u2.lpszLongName )
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1034 dwTotalSize += lpConn->dwAddressSize;
1036 return dwTotalSize;
1041 /* Copy an ANSI session desc structure to the given buffer */
1042 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1043 LPCDPSESSIONDESC2 lpSessionSrc )
1045 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1047 if( lpSessionSrc->u1.lpszSessionNameA )
1049 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1050 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1051 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1053 if( lpSessionSrc->u2.lpszPasswordA )
1055 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1056 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1057 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1060 return TRUE;
1063 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1065 UINT i;
1067 /* FIXME: Is this an error if it exists already? */
1069 /* Crude/wrong implementation for now. Just always add to first empty spot */
1070 for( i=0; i < numSupportedSessions; i++ )
1072 /* Is this one empty? */
1073 if( sessionData[i].dwSize == 0 )
1075 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1076 break;
1082 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1084 LPDPLAYX_LOBBYDATA lpLobbyData;
1086 DPLAYX_AcquireSemaphore();
1088 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1090 DPLAYX_ReleaseSemaphore();
1091 return FALSE;
1094 lpLobbyData->bWaitForConnectionSettings = bWait;
1096 DPLAYX_ReleaseSemaphore();
1098 return TRUE;
1101 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1103 UINT i;
1104 BOOL bFound = FALSE;
1106 DPLAYX_AcquireSemaphore();
1108 for( i=0; i < numSupportedLobbies; i++ )
1110 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1111 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1114 bFound = TRUE;
1115 break;
1119 DPLAYX_ReleaseSemaphore();
1121 return bFound;
1124 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1126 LPDPLAYX_LOBBYDATA lpLobbyData;
1128 DPLAYX_AcquireSemaphore();
1130 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1132 DPLAYX_ReleaseSemaphore();
1133 return FALSE;
1136 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1138 DPLAYX_ReleaseSemaphore();
1140 return TRUE;
1143 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1144 with the correct string printed in the case where the HRESULT is not
1145 known. You will just get the last hr passed in. This can change
1146 over time if this method is used a lot :) */
1147 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1149 static char szTempStr[12];
1151 switch (hr)
1153 case DP_OK:
1154 return "DP_OK";
1155 case DPERR_ALREADYINITIALIZED:
1156 return "DPERR_ALREADYINITIALIZED";
1157 case DPERR_ACCESSDENIED:
1158 return "DPERR_ACCESSDENIED";
1159 case DPERR_ACTIVEPLAYERS:
1160 return "DPERR_ACTIVEPLAYERS";
1161 case DPERR_BUFFERTOOSMALL:
1162 return "DPERR_BUFFERTOOSMALL";
1163 case DPERR_CANTADDPLAYER:
1164 return "DPERR_CANTADDPLAYER";
1165 case DPERR_CANTCREATEGROUP:
1166 return "DPERR_CANTCREATEGROUP";
1167 case DPERR_CANTCREATEPLAYER:
1168 return "DPERR_CANTCREATEPLAYER";
1169 case DPERR_CANTCREATESESSION:
1170 return "DPERR_CANTCREATESESSION";
1171 case DPERR_CAPSNOTAVAILABLEYET:
1172 return "DPERR_CAPSNOTAVAILABLEYET";
1173 case DPERR_EXCEPTION:
1174 return "DPERR_EXCEPTION";
1175 case DPERR_GENERIC:
1176 return "DPERR_GENERIC";
1177 case DPERR_INVALIDFLAGS:
1178 return "DPERR_INVALIDFLAGS";
1179 case DPERR_INVALIDOBJECT:
1180 return "DPERR_INVALIDOBJECT";
1181 case DPERR_INVALIDPARAMS:
1182 return "DPERR_INVALIDPARAMS";
1183 case DPERR_INVALIDPLAYER:
1184 return "DPERR_INVALIDPLAYER";
1185 case DPERR_INVALIDGROUP:
1186 return "DPERR_INVALIDGROUP";
1187 case DPERR_NOCAPS:
1188 return "DPERR_NOCAPS";
1189 case DPERR_NOCONNECTION:
1190 return "DPERR_NOCONNECTION";
1191 case DPERR_OUTOFMEMORY:
1192 return "DPERR_OUTOFMEMORY";
1193 case DPERR_NOMESSAGES:
1194 return "DPERR_NOMESSAGES";
1195 case DPERR_NONAMESERVERFOUND:
1196 return "DPERR_NONAMESERVERFOUND";
1197 case DPERR_NOPLAYERS:
1198 return "DPERR_NOPLAYERS";
1199 case DPERR_NOSESSIONS:
1200 return "DPERR_NOSESSIONS";
1201 case DPERR_PENDING:
1202 return "DPERR_PENDING";
1203 case DPERR_SENDTOOBIG:
1204 return "DPERR_SENDTOOBIG";
1205 case DPERR_TIMEOUT:
1206 return "DPERR_TIMEOUT";
1207 case DPERR_UNAVAILABLE:
1208 return "DPERR_UNAVAILABLE";
1209 case DPERR_UNSUPPORTED:
1210 return "DPERR_UNSUPPORTED";
1211 case DPERR_BUSY:
1212 return "DPERR_BUSY";
1213 case DPERR_USERCANCEL:
1214 return "DPERR_USERCANCEL";
1215 case DPERR_NOINTERFACE:
1216 return "DPERR_NOINTERFACE";
1217 case DPERR_CANNOTCREATESERVER:
1218 return "DPERR_CANNOTCREATESERVER";
1219 case DPERR_PLAYERLOST:
1220 return "DPERR_PLAYERLOST";
1221 case DPERR_SESSIONLOST:
1222 return "DPERR_SESSIONLOST";
1223 case DPERR_UNINITIALIZED:
1224 return "DPERR_UNINITIALIZED";
1225 case DPERR_NONEWPLAYERS:
1226 return "DPERR_NONEWPLAYERS";
1227 case DPERR_INVALIDPASSWORD:
1228 return "DPERR_INVALIDPASSWORD";
1229 case DPERR_CONNECTING:
1230 return "DPERR_CONNECTING";
1231 case DPERR_CONNECTIONLOST:
1232 return "DPERR_CONNECTIONLOST";
1233 case DPERR_UNKNOWNMESSAGE:
1234 return "DPERR_UNKNOWNMESSAGE";
1235 case DPERR_CANCELFAILED:
1236 return "DPERR_CANCELFAILED";
1237 case DPERR_INVALIDPRIORITY:
1238 return "DPERR_INVALIDPRIORITY";
1239 case DPERR_NOTHANDLED:
1240 return "DPERR_NOTHANDLED";
1241 case DPERR_CANCELLED:
1242 return "DPERR_CANCELLED";
1243 case DPERR_ABORTED:
1244 return "DPERR_ABORTED";
1245 case DPERR_BUFFERTOOLARGE:
1246 return "DPERR_BUFFERTOOLARGE";
1247 case DPERR_CANTCREATEPROCESS:
1248 return "DPERR_CANTCREATEPROCESS";
1249 case DPERR_APPNOTSTARTED:
1250 return "DPERR_APPNOTSTARTED";
1251 case DPERR_INVALIDINTERFACE:
1252 return "DPERR_INVALIDINTERFACE";
1253 case DPERR_NOSERVICEPROVIDER:
1254 return "DPERR_NOSERVICEPROVIDER";
1255 case DPERR_UNKNOWNAPPLICATION:
1256 return "DPERR_UNKNOWNAPPLICATION";
1257 case DPERR_NOTLOBBIED:
1258 return "DPERR_NOTLOBBIED";
1259 case DPERR_SERVICEPROVIDERLOADED:
1260 return "DPERR_SERVICEPROVIDERLOADED";
1261 case DPERR_ALREADYREGISTERED:
1262 return "DPERR_ALREADYREGISTERED";
1263 case DPERR_NOTREGISTERED:
1264 return "DPERR_NOTREGISTERED";
1265 case DPERR_AUTHENTICATIONFAILED:
1266 return "DPERR_AUTHENTICATIONFAILED";
1267 case DPERR_CANTLOADSSPI:
1268 return "DPERR_CANTLOADSSPI";
1269 case DPERR_ENCRYPTIONFAILED:
1270 return "DPERR_ENCRYPTIONFAILED";
1271 case DPERR_SIGNFAILED:
1272 return "DPERR_SIGNFAILED";
1273 case DPERR_CANTLOADSECURITYPACKAGE:
1274 return "DPERR_CANTLOADSECURITYPACKAGE";
1275 case DPERR_ENCRYPTIONNOTSUPPORTED:
1276 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1277 case DPERR_CANTLOADCAPI:
1278 return "DPERR_CANTLOADCAPI";
1279 case DPERR_NOTLOGGEDIN:
1280 return "DPERR_NOTLOGGEDIN";
1281 case DPERR_LOGONDENIED:
1282 return "DPERR_LOGONDENIED";
1283 default:
1284 /* For errors not in the list, return HRESULT as a string
1285 This part is not thread safe */
1286 WARN( "Unknown error 0x%08x\n", hr );
1287 wsprintfA( szTempStr, "0x%08lx", hr );
1288 return szTempStr;