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.
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
33 #include "wine/unicode.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)
79 DWORD data
[dwBlockSize
-sizeof(DWORD
)];
82 static DPLAYX_MEM_SLICE
* lpMemArea
;
84 void DPLAYX_PrivHeapFree( LPVOID addr
);
85 void DPLAYX_PrivHeapFree( LPVOID addr
)
90 /* Handle getting passed a NULL */
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
;
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 */
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
);
127 ERR( "No free block found\n" );
131 if( flags
& HEAP_ZERO_MEMORY
)
133 ZeroMemory( lpvArea
, size
);
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 );
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
) );
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 */
171 DWORD dwAppLaunchedFromID
;
173 /* Should this lobby app send messages to creator at important life
176 HANDLE hInformOnAppStart
;
177 HANDLE hInformOnAppDeath
;
178 HANDLE hInformOnSettingRead
;
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
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
);
240 ERR( ": semaphore error %ld\n", GetLastError() );
244 SetLastError( ERROR_SUCCESS
);
246 DPLAYX_AquireSemaphore();
248 hDplayxSharedMem
= CreateFileMappingA( INVALID_HANDLE_VALUE
,
250 PAGE_READWRITE
| SEC_COMMIT
,
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
);
265 ERR( ": unable to create shared memory (%ld)\n", GetLastError() );
269 lpSharedStaticData
= MapViewOfFileEx( hDplayxSharedMem
,
271 0, 0, 0, lpDesiredMemoryMapStart
);
273 if( lpSharedStaticData
== NULL
)
275 ERR( ": unable to map static data into process memory space (%ld)\n",
281 if( lpDesiredMemoryMapStart
== lpSharedStaticData
)
283 TRACE( "File mapped to %p\n", lpSharedStaticData
);
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
)
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
) &&
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
);
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
) &&
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
);
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
)
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
];
425 /* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
426 BOOL
DPLAYX_CreateLobbyApplication( DWORD dwAppID
)
430 /* 0 is the marker for unused application data slots */
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();
460 ERR( "No empty lobbies\n" );
462 DPLAYX_ReleaseSemaphore();
466 /* I'm not sure when I'm going to need this, but here it is */
467 BOOL
DPLAYX_DestroyLobbyApplication( DWORD dwAppID
)
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();
488 DPLAYX_ReleaseSemaphore();
489 ERR( "Unable to find global entry for application\n" );
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 */
504 DPLAYX_AquireSemaphore();
506 if( !DPLAYX_IsAppIdLobbied( dwAppID
, &lpLData
) )
508 DPLAYX_ReleaseSemaphore();
512 lpLData
->hInformOnAppStart
= hStart
;
513 lpLData
->hInformOnAppDeath
= hDeath
;
514 lpLData
->hInformOnSettingRead
= hConnRead
;
516 DPLAYX_ReleaseSemaphore();
521 BOOL
DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart
,
523 LPHANDLE lphConnRead
,
524 BOOL bClearSetHandles
)
526 LPDPLAYX_LOBBYDATA lpLData
;
528 DPLAYX_AquireSemaphore();
530 if( !DPLAYX_IsAppIdLobbied( 0, &lpLData
) )
532 DPLAYX_ReleaseSemaphore();
536 if( lphStart
!= NULL
)
538 if( lpLData
->hInformOnAppStart
== 0 )
540 DPLAYX_ReleaseSemaphore();
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();
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();
578 *lphConnRead
= lpLData
->hInformOnSettingRead
;
580 if( bClearSetHandles
)
582 CloseHandle( lpLData
->hInformOnSettingRead
);
583 lpLData
->hInformOnSettingRead
= 0;
587 DPLAYX_ReleaseSemaphore();
593 HRESULT DPLAYX_GetConnectionSettingsA
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
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
) &&
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
);
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 */
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
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
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
) &&
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
);
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 */
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
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 */
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
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 */
956 DWORD
DPLAYX_SizeOfLobbyDataA( LPDPLCONNECTION lpConn
)
958 DWORD dwTotalSize
= sizeof( DPLCONNECTION
);
960 /* Just a safety check */
963 ERR( "lpConn is NULL\n" );
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
;
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" );
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
;
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
);
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 */
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 */
1120 void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd
)
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
);
1139 BOOL
DPLAYX_WaitForConnectionSettings( BOOL bWait
)
1141 LPDPLAYX_LOBBYDATA lpLobbyData
;
1143 DPLAYX_AquireSemaphore();
1145 if( !DPLAYX_IsAppIdLobbied( 0, &lpLobbyData
) )
1147 DPLAYX_ReleaseSemaphore();
1151 lpLobbyData
->bWaitForConnectionSettings
= bWait
;
1153 DPLAYX_ReleaseSemaphore();
1158 BOOL
DPLAYX_AnyLobbiesWaitingForConnSettings(void)
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 */
1176 DPLAYX_ReleaseSemaphore();
1181 BOOL
DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId
, DWORD dwThreadId
)
1183 LPDPLAYX_LOBBYDATA lpLobbyData
;
1185 DPLAYX_AquireSemaphore();
1187 if( !DPLAYX_IsAppIdLobbied( dwAppId
, &lpLobbyData
) )
1189 DPLAYX_ReleaseSemaphore();
1193 lpLobbyData
->dwLobbyMsgThreadId
= dwThreadId
;
1195 DPLAYX_ReleaseSemaphore();
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];
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";
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";
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";
1259 return "DPERR_PENDING";
1260 case DPERR_SENDTOOBIG
:
1261 return "DPERR_SENDTOOBIG";
1263 return "DPERR_TIMEOUT";
1264 case DPERR_UNAVAILABLE
:
1265 return "DPERR_UNAVAILABLE";
1266 case DPERR_UNSUPPORTED
:
1267 return "DPERR_UNSUPPORTED";
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";
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";
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
);