win32u: Move NtUserTranslateMessage implementation from user32.
[wine.git] / dlls / dplayx / dplayx_global.c
blobec62d273cb4b0bca9ac053e387ca22c8e112a302
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"
42 #include "wingdi.h"
43 #include "winuser.h"
45 #include "dplayx_global.h"
46 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
48 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
50 /* FIXME: Need to do all that fun other dll referencing type of stuff */
52 /* Static data for all processes */
53 static const char lpszDplayxSemaName[] = "WINE_DPLAYX_SM";
54 static HANDLE hDplayxSema;
56 static const char lpszDplayxFileMapping[] = "WINE_DPLAYX_FM";
57 static HANDLE hDplayxSharedMem;
59 static LPVOID lpSharedStaticData = NULL;
62 #define DPLAYX_AcquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
63 WaitForSingleObject( hDplayxSema, INFINITE );\
64 TRACE( "Through wait\n" )
66 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
67 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
70 /* HACK for simple global data right now */
71 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
72 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
73 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
76 /* FIXME: Is there no easier way? */
78 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
79 * Each block has 4 bytes which are 0 unless used */
80 #define dwBlockSize 512
81 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
83 typedef struct
85 BOOL used;
86 BYTE data[dwBlockSize - sizeof(BOOL)];
87 } DPLAYX_MEM_SLICE;
88 C_ASSERT(sizeof(DPLAYX_MEM_SLICE) == dwBlockSize);
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 = CONTAINING_RECORD(addr, DPLAYX_MEM_SLICE, data); /* Find block header */
104 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
106 lpMemArea[ dwBlockUsed ].used = FALSE;
109 static LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
111 LPVOID lpvArea = NULL;
112 UINT uBlockUsed;
114 if( size > (dwBlockSize - sizeof(BOOL)) )
116 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
117 size = dwBlockSize - sizeof(BOOL);
120 /* Find blank area */
121 uBlockUsed = 0;
122 while( uBlockUsed < dwMaxBlock && lpMemArea[ uBlockUsed ].used ) { uBlockUsed++; }
124 if( uBlockUsed < dwMaxBlock )
126 /* Set the area used */
127 lpMemArea[ uBlockUsed ].used = TRUE;
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 ]; */
178 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
180 ZeroMemory( lpData, sizeof( *lpData ) );
183 /* NOTE: This must be called with the semaphore acquired.
184 * TRUE/FALSE with a pointer to its data returned. Pointer data is
185 * is only valid if TRUE is returned.
187 static BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
189 UINT i;
191 *lplpDplData = NULL;
193 if( dwAppID == 0 )
195 dwAppID = GetCurrentProcessId();
196 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
199 for( i=0; i < numSupportedLobbies; i++ )
201 if( lobbyData[ i ].dwAppID == dwAppID )
203 /* This process is lobbied */
204 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
205 *lplpDplData = &lobbyData[ i ];
206 return TRUE;
210 return FALSE;
213 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
214 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
216 UINT i;
218 /* 0 is the marker for unused application data slots */
219 if( dwAppID == 0 )
221 return FALSE;
224 DPLAYX_AcquireSemaphore();
226 /* Find an empty space in the list and insert the data */
227 for( i=0; i < numSupportedLobbies; i++ )
229 if( lobbyData[ i ].dwAppID == 0 )
231 /* This process is now lobbied */
232 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
233 i, dwAppID, GetCurrentProcessId() );
235 lobbyData[ i ].dwAppID = dwAppID;
236 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
238 /* FIXME: Where is the best place for this? In interface or here? */
239 lobbyData[ i ].hInformOnAppStart = 0;
240 lobbyData[ i ].hInformOnAppDeath = 0;
241 lobbyData[ i ].hInformOnSettingRead = 0;
243 DPLAYX_ReleaseSemaphore();
244 return TRUE;
248 ERR( "No empty lobbies\n" );
250 DPLAYX_ReleaseSemaphore();
251 return FALSE;
254 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
255 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
257 LPDPLAYX_LOBBYDATA lpLData;
259 /* Need to explicitly give lobby application. Can't set for yourself */
260 if( dwAppID == 0 )
262 return FALSE;
265 DPLAYX_AcquireSemaphore();
267 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
269 DPLAYX_ReleaseSemaphore();
270 return FALSE;
273 lpLData->hInformOnAppStart = hStart;
274 lpLData->hInformOnAppDeath = hDeath;
275 lpLData->hInformOnSettingRead = hConnRead;
277 DPLAYX_ReleaseSemaphore();
279 return TRUE;
282 static BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
283 LPHANDLE lphDeath,
284 LPHANDLE lphConnRead,
285 BOOL bClearSetHandles )
287 LPDPLAYX_LOBBYDATA lpLData;
289 DPLAYX_AcquireSemaphore();
291 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
293 DPLAYX_ReleaseSemaphore();
294 return FALSE;
297 if( lphStart != NULL )
299 if( lpLData->hInformOnAppStart == 0 )
301 DPLAYX_ReleaseSemaphore();
302 return FALSE;
305 *lphStart = lpLData->hInformOnAppStart;
307 if( bClearSetHandles )
309 CloseHandle( lpLData->hInformOnAppStart );
310 lpLData->hInformOnAppStart = 0;
314 if( lphDeath != NULL )
316 if( lpLData->hInformOnAppDeath == 0 )
318 DPLAYX_ReleaseSemaphore();
319 return FALSE;
322 *lphDeath = lpLData->hInformOnAppDeath;
324 if( bClearSetHandles )
326 CloseHandle( lpLData->hInformOnAppDeath );
327 lpLData->hInformOnAppDeath = 0;
331 if( lphConnRead != NULL )
333 if( lpLData->hInformOnSettingRead == 0 )
335 DPLAYX_ReleaseSemaphore();
336 return FALSE;
339 *lphConnRead = lpLData->hInformOnSettingRead;
341 if( bClearSetHandles )
343 CloseHandle( lpLData->hInformOnSettingRead );
344 lpLData->hInformOnSettingRead = 0;
348 DPLAYX_ReleaseSemaphore();
350 return TRUE;
353 /***************************************************************************
354 * Called to initialize the global data. This will only be used on the
355 * loading of the dll
356 ***************************************************************************/
357 BOOL DPLAYX_ConstructData(void)
359 SECURITY_ATTRIBUTES s_attrib;
360 BOOL bInitializeSharedMemory = FALSE;
361 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
362 HANDLE hInformOnStart;
364 TRACE( "DPLAYX dll loaded - construct called\n" );
366 /* Create a semaphore to block access to DPLAYX global data structs */
368 s_attrib.bInheritHandle = TRUE;
369 s_attrib.lpSecurityDescriptor = NULL;
370 s_attrib.nLength = sizeof(s_attrib);
372 hDplayxSema = CreateSemaphoreA( &s_attrib, 0, 1, lpszDplayxSemaName );
374 /* First instance creates the semaphore. Others just use it */
375 if( GetLastError() == ERROR_SUCCESS )
377 TRACE( "Semaphore %p created\n", hDplayxSema );
379 /* The semaphore creator will also build the shared memory */
380 bInitializeSharedMemory = TRUE;
382 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
384 TRACE( "Found semaphore handle %p\n", hDplayxSema );
385 DPLAYX_AcquireSemaphore();
387 else
389 ERR( ": semaphore error %ld\n", GetLastError() );
390 return FALSE;
393 SetLastError( ERROR_SUCCESS );
395 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
396 &s_attrib,
397 PAGE_READWRITE | SEC_COMMIT,
399 dwTotalSharedSize,
400 lpszDplayxFileMapping );
402 if( GetLastError() == ERROR_SUCCESS )
404 TRACE( "File mapped %p created\n", hDplayxSharedMem );
406 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
408 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
410 else
412 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
413 DPLAYX_ReleaseSemaphore();
414 return FALSE;
417 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
418 FILE_MAP_WRITE,
419 0, 0, 0, lpDesiredMemoryMapStart );
421 if( lpSharedStaticData == NULL && GetLastError() == ERROR_INVALID_ADDRESS )
423 /* We couldn't map the data where we wanted. Try again, allowing any
424 * location. */
425 lpSharedStaticData = MapViewOfFile( hDplayxSharedMem,
426 FILE_MAP_WRITE,
427 0, 0, 0 );
430 if( lpSharedStaticData == NULL )
432 ERR( ": unable to map static data into process memory space (%ld)\n",
433 GetLastError() );
434 DPLAYX_ReleaseSemaphore();
435 return FALSE;
437 else
439 if( lpDesiredMemoryMapStart == lpSharedStaticData )
441 TRACE( "File mapped to %p\n", lpSharedStaticData );
443 else
445 /* Presently the shared data structures use pointers. If the
446 * files are not mapped into the same area, the pointers will no
447 * longer make any sense :(
448 * FIXME: In the future make the shared data structures have some
449 * sort of fixup to make them independent between data spaces.
450 * This will also require a rework of the session data stuff.
452 ERR( "File mapped to %p (not %p). Expect failure\n",
453 lpSharedStaticData, lpDesiredMemoryMapStart );
457 /* Dynamic area starts just after the static area */
458 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
460 /* FIXME: Crude hack */
461 lobbyData = lpSharedStaticData;
462 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
464 /* Initialize shared data segments. */
465 if( bInitializeSharedMemory )
467 UINT i;
469 TRACE( "Initializing shared memory\n" );
471 /* Set all lobbies to be "empty" */
472 for( i=0; i < numSupportedLobbies; i++ )
474 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
477 /* Set all sessions to be "empty" */
478 for( i=0; i < numSupportedSessions; i++ )
480 sessionData[i].dwSize = 0;
483 /* Zero out the dynamic area */
484 ZeroMemory( lpMemArea, dwDynamicSharedSize );
486 /* Just for fun sync the whole data area */
487 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
490 DPLAYX_ReleaseSemaphore();
492 /* Everything was created correctly. Signal the lobby client that
493 * we started up correctly
495 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
496 hInformOnStart
499 BOOL bSuccess;
500 bSuccess = SetEvent( hInformOnStart );
501 TRACE( "Signalling lobby app start event %p %s\n",
502 hInformOnStart, bSuccess ? "succeed" : "failed" );
504 /* Close out handle */
505 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
508 return TRUE;
511 /***************************************************************************
512 * Called to destroy all global data. This will only be used on the
513 * unloading of the dll
514 ***************************************************************************/
515 BOOL DPLAYX_DestructData(void)
517 HANDLE hInformOnDeath;
519 TRACE( "DPLAYX dll unloaded - destruct called\n" );
521 /* If required, inform that this app is dying */
522 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
523 hInformOnDeath
526 BOOL bSuccess;
527 bSuccess = SetEvent( hInformOnDeath );
528 TRACE( "Signalling lobby app death event %p %s\n",
529 hInformOnDeath, bSuccess ? "succeed" : "failed" );
531 /* Close out handle */
532 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
535 /* DO CLEAN UP (LAST) */
537 /* Delete the semaphore */
538 CloseHandle( hDplayxSema );
540 /* Delete shared memory file mapping */
541 UnmapViewOfFile( lpSharedStaticData );
542 CloseHandle( hDplayxSharedMem );
544 return FALSE;
548 /* Assumption: Enough contiguous space was allocated at dest */
549 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, const DPLCONNECTION *src )
551 BYTE* lpStartOfFreeSpace;
553 *dest = *src;
555 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
557 /* Copy the LPDPSESSIONDESC2 structure if it exists */
558 if( src->lpSessionDesc )
560 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
561 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
562 *dest->lpSessionDesc = *src->lpSessionDesc;
564 /* Session names may or may not exist */
565 if( src->lpSessionDesc->u1.lpszSessionNameA )
567 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
568 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
569 lpStartOfFreeSpace +=
570 strlen( dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
573 if( src->lpSessionDesc->u2.lpszPasswordA )
575 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
576 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
577 lpStartOfFreeSpace +=
578 strlen( dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
582 /* DPNAME structure is optional */
583 if( src->lpPlayerName )
585 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
586 lpStartOfFreeSpace += sizeof( DPNAME );
587 *dest->lpPlayerName = *src->lpPlayerName;
589 if( src->lpPlayerName->u1.lpszShortNameA )
591 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
592 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
593 lpStartOfFreeSpace +=
594 strlen( dest->lpPlayerName->u1.lpszShortNameA ) + 1;
597 if( src->lpPlayerName->u2.lpszLongNameA )
599 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
600 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
601 lpStartOfFreeSpace +=
602 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
607 /* Copy address if it exists */
608 if( src->lpAddress )
610 dest->lpAddress = lpStartOfFreeSpace;
611 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
612 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
616 /* Assumption: Enough contiguous space was allocated at dest */
617 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, const DPLCONNECTION *src )
619 BYTE* lpStartOfFreeSpace;
621 *dest = *src;
623 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
625 /* Copy the LPDPSESSIONDESC2 structure if it exists */
626 if( src->lpSessionDesc )
628 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
629 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
630 *dest->lpSessionDesc = *src->lpSessionDesc;
632 /* Session names may or may not exist */
633 if( src->lpSessionDesc->u1.lpszSessionName )
635 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionName );
636 dest->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
637 lpStartOfFreeSpace += sizeof(WCHAR) *
638 ( lstrlenW( dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
641 if( src->lpSessionDesc->u2.lpszPassword )
643 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
644 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
645 lpStartOfFreeSpace += sizeof(WCHAR) *
646 ( lstrlenW( dest->lpSessionDesc->u2.lpszPassword ) + 1 );
650 /* DPNAME structure is optional */
651 if( src->lpPlayerName )
653 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
654 lpStartOfFreeSpace += sizeof( DPNAME );
655 *dest->lpPlayerName = *src->lpPlayerName;
657 if( src->lpPlayerName->u1.lpszShortName )
659 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
660 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
661 lpStartOfFreeSpace += sizeof(WCHAR) *
662 ( lstrlenW( dest->lpPlayerName->u1.lpszShortName ) + 1 );
665 if( src->lpPlayerName->u2.lpszLongName )
667 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
668 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
669 lpStartOfFreeSpace += sizeof(WCHAR) *
670 ( lstrlenW( dest->lpPlayerName->u2.lpszLongName ) + 1 );
675 /* Copy address if it exists */
676 if( src->lpAddress )
678 dest->lpAddress = lpStartOfFreeSpace;
679 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
680 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
685 static DWORD DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION *lpConn )
687 DWORD dwTotalSize = sizeof( DPLCONNECTION );
689 /* Just a safety check */
690 if( lpConn == NULL )
692 ERR( "lpConn is NULL\n" );
693 return 0;
696 if( lpConn->lpSessionDesc != NULL )
698 dwTotalSize += sizeof( DPSESSIONDESC2 );
700 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
702 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
705 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
707 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
711 if( lpConn->lpPlayerName != NULL )
713 dwTotalSize += sizeof( DPNAME );
715 if( lpConn->lpPlayerName->u1.lpszShortNameA )
717 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
720 if( lpConn->lpPlayerName->u2.lpszLongNameA )
722 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
727 dwTotalSize += lpConn->dwAddressSize;
729 return dwTotalSize;
732 static DWORD DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION *lpConn )
734 DWORD dwTotalSize = sizeof( DPLCONNECTION );
736 /* Just a safety check */
737 if( lpConn == NULL )
739 ERR( "lpConn is NULL\n" );
740 return 0;
743 if( lpConn->lpSessionDesc != NULL )
745 dwTotalSize += sizeof( DPSESSIONDESC2 );
747 if( lpConn->lpSessionDesc->u1.lpszSessionName )
749 dwTotalSize += sizeof( WCHAR ) *
750 ( lstrlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
753 if( lpConn->lpSessionDesc->u2.lpszPassword )
755 dwTotalSize += sizeof( WCHAR ) *
756 ( lstrlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
760 if( lpConn->lpPlayerName != NULL )
762 dwTotalSize += sizeof( DPNAME );
764 if( lpConn->lpPlayerName->u1.lpszShortName )
766 dwTotalSize += sizeof( WCHAR ) *
767 ( lstrlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
770 if( lpConn->lpPlayerName->u2.lpszLongName )
772 dwTotalSize += sizeof( WCHAR ) *
773 ( lstrlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
778 dwTotalSize += lpConn->dwAddressSize;
780 return dwTotalSize;
783 HRESULT DPLAYX_GetConnectionSettingsA
784 ( DWORD dwAppID,
785 LPVOID lpData,
786 LPDWORD lpdwDataSize )
788 LPDPLAYX_LOBBYDATA lpDplData;
789 DWORD dwRequiredDataSize = 0;
790 HANDLE hInformOnSettingRead;
792 DPLAYX_AcquireSemaphore();
794 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
796 DPLAYX_ReleaseSemaphore();
798 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
799 return DPERR_NOTLOBBIED;
802 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
804 /* Do they want to know the required buffer size or is the provided buffer
805 * big enough?
807 if ( ( lpData == NULL ) ||
808 ( *lpdwDataSize < dwRequiredDataSize )
811 DPLAYX_ReleaseSemaphore();
813 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
815 return DPERR_BUFFERTOOSMALL;
818 DPLAYX_CopyConnStructA( lpData, lpDplData->lpConn );
820 DPLAYX_ReleaseSemaphore();
822 /* They have gotten the information - signal the event if required */
823 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
824 hInformOnSettingRead
827 BOOL bSuccess;
828 bSuccess = SetEvent( hInformOnSettingRead );
829 TRACE( "Signalling setting read event %p %s\n",
830 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
832 /* Close out handle */
833 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
836 return DP_OK;
839 HRESULT DPLAYX_GetConnectionSettingsW
840 ( DWORD dwAppID,
841 LPVOID lpData,
842 LPDWORD lpdwDataSize )
844 LPDPLAYX_LOBBYDATA lpDplData;
845 DWORD dwRequiredDataSize = 0;
846 HANDLE hInformOnSettingRead;
848 DPLAYX_AcquireSemaphore();
850 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
852 DPLAYX_ReleaseSemaphore();
853 return DPERR_NOTLOBBIED;
856 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
858 /* Do they want to know the required buffer size or is the provided buffer
859 * big enough?
861 if ( ( lpData == NULL ) ||
862 ( *lpdwDataSize < dwRequiredDataSize )
865 DPLAYX_ReleaseSemaphore();
867 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
869 return DPERR_BUFFERTOOSMALL;
872 DPLAYX_CopyConnStructW( lpData, lpDplData->lpConn );
874 DPLAYX_ReleaseSemaphore();
876 /* They have gotten the information - signal the event if required */
877 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
878 hInformOnSettingRead
881 BOOL bSuccess;
882 bSuccess = SetEvent( hInformOnSettingRead );
883 TRACE( "Signalling setting read event %p %s\n",
884 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
886 /* Close out handle */
887 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
890 return DP_OK;
893 /* Store the structure into the shared data structure. Ensure that allocs for
894 * variable length strings come from the shared data structure.
895 * FIXME: We need to free information as well.
897 HRESULT DPLAYX_SetConnectionSettingsA
898 ( DWORD dwFlags,
899 DWORD dwAppID,
900 const DPLCONNECTION *lpConn )
902 LPDPLAYX_LOBBYDATA lpDplData;
904 /* Parameter check */
905 if( dwFlags || !lpConn )
907 ERR("invalid parameters.\n");
908 return DPERR_INVALIDPARAMS;
911 /* Store information */
912 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
914 ERR(": old/new DPLCONNECTION type? Size=%08lx\n", lpConn->dwSize );
916 return DPERR_INVALIDPARAMS;
919 DPLAYX_AcquireSemaphore();
921 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
923 DPLAYX_ReleaseSemaphore();
925 return DPERR_NOTLOBBIED;
928 if( (!lpConn->lpSessionDesc ) ||
929 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
932 DPLAYX_ReleaseSemaphore();
934 ERR("DPSESSIONDESC passed in? Size=%lu\n",
935 lpConn->lpSessionDesc?lpConn->lpSessionDesc->dwSize:0 );
937 return DPERR_INVALIDPARAMS;
940 /* Free the existing memory */
941 DPLAYX_PrivHeapFree( lpDplData->lpConn );
943 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
944 DPLAYX_SizeOfLobbyDataA( lpConn ) );
946 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
949 DPLAYX_ReleaseSemaphore();
951 /* FIXME: Send a message - I think */
953 return DP_OK;
956 /* Store the structure into the shared data structure. Ensure that allocs for
957 * variable length strings come from the shared data structure.
958 * FIXME: We need to free information as well
960 HRESULT DPLAYX_SetConnectionSettingsW
961 ( DWORD dwFlags,
962 DWORD dwAppID,
963 const DPLCONNECTION *lpConn )
965 LPDPLAYX_LOBBYDATA lpDplData;
967 /* Parameter check */
968 if( dwFlags || !lpConn )
970 ERR("invalid parameters.\n");
971 return DPERR_INVALIDPARAMS;
974 /* Store information */
975 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
977 ERR(": old/new DPLCONNECTION type? Size=%lu\n", lpConn->dwSize );
979 return DPERR_INVALIDPARAMS;
982 DPLAYX_AcquireSemaphore();
984 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
986 DPLAYX_ReleaseSemaphore();
988 return DPERR_NOTLOBBIED;
991 /* Free the existing memory */
992 DPLAYX_PrivHeapFree( lpDplData->lpConn );
994 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
995 DPLAYX_SizeOfLobbyDataW( lpConn ) );
997 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
1000 DPLAYX_ReleaseSemaphore();
1002 /* FIXME: Send a message - I think */
1004 return DP_OK;
1007 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1009 LPDPLAYX_LOBBYDATA lpLobbyData;
1011 DPLAYX_AcquireSemaphore();
1013 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1015 DPLAYX_ReleaseSemaphore();
1016 return FALSE;
1019 lpLobbyData->bWaitForConnectionSettings = bWait;
1021 DPLAYX_ReleaseSemaphore();
1023 return TRUE;
1026 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1028 UINT i;
1029 BOOL bFound = FALSE;
1031 DPLAYX_AcquireSemaphore();
1033 for( i=0; i < numSupportedLobbies; i++ )
1035 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1036 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1039 bFound = TRUE;
1040 break;
1044 DPLAYX_ReleaseSemaphore();
1046 return bFound;
1049 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1051 LPDPLAYX_LOBBYDATA lpLobbyData;
1053 DPLAYX_AcquireSemaphore();
1055 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1057 DPLAYX_ReleaseSemaphore();
1058 return FALSE;
1061 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1063 DPLAYX_ReleaseSemaphore();
1065 return TRUE;
1068 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1069 with the correct string printed in the case where the HRESULT is not
1070 known. You will just get the last hr passed in. This can change
1071 over time if this method is used a lot :) */
1072 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1074 static char szTempStr[12];
1076 switch (hr)
1078 case DP_OK:
1079 return "DP_OK";
1080 case DPERR_ALREADYINITIALIZED:
1081 return "DPERR_ALREADYINITIALIZED";
1082 case DPERR_ACCESSDENIED:
1083 return "DPERR_ACCESSDENIED";
1084 case DPERR_ACTIVEPLAYERS:
1085 return "DPERR_ACTIVEPLAYERS";
1086 case DPERR_BUFFERTOOSMALL:
1087 return "DPERR_BUFFERTOOSMALL";
1088 case DPERR_CANTADDPLAYER:
1089 return "DPERR_CANTADDPLAYER";
1090 case DPERR_CANTCREATEGROUP:
1091 return "DPERR_CANTCREATEGROUP";
1092 case DPERR_CANTCREATEPLAYER:
1093 return "DPERR_CANTCREATEPLAYER";
1094 case DPERR_CANTCREATESESSION:
1095 return "DPERR_CANTCREATESESSION";
1096 case DPERR_CAPSNOTAVAILABLEYET:
1097 return "DPERR_CAPSNOTAVAILABLEYET";
1098 case DPERR_EXCEPTION:
1099 return "DPERR_EXCEPTION";
1100 case DPERR_GENERIC:
1101 return "DPERR_GENERIC";
1102 case DPERR_INVALIDFLAGS:
1103 return "DPERR_INVALIDFLAGS";
1104 case DPERR_INVALIDOBJECT:
1105 return "DPERR_INVALIDOBJECT";
1106 case DPERR_INVALIDPARAMS:
1107 return "DPERR_INVALIDPARAMS";
1108 case DPERR_INVALIDPLAYER:
1109 return "DPERR_INVALIDPLAYER";
1110 case DPERR_INVALIDGROUP:
1111 return "DPERR_INVALIDGROUP";
1112 case DPERR_NOCAPS:
1113 return "DPERR_NOCAPS";
1114 case DPERR_NOCONNECTION:
1115 return "DPERR_NOCONNECTION";
1116 case DPERR_OUTOFMEMORY:
1117 return "DPERR_OUTOFMEMORY";
1118 case DPERR_NOMESSAGES:
1119 return "DPERR_NOMESSAGES";
1120 case DPERR_NONAMESERVERFOUND:
1121 return "DPERR_NONAMESERVERFOUND";
1122 case DPERR_NOPLAYERS:
1123 return "DPERR_NOPLAYERS";
1124 case DPERR_NOSESSIONS:
1125 return "DPERR_NOSESSIONS";
1126 case DPERR_PENDING:
1127 return "DPERR_PENDING";
1128 case DPERR_SENDTOOBIG:
1129 return "DPERR_SENDTOOBIG";
1130 case DPERR_TIMEOUT:
1131 return "DPERR_TIMEOUT";
1132 case DPERR_UNAVAILABLE:
1133 return "DPERR_UNAVAILABLE";
1134 case DPERR_UNSUPPORTED:
1135 return "DPERR_UNSUPPORTED";
1136 case DPERR_BUSY:
1137 return "DPERR_BUSY";
1138 case DPERR_USERCANCEL:
1139 return "DPERR_USERCANCEL";
1140 case DPERR_NOINTERFACE:
1141 return "DPERR_NOINTERFACE";
1142 case DPERR_CANNOTCREATESERVER:
1143 return "DPERR_CANNOTCREATESERVER";
1144 case DPERR_PLAYERLOST:
1145 return "DPERR_PLAYERLOST";
1146 case DPERR_SESSIONLOST:
1147 return "DPERR_SESSIONLOST";
1148 case DPERR_UNINITIALIZED:
1149 return "DPERR_UNINITIALIZED";
1150 case DPERR_NONEWPLAYERS:
1151 return "DPERR_NONEWPLAYERS";
1152 case DPERR_INVALIDPASSWORD:
1153 return "DPERR_INVALIDPASSWORD";
1154 case DPERR_CONNECTING:
1155 return "DPERR_CONNECTING";
1156 case DPERR_CONNECTIONLOST:
1157 return "DPERR_CONNECTIONLOST";
1158 case DPERR_UNKNOWNMESSAGE:
1159 return "DPERR_UNKNOWNMESSAGE";
1160 case DPERR_CANCELFAILED:
1161 return "DPERR_CANCELFAILED";
1162 case DPERR_INVALIDPRIORITY:
1163 return "DPERR_INVALIDPRIORITY";
1164 case DPERR_NOTHANDLED:
1165 return "DPERR_NOTHANDLED";
1166 case DPERR_CANCELLED:
1167 return "DPERR_CANCELLED";
1168 case DPERR_ABORTED:
1169 return "DPERR_ABORTED";
1170 case DPERR_BUFFERTOOLARGE:
1171 return "DPERR_BUFFERTOOLARGE";
1172 case DPERR_CANTCREATEPROCESS:
1173 return "DPERR_CANTCREATEPROCESS";
1174 case DPERR_APPNOTSTARTED:
1175 return "DPERR_APPNOTSTARTED";
1176 case DPERR_INVALIDINTERFACE:
1177 return "DPERR_INVALIDINTERFACE";
1178 case DPERR_NOSERVICEPROVIDER:
1179 return "DPERR_NOSERVICEPROVIDER";
1180 case DPERR_UNKNOWNAPPLICATION:
1181 return "DPERR_UNKNOWNAPPLICATION";
1182 case DPERR_NOTLOBBIED:
1183 return "DPERR_NOTLOBBIED";
1184 case DPERR_SERVICEPROVIDERLOADED:
1185 return "DPERR_SERVICEPROVIDERLOADED";
1186 case DPERR_ALREADYREGISTERED:
1187 return "DPERR_ALREADYREGISTERED";
1188 case DPERR_NOTREGISTERED:
1189 return "DPERR_NOTREGISTERED";
1190 case DPERR_AUTHENTICATIONFAILED:
1191 return "DPERR_AUTHENTICATIONFAILED";
1192 case DPERR_CANTLOADSSPI:
1193 return "DPERR_CANTLOADSSPI";
1194 case DPERR_ENCRYPTIONFAILED:
1195 return "DPERR_ENCRYPTIONFAILED";
1196 case DPERR_SIGNFAILED:
1197 return "DPERR_SIGNFAILED";
1198 case DPERR_CANTLOADSECURITYPACKAGE:
1199 return "DPERR_CANTLOADSECURITYPACKAGE";
1200 case DPERR_ENCRYPTIONNOTSUPPORTED:
1201 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1202 case DPERR_CANTLOADCAPI:
1203 return "DPERR_CANTLOADCAPI";
1204 case DPERR_NOTLOGGEDIN:
1205 return "DPERR_NOTLOGGEDIN";
1206 case DPERR_LOGONDENIED:
1207 return "DPERR_LOGONDENIED";
1208 default:
1209 /* For errors not in the list, return HRESULT as a string
1210 This part is not thread safe */
1211 WARN( "Unknown error 0x%08lx\n", hr );
1212 wsprintfA( szTempStr, "0x%08x", hr );
1213 return szTempStr;