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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * o Implementation of all things which are associated with dplay on
23 * the computer - ie shared resources and such. Methods in this
24 * compilation unit should not call anything out side this unit
25 * excepting 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.
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "wine/debug.h"
41 #include "wine/unicode.h"
46 #include "dplayx_global.h"
47 #include "dplayx_messages.h" /* For CreateMessageReceptionThread only */
49 WINE_DEFAULT_DEBUG_CHANNEL(dplay
);
51 /* FIXME: Need to do all that fun other dll referencing type of stuff */
53 /* Static data for all processes */
54 static LPCSTR lpszDplayxSemaName
= "WINE_DPLAYX_SM";
55 static HANDLE hDplayxSema
;
57 static LPCSTR lpszDplayxFileMapping
= "WINE_DPLAYX_FM";
58 static HANDLE hDplayxSharedMem
;
60 static LPVOID lpSharedStaticData
= NULL
;
63 #define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX semaphore\n" ); \
64 WaitForSingleObject( hDplayxSema, INFINITE );\
65 TRACE( "Through wait\n" )
67 #define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
68 TRACE( "DPLAYX Semaphore released\n" ) /* FIXME: Is this correct? */
71 /* HACK for simple global data right now */
72 #define dwStaticSharedSize (128 * 1024) /* 128 KBytes */
73 #define dwDynamicSharedSize (512 * 1024) /* 512 KBytes */
74 #define dwTotalSharedSize ( dwStaticSharedSize + dwDynamicSharedSize )
77 /* FIXME: Is there no easier way? */
79 /* Pretend the entire dynamic area is carved up into 512 byte blocks.
80 * Each block has 4 bytes which are 0 unless used */
81 #define dwBlockSize 512
82 #define dwMaxBlock (dwDynamicSharedSize/dwBlockSize)
87 DWORD data
[dwBlockSize
-sizeof(DWORD
)];
90 static DPLAYX_MEM_SLICE
* lpMemArea
;
92 void DPLAYX_PrivHeapFree( LPVOID addr
);
93 void DPLAYX_PrivHeapFree( LPVOID addr
)
98 /* Handle getting passed a NULL */
104 lpAddrStart
= (char*)addr
- sizeof(DWORD
); /* Find block header */
105 dwBlockUsed
= ((BYTE
*)lpAddrStart
- (BYTE
*)lpMemArea
)/dwBlockSize
;
107 lpMemArea
[ dwBlockUsed
].used
= 0;
110 /* FIXME: This should be static, but is being used for a hack right now */
111 LPVOID
DPLAYX_PrivHeapAlloc( DWORD flags
, DWORD size
);
112 LPVOID
DPLAYX_PrivHeapAlloc( DWORD flags
, DWORD size
)
114 LPVOID lpvArea
= NULL
;
117 if( size
> (dwBlockSize
- sizeof(DWORD
)) )
119 FIXME( "Size exceeded. Request of 0x%08lx\n", size
);
120 size
= dwBlockSize
- sizeof(DWORD
);
123 /* Find blank area */
125 while( ( lpMemArea
[ uBlockUsed
].used
!= 0 ) && ( uBlockUsed
<= dwMaxBlock
) ) { uBlockUsed
++; }
127 if( uBlockUsed
<= dwMaxBlock
)
129 /* Set the area used */
130 lpMemArea
[ uBlockUsed
].used
= 1;
131 lpvArea
= &(lpMemArea
[ uBlockUsed
].data
);
135 ERR( "No free block found\n" );
139 if( flags
& HEAP_ZERO_MEMORY
)
141 ZeroMemory( lpvArea
, size
);
147 LPSTR
DPLAYX_strdupA( DWORD flags
, LPCSTR str
);
148 LPSTR
DPLAYX_strdupA( DWORD flags
, LPCSTR str
)
150 LPSTR p
= DPLAYX_PrivHeapAlloc( flags
, strlen(str
) + 1 );
157 LPWSTR
DPLAYX_strdupW( DWORD flags
, LPCWSTR str
);
158 LPWSTR
DPLAYX_strdupW( DWORD flags
, LPCWSTR str
)
160 INT len
= strlenW(str
) + 1;
161 LPWSTR p
= DPLAYX_PrivHeapAlloc( flags
, len
* sizeof(WCHAR
) );
169 enum { numSupportedLobbies
= 32, numSupportedSessions
= 32 };
170 typedef struct tagDPLAYX_LOBBYDATA
172 /* Points to lpConn + block of contiguous extra memory for dynamic parts
173 * of the struct directly following
175 LPDPLCONNECTION lpConn
;
177 /* Information for dplobby interfaces */
179 DWORD dwAppLaunchedFromID
;
181 /* Should this lobby app send messages to creator at important life
184 HANDLE hInformOnAppStart
;
185 HANDLE hInformOnAppDeath
;
186 HANDLE hInformOnSettingRead
;
189 BOOL bWaitForConnectionSettings
;
190 DWORD dwLobbyMsgThreadId
;
193 } DPLAYX_LOBBYDATA
, *LPDPLAYX_LOBBYDATA
;
195 static DPLAYX_LOBBYDATA
* lobbyData
= NULL
;
196 /* static DPLAYX_LOBBYDATA lobbyData[ numSupportedLobbies ]; */
198 static DPSESSIONDESC2
* sessionData
= NULL
;
199 /* static DPSESSIONDESC2* sessionData[ numSupportedSessions ]; */
201 /* Function prototypes */
202 DWORD
DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpDplData
);
203 DWORD
DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpDplData
);
204 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest
, LPDPLCONNECTION src
);
205 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest
, LPDPLCONNECTION src
);
206 BOOL
DPLAYX_IsAppIdLobbied( DWORD dwAppId
, LPDPLAYX_LOBBYDATA
* dplData
);
207 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData
);
208 BOOL
DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest
,
209 LPCDPSESSIONDESC2 lpSessionSrc
);
213 /***************************************************************************
214 * Called to initialize the global data. This will only be used on the
216 ***************************************************************************/
217 BOOL
DPLAYX_ConstructData(void)
219 SECURITY_ATTRIBUTES s_attrib
;
220 BOOL bInitializeSharedMemory
= FALSE
;
221 LPVOID lpDesiredMemoryMapStart
= (LPVOID
)0x50000000;
222 HANDLE hInformOnStart
;
224 TRACE( "DPLAYX dll loaded - construct called\n" );
226 /* Create a semaphore to block access to DPLAYX global data structs */
228 s_attrib
.bInheritHandle
= TRUE
;
229 s_attrib
.lpSecurityDescriptor
= NULL
;
230 s_attrib
.nLength
= sizeof(s_attrib
);
232 hDplayxSema
= CreateSemaphoreA( &s_attrib
, 0, 1, lpszDplayxSemaName
);
234 /* First instance creates the semaphore. Others just use it */
235 if( GetLastError() == ERROR_SUCCESS
)
237 TRACE( "Semaphore %p created\n", hDplayxSema
);
239 /* The semaphore creator will also build the shared memory */
240 bInitializeSharedMemory
= TRUE
;
242 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
244 TRACE( "Found semaphore handle %p\n", hDplayxSema
);
245 DPLAYX_AquireSemaphore();
249 ERR( ": semaphore error %ld\n", GetLastError() );
253 SetLastError( ERROR_SUCCESS
);
255 hDplayxSharedMem
= CreateFileMappingA( INVALID_HANDLE_VALUE
,
257 PAGE_READWRITE
| SEC_COMMIT
,
260 lpszDplayxFileMapping
);
262 if( GetLastError() == ERROR_SUCCESS
)
264 TRACE( "File mapped %p created\n", hDplayxSharedMem
);
266 else if ( GetLastError() == ERROR_ALREADY_EXISTS
)
268 TRACE( "Found FileMapping handle %p\n", hDplayxSharedMem
);
272 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
273 DPLAYX_ReleaseSemaphore();
277 lpSharedStaticData
= MapViewOfFileEx( hDplayxSharedMem
,
279 0, 0, 0, lpDesiredMemoryMapStart
);
281 if( lpSharedStaticData
== NULL
)
283 ERR( ": unable to map static data into process memory space (%ld)\n",
285 DPLAYX_ReleaseSemaphore();
290 if( lpDesiredMemoryMapStart
== lpSharedStaticData
)
292 TRACE( "File mapped to %p\n", lpSharedStaticData
);
296 /* Presently the shared data structures use pointers. If the
297 * files are no mapped into the same area, the pointers will no
298 * longer make any sense :(
299 * FIXME: In the future make the shared data structures have some
300 * sort of fixup to make them independent between data spaces.
301 * This will also require a rework of the session data stuff.
303 ERR( "File mapped to %p (not %p). Expect failure\n",
304 lpSharedStaticData
, lpDesiredMemoryMapStart
);
308 /* Dynamic area starts just after the static area */
309 lpMemArea
= (LPVOID
)((BYTE
*)lpSharedStaticData
+ dwStaticSharedSize
);
311 /* FIXME: Crude hack */
312 lobbyData
= (DPLAYX_LOBBYDATA
*)lpSharedStaticData
;
313 sessionData
= (DPSESSIONDESC2
*)((BYTE
*)lpSharedStaticData
+ (dwStaticSharedSize
/2));
315 /* Initialize shared data segments. */
316 if( bInitializeSharedMemory
)
320 TRACE( "Initializing shared memory\n" );
322 /* Set all lobbies to be "empty" */
323 for( i
=0; i
< numSupportedLobbies
; i
++ )
325 DPLAYX_InitializeLobbyDataEntry( &lobbyData
[ i
] );
328 /* Set all sessions to be "empty" */
329 for( i
=0; i
< numSupportedSessions
; i
++ )
331 sessionData
[i
].dwSize
= 0;
334 /* Zero out the dynmaic area */
335 ZeroMemory( lpMemArea
, dwDynamicSharedSize
);
337 /* Just for fun sync the whole data area */
338 FlushViewOfFile( lpSharedStaticData
, dwTotalSharedSize
);
341 DPLAYX_ReleaseSemaphore();
343 /* Everything was created correctly. Signal the lobby client that
344 * we started up correctly
346 if( DPLAYX_GetThisLobbyHandles( &hInformOnStart
, NULL
, NULL
, FALSE
) &&
351 bSuccess
= SetEvent( hInformOnStart
);
352 TRACE( "Signalling lobby app start event %p %s\n",
353 hInformOnStart
, bSuccess
? "succeed" : "failed" );
355 /* Close out handle */
356 DPLAYX_GetThisLobbyHandles( &hInformOnStart
, NULL
, NULL
, TRUE
);
362 /***************************************************************************
363 * Called to destroy all global data. This will only be used on the
364 * unloading of the dll
365 ***************************************************************************/
366 BOOL
DPLAYX_DestructData(void)
368 HANDLE hInformOnDeath
;
370 TRACE( "DPLAYX dll unloaded - destruct called\n" );
372 /* If required, inform that this app is dying */
373 if( DPLAYX_GetThisLobbyHandles( NULL
, &hInformOnDeath
, NULL
, FALSE
) &&
378 bSuccess
= SetEvent( hInformOnDeath
);
379 TRACE( "Signalling lobby app death event %p %s\n",
380 hInformOnDeath
, bSuccess
? "succeed" : "failed" );
382 /* Close out handle */
383 DPLAYX_GetThisLobbyHandles( NULL
, &hInformOnDeath
, NULL
, TRUE
);
386 /* DO CLEAN UP (LAST) */
388 /* Delete the semaphore */
389 CloseHandle( hDplayxSema
);
391 /* Delete shared memory file mapping */
392 UnmapViewOfFile( lpSharedStaticData
);
393 CloseHandle( hDplayxSharedMem
);
399 void DPLAYX_InitializeLobbyDataEntry( LPDPLAYX_LOBBYDATA lpData
)
401 ZeroMemory( lpData
, sizeof( *lpData
) );
404 /* NOTE: This must be called with the semaphore aquired.
405 * TRUE/FALSE with a pointer to it's data returned. Pointer data is
406 * is only valid if TRUE is returned.
408 BOOL
DPLAYX_IsAppIdLobbied( DWORD dwAppID
, LPDPLAYX_LOBBYDATA
* lplpDplData
)
416 dwAppID
= GetCurrentProcessId();
417 TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID
);
420 for( i
=0; i
< numSupportedLobbies
; i
++ )
422 if( lobbyData
[ i
].dwAppID
== dwAppID
)
424 /* This process is lobbied */
425 TRACE( "Found 0x%08lx @ %u\n", dwAppID
, i
);
426 *lplpDplData
= &lobbyData
[ i
];
434 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
435 BOOL
DPLAYX_CreateLobbyApplication( DWORD dwAppID
)
439 /* 0 is the marker for unused application data slots */
445 DPLAYX_AquireSemaphore();
447 /* Find an empty space in the list and insert the data */
448 for( i
=0; i
< numSupportedLobbies
; i
++ )
450 if( lobbyData
[ i
].dwAppID
== 0 )
452 /* This process is now lobbied */
453 TRACE( "Setting lobbyData[%u] for (0x%08lx,0x%08lx)\n",
454 i
, dwAppID
, GetCurrentProcessId() );
456 lobbyData
[ i
].dwAppID
= dwAppID
;
457 lobbyData
[ i
].dwAppLaunchedFromID
= GetCurrentProcessId();
459 /* FIXME: Where is the best place for this? In interface or here? */
460 lobbyData
[ i
].hInformOnAppStart
= 0;
461 lobbyData
[ i
].hInformOnAppDeath
= 0;
462 lobbyData
[ i
].hInformOnSettingRead
= 0;
464 DPLAYX_ReleaseSemaphore();
469 ERR( "No empty lobbies\n" );
471 DPLAYX_ReleaseSemaphore();
475 /* I'm not sure when I'm going to need this, but here it is */
476 BOOL
DPLAYX_DestroyLobbyApplication( DWORD dwAppID
)
480 DPLAYX_AquireSemaphore();
482 /* Find an empty space in the list and insert the data */
483 for( i
=0; i
< numSupportedLobbies
; i
++ )
485 if( lobbyData
[ i
].dwAppID
== dwAppID
)
487 /* FIXME: Should free up anything unused. Tisk tisk :0 */
488 /* Mark this entry unused */
489 TRACE( "Marking lobbyData[%u] unused\n", i
);
490 DPLAYX_InitializeLobbyDataEntry( &lobbyData
[ i
] );
492 DPLAYX_ReleaseSemaphore();
497 DPLAYX_ReleaseSemaphore();
498 ERR( "Unable to find global entry for application\n" );
502 BOOL
DPLAYX_SetLobbyHandles( DWORD dwAppID
,
503 HANDLE hStart
, HANDLE hDeath
, HANDLE hConnRead
)
505 LPDPLAYX_LOBBYDATA lpLData
;
507 /* Need to explictly give lobby application. Can't set for yourself */
513 DPLAYX_AquireSemaphore();
515 if( !DPLAYX_IsAppIdLobbied( dwAppID
, &lpLData
) )
517 DPLAYX_ReleaseSemaphore();
521 lpLData
->hInformOnAppStart
= hStart
;
522 lpLData
->hInformOnAppDeath
= hDeath
;
523 lpLData
->hInformOnSettingRead
= hConnRead
;
525 DPLAYX_ReleaseSemaphore();
530 BOOL
DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart
,
532 LPHANDLE lphConnRead
,
533 BOOL bClearSetHandles
)
535 LPDPLAYX_LOBBYDATA lpLData
;
537 DPLAYX_AquireSemaphore();
539 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData
) )
541 DPLAYX_ReleaseSemaphore();
545 if( lphStart
!= NULL
)
547 if( lpLData
->hInformOnAppStart
== 0 )
549 DPLAYX_ReleaseSemaphore();
553 *lphStart
= lpLData
->hInformOnAppStart
;
555 if( bClearSetHandles
)
557 CloseHandle( lpLData
->hInformOnAppStart
);
558 lpLData
->hInformOnAppStart
= 0;
562 if( lphDeath
!= NULL
)
564 if( lpLData
->hInformOnAppDeath
== 0 )
566 DPLAYX_ReleaseSemaphore();
570 *lphDeath
= lpLData
->hInformOnAppDeath
;
572 if( bClearSetHandles
)
574 CloseHandle( lpLData
->hInformOnAppDeath
);
575 lpLData
->hInformOnAppDeath
= 0;
579 if( lphConnRead
!= NULL
)
581 if( lpLData
->hInformOnSettingRead
== 0 )
583 DPLAYX_ReleaseSemaphore();
587 *lphConnRead
= lpLData
->hInformOnSettingRead
;
589 if( bClearSetHandles
)
591 CloseHandle( lpLData
->hInformOnSettingRead
);
592 lpLData
->hInformOnSettingRead
= 0;
596 DPLAYX_ReleaseSemaphore();
602 HRESULT DPLAYX_GetConnectionSettingsA
605 LPDWORD lpdwDataSize
)
607 LPDPLAYX_LOBBYDATA lpDplData
;
608 DWORD dwRequiredDataSize
= 0;
609 HANDLE hInformOnSettingRead
;
611 DPLAYX_AquireSemaphore();
613 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
615 DPLAYX_ReleaseSemaphore();
617 TRACE( "Application 0x%08lx is not lobbied\n", dwAppID
);
618 return DPERR_NOTLOBBIED
;
621 dwRequiredDataSize
= DPLAYX_SizeOfLobbyDataA( lpDplData
->lpConn
);
623 /* Do they want to know the required buffer size or is the provided buffer
626 if ( ( lpData
== NULL
) ||
627 ( *lpdwDataSize
< dwRequiredDataSize
)
630 DPLAYX_ReleaseSemaphore();
632 *lpdwDataSize
= DPLAYX_SizeOfLobbyDataA( lpDplData
->lpConn
);
634 return DPERR_BUFFERTOOSMALL
;
637 DPLAYX_CopyConnStructA( (LPDPLCONNECTION
)lpData
, lpDplData
->lpConn
);
639 DPLAYX_ReleaseSemaphore();
641 /* They have gotten the information - signal the event if required */
642 if( DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, FALSE
) &&
647 bSuccess
= SetEvent( hInformOnSettingRead
);
648 TRACE( "Signalling setting read event %p %s\n",
649 hInformOnSettingRead
, bSuccess
? "succeed" : "failed" );
651 /* Close out handle */
652 DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, TRUE
);
658 /* Assumption: Enough contiguous space was allocated at dest */
659 void DPLAYX_CopyConnStructA( LPDPLCONNECTION dest
, LPDPLCONNECTION src
)
661 BYTE
* lpStartOfFreeSpace
;
663 CopyMemory( dest
, src
, sizeof( DPLCONNECTION
) );
665 lpStartOfFreeSpace
= ((BYTE
*)dest
) + sizeof( DPLCONNECTION
);
667 /* Copy the LPDPSESSIONDESC2 structure if it exists */
668 if( src
->lpSessionDesc
)
670 dest
->lpSessionDesc
= (LPDPSESSIONDESC2
)lpStartOfFreeSpace
;
671 lpStartOfFreeSpace
+= sizeof( DPSESSIONDESC2
);
672 CopyMemory( dest
->lpSessionDesc
, src
->lpSessionDesc
, sizeof( DPSESSIONDESC2
) );
674 /* Session names may or may not exist */
675 if( src
->lpSessionDesc
->u1
.lpszSessionNameA
)
677 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u1
.lpszSessionNameA
);
678 dest
->lpSessionDesc
->u1
.lpszSessionNameA
= (LPSTR
)lpStartOfFreeSpace
;
679 lpStartOfFreeSpace
+=
680 strlen( (LPSTR
)dest
->lpSessionDesc
->u1
.lpszSessionNameA
) + 1;
683 if( src
->lpSessionDesc
->u2
.lpszPasswordA
)
685 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u2
.lpszPasswordA
);
686 dest
->lpSessionDesc
->u2
.lpszPasswordA
= (LPSTR
)lpStartOfFreeSpace
;
687 lpStartOfFreeSpace
+=
688 strlen( (LPSTR
)dest
->lpSessionDesc
->u2
.lpszPasswordA
) + 1;
692 /* DPNAME structure is optional */
693 if( src
->lpPlayerName
)
695 dest
->lpPlayerName
= (LPDPNAME
)lpStartOfFreeSpace
;
696 lpStartOfFreeSpace
+= sizeof( DPNAME
);
697 CopyMemory( dest
->lpPlayerName
, src
->lpPlayerName
, sizeof( DPNAME
) );
699 if( src
->lpPlayerName
->u1
.lpszShortNameA
)
701 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u1
.lpszShortNameA
);
702 dest
->lpPlayerName
->u1
.lpszShortNameA
= (LPSTR
)lpStartOfFreeSpace
;
703 lpStartOfFreeSpace
+=
704 strlen( (LPSTR
)dest
->lpPlayerName
->u1
.lpszShortNameA
) + 1;
707 if( src
->lpPlayerName
->u2
.lpszLongNameA
)
709 strcpy( (LPSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u2
.lpszLongNameA
);
710 dest
->lpPlayerName
->u2
.lpszLongNameA
= (LPSTR
)lpStartOfFreeSpace
;
711 lpStartOfFreeSpace
+=
712 strlen( (LPSTR
)dest
->lpPlayerName
->u2
.lpszLongName
) + 1 ;
717 /* Copy address if it exists */
720 dest
->lpAddress
= (LPVOID
)lpStartOfFreeSpace
;
721 CopyMemory( lpStartOfFreeSpace
, src
->lpAddress
, src
->dwAddressSize
);
722 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
726 HRESULT DPLAYX_GetConnectionSettingsW
729 LPDWORD lpdwDataSize
)
731 LPDPLAYX_LOBBYDATA lpDplData
;
732 DWORD dwRequiredDataSize
= 0;
733 HANDLE hInformOnSettingRead
;
735 DPLAYX_AquireSemaphore();
737 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
739 DPLAYX_ReleaseSemaphore();
740 return DPERR_NOTLOBBIED
;
743 dwRequiredDataSize
= DPLAYX_SizeOfLobbyDataW( lpDplData
->lpConn
);
745 /* Do they want to know the required buffer size or is the provided buffer
748 if ( ( lpData
== NULL
) ||
749 ( *lpdwDataSize
< dwRequiredDataSize
)
752 DPLAYX_ReleaseSemaphore();
754 *lpdwDataSize
= DPLAYX_SizeOfLobbyDataW( lpDplData
->lpConn
);
756 return DPERR_BUFFERTOOSMALL
;
759 DPLAYX_CopyConnStructW( (LPDPLCONNECTION
)lpData
, lpDplData
->lpConn
);
761 DPLAYX_ReleaseSemaphore();
763 /* They have gotten the information - signal the event if required */
764 if( DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, FALSE
) &&
769 bSuccess
= SetEvent( hInformOnSettingRead
);
770 TRACE( "Signalling setting read event %p %s\n",
771 hInformOnSettingRead
, bSuccess
? "succeed" : "failed" );
773 /* Close out handle */
774 DPLAYX_GetThisLobbyHandles( NULL
, NULL
, &hInformOnSettingRead
, TRUE
);
780 /* Assumption: Enough contiguous space was allocated at dest */
781 void DPLAYX_CopyConnStructW( LPDPLCONNECTION dest
, LPDPLCONNECTION src
)
783 BYTE
* lpStartOfFreeSpace
;
785 CopyMemory( dest
, src
, sizeof( DPLCONNECTION
) );
787 lpStartOfFreeSpace
= ( (BYTE
*)dest
) + sizeof( DPLCONNECTION
);
789 /* Copy the LPDPSESSIONDESC2 structure if it exists */
790 if( src
->lpSessionDesc
)
792 dest
->lpSessionDesc
= (LPDPSESSIONDESC2
)lpStartOfFreeSpace
;
793 lpStartOfFreeSpace
+= sizeof( DPSESSIONDESC2
);
794 CopyMemory( dest
->lpSessionDesc
, src
->lpSessionDesc
, sizeof( DPSESSIONDESC2
) );
796 /* Session names may or may not exist */
797 if( src
->lpSessionDesc
->u1
.lpszSessionName
)
799 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, dest
->lpSessionDesc
->u1
.lpszSessionName
);
800 src
->lpSessionDesc
->u1
.lpszSessionName
= (LPWSTR
)lpStartOfFreeSpace
;
801 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
802 ( strlenW( (LPWSTR
)dest
->lpSessionDesc
->u1
.lpszSessionName
) + 1 );
805 if( src
->lpSessionDesc
->u2
.lpszPassword
)
807 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpSessionDesc
->u2
.lpszPassword
);
808 dest
->lpSessionDesc
->u2
.lpszPassword
= (LPWSTR
)lpStartOfFreeSpace
;
809 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
810 ( strlenW( (LPWSTR
)dest
->lpSessionDesc
->u2
.lpszPassword
) + 1 );
814 /* DPNAME structure is optional */
815 if( src
->lpPlayerName
)
817 dest
->lpPlayerName
= (LPDPNAME
)lpStartOfFreeSpace
;
818 lpStartOfFreeSpace
+= sizeof( DPNAME
);
819 CopyMemory( dest
->lpPlayerName
, src
->lpPlayerName
, sizeof( DPNAME
) );
821 if( src
->lpPlayerName
->u1
.lpszShortName
)
823 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u1
.lpszShortName
);
824 dest
->lpPlayerName
->u1
.lpszShortName
= (LPWSTR
)lpStartOfFreeSpace
;
825 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
826 ( strlenW( (LPWSTR
)dest
->lpPlayerName
->u1
.lpszShortName
) + 1 );
829 if( src
->lpPlayerName
->u2
.lpszLongName
)
831 strcpyW( (LPWSTR
)lpStartOfFreeSpace
, src
->lpPlayerName
->u2
.lpszLongName
);
832 dest
->lpPlayerName
->u2
.lpszLongName
= (LPWSTR
)lpStartOfFreeSpace
;
833 lpStartOfFreeSpace
+= sizeof(WCHAR
) *
834 ( strlenW( (LPWSTR
)dest
->lpPlayerName
->u2
.lpszLongName
) + 1 );
839 /* Copy address if it exists */
842 dest
->lpAddress
= (LPVOID
)lpStartOfFreeSpace
;
843 CopyMemory( lpStartOfFreeSpace
, src
->lpAddress
, src
->dwAddressSize
);
844 /* No need to advance lpStartOfFreeSpace as there is no more "dynamic" data */
849 /* Store the structure into the shared data structre. Ensure that allocs for
850 * variable length strings come from the shared data structure.
851 * FIXME: We need to free information as well
853 HRESULT DPLAYX_SetConnectionSettingsA
856 LPDPLCONNECTION lpConn
)
858 LPDPLAYX_LOBBYDATA lpDplData
;
860 /* Parameter check */
861 if( dwFlags
|| !lpConn
)
863 ERR("invalid parameters.\n");
864 return DPERR_INVALIDPARAMS
;
867 /* Store information */
868 if( lpConn
->dwSize
!= sizeof(DPLCONNECTION
) )
870 ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
871 lpConn
->dwSize
, sizeof( DPLCONNECTION
) );
873 return DPERR_INVALIDPARAMS
;
876 DPLAYX_AquireSemaphore();
878 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
880 DPLAYX_ReleaseSemaphore();
882 return DPERR_NOTLOBBIED
;
885 if( (!lpConn
->lpSessionDesc
) ||
886 ( lpConn
->lpSessionDesc
->dwSize
!= sizeof( DPSESSIONDESC2
) )
889 DPLAYX_ReleaseSemaphore();
891 ERR("DPSESSIONDESC passed in? Size=%lu vs. expected=%u bytes\n",
892 lpConn
->lpSessionDesc
->dwSize
, sizeof( DPSESSIONDESC2
) );
894 return DPERR_INVALIDPARAMS
;
897 /* Free the existing memory */
898 DPLAYX_PrivHeapFree( lpDplData
->lpConn
);
900 lpDplData
->lpConn
= DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY
,
901 DPLAYX_SizeOfLobbyDataA( lpConn
) );
903 DPLAYX_CopyConnStructA( lpDplData
->lpConn
, lpConn
);
906 DPLAYX_ReleaseSemaphore();
908 /* FIXME: Send a message - I think */
913 /* Store the structure into the shared data structre. Ensure that allocs for
914 * variable length strings come from the shared data structure.
915 * FIXME: We need to free information as well
917 HRESULT DPLAYX_SetConnectionSettingsW
920 LPDPLCONNECTION lpConn
)
922 LPDPLAYX_LOBBYDATA lpDplData
;
924 /* Parameter check */
925 if( dwFlags
|| !lpConn
)
927 ERR("invalid parameters.\n");
928 return DPERR_INVALIDPARAMS
;
931 /* Store information */
932 if( lpConn
->dwSize
!= sizeof(DPLCONNECTION
) )
934 ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
935 lpConn
->dwSize
, sizeof( DPLCONNECTION
) );
937 return DPERR_INVALIDPARAMS
;
940 DPLAYX_AquireSemaphore();
942 if ( ! DPLAYX_IsAppIdLobbied( dwAppID
, &lpDplData
) )
944 DPLAYX_ReleaseSemaphore();
946 return DPERR_NOTLOBBIED
;
949 /* Free the existing memory */
950 DPLAYX_PrivHeapFree( lpDplData
->lpConn
);
952 lpDplData
->lpConn
= DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY
,
953 DPLAYX_SizeOfLobbyDataW( lpConn
) );
955 DPLAYX_CopyConnStructW( lpDplData
->lpConn
, lpConn
);
958 DPLAYX_ReleaseSemaphore();
960 /* FIXME: Send a message - I think */
965 DWORD
DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn
)
967 DWORD dwTotalSize
= sizeof( DPLCONNECTION
);
969 /* Just a safety check */
972 ERR( "lpConn is NULL\n" );
976 if( lpConn
->lpSessionDesc
!= NULL
)
978 dwTotalSize
+= sizeof( DPSESSIONDESC2
);
980 if( lpConn
->lpSessionDesc
->u1
.lpszSessionNameA
)
982 dwTotalSize
+= strlen( lpConn
->lpSessionDesc
->u1
.lpszSessionNameA
) + 1;
985 if( lpConn
->lpSessionDesc
->u2
.lpszPasswordA
)
987 dwTotalSize
+= strlen( lpConn
->lpSessionDesc
->u2
.lpszPasswordA
) + 1;
991 if( lpConn
->lpPlayerName
!= NULL
)
993 dwTotalSize
+= sizeof( DPNAME
);
995 if( lpConn
->lpPlayerName
->u1
.lpszShortNameA
)
997 dwTotalSize
+= strlen( lpConn
->lpPlayerName
->u1
.lpszShortNameA
) + 1;
1000 if( lpConn
->lpPlayerName
->u2
.lpszLongNameA
)
1002 dwTotalSize
+= strlen( lpConn
->lpPlayerName
->u2
.lpszLongNameA
) + 1;
1007 dwTotalSize
+= lpConn
->dwAddressSize
;
1012 DWORD
DPLAYX_SizeOfLobbyDataW( LPDPLCONNECTION lpConn
)
1014 DWORD dwTotalSize
= sizeof( DPLCONNECTION
);
1016 /* Just a safety check */
1017 if( lpConn
== NULL
)
1019 ERR( "lpConn is NULL\n" );
1023 if( lpConn
->lpSessionDesc
!= NULL
)
1025 dwTotalSize
+= sizeof( DPSESSIONDESC2
);
1027 if( lpConn
->lpSessionDesc
->u1
.lpszSessionName
)
1029 dwTotalSize
+= sizeof( WCHAR
) *
1030 ( strlenW( lpConn
->lpSessionDesc
->u1
.lpszSessionName
) + 1 );
1033 if( lpConn
->lpSessionDesc
->u2
.lpszPassword
)
1035 dwTotalSize
+= sizeof( WCHAR
) *
1036 ( strlenW( lpConn
->lpSessionDesc
->u2
.lpszPassword
) + 1 );
1040 if( lpConn
->lpPlayerName
!= NULL
)
1042 dwTotalSize
+= sizeof( DPNAME
);
1044 if( lpConn
->lpPlayerName
->u1
.lpszShortName
)
1046 dwTotalSize
+= sizeof( WCHAR
) *
1047 ( strlenW( lpConn
->lpPlayerName
->u1
.lpszShortName
) + 1 );
1050 if( lpConn
->lpPlayerName
->u2
.lpszLongName
)
1052 dwTotalSize
+= sizeof( WCHAR
) *
1053 ( strlenW( lpConn
->lpPlayerName
->u2
.lpszLongName
) + 1 );
1058 dwTotalSize
+= lpConn
->dwAddressSize
;
1065 static LPDPSESSIONDESC2
DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc
)
1067 LPDPSESSIONDESC2 lpSessionDest
=
1068 HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof( *lpSessionSrc
) );
1069 DPLAYX_CopyIntoSessionDesc2A( lpSessionDest
, lpSessionSrc
);
1071 return lpSessionDest
;
1074 /* Copy an ANSI session desc structure to the given buffer */
1075 BOOL
DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest
,
1076 LPCDPSESSIONDESC2 lpSessionSrc
)
1078 CopyMemory( lpSessionDest
, lpSessionSrc
, sizeof( *lpSessionSrc
) );
1080 if( lpSessionSrc
->u1
.lpszSessionNameA
)
1082 if ((lpSessionDest
->u1
.lpszSessionNameA
= HeapAlloc( GetProcessHeap(), 0,
1083 strlen(lpSessionSrc
->u1
.lpszSessionNameA
)+1 )))
1084 strcpy( lpSessionDest
->u1
.lpszSessionNameA
, lpSessionSrc
->u1
.lpszSessionNameA
);
1086 if( lpSessionSrc
->u2
.lpszPasswordA
)
1088 if ((lpSessionDest
->u2
.lpszPasswordA
= HeapAlloc( GetProcessHeap(), 0,
1089 strlen(lpSessionSrc
->u2
.lpszPasswordA
)+1 )))
1090 strcpy( lpSessionDest
->u2
.lpszPasswordA
, lpSessionSrc
->u2
.lpszPasswordA
);
1096 /* Start the index at 0. index will be updated to equal that which should
1097 be passed back into this function for the next element */
1098 LPDPSESSIONDESC2
DPLAYX_CopyAndAllocateLocalSession( UINT
* index
)
1100 for( ; (*index
) < numSupportedSessions
; (*index
)++ )
1102 if( sessionData
[(*index
)].dwSize
!= 0 )
1104 return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData
[(*index
)++] );
1108 /* No more sessions */
1112 /* Start the index at 0. index will be updated to equal that which should
1113 be passed back into this function for the next element */
1114 BOOL
DPLAYX_CopyLocalSession( UINT
* index
, LPDPSESSIONDESC2 lpsd
)
1116 for( ; (*index
) < numSupportedSessions
; (*index
)++ )
1118 if( sessionData
[(*index
)].dwSize
!= 0 )
1120 return DPLAYX_CopyIntoSessionDesc2A( lpsd
, &sessionData
[(*index
)++] );
1124 /* No more sessions */
1128 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd
)
1132 /* FIXME: Is this an error if it exists already? */
1134 /* Crude/wrong implementation for now. Just always add to first empty spot */
1135 for( i
=0; i
< numSupportedSessions
; i
++ )
1137 /* Is this one empty? */
1138 if( sessionData
[i
].dwSize
== 0 )
1140 DPLAYX_CopyIntoSessionDesc2A( &sessionData
[i
], lpsd
);
1147 BOOL
DPLAYX_WaitForConnectionSettings( BOOL bWait
)
1149 LPDPLAYX_LOBBYDATA lpLobbyData
;
1151 DPLAYX_AquireSemaphore();
1153 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData
) )
1155 DPLAYX_ReleaseSemaphore();
1159 lpLobbyData
->bWaitForConnectionSettings
= bWait
;
1161 DPLAYX_ReleaseSemaphore();
1166 BOOL
DPLAYX_AnyLobbiesWaitingForConnSettings(void)
1169 BOOL bFound
= FALSE
;
1171 DPLAYX_AquireSemaphore();
1173 for( i
=0; i
< numSupportedLobbies
; i
++ )
1175 if( ( lobbyData
[ i
].dwAppID
!= 0 ) && /* lobby initialized */
1176 ( lobbyData
[ i
].bWaitForConnectionSettings
) /* Waiting */
1184 DPLAYX_ReleaseSemaphore();
1189 BOOL
DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId
, DWORD dwThreadId
)
1191 LPDPLAYX_LOBBYDATA lpLobbyData
;
1193 DPLAYX_AquireSemaphore();
1195 if( !DPLAYX_IsAppIdLobbied( dwAppId
, &lpLobbyData
) )
1197 DPLAYX_ReleaseSemaphore();
1201 lpLobbyData
->dwLobbyMsgThreadId
= dwThreadId
;
1203 DPLAYX_ReleaseSemaphore();
1208 /* NOTE: This is potentially not thread safe. You are not guaranteed to end up
1209 with the correct string printed in the case where the HRESULT is not
1210 known. You will just get the last hr passed in. This can change
1211 over time if this method is used a lot :) */
1212 LPCSTR
DPLAYX_HresultToString(HRESULT hr
)
1214 static char szTempStr
[12];
1220 case DPERR_ALREADYINITIALIZED
:
1221 return "DPERR_ALREADYINITIALIZED";
1222 case DPERR_ACCESSDENIED
:
1223 return "DPERR_ACCESSDENIED";
1224 case DPERR_ACTIVEPLAYERS
:
1225 return "DPERR_ACTIVEPLAYERS";
1226 case DPERR_BUFFERTOOSMALL
:
1227 return "DPERR_BUFFERTOOSMALL";
1228 case DPERR_CANTADDPLAYER
:
1229 return "DPERR_CANTADDPLAYER";
1230 case DPERR_CANTCREATEGROUP
:
1231 return "DPERR_CANTCREATEGROUP";
1232 case DPERR_CANTCREATEPLAYER
:
1233 return "DPERR_CANTCREATEPLAYER";
1234 case DPERR_CANTCREATESESSION
:
1235 return "DPERR_CANTCREATESESSION";
1236 case DPERR_CAPSNOTAVAILABLEYET
:
1237 return "DPERR_CAPSNOTAVAILABLEYET";
1238 case DPERR_EXCEPTION
:
1239 return "DPERR_EXCEPTION";
1241 return "DPERR_GENERIC";
1242 case DPERR_INVALIDFLAGS
:
1243 return "DPERR_INVALIDFLAGS";
1244 case DPERR_INVALIDOBJECT
:
1245 return "DPERR_INVALIDOBJECT";
1246 case DPERR_INVALIDPARAMS
:
1247 return "DPERR_INVALIDPARAMS";
1248 case DPERR_INVALIDPLAYER
:
1249 return "DPERR_INVALIDPLAYER";
1250 case DPERR_INVALIDGROUP
:
1251 return "DPERR_INVALIDGROUP";
1253 return "DPERR_NOCAPS";
1254 case DPERR_NOCONNECTION
:
1255 return "DPERR_NOCONNECTION";
1256 case DPERR_OUTOFMEMORY
:
1257 return "DPERR_OUTOFMEMORY";
1258 case DPERR_NOMESSAGES
:
1259 return "DPERR_NOMESSAGES";
1260 case DPERR_NONAMESERVERFOUND
:
1261 return "DPERR_NONAMESERVERFOUND";
1262 case DPERR_NOPLAYERS
:
1263 return "DPERR_NOPLAYERS";
1264 case DPERR_NOSESSIONS
:
1265 return "DPERR_NOSESSIONS";
1267 return "DPERR_PENDING";
1268 case DPERR_SENDTOOBIG
:
1269 return "DPERR_SENDTOOBIG";
1271 return "DPERR_TIMEOUT";
1272 case DPERR_UNAVAILABLE
:
1273 return "DPERR_UNAVAILABLE";
1274 case DPERR_UNSUPPORTED
:
1275 return "DPERR_UNSUPPORTED";
1277 return "DPERR_BUSY";
1278 case DPERR_USERCANCEL
:
1279 return "DPERR_USERCANCEL";
1280 case DPERR_NOINTERFACE
:
1281 return "DPERR_NOINTERFACE";
1282 case DPERR_CANNOTCREATESERVER
:
1283 return "DPERR_CANNOTCREATESERVER";
1284 case DPERR_PLAYERLOST
:
1285 return "DPERR_PLAYERLOST";
1286 case DPERR_SESSIONLOST
:
1287 return "DPERR_SESSIONLOST";
1288 case DPERR_UNINITIALIZED
:
1289 return "DPERR_UNINITIALIZED";
1290 case DPERR_NONEWPLAYERS
:
1291 return "DPERR_NONEWPLAYERS";
1292 case DPERR_INVALIDPASSWORD
:
1293 return "DPERR_INVALIDPASSWORD";
1294 case DPERR_CONNECTING
:
1295 return "DPERR_CONNECTING";
1296 case DPERR_CONNECTIONLOST
:
1297 return "DPERR_CONNECTIONLOST";
1298 case DPERR_UNKNOWNMESSAGE
:
1299 return "DPERR_UNKNOWNMESSAGE";
1300 case DPERR_CANCELFAILED
:
1301 return "DPERR_CANCELFAILED";
1302 case DPERR_INVALIDPRIORITY
:
1303 return "DPERR_INVALIDPRIORITY";
1304 case DPERR_NOTHANDLED
:
1305 return "DPERR_NOTHANDLED";
1306 case DPERR_CANCELLED
:
1307 return "DPERR_CANCELLED";
1309 return "DPERR_ABORTED";
1310 case DPERR_BUFFERTOOLARGE
:
1311 return "DPERR_BUFFERTOOLARGE";
1312 case DPERR_CANTCREATEPROCESS
:
1313 return "DPERR_CANTCREATEPROCESS";
1314 case DPERR_APPNOTSTARTED
:
1315 return "DPERR_APPNOTSTARTED";
1316 case DPERR_INVALIDINTERFACE
:
1317 return "DPERR_INVALIDINTERFACE";
1318 case DPERR_NOSERVICEPROVIDER
:
1319 return "DPERR_NOSERVICEPROVIDER";
1320 case DPERR_UNKNOWNAPPLICATION
:
1321 return "DPERR_UNKNOWNAPPLICATION";
1322 case DPERR_NOTLOBBIED
:
1323 return "DPERR_NOTLOBBIED";
1324 case DPERR_SERVICEPROVIDERLOADED
:
1325 return "DPERR_SERVICEPROVIDERLOADED";
1326 case DPERR_ALREADYREGISTERED
:
1327 return "DPERR_ALREADYREGISTERED";
1328 case DPERR_NOTREGISTERED
:
1329 return "DPERR_NOTREGISTERED";
1330 case DPERR_AUTHENTICATIONFAILED
:
1331 return "DPERR_AUTHENTICATIONFAILED";
1332 case DPERR_CANTLOADSSPI
:
1333 return "DPERR_CANTLOADSSPI";
1334 case DPERR_ENCRYPTIONFAILED
:
1335 return "DPERR_ENCRYPTIONFAILED";
1336 case DPERR_SIGNFAILED
:
1337 return "DPERR_SIGNFAILED";
1338 case DPERR_CANTLOADSECURITYPACKAGE
:
1339 return "DPERR_CANTLOADSECURITYPACKAGE";
1340 case DPERR_ENCRYPTIONNOTSUPPORTED
:
1341 return "DPERR_ENCRYPTIONNOTSUPPORTED";
1342 case DPERR_CANTLOADCAPI
:
1343 return "DPERR_CANTLOADCAPI";
1344 case DPERR_NOTLOGGEDIN
:
1345 return "DPERR_NOTLOGGEDIN";
1346 case DPERR_LOGONDENIED
:
1347 return "DPERR_LOGONDENIED";
1349 /* For errors not in the list, return HRESULT as a string
1350 This part is not thread safe */
1351 WARN( "Unknown error 0x%08lx\n", hr
);
1352 wsprintfA( szTempStr
, "0x%08lx", hr
);