Sweden-Number/dlls/dplayx/dplayx_global.c

828 lines
26 KiB
C

/* dplayx.dll global data implementation.
*
* Copyright 1999,2000 - 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 <stdio.h>
#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 */
/* Static data for all processes */
static LPSTR lpszDplayxSemaName = "WINE_DPLAYX_SM";
static HANDLE hDplayxSema;
#define DPLAYX_AquireSemaphore() TRACE( "Waiting for DPLAYX sema\n" ); \
WaitForSingleObject( hDplayxSema, INFINITE ); TRACE( "Through wait\n" )
#define DPLAYX_ReleaseSemaphore() ReleaseSemaphore( hDplayxSema, 1, NULL ); \
TRACE( "DPLAYX Sema released\n" ); /* FIXME: Is this correct? */
/* HACK for simple global data right now */
enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
typedef struct tagDirectPlayLobbyData
{
/* Just a DPLCONNECTION struct */
DWORD dwConnFlags;
DPSESSIONDESC2 sessionDesc;
DPNAME playerName;
GUID guidSP;
LPVOID lpAddress;
DWORD dwAddressSize;
/* Information for dplobby interfaces */
DWORD dwAppID;
HANDLE hReceiveEvent;
DWORD dwAppLaunchedFromID;
} DirectPlayLobbyData, *lpDirectPlayLobbyData;
static DirectPlayLobbyData lobbyData[ numSupportedLobbies ];
/* Hack for now */
static DPSESSIONDESC2 sessionData[ numSupportedSessions ];
/* Function prototypes */
BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, lpDirectPlayLobbyData* dplData );
void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData );
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
LPCDPSESSIONDESC2 lpSessionSrc );
/***************************************************************************
* 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" );
/* Create a semahopre to block access to DPLAYX global data structs
It starts unblocked, and allows up to 65000 users blocked on it. Seems reasonable
for the time being */
hDplayxSema = CreateSemaphoreA( NULL, 1, 65000, 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++ )
{
DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
}
/* Set all sessions to be "empty" */
for( i=0; i < numSupportedSessions; i++ )
{
sessionData[i].dwSize = 0;
}
}
/***************************************************************************
* Called to destroy all global data. This will only be used on the
* unloading of the dll
***************************************************************************/
void DPLAYX_DestructData(void)
{
TRACE( "DPLAYX dll unloaded - destruct called\n" );
/* delete the semaphore */
CloseHandle( hDplayxSema );
}
void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData )
{
ZeroMemory( lpData, sizeof( *lpData ) );
/* Set the handle to a better invalid value */
lpData->hReceiveEvent = INVALID_HANDLE_VALUE;
}
/* NOTE: This must be called with the semaphore aquired.
* TRUE/FALSE with a pointer to it's data returned. Pointer data is
* is only valid if TRUE is returned.
*/
BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppID, lpDirectPlayLobbyData* lplpDplData )
{
INT i;
*lplpDplData = NULL;
if( dwAppID == 0 )
{
dwAppID = GetCurrentProcessId();
TRACE( "Translated dwAppID == 0 into 0x%08lx\n", dwAppID );
}
for( i=0; i < numSupportedLobbies; i++ )
{
if( lobbyData[ i ].dwAppID == dwAppID )
{
/* This process is lobbied */
*lplpDplData = &lobbyData[ i ];
return TRUE;
}
}
return FALSE;
}
/* Reserve a spot for the new appliction. TRUE means success and FALSE failure. */
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent )
{
UINT i;
/* 0 is the marker for unused application data slots */
if( dwAppID == 0 )
{
return FALSE;
}
DPLAYX_AquireSemaphore();
/* Find an empty space in the list and insert the data */
for( i=0; i < numSupportedLobbies; i++ )
{
if( lobbyData[ i ].dwAppID == 0 )
{
/* This process is now lobbied */
lobbyData[ i ].dwAppID = dwAppID;
lobbyData[ i ].hReceiveEvent = hReceiveEvent;
lobbyData[ i ].dwAppLaunchedFromID = GetCurrentProcessId();
DPLAYX_ReleaseSemaphore();
return TRUE;
}
}
DPLAYX_ReleaseSemaphore();
return FALSE;
}
/* I'm not sure when I'm going to need this, but here it is */
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID )
{
UINT i;
DPLAYX_AquireSemaphore();
/* Find an empty space in the list and insert the data */
for( i=0; i < numSupportedLobbies; i++ )
{
if( lobbyData[ i ].dwAppID == dwAppID )
{
/* Mark this entry unused */
DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
DPLAYX_ReleaseSemaphore();
return TRUE;
}
}
DPLAYX_ReleaseSemaphore();
ERR( "Unable to find global entry for application\n" );
return FALSE;
}
HRESULT DPLAYX_GetConnectionSettingsA
( DWORD dwAppID,
LPVOID lpData,
LPDWORD lpdwDataSize )
{
lpDirectPlayLobbyData lpDplData;
LPDPLCONNECTION lpDplConnection;
/* Verify buffer size */
if ( ( lpData == NULL ) ||
( *lpdwDataSize < sizeof( DPLCONNECTION ) )
)
{
*lpdwDataSize = sizeof( DPLCONNECTION );
return DPERR_BUFFERTOOSMALL;
}
DPLAYX_AquireSemaphore();
if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
TRACE( "Application 0x%08lx is not lobbied\n", dwAppID );
return DPERR_NOTLOBBIED;
}
/* 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;
/* FIXME: 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;
/* Verify buffer size */
if ( ( lpData == NULL ) ||
( *lpdwDataSize < sizeof( DPLCONNECTION ) )
)
{
*lpdwDataSize = sizeof( DPLCONNECTION );
return DPERR_BUFFERTOOSMALL;
}
DPLAYX_AquireSemaphore();
if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
return DPERR_NOTLOBBIED;
}
/* 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;
/* FIXME: Send a message - or only the first time? */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
HRESULT DPLAYX_SetConnectionSettingsA
( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
lpDirectPlayLobbyData lpDplData;
/* Paramater check */
if( dwFlags || !lpConn )
{
ERR("invalid parameters.\n");
return DPERR_INVALIDPARAMS;
}
/* Store information */
if( lpConn->dwSize != sizeof(DPLCONNECTION) )
{
ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
lpConn->dwSize, sizeof( DPLCONNECTION ) );
return DPERR_INVALIDPARAMS;
}
if( dwAppID == 0 )
{
dwAppID = GetCurrentProcessId();
}
DPLAYX_AquireSemaphore();
if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
{
/* FIXME: Create a new entry for this dwAppID? */
DPLAYX_ReleaseSemaphore();
return DPERR_GENERIC;
}
/* Store information */
if( lpConn->dwSize != sizeof(DPLCONNECTION) )
{
DPLAYX_ReleaseSemaphore();
ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u 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=%lu vs. expected=%u 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;
/* FIXME: Send a message - I think */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
HRESULT DPLAYX_SetConnectionSettingsW
( DWORD dwFlags,
DWORD dwAppID,
LPDPLCONNECTION lpConn )
{
lpDirectPlayLobbyData lpDplData;
/* Paramater check */
if( dwFlags || !lpConn )
{
ERR("invalid parameters.\n");
return DPERR_INVALIDPARAMS;
}
/* Store information */
if( lpConn->dwSize != sizeof(DPLCONNECTION) )
{
ERR(": old/new DPLCONNECTION type? Size=%lu vs. expected=%u bytes\n",
lpConn->dwSize, sizeof( DPLCONNECTION ) );
return DPERR_INVALIDPARAMS;
}
if( dwAppID == 0 )
{
dwAppID = GetCurrentProcessId();
}
DPLAYX_AquireSemaphore();
if ( ! DPLAYX_IsAppIdLobbied( dwAppID, &lpDplData ) )
{
DPLAYX_ReleaseSemaphore();
return DPERR_NOTLOBBIED;
}
/* 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=%lu vs. expected=%u 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;
/* FIXME: Send a message - I think */
DPLAYX_ReleaseSemaphore();
return DP_OK;
}
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
{
LPDPSESSIONDESC2 lpSessionDest = (LPDPSESSIONDESC2) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *lpSessionSrc ) );
DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
return lpSessionDest;
}
/* Copy an ANSI session desc structure to the given buffer */
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
LPCDPSESSIONDESC2 lpSessionSrc )
{
memcpy( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
if( lpSessionSrc->sess.lpszSessionNameA )
{
lpSessionDest->sess.lpszSessionNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
}
if( lpSessionSrc->pass.lpszPasswordA )
{
lpSessionDest->pass.lpszPasswordA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
}
return TRUE;
}
/* Start the index at 0. index will be updated to equal that which should
be passed back into this function for the next element */
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
{
for( ; (*index) < numSupportedSessions; (*index)++ )
{
if( sessionData[(*index)].dwSize != 0 )
{
return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
}
}
/* No more sessions */
return NULL;
}
/* Start the index at 0. index will be updated to equal that which should
be passed back into this function for the next element */
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
{
for( ; (*index) < numSupportedSessions; (*index)++ )
{
if( sessionData[(*index)].dwSize != 0 )
{
return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
}
}
/* No more sessions */
return FALSE;
}
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
{
UINT i;
FIXME( ": stub\n" );
/* FIXME: Is this an error if it exists already? */
/* Crude/wrong implementation for now. Just always add to first empty spot */
for( i=0; i < numSupportedSessions; i++ )
{
/* Is this one empty? */
if( sessionData[i].dwSize == 0 )
{
DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
break;
}
}
}
/* NOTE: This is potentially not thread safe. You are not guaranteed to end up
with the correct string printed in the case where the HRESULT is not
known. You'll just get the last hr passed in printed. This can change
over time if this method is used alot :) */
LPCSTR DPLAYX_HresultToString(HRESULT hr)
{
static char szTempStr[12];
switch (hr)
{
case DP_OK:
return "DP_OK";
case DPERR_ALREADYINITIALIZED:
return "DPERR_ALREADYINITIALIZED";
case DPERR_ACCESSDENIED:
return "DPERR_ACCESSDENIED";
case DPERR_ACTIVEPLAYERS:
return "DPERR_ACTIVEPLAYERS";
case DPERR_BUFFERTOOSMALL:
return "DPERR_BUFFERTOOSMALL";
case DPERR_CANTADDPLAYER:
return "DPERR_CANTADDPLAYER";
case DPERR_CANTCREATEGROUP:
return "DPERR_CANTCREATEGROUP";
case DPERR_CANTCREATEPLAYER:
return "DPERR_CANTCREATEPLAYER";
case DPERR_CANTCREATESESSION:
return "DPERR_CANTCREATESESSION";
case DPERR_CAPSNOTAVAILABLEYET:
return "DPERR_CAPSNOTAVAILABLEYET";
case DPERR_EXCEPTION:
return "DPERR_EXCEPTION";
case DPERR_GENERIC:
return "DPERR_GENERIC";
case DPERR_INVALIDFLAGS:
return "DPERR_INVALIDFLAGS";
case DPERR_INVALIDOBJECT:
return "DPERR_INVALIDOBJECT";
case DPERR_INVALIDPARAMS:
return "DPERR_INVALIDPARAMS";
case DPERR_INVALIDPLAYER:
return "DPERR_INVALIDPLAYER";
case DPERR_INVALIDGROUP:
return "DPERR_INVALIDGROUP";
case DPERR_NOCAPS:
return "DPERR_NOCAPS";
case DPERR_NOCONNECTION:
return "DPERR_NOCONNECTION";
case DPERR_OUTOFMEMORY:
return "DPERR_OUTOFMEMORY";
case DPERR_NOMESSAGES:
return "DPERR_NOMESSAGES";
case DPERR_NONAMESERVERFOUND:
return "DPERR_NONAMESERVERFOUND";
case DPERR_NOPLAYERS:
return "DPERR_NOPLAYERS";
case DPERR_NOSESSIONS:
return "DPERR_NOSESSIONS";
/* This one isn't defined yet in WINE sources. I don't know the value
case DPERR_PENDING:
return "DPERR_PENDING";
*/
case DPERR_SENDTOOBIG:
return "DPERR_SENDTOOBIG";
case DPERR_TIMEOUT:
return "DPERR_TIMEOUT";
case DPERR_UNAVAILABLE:
return "DPERR_UNAVAILABLE";
case DPERR_UNSUPPORTED:
return "DPERR_UNSUPPORTED";
case DPERR_BUSY:
return "DPERR_BUSY";
case DPERR_USERCANCEL:
return "DPERR_USERCANCEL";
case DPERR_NOINTERFACE:
return "DPERR_NOINTERFACE";
case DPERR_CANNOTCREATESERVER:
return "DPERR_CANNOTCREATESERVER";
case DPERR_PLAYERLOST:
return "DPERR_PLAYERLOST";
case DPERR_SESSIONLOST:
return "DPERR_SESSIONLOST";
case DPERR_UNINITIALIZED:
return "DPERR_UNINITIALIZED";
case DPERR_NONEWPLAYERS:
return "DPERR_NONEWPLAYERS";
case DPERR_INVALIDPASSWORD:
return "DPERR_INVALIDPASSWORD";
case DPERR_CONNECTING:
return "DPERR_CONNECTING";
case DPERR_CONNECTIONLOST:
return "DPERR_CONNECTIONLOST";
case DPERR_UNKNOWNMESSAGE:
return "DPERR_UNKNOWNMESSAGE";
case DPERR_CANCELFAILED:
return "DPERR_CANCELFAILED";
case DPERR_INVALIDPRIORITY:
return "DPERR_INVALIDPRIORITY";
case DPERR_NOTHANDLED:
return "DPERR_NOTHANDLED";
case DPERR_CANCELLED:
return "DPERR_CANCELLED";
case DPERR_ABORTED:
return "DPERR_ABORTED";
case DPERR_BUFFERTOOLARGE:
return "DPERR_BUFFERTOOLARGE";
case DPERR_CANTCREATEPROCESS:
return "DPERR_CANTCREATEPROCESS";
case DPERR_APPNOTSTARTED:
return "DPERR_APPNOTSTARTED";
case DPERR_INVALIDINTERFACE:
return "DPERR_INVALIDINTERFACE";
case DPERR_NOSERVICEPROVIDER:
return "DPERR_NOSERVICEPROVIDER";
case DPERR_UNKNOWNAPPLICATION:
return "DPERR_UNKNOWNAPPLICATION";
case DPERR_NOTLOBBIED:
return "DPERR_NOTLOBBIED";
case DPERR_SERVICEPROVIDERLOADED:
return "DPERR_SERVICEPROVIDERLOADED";
case DPERR_ALREADYREGISTERED:
return "DPERR_ALREADYREGISTERED";
case DPERR_NOTREGISTERED:
return "DPERR_NOTREGISTERED";
case DPERR_AUTHENTICATIONFAILED:
return "DPERR_AUTHENTICATIONFAILED";
case DPERR_CANTLOADSSPI:
return "DPERR_CANTLOADSSPI";
case DPERR_ENCRYPTIONFAILED:
return "DPERR_ENCRYPTIONFAILED";
case DPERR_SIGNFAILED:
return "DPERR_SIGNFAILED";
case DPERR_CANTLOADSECURITYPACKAGE:
return "DPERR_CANTLOADSECURITYPACKAGE";
case DPERR_ENCRYPTIONNOTSUPPORTED:
return "DPERR_ENCRYPTIONNOTSUPPORTED";
case DPERR_CANTLOADCAPI:
return "DPERR_CANTLOADCAPI";
case DPERR_NOTLOGGEDIN:
return "DPERR_NOTLOGGEDIN";
case DPERR_LOGONDENIED:
return "DPERR_LOGONDENIED";
default:
/* For errors not in the list, return HRESULT as a string
This part is not thread safe */
WARN( "Unknown error 0x%08lx\n", hr );
sprintf( szTempStr, "0x%08lx", hr );
return szTempStr;
}
}