Sweden-Number/dlls/dplayx/dplayx_global.c

533 lines
16 KiB
C

/* dplayx.dll global data implementation.
*
* Copyright 1999 - Peter Hunnisett
*
* <presently under construction - contact hunnise@nortelnetworks.com>
*
*/
/* NOTE: Methods that begin with DPLAYX_ are used for dealing with
* dplayx.dll data which is accessible from all processes.
*/
#include "debugtools.h"
#include "winbase.h"
#include "winerror.h"
#include "heap.h" /* Really shouldn't be using those HEAP_strdupA interfaces should I? */
#include "dplayx_global.h"
DEFAULT_DEBUG_CHANNEL(dplay)
/* FIXME: Need to do all that fun other dll referencing type of stuff */
/* FIXME: Need to allocate a giant static area - or a global data type thing for Get/Set */
/* Static data for all processes */
static LPSTR lpszDplayxSemaName = "DPLAYX_SM";
static HANDLE hDplayxSema;
#define DPLAYX_AquireSemaphore() 0L /* WaitForSingleObject( hDplayxSema, INFINITE? ) */
#define DPLAYX_ReleaseSemaphore() 0L /* ReleaseSemaphore( hDplayxSema, ..., ... ) */
/* HACK for simple global data right now */
enum { numSupportedLobbies = 32 };
typedef struct tagDirectPlayLobbyData
{
DWORD dwConnFlags;
DPSESSIONDESC2 sessionDesc;
DPNAME playerName;
GUID guidSP;
LPVOID lpAddress;
DWORD dwAddressSize;
DWORD dwAppID;
HANDLE hReceiveEvent;
} DirectPlayLobbyData, *lpDirectPlayLobbyData;
static DirectPlayLobbyData lobbyData[ numSupportedLobbies ];
/* Function prototypes */
BOOL DPLAYX_AppIdLobbied( DWORD dwAppId, lpDirectPlayLobbyData* dplData );
/***************************************************************************
* Called to initialize the global data. This will only be used on the
* loading of the dll
***************************************************************************/
void DPLAYX_ConstructData(void)
{
UINT i;
TRACE( "DPLAYX dll loaded - construct called\n" );
/* FIXME: This needs to be allocated shared */
hDplayxSema = CreateSemaphoreA( NULL, 0, 1, lpszDplayxSemaName );
if( !hDplayxSema )
{
/* Really don't have any choice but to continue... */
ERR( "Semaphore creation error 0x%08lx\n", GetLastError() );
}
/* Set all lobbies to be "empty" */
for( i=0; i < numSupportedLobbies; i++ )
{
lobbyData[ i ].dwAppID = 0;
}
}
/***************************************************************************
* Called to destroy all global data. This will only be used on the
* unloading of the dll
***************************************************************************/
void DPLAYX_DestructData(void)
{
/* Hmmm...what to call to delete the semaphore? Auto delete? */
TRACE( "DPLAYX dll unloaded - destruct called\n" );
}
/* NOTE: This must be called with the semaphore aquired.
* TRUE/FALSE with a pointer to it's data returned
*/
BOOL DPLAYX_AppIdLobbied( DWORD dwAppID, lpDirectPlayLobbyData* lplpDplData )
{
INT i;
if( dwAppID == 0 )
{
dwAppID = GetCurrentProcessId();
}
for( i=0; i < numSupportedLobbies; i++ )
{
if( lobbyData[ i ].dwAppID == dwAppID )
{
/* This process is lobbied */
*lplpDplData = &lobbyData[ i ];
return TRUE;
}
}
return FALSE;
}
#if !defined( WORKING_PROCESS_SUSPEND )
/* These two functions should not exist. We would normally create a process initially
suspended when we RunApplication. This gives us time to actually store some data
before the new process might try to read it. However, process suspension doesn't
work yet and I'm too stupid to get it going. So, we'll just hack in fine fashion */
DWORD DPLAYX_AquireSemaphoreHack( void )
{
return DPLAYX_AquireSemaphore();
}
DWORD DPLAYX_ReleaseSemaphoreHack( void )
{
return DPLAYX_ReleaseSemaphore();
}
#endif
/* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
{
INT i;
DPLAYX_AquireSemaphore();
for( i=0; i < numSupportedLobbies; i++ )
{
if( lobbyData[ i ].dwAppID == 0 )
{
/* This process is now lobbied */
lobbyData[ i ].dwAppID = dwAppID;
lobbyData[ i ].hReceiveEvent = hReceiveEvent;
DPLAYX_ReleaseSemaphore();
return TRUE;
}
}
DPLAYX_ReleaseSemaphore();
return FALSE;
}
HRESULT DPLAYX_GetConnectionSettingsA
( DWORD dwAppID,
LPVOID lpData,
LPDWORD lpdwDataSize )
{
lpDirectPlayLobbyData lpDplData;
LPDPLCONNECTION lpDplConnection;
DPLAYX_AquireSemaphore();
if ( !DPLAYX_AppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
return DPERR_NOTLOBBIED;
}
/* Verify buffer size */
if ( ( lpData == NULL ) ||
( *lpdwDataSize < sizeof( DPLCONNECTION ) )
)
{
DPLAYX_ReleaseSemaphore();
*lpdwDataSize = sizeof( DPLCONNECTION );
return DPERR_BUFFERTOOSMALL;
}
/* Copy the information */
lpDplConnection = (LPDPLCONNECTION)lpData;
/* Copy everything we've got into here */
/* Need to actually store the stuff here. Check if we've already allocated each field first. */
lpDplConnection->dwSize = sizeof( DPLCONNECTION );
lpDplConnection->dwFlags = lpDplData->dwConnFlags;
/* Copy LPDPSESSIONDESC2 struct */
lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
if( lpDplData->sessionDesc.sess.lpszSessionNameA )
{
lpDplConnection->lpSessionDesc->sess.lpszSessionNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionNameA );
}
if( lpDplData->sessionDesc.pass.lpszPasswordA )
{
lpDplConnection->lpSessionDesc->pass.lpszPasswordA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPasswordA );
}
lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
/* Copy DPNAME struct - seems to be optional - check for existance first */
lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
if( lpDplData->playerName.psn.lpszShortNameA )
{
lpDplConnection->lpPlayerName->psn.lpszShortNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortNameA );
}
if( lpDplData->playerName.pln.lpszLongNameA )
{
lpDplConnection->lpPlayerName->pln.lpszLongNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongNameA );
}
memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
/* Send a message - or only the first time? */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
HRESULT DPLAYX_GetConnectionSettingsW
( DWORD dwAppID,
LPVOID lpData,
LPDWORD lpdwDataSize )
{
lpDirectPlayLobbyData lpDplData;
LPDPLCONNECTION lpDplConnection;
DPLAYX_AquireSemaphore();
if ( !DPLAYX_AppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
return DPERR_NOTLOBBIED;
}
/* Verify buffer size */
if ( ( lpData == NULL ) ||
( *lpdwDataSize < sizeof( DPLCONNECTION ) )
)
{
DPLAYX_ReleaseSemaphore();
*lpdwDataSize = sizeof( DPLCONNECTION );
return DPERR_BUFFERTOOSMALL;
}
/* Copy the information */
lpDplConnection = (LPDPLCONNECTION)lpData;
/* Copy everything we've got into here */
/* Need to actually store the stuff here. Check if we've already allocated each field first. */
lpDplConnection->dwSize = sizeof( DPLCONNECTION );
lpDplConnection->dwFlags = lpDplData->dwConnFlags;
/* Copy LPDPSESSIONDESC2 struct */
lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->sessionDesc ) );
memcpy( lpDplConnection->lpSessionDesc, &lpDplData->sessionDesc, sizeof( lpDplData->sessionDesc ) );
if( lpDplData->sessionDesc.sess.lpszSessionName )
{
lpDplConnection->lpSessionDesc->sess.lpszSessionName =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.sess.lpszSessionName );
}
if( lpDplData->sessionDesc.pass.lpszPassword )
{
lpDplConnection->lpSessionDesc->pass.lpszPassword =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->sessionDesc.pass.lpszPassword );
}
lpDplConnection->lpSessionDesc->dwReserved1 = lpDplData->sessionDesc.dwReserved1;
lpDplConnection->lpSessionDesc->dwReserved2 = lpDplData->sessionDesc.dwReserved2;
/* Copy DPNAME struct - seems to be optional - check for existance first */
lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( lpDplData->playerName ) );
memcpy( lpDplConnection->lpPlayerName, &(lpDplData->playerName), sizeof( lpDplData->playerName ) );
if( lpDplData->playerName.psn.lpszShortName )
{
lpDplConnection->lpPlayerName->psn.lpszShortName =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.psn.lpszShortName );
}
if( lpDplData->playerName.pln.lpszLongName )
{
lpDplConnection->lpPlayerName->pln.lpszLongName =
HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->playerName.pln.lpszLongName );
}
memcpy( &lpDplConnection->guidSP, &lpDplData->guidSP, sizeof( lpDplData->guidSP ) );
lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDplData->dwAddressSize );
memcpy( lpDplConnection->lpAddress, lpDplData->lpAddress, lpDplData->dwAddressSize );
lpDplConnection->dwAddressSize = lpDplData->dwAddressSize;
/* Send a message - or only the first time? */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
HRESULT DPLAYX_SetConnectionSettingsA
( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
lpDirectPlayLobbyData lpDplData;
DPLAYX_AquireSemaphore();
if ( !DPLAYX_AppIdLobbied( dwAppID, &lpDplData ) )
{
/* FIXME: Create a new entry for this dwAppID? */
DPLAYX_ReleaseSemaphore();
return DPERR_GENERIC;
}
/* Paramater check */
if( dwFlags || !lpConn )
{
DPLAYX_ReleaseSemaphore();
ERR("invalid parameters.\n");
return DPERR_INVALIDPARAMS;
}
/* Store information */
if( lpConn->dwSize != sizeof(DPLCONNECTION) )
{
DPLAYX_ReleaseSemaphore();
ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
lpConn->dwSize, sizeof( DPLCONNECTION ) );
return DPERR_INVALIDPARAMS;
}
/* Need to investigate the lpConn->lpSessionDesc to figure out
* what type of session we need to join/create.
*/
if( (!lpConn->lpSessionDesc ) ||
( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
)
{
DPLAYX_ReleaseSemaphore();
ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
return DPERR_INVALIDPARAMS;
}
/* FIXME: How do I store this stuff so that it can be read by all processes? Static area? What about strings? Ewww...large global shared */
/* Need to actually store the stuff here. Check if we've already allocated each field first. */
lpDplData->dwConnFlags = lpConn->dwFlags;
/* Copy LPDPSESSIONDESC2 struct - this is required */
memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
/* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
lpDplData->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA );
else
lpDplData->sessionDesc.sess.lpszSessionNameA = NULL;
if( lpConn->lpSessionDesc->pass.lpszPasswordA )
lpDplData->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA );
else
lpDplData->sessionDesc.pass.lpszPasswordA = NULL;
lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
/* Copy DPNAME struct - seems to be optional - check for existance first */
if( lpConn->lpPlayerName )
{
memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
if( lpConn->lpPlayerName->psn.lpszShortNameA )
lpDplData->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA );
if( lpConn->lpPlayerName->pln.lpszLongNameA )
lpDplData->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA );
}
memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
lpDplData->dwAddressSize = lpConn->dwAddressSize;
/* Send a message - I think */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
HRESULT DPLAYX_SetConnectionSettingsW
( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
lpDirectPlayLobbyData lpDplData;
DPLAYX_AquireSemaphore();
if ( !DPLAYX_AppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
return DPERR_NOTLOBBIED;
}
/* Paramater check */
if( dwFlags || !lpConn )
{
DPLAYX_ReleaseSemaphore();
ERR("invalid parameters.\n");
return DPERR_INVALIDPARAMS;
}
/* Store information */
if( lpConn->dwSize != sizeof(DPLCONNECTION) )
{
DPLAYX_ReleaseSemaphore();
ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
lpConn->dwSize, sizeof( DPLCONNECTION ) );
return DPERR_INVALIDPARAMS;
}
/* Need to investigate the lpConn->lpSessionDesc to figure out
* what type of session we need to join/create.
*/
if( (!lpConn->lpSessionDesc ) ||
( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
)
{
DPLAYX_ReleaseSemaphore();
ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
return DPERR_INVALIDPARAMS;
}
/* FIXME: How do I store this stuff so that it can be read by all processes? Static area? What about strings? Ewww...large global shared */
/* Need to actually store the stuff here. Check if we've already allocated each field first. */
lpDplData->dwConnFlags = lpConn->dwFlags;
/* Copy LPDPSESSIONDESC2 struct - this is required */
memcpy( &lpDplData->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
/* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
if( lpConn->lpSessionDesc->sess.lpszSessionName )
lpDplData->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
else
lpDplData->sessionDesc.sess.lpszSessionName = NULL;
if( lpConn->lpSessionDesc->pass.lpszPassword )
lpDplData->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
else
lpDplData->sessionDesc.pass.lpszPassword = NULL;
lpDplData->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
lpDplData->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
/* Copy DPNAME struct - seems to be optional - check for existance first */
if( lpConn->lpPlayerName )
{
memcpy( &lpDplData->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
if( lpConn->lpPlayerName->psn.lpszShortName )
lpDplData->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName );
if( lpConn->lpPlayerName->pln.lpszLongName )
lpDplData->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
}
memcpy( &lpDplData->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
lpDplData->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
memcpy( lpDplData->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
lpDplData->dwAddressSize = lpConn->dwAddressSize;
/* Send a message - I think */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}