kernel32/tests: Add a test to check some fields in fake dlls.
[wine.git] / dlls / dplayx / dplayx_global.c
blobbc087c8b33b006bdc88005f26047668ca18f2e00
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
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 BOOL used;
87 BYTE data[dwBlockSize - sizeof(BOOL)];
88 } DPLAYX_MEM_SLICE;
89 C_ASSERT(sizeof(DPLAYX_MEM_SLICE) == dwBlockSize);
91 static DPLAYX_MEM_SLICE* lpMemArea;
93 static 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 = CONTAINING_RECORD(addr, DPLAYX_MEM_SLICE, data); /* Find block header */
105 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
107 lpMemArea[ dwBlockUsed ].used = FALSE;
110 static LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
112 LPVOID lpvArea = NULL;
113 UINT uBlockUsed;
115 if( size > (dwBlockSize - sizeof(BOOL)) )
117 FIXME( "Size exceeded. Request of 0x%08x\n", size );
118 size = dwBlockSize - sizeof(BOOL);
121 /* Find blank area */
122 uBlockUsed = 0;
123 while( uBlockUsed < dwMaxBlock && lpMemArea[ uBlockUsed ].used ) { uBlockUsed++; }
125 if( uBlockUsed < dwMaxBlock )
127 /* Set the area used */
128 lpMemArea[ uBlockUsed ].used = TRUE;
129 lpvArea = lpMemArea[ uBlockUsed ].data;
131 else
133 ERR( "No free block found\n" );
134 return NULL;
137 if( flags & HEAP_ZERO_MEMORY )
139 ZeroMemory( lpvArea, size );
142 return lpvArea;
146 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
147 typedef struct tagDPLAYX_LOBBYDATA
149 /* Points to lpConn + block of contiguous extra memory for dynamic parts
150 * of the struct directly following
152 LPDPLCONNECTION lpConn;
154 /* Information for dplobby interfaces */
155 DWORD dwAppID;
156 DWORD dwAppLaunchedFromID;
158 /* Should this lobby app send messages to creator at important life
159 * stages
161 HANDLE hInformOnAppStart;
162 HANDLE hInformOnAppDeath;
163 HANDLE hInformOnSettingRead;
165 /* Sundries */
166 BOOL bWaitForConnectionSettings;
167 DWORD dwLobbyMsgThreadId;
170 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
172 static DPLAYX_LOBBYDATA* lobbyData = NULL;
173 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
175 static DPSESSIONDESC2* sessionData = NULL;
176 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
179 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
181 ZeroMemory( lpData, sizeof( *lpData ) );
184 /* NOTE: This must be called with the semaphore acquired.
185 * TRUE/FALSE with a pointer to its data returned. Pointer data is
186 * is only valid if TRUE is returned.
188 static BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
190 UINT i;
192 *lplpDplData = NULL;
194 if( dwAppID == 0 )
196 dwAppID = GetCurrentProcessId();
197 TRACE( "Translated dwAppID == 0 into 0x%08x\n", dwAppID );
200 for( i=0; i < numSupportedLobbies; i++ )
202 if( lobbyData[ i ].dwAppID == dwAppID )
204 /* This process is lobbied */
205 TRACE( "Found 0x%08x @ %u\n", dwAppID, i );
206 *lplpDplData = &lobbyData[ i ];
207 return TRUE;
211 return FALSE;
214 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
215 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
217 UINT i;
219 /* 0 is the marker for unused application data slots */
220 if( dwAppID == 0 )
222 return FALSE;
225 DPLAYX_AcquireSemaphore();
227 /* Find an empty space in the list and insert the data */
228 for( i=0; i < numSupportedLobbies; i++ )
230 if( lobbyData[ i ].dwAppID == 0 )
232 /* This process is now lobbied */
233 TRACE( "Setting lobbyData[%u] for (0x%08x,0x%08x)\n",
234 i, dwAppID, GetCurrentProcessId() );
236 lobbyData[ i ].dwAppID = dwAppID;
237 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
239 /* FIXME: Where is the best place for this? In interface or here? */
240 lobbyData[ i ].hInformOnAppStart = 0;
241 lobbyData[ i ].hInformOnAppDeath = 0;
242 lobbyData[ i ].hInformOnSettingRead = 0;
244 DPLAYX_ReleaseSemaphore();
245 return TRUE;
249 ERR( "No empty lobbies\n" );
251 DPLAYX_ReleaseSemaphore();
252 return FALSE;
255 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
256 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
258 LPDPLAYX_LOBBYDATA lpLData;
260 /* Need to explicitly give lobby application. Can't set for yourself */
261 if( dwAppID == 0 )
263 return FALSE;
266 DPLAYX_AcquireSemaphore();
268 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
270 DPLAYX_ReleaseSemaphore();
271 return FALSE;
274 lpLData->hInformOnAppStart = hStart;
275 lpLData->hInformOnAppDeath = hDeath;
276 lpLData->hInformOnSettingRead = hConnRead;
278 DPLAYX_ReleaseSemaphore();
280 return TRUE;
283 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
284 LPHANDLE lphDeath,
285 LPHANDLE lphConnRead,
286 BOOL bClearSetHandles )
288 LPDPLAYX_LOBBYDATA lpLData;
290 DPLAYX_AcquireSemaphore();
292 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
294 DPLAYX_ReleaseSemaphore();
295 return FALSE;
298 if( lphStart != NULL )
300 if( lpLData->hInformOnAppStart == 0 )
302 DPLAYX_ReleaseSemaphore();
303 return FALSE;
306 *lphStart = lpLData->hInformOnAppStart;
308 if( bClearSetHandles )
310 CloseHandle( lpLData->hInformOnAppStart );
311 lpLData->hInformOnAppStart = 0;
315 if( lphDeath != NULL )
317 if( lpLData->hInformOnAppDeath == 0 )
319 DPLAYX_ReleaseSemaphore();
320 return FALSE;
323 *lphDeath = lpLData->hInformOnAppDeath;
325 if( bClearSetHandles )
327 CloseHandle( lpLData->hInformOnAppDeath );
328 lpLData->hInformOnAppDeath = 0;
332 if( lphConnRead != NULL )
334 if( lpLData->hInformOnSettingRead == 0 )
336 DPLAYX_ReleaseSemaphore();
337 return FALSE;
340 *lphConnRead = lpLData->hInformOnSettingRead;
342 if( bClearSetHandles )
344 CloseHandle( lpLData->hInformOnSettingRead );
345 lpLData->hInformOnSettingRead = 0;
349 DPLAYX_ReleaseSemaphore();
351 return TRUE;
354 /***************************************************************************
355 * Called to initialize the global data. This will only be used on the
356 * loading of the dll
357 ***************************************************************************/
358 BOOL DPLAYX_ConstructData(void)
360 SECURITY_ATTRIBUTES s_attrib;
361 BOOL bInitializeSharedMemory = FALSE;
362 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
363 HANDLE hInformOnStart;
365 TRACE( "DPLAYX dll loaded - construct called\n" );
367 /* Create a semaphore to block access to DPLAYX global data structs */
369 s_attrib.bInheritHandle = TRUE;
370 s_attrib.lpSecurityDescriptor = NULL;
371 s_attrib.nLength = sizeof(s_attrib);
373 hDplayxSema = CreateSemaphoreA( &s_attrib, 0, 1, lpszDplayxSemaName );
375 /* First instance creates the semaphore. Others just use it */
376 if( GetLastError() == ERROR_SUCCESS )
378 TRACE( "Semaphore %p created\n", hDplayxSema );
380 /* The semaphore creator will also build the shared memory */
381 bInitializeSharedMemory = TRUE;
383 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
385 TRACE( "Found semaphore handle %p\n", hDplayxSema );
386 DPLAYX_AcquireSemaphore();
388 else
390 ERR( ": semaphore error %d\n", GetLastError() );
391 return FALSE;
394 SetLastError( ERROR_SUCCESS );
396 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
397 &s_attrib,
398 PAGE_READWRITE | SEC_COMMIT,
400 dwTotalSharedSize,
401 lpszDplayxFileMapping );
403 if( GetLastError() == ERROR_SUCCESS )
405 TRACE( "File mapped %p created\n", hDplayxSharedMem );
407 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
409 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
411 else
413 ERR( ": unable to create shared memory (%d)\n", GetLastError() );
414 DPLAYX_ReleaseSemaphore();
415 return FALSE;
418 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
419 FILE_MAP_WRITE,
420 0, 0, 0, lpDesiredMemoryMapStart );
422 if( lpSharedStaticData == NULL )
424 ERR( ": unable to map static data into process memory space (%d)\n",
425 GetLastError() );
426 DPLAYX_ReleaseSemaphore();
427 return FALSE;
429 else
431 if( lpDesiredMemoryMapStart == lpSharedStaticData )
433 TRACE( "File mapped to %p\n", lpSharedStaticData );
435 else
437 /* Presently the shared data structures use pointers. If the
438 * files are not mapped into the same area, the pointers will no
439 * longer make any sense :(
440 * FIXME: In the future make the shared data structures have some
441 * sort of fixup to make them independent between data spaces.
442 * This will also require a rework of the session data stuff.
444 ERR( "File mapped to %p (not %p). Expect failure\n",
445 lpSharedStaticData, lpDesiredMemoryMapStart );
449 /* Dynamic area starts just after the static area */
450 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
452 /* FIXME: Crude hack */
453 lobbyData = lpSharedStaticData;
454 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
456 /* Initialize shared data segments. */
457 if( bInitializeSharedMemory )
459 UINT i;
461 TRACE( "Initializing shared memory\n" );
463 /* Set all lobbies to be "empty" */
464 for( i=0; i < numSupportedLobbies; i++ )
466 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
469 /* Set all sessions to be "empty" */
470 for( i=0; i < numSupportedSessions; i++ )
472 sessionData[i].dwSize = 0;
475 /* Zero out the dynamic area */
476 ZeroMemory( lpMemArea, dwDynamicSharedSize );
478 /* Just for fun sync the whole data area */
479 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
482 DPLAYX_ReleaseSemaphore();
484 /* Everything was created correctly. Signal the lobby client that
485 * we started up correctly
487 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
488 hInformOnStart
491 BOOL bSuccess;
492 bSuccess = SetEvent( hInformOnStart );
493 TRACE( "Signalling lobby app start event %p %s\n",
494 hInformOnStart, bSuccess ? "succeed" : "failed" );
496 /* Close out handle */
497 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
500 return TRUE;
503 /***************************************************************************
504 * Called to destroy all global data. This will only be used on the
505 * unloading of the dll
506 ***************************************************************************/
507 BOOL DPLAYX_DestructData(void)
509 HANDLE hInformOnDeath;
511 TRACE( "DPLAYX dll unloaded - destruct called\n" );
513 /* If required, inform that this app is dying */
514 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
515 hInformOnDeath
518 BOOL bSuccess;
519 bSuccess = SetEvent( hInformOnDeath );
520 TRACE( "Signalling lobby app death event %p %s\n",
521 hInformOnDeath, bSuccess ? "succeed" : "failed" );
523 /* Close out handle */
524 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
527 /* DO CLEAN UP (LAST) */
529 /* Delete the semaphore */
530 CloseHandle( hDplayxSema );
532 /* Delete shared memory file mapping */
533 UnmapViewOfFile( lpSharedStaticData );
534 CloseHandle( hDplayxSharedMem );
536 return FALSE;
540 /* Assumption: Enough contiguous space was allocated at dest */
541 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src )
543 BYTE* lpStartOfFreeSpace;
545 *dest = *src;
547 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
549 /* Copy the LPDPSESSIONDESC2 structure if it exists */
550 if( src->lpSessionDesc )
552 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
553 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
554 *dest->lpSessionDesc = *src->lpSessionDesc;
556 /* Session names may or may not exist */
557 if( src->lpSessionDesc->u1.lpszSessionNameA )
559 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
560 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
561 lpStartOfFreeSpace +=
562 strlen( dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
565 if( src->lpSessionDesc->u2.lpszPasswordA )
567 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
568 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
569 lpStartOfFreeSpace +=
570 strlen( dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
574 /* DPNAME structure is optional */
575 if( src->lpPlayerName )
577 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
578 lpStartOfFreeSpace += sizeof( DPNAME );
579 *dest->lpPlayerName = *src->lpPlayerName;
581 if( src->lpPlayerName->u1.lpszShortNameA )
583 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
584 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
585 lpStartOfFreeSpace +=
586 strlen( dest->lpPlayerName->u1.lpszShortNameA ) + 1;
589 if( src->lpPlayerName->u2.lpszLongNameA )
591 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
592 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
593 lpStartOfFreeSpace +=
594 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
599 /* Copy address if it exists */
600 if( src->lpAddress )
602 dest->lpAddress = lpStartOfFreeSpace;
603 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
604 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
608 /* Assumption: Enough contiguous space was allocated at dest */
609 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src )
611 BYTE* lpStartOfFreeSpace;
613 *dest = *src;
615 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
617 /* Copy the LPDPSESSIONDESC2 structure if it exists */
618 if( src->lpSessionDesc )
620 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
621 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
622 *dest->lpSessionDesc = *src->lpSessionDesc;
624 /* Session names may or may not exist */
625 if( src->lpSessionDesc->u1.lpszSessionName )
627 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionName );
628 dest->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
629 lpStartOfFreeSpace += sizeof(WCHAR) *
630 ( strlenW( dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
633 if( src->lpSessionDesc->u2.lpszPassword )
635 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
636 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
637 lpStartOfFreeSpace += sizeof(WCHAR) *
638 ( strlenW( dest->lpSessionDesc->u2.lpszPassword ) + 1 );
642 /* DPNAME structure is optional */
643 if( src->lpPlayerName )
645 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
646 lpStartOfFreeSpace += sizeof( DPNAME );
647 *dest->lpPlayerName = *src->lpPlayerName;
649 if( src->lpPlayerName->u1.lpszShortName )
651 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
652 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
653 lpStartOfFreeSpace += sizeof(WCHAR) *
654 ( strlenW( dest->lpPlayerName->u1.lpszShortName ) + 1 );
657 if( src->lpPlayerName->u2.lpszLongName )
659 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
660 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
661 lpStartOfFreeSpace += sizeof(WCHAR) *
662 ( strlenW( dest->lpPlayerName->u2.lpszLongName ) + 1 );
667 /* Copy address if it exists */
668 if( src->lpAddress )
670 dest->lpAddress = lpStartOfFreeSpace;
671 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
672 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
677 static DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpConn )
679 DWORD dwTotalSize = sizeof( DPLCONNECTION );
681 /* Just a safety check */
682 if( lpConn == NULL )
684 ERR( "lpConn is NULL\n" );
685 return 0;
688 if( lpConn->lpSessionDesc != NULL )
690 dwTotalSize += sizeof( DPSESSIONDESC2 );
692 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
694 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
697 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
699 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
703 if( lpConn->lpPlayerName != NULL )
705 dwTotalSize += sizeof( DPNAME );
707 if( lpConn->lpPlayerName->u1.lpszShortNameA )
709 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
712 if( lpConn->lpPlayerName->u2.lpszLongNameA )
714 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
719 dwTotalSize += lpConn->dwAddressSize;
721 return dwTotalSize;
724 static DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpConn )
726 DWORD dwTotalSize = sizeof( DPLCONNECTION );
728 /* Just a safety check */
729 if( lpConn == NULL )
731 ERR( "lpConn is NULL\n" );
732 return 0;
735 if( lpConn->lpSessionDesc != NULL )
737 dwTotalSize += sizeof( DPSESSIONDESC2 );
739 if( lpConn->lpSessionDesc->u1.lpszSessionName )
741 dwTotalSize += sizeof( WCHAR ) *
742 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
745 if( lpConn->lpSessionDesc->u2.lpszPassword )
747 dwTotalSize += sizeof( WCHAR ) *
748 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
752 if( lpConn->lpPlayerName != NULL )
754 dwTotalSize += sizeof( DPNAME );
756 if( lpConn->lpPlayerName->u1.lpszShortName )
758 dwTotalSize += sizeof( WCHAR ) *
759 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
762 if( lpConn->lpPlayerName->u2.lpszLongName )
764 dwTotalSize += sizeof( WCHAR ) *
765 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
770 dwTotalSize += lpConn->dwAddressSize;
772 return dwTotalSize;
775 HRESULT DPLAYX_GetConnectionSettingsA
776 ( DWORD dwAppID,
777 LPVOID lpData,
778 LPDWORD lpdwDataSize )
780 LPDPLAYX_LOBBYDATA lpDplData;
781 DWORD dwRequiredDataSize = 0;
782 HANDLE hInformOnSettingRead;
784 DPLAYX_AcquireSemaphore();
786 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
788 DPLAYX_ReleaseSemaphore();
790 TRACE( "Application 0x%08x is not lobbied\n", dwAppID );
791 return DPERR_NOTLOBBIED;
794 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
796 /* Do they want to know the required buffer size or is the provided buffer
797 * big enough?
799 if ( ( lpData == NULL ) ||
800 ( *lpdwDataSize < dwRequiredDataSize )
803 DPLAYX_ReleaseSemaphore();
805 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
807 return DPERR_BUFFERTOOSMALL;
810 DPLAYX_CopyConnStructA( lpData, lpDplData->lpConn );
812 DPLAYX_ReleaseSemaphore();
814 /* They have gotten the information - signal the event if required */
815 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
816 hInformOnSettingRead
819 BOOL bSuccess;
820 bSuccess = SetEvent( hInformOnSettingRead );
821 TRACE( "Signalling setting read event %p %s\n",
822 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
824 /* Close out handle */
825 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
828 return DP_OK;
831 HRESULT DPLAYX_GetConnectionSettingsW
832 ( DWORD dwAppID,
833 LPVOID lpData,
834 LPDWORD lpdwDataSize )
836 LPDPLAYX_LOBBYDATA lpDplData;
837 DWORD dwRequiredDataSize = 0;
838 HANDLE hInformOnSettingRead;
840 DPLAYX_AcquireSemaphore();
842 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
844 DPLAYX_ReleaseSemaphore();
845 return DPERR_NOTLOBBIED;
848 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
850 /* Do they want to know the required buffer size or is the provided buffer
851 * big enough?
853 if ( ( lpData == NULL ) ||
854 ( *lpdwDataSize < dwRequiredDataSize )
857 DPLAYX_ReleaseSemaphore();
859 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
861 return DPERR_BUFFERTOOSMALL;
864 DPLAYX_CopyConnStructW( lpData, lpDplData->lpConn );
866 DPLAYX_ReleaseSemaphore();
868 /* They have gotten the information - signal the event if required */
869 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
870 hInformOnSettingRead
873 BOOL bSuccess;
874 bSuccess = SetEvent( hInformOnSettingRead );
875 TRACE( "Signalling setting read event %p %s\n",
876 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
878 /* Close out handle */
879 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
882 return DP_OK;
885 /* Store the structure into the shared data structure. Ensure that allocs for
886 * variable length strings come from the shared data structure.
887 * FIXME: We need to free information as well.
889 HRESULT DPLAYX_SetConnectionSettingsA
890 ( DWORD dwFlags,
891 DWORD dwAppID,
892 const DPLCONNECTION *lpConn )
894 LPDPLAYX_LOBBYDATA lpDplData;
896 /* Parameter check */
897 if( dwFlags || !lpConn )
899 ERR("invalid parameters.\n");
900 return DPERR_INVALIDPARAMS;
903 /* Store information */
904 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
906 ERR(": old/new DPLCONNECTION type? Size=%08x\n", lpConn->dwSize );
908 return DPERR_INVALIDPARAMS;
911 DPLAYX_AcquireSemaphore();
913 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
915 DPLAYX_ReleaseSemaphore();
917 return DPERR_NOTLOBBIED;
920 if( (!lpConn->lpSessionDesc ) ||
921 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
924 DPLAYX_ReleaseSemaphore();
926 ERR("DPSESSIONDESC passed in? Size=%u\n",
927 lpConn->lpSessionDesc?lpConn->lpSessionDesc->dwSize:0 );
929 return DPERR_INVALIDPARAMS;
932 /* Free the existing memory */
933 DPLAYX_PrivHeapFree( lpDplData->lpConn );
935 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
936 DPLAYX_SizeOfLobbyDataA( lpConn ) );
938 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
941 DPLAYX_ReleaseSemaphore();
943 /* FIXME: Send a message - I think */
945 return DP_OK;
948 /* Store the structure into the shared data structure. Ensure that allocs for
949 * variable length strings come from the shared data structure.
950 * FIXME: We need to free information as well
952 HRESULT DPLAYX_SetConnectionSettingsW
953 ( DWORD dwFlags,
954 DWORD dwAppID,
955 const DPLCONNECTION *lpConn )
957 LPDPLAYX_LOBBYDATA lpDplData;
959 /* Parameter check */
960 if( dwFlags || !lpConn )
962 ERR("invalid parameters.\n");
963 return DPERR_INVALIDPARAMS;
966 /* Store information */
967 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
969 ERR(": old/new DPLCONNECTION type? Size=%u\n", lpConn->dwSize );
971 return DPERR_INVALIDPARAMS;
974 DPLAYX_AcquireSemaphore();
976 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
978 DPLAYX_ReleaseSemaphore();
980 return DPERR_NOTLOBBIED;
983 /* Free the existing memory */
984 DPLAYX_PrivHeapFree( lpDplData->lpConn );
986 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
987 DPLAYX_SizeOfLobbyDataW( lpConn ) );
989 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
992 DPLAYX_ReleaseSemaphore();
994 /* FIXME: Send a message - I think */
996 return DP_OK;
999 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1001 LPDPLAYX_LOBBYDATA lpLobbyData;
1003 DPLAYX_AcquireSemaphore();
1005 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1007 DPLAYX_ReleaseSemaphore();
1008 return FALSE;
1011 lpLobbyData->bWaitForConnectionSettings = bWait;
1013 DPLAYX_ReleaseSemaphore();
1015 return TRUE;
1018 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1020 UINT i;
1021 BOOL bFound = FALSE;
1023 DPLAYX_AcquireSemaphore();
1025 for( i=0; i < numSupportedLobbies; i++ )
1027 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1028 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1031 bFound = TRUE;
1032 break;
1036 DPLAYX_ReleaseSemaphore();
1038 return bFound;
1041 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1043 LPDPLAYX_LOBBYDATA lpLobbyData;
1045 DPLAYX_AcquireSemaphore();
1047 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1049 DPLAYX_ReleaseSemaphore();
1050 return FALSE;
1053 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1055 DPLAYX_ReleaseSemaphore();
1057 return TRUE;
1060 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1061 with the correct string printed in the case where the HRESULT is not
1062 known. You will just get the last hr passed in. This can change
1063 over time if this method is used a lot :) */
1064 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1066 static char szTempStr[12];
1068 switch (hr)
1070 case DP_OK:
1071 return "DP_OK";
1072 case DPERR_ALREADYINITIALIZED:
1073 return "DPERR_ALREADYINITIALIZED";
1074 case DPERR_ACCESSDENIED:
1075 return "DPERR_ACCESSDENIED";
1076 case DPERR_ACTIVEPLAYERS:
1077 return "DPERR_ACTIVEPLAYERS";
1078 case DPERR_BUFFERTOOSMALL:
1079 return "DPERR_BUFFERTOOSMALL";
1080 case DPERR_CANTADDPLAYER:
1081 return "DPERR_CANTADDPLAYER";
1082 case DPERR_CANTCREATEGROUP:
1083 return "DPERR_CANTCREATEGROUP";
1084 case DPERR_CANTCREATEPLAYER:
1085 return "DPERR_CANTCREATEPLAYER";
1086 case DPERR_CANTCREATESESSION:
1087 return "DPERR_CANTCREATESESSION";
1088 case DPERR_CAPSNOTAVAILABLEYET:
1089 return "DPERR_CAPSNOTAVAILABLEYET";
1090 case DPERR_EXCEPTION:
1091 return "DPERR_EXCEPTION";
1092 case DPERR_GENERIC:
1093 return "DPERR_GENERIC";
1094 case DPERR_INVALIDFLAGS:
1095 return "DPERR_INVALIDFLAGS";
1096 case DPERR_INVALIDOBJECT:
1097 return "DPERR_INVALIDOBJECT";
1098 case DPERR_INVALIDPARAMS:
1099 return "DPERR_INVALIDPARAMS";
1100 case DPERR_INVALIDPLAYER:
1101 return "DPERR_INVALIDPLAYER";
1102 case DPERR_INVALIDGROUP:
1103 return "DPERR_INVALIDGROUP";
1104 case DPERR_NOCAPS:
1105 return "DPERR_NOCAPS";
1106 case DPERR_NOCONNECTION:
1107 return "DPERR_NOCONNECTION";
1108 case DPERR_OUTOFMEMORY:
1109 return "DPERR_OUTOFMEMORY";
1110 case DPERR_NOMESSAGES:
1111 return "DPERR_NOMESSAGES";
1112 case DPERR_NONAMESERVERFOUND:
1113 return "DPERR_NONAMESERVERFOUND";
1114 case DPERR_NOPLAYERS:
1115 return "DPERR_NOPLAYERS";
1116 case DPERR_NOSESSIONS:
1117 return "DPERR_NOSESSIONS";
1118 case DPERR_PENDING:
1119 return "DPERR_PENDING";
1120 case DPERR_SENDTOOBIG:
1121 return "DPERR_SENDTOOBIG";
1122 case DPERR_TIMEOUT:
1123 return "DPERR_TIMEOUT";
1124 case DPERR_UNAVAILABLE:
1125 return "DPERR_UNAVAILABLE";
1126 case DPERR_UNSUPPORTED:
1127 return "DPERR_UNSUPPORTED";
1128 case DPERR_BUSY:
1129 return "DPERR_BUSY";
1130 case DPERR_USERCANCEL:
1131 return "DPERR_USERCANCEL";
1132 case DPERR_NOINTERFACE:
1133 return "DPERR_NOINTERFACE";
1134 case DPERR_CANNOTCREATESERVER:
1135 return "DPERR_CANNOTCREATESERVER";
1136 case DPERR_PLAYERLOST:
1137 return "DPERR_PLAYERLOST";
1138 case DPERR_SESSIONLOST:
1139 return "DPERR_SESSIONLOST";
1140 case DPERR_UNINITIALIZED:
1141 return "DPERR_UNINITIALIZED";
1142 case DPERR_NONEWPLAYERS:
1143 return "DPERR_NONEWPLAYERS";
1144 case DPERR_INVALIDPASSWORD:
1145 return "DPERR_INVALIDPASSWORD";
1146 case DPERR_CONNECTING:
1147 return "DPERR_CONNECTING";
1148 case DPERR_CONNECTIONLOST:
1149 return "DPERR_CONNECTIONLOST";
1150 case DPERR_UNKNOWNMESSAGE:
1151 return "DPERR_UNKNOWNMESSAGE";
1152 case DPERR_CANCELFAILED:
1153 return "DPERR_CANCELFAILED";
1154 case DPERR_INVALIDPRIORITY:
1155 return "DPERR_INVALIDPRIORITY";
1156 case DPERR_NOTHANDLED:
1157 return "DPERR_NOTHANDLED";
1158 case DPERR_CANCELLED:
1159 return "DPERR_CANCELLED";
1160 case DPERR_ABORTED:
1161 return "DPERR_ABORTED";
1162 case DPERR_BUFFERTOOLARGE:
1163 return "DPERR_BUFFERTOOLARGE";
1164 case DPERR_CANTCREATEPROCESS:
1165 return "DPERR_CANTCREATEPROCESS";
1166 case DPERR_APPNOTSTARTED:
1167 return "DPERR_APPNOTSTARTED";
1168 case DPERR_INVALIDINTERFACE:
1169 return "DPERR_INVALIDINTERFACE";
1170 case DPERR_NOSERVICEPROVIDER:
1171 return "DPERR_NOSERVICEPROVIDER";
1172 case DPERR_UNKNOWNAPPLICATION:
1173 return "DPERR_UNKNOWNAPPLICATION";
1174 case DPERR_NOTLOBBIED:
1175 return "DPERR_NOTLOBBIED";
1176 case DPERR_SERVICEPROVIDERLOADED:
1177 return "DPERR_SERVICEPROVIDERLOADED";
1178 case DPERR_ALREADYREGISTERED:
1179 return "DPERR_ALREADYREGISTERED";
1180 case DPERR_NOTREGISTERED:
1181 return "DPERR_NOTREGISTERED";
1182 case DPERR_AUTHENTICATIONFAILED:
1183 return "DPERR_AUTHENTICATIONFAILED";
1184 case DPERR_CANTLOADSSPI:
1185 return "DPERR_CANTLOADSSPI";
1186 case DPERR_ENCRYPTIONFAILED:
1187 return "DPERR_ENCRYPTIONFAILED";
1188 case DPERR_SIGNFAILED:
1189 return "DPERR_SIGNFAILED";
1190 case DPERR_CANTLOADSECURITYPACKAGE:
1191 return "DPERR_CANTLOADSECURITYPACKAGE";
1192 case DPERR_ENCRYPTIONNOTSUPPORTED:
1193 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1194 case DPERR_CANTLOADCAPI:
1195 return "DPERR_CANTLOADCAPI";
1196 case DPERR_NOTLOGGEDIN:
1197 return "DPERR_NOTLOGGEDIN";
1198 case DPERR_LOGONDENIED:
1199 return "DPERR_LOGONDENIED";
1200 default:
1201 /* For errors not in the list, return HRESULT as a string
1202 This part is not thread safe */
1203 WARN( "Unknown error 0x%08x\n", hr );
1204 wsprintfA( szTempStr, "0x%08x", hr );
1205 return szTempStr;