Release 20030408.
[wine/gsoc-2012-control.git] / dlls / dplayx / dplayx_global.c
blob17c95f837826834a3255fd39dacff25389155df4
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 <string.h>
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "wine/unicode.h"
35 #include "wingdi.h"
36 #include "winuser.h"
38 #include "dplayx_global.h"
39 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
41 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
43 /* FIXME: Need to do all that fun other dll referencing type of stuff */
45 /* Static data for all processes */
46 static LPCSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
47 static HANDLE hDplayxSema;
49 static LPCSTR lpszDplayxFileMapping = "WINE_DPLAYX_FM";
50 static HANDLE hDplayxSharedMem;
52 static LPVOID lpSharedStaticData = NULL;
55 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
56 WaitForSingleObject( hDplayxSema, INFINITE );\
57 TRACE( "Through wait\n" )
59 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
60 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
63 /* HACK for simple global data right now */
64 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
65 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
66 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
69 /* FIXME: Is there no easier way? */
71 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
72 * Each block has 4 bytes which are 0 unless used */
73 #define dwBlockSize 512
74 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
76 typedef struct
78 DWORD used;
79 DWORD data[dwBlockSize-sizeof(DWORD)];
80 } DPLAYX_MEM_SLICE;
82 static DPLAYX_MEM_SLICE* lpMemArea;
84 void DPLAYX_PrivHeapFree( LPVOID addr );
85 void DPLAYX_PrivHeapFree( LPVOID addr )
87 LPVOID lpAddrStart;
88 DWORD dwBlockUsed;
90 /* Handle getting passed a NULL */
91 if( addr == NULL )
93 return;
96 lpAddrStart = (char*)addr - sizeof(DWORD); /* Find block header */
97 dwBlockUsed = ((BYTE*)lpAddrStart - (BYTE*)lpMemArea)/dwBlockSize;
99 lpMemArea[ dwBlockUsed ].used = 0;
102 /* FIXME: This should be static, but is being used for a hack right now */
103 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
104 LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size )
106 LPVOID lpvArea = NULL;
107 UINT uBlockUsed;
109 if( size > (dwBlockSize - sizeof(DWORD)) )
111 FIXME( "Size exceeded. Request of 0x%08lx\n", size );
112 size = dwBlockSize - sizeof(DWORD);
115 /* Find blank area */
116 uBlockUsed = 0;
117 while( ( lpMemArea[ uBlockUsed ].used != 0 ) && ( uBlockUsed <= dwMaxBlock ) ) { uBlockUsed++; }
119 if( uBlockUsed <= dwMaxBlock )
121 /* Set the area used */
122 lpMemArea[ uBlockUsed ].used = 1;
123 lpvArea = &(lpMemArea[ uBlockUsed ].data);
125 else
127 ERR( "No free block found\n" );
128 return NULL;
131 if( flags & HEAP_ZERO_MEMORY )
133 ZeroMemory( lpvArea, size );
136 return lpvArea;
139 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
140 LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str )
142 LPSTR p = DPLAYX_PrivHeapAlloc( flags, strlen(str) + 1 );
143 if(p) {
144 strcpy( p, str );
146 return p;
149 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
150 LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str )
152 INT len = strlenW(str) + 1;
153 LPWSTR p = DPLAYX_PrivHeapAlloc( flags, len * sizeof(WCHAR) );
154 if(p) {
155 strcpyW( p, str );
157 return p;
161 enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
162 typedef struct tagDPLAYX_LOBBYDATA
164 /* Points to lpConn + block of contiguous extra memory for dynamic parts
165 * of the struct directly following
167 LPDPLCONNECTION lpConn;
169 /* Information for dplobby interfaces */
170 DWORD dwAppID;
171 DWORD dwAppLaunchedFromID;
173 /* Should this lobby app send messages to creator at important life
174 * stages
176 HANDLE hInformOnAppStart;
177 HANDLE hInformOnAppDeath;
178 HANDLE hInformOnSettingRead;
180 /* Sundries */
181 BOOL bWaitForConnectionSettings;
182 DWORD dwLobbyMsgThreadId;
185 } DPLAYX_LOBBYDATA, *LPDPLAYX_LOBBYDATA;
187 static DPLAYX_LOBBYDATA* lobbyData = NULL;
188 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
190 static DPSESSIONDESC2* sessionData = NULL;
191 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
193 /* Function prototypes */
194 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData );
195 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData );
196 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src );
197 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src );
198 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, LPDPLAYX_LOBBYDATA* dplData );
199 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData );
200 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
201 LPCDPSESSIONDESC2 lpSessionSrc );
205 /***************************************************************************
206 * Called to initialize the global data. This will only be used on the
207 * loading of the dll
208 ***************************************************************************/
209 BOOL DPLAYX_ConstructData(void)
211 SECURITY_ATTRIBUTES s_attrib;
212 BOOL bInitializeSharedMemory = FALSE;
213 LPVOID lpDesiredMemoryMapStart = (LPVOID)0x50000000;
214 HANDLE hInformOnStart;
216 TRACE( "DPLAYX dll loaded - construct called\n" );
218 /* Create a semaphore to block access to DPLAYX global data structs */
220 s_attrib.bInheritHandle = TRUE;
221 s_attrib.lpSecurityDescriptor = NULL;
222 s_attrib.nLength = sizeof(s_attrib);
224 hDplayxSema = CreateSemaphoreA( &s_attrib, 1, 1, lpszDplayxSemaName );
226 /* First instance creates the semaphore. Others just use it */
227 if( GetLastError() == ERROR_SUCCESS )
229 TRACE( "Semaphore %p created\n", hDplayxSema );
231 /* The semaphore creator will also build the shared memory */
232 bInitializeSharedMemory = TRUE;
234 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
236 TRACE( "Found semaphore handle %p\n", hDplayxSema );
238 else
240 ERR( ": semaphore error %ld\n", GetLastError() );
241 return FALSE;
244 SetLastError( ERROR_SUCCESS );
246 DPLAYX_AquireSemaphore();
248 hDplayxSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE,
249 &s_attrib,
250 PAGE_READWRITE | SEC_COMMIT,
252 dwTotalSharedSize,
253 lpszDplayxFileMapping );
255 if( GetLastError() == ERROR_SUCCESS )
257 TRACE( "File mapped %p created\n", hDplayxSharedMem );
259 else if ( GetLastError() == ERROR_ALREADY_EXISTS )
261 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem );
263 else
265 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
266 return FALSE;
269 lpSharedStaticData = MapViewOfFileEx( hDplayxSharedMem,
270 FILE_MAP_WRITE,
271 0, 0, 0, lpDesiredMemoryMapStart );
273 if( lpSharedStaticData == NULL )
275 ERR( ": unable to map static data into process memory space (%ld)\n",
276 GetLastError() );
277 return FALSE;
279 else
281 if( lpDesiredMemoryMapStart == lpSharedStaticData )
283 TRACE( "File mapped to %p\n", lpSharedStaticData );
285 else
287 /* Presently the shared data structures use pointers. If the
288 * files are no mapped into the same area, the pointers will no
289 * longer make any sense :(
290 * FIXME: In the future make the shared data structures have some
291 * sort of fixup to make them independent between data spaces.
292 * This will also require a rework of the session data stuff.
294 ERR( "File mapped to %p (not %p). Expect failure\n",
295 lpSharedStaticData, lpDesiredMemoryMapStart );
299 /* Dynamic area starts just after the static area */
300 lpMemArea = (LPVOID)((BYTE*)lpSharedStaticData + dwStaticSharedSize);
302 /* FIXME: Crude hack */
303 lobbyData = (DPLAYX_LOBBYDATA*)lpSharedStaticData;
304 sessionData = (DPSESSIONDESC2*)((BYTE*)lpSharedStaticData + (dwStaticSharedSize/2));
306 /* Initialize shared data segments. */
307 if( bInitializeSharedMemory )
309 UINT i;
311 TRACE( "Initializing shared memory\n" );
313 /* Set all lobbies to be "empty" */
314 for( i=0; i < numSupportedLobbies; i++ )
316 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
319 /* Set all sessions to be "empty" */
320 for( i=0; i < numSupportedSessions; i++ )
322 sessionData[i].dwSize = 0;
325 /* Zero out the dynmaic area */
326 ZeroMemory( lpMemArea, dwDynamicSharedSize );
328 /* Just for fun sync the whole data area */
329 FlushViewOfFile( lpSharedStaticData, dwTotalSharedSize );
332 DPLAYX_ReleaseSemaphore();
334 /* Everything was created correctly. Signal the lobby client that
335 * we started up correctly
337 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, FALSE ) &&
338 hInformOnStart
341 BOOL bSuccess;
342 bSuccess = SetEvent( hInformOnStart );
343 TRACE( "Signalling lobby app start event %p %s\n",
344 hInformOnStart, bSuccess ? "succeed" : "failed" );
346 /* Close out handle */
347 DPLAYX_GetThisLobbyHandles( &hInformOnStart, NULL, NULL, TRUE );
350 return TRUE;
353 /***************************************************************************
354 * Called to destroy all global data. This will only be used on the
355 * unloading of the dll
356 ***************************************************************************/
357 BOOL DPLAYX_DestructData(void)
359 HANDLE hInformOnDeath;
361 TRACE( "DPLAYX dll unloaded - destruct called\n" );
363 /* If required, inform that this app is dying */
364 if( DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, FALSE ) &&
365 hInformOnDeath
368 BOOL bSuccess;
369 bSuccess = SetEvent( hInformOnDeath );
370 TRACE( "Signalling lobby app death event %p %s\n",
371 hInformOnDeath, bSuccess ? "succeed" : "failed" );
373 /* Close out handle */
374 DPLAYX_GetThisLobbyHandles( NULL, &hInformOnDeath, NULL, TRUE );
377 /* DO CLEAN UP (LAST) */
379 /* Delete the semaphore */
380 CloseHandle( hDplayxSema );
382 /* Delete shared memory file mapping */
383 UnmapViewOfFile( lpSharedStaticData );
384 CloseHandle( hDplayxSharedMem );
386 return FALSE;
390 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData )
392 ZeroMemory( lpData, sizeof( *lpData ) );
395 /* NOTE: This must be called with the semaphore aquired.
396 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
397 * is only valid if TRUE is returned.
399 BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, LPDPLAYX_LOBBYDATA* lplpDplData )
401 UINT i;
403 *lplpDplData = NULL;
405 if( dwAppID == 0 )
407 dwAppID = GetCurrentProcessId();
408 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
411 for( i=0; i < numSupportedLobbies; i++ )
413 if( lobbyData[ i ].dwAppID == dwAppID )
415 /* This process is lobbied */
416 TRACE( "Found 0x%08lx @ %u\n", dwAppID, i );
417 *lplpDplData = &lobbyData[ i ];
418 return TRUE;
422 return FALSE;
425 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
426 BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID )
428 UINT i;
430 /* 0 is the marker for unused application data slots */
431 if( dwAppID == 0 )
433 return FALSE;
436 DPLAYX_AquireSemaphore();
438 /* Find an empty space in the list and insert the data */
439 for( i=0; i < numSupportedLobbies; i++ )
441 if( lobbyData[ i ].dwAppID == 0 )
443 /* This process is now lobbied */
444 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
445 i, dwAppID, GetCurrentProcessId() );
447 lobbyData[ i ].dwAppID = dwAppID;
448 lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
450 /* FIXME: Where is the best place for this? In interface or here? */
451 lobbyData[ i ].hInformOnAppStart = 0;
452 lobbyData[ i ].hInformOnAppDeath = 0;
453 lobbyData[ i ].hInformOnSettingRead = 0;
455 DPLAYX_ReleaseSemaphore();
456 return TRUE;
460 ERR( "No empty lobbies\n" );
462 DPLAYX_ReleaseSemaphore();
463 return FALSE;
466 /* I'm not sure when I'm going to need this, but here it is */
467 BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
469 UINT i;
471 DPLAYX_AquireSemaphore();
473 /* Find an empty space in the list and insert the data */
474 for( i=0; i < numSupportedLobbies; i++ )
476 if( lobbyData[ i ].dwAppID == dwAppID )
478 /* FIXME: Should free up anything unused. Tisk tisk :0 */
479 /* Mark this entry unused */
480 TRACE( "Marking lobbyData[%u] unused\n", i );
481 DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
483 DPLAYX_ReleaseSemaphore();
484 return TRUE;
488 DPLAYX_ReleaseSemaphore();
489 ERR( "Unable to find global entry for application\n" );
490 return FALSE;
493 BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
494 HANDLE hStart, HANDLE hDeath, HANDLE hConnRead )
496 LPDPLAYX_LOBBYDATA lpLData;
498 /* Need to explictly give lobby application. Can't set for yourself */
499 if( dwAppID == 0 )
501 return FALSE;
504 DPLAYX_AquireSemaphore();
506 if( !DPLAYX_IsAppIdLobbied( dwAppID, &lpLData ) )
508 DPLAYX_ReleaseSemaphore();
509 return FALSE;
512 lpLData->hInformOnAppStart = hStart;
513 lpLData->hInformOnAppDeath = hDeath;
514 lpLData->hInformOnSettingRead = hConnRead;
516 DPLAYX_ReleaseSemaphore();
518 return TRUE;
521 BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
522 LPHANDLE lphDeath,
523 LPHANDLE lphConnRead,
524 BOOL bClearSetHandles )
526 LPDPLAYX_LOBBYDATA lpLData;
528 DPLAYX_AquireSemaphore();
530 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData ) )
532 DPLAYX_ReleaseSemaphore();
533 return FALSE;
536 if( lphStart != NULL )
538 if( lpLData->hInformOnAppStart == 0 )
540 DPLAYX_ReleaseSemaphore();
541 return FALSE;
544 *lphStart = lpLData->hInformOnAppStart;
546 if( bClearSetHandles )
548 CloseHandle( lpLData->hInformOnAppStart );
549 lpLData->hInformOnAppStart = 0;
553 if( lphDeath != NULL )
555 if( lpLData->hInformOnAppDeath == 0 )
557 DPLAYX_ReleaseSemaphore();
558 return FALSE;
561 *lphDeath = lpLData->hInformOnAppDeath;
563 if( bClearSetHandles )
565 CloseHandle( lpLData->hInformOnAppDeath );
566 lpLData->hInformOnAppDeath = 0;
570 if( lphConnRead != NULL )
572 if( lpLData->hInformOnSettingRead == 0 )
574 DPLAYX_ReleaseSemaphore();
575 return FALSE;
578 *lphConnRead = lpLData->hInformOnSettingRead;
580 if( bClearSetHandles )
582 CloseHandle( lpLData->hInformOnSettingRead );
583 lpLData->hInformOnSettingRead = 0;
587 DPLAYX_ReleaseSemaphore();
589 return TRUE;
593 HRESULT DPLAYX_GetConnectionSettingsA
594 ( DWORD dwAppID,
595 LPVOID lpData,
596 LPDWORD lpdwDataSize )
598 LPDPLAYX_LOBBYDATA lpDplData;
599 DWORD dwRequiredDataSize = 0;
600 HANDLE hInformOnSettingRead;
602 DPLAYX_AquireSemaphore();
604 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
606 DPLAYX_ReleaseSemaphore();
608 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
609 return DPERR_NOTLOBBIED;
612 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
614 /* Do they want to know the required buffer size or is the provided buffer
615 * big enough?
617 if ( ( lpData == NULL ) ||
618 ( *lpdwDataSize < dwRequiredDataSize )
621 DPLAYX_ReleaseSemaphore();
623 *lpdwDataSize = DPLAYX_SizeOfLobbyDataA( lpDplData->lpConn );
625 return DPERR_BUFFERTOOSMALL;
628 DPLAYX_CopyConnStructA( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
630 DPLAYX_ReleaseSemaphore();
632 /* They have gotten the information - signal the event if required */
633 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
634 hInformOnSettingRead
637 BOOL bSuccess;
638 bSuccess = SetEvent( hInformOnSettingRead );
639 TRACE( "Signalling setting read event %p %s\n",
640 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
642 /* Close out handle */
643 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
646 return DP_OK;
649 /* Assumption: Enough contiguous space was allocated at dest */
650 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest, LPDPLCONNECTION src )
652 BYTE* lpStartOfFreeSpace;
654 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
656 lpStartOfFreeSpace = ((BYTE*)dest) + sizeof( DPLCONNECTION );
658 /* Copy the LPDPSESSIONDESC2 structure if it exists */
659 if( src->lpSessionDesc )
661 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
662 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
663 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
665 /* Session names may or may not exist */
666 if( src->lpSessionDesc->u1.lpszSessionNameA )
668 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
669 dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
670 lpStartOfFreeSpace +=
671 strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
674 if( src->lpSessionDesc->u2.lpszPasswordA )
676 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
677 dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
678 lpStartOfFreeSpace +=
679 strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
683 /* DPNAME structure is optional */
684 if( src->lpPlayerName )
686 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
687 lpStartOfFreeSpace += sizeof( DPNAME );
688 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
690 if( src->lpPlayerName->u1.lpszShortNameA )
692 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
693 dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
694 lpStartOfFreeSpace +=
695 strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
698 if( src->lpPlayerName->u2.lpszLongNameA )
700 strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
701 dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
702 lpStartOfFreeSpace +=
703 strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
708 /* Copy address if it exists */
709 if( src->lpAddress )
711 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
712 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
713 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
717 HRESULT DPLAYX_GetConnectionSettingsW
718 ( DWORD dwAppID,
719 LPVOID lpData,
720 LPDWORD lpdwDataSize )
722 LPDPLAYX_LOBBYDATA lpDplData;
723 DWORD dwRequiredDataSize = 0;
724 HANDLE hInformOnSettingRead;
726 DPLAYX_AquireSemaphore();
728 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
730 DPLAYX_ReleaseSemaphore();
731 return DPERR_NOTLOBBIED;
734 dwRequiredDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
736 /* Do they want to know the required buffer size or is the provided buffer
737 * big enough?
739 if ( ( lpData == NULL ) ||
740 ( *lpdwDataSize < dwRequiredDataSize )
743 DPLAYX_ReleaseSemaphore();
745 *lpdwDataSize = DPLAYX_SizeOfLobbyDataW( lpDplData->lpConn );
747 return DPERR_BUFFERTOOSMALL;
750 DPLAYX_CopyConnStructW( (LPDPLCONNECTION)lpData, lpDplData->lpConn );
752 DPLAYX_ReleaseSemaphore();
754 /* They have gotten the information - signal the event if required */
755 if( DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, FALSE ) &&
756 hInformOnSettingRead
759 BOOL bSuccess;
760 bSuccess = SetEvent( hInformOnSettingRead );
761 TRACE( "Signalling setting read event %p %s\n",
762 hInformOnSettingRead, bSuccess ? "succeed" : "failed" );
764 /* Close out handle */
765 DPLAYX_GetThisLobbyHandles( NULL, NULL, &hInformOnSettingRead, TRUE );
768 return DP_OK;
771 /* Assumption: Enough contiguous space was allocated at dest */
772 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
774 BYTE* lpStartOfFreeSpace;
776 CopyMemory( dest, src, sizeof( DPLCONNECTION ) );
778 lpStartOfFreeSpace = ( (BYTE*)dest) + sizeof( DPLCONNECTION );
780 /* Copy the LPDPSESSIONDESC2 structure if it exists */
781 if( src->lpSessionDesc )
783 dest->lpSessionDesc = (LPDPSESSIONDESC2)lpStartOfFreeSpace;
784 lpStartOfFreeSpace += sizeof( DPSESSIONDESC2 );
785 CopyMemory( dest->lpSessionDesc, src->lpSessionDesc, sizeof( DPSESSIONDESC2 ) );
787 /* Session names may or may not exist */
788 if( src->lpSessionDesc->u1.lpszSessionName )
790 strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
791 src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
792 lpStartOfFreeSpace += sizeof(WCHAR) *
793 ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
796 if( src->lpSessionDesc->u2.lpszPassword )
798 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
799 dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
800 lpStartOfFreeSpace += sizeof(WCHAR) *
801 ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
805 /* DPNAME structure is optional */
806 if( src->lpPlayerName )
808 dest->lpPlayerName = (LPDPNAME)lpStartOfFreeSpace;
809 lpStartOfFreeSpace += sizeof( DPNAME );
810 CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
812 if( src->lpPlayerName->u1.lpszShortName )
814 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
815 dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
816 lpStartOfFreeSpace += sizeof(WCHAR) *
817 ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
820 if( src->lpPlayerName->u2.lpszLongName )
822 strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
823 dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
824 lpStartOfFreeSpace += sizeof(WCHAR) *
825 ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
830 /* Copy address if it exists */
831 if( src->lpAddress )
833 dest->lpAddress = (LPVOID)lpStartOfFreeSpace;
834 CopyMemory( lpStartOfFreeSpace, src->lpAddress, src->dwAddressSize );
835 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
840 /* Store the structure into the shared data structre. Ensure that allocs for
841 * variable length strings come from the shared data structure.
842 * FIXME: We need to free information as well
844 HRESULT DPLAYX_SetConnectionSettingsA
845 ( DWORD dwFlags,
846 DWORD dwAppID,
847 LPDPLCONNECTION lpConn )
849 LPDPLAYX_LOBBYDATA lpDplData;
851 /* Paramater check */
852 if( dwFlags || !lpConn )
854 ERR("invalid parameters.\n");
855 return DPERR_INVALIDPARAMS;
858 /* Store information */
859 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
861 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
862 lpConn->dwSize, sizeof( DPLCONNECTION ) );
864 return DPERR_INVALIDPARAMS;
867 DPLAYX_AquireSemaphore();
869 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
871 DPLAYX_ReleaseSemaphore();
873 return DPERR_NOTLOBBIED;
876 if( (!lpConn->lpSessionDesc ) ||
877 ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
880 DPLAYX_ReleaseSemaphore();
882 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
883 lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
885 return DPERR_INVALIDPARAMS;
888 /* Free the existing memory */
889 DPLAYX_PrivHeapFree( lpDplData->lpConn );
891 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
892 DPLAYX_SizeOfLobbyDataA( lpConn ) );
894 DPLAYX_CopyConnStructA( lpDplData->lpConn, lpConn );
897 DPLAYX_ReleaseSemaphore();
899 /* FIXME: Send a message - I think */
901 return DP_OK;
904 /* Store the structure into the shared data structre. Ensure that allocs for
905 * variable length strings come from the shared data structure.
906 * FIXME: We need to free information as well
908 HRESULT DPLAYX_SetConnectionSettingsW
909 ( DWORD dwFlags,
910 DWORD dwAppID,
911 LPDPLCONNECTION lpConn )
913 LPDPLAYX_LOBBYDATA lpDplData;
915 /* Paramater check */
916 if( dwFlags || !lpConn )
918 ERR("invalid parameters.\n");
919 return DPERR_INVALIDPARAMS;
922 /* Store information */
923 if( lpConn->dwSize != sizeof(DPLCONNECTION) )
925 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
926 lpConn->dwSize, sizeof( DPLCONNECTION ) );
928 return DPERR_INVALIDPARAMS;
931 DPLAYX_AquireSemaphore();
933 if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
935 DPLAYX_ReleaseSemaphore();
937 return DPERR_NOTLOBBIED;
940 /* Free the existing memory */
941 DPLAYX_PrivHeapFree( lpDplData->lpConn );
943 lpDplData->lpConn = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY,
944 DPLAYX_SizeOfLobbyDataW( lpConn ) );
946 DPLAYX_CopyConnStructW( lpDplData->lpConn, lpConn );
949 DPLAYX_ReleaseSemaphore();
951 /* FIXME: Send a message - I think */
953 return DP_OK;
956 DWORD DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn )
958 DWORD dwTotalSize = sizeof( DPLCONNECTION );
960 /* Just a safety check */
961 if( lpConn == NULL )
963 ERR( "lpConn is NULL\n" );
964 return 0;
967 if( lpConn->lpSessionDesc != NULL )
969 dwTotalSize += sizeof( DPSESSIONDESC2 );
971 if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
973 dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
976 if( lpConn->lpSessionDesc->u2.lpszPasswordA )
978 dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
982 if( lpConn->lpPlayerName != NULL )
984 dwTotalSize += sizeof( DPNAME );
986 if( lpConn->lpPlayerName->u1.lpszShortNameA )
988 dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
991 if( lpConn->lpPlayerName->u2.lpszLongNameA )
993 dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
998 dwTotalSize += lpConn->dwAddressSize;
1000 return dwTotalSize;
1003 DWORD DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn )
1005 DWORD dwTotalSize = sizeof( DPLCONNECTION );
1007 /* Just a safety check */
1008 if( lpConn == NULL )
1010 ERR( "lpConn is NULL\n" );
1011 return 0;
1014 if( lpConn->lpSessionDesc != NULL )
1016 dwTotalSize += sizeof( DPSESSIONDESC2 );
1018 if( lpConn->lpSessionDesc->u1.lpszSessionName )
1020 dwTotalSize += sizeof( WCHAR ) *
1021 ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
1024 if( lpConn->lpSessionDesc->u2.lpszPassword )
1026 dwTotalSize += sizeof( WCHAR ) *
1027 ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
1031 if( lpConn->lpPlayerName != NULL )
1033 dwTotalSize += sizeof( DPNAME );
1035 if( lpConn->lpPlayerName->u1.lpszShortName )
1037 dwTotalSize += sizeof( WCHAR ) *
1038 ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
1041 if( lpConn->lpPlayerName->u2.lpszLongName )
1043 dwTotalSize += sizeof( WCHAR ) *
1044 ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
1049 dwTotalSize += lpConn->dwAddressSize;
1051 return dwTotalSize;
1056 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
1058 LPDPSESSIONDESC2 lpSessionDest =
1059 (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
1060 HEAP_ZERO_MEMORY, sizeof( *lpSessionSrc ) );
1061 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
1063 return lpSessionDest;
1066 /* Copy an ANSI session desc structure to the given buffer */
1067 BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
1068 LPCDPSESSIONDESC2 lpSessionSrc )
1070 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
1072 if( lpSessionSrc->u1.lpszSessionNameA )
1074 if ((lpSessionDest->u1.lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0,
1075 strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
1076 strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
1078 if( lpSessionSrc->u2.lpszPasswordA )
1080 if ((lpSessionDest->u2.lpszPasswordA = HeapAlloc( GetProcessHeap(), 0,
1081 strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
1082 strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
1085 return TRUE;
1088 /* Start the index at 0. index will be updated to equal that which should
1089 be passed back into this function for the next element */
1090 LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
1092 for( ; (*index) < numSupportedSessions; (*index)++ )
1094 if( sessionData[(*index)].dwSize != 0 )
1096 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
1100 /* No more sessions */
1101 return NULL;
1104 /* Start the index at 0. index will be updated to equal that which should
1105 be passed back into this function for the next element */
1106 BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
1108 for( ; (*index) < numSupportedSessions; (*index)++ )
1110 if( sessionData[(*index)].dwSize != 0 )
1112 return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
1116 /* No more sessions */
1117 return FALSE;
1120 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
1122 UINT i;
1124 /* FIXME: Is this an error if it exists already? */
1126 /* Crude/wrong implementation for now. Just always add to first empty spot */
1127 for( i=0; i < numSupportedSessions; i++ )
1129 /* Is this one empty? */
1130 if( sessionData[i].dwSize == 0 )
1132 DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
1133 break;
1139 BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait )
1141 LPDPLAYX_LOBBYDATA lpLobbyData;
1143 DPLAYX_AquireSemaphore();
1145 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData ) )
1147 DPLAYX_ReleaseSemaphore();
1148 return FALSE;
1151 lpLobbyData->bWaitForConnectionSettings = bWait;
1153 DPLAYX_ReleaseSemaphore();
1155 return TRUE;
1158 BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1160 UINT i;
1161 BOOL bFound = FALSE;
1163 DPLAYX_AquireSemaphore();
1165 for( i=0; i < numSupportedLobbies; i++ )
1167 if( ( lobbyData[ i ].dwAppID != 0 ) && /* lobby initialized */
1168 ( lobbyData[ i ].bWaitForConnectionSettings ) /* Waiting */
1171 bFound = TRUE;
1172 break;
1176 DPLAYX_ReleaseSemaphore();
1178 return bFound;
1181 BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId )
1183 LPDPLAYX_LOBBYDATA lpLobbyData;
1185 DPLAYX_AquireSemaphore();
1187 if( !DPLAYX_IsAppIdLobbied( dwAppId, &lpLobbyData ) )
1189 DPLAYX_ReleaseSemaphore();
1190 return FALSE;
1193 lpLobbyData->dwLobbyMsgThreadId = dwThreadId;
1195 DPLAYX_ReleaseSemaphore();
1197 return TRUE;
1200 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1201 with the correct string printed in the case where the HRESULT is not
1202 known. You'll just get the last hr passed in printed. This can change
1203 over time if this method is used alot :) */
1204 LPCSTR DPLAYX_HresultToString(HRESULT hr)
1206 static char szTempStr[12];
1208 switch (hr)
1210 case DP_OK:
1211 return "DP_OK";
1212 case DPERR_ALREADYINITIALIZED:
1213 return "DPERR_ALREADYINITIALIZED";
1214 case DPERR_ACCESSDENIED:
1215 return "DPERR_ACCESSDENIED";
1216 case DPERR_ACTIVEPLAYERS:
1217 return "DPERR_ACTIVEPLAYERS";
1218 case DPERR_BUFFERTOOSMALL:
1219 return "DPERR_BUFFERTOOSMALL";
1220 case DPERR_CANTADDPLAYER:
1221 return "DPERR_CANTADDPLAYER";
1222 case DPERR_CANTCREATEGROUP:
1223 return "DPERR_CANTCREATEGROUP";
1224 case DPERR_CANTCREATEPLAYER:
1225 return "DPERR_CANTCREATEPLAYER";
1226 case DPERR_CANTCREATESESSION:
1227 return "DPERR_CANTCREATESESSION";
1228 case DPERR_CAPSNOTAVAILABLEYET:
1229 return "DPERR_CAPSNOTAVAILABLEYET";
1230 case DPERR_EXCEPTION:
1231 return "DPERR_EXCEPTION";
1232 case DPERR_GENERIC:
1233 return "DPERR_GENERIC";
1234 case DPERR_INVALIDFLAGS:
1235 return "DPERR_INVALIDFLAGS";
1236 case DPERR_INVALIDOBJECT:
1237 return "DPERR_INVALIDOBJECT";
1238 case DPERR_INVALIDPARAMS:
1239 return "DPERR_INVALIDPARAMS";
1240 case DPERR_INVALIDPLAYER:
1241 return "DPERR_INVALIDPLAYER";
1242 case DPERR_INVALIDGROUP:
1243 return "DPERR_INVALIDGROUP";
1244 case DPERR_NOCAPS:
1245 return "DPERR_NOCAPS";
1246 case DPERR_NOCONNECTION:
1247 return "DPERR_NOCONNECTION";
1248 case DPERR_OUTOFMEMORY:
1249 return "DPERR_OUTOFMEMORY";
1250 case DPERR_NOMESSAGES:
1251 return "DPERR_NOMESSAGES";
1252 case DPERR_NONAMESERVERFOUND:
1253 return "DPERR_NONAMESERVERFOUND";
1254 case DPERR_NOPLAYERS:
1255 return "DPERR_NOPLAYERS";
1256 case DPERR_NOSESSIONS:
1257 return "DPERR_NOSESSIONS";
1258 case DPERR_PENDING:
1259 return "DPERR_PENDING";
1260 case DPERR_SENDTOOBIG:
1261 return "DPERR_SENDTOOBIG";
1262 case DPERR_TIMEOUT:
1263 return "DPERR_TIMEOUT";
1264 case DPERR_UNAVAILABLE:
1265 return "DPERR_UNAVAILABLE";
1266 case DPERR_UNSUPPORTED:
1267 return "DPERR_UNSUPPORTED";
1268 case DPERR_BUSY:
1269 return "DPERR_BUSY";
1270 case DPERR_USERCANCEL:
1271 return "DPERR_USERCANCEL";
1272 case DPERR_NOINTERFACE:
1273 return "DPERR_NOINTERFACE";
1274 case DPERR_CANNOTCREATESERVER:
1275 return "DPERR_CANNOTCREATESERVER";
1276 case DPERR_PLAYERLOST:
1277 return "DPERR_PLAYERLOST";
1278 case DPERR_SESSIONLOST:
1279 return "DPERR_SESSIONLOST";
1280 case DPERR_UNINITIALIZED:
1281 return "DPERR_UNINITIALIZED";
1282 case DPERR_NONEWPLAYERS:
1283 return "DPERR_NONEWPLAYERS";
1284 case DPERR_INVALIDPASSWORD:
1285 return "DPERR_INVALIDPASSWORD";
1286 case DPERR_CONNECTING:
1287 return "DPERR_CONNECTING";
1288 case DPERR_CONNECTIONLOST:
1289 return "DPERR_CONNECTIONLOST";
1290 case DPERR_UNKNOWNMESSAGE:
1291 return "DPERR_UNKNOWNMESSAGE";
1292 case DPERR_CANCELFAILED:
1293 return "DPERR_CANCELFAILED";
1294 case DPERR_INVALIDPRIORITY:
1295 return "DPERR_INVALIDPRIORITY";
1296 case DPERR_NOTHANDLED:
1297 return "DPERR_NOTHANDLED";
1298 case DPERR_CANCELLED:
1299 return "DPERR_CANCELLED";
1300 case DPERR_ABORTED:
1301 return "DPERR_ABORTED";
1302 case DPERR_BUFFERTOOLARGE:
1303 return "DPERR_BUFFERTOOLARGE";
1304 case DPERR_CANTCREATEPROCESS:
1305 return "DPERR_CANTCREATEPROCESS";
1306 case DPERR_APPNOTSTARTED:
1307 return "DPERR_APPNOTSTARTED";
1308 case DPERR_INVALIDINTERFACE:
1309 return "DPERR_INVALIDINTERFACE";
1310 case DPERR_NOSERVICEPROVIDER:
1311 return "DPERR_NOSERVICEPROVIDER";
1312 case DPERR_UNKNOWNAPPLICATION:
1313 return "DPERR_UNKNOWNAPPLICATION";
1314 case DPERR_NOTLOBBIED:
1315 return "DPERR_NOTLOBBIED";
1316 case DPERR_SERVICEPROVIDERLOADED:
1317 return "DPERR_SERVICEPROVIDERLOADED";
1318 case DPERR_ALREADYREGISTERED:
1319 return "DPERR_ALREADYREGISTERED";
1320 case DPERR_NOTREGISTERED:
1321 return "DPERR_NOTREGISTERED";
1322 case DPERR_AUTHENTICATIONFAILED:
1323 return "DPERR_AUTHENTICATIONFAILED";
1324 case DPERR_CANTLOADSSPI:
1325 return "DPERR_CANTLOADSSPI";
1326 case DPERR_ENCRYPTIONFAILED:
1327 return "DPERR_ENCRYPTIONFAILED";
1328 case DPERR_SIGNFAILED:
1329 return "DPERR_SIGNFAILED";
1330 case DPERR_CANTLOADSECURITYPACKAGE:
1331 return "DPERR_CANTLOADSECURITYPACKAGE";
1332 case DPERR_ENCRYPTIONNOTSUPPORTED:
1333 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1334 case DPERR_CANTLOADCAPI:
1335 return "DPERR_CANTLOADCAPI";
1336 case DPERR_NOTLOGGEDIN:
1337 return "DPERR_NOTLOGGEDIN";
1338 case DPERR_LOGONDENIED:
1339 return "DPERR_LOGONDENIED";
1340 default:
1341 /* For errors not in the list, return HRESULT as a string
1342 This part is not thread safe */
1343 WARN( "Unknown error 0x%08lx\n", hr );
1344 wsprintfA( szTempStr, "0x%08lx", hr );
1345 return szTempStr;