Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / dplayx / dplayx_global.c
blobd344285593c544cf20ded53d835adb9fc8b0c856
1 /* dplayx.dll global data implementation.
3 * Copyright 1999,2000 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /* NOTE: Methods that begin with DPLAYX_ are used for dealing with
23 * dplayx.dll data which is accessible from all processes.
26 #include <stdarg.h>
27 #include <string.h>
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "wine/debug.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winerror.h"
35 #include "wine/unicode.h"
37 #include "wingdi.h"
38 #include "winuser.h"
40 #include "dplayx_global.h"
41 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
43 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
45 /* FIXME: Need to do all that fun other dll referencing type of stuff */
47 /* Static data for all processes */
48 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
49 static HANDLE hDplayxSema;
51 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
52 static HANDLE hDplayxSharedMem;
54 static LPVOID lpSharedStaticData = NULL;
57 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
58 WaitForSingleObject( hDplayxSema, INFINITE );\
59 TRACE( "Through wait\n" )
61 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
62 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
65 /* HACK for simple global data right now */
66 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
67 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
68 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
71 /* FIXME: Is there no easier way? */
73 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
74 * Each block has 4 bytes which are 0 unless used */
75 #define dwBlockSize 512
76 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
78 typedef struct
80 DWORD used;
81 DWORD data[dwBlockSize-sizeof(DWORD)];
82 } DPLAYX_MEM_SLICE;
84 static DPLAYX_MEM_SLICE* lpMemArea;
86 void DPLAYX_PrivHeapFree( LPVOID addr );
87 void DPLAYX_PrivHeapFree( LPVOID addr )
89 LPVOID lpAddrStart;
90 DWORD dwBlockUsed;
92 /* Handle getting passed a NULL */
93 if( addr == NULL )
95 return;
98 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
99 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
101 lpMemArea[ dwBlockUsed ].used = 0;
104 /* FIXME: This should be static, but is being used for a hack right now */
105 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
106 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
108 LPVOID lpvArea = NULL;
109 UINT uBlockUsed;
111 if( size > (dwBlockSize - sizeof(DWORD)) )
113 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
114 size = dwBlockSize - sizeof(DWORD);
117 /* Find blank area */
118 uBlockUsed = 0;
119 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
121 if( uBlockUsed <= dwMaxBlock )
123 /* Set the area used */
124 lpMemArea[ uBlockUsed ].used = 1;
125 lpvArea = &(lpMemArea[ uBlockUsed ].data);
127 else
129 ERR( "No free block found\n" );
130 return NULL;
133 if( flags & HEAP_ZERO_MEMORY )
135 ZeroMemory( lpvArea, size );
138 return lpvArea;
141 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
142 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
144 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
145 if(p) {
146 strcpy( p, str );
148 return p;
151 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
152 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
154 INT len = strlenW(str) + 1;
155 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
156 if(p) {
157 strcpyW( p, str );
159 return p;
163 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
164 typedef struct tagDPLAYX_LOBBYDATA
166 /* Points to lpConn + block of contiguous extra memory for dynamic parts
167 * of the struct directly following
169 LPDPLCONNECTION lpConn;
171 /* Information for dplobby interfaces */
172 DWORD dwAppID;
173 DWORD dwAppLaunchedFromID;
175 /* Should this lobby app send messages to creator at important life
176 * stages
178 HANDLE hInformOnAppStart;
179 HANDLE hInformOnAppDeath;
180 HANDLE hInformOnSettingRead;
182 /* Sundries */
183 BOOL bWaitForConnectionSettings;
184 DWORD dwLobbyMsgThreadId;
187 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
189 static DPLAYX_LOBBYDATA* lobbyData = NULL;
190 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
192 static DPSESSIONDESC2* sessionData = NULL;
193 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
195 /* Function prototypes */
196 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
197 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
198 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
199 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
200 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
201 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
202 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
203 LPCDPSESSIONDESC2 lpSessionSrc );
207 /***************************************************************************
208 * Called to initialize the global data. This will only be used on the
209 * loading of the dll
210 ***************************************************************************/
211 BOOL DPLAYX_ConstructData(void)
213 SECURITY_ATTRIBUTES s_attrib;
214 BOOL bInitializeSharedMemory = FALSE;
215 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
216 HANDLE hInformOnStart;
218 TRACE( "DPLAYX dll loaded - construct called\n" );
220 /* Create a semaphore to block access to DPLAYX global data structs */
222 s_attrib.bInheritHandle = TRUE;
223 s_attrib.lpSecurityDescriptor = NULL;
224 s_attrib.nLength = sizeof(s_attrib);
226 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
228 /* First instance creates the semaphore. Others just use it */
229 if( GetLastError() == ERROR_SUCCESS )
231 TRACE( "Semaphore %p created\n", hDplayxSema );
233 /* The semaphore creator will also build the shared memory */
234 bInitializeSharedMemory = TRUE;
236 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
238 TRACE( "Found semaphore handle %p\n", hDplayxSema );
240 else
242 ERR( ": semaphore error %ld\n", GetLastError() );
243 return FALSE;
246 SetLastError( ERROR_SUCCESS );
248 DPLAYX_AquireSemaphore();
250 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
251 &s_attrib,
252 PAGE_READWRITE | SEC_COMMIT,
254 dwTotalSharedSize,
255 lpszDplayxFileMapping );
257 if( GetLastError() == ERROR_SUCCESS )
259 TRACE( "File mapped %p created\n", hDplayxSharedMem );
261 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
263 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
265 else
267 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
268 return FALSE;
271 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
272 FILE_MAP_WRITE,
273 0, 0, 0, lpDesiredMemoryMapStart );
275 if( lpSharedStaticData == NULL )
277 ERR( ": unable to map static data into process memory space (%ld)\n",
278 GetLastError() );
279 return FALSE;
281 else
283 if( lpDesiredMemoryMapStart == lpSharedStaticData )
285 TRACE( "File mapped to %p\n", lpSharedStaticData );
287 else
289 /* Presently the shared data structures use pointers. If the
290 * files are no mapped into the same area, the pointers will no
291 * longer make any sense :(
292 * FIXME: In the future make the shared data structures have some
293 * sort of fixup to make them independent between data spaces.
294 * This will also require a rework of the session data stuff.
296 ERR( "File mapped to %p (not %p). Expect failure\n",
297 lpSharedStaticData, lpDesiredMemoryMapStart );
301 /* Dynamic area starts just after the static area */
302 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
304 /* FIXME: Crude hack */
305 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
306 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
308 /* Initialize shared data segments. */
309 if( bInitializeSharedMemory )
311 UINT i;
313 TRACE( "Initializing shared memory\n" );
315 /* Set all lobbies to be "empty" */
316 for( i=0; i < numSupportedLobbies; i++ )
318 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
321 /* Set all sessions to be "empty" */
322 for( i=0; i < numSupportedSessions; i++ )
324 sessionData[i].dwSize = 0;
327 /* Zero out the dynmaic area */
328 ZeroMemory( lpMemArea, dwDynamicSharedSize );
330 /* Just for fun sync the whole data area */
331 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
334 DPLAYX_ReleaseSemaphore();
336 /* Everything was created correctly. Signal the lobby client that
337 * we started up correctly
339 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
340 hInformOnStart
343 BOOL bSuccess;
344 bSuccess = SetEvent( hInformOnStart );
345 TRACE( "Signalling lobby app start event %p %s\n",
346 hInformOnStart, bSuccess ? "succeed" : "failed" );
348 /* Close out handle */
349 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
352 return TRUE;
355 /***************************************************************************
356 * Called to destroy all global data. This will only be used on the
357 * unloading of the dll
358 ***************************************************************************/
359 BOOL DPLAYX_DestructData(void)
361 HANDLE hInformOnDeath;
363 TRACE( "DPLAYX dll unloaded - destruct called\n" );
365 /* If required, inform that this app is dying */
366 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
367 hInformOnDeath
370 BOOL bSuccess;
371 bSuccess = SetEvent( hInformOnDeath );
372 TRACE( "Signalling lobby app death event %p %s\n",
373 hInformOnDeath, bSuccess ? "succeed" : "failed" );
375 /* Close out handle */
376 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
379 /* DO CLEAN UP (LAST) */
381 /* Delete the semaphore */
382 CloseHandle( hDplayxSema );
384 /* Delete shared memory file mapping */
385 UnmapViewOfFile( lpSharedStaticData );
386 CloseHandle( hDplayxSharedMem );
388 return FALSE;
392 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
394 ZeroMemory( lpData, sizeof( *lpData ) );
397 /* NOTE: This must be called with the semaphore aquired.
398 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
399 * is only valid if TRUE is returned.
401 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
403 UINT i;
405 *lplpDplData = NULL;
407 if( dwAppID == 0 )
409 dwAppID = GetCurrentProcessId();
410 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
413 for( i=0; i < numSupportedLobbies; i++ )
415 if( lobbyData[ i ].dwAppID == dwAppID )
417 /* This process is lobbied */
418 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
419 *lplpDplData = &lobbyData[ i ];
420 return TRUE;
424 return FALSE;
427 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
428 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
430 UINT i;
432 /* 0 is the marker for unused application data slots */
433 if( dwAppID == 0 )
435 return FALSE;
438 DPLAYX_AquireSemaphore();
440 /* Find an empty space in the list and insert the data */
441 for( i=0; i < numSupportedLobbies; i++ )
443 if( lobbyData[ i ].dwAppID == 0 )
445 /* This process is now lobbied */
446 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
447 i, dwAppID, GetCurrentProcessId() );
449 lobbyData[ i ].dwAppID = dwAppID;
450 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
452 /* FIXME: Where is the best place for this? In interface or here? */
453 lobbyData[ i ].hInformOnAppStart = 0;
454 lobbyData[ i ].hInformOnAppDeath = 0;
455 lobbyData[ i ].hInformOnSettingRead = 0;
457 DPLAYX_ReleaseSemaphore();
458 return TRUE;
462 ERR( "No empty lobbies\n" );
464 DPLAYX_ReleaseSemaphore();
465 return FALSE;
468 /* I'm not sure when I'm going to need this, but here it is */
469 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
471 UINT i;
473 DPLAYX_AquireSemaphore();
475 /* Find an empty space in the list and insert the data */
476 for( i=0; i < numSupportedLobbies; i++ )
478 if( lobbyData[ i ].dwAppID == dwAppID )
480 /* FIXME: Should free up anything unused. Tisk tisk :0 */
481 /* Mark this entry unused */
482 TRACE( "Marking lobbyData[%u] unused\n", i );
483 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
485 DPLAYX_ReleaseSemaphore();
486 return TRUE;
490 DPLAYX_ReleaseSemaphore();
491 ERR( "Unable to find global entry for application\n" );
492 return FALSE;
495 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
496 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
498 LPDPLAYX_LOBBYDATA lpLData;
500 /* Need to explictly give lobby application. Can't set for yourself */
501 if( dwAppID == 0 )
503 return FALSE;
506 DPLAYX_AquireSemaphore();
508 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
510 DPLAYX_ReleaseSemaphore();
511 return FALSE;
514 lpLData->hInformOnAppStart = hStart;
515 lpLData->hInformOnAppDeath = hDeath;
516 lpLData->hInformOnSettingRead = hConnRead;
518 DPLAYX_ReleaseSemaphore();
520 return TRUE;
523 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
524 LPHANDLE lphDeath,
525 LPHANDLE lphConnRead,
526 BOOL bClearSetHandles )
528 LPDPLAYX_LOBBYDATA lpLData;
530 DPLAYX_AquireSemaphore();
532 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
534 DPLAYX_ReleaseSemaphore();
535 return FALSE;
538 if( lphStart != NULL )
540 if( lpLData->hInformOnAppStart == 0 )
542 DPLAYX_ReleaseSemaphore();
543 return FALSE;
546 *lphStart = lpLData->hInformOnAppStart;
548 if( bClearSetHandles )
550 CloseHandle( lpLData->hInformOnAppStart );
551 lpLData->hInformOnAppStart = 0;
555 if( lphDeath != NULL )
557 if( lpLData->hInformOnAppDeath == 0 )
559 DPLAYX_ReleaseSemaphore();
560 return FALSE;
563 *lphDeath = lpLData->hInformOnAppDeath;
565 if( bClearSetHandles )
567 CloseHandle( lpLData->hInformOnAppDeath );
568 lpLData->hInformOnAppDeath = 0;
572 if( lphConnRead != NULL )
574 if( lpLData->hInformOnSettingRead == 0 )
576 DPLAYX_ReleaseSemaphore();
577 return FALSE;
580 *lphConnRead = lpLData->hInformOnSettingRead;
582 if( bClearSetHandles )
584 CloseHandle( lpLData->hInformOnSettingRead );
585 lpLData->hInformOnSettingRead = 0;
589 DPLAYX_ReleaseSemaphore();
591 return TRUE;
595 HRESULT DPLAYX_GetConnectionSettingsA
596 ( DWORD dwAppID,
597 LPVOID lpData,
598 LPDWORD lpdwDataSize )
600 LPDPLAYX_LOBBYDATA lpDplData;
601 DWORD dwRequiredDataSize = 0;
602 HANDLE hInformOnSettingRead;
604 DPLAYX_AquireSemaphore();
606 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
608 DPLAYX_ReleaseSemaphore();
610 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
611 return DPERR_NOTLOBBIED;
614 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
616 /* Do they want to know the required buffer size or is the provided buffer
617 * big enough?
619 if ( ( lpData == NULL ) ||
620 ( *lpdwDataSize < dwRequiredDataSize )
623 DPLAYX_ReleaseSemaphore();
625 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
627 return DPERR_BUFFERTOOSMALL;
630 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
632 DPLAYX_ReleaseSemaphore();
634 /* They have gotten the information - signal the event if required */
635 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
636 hInformOnSettingRead
639 BOOL bSuccess;
640 bSuccess = SetEvent( hInformOnSettingRead );
641 TRACE( "Signalling setting read event %p %s\n",
642 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
644 /* Close out handle */
645 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
648 return DP_OK;
651 /* Assumption: Enough contiguous space was allocated at dest */
652 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
654 BYTE* lpStartOfFreeSpace;
656 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
658 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
660 /* Copy the LPDPSESSIONDESC2 structure if it exists */
661 if( src->lpSessionDesc )
663 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
664 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
665 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
667 /* Session names may or may not exist */
668 if( src->lpSessionDesc->u1.lpszSessionNameA )
670 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
671 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
672 lpStartOfFreeSpace +=
673 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
676 if( src->lpSessionDesc->u2.lpszPasswordA )
678 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
679 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
680 lpStartOfFreeSpace +=
681 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
685 /* DPNAME structure is optional */
686 if( src->lpPlayerName )
688 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
689 lpStartOfFreeSpace += sizeof( DPNAME );
690 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
692 if( src->lpPlayerName->u1.lpszShortNameA )
694 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
695 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
696 lpStartOfFreeSpace +=
697 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
700 if( src->lpPlayerName->u2.lpszLongNameA )
702 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
703 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
704 lpStartOfFreeSpace +=
705 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
710 /* Copy address if it exists */
711 if( src->lpAddress )
713 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
714 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
715 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
719 HRESULT DPLAYX_GetConnectionSettingsW
720 ( DWORD dwAppID,
721 LPVOID lpData,
722 LPDWORD lpdwDataSize )
724 LPDPLAYX_LOBBYDATA lpDplData;
725 DWORD dwRequiredDataSize = 0;
726 HANDLE hInformOnSettingRead;
728 DPLAYX_AquireSemaphore();
730 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
732 DPLAYX_ReleaseSemaphore();
733 return DPERR_NOTLOBBIED;
736 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
738 /* Do they want to know the required buffer size or is the provided buffer
739 * big enough?
741 if ( ( lpData == NULL ) ||
742 ( *lpdwDataSize < dwRequiredDataSize )
745 DPLAYX_ReleaseSemaphore();
747 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
749 return DPERR_BUFFERTOOSMALL;
752 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
754 DPLAYX_ReleaseSemaphore();
756 /* They have gotten the information - signal the event if required */
757 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
758 hInformOnSettingRead
761 BOOL bSuccess;
762 bSuccess = SetEvent( hInformOnSettingRead );
763 TRACE( "Signalling setting read event %p %s\n",
764 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
766 /* Close out handle */
767 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
770 return DP_OK;
773 /* Assumption: Enough contiguous space was allocated at dest */
774 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
776 BYTE* lpStartOfFreeSpace;
778 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
780 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
782 /* Copy the LPDPSESSIONDESC2 structure if it exists */
783 if( src->lpSessionDesc )
785 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
786 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
787 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
789 /* Session names may or may not exist */
790 if( src->lpSessionDesc->u1.lpszSessionName )
792 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
793 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
794 lpStartOfFreeSpace += sizeof(WCHAR) *
795 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
798 if( src->lpSessionDesc->u2.lpszPassword )
800 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
801 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
802 lpStartOfFreeSpace += sizeof(WCHAR) *
803 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
807 /* DPNAME structure is optional */
808 if( src->lpPlayerName )
810 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
811 lpStartOfFreeSpace += sizeof( DPNAME );
812 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
814 if( src->lpPlayerName->u1.lpszShortName )
816 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
817 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
818 lpStartOfFreeSpace += sizeof(WCHAR) *
819 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
822 if( src->lpPlayerName->u2.lpszLongName )
824 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
825 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
826 lpStartOfFreeSpace += sizeof(WCHAR) *
827 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
832 /* Copy address if it exists */
833 if( src->lpAddress )
835 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
836 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
837 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
842 /* Store the structure into the shared data structre. Ensure that allocs for
843 * variable length strings come from the shared data structure.
844 * FIXME: We need to free information as well
846 HRESULT DPLAYX_SetConnectionSettingsA
847 ( DWORD dwFlags,
848 DWORD dwAppID,
849 LPDPLCONNECTION lpConn )
851 LPDPLAYX_LOBBYDATA lpDplData;
853 /* Parameter check */
854 if( dwFlags || !lpConn )
856 ERR("invalid parameters.\n");
857 return DPERR_INVALIDPARAMS;
860 /* Store information */
861 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
863 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
864 lpConn->dwSize, sizeof( DPLCONNECTION ) );
866 return DPERR_INVALIDPARAMS;
869 DPLAYX_AquireSemaphore();
871 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
873 DPLAYX_ReleaseSemaphore();
875 return DPERR_NOTLOBBIED;
878 if( (!lpConn->lpSessionDesc ) ||
879 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
882 DPLAYX_ReleaseSemaphore();
884 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
885 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
887 return DPERR_INVALIDPARAMS;
890 /* Free the existing memory */
891 DPLAYX_PrivHeapFree( lpDplData->lpConn );
893 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
894 DPLAYX_SizeOfLobbyDataA( lpConn ) );
896 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
899 DPLAYX_ReleaseSemaphore();
901 /* FIXME: Send a message - I think */
903 return DP_OK;
906 /* Store the structure into the shared data structre. Ensure that allocs for
907 * variable length strings come from the shared data structure.
908 * FIXME: We need to free information as well
910 HRESULT DPLAYX_SetConnectionSettingsW
911 ( DWORD dwFlags,
912 DWORD dwAppID,
913 LPDPLCONNECTION lpConn )
915 LPDPLAYX_LOBBYDATA lpDplData;
917 /* Parameter check */
918 if( dwFlags || !lpConn )
920 ERR("invalid parameters.\n");
921 return DPERR_INVALIDPARAMS;
924 /* Store information */
925 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
927 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
928 lpConn->dwSize, sizeof( DPLCONNECTION ) );
930 return DPERR_INVALIDPARAMS;
933 DPLAYX_AquireSemaphore();
935 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
937 DPLAYX_ReleaseSemaphore();
939 return DPERR_NOTLOBBIED;
942 /* Free the existing memory */
943 DPLAYX_PrivHeapFree( lpDplData->lpConn );
945 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
946 DPLAYX_SizeOfLobbyDataW( lpConn ) );
948 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
951 DPLAYX_ReleaseSemaphore();
953 /* FIXME: Send a message - I think */
955 return DP_OK;
958 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
960 DWORD dwTotalSize = sizeof( DPLCONNECTION );
962 /* Just a safety check */
963 if( lpConn == NULL )
965 ERR( "lpConn is NULL\n" );
966 return 0;
969 if( lpConn->lpSessionDesc != NULL )
971 dwTotalSize += sizeof( DPSESSIONDESC2 );
973 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
975 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
978 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
980 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
984 if( lpConn->lpPlayerName != NULL )
986 dwTotalSize += sizeof( DPNAME );
988 if( lpConn->lpPlayerName->u1.lpszShortNameA )
990 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
993 if( lpConn->lpPlayerName->u2.lpszLongNameA )
995 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
1000 dwTotalSize += lpConn->dwAddressSize;
1002 return dwTotalSize;
1005 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
1007 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1009 /* Just a safety check */
1010 if( lpConn == NULL )
1012 ERR( "lpConn is NULL\n" );
1013 return 0;
1016 if( lpConn->lpSessionDesc != NULL )
1018 dwTotalSize += sizeof( DPSESSIONDESC2 );
1020 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1022 dwTotalSize += sizeof( WCHAR ) *
1023 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1026 if( lpConn->lpSessionDesc->u2.lpszPassword )
1028 dwTotalSize += sizeof( WCHAR ) *
1029 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1033 if( lpConn->lpPlayerName != NULL )
1035 dwTotalSize += sizeof( DPNAME );
1037 if( lpConn->lpPlayerName->u1.lpszShortName )
1039 dwTotalSize += sizeof( WCHAR ) *
1040 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1043 if( lpConn->lpPlayerName->u2.lpszLongName )
1045 dwTotalSize += sizeof( WCHAR ) *
1046 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1051 dwTotalSize += lpConn->dwAddressSize;
1053 return dwTotalSize;
1058 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1060 LPDPSESSIONDESC2 lpSessionDest =
1061 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1062 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1063 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1065 return lpSessionDest;
1068 /* Copy an ANSI session desc structure to the given buffer */
1069 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1070 LPCDPSESSIONDESC2 lpSessionSrc )
1072 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1074 if( lpSessionSrc->u1.lpszSessionNameA )
1076 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1077 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1078 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1080 if( lpSessionSrc->u2.lpszPasswordA )
1082 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1083 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1084 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1087 return TRUE;
1090 /* Start the index at 0. index will be updated to equal that which should
1091 be passed back into this function for the next element */
1092 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1094 for( ; (*index) < numSupportedSessions; (*index)++ )
1096 if( sessionData[(*index)].dwSize != 0 )
1098 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1102 /* No more sessions */
1103 return NULL;
1106 /* Start the index at 0. index will be updated to equal that which should
1107 be passed back into this function for the next element */
1108 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1110 for( ; (*index) < numSupportedSessions; (*index)++ )
1112 if( sessionData[(*index)].dwSize != 0 )
1114 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1118 /* No more sessions */
1119 return FALSE;
1122 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1124 UINT i;
1126 /* FIXME: Is this an error if it exists already? */
1128 /* Crude/wrong implementation for now. Just always add to first empty spot */
1129 for( i=0; i < numSupportedSessions; i++ )
1131 /* Is this one empty? */
1132 if( sessionData[i].dwSize == 0 )
1134 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1135 break;
1141 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1143 LPDPLAYX_LOBBYDATA lpLobbyData;
1145 DPLAYX_AquireSemaphore();
1147 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1149 DPLAYX_ReleaseSemaphore();
1150 return FALSE;
1153 lpLobbyData->bWaitForConnectionSettings = bWait;
1155 DPLAYX_ReleaseSemaphore();
1157 return TRUE;
1160 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1162 UINT i;
1163 BOOL bFound = FALSE;
1165 DPLAYX_AquireSemaphore();
1167 for( i=0; i < numSupportedLobbies; i++ )
1169 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1170 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1173 bFound = TRUE;
1174 break;
1178 DPLAYX_ReleaseSemaphore();
1180 return bFound;
1183 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1185 LPDPLAYX_LOBBYDATA lpLobbyData;
1187 DPLAYX_AquireSemaphore();
1189 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1191 DPLAYX_ReleaseSemaphore();
1192 return FALSE;
1195 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1197 DPLAYX_ReleaseSemaphore();
1199 return TRUE;
1202 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1203 with the correct string printed in the case where the HRESULT is not
1204 known. You'll just get the last hr passed in printed. This can change
1205 over time if this method is used alot :) */
1206 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1208 static char szTempStr[12];
1210 switch (hr)
1212 case DP_OK:
1213 return "DP_OK";
1214 case DPERR_ALREADYINITIALIZED:
1215 return "DPERR_ALREADYINITIALIZED";
1216 case DPERR_ACCESSDENIED:
1217 return "DPERR_ACCESSDENIED";
1218 case DPERR_ACTIVEPLAYERS:
1219 return "DPERR_ACTIVEPLAYERS";
1220 case DPERR_BUFFERTOOSMALL:
1221 return "DPERR_BUFFERTOOSMALL";
1222 case DPERR_CANTADDPLAYER:
1223 return "DPERR_CANTADDPLAYER";
1224 case DPERR_CANTCREATEGROUP:
1225 return "DPERR_CANTCREATEGROUP";
1226 case DPERR_CANTCREATEPLAYER:
1227 return "DPERR_CANTCREATEPLAYER";
1228 case DPERR_CANTCREATESESSION:
1229 return "DPERR_CANTCREATESESSION";
1230 case DPERR_CAPSNOTAVAILABLEYET:
1231 return "DPERR_CAPSNOTAVAILABLEYET";
1232 case DPERR_EXCEPTION:
1233 return "DPERR_EXCEPTION";
1234 case DPERR_GENERIC:
1235 return "DPERR_GENERIC";
1236 case DPERR_INVALIDFLAGS:
1237 return "DPERR_INVALIDFLAGS";
1238 case DPERR_INVALIDOBJECT:
1239 return "DPERR_INVALIDOBJECT";
1240 case DPERR_INVALIDPARAMS:
1241 return "DPERR_INVALIDPARAMS";
1242 case DPERR_INVALIDPLAYER:
1243 return "DPERR_INVALIDPLAYER";
1244 case DPERR_INVALIDGROUP:
1245 return "DPERR_INVALIDGROUP";
1246 case DPERR_NOCAPS:
1247 return "DPERR_NOCAPS";
1248 case DPERR_NOCONNECTION:
1249 return "DPERR_NOCONNECTION";
1250 case DPERR_OUTOFMEMORY:
1251 return "DPERR_OUTOFMEMORY";
1252 case DPERR_NOMESSAGES:
1253 return "DPERR_NOMESSAGES";
1254 case DPERR_NONAMESERVERFOUND:
1255 return "DPERR_NONAMESERVERFOUND";
1256 case DPERR_NOPLAYERS:
1257 return "DPERR_NOPLAYERS";
1258 case DPERR_NOSESSIONS:
1259 return "DPERR_NOSESSIONS";
1260 case DPERR_PENDING:
1261 return "DPERR_PENDING";
1262 case DPERR_SENDTOOBIG:
1263 return "DPERR_SENDTOOBIG";
1264 case DPERR_TIMEOUT:
1265 return "DPERR_TIMEOUT";
1266 case DPERR_UNAVAILABLE:
1267 return "DPERR_UNAVAILABLE";
1268 case DPERR_UNSUPPORTED:
1269 return "DPERR_UNSUPPORTED";
1270 case DPERR_BUSY:
1271 return "DPERR_BUSY";
1272 case DPERR_USERCANCEL:
1273 return "DPERR_USERCANCEL";
1274 case DPERR_NOINTERFACE:
1275 return "DPERR_NOINTERFACE";
1276 case DPERR_CANNOTCREATESERVER:
1277 return "DPERR_CANNOTCREATESERVER";
1278 case DPERR_PLAYERLOST:
1279 return "DPERR_PLAYERLOST";
1280 case DPERR_SESSIONLOST:
1281 return "DPERR_SESSIONLOST";
1282 case DPERR_UNINITIALIZED:
1283 return "DPERR_UNINITIALIZED";
1284 case DPERR_NONEWPLAYERS:
1285 return "DPERR_NONEWPLAYERS";
1286 case DPERR_INVALIDPASSWORD:
1287 return "DPERR_INVALIDPASSWORD";
1288 case DPERR_CONNECTING:
1289 return "DPERR_CONNECTING";
1290 case DPERR_CONNECTIONLOST:
1291 return "DPERR_CONNECTIONLOST";
1292 case DPERR_UNKNOWNMESSAGE:
1293 return "DPERR_UNKNOWNMESSAGE";
1294 case DPERR_CANCELFAILED:
1295 return "DPERR_CANCELFAILED";
1296 case DPERR_INVALIDPRIORITY:
1297 return "DPERR_INVALIDPRIORITY";
1298 case DPERR_NOTHANDLED:
1299 return "DPERR_NOTHANDLED";
1300 case DPERR_CANCELLED:
1301 return "DPERR_CANCELLED";
1302 case DPERR_ABORTED:
1303 return "DPERR_ABORTED";
1304 case DPERR_BUFFERTOOLARGE:
1305 return "DPERR_BUFFERTOOLARGE";
1306 case DPERR_CANTCREATEPROCESS:
1307 return "DPERR_CANTCREATEPROCESS";
1308 case DPERR_APPNOTSTARTED:
1309 return "DPERR_APPNOTSTARTED";
1310 case DPERR_INVALIDINTERFACE:
1311 return "DPERR_INVALIDINTERFACE";
1312 case DPERR_NOSERVICEPROVIDER:
1313 return "DPERR_NOSERVICEPROVIDER";
1314 case DPERR_UNKNOWNAPPLICATION:
1315 return "DPERR_UNKNOWNAPPLICATION";
1316 case DPERR_NOTLOBBIED:
1317 return "DPERR_NOTLOBBIED";
1318 case DPERR_SERVICEPROVIDERLOADED:
1319 return "DPERR_SERVICEPROVIDERLOADED";
1320 case DPERR_ALREADYREGISTERED:
1321 return "DPERR_ALREADYREGISTERED";
1322 case DPERR_NOTREGISTERED:
1323 return "DPERR_NOTREGISTERED";
1324 case DPERR_AUTHENTICATIONFAILED:
1325 return "DPERR_AUTHENTICATIONFAILED";
1326 case DPERR_CANTLOADSSPI:
1327 return "DPERR_CANTLOADSSPI";
1328 case DPERR_ENCRYPTIONFAILED:
1329 return "DPERR_ENCRYPTIONFAILED";
1330 case DPERR_SIGNFAILED:
1331 return "DPERR_SIGNFAILED";
1332 case DPERR_CANTLOADSECURITYPACKAGE:
1333 return "DPERR_CANTLOADSECURITYPACKAGE";
1334 case DPERR_ENCRYPTIONNOTSUPPORTED:
1335 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1336 case DPERR_CANTLOADCAPI:
1337 return "DPERR_CANTLOADCAPI";
1338 case DPERR_NOTLOGGEDIN:
1339 return "DPERR_NOTLOGGEDIN";
1340 case DPERR_LOGONDENIED:
1341 return "DPERR_LOGONDENIED";
1342 default:
1343 /* For errors not in the list, return HRESULT as a string
1344 This part is not thread safe */
1345 WARN( "Unknown error 0x%08lx\n", hr );
1346 wsprintfA( szTempStr, "0x%08lx", hr );
1347 return szTempStr;