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
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
27 * o Methods that begin with DPLAYX_ are used for dealing with
28 * dplayx.dll data which is accessible from all processes.
32 #include "dplayx_global.h"
34 /* FIXME: Need to do all that fun other dll referencing type of stuff */
36 /* Static data for all processes */
37 static const char lpszDplayxSemaName
[] = "WINE_DPLAYX_SM";
38 static HANDLE hDplayxSema
;
40 static const char lpszDplayxFileMapping
[] = "WINE_DPLAYX_FM";
41 static HANDLE hDplayxSharedMem
;
43 static LPVOID lpSharedStaticData
= NULL
;
46 #define DPLAYX_AcquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
47 WaitForSingleObject( hDplayxSema, INFINITE );\
48 TRACE( "Through wait\n" )
50 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
51 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
54 /* HACK for simple global data right now */
55 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
56 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
57 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
60 /* FIXME: Is there no easier way? */
62 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
63 * Each block has 4 bytes which are 0 unless used */
64 #define dwBlockSize 512
65 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
70 BYTE data
[dwBlockSize
- sizeof(BOOL
)];
72 C_ASSERT(sizeof(DPLAYX_MEM_SLICE
) == dwBlockSize
);
74 static DPLAYX_MEM_SLICE
* lpMemArea
;
76 static void DPLAYX_PrivHeapFree( LPVOID addr
)
81 /* Handle getting passed a NULL */
87 lpAddrStart
= CONTAINING_RECORD(addr
, DPLAYX_MEM_SLICE
, data
); /* Find block header */
88 dwBlockUsed
= ((BYTE
*)lpAddrStart
- (BYTE
*)lpMemArea
)/dwBlockSize
;
90 lpMemArea
[ dwBlockUsed
].used
= FALSE
;
93 static LPVOID
DPLAYX_PrivHeapAlloc( DWORD flags
, DWORD size
)
95 LPVOID lpvArea
= NULL
;
98 if( size
> (dwBlockSize
- sizeof(BOOL
)) )
100 FIXME( "Size exceeded. Request of 0x%08x\n", size
);
101 size
= dwBlockSize
- sizeof(BOOL
);
104 /* Find blank area */
106 while( lpMemArea
[ uBlockUsed
].used
&& uBlockUsed
<= dwMaxBlock
) { uBlockUsed
++; }
108 if( uBlockUsed
<= dwMaxBlock
)
110 /* Set the area used */
111 lpMemArea
[ uBlockUsed
].used
= TRUE
;
112 lpvArea
= lpMemArea
[ uBlockUsed
].data
;
116 ERR( "No free block found\n" );
120 if( flags
& HEAP_ZERO_MEMORY
)
122 ZeroMemory( lpvArea
, size
);
129 enum { numSupportedLobbies
= 32, numSupportedSessions
= 32 };
130 typedef struct tagDPLAYX_LOBBYDATA
132 /* Points to lpConn + block of contiguous extra memory for dynamic parts
133 * of the struct directly following
135 LPDPLCONNECTION lpConn
;
137 /* Information for dplobby interfaces */
139 DWORD dwAppLaunchedFromID
;
141 /* Should this lobby app send messages to creator at important life
144 HANDLE hInformOnAppStart
;
145 HANDLE hInformOnAppDeath
;
146 HANDLE hInformOnSettingRead
;
149 BOOL bWaitForConnectionSettings
;
150 DWORD dwLobbyMsgThreadId
;
153 } DPLAYX_LOBBYDATA
, *LPDPLAYX_LOBBYDATA
;
155 static DPLAYX_LOBBYDATA
* lobbyData
= NULL
;
156 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
158 static DPSESSIONDESC2
* sessionData
= NULL
;
159 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
162 static void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData
)
164 ZeroMemory( lpData
, sizeof( *lpData
) );
167 /* NOTE: This must be called with the semaphore acquired.
168 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
169 * is only valid if TRUE is returned.
171 static BOOL
DPLAYX_IsAppIdLobbied( DWORD dwAppID
, LPDPLAYX_LOBBYDATA
* lplpDplData
)
179 dwAppID
= GetCurrentProcessId();
180 TRACE( "Translated dwAppID == 0 into 0x%08x\n", dwAppID
);
183 for( i
=0; i
< numSupportedLobbies
; i
++ )
185 if( lobbyData
[ i
].dwAppID
== dwAppID
)
187 /* This process is lobbied */
188 TRACE( "Found 0x%08x @ %u\n", dwAppID
, i
);
189 *lplpDplData
= &lobbyData
[ i
];
197 /* Reserve a spot for the new application. TRUE means success and FALSE failure. */
198 BOOL
DPLAYX_CreateLobbyApplication( DWORD dwAppID
)
202 /* 0 is the marker for unused application data slots */
208 DPLAYX_AcquireSemaphore();
210 /* Find an empty space in the list and insert the data */
211 for( i
=0; i
< numSupportedLobbies
; i
++ )
213 if( lobbyData
[ i
].dwAppID
== 0 )
215 /* This process is now lobbied */
216 TRACE( "Setting lobbyData[%u] for (0x%08x,0x%08x)\n",
217 i
, dwAppID
, GetCurrentProcessId() );
219 lobbyData
[ i
].dwAppID
= dwAppID
;
220 lobbyData
[ i
].dwAppLaunchedFromID
= GetCurrentProcessId();
222 /* FIXME: Where is the best place for this? In interface or here? */
223 lobbyData
[ i
].hInformOnAppStart
= 0;
224 lobbyData
[ i
].hInformOnAppDeath
= 0;
225 lobbyData
[ i
].hInformOnSettingRead
= 0;
227 DPLAYX_ReleaseSemaphore();
232 ERR( "No empty lobbies\n" );
234 DPLAYX_ReleaseSemaphore();
238 BOOL
DPLAYX_SetLobbyHandles( DWORD dwAppID
,
239 HANDLE hStart
, HANDLE hDeath
, HANDLE hConnRead
)
241 LPDPLAYX_LOBBYDATA lpLData
;
243 /* Need to explicitly give lobby application. Can't set for yourself */
249 DPLAYX_AcquireSemaphore();
251 if( !DPLAYX_IsAppIdLobbied( dwAppID
, &lpLData
) )
253 DPLAYX_ReleaseSemaphore();
257 lpLData
->hInformOnAppStart
= hStart
;
258 lpLData
->hInformOnAppDeath
= hDeath
;
259 lpLData
->hInformOnSettingRead
= hConnRead
;
261 DPLAYX_ReleaseSemaphore();
266 static BOOL
DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart
,
268 LPHANDLE lphConnRead
,
269 BOOL bClearSetHandles
)
271 LPDPLAYX_LOBBYDATA lpLData
;
273 DPLAYX_AcquireSemaphore();
275 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData
) )
277 DPLAYX_ReleaseSemaphore();
281 if( lphStart
!= NULL
)
283 if( lpLData
->hInformOnAppStart
== 0 )
285 DPLAYX_ReleaseSemaphore();
289 *lphStart
= lpLData
->hInformOnAppStart
;
291 if( bClearSetHandles
)
293 CloseHandle( lpLData
->hInformOnAppStart
);
294 lpLData
->hInformOnAppStart
= 0;
298 if( lphDeath
!= NULL
)
300 if( lpLData
->hInformOnAppDeath
== 0 )
302 DPLAYX_ReleaseSemaphore();
306 *lphDeath
= lpLData
->hInformOnAppDeath
;
308 if( bClearSetHandles
)
310 CloseHandle( lpLData
->hInformOnAppDeath
);
311 lpLData
->hInformOnAppDeath
= 0;
315 if( lphConnRead
!= NULL
)
317 if( lpLData
->hInformOnSettingRead
== 0 )
319 DPLAYX_ReleaseSemaphore();
323 *lphConnRead
= lpLData
->hInformOnSettingRead
;
325 if( bClearSetHandles
)
327 CloseHandle( lpLData
->hInformOnSettingRead
);
328 lpLData
->hInformOnSettingRead
= 0;
332 DPLAYX_ReleaseSemaphore();
337 /***************************************************************************
338 * Called to initialize the global data. This will only be used on the
340 ***************************************************************************/
341 BOOL
DPLAYX_ConstructData(void)
343 SECURITY_ATTRIBUTES s_attrib
;
344 BOOL bInitializeSharedMemory
= FALSE
;
345 LPVOID lpDesiredMemoryMapStart
= (LPVOID
)0x50000000;
346 HANDLE hInformOnStart
;
348 TRACE( "DPLAYX dll loaded - construct called\n" );
350 /* Create a semaphore to block access to DPLAYX global data structs */
352 s_attrib
.bInheritHandle
= TRUE
;
353 s_attrib
.lpSecurityDescriptor
= NULL
;
354 s_attrib
.nLength
= sizeof(s_attrib
);
356 hDplayxSema
= CreateSemaphoreA( &s_attrib
, 0, 1, lpszDplayxSemaName
);
358 /* First instance creates the semaphore. Others just use it */
359 if( GetLastError() == ERROR_SUCCESS
)
361 TRACE( "Semaphore %p created\n", hDplayxSema
);
363 /* The semaphore creator will also build the shared memory */
364 bInitializeSharedMemory
= TRUE
;
366 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
368 TRACE( "Found semaphore handle %p\n", hDplayxSema
);
369 DPLAYX_AcquireSemaphore();
373 ERR( ": semaphore error %d\n", GetLastError() );
377 SetLastError( ERROR_SUCCESS
);
379 hDplayxSharedMem
= CreateFileMappingA( INVALID_HANDLE_VALUE
,
381 PAGE_READWRITE
| SEC_COMMIT
,
384 lpszDplayxFileMapping
);
386 if( GetLastError() == ERROR_SUCCESS
)
388 TRACE( "File mapped %p created\n", hDplayxSharedMem
);
390 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
392 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem
);
396 ERR( ": unable to create shared memory (%d)\n", GetLastError() );
397 DPLAYX_ReleaseSemaphore();
401 lpSharedStaticData
= MapViewOfFileEx( hDplayxSharedMem
,
403 0, 0, 0, lpDesiredMemoryMapStart
);
405 if( lpSharedStaticData
== NULL
)
407 ERR( ": unable to map static data into process memory space (%d)\n",
409 DPLAYX_ReleaseSemaphore();
414 if( lpDesiredMemoryMapStart
== lpSharedStaticData
)
416 TRACE( "File mapped to %p\n", lpSharedStaticData
);
420 /* Presently the shared data structures use pointers. If the
421 * files are not mapped into the same area, the pointers will no
422 * longer make any sense :(
423 * FIXME: In the future make the shared data structures have some
424 * sort of fixup to make them independent between data spaces.
425 * This will also require a rework of the session data stuff.
427 ERR( "File mapped to %p (not %p). Expect failure\n",
428 lpSharedStaticData
, lpDesiredMemoryMapStart
);
432 /* Dynamic area starts just after the static area */
433 lpMemArea
= (LPVOID
)((BYTE
*)lpSharedStaticData
+ dwStaticSharedSize
);
435 /* FIXME: Crude hack */
436 lobbyData
= lpSharedStaticData
;
437 sessionData
= (DPSESSIONDESC2
*)((BYTE
*)lpSharedStaticData
+ (dwStaticSharedSize
/2));
439 /* Initialize shared data segments. */
440 if( bInitializeSharedMemory
)
444 TRACE( "Initializing shared memory\n" );
446 /* Set all lobbies to be "empty" */
447 for( i
=0; i
< numSupportedLobbies
; i
++ )
449 DPLAYX_InitializeLobbyDataEntry( &lobbyData
[ i
] );
452 /* Set all sessions to be "empty" */
453 for( i
=0; i
< numSupportedSessions
; i
++ )
455 sessionData
[i
].dwSize
= 0;
458 /* Zero out the dynamic area */
459 ZeroMemory( lpMemArea
, dwDynamicSharedSize
);
461 /* Just for fun sync the whole data area */
462 FlushViewOfFile( lpSharedStaticData
, dwTotalSharedSize
);
465 DPLAYX_ReleaseSemaphore();
467 /* Everything was created correctly. Signal the lobby client that
468 * we started up correctly
470 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart
, NULL
, NULL
, FALSE
) &&
475 bSuccess
= SetEvent( hInformOnStart
);
476 TRACE( "Signalling lobby app start event %p %s\n",
477 hInformOnStart
, bSuccess
? "succeed" : "failed" );
479 /* Close out handle */
480 DPLAYX_GetThisLobbyHandles( &hInformOnStart
, NULL
, NULL
, TRUE
);
486 /***************************************************************************
487 * Called to destroy all global data. This will only be used on the
488 * unloading of the dll
489 ***************************************************************************/
490 BOOL
DPLAYX_DestructData(void)
492 HANDLE hInformOnDeath
;
494 TRACE( "DPLAYX dll unloaded - destruct called\n" );
496 /* If required, inform that this app is dying */
497 if( DPLAYX_GetThisLobbyHandles( NULL
, &hInformOnDeath
, NULL
, FALSE
) &&
502 bSuccess
= SetEvent( hInformOnDeath
);
503 TRACE( "Signalling lobby app death event %p %s\n",
504 hInformOnDeath
, bSuccess
? "succeed" : "failed" );
506 /* Close out handle */
507 DPLAYX_GetThisLobbyHandles( NULL
, &hInformOnDeath
, NULL
, TRUE
);
510 /* DO CLEAN UP (LAST) */
512 /* Delete the semaphore */
513 CloseHandle( hDplayxSema
);
515 /* Delete shared memory file mapping */
516 UnmapViewOfFile( lpSharedStaticData
);
517 CloseHandle( hDplayxSharedMem
);
523 /* Assumption: Enough contiguous space was allocated at dest */
524 static void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest
, const DPLCONNECTION
*src
)
526 BYTE
* lpStartOfFreeSpace
;
530 lpStartOfFreeSpace
= ((BYTE
*)dest
) + sizeof( DPLCONNECTION
);
532 /* Copy the LPDPSESSIONDESC2 structure if it exists */
533 if( src
->lpSessionDesc
)
535 dest
->lpSessionDesc
= (LPDPSESSIONDESC2
)lpStartOfFreeSpace
;
536 lpStartOfFreeSpace
+= sizeof( DPSESSIONDESC2
);
537 *dest
->lpSessionDesc
= *src
->lpSessionDesc
;
539 /* Session names may or may not exist */
540 if( src
->lpSessionDesc
->u1
.lpszSessionNameA
)
542 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u1
.lpszSessionNameA
);
543 dest
->lpSessionDesc
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
544 lpStartOfFreeSpace
+=
545 strlen( dest
->lpSessionDesc
->u1
.lpszSessionNameA
) + 1;
548 if( src
->lpSessionDesc
->u2
.lpszPasswordA
)
550 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u2
.lpszPasswordA
);
551 dest
->lpSessionDesc
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
552 lpStartOfFreeSpace
+=
553 strlen( dest
->lpSessionDesc
->u2
.lpszPasswordA
) + 1;
557 /* DPNAME structure is optional */
558 if( src
->lpPlayerName
)
560 dest
->lpPlayerName
= (LPDPNAME
)lpStartOfFreeSpace
;
561 lpStartOfFreeSpace
+= sizeof( DPNAME
);
562 *dest
->lpPlayerName
= *src
->lpPlayerName
;
564 if( src
->lpPlayerName
->u1
.lpszShortNameA
)
566 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u1
.lpszShortNameA
);
567 dest
->lpPlayerName
->u1
.lpszShortNameA
= (LPSTR
)lpStartOfFreeSpace
;
568 lpStartOfFreeSpace
+=
569 strlen( dest
->lpPlayerName
->u1
.lpszShortNameA
) + 1;
572 if( src
->lpPlayerName
->u2
.lpszLongNameA
)
574 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u2
.lpszLongNameA
);
575 dest
->lpPlayerName
->u2
.lpszLongNameA
= (LPSTR
)lpStartOfFreeSpace
;
576 lpStartOfFreeSpace
+=
577 strlen( (LPSTR
)dest
->lpPlayerName
->u2
.lpszLongName
) + 1 ;
582 /* Copy address if it exists */
585 dest
->lpAddress
= lpStartOfFreeSpace
;
586 CopyMemory( lpStartOfFreeSpace
, src
->lpAddress
, src
->dwAddressSize
);
587 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
591 /* Assumption: Enough contiguous space was allocated at dest */
592 static void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest
, const DPLCONNECTION
*src
)
594 BYTE
* lpStartOfFreeSpace
;
598 lpStartOfFreeSpace
= ( (BYTE
*)dest
) + sizeof( DPLCONNECTION
);
600 /* Copy the LPDPSESSIONDESC2 structure if it exists */
601 if( src
->lpSessionDesc
)
603 dest
->lpSessionDesc
= (LPDPSESSIONDESC2
)lpStartOfFreeSpace
;
604 lpStartOfFreeSpace
+= sizeof( DPSESSIONDESC2
);
605 *dest
->lpSessionDesc
= *src
->lpSessionDesc
;
607 /* Session names may or may not exist */
608 if( src
->lpSessionDesc
->u1
.lpszSessionName
)
610 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u1
.lpszSessionName
);
611 dest
->lpSessionDesc
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
612 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
613 ( strlenW( dest
->lpSessionDesc
->u1
.lpszSessionName
) + 1 );
616 if( src
->lpSessionDesc
->u2
.lpszPassword
)
618 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u2
.lpszPassword
);
619 dest
->lpSessionDesc
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
620 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
621 ( strlenW( dest
->lpSessionDesc
->u2
.lpszPassword
) + 1 );
625 /* DPNAME structure is optional */
626 if( src
->lpPlayerName
)
628 dest
->lpPlayerName
= (LPDPNAME
)lpStartOfFreeSpace
;
629 lpStartOfFreeSpace
+= sizeof( DPNAME
);
630 *dest
->lpPlayerName
= *src
->lpPlayerName
;
632 if( src
->lpPlayerName
->u1
.lpszShortName
)
634 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u1
.lpszShortName
);
635 dest
->lpPlayerName
->u1
.lpszShortName
= (LPWSTR
)lpStartOfFreeSpace
;
636 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
637 ( strlenW( dest
->lpPlayerName
->u1
.lpszShortName
) + 1 );
640 if( src
->lpPlayerName
->u2
.lpszLongName
)
642 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u2
.lpszLongName
);
643 dest
->lpPlayerName
->u2
.lpszLongName
= (LPWSTR
)lpStartOfFreeSpace
;
644 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
645 ( strlenW( dest
->lpPlayerName
->u2
.lpszLongName
) + 1 );
650 /* Copy address if it exists */
653 dest
->lpAddress
= lpStartOfFreeSpace
;
654 CopyMemory( lpStartOfFreeSpace
, src
->lpAddress
, src
->dwAddressSize
);
655 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
660 static DWORD
DPLAYX_SizeOfLobbyDataA( const DPLCONNECTION
*lpConn
)
662 DWORD dwTotalSize
= sizeof( DPLCONNECTION
);
664 /* Just a safety check */
667 ERR( "lpConn is NULL\n" );
671 if( lpConn
->lpSessionDesc
!= NULL
)
673 dwTotalSize
+= sizeof( DPSESSIONDESC2
);
675 if( lpConn
->lpSessionDesc
->u1
.lpszSessionNameA
)
677 dwTotalSize
+= strlen( lpConn
->lpSessionDesc
->u1
.lpszSessionNameA
) + 1;
680 if( lpConn
->lpSessionDesc
->u2
.lpszPasswordA
)
682 dwTotalSize
+= strlen( lpConn
->lpSessionDesc
->u2
.lpszPasswordA
) + 1;
686 if( lpConn
->lpPlayerName
!= NULL
)
688 dwTotalSize
+= sizeof( DPNAME
);
690 if( lpConn
->lpPlayerName
->u1
.lpszShortNameA
)
692 dwTotalSize
+= strlen( lpConn
->lpPlayerName
->u1
.lpszShortNameA
) + 1;
695 if( lpConn
->lpPlayerName
->u2
.lpszLongNameA
)
697 dwTotalSize
+= strlen( lpConn
->lpPlayerName
->u2
.lpszLongNameA
) + 1;
702 dwTotalSize
+= lpConn
->dwAddressSize
;
707 static DWORD
DPLAYX_SizeOfLobbyDataW( const DPLCONNECTION
*lpConn
)
709 DWORD dwTotalSize
= sizeof( DPLCONNECTION
);
711 /* Just a safety check */
714 ERR( "lpConn is NULL\n" );
718 if( lpConn
->lpSessionDesc
!= NULL
)
720 dwTotalSize
+= sizeof( DPSESSIONDESC2
);
722 if( lpConn
->lpSessionDesc
->u1
.lpszSessionName
)
724 dwTotalSize
+= sizeof( WCHAR
) *
725 ( strlenW( lpConn
->lpSessionDesc
->u1
.lpszSessionName
) + 1 );
728 if( lpConn
->lpSessionDesc
->u2
.lpszPassword
)
730 dwTotalSize
+= sizeof( WCHAR
) *
731 ( strlenW( lpConn
->lpSessionDesc
->u2
.lpszPassword
) + 1 );
735 if( lpConn
->lpPlayerName
!= NULL
)
737 dwTotalSize
+= sizeof( DPNAME
);
739 if( lpConn
->lpPlayerName
->u1
.lpszShortName
)
741 dwTotalSize
+= sizeof( WCHAR
) *
742 ( strlenW( lpConn
->lpPlayerName
->u1
.lpszShortName
) + 1 );
745 if( lpConn
->lpPlayerName
->u2
.lpszLongName
)
747 dwTotalSize
+= sizeof( WCHAR
) *
748 ( strlenW( lpConn
->lpPlayerName
->u2
.lpszLongName
) + 1 );
753 dwTotalSize
+= lpConn
->dwAddressSize
;
758 HRESULT DPLAYX_GetConnectionSettingsA
761 LPDWORD lpdwDataSize
)
763 LPDPLAYX_LOBBYDATA lpDplData
;
764 DWORD dwRequiredDataSize
= 0;
765 HANDLE hInformOnSettingRead
;
767 DPLAYX_AcquireSemaphore();
769 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
771 DPLAYX_ReleaseSemaphore();
773 TRACE( "Application 0x%08x is not lobbied\n", dwAppID
);
774 return DPERR_NOTLOBBIED
;
777 dwRequiredDataSize
= DPLAYX_SizeOfLobbyDataA( lpDplData
->lpConn
);
779 /* Do they want to know the required buffer size or is the provided buffer
782 if ( ( lpData
== NULL
) ||
783 ( *lpdwDataSize
< dwRequiredDataSize
)
786 DPLAYX_ReleaseSemaphore();
788 *lpdwDataSize
= DPLAYX_SizeOfLobbyDataA( lpDplData
->lpConn
);
790 return DPERR_BUFFERTOOSMALL
;
793 DPLAYX_CopyConnStructA( lpData
, lpDplData
->lpConn
);
795 DPLAYX_ReleaseSemaphore();
797 /* They have gotten the information - signal the event if required */
798 if( DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, FALSE
) &&
803 bSuccess
= SetEvent( hInformOnSettingRead
);
804 TRACE( "Signalling setting read event %p %s\n",
805 hInformOnSettingRead
, bSuccess
? "succeed" : "failed" );
807 /* Close out handle */
808 DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, TRUE
);
814 HRESULT DPLAYX_GetConnectionSettingsW
817 LPDWORD lpdwDataSize
)
819 LPDPLAYX_LOBBYDATA lpDplData
;
820 DWORD dwRequiredDataSize
= 0;
821 HANDLE hInformOnSettingRead
;
823 DPLAYX_AcquireSemaphore();
825 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
827 DPLAYX_ReleaseSemaphore();
828 return DPERR_NOTLOBBIED
;
831 dwRequiredDataSize
= DPLAYX_SizeOfLobbyDataW( lpDplData
->lpConn
);
833 /* Do they want to know the required buffer size or is the provided buffer
836 if ( ( lpData
== NULL
) ||
837 ( *lpdwDataSize
< dwRequiredDataSize
)
840 DPLAYX_ReleaseSemaphore();
842 *lpdwDataSize
= DPLAYX_SizeOfLobbyDataW( lpDplData
->lpConn
);
844 return DPERR_BUFFERTOOSMALL
;
847 DPLAYX_CopyConnStructW( lpData
, lpDplData
->lpConn
);
849 DPLAYX_ReleaseSemaphore();
851 /* They have gotten the information - signal the event if required */
852 if( DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, FALSE
) &&
857 bSuccess
= SetEvent( hInformOnSettingRead
);
858 TRACE( "Signalling setting read event %p %s\n",
859 hInformOnSettingRead
, bSuccess
? "succeed" : "failed" );
861 /* Close out handle */
862 DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, TRUE
);
868 /* Store the structure into the shared data structure. Ensure that allocs for
869 * variable length strings come from the shared data structure.
870 * FIXME: We need to free information as well.
872 HRESULT DPLAYX_SetConnectionSettingsA
875 const DPLCONNECTION
*lpConn
)
877 LPDPLAYX_LOBBYDATA lpDplData
;
879 /* Parameter check */
880 if( dwFlags
|| !lpConn
)
882 ERR("invalid parameters.\n");
883 return DPERR_INVALIDPARAMS
;
886 /* Store information */
887 if( lpConn
->dwSize
!= sizeof(DPLCONNECTION
) )
889 ERR(": old/new DPLCONNECTION type? Size=%08x\n", lpConn
->dwSize
);
891 return DPERR_INVALIDPARAMS
;
894 DPLAYX_AcquireSemaphore();
896 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
898 DPLAYX_ReleaseSemaphore();
900 return DPERR_NOTLOBBIED
;
903 if( (!lpConn
->lpSessionDesc
) ||
904 ( lpConn
->lpSessionDesc
->dwSize
!= sizeof( DPSESSIONDESC2
) )
907 DPLAYX_ReleaseSemaphore();
909 ERR("DPSESSIONDESC passed in? Size=%u\n",
910 lpConn
->lpSessionDesc
?lpConn
->lpSessionDesc
->dwSize
:0 );
912 return DPERR_INVALIDPARAMS
;
915 /* Free the existing memory */
916 DPLAYX_PrivHeapFree( lpDplData
->lpConn
);
918 lpDplData
->lpConn
= DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY
,
919 DPLAYX_SizeOfLobbyDataA( lpConn
) );
921 DPLAYX_CopyConnStructA( lpDplData
->lpConn
, lpConn
);
924 DPLAYX_ReleaseSemaphore();
926 /* FIXME: Send a message - I think */
931 /* Store the structure into the shared data structure. Ensure that allocs for
932 * variable length strings come from the shared data structure.
933 * FIXME: We need to free information as well
935 HRESULT DPLAYX_SetConnectionSettingsW
938 const DPLCONNECTION
*lpConn
)
940 LPDPLAYX_LOBBYDATA lpDplData
;
942 /* Parameter check */
943 if( dwFlags
|| !lpConn
)
945 ERR("invalid parameters.\n");
946 return DPERR_INVALIDPARAMS
;
949 /* Store information */
950 if( lpConn
->dwSize
!= sizeof(DPLCONNECTION
) )
952 ERR(": old/new DPLCONNECTION type? Size=%u\n", lpConn
->dwSize
);
954 return DPERR_INVALIDPARAMS
;
957 DPLAYX_AcquireSemaphore();
959 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
961 DPLAYX_ReleaseSemaphore();
963 return DPERR_NOTLOBBIED
;
966 /* Free the existing memory */
967 DPLAYX_PrivHeapFree( lpDplData
->lpConn
);
969 lpDplData
->lpConn
= DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY
,
970 DPLAYX_SizeOfLobbyDataW( lpConn
) );
972 DPLAYX_CopyConnStructW( lpDplData
->lpConn
, lpConn
);
975 DPLAYX_ReleaseSemaphore();
977 /* FIXME: Send a message - I think */
982 BOOL
DPLAYX_WaitForConnectionSettings( BOOL bWait
)
984 LPDPLAYX_LOBBYDATA lpLobbyData
;
986 DPLAYX_AcquireSemaphore();
988 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData
) )
990 DPLAYX_ReleaseSemaphore();
994 lpLobbyData
->bWaitForConnectionSettings
= bWait
;
996 DPLAYX_ReleaseSemaphore();
1001 BOOL
DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1004 BOOL bFound
= FALSE
;
1006 DPLAYX_AcquireSemaphore();
1008 for( i
=0; i
< numSupportedLobbies
; i
++ )
1010 if( ( lobbyData
[ i
].dwAppID
!= 0 ) && /* lobby initialized */
1011 ( lobbyData
[ i
].bWaitForConnectionSettings
) /* Waiting */
1019 DPLAYX_ReleaseSemaphore();
1024 BOOL
DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId
, DWORD dwThreadId
)
1026 LPDPLAYX_LOBBYDATA lpLobbyData
;
1028 DPLAYX_AcquireSemaphore();
1030 if( !DPLAYX_IsAppIdLobbied( dwAppId
, &lpLobbyData
) )
1032 DPLAYX_ReleaseSemaphore();
1036 lpLobbyData
->dwLobbyMsgThreadId
= dwThreadId
;
1038 DPLAYX_ReleaseSemaphore();
1043 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1044 with the correct string printed in the case where the HRESULT is not
1045 known. You will just get the last hr passed in. This can change
1046 over time if this method is used a lot :) */
1047 LPCSTR
DPLAYX_HresultToString(HRESULT hr
)
1049 static char szTempStr
[12];
1055 case DPERR_ALREADYINITIALIZED
:
1056 return "DPERR_ALREADYINITIALIZED";
1057 case DPERR_ACCESSDENIED
:
1058 return "DPERR_ACCESSDENIED";
1059 case DPERR_ACTIVEPLAYERS
:
1060 return "DPERR_ACTIVEPLAYERS";
1061 case DPERR_BUFFERTOOSMALL
:
1062 return "DPERR_BUFFERTOOSMALL";
1063 case DPERR_CANTADDPLAYER
:
1064 return "DPERR_CANTADDPLAYER";
1065 case DPERR_CANTCREATEGROUP
:
1066 return "DPERR_CANTCREATEGROUP";
1067 case DPERR_CANTCREATEPLAYER
:
1068 return "DPERR_CANTCREATEPLAYER";
1069 case DPERR_CANTCREATESESSION
:
1070 return "DPERR_CANTCREATESESSION";
1071 case DPERR_CAPSNOTAVAILABLEYET
:
1072 return "DPERR_CAPSNOTAVAILABLEYET";
1073 case DPERR_EXCEPTION
:
1074 return "DPERR_EXCEPTION";
1076 return "DPERR_GENERIC";
1077 case DPERR_INVALIDFLAGS
:
1078 return "DPERR_INVALIDFLAGS";
1079 case DPERR_INVALIDOBJECT
:
1080 return "DPERR_INVALIDOBJECT";
1081 case DPERR_INVALIDPARAMS
:
1082 return "DPERR_INVALIDPARAMS";
1083 case DPERR_INVALIDPLAYER
:
1084 return "DPERR_INVALIDPLAYER";
1085 case DPERR_INVALIDGROUP
:
1086 return "DPERR_INVALIDGROUP";
1088 return "DPERR_NOCAPS";
1089 case DPERR_NOCONNECTION
:
1090 return "DPERR_NOCONNECTION";
1091 case DPERR_OUTOFMEMORY
:
1092 return "DPERR_OUTOFMEMORY";
1093 case DPERR_NOMESSAGES
:
1094 return "DPERR_NOMESSAGES";
1095 case DPERR_NONAMESERVERFOUND
:
1096 return "DPERR_NONAMESERVERFOUND";
1097 case DPERR_NOPLAYERS
:
1098 return "DPERR_NOPLAYERS";
1099 case DPERR_NOSESSIONS
:
1100 return "DPERR_NOSESSIONS";
1102 return "DPERR_PENDING";
1103 case DPERR_SENDTOOBIG
:
1104 return "DPERR_SENDTOOBIG";
1106 return "DPERR_TIMEOUT";
1107 case DPERR_UNAVAILABLE
:
1108 return "DPERR_UNAVAILABLE";
1109 case DPERR_UNSUPPORTED
:
1110 return "DPERR_UNSUPPORTED";
1112 return "DPERR_BUSY";
1113 case DPERR_USERCANCEL
:
1114 return "DPERR_USERCANCEL";
1115 case DPERR_NOINTERFACE
:
1116 return "DPERR_NOINTERFACE";
1117 case DPERR_CANNOTCREATESERVER
:
1118 return "DPERR_CANNOTCREATESERVER";
1119 case DPERR_PLAYERLOST
:
1120 return "DPERR_PLAYERLOST";
1121 case DPERR_SESSIONLOST
:
1122 return "DPERR_SESSIONLOST";
1123 case DPERR_UNINITIALIZED
:
1124 return "DPERR_UNINITIALIZED";
1125 case DPERR_NONEWPLAYERS
:
1126 return "DPERR_NONEWPLAYERS";
1127 case DPERR_INVALIDPASSWORD
:
1128 return "DPERR_INVALIDPASSWORD";
1129 case DPERR_CONNECTING
:
1130 return "DPERR_CONNECTING";
1131 case DPERR_CONNECTIONLOST
:
1132 return "DPERR_CONNECTIONLOST";
1133 case DPERR_UNKNOWNMESSAGE
:
1134 return "DPERR_UNKNOWNMESSAGE";
1135 case DPERR_CANCELFAILED
:
1136 return "DPERR_CANCELFAILED";
1137 case DPERR_INVALIDPRIORITY
:
1138 return "DPERR_INVALIDPRIORITY";
1139 case DPERR_NOTHANDLED
:
1140 return "DPERR_NOTHANDLED";
1141 case DPERR_CANCELLED
:
1142 return "DPERR_CANCELLED";
1144 return "DPERR_ABORTED";
1145 case DPERR_BUFFERTOOLARGE
:
1146 return "DPERR_BUFFERTOOLARGE";
1147 case DPERR_CANTCREATEPROCESS
:
1148 return "DPERR_CANTCREATEPROCESS";
1149 case DPERR_APPNOTSTARTED
:
1150 return "DPERR_APPNOTSTARTED";
1151 case DPERR_INVALIDINTERFACE
:
1152 return "DPERR_INVALIDINTERFACE";
1153 case DPERR_NOSERVICEPROVIDER
:
1154 return "DPERR_NOSERVICEPROVIDER";
1155 case DPERR_UNKNOWNAPPLICATION
:
1156 return "DPERR_UNKNOWNAPPLICATION";
1157 case DPERR_NOTLOBBIED
:
1158 return "DPERR_NOTLOBBIED";
1159 case DPERR_SERVICEPROVIDERLOADED
:
1160 return "DPERR_SERVICEPROVIDERLOADED";
1161 case DPERR_ALREADYREGISTERED
:
1162 return "DPERR_ALREADYREGISTERED";
1163 case DPERR_NOTREGISTERED
:
1164 return "DPERR_NOTREGISTERED";
1165 case DPERR_AUTHENTICATIONFAILED
:
1166 return "DPERR_AUTHENTICATIONFAILED";
1167 case DPERR_CANTLOADSSPI
:
1168 return "DPERR_CANTLOADSSPI";
1169 case DPERR_ENCRYPTIONFAILED
:
1170 return "DPERR_ENCRYPTIONFAILED";
1171 case DPERR_SIGNFAILED
:
1172 return "DPERR_SIGNFAILED";
1173 case DPERR_CANTLOADSECURITYPACKAGE
:
1174 return "DPERR_CANTLOADSECURITYPACKAGE";
1175 case DPERR_ENCRYPTIONNOTSUPPORTED
:
1176 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1177 case DPERR_CANTLOADCAPI
:
1178 return "DPERR_CANTLOADCAPI";
1179 case DPERR_NOTLOGGEDIN
:
1180 return "DPERR_NOTLOGGEDIN";
1181 case DPERR_LOGONDENIED
:
1182 return "DPERR_LOGONDENIED";
1184 /* For errors not in the list, return HRESULT as a string
1185 This part is not thread safe */
1186 WARN( "Unknown error 0x%08x\n", hr
);
1187 wsprintfA( szTempStr
, "0x%08x", hr
);