mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Addin wine 0.9 dplay and dplayx it is directx core for network and tested in windows and not in reactos.
it is working in windows. svn path=/trunk/; revision=18811
This commit is contained in:
parent
da8e63268f
commit
5bd48cf0fa
26 changed files with 13851 additions and 0 deletions
|
@ -62,6 +62,12 @@
|
|||
<directory name="dnsapi">
|
||||
<xi:include href="dnsapi/dnsapi.xml" />
|
||||
</directory>
|
||||
<directory name="dplay">
|
||||
<xi:include href="dplay/dplay.xml" />
|
||||
</directory>
|
||||
<directory name="dplayx">
|
||||
<xi:include href="dplayx/dplayx.xml" />
|
||||
</directory>
|
||||
<directory name="dsound">
|
||||
<xi:include href="dsound/dsound.xml" />
|
||||
</directory>
|
||||
|
|
4
reactos/lib/dplay/dplay.spec
Normal file
4
reactos/lib/dplay/dplay.spec
Normal file
|
@ -0,0 +1,4 @@
|
|||
# First DirectPlay dll. Replaced by dplayx.dll.
|
||||
|
||||
@ stdcall DirectPlayCreate(ptr ptr ptr) dplayx.DirectPlayCreate
|
||||
@ stdcall DirectPlayEnumerate(ptr ptr) dplayx.DirectPlayEnumerate
|
25
reactos/lib/dplay/dplay.xml
Normal file
25
reactos/lib/dplay/dplay.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<module name="dplay" type="win32dll" baseaddress="${BASEADDRESS_DPLAY}" installbase="system32" installname="dplay.dll">
|
||||
<importlibrary definition="dplay.spec.def" />
|
||||
<include base="dinput8">.</include>
|
||||
<include base="ReactOS">include/wine</include>
|
||||
<define name="UNICODE" />
|
||||
<define name="_UNICODE" />
|
||||
<define name="__REACTOS__" />
|
||||
<define name="__USE_W32API" />
|
||||
<define name="_WIN32_IE">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x501</define>
|
||||
<define name="WINVER">0x501</define>
|
||||
<library>wine</library>
|
||||
<library>uuid</library>
|
||||
<library>ntdll</library>
|
||||
<library>kernel32</library>
|
||||
<library>user32</library>
|
||||
<library>advapi32</library>
|
||||
<library>ole32</library>
|
||||
<library>winmm</library>
|
||||
<library>dxguid</library>
|
||||
<library>dinput</library>
|
||||
<file>version.rc</file>
|
||||
<file>dplay_main.c</file>
|
||||
<file>dplay.spec</file>
|
||||
</module>
|
1
reactos/lib/dplay/dplay_main.c
Normal file
1
reactos/lib/dplay/dplay_main.c
Normal file
|
@ -0,0 +1 @@
|
|||
/* nothing here yet */
|
27
reactos/lib/dplay/version.rc
Normal file
27
reactos/lib/dplay/version.rc
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2004 Tom Wickline
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define WINE_OLESELFREGISTER
|
||||
#define WINE_FILEDESCRIPTION_STR "Wine DirectPlay"
|
||||
#define WINE_FILENAME_STR "dplay.dll"
|
||||
#define WINE_FILEVERSION 5,3,0,900
|
||||
#define WINE_FILEVERSION_STR "5.3.0.900"
|
||||
#define WINE_PRODUCTVERSION 5,3,0,900
|
||||
#define WINE_PRODUCTVERSION_STR "5.3"
|
||||
|
||||
#include "wine/wine_common_ver.rc"
|
134
reactos/lib/dplayx/dpclassfactory.c
Normal file
134
reactos/lib/dplayx/dpclassfactory.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* COM class factory for direct play lobby interfaces.
|
||||
*
|
||||
* Copyright 1999, 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define COBJMACROS
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "objbase.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "dpinit.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DirectPlayLobby ClassFactory
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* IUnknown fields */
|
||||
const IClassFactoryVtbl *lpVtbl;
|
||||
LONG ref;
|
||||
} IClassFactoryImpl;
|
||||
|
||||
static HRESULT WINAPI
|
||||
DP_and_DPL_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI
|
||||
DP_and_DPL_AddRef(LPCLASSFACTORY iface) {
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI DP_and_DPL_Release(LPCLASSFACTORY iface) {
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
/* static class (reference starts @ 1), won't ever be freed */
|
||||
return InterlockedDecrement(&This->ref);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DP_and_DPL_CreateInstance(
|
||||
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
|
||||
) {
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
|
||||
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
|
||||
|
||||
if ( DPL_CreateInterface( riid, ppobj ) == S_OK )
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else if ( DP_CreateInterface( riid, ppobj ) == S_OK )
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DP_and_DPL_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
|
||||
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
|
||||
FIXME("(%p)->(%d),stub!\n",This,dolock);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IClassFactoryVtbl DP_and_DPL_Vtbl = {
|
||||
DP_and_DPL_QueryInterface,
|
||||
DP_and_DPL_AddRef,
|
||||
DP_and_DPL_Release,
|
||||
DP_and_DPL_CreateInstance,
|
||||
DP_and_DPL_LockServer
|
||||
};
|
||||
|
||||
static IClassFactoryImpl DP_and_DPL_CF = {&DP_and_DPL_Vtbl, 1 };
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DllGetClassObject [DPLAYX.@]
|
||||
* Retrieves DP or DPL class object from a DLL object
|
||||
*
|
||||
* NOTES
|
||||
* Docs say returns STDAPI
|
||||
*
|
||||
* PARAMS
|
||||
* rclsid [I] CLSID for the class object
|
||||
* riid [I] Reference to identifier of interface for class object
|
||||
* ppv [O] Address of variable to receive interface pointer for riid
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK
|
||||
* Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
|
||||
* E_UNEXPECTED
|
||||
*/
|
||||
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
|
||||
if ( IsEqualCLSID( riid, &IID_IClassFactory ) )
|
||||
{
|
||||
*ppv = (LPVOID)&DP_and_DPL_CF;
|
||||
IClassFactory_AddRef( (IClassFactory*)*ppv );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ERR("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
37
reactos/lib/dplayx/dpinit.h
Normal file
37
reactos/lib/dplayx/dpinit.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 1999, 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPINIT_H
|
||||
#define __WINE_DPINIT_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wtypes.h"
|
||||
#include "dplay_global.h"
|
||||
|
||||
extern HRESULT DP_CreateInterface( REFIID riid, LPVOID* ppvObj );
|
||||
extern HRESULT DPL_CreateInterface( REFIID riid, LPVOID* ppvObj );
|
||||
extern HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
|
||||
IDirectPlay2Impl* dp );
|
||||
extern HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj,
|
||||
IDirectPlay2Impl* dp );
|
||||
|
||||
|
||||
#endif
|
5451
reactos/lib/dplayx/dplay.c
Normal file
5451
reactos/lib/dplayx/dplay.c
Normal file
File diff suppressed because it is too large
Load diff
246
reactos/lib/dplayx/dplay_global.h
Normal file
246
reactos/lib/dplayx/dplay_global.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPLAY_GLOBAL_INCLUDED
|
||||
#define __WINE_DPLAY_GLOBAL_INCLUDED
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "dplaysp.h"
|
||||
#include "lobbysp.h"
|
||||
#include "dplayx_queue.h"
|
||||
|
||||
extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
|
||||
LPCVOID lpAddress, DWORD dwAddressSize,
|
||||
LPVOID lpContext );
|
||||
|
||||
extern DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interface implementation structures
|
||||
*/
|
||||
typedef struct IDirectPlay2Impl IDirectPlay2AImpl;
|
||||
typedef struct IDirectPlay2Impl IDirectPlay2Impl;
|
||||
typedef struct IDirectPlay3Impl IDirectPlay3AImpl;
|
||||
typedef struct IDirectPlay3Impl IDirectPlay3Impl;
|
||||
typedef struct IDirectPlay4Impl IDirectPlay4AImpl;
|
||||
typedef struct IDirectPlay4Impl IDirectPlay4Impl;
|
||||
|
||||
typedef struct tagDirectPlayIUnknownData
|
||||
{
|
||||
LONG ulObjRef;
|
||||
CRITICAL_SECTION DP_lock;
|
||||
} DirectPlayIUnknownData;
|
||||
|
||||
typedef struct tagEnumSessionAsyncCallbackData
|
||||
{
|
||||
LPSPINITDATA lpSpData;
|
||||
GUID requestGuid;
|
||||
DWORD dwEnumSessionFlags;
|
||||
DWORD dwTimeout;
|
||||
HANDLE hSuicideRequest;
|
||||
} EnumSessionAsyncCallbackData;
|
||||
|
||||
typedef struct tagDP_MSG_REPLY_STRUCT
|
||||
{
|
||||
HANDLE hReceipt;
|
||||
WORD wExpectedReply;
|
||||
LPVOID lpReplyMsg;
|
||||
DWORD dwMsgBodySize;
|
||||
/* FIXME: Is the message header required as well? */
|
||||
} DP_MSG_REPLY_STRUCT, *LPDP_MSG_REPLY_STRUCT;
|
||||
|
||||
typedef struct tagDP_MSG_REPLY_STRUCT_LIST
|
||||
{
|
||||
DPQ_ENTRY(tagDP_MSG_REPLY_STRUCT_LIST) replysExpected;
|
||||
DP_MSG_REPLY_STRUCT replyExpected;
|
||||
} DP_MSG_REPLY_STRUCT_LIST, *LPDP_MSG_REPLY_STRUCT_LIST;
|
||||
|
||||
struct PlayerData
|
||||
{
|
||||
/* Individual player information */
|
||||
DPID dpid;
|
||||
|
||||
DPNAME name;
|
||||
HANDLE hEvent;
|
||||
|
||||
ULONG uRef; /* What is the reference count on this data? */
|
||||
|
||||
/* View of local data */
|
||||
LPVOID lpLocalData;
|
||||
DWORD dwLocalDataSize;
|
||||
|
||||
/* View of remote data */
|
||||
LPVOID lpRemoteData;
|
||||
DWORD dwRemoteDataSize;
|
||||
|
||||
/* SP data on a per player basis */
|
||||
LPVOID lpSPPlayerData;
|
||||
|
||||
DWORD dwFlags; /* Special remarks about the type of player */
|
||||
};
|
||||
typedef struct PlayerData* lpPlayerData;
|
||||
|
||||
struct PlayerList
|
||||
{
|
||||
DPQ_ENTRY(PlayerList) players;
|
||||
|
||||
lpPlayerData lpPData;
|
||||
};
|
||||
typedef struct PlayerList* lpPlayerList;
|
||||
|
||||
struct GroupData
|
||||
{
|
||||
/* Internal information */
|
||||
DPID parent; /* If parent == 0 it's a top level group */
|
||||
|
||||
ULONG uRef; /* Reference count */
|
||||
|
||||
DPQ_HEAD(GroupList) groups; /* A group has [0..n] groups */
|
||||
DPQ_HEAD(PlayerList) players; /* A group has [0..n] players */
|
||||
|
||||
DPID idGroupOwner; /* ID of player who owns the group */
|
||||
|
||||
DWORD dwFlags; /* Flags describing anything special about the group */
|
||||
|
||||
DPID dpid;
|
||||
DPNAME name;
|
||||
|
||||
/* View of local data */
|
||||
LPVOID lpLocalData;
|
||||
DWORD dwLocalDataSize;
|
||||
|
||||
/* View of remote data */
|
||||
LPVOID lpRemoteData;
|
||||
DWORD dwRemoteDataSize;
|
||||
};
|
||||
typedef struct GroupData GroupData;
|
||||
typedef struct GroupData* lpGroupData;
|
||||
|
||||
struct GroupList
|
||||
{
|
||||
DPQ_ENTRY(GroupList) groups;
|
||||
|
||||
lpGroupData lpGData;
|
||||
};
|
||||
typedef struct GroupList* lpGroupList;
|
||||
|
||||
struct DPMSG
|
||||
{
|
||||
DPQ_ENTRY( DPMSG ) msgs;
|
||||
DPMSG_GENERIC* msg;
|
||||
};
|
||||
typedef struct DPMSG* LPDPMSG;
|
||||
|
||||
enum SPSTATE
|
||||
{
|
||||
NO_PROVIDER = 0,
|
||||
DP_SERVICE_PROVIDER = 1,
|
||||
DP_LOBBY_PROVIDER = 2
|
||||
};
|
||||
|
||||
/* Contains all data members. FIXME: Rename me */
|
||||
typedef struct tagDirectPlay2Data
|
||||
{
|
||||
BOOL bConnectionOpen;
|
||||
|
||||
/* For async EnumSessions requests */
|
||||
HANDLE hEnumSessionThread;
|
||||
HANDLE hKillEnumSessionThreadEvent;
|
||||
|
||||
LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
|
||||
|
||||
BOOL bHostInterface; /* Did this interface create the session */
|
||||
|
||||
lpGroupData lpSysGroup; /* System group with _everything_ in it */
|
||||
|
||||
LPDPSESSIONDESC2 lpSessionDesc;
|
||||
|
||||
/* I/O Msg queues */
|
||||
DPQ_HEAD( DPMSG ) receiveMsgs; /* Msg receive queue */
|
||||
DPQ_HEAD( DPMSG ) sendMsgs; /* Msg send pending queue */
|
||||
|
||||
/* Information about the service provider active on this connection */
|
||||
SPINITDATA spData;
|
||||
BOOL bSPInitialized;
|
||||
|
||||
/* Information about the lobby server that's attached to this DP object */
|
||||
SPDATA_INIT dplspData;
|
||||
BOOL bDPLSPInitialized;
|
||||
|
||||
/* Our service provider */
|
||||
HMODULE hServiceProvider;
|
||||
|
||||
/* Our DP lobby provider */
|
||||
HMODULE hDPLobbyProvider;
|
||||
|
||||
enum SPSTATE connectionInitialized;
|
||||
|
||||
/* Expected messages queue */
|
||||
DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected;
|
||||
} DirectPlay2Data;
|
||||
|
||||
typedef struct tagDirectPlay3Data
|
||||
{
|
||||
BOOL dummy;
|
||||
} DirectPlay3Data;
|
||||
typedef struct tagDirectPlay4Data
|
||||
{
|
||||
BOOL dummy;
|
||||
} DirectPlay4Data;
|
||||
|
||||
#define DP_IMPL_FIELDS \
|
||||
LONG ulInterfaceRef; \
|
||||
DirectPlayIUnknownData* unk; \
|
||||
DirectPlay2Data* dp2; \
|
||||
DirectPlay3Data* dp3; \
|
||||
DirectPlay4Data* dp4;
|
||||
|
||||
struct IDirectPlay2Impl
|
||||
{
|
||||
const IDirectPlay2Vtbl *lpVtbl;
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
struct IDirectPlay3Impl
|
||||
{
|
||||
const IDirectPlay3Vtbl *lpVtbl;
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
struct IDirectPlay4Impl
|
||||
{
|
||||
const IDirectPlay4Vtbl *lpVtbl;
|
||||
DP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
|
||||
DWORD dwMessageBodySize, LPCVOID lpMessageHeader,
|
||||
WORD wCommandId, WORD wVersion,
|
||||
LPVOID* lplpReply, LPDWORD lpdwMsgSize );
|
||||
|
||||
/* DP SP external interfaces into DirectPlay */
|
||||
extern HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID* lplpData );
|
||||
extern HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID lpData );
|
||||
|
||||
/* DP external interfaces to call into DPSP interface */
|
||||
extern LPVOID DPSP_CreateSPPlayerData(void);
|
||||
|
||||
#endif /* __WINE_DPLAY_GLOBAL_INCLUDED */
|
955
reactos/lib/dplayx/dplaysp.c
Normal file
955
reactos/lib/dplayx/dplaysp.c
Normal file
|
@ -0,0 +1,955 @@
|
|||
/* This contains the implementation of the interface Service
|
||||
* Providers require to communicate with Direct Play
|
||||
*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "dpinit.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplay_global.h"
|
||||
#include "name_server.h"
|
||||
#include "dplayx_messages.h"
|
||||
|
||||
#include "dplayx_global.h" /* FIXME: For global hack */
|
||||
|
||||
/* FIXME: Need to add interface locking inside procedures */
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* Prototypes */
|
||||
static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
|
||||
static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
|
||||
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
|
||||
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
|
||||
|
||||
/* Predefine the interface */
|
||||
typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
|
||||
|
||||
typedef struct tagDirectPlaySPIUnknownData
|
||||
{
|
||||
LONG ulObjRef;
|
||||
CRITICAL_SECTION DPSP_lock;
|
||||
} DirectPlaySPIUnknownData;
|
||||
|
||||
typedef struct tagDirectPlaySPData
|
||||
{
|
||||
LPVOID lpSpRemoteData;
|
||||
DWORD dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
|
||||
|
||||
LPVOID lpSpLocalData;
|
||||
DWORD dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
|
||||
|
||||
IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
|
||||
|
||||
} DirectPlaySPData;
|
||||
|
||||
#define DPSP_IMPL_FIELDS \
|
||||
LONG ulInterfaceRef; \
|
||||
DirectPlaySPIUnknownData* unk; \
|
||||
DirectPlaySPData* sp;
|
||||
|
||||
struct IDirectPlaySPImpl
|
||||
{
|
||||
const IDirectPlaySPVtbl *lpVtbl;
|
||||
DPSP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
/* Forward declaration of virtual tables */
|
||||
static const IDirectPlaySPVtbl directPlaySPVT;
|
||||
|
||||
/* This structure is passed to the DP object for safe keeping */
|
||||
typedef struct tagDP_SPPLAYERDATA
|
||||
{
|
||||
LPVOID lpPlayerLocalData;
|
||||
DWORD dwPlayerLocalDataSize;
|
||||
|
||||
LPVOID lpPlayerRemoteData;
|
||||
DWORD dwPlayerRemoteDataSize;
|
||||
} DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
|
||||
|
||||
/* Create the SP interface */
|
||||
extern
|
||||
HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
|
||||
{
|
||||
TRACE( " for %s\n", debugstr_guid( riid ) );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( IDirectPlaySPImpl ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
|
||||
This->lpVtbl = &directPlaySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
if( DPSP_CreateIUnknown( *ppvObj ) &&
|
||||
DPSP_CreateDirectPlaySP( *ppvObj, dp )
|
||||
)
|
||||
{
|
||||
IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Initialize failed, destroy it */
|
||||
DPSP_DestroyDirectPlaySP( *ppvObj );
|
||||
DPSP_DestroyIUnknown( *ppvObj );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return DPERR_NOMEMORY;
|
||||
}
|
||||
|
||||
static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
|
||||
|
||||
This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
|
||||
|
||||
if ( This->unk == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
InitializeCriticalSection( &This->unk->DPSP_lock );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
|
||||
|
||||
DeleteCriticalSection( &This->unk->DPSP_lock );
|
||||
HeapFree( GetProcessHeap(), 0, This->unk );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
|
||||
|
||||
This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
|
||||
|
||||
if ( This->sp == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
This->sp->dplay = dp;
|
||||
|
||||
/* Normally we should be keeping a reference, but since only the dplay
|
||||
* interface that created us can destroy us, we do not keep a reference
|
||||
* to it (ie we'd be stuck with always having one reference to the dplay
|
||||
* object, and hence us, around).
|
||||
* NOTE: The dp object does reference count us.
|
||||
*
|
||||
* FIXME: This is a kludge to get around a problem where a queryinterface
|
||||
* is used to get a new interface and then is closed. We will then
|
||||
* reference garbage. However, with this we will never deallocate
|
||||
* the interface we store. The correct fix is to require all
|
||||
* DP internal interfaces to use the This->dp2 interface which
|
||||
* should be changed to This->dp
|
||||
*/
|
||||
IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)lpSP;
|
||||
|
||||
/* Normally we should be keeping a reference, but since only the dplay
|
||||
* interface that created us can destroy us, we do not keep a reference
|
||||
* to it (ie we'd be stuck with always having one reference to the dplay
|
||||
* object, and hence us, around).
|
||||
* NOTE: The dp object does reference count us.
|
||||
*/
|
||||
/*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
|
||||
|
||||
/* FIXME: Need to delete player queue */
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, This->sp );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Interface implementation */
|
||||
|
||||
static HRESULT WINAPI DPSP_QueryInterface
|
||||
( LPDIRECTPLAYSP iface,
|
||||
REFIID riid,
|
||||
LPVOID* ppvObj )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( *This ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
CopyMemory( *ppvObj, This, sizeof( *This ) );
|
||||
(*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
|
||||
|
||||
if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)*ppvObj;
|
||||
This->lpVtbl = &directPlaySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DPSP_AddRef
|
||||
( LPDIRECTPLAYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
|
||||
ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
|
||||
|
||||
TRACE( "ref count incremented to %lu:%lu for %p\n",
|
||||
ulInterfaceRefCount, ulObjRefCount, This );
|
||||
|
||||
return ulObjRefCount;
|
||||
}
|
||||
|
||||
static ULONG WINAPI DPSP_Release
|
||||
( LPDIRECTPLAYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
|
||||
ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
|
||||
|
||||
TRACE( "ref count decremented to %lu:%lu for %p\n",
|
||||
ulInterfaceRefCount, ulObjRefCount, This );
|
||||
|
||||
/* Deallocate if this is the last reference to the object */
|
||||
if( ulObjRefCount == 0 )
|
||||
{
|
||||
DPSP_DestroyDirectPlaySP( This );
|
||||
DPSP_DestroyIUnknown( This );
|
||||
}
|
||||
|
||||
if( ulInterfaceRefCount == 0 )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
}
|
||||
|
||||
return ulInterfaceRefCount;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCWSTR lpSection,
|
||||
LPCWSTR lpKey,
|
||||
LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwMaxEntries
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
/* Should be able to call the comctl32 undocumented MRU routines.
|
||||
I suspect that the interface works appropriately */
|
||||
FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n",
|
||||
This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
REFGUID guidSP,
|
||||
REFGUID guidDataType,
|
||||
LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
LPVOID lpAddress,
|
||||
LPDWORD lpdwAddressSize
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n",
|
||||
This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
|
||||
lpData, dwDataSize, lpAddress, lpdwAddressSize );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
|
||||
LPCVOID lpAddress,
|
||||
DWORD dwAddressSize,
|
||||
LPVOID lpContext
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n",
|
||||
This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
||||
|
||||
DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCWSTR lpSection,
|
||||
LPCWSTR lpKey,
|
||||
LPENUMMRUCALLBACK lpEnumMRUCallback,
|
||||
LPVOID lpContext
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
/* Should be able to call the comctl32 undocumented MRU routines.
|
||||
I suspect that the interface works appropriately */
|
||||
FIXME( "(%p)->(%p,%p,%p,%p,): stub\n",
|
||||
This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPDWORD lpdwPlayerFlags
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
FIXME( "(%p)->(0x%08lx,%p): stub\n",
|
||||
This, idPlayer, lpdwPlayerFlags );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPVOID* lplpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPDP_SPPLAYERDATA lpPlayerData;
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
|
||||
This, idPlayer, lplpData, lpdwDataSize, dwFlags );
|
||||
|
||||
hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
|
||||
return DPERR_INVALIDPLAYER;
|
||||
}
|
||||
|
||||
/* What to do in the case where there is nothing set yet? */
|
||||
if( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
|
||||
*lplpData = lpPlayerData->lpPlayerLocalData;
|
||||
*lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
|
||||
}
|
||||
else if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
|
||||
*lplpData = lpPlayerData->lpPlayerRemoteData;
|
||||
*lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
|
||||
}
|
||||
|
||||
if( *lplpData == NULL )
|
||||
{
|
||||
hr = DPERR_GENERIC;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID lpMessageBody,
|
||||
DWORD dwMessageBodySize,
|
||||
LPVOID lpMessageHeader
|
||||
)
|
||||
{
|
||||
LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
|
||||
HRESULT hr = DPERR_GENERIC;
|
||||
WORD wCommandId;
|
||||
WORD wVersion;
|
||||
DPSP_REPLYDATA data;
|
||||
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
|
||||
This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
|
||||
|
||||
wCommandId = lpMsg->wCommandId;
|
||||
wVersion = lpMsg->wVersion;
|
||||
|
||||
TRACE( "Incoming message has envelope of 0x%08lx, %u, %u\n",
|
||||
lpMsg->dwMagic, wCommandId, wVersion );
|
||||
|
||||
if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
|
||||
{
|
||||
ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
|
||||
return DPERR_GENERIC;
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
const LPDWORD lpcHeader = (LPDWORD)lpMessageHeader;
|
||||
|
||||
TRACE( "lpMessageHeader = [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx] [0x%08lx]\n",
|
||||
lpcHeader[0], lpcHeader[1], lpcHeader[2], lpcHeader[3], lpcHeader[4] );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pass everything else to Direct Play */
|
||||
data.lpMessage = NULL;
|
||||
data.dwMessageSize = 0;
|
||||
|
||||
/* Pass this message to the dplay interface to handle */
|
||||
hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
|
||||
lpMessageHeader, wCommandId, wVersion,
|
||||
&data.lpMessage, &data.dwMessageSize );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Command processing failed %s\n", DPLAYX_HresultToString(hr) );
|
||||
}
|
||||
|
||||
/* Do we want a reply? */
|
||||
if( data.lpMessage != NULL )
|
||||
{
|
||||
data.lpSPMessageHeader = lpMessageHeader;
|
||||
data.idNameServer = 0;
|
||||
data.lpISP = iface;
|
||||
|
||||
hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
|
||||
#if 0
|
||||
HRESULT hr = DP_OK;
|
||||
HANDLE hReceiveEvent = 0;
|
||||
/* FIXME: Aquire some sort of interface lock */
|
||||
/* FIXME: Need some sort of context for this callback. Need to determine
|
||||
* how this is actually done with the SP
|
||||
*/
|
||||
/* FIXME: Who needs to delete the message when done? */
|
||||
switch( lpMsg->dwType )
|
||||
{
|
||||
case DPSYS_CREATEPLAYERORGROUP:
|
||||
{
|
||||
LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
/* Group in group situation? */
|
||||
if( msg->dpIdParent == DPID_NOPARENT_GROUP )
|
||||
{
|
||||
hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
else /* Group in Group */
|
||||
{
|
||||
hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
|
||||
&msg->dpnName, 0, msg->lpData,
|
||||
msg->dwDataSize, msg->dwFlags, ... );
|
||||
}
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DESTROYPLAYERORGROUP:
|
||||
{
|
||||
LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_ADDPLAYERTOGROUP:
|
||||
{
|
||||
LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DELETEPLAYERFROMGROUP:
|
||||
{
|
||||
LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
|
||||
... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SESSIONLOST:
|
||||
{
|
||||
LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SESSIONLOST not handled\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_HOST:
|
||||
{
|
||||
LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_HOST not handled\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETPLAYERORGROUPDATA:
|
||||
{
|
||||
LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize, DPSET_REMOTE, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
|
||||
DPSET_REMOTE, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETPLAYERORGROUPNAME:
|
||||
{
|
||||
LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
|
||||
|
||||
if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
|
||||
{
|
||||
hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
|
||||
}
|
||||
else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
|
||||
{
|
||||
hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
|
||||
}
|
||||
else /* Hmmm? */
|
||||
{
|
||||
ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETSESSIONDESC;
|
||||
{
|
||||
LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
|
||||
|
||||
hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_ADDGROUPTOGROUP:
|
||||
{
|
||||
LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
|
||||
... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_DELETEGROUPFROMGROUP:
|
||||
{
|
||||
LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
|
||||
|
||||
hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
|
||||
msg->dpIdGroup, ... );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SECUREMESSAGE:
|
||||
{
|
||||
LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_STARTSESSION:
|
||||
{
|
||||
LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_STARTSESSION not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_CHAT:
|
||||
{
|
||||
LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_CHAT not implemeneted\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SETGROUPOWNER:
|
||||
{
|
||||
LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DPSYS_SENDCOMPLETE:
|
||||
{
|
||||
LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
|
||||
|
||||
FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
/* NOTE: This should be a user defined type. There is nothing that we
|
||||
* need to do with it except queue it.
|
||||
*/
|
||||
TRACE( "Received user message type(?) 0x%08lx through SP.\n",
|
||||
lpMsg->dwType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FIXME( "Queue message in the receive queue. Need some context data!\n" );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
|
||||
}
|
||||
/* If a receive event was registered for this player, invoke it */
|
||||
if( hReceiveEvent )
|
||||
{
|
||||
SetEvent( hReceiveEvent );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
DPID idPlayer,
|
||||
LPVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPDP_SPPLAYERDATA lpPlayerEntry;
|
||||
LPVOID lpPlayerData;
|
||||
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
|
||||
TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
|
||||
This, idPlayer, lpData, dwDataSize, dwFlags );
|
||||
|
||||
hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
/* Player must not exist */
|
||||
return DPERR_INVALIDPLAYER;
|
||||
}
|
||||
|
||||
lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
|
||||
CopyMemory( lpPlayerData, lpData, dwDataSize );
|
||||
|
||||
if( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
|
||||
lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
|
||||
}
|
||||
else if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
|
||||
lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
|
||||
}
|
||||
|
||||
hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPCDPCOMPOUNDADDRESSELEMENT lpElements,
|
||||
DWORD dwElementCount,
|
||||
LPVOID lpAddress,
|
||||
LPDWORD lpdwAddressSize
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n",
|
||||
This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID* lplpData,
|
||||
LPDWORD lpdwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
HRESULT hr = DP_OK;
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
|
||||
TRACE( "(%p)->(%p,%p,0x%08lx)\n",
|
||||
This, lplpData, lpdwDataSize, dwFlags );
|
||||
|
||||
#if 0
|
||||
/* This is what the documentation says... */
|
||||
if( dwFlags != DPSET_REMOTE )
|
||||
{
|
||||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
#else
|
||||
/* ... but most service providers call this with 1 */
|
||||
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
|
||||
* thing?
|
||||
*/
|
||||
if( dwFlags != DPSET_REMOTE )
|
||||
{
|
||||
TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: What to do in the case where this isn't initialized yet? */
|
||||
|
||||
/* Yes, we're supposed to return a pointer to the memory we have stored! */
|
||||
if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
*lpdwDataSize = This->sp->dwSpRemoteDataSize;
|
||||
*lplpData = This->sp->lpSpRemoteData;
|
||||
|
||||
if( This->sp->lpSpRemoteData == NULL )
|
||||
{
|
||||
hr = DPERR_GENERIC;
|
||||
}
|
||||
}
|
||||
else if( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
*lpdwDataSize = This->sp->dwSpLocalDataSize;
|
||||
*lplpData = This->sp->lpSpLocalData;
|
||||
|
||||
if( This->sp->lpSpLocalData == NULL )
|
||||
{
|
||||
hr = DPERR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
DWORD dwFlags
|
||||
)
|
||||
{
|
||||
LPVOID lpSpData;
|
||||
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
|
||||
TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
|
||||
This, lpData, dwDataSize, dwFlags );
|
||||
|
||||
#if 0
|
||||
/* This is what the documentation says... */
|
||||
if( dwFlags != DPSET_REMOTE )
|
||||
{
|
||||
return DPERR_INVALIDPARAMS;
|
||||
}
|
||||
#else
|
||||
/* ... but most service providers call this with 1 */
|
||||
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
|
||||
* thing?
|
||||
*/
|
||||
if( dwFlags != DPSET_REMOTE )
|
||||
{
|
||||
TRACE( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
|
||||
}
|
||||
#endif
|
||||
|
||||
lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
|
||||
CopyMemory( lpSpData, lpData, dwDataSize );
|
||||
|
||||
/* If we have data already allocated, free it and replace it */
|
||||
if( dwFlags == DPSET_REMOTE )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
|
||||
This->sp->dwSpRemoteDataSize = dwDataSize;
|
||||
This->sp->lpSpRemoteData = lpSpData;
|
||||
}
|
||||
else if ( dwFlags == DPSET_LOCAL )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
|
||||
This->sp->lpSpLocalData = lpSpData;
|
||||
This->sp->dwSpLocalDataSize = dwDataSize;
|
||||
}
|
||||
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static VOID WINAPI IDirectPlaySPImpl_SendComplete
|
||||
( LPDIRECTPLAYSP iface,
|
||||
LPVOID unknownA,
|
||||
DWORD unknownB
|
||||
)
|
||||
{
|
||||
IDirectPlaySPImpl *This = (IDirectPlaySPImpl *)iface;
|
||||
|
||||
FIXME( "(%p)->(%p,0x%08lx): stub\n",
|
||||
This, unknownA, unknownB );
|
||||
}
|
||||
|
||||
static const IDirectPlaySPVtbl directPlaySPVT =
|
||||
{
|
||||
|
||||
DPSP_QueryInterface,
|
||||
DPSP_AddRef,
|
||||
DPSP_Release,
|
||||
|
||||
IDirectPlaySPImpl_AddMRUEntry,
|
||||
IDirectPlaySPImpl_CreateAddress,
|
||||
IDirectPlaySPImpl_EnumAddress,
|
||||
IDirectPlaySPImpl_EnumMRUEntries,
|
||||
IDirectPlaySPImpl_GetPlayerFlags,
|
||||
IDirectPlaySPImpl_GetSPPlayerData,
|
||||
IDirectPlaySPImpl_HandleMessage,
|
||||
IDirectPlaySPImpl_SetSPPlayerData,
|
||||
IDirectPlaySPImpl_CreateCompoundAddress,
|
||||
IDirectPlaySPImpl_GetSPData,
|
||||
IDirectPlaySPImpl_SetSPData,
|
||||
IDirectPlaySPImpl_SendComplete
|
||||
};
|
||||
|
||||
|
||||
/* DP external interfaces to call into DPSP interface */
|
||||
|
||||
/* Allocate the structure */
|
||||
extern LPVOID DPSP_CreateSPPlayerData(void)
|
||||
{
|
||||
TRACE( "Creating SPPlayer data struct\n" );
|
||||
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( DP_SPPLAYERDATA ) );
|
||||
}
|
366
reactos/lib/dplayx/dplaysp.h
Normal file
366
reactos/lib/dplayx/dplaysp.h
Normal file
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DIRECT_PLAY_SP_H
|
||||
#define __WINE_DIRECT_PLAY_SP_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "dplay.h"
|
||||
#include "dplobby.h"
|
||||
|
||||
/* GUID for IDirectPlaySP {0C9F6360-CC61-11cf-ACEC-00AA006886E3} */
|
||||
DEFINE_GUID(IID_IDirectPlaySP, 0xc9f6360, 0xcc61, 0x11cf, 0xac, 0xec, 0x0, 0xaa, 0x0, 0x68, 0x86, 0xe3);
|
||||
typedef struct IDirectPlaySP *LPDIRECTPLAYSP;
|
||||
|
||||
|
||||
typedef BOOL (CALLBACK *LPENUMMRUCALLBACK)( LPCVOID lpData,
|
||||
DWORD dwDataSize,
|
||||
LPVOID lpContext );
|
||||
|
||||
/* For SP. Top 16 bits is dplay, bottom 16 is SP */
|
||||
#define DPSP_MAJORVERSION 0x00060000
|
||||
#define DPSP_DX5VERSION 0x00050000
|
||||
#define DPSP_DX3VERSION 0x00040000
|
||||
|
||||
#define DPSP_MAJORVERSIONMASK 0xFFFF0000
|
||||
#define DPSP_MINORVERSIONMASK 0x0000FFFF
|
||||
|
||||
|
||||
/* Some flags */
|
||||
#define DPLAYI_PLAYER_SYSPLAYER 0x00000001
|
||||
#define DPLAYI_PLAYER_NAMESRVR 0x00000002
|
||||
#define DPLAYI_PLAYER_PLAYERINGROUP 0x00000004
|
||||
#define DPLAYI_PLAYER_PLAYERLOCAL 0x00000008
|
||||
#define DPLAYI_GROUP_SYSGROUP 0x00000020
|
||||
#define DPLAYI_GROUP_DPLAYOWNS 0x00000040
|
||||
#define DPLAYI_PLAYER_APPSERVER 0x00000080
|
||||
#define DPLAYI_GROUP_HIDDEN 0x00000400
|
||||
|
||||
/* Define the COM interface */
|
||||
#define INTERFACE IDirectPlaySP
|
||||
DECLARE_INTERFACE_(IDirectPlaySP,IUnknown)
|
||||
{
|
||||
/*** IUnknown methods ***/
|
||||
STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
|
||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||
/*** IDirectPlaySP methods ***/
|
||||
STDMETHOD(AddMRUEntry)(THIS_ LPCWSTR lpSection, LPCWSTR lpKey, LPCVOID lpData, DWORD dwDataSize, DWORD dwMaxEntries ) PURE;
|
||||
STDMETHOD(CreateAddress)(THIS_ REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize, LPVOID lpAddress,LPDWORD lpdwAddressSize) PURE;
|
||||
STDMETHOD(EnumAddress)(THIS_ LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress, DWORD dwAddressSize, LPVOID lpContext ) PURE;
|
||||
STDMETHOD(EnumMRUEntries)(THIS_ LPCWSTR lpSection, LPCWSTR lpKey, LPENUMMRUCALLBACK lpEnumMRUCallback, LPVOID lpContext ) PURE;
|
||||
STDMETHOD(GetPlayerFlags)(THIS_ DPID idPlayer, LPDWORD lpdwPlayerFlags ) PURE;
|
||||
STDMETHOD(GetSPPlayerData)(THIS_ DPID idPlayer, LPVOID *lplpData, LPDWORD lpdwDataSize, DWORD dwFlags ) PURE;
|
||||
STDMETHOD(HandleMessage)(THIS_ LPVOID lpMessageBody, DWORD dwMessageBodySize, LPVOID lpMessageHeader ) PURE;
|
||||
STDMETHOD(SetSPPlayerData)(THIS_ DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) PURE;
|
||||
STDMETHOD(CreateCompoundAddress)(THIS_ LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, LPVOID lpAddress, LPDWORD lpdwAddressSize ) PURE;
|
||||
STDMETHOD(GetSPData)(THIS_ LPVOID *lplpData, LPDWORD dwDataSize, DWORD dwFlags ) PURE;
|
||||
STDMETHOD(SetSPData)(THIS_ LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) PURE;
|
||||
STDMETHOD_(VOID,SendComplete)(THIS_ LPVOID , DWORD ) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
|
||||
/* NOTE: The microsoft provided header file doesn't have these access
|
||||
* functions
|
||||
*/
|
||||
#if !defined (__cplusplus) || defined(CINTERFACE)
|
||||
/*** IUnknown methods ***/
|
||||
#define IDirectPlaySP_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IDirectPlaySP_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IDirectPlaySP_Release(p) (p)->lpVtbl->Release(p)
|
||||
/*** IDirectPlaySP methods ***/
|
||||
#define IDirectPlaySP_AddMRUEntry(p,a,b,c,d,e) (p)->lpVtbl->AddMRUEntry(p,a,b,c,d,e)
|
||||
#define IDirectPlaySP_CreateAddress(p,a,b,c,d,e,f) (p)->lpVtbl->CreateAddress(p,a,b,c,d,e,f)
|
||||
#define IDirectPlaySP_EnumAddress(p,a,b,c,d) (p)->lpVtbl->EnumAddress(p,a,b,c,d)
|
||||
#define IDirectPlaySP_EnumMRUEntries(p,a,b,c,d) (p)->lpVtbl->EnumMRUEntries(p,a,b,c,d)
|
||||
#define IDirectPlaySP_GetPlayerFlags(p,a,b) (p)->lpVtbl->GetPlayerFlags(p,a,b)
|
||||
#define IDirectPlaySP_GetSPPlayerData(p,a,b,c,d) (p)->lpVtbl->GetSPPlayerData(p,a,b,c,d)
|
||||
#define IDirectPlaySP_HandleMessage(p,a,b,c) (p)->lpVtbl->HandleMessage(p,a,b,c)
|
||||
#define IDirectPlaySP_SetSPPlayerData(p,a,b,c,d) (p)->lpVtbl->SetSPPlayerData(p,a,b,c,d)
|
||||
#define IDirectPlaySP_CreateCompoundAddress(p,a,b,c,d) (p)->lpVtbl->CreateCompoundAddress(p,a,b,c,d)
|
||||
#define IDirectPlaySP_GetSPData(p,a,b,c) (p)->lpVtbl->GetSPData(p,a,b,c)
|
||||
#define IDirectPlaySP_SetSPData(p,a,b,c) (p)->lpVtbl->SetSPData(p,a,b,c)
|
||||
#define IDirectPlaySP_SendComplete(p,a,b) (p)->lpVtbl->SendComplete(p,a,b)
|
||||
#endif
|
||||
|
||||
/* SP Callback stuff */
|
||||
|
||||
typedef struct tagDPSP_ADDPLAYERTOGROUPDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DPID idGroup;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_ADDPLAYERTOGROUPDATA, *LPDPSP_ADDPLAYERTOGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_CLOSEDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CLOSEDATA, *LPDPSP_CLOSEDATA;
|
||||
|
||||
typedef struct tagDPSP_CREATEGROUPDATA
|
||||
{
|
||||
DPID idGroup;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CREATEGROUPDATA, *LPDPSP_CREATEGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_CREATEPLAYERDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_CREATEPLAYERDATA, *LPDPSP_CREATEPLAYERDATA;
|
||||
|
||||
typedef struct tagDPSP_DELETEGROUPDATA
|
||||
{
|
||||
DPID idGroup;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_DELETEGROUPDATA, *LPDPSP_DELETEGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_DELETEPLAYERDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_DELETEPLAYERDATA, *LPDPSP_DELETEPLAYERDATA;
|
||||
|
||||
typedef struct tagDPSP_ENUMSESSIONSDATA
|
||||
{
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
BOOL bReturnStatus;
|
||||
} DPSP_ENUMSESSIONSDATA, *LPDPSP_ENUMSESSIONSDATA;
|
||||
|
||||
typedef struct _DPSP_GETADDRESSDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DWORD dwFlags;
|
||||
LPDPADDRESS lpAddress;
|
||||
LPDWORD lpdwAddressSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETADDRESSDATA, *LPDPSP_GETADDRESSDATA;
|
||||
|
||||
typedef struct tagDPSP_GETADDRESSCHOICESDATA
|
||||
{
|
||||
LPDPADDRESS lpAddress;
|
||||
LPDWORD lpdwAddressSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETADDRESSCHOICESDATA, *LPDPSP_GETADDRESSCHOICESDATA;
|
||||
|
||||
typedef struct tagDPSP_GETCAPSDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
LPDPCAPS lpCaps;
|
||||
DWORD dwFlags;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_GETCAPSDATA, *LPDPSP_GETCAPSDATA;
|
||||
|
||||
typedef struct tagDPSP_OPENDATA
|
||||
{
|
||||
BOOL bCreate;
|
||||
LPVOID lpSPMessageHeader;
|
||||
IDirectPlaySP* lpISP;
|
||||
BOOL bReturnStatus;
|
||||
DWORD dwOpenFlags;
|
||||
DWORD dwSessionFlags;
|
||||
} DPSP_OPENDATA, *LPDPSP_OPENDATA;
|
||||
|
||||
typedef struct tagDPSP_REMOVEPLAYERFROMGROUPDATA
|
||||
{
|
||||
DPID idPlayer;
|
||||
DPID idGroup;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_REMOVEPLAYERFROMGROUPDATA, *LPDPSP_REMOVEPLAYERFROMGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_REPLYDATA
|
||||
{
|
||||
LPVOID lpSPMessageHeader;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
DPID idNameServer;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_REPLYDATA, *LPDPSP_REPLYDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDDATA
|
||||
{
|
||||
DWORD dwFlags;
|
||||
DPID idPlayerTo;
|
||||
DPID idPlayerFrom;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
BOOL bSystemMessage;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SENDDATA, *LPDPSP_SENDDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDTOGROUPDATA
|
||||
{
|
||||
DWORD dwFlags;
|
||||
DPID idGroupTo;
|
||||
DPID idPlayerFrom;
|
||||
LPVOID lpMessage;
|
||||
DWORD dwMessageSize;
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SENDTOGROUPDATA, *LPDPSP_SENDTOGROUPDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDEXDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idPlayerTo;
|
||||
DPID idPlayerFrom;
|
||||
LPSGBUFFER lpSendBuffers;
|
||||
DWORD cBuffers;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwPriority;
|
||||
DWORD dwTimeout;
|
||||
LPVOID lpDPContext;
|
||||
LPDWORD lpdwSPMsgID;
|
||||
BOOL bSystemMessage;
|
||||
} DPSP_SENDEXDATA, *LPDPSP_SENDEXDATA;
|
||||
|
||||
typedef struct tagDPSP_SENDTOGROUPEXDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idGroupTo;
|
||||
DPID idPlayerFrom;
|
||||
LPSGBUFFER lpSendBuffers;
|
||||
DWORD cBuffers;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwPriority;
|
||||
DWORD dwTimeout;
|
||||
LPVOID lpDPContext;
|
||||
LPDWORD lpdwSPMsgID;
|
||||
} DPSP_SENDTOGROUPEXDATA, *LPDPSP_SENDTOGROUPEXDATA;
|
||||
|
||||
typedef struct tagDPSP_GETMESSAGEQUEUEDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
DPID idFrom;
|
||||
DPID idTo;
|
||||
LPDWORD lpdwNumMsgs;
|
||||
LPDWORD lpdwNumBytes;
|
||||
} DPSP_GETMESSAGEQUEUEDATA, *LPDPSP_GETMESSAGEQUEUEDATA;
|
||||
|
||||
#define DPCANCELSEND_PRIORITY 0x00000001
|
||||
#define DPCANCELSEND_ALL 0x00000002
|
||||
|
||||
typedef struct tagDPSP_CANCELDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
DWORD dwFlags;
|
||||
LPRGLPVOID lprglpvSPMsgID;
|
||||
DWORD cSPMsgID;
|
||||
DWORD dwMinPriority;
|
||||
DWORD dwMaxPriority;
|
||||
} DPSP_CANCELDATA, *LPDPSP_CANCELDATA;
|
||||
|
||||
typedef struct tagDPSP_SHUTDOWNDATA
|
||||
{
|
||||
IDirectPlaySP* lpISP;
|
||||
} DPSP_SHUTDOWNDATA, *LPDPSP_SHUTDOWNDATA;
|
||||
|
||||
|
||||
/* Prototypes returned by SPInit */
|
||||
typedef HRESULT (WINAPI *LPDPSP_CREATEPLAYER)(LPDPSP_CREATEPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_DELETEPLAYER)(LPDPSP_DELETEPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SEND)(LPDPSP_SENDDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_ENUMSESSIONS)(LPDPSP_ENUMSESSIONSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_REPLY)(LPDPSP_REPLYDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SHUTDOWN)(void);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CREATEGROUP)(LPDPSP_CREATEGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_DELETEGROUP)(LPDPSP_DELETEGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_ADDPLAYERTOGROUP)(LPDPSP_ADDPLAYERTOGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_REMOVEPLAYERFROMGROUP)(LPDPSP_REMOVEPLAYERFROMGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETCAPS)(LPDPSP_GETCAPSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETADDRESS)(LPDPSP_GETADDRESSDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETADDRESSCHOICES)(LPDPSP_GETADDRESSCHOICESDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_OPEN)(LPDPSP_OPENDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CLOSE)(void);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUP)(LPDPSP_SENDTOGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SHUTDOWNEX)(LPDPSP_SHUTDOWNDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CLOSEEX)(LPDPSP_CLOSEDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDEX)(LPDPSP_SENDEXDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_SENDTOGROUPEX)(LPDPSP_SENDTOGROUPEXDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_CANCEL)(LPDPSP_CANCELDATA);
|
||||
typedef HRESULT (WINAPI *LPDPSP_GETMESSAGEQUEUE)(LPDPSP_GETMESSAGEQUEUEDATA);
|
||||
|
||||
|
||||
typedef struct tagDPSP_SPCALLBACKS
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwVersion;
|
||||
|
||||
LPDPSP_ENUMSESSIONS EnumSessions; /* Must be provided */
|
||||
LPDPSP_REPLY Reply; /* Must be provided */
|
||||
LPDPSP_SEND Send; /* Must be provided */
|
||||
LPDPSP_ADDPLAYERTOGROUP AddPlayerToGroup; /* Optional */
|
||||
LPDPSP_CLOSE Close; /* Optional */
|
||||
LPDPSP_CREATEGROUP CreateGroup; /* Optional */
|
||||
LPDPSP_CREATEPLAYER CreatePlayer; /* Optional */
|
||||
LPDPSP_DELETEGROUP DeleteGroup; /* Optional */
|
||||
LPDPSP_DELETEPLAYER DeletePlayer; /* Optional */
|
||||
LPDPSP_GETADDRESS GetAddress; /* Optional */
|
||||
LPDPSP_GETCAPS GetCaps; /* Optional */
|
||||
LPDPSP_OPEN Open; /* Optional */
|
||||
LPDPSP_REMOVEPLAYERFROMGROUP RemovePlayerFromGroup; /* Optional */
|
||||
LPDPSP_SENDTOGROUP SendToGroup; /* Optional */
|
||||
LPDPSP_SHUTDOWN Shutdown; /* Optional */
|
||||
|
||||
LPDPSP_CLOSEEX CloseEx; /* Optional */
|
||||
LPDPSP_SHUTDOWNEX ShutdownEx; /* Optional */
|
||||
LPDPSP_GETADDRESSCHOICES GetAddressChoices; /* Optional */
|
||||
|
||||
LPDPSP_SENDEX SendEx; /* Optional */
|
||||
LPDPSP_SENDTOGROUPEX SendToGroupEx; /* Optional */
|
||||
LPDPSP_CANCEL Cancel; /* Optional */
|
||||
LPDPSP_GETMESSAGEQUEUE GetMessageQueue; /* Optional */
|
||||
} DPSP_SPCALLBACKS, *LPDPSP_SPCALLBACKS;
|
||||
|
||||
typedef struct tagSPINITDATA
|
||||
{
|
||||
LPDPSP_SPCALLBACKS lpCB;
|
||||
IDirectPlaySP* lpISP;
|
||||
LPWSTR lpszName;
|
||||
LPGUID lpGuid;
|
||||
DWORD dwReserved1;
|
||||
DWORD dwReserved2;
|
||||
DWORD dwSPHeaderSize;
|
||||
LPDPADDRESS lpAddress;
|
||||
DWORD dwAddressSize;
|
||||
DWORD dwSPVersion;
|
||||
} SPINITDATA, *LPSPINITDATA;
|
||||
|
||||
typedef HRESULT (WINAPI *LPDPSP_SPINIT)(LPSPINITDATA);
|
||||
|
||||
/* This variable is exported from the DLL at ordinal 6 to be accessed by the
|
||||
* SP directly
|
||||
*/
|
||||
extern DWORD gdwDPlaySPRefCount;
|
||||
|
||||
#endif
|
12
reactos/lib/dplayx/dplayx.spec
Normal file
12
reactos/lib/dplayx/dplayx.spec
Normal file
|
@ -0,0 +1,12 @@
|
|||
1 stdcall DirectPlayCreate(ptr ptr ptr)
|
||||
2 stdcall DirectPlayEnumerateA(ptr ptr)
|
||||
3 stdcall DirectPlayEnumerateW(ptr ptr)
|
||||
4 stdcall DirectPlayLobbyCreateA(ptr ptr ptr ptr long)
|
||||
5 stdcall DirectPlayLobbyCreateW(ptr ptr ptr ptr long)
|
||||
6 extern gdwDPlaySPRefCount
|
||||
9 stdcall DirectPlayEnumerate(ptr ptr) DirectPlayEnumerateA
|
||||
|
||||
@ stdcall -private DllCanUnloadNow()
|
||||
@ stdcall -private DllGetClassObject(ptr ptr ptr)
|
||||
@ stdcall -private DllRegisterServer()
|
||||
@ stdcall -private DllUnregisterServer()
|
33
reactos/lib/dplayx/dplayx.xml
Normal file
33
reactos/lib/dplayx/dplayx.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<module name="dplayx" type="win32dll" baseaddress="${BASEADDRESS_DPLAYX}" installbase="system32" installname="dplayx.dll" allowwarnings ="true">
|
||||
<importlibrary definition="dplayx.spec.def" />
|
||||
<include base="dplayx">.</include>
|
||||
<include base="ReactOS">include/wine</include>
|
||||
<define name="UNICODE" />
|
||||
<define name="_UNICODE" />
|
||||
<define name="__REACTOS__" />
|
||||
<define name="__USE_W32API" />
|
||||
<define name="_WIN32_IE">0x600</define>
|
||||
<define name="_WIN32_WINNT">0x501</define>
|
||||
<define name="WINVER">0x501</define>
|
||||
<library>wine</library>
|
||||
<library>uuid</library>
|
||||
<library>ntdll</library>
|
||||
<library>kernel32</library>
|
||||
<library>user32</library>
|
||||
<library>advapi32</library>
|
||||
<library>ole32</library>
|
||||
<library>winmm</library>
|
||||
<library>dxguid</library>
|
||||
<file>version.rc</file>
|
||||
<file>dpclassfactory.c</file>
|
||||
<file>dplay.c</file>
|
||||
<file>dplaysp.c</file>
|
||||
<file>dplayx_global.c</file>
|
||||
<file>dplayx_main.c</file>
|
||||
<file>dplayx_messages.c</file>
|
||||
<file>dplobby.c</file>
|
||||
<file>lobbysp.c</file>
|
||||
<file>name_server.c</file>
|
||||
<file>regsvr.c</file>
|
||||
<file>dplayx.spec</file>
|
||||
</module>
|
1354
reactos/lib/dplayx/dplayx_global.c
Normal file
1354
reactos/lib/dplayx/dplayx_global.c
Normal file
File diff suppressed because it is too large
Load diff
76
reactos/lib/dplayx/dplayx_global.h
Normal file
76
reactos/lib/dplayx/dplayx_global.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 1999, 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPLAYX_GLOBAL
|
||||
#define __WINE_DPLAYX_GLOBAL
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "dplay.h"
|
||||
|
||||
BOOL DPLAYX_ConstructData(void);
|
||||
BOOL DPLAYX_DestructData(void);
|
||||
|
||||
HRESULT DPLAYX_GetConnectionSettingsA ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize );
|
||||
HRESULT DPLAYX_GetConnectionSettingsW ( DWORD dwAppID,
|
||||
LPVOID lpData,
|
||||
LPDWORD lpdwDataSize );
|
||||
|
||||
HRESULT DPLAYX_SetConnectionSettingsA ( DWORD dwFlags,
|
||||
DWORD dwAppID,
|
||||
LPDPLCONNECTION lpConn );
|
||||
HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags,
|
||||
DWORD dwAppID,
|
||||
LPDPLCONNECTION lpConn );
|
||||
|
||||
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID );
|
||||
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID );
|
||||
|
||||
BOOL DPLAYX_WaitForConnectionSettings( BOOL bWait );
|
||||
BOOL DPLAYX_AnyLobbiesWaitingForConnSettings(void);
|
||||
|
||||
BOOL DPLAYX_SetLobbyHandles( DWORD dwAppID,
|
||||
HANDLE hStart, HANDLE hDeath, HANDLE hConnRead );
|
||||
BOOL DPLAYX_GetThisLobbyHandles( LPHANDLE lphStart,
|
||||
LPHANDLE lphDeath,
|
||||
LPHANDLE lphConnRead, BOOL bClearSetHandles );
|
||||
|
||||
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index );
|
||||
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd );
|
||||
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd );
|
||||
|
||||
BOOL DPLAYX_SetLobbyMsgThreadId( DWORD dwAppId, DWORD dwThreadId );
|
||||
|
||||
/* FIXME: This should not be here */
|
||||
LPVOID DPLAYX_PrivHeapAlloc( DWORD flags, DWORD size );
|
||||
void DPLAYX_PrivHeapFree( LPVOID addr );
|
||||
|
||||
LPSTR DPLAYX_strdupA( DWORD flags, LPCSTR str );
|
||||
LPWSTR DPLAYX_strdupW( DWORD flags, LPCWSTR str );
|
||||
/* FIXME: End shared data alloc which should be local */
|
||||
|
||||
|
||||
/* Convert a DP or DPL HRESULT code into a string for human consumption */
|
||||
LPCSTR DPLAYX_HresultToString( HRESULT hr );
|
||||
|
||||
#endif /* __WINE_DPLAYX_GLOBAL */
|
111
reactos/lib/dplayx/dplayx_main.c
Normal file
111
reactos/lib/dplayx/dplayx_main.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* DPLAYX.DLL LibMain
|
||||
*
|
||||
* Copyright 1999,2000 - Peter Hunnisett
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NOTES
|
||||
* o DPMSGCMD_ENUMSESSIONSREPLY & DPMSGCMD_ENUMSESSIONSREQUEST
|
||||
* Have most fields understood, but not all. Everything seems to work.
|
||||
* o DPMSGCMD_REQUESTNEWPLAYERID & DPMSGCMD_NEWPLAYERIDREPLY
|
||||
* Barely work. This needs to be completed for sessions to start.
|
||||
* o A small issue will be the fact that DirectX 6.1(ie. DirectPlay4)
|
||||
* introduces a layer of functionality inside the DP objects which
|
||||
* provide guaranteed protocol delivery. This is even if the native
|
||||
* protocol, IPX or modem for instance, doesn't guarantee it. I'm going
|
||||
* to leave this kind of implementation to as close to the end as
|
||||
* possible. However, I will implement an abstraction layer, where
|
||||
* possible, for this functionality. It will do nothing to start, but
|
||||
* will require only the implementation of the guaranteness to give
|
||||
* final implementation.
|
||||
*
|
||||
* TODO:
|
||||
* - Implement mutual exclusion on object data for existing functions
|
||||
* - Ensure that all dll stubs are present and the ordinals are correct
|
||||
* - Addition of DirectX 7.0 functionality for direct play
|
||||
* - Implement some WineLib test programs using sdk programs as a skeleton
|
||||
* - Change RegEnumKeyEx enumeration pattern to allow error handling and to
|
||||
* share registry implementation (or at least simplify).
|
||||
* - Add in appropriate RegCloseKey calls for all the opening we're doing...
|
||||
* - Fix all the buffer sizes for registry calls. They're off by one -
|
||||
* but in a safe direction.
|
||||
* - Fix race condition on interface destruction
|
||||
* - Handles need to be correctly reference counted
|
||||
* - Check if we need to deallocate any list objects when destroying
|
||||
* a dplay interface
|
||||
* - RunApplication process spawning needs to have correct syncronization.
|
||||
* - Need to get inter lobby messages working.
|
||||
* - Decypher dplay messages between applications and implement...
|
||||
* - Need to implement lobby session spawning.
|
||||
* - Improve footprint and realtime blocking by setting up a separate data share
|
||||
* between lobby application and client since there can be multiple apps per
|
||||
* client. Also get rid of offset dependency by making data offset independent
|
||||
* somehow.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "winerror.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wine/debug.h"
|
||||
#include "dplayx_global.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* This is a globally exported variable at ordinal 6 of DPLAYX.DLL */
|
||||
DWORD gdwDPlaySPRefCount = 0; /* FIXME: Should it be initialized here? */
|
||||
|
||||
|
||||
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
|
||||
{
|
||||
|
||||
TRACE( "(%p,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved );
|
||||
|
||||
switch ( fdwReason )
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
/* First instance perform construction of global processor data */
|
||||
return DPLAYX_ConstructData();
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
/* Last instance performs destruction of global processor data */
|
||||
return DPLAYX_DestructData();
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllCanUnloadNow (DPLAYX.@)
|
||||
*/
|
||||
HRESULT WINAPI DllCanUnloadNow(void)
|
||||
{
|
||||
HRESULT hr = ( gdwDPlaySPRefCount > 0 ) ? S_FALSE : S_OK;
|
||||
|
||||
/* FIXME: Should I be putting a check in for class factory objects
|
||||
* as well
|
||||
*/
|
||||
|
||||
TRACE( ": returning 0x%08lx\n", hr );
|
||||
|
||||
return hr;
|
||||
}
|
511
reactos/lib/dplayx/dplayx_messages.c
Normal file
511
reactos/lib/dplayx/dplayx_messages.c
Normal file
|
@ -0,0 +1,511 @@
|
|||
/* DirectPlay & DirectPlayLobby messaging implementation
|
||||
*
|
||||
* Copyright 2000,2001 - Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NOTES
|
||||
* o Messaging interface required for both DirectPlay and DirectPlayLobby.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "winerror.h"
|
||||
#include "ntstatus.h"
|
||||
|
||||
#include "dplayx_messages.h"
|
||||
#include "dplay_global.h"
|
||||
#include "dplayx_global.h"
|
||||
#include "name_server.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
typedef struct tagMSGTHREADINFO
|
||||
{
|
||||
HANDLE hStart;
|
||||
HANDLE hDeath;
|
||||
HANDLE hSettingRead;
|
||||
HANDLE hNotifyEvent;
|
||||
} MSGTHREADINFO, *LPMSGTHREADINFO;
|
||||
|
||||
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
|
||||
static LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA data,
|
||||
DWORD dwWaitTime, WORD wReplyCommandId,
|
||||
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
|
||||
|
||||
|
||||
/* Create the message reception thread to allow the application to receive
|
||||
* asynchronous message reception
|
||||
*/
|
||||
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
|
||||
HANDLE hDeath, HANDLE hConnRead )
|
||||
{
|
||||
DWORD dwMsgThreadId;
|
||||
LPMSGTHREADINFO lpThreadInfo;
|
||||
|
||||
lpThreadInfo = HeapAlloc( GetProcessHeap(), 0, sizeof( *lpThreadInfo ) );
|
||||
if( lpThreadInfo == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The notify event may or may not exist. Depends if async comm or not */
|
||||
if( hNotifyEvent &&
|
||||
!DuplicateHandle( GetCurrentProcess(), hNotifyEvent,
|
||||
GetCurrentProcess(), &lpThreadInfo->hNotifyEvent,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS ) )
|
||||
{
|
||||
ERR( "Unable to duplicate event handle\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* These 3 handles don't need to be duplicated because we don't keep a
|
||||
* reference to them where they're created. They're created specifically
|
||||
* for the message thread
|
||||
*/
|
||||
lpThreadInfo->hStart = hStart;
|
||||
lpThreadInfo->hDeath = hDeath;
|
||||
lpThreadInfo->hSettingRead = hConnRead;
|
||||
|
||||
if( !CreateThread( NULL, /* Security attribs */
|
||||
0, /* Stack */
|
||||
DPL_MSG_ThreadMain, /* Msg reception function */
|
||||
lpThreadInfo, /* Msg reception func parameter */
|
||||
0, /* Flags */
|
||||
&dwMsgThreadId /* Updated with thread id */
|
||||
)
|
||||
)
|
||||
{
|
||||
ERR( "Unable to create msg thread\n" );
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* FIXME: Should I be closing the handle to the thread or does that
|
||||
terminate the thread? */
|
||||
|
||||
return dwMsgThreadId;
|
||||
|
||||
error:
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, lpThreadInfo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext )
|
||||
{
|
||||
LPMSGTHREADINFO lpThreadInfo = (LPMSGTHREADINFO)lpContext;
|
||||
DWORD dwWaitResult;
|
||||
|
||||
TRACE( "Msg thread created. Waiting on app startup\n" );
|
||||
|
||||
/* Wait to ensure that the lobby application is started w/ 1 min timeout */
|
||||
dwWaitResult = WaitForSingleObject( lpThreadInfo->hStart, 10000 /* 10 sec */ );
|
||||
if( dwWaitResult == WAIT_TIMEOUT )
|
||||
{
|
||||
FIXME( "Should signal app/wait creation failure (0x%08lx)\n", dwWaitResult );
|
||||
goto end_of_thread;
|
||||
}
|
||||
|
||||
/* Close this handle as it's not needed anymore */
|
||||
CloseHandle( lpThreadInfo->hStart );
|
||||
lpThreadInfo->hStart = 0;
|
||||
|
||||
/* Wait until the lobby knows what it is */
|
||||
dwWaitResult = WaitForSingleObject( lpThreadInfo->hSettingRead, INFINITE );
|
||||
if( dwWaitResult == WAIT_TIMEOUT )
|
||||
{
|
||||
ERR( "App Read connection setting timeout fail (0x%08lx)\n", dwWaitResult );
|
||||
}
|
||||
|
||||
/* Close this handle as it's not needed anymore */
|
||||
CloseHandle( lpThreadInfo->hSettingRead );
|
||||
lpThreadInfo->hSettingRead = 0;
|
||||
|
||||
TRACE( "App created && intialized starting main message reception loop\n" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
MSG lobbyMsg;
|
||||
GetMessageW( &lobbyMsg, 0, 0, 0 );
|
||||
}
|
||||
|
||||
end_of_thread:
|
||||
TRACE( "Msg thread exiting!\n" );
|
||||
HeapFree( GetProcessHeap(), 0, lpThreadInfo );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DP messageing stuff */
|
||||
static HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
|
||||
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
|
||||
WORD wReplyCommandId );
|
||||
static LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
|
||||
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
|
||||
|
||||
|
||||
static
|
||||
HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
|
||||
LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, WORD wReplyCommandId )
|
||||
{
|
||||
lpReplyStructList->replyExpected.hReceipt = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
|
||||
lpReplyStructList->replyExpected.lpReplyMsg = NULL;
|
||||
lpReplyStructList->replyExpected.dwMsgBodySize = 0;
|
||||
|
||||
/* Insert into the message queue while locked */
|
||||
EnterCriticalSection( &This->unk->DP_lock );
|
||||
DPQ_INSERT( This->dp2->replysExpected, lpReplyStructList, replysExpected );
|
||||
LeaveCriticalSection( &This->unk->DP_lock );
|
||||
|
||||
return lpReplyStructList->replyExpected.hReceipt;
|
||||
}
|
||||
|
||||
static
|
||||
LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
|
||||
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
|
||||
{
|
||||
CloseHandle( lpReplyStructList->replyExpected.hReceipt );
|
||||
|
||||
*lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg;
|
||||
*lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
|
||||
|
||||
return lpReplyStructList->replyExpected.lpReplyMsg;
|
||||
}
|
||||
|
||||
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
|
||||
LPDPID lpdpidAllocatedId )
|
||||
{
|
||||
LPVOID lpMsg;
|
||||
LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
|
||||
DWORD dwMsgSize;
|
||||
HRESULT hr = DP_OK;
|
||||
|
||||
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
|
||||
|
||||
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
|
||||
|
||||
lpMsgBody = (LPDPMSG_REQUESTNEWPLAYERID)( (BYTE*)lpMsg +
|
||||
This->dp2->spData.dwSPHeaderSize );
|
||||
|
||||
/* Compose dplay message envelope */
|
||||
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
|
||||
lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
/* Compose the body of the message */
|
||||
lpMsgBody->dwFlags = dwFlags;
|
||||
|
||||
/* Send the message */
|
||||
{
|
||||
DPSP_SENDDATA data;
|
||||
|
||||
data.dwFlags = DPSEND_GUARANTEED;
|
||||
data.idPlayerTo = 0; /* Name server */
|
||||
data.idPlayerFrom = 0; /* Sending from DP */
|
||||
data.lpMessage = lpMsg;
|
||||
data.dwMessageSize = dwMsgSize;
|
||||
data.bSystemMessage = TRUE; /* Allow reply to be sent */
|
||||
data.lpISP = This->dp2->spData.lpISP;
|
||||
|
||||
TRACE( "Asking for player id w/ dwFlags 0x%08lx\n",
|
||||
lpMsgBody->dwFlags );
|
||||
|
||||
DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY,
|
||||
&lpMsg, &dwMsgSize );
|
||||
}
|
||||
|
||||
/* Need to examine the data and extract the new player id */
|
||||
if( !FAILED(hr) )
|
||||
{
|
||||
LPCDPMSG_NEWPLAYERIDREPLY lpcReply;
|
||||
|
||||
lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)lpMsg;
|
||||
|
||||
*lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
|
||||
|
||||
TRACE( "Received reply for id = 0x%08lx\n", lpcReply->dpidNewPlayerId );
|
||||
|
||||
/* FIXME: I think that the rest of the message has something to do
|
||||
* with remote data for the player that perhaps I need to setup.
|
||||
* However, with the information that is passed, all that it could
|
||||
* be used for is a standardized intialization value, which I'm
|
||||
* guessing we can do without. Unless the message content is the same
|
||||
* for several different messages?
|
||||
*/
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, lpMsg );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer )
|
||||
{
|
||||
LPVOID lpMsg;
|
||||
LPDPMSG_FORWARDADDPLAYER lpMsgBody;
|
||||
DWORD dwMsgSize;
|
||||
HRESULT hr = DP_OK;
|
||||
|
||||
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
|
||||
|
||||
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
|
||||
|
||||
lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
|
||||
This->dp2->spData.dwSPHeaderSize );
|
||||
|
||||
/* Compose dplay message envelope */
|
||||
lpMsgBody->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
lpMsgBody->envelope.wCommandId = DPMSGCMD_FORWARDADDPLAYER;
|
||||
lpMsgBody->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
#if 0
|
||||
{
|
||||
LPBYTE lpPData;
|
||||
DWORD dwDataSize;
|
||||
|
||||
/* SP Player remote data needs to be propagated at some point - is this the point? */
|
||||
IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, 0, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE );
|
||||
|
||||
ERR( "Player Data size is 0x%08lx\n"
|
||||
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
|
||||
"[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n",
|
||||
|
||||
dwDataSize,
|
||||
lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
|
||||
lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
|
||||
lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
|
||||
lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
|
||||
lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
|
||||
lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
|
||||
lpPData[30], lpPData[31]
|
||||
);
|
||||
DebugBreak();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compose body of message */
|
||||
lpMsgBody->dpidAppServer = dpidServer;
|
||||
lpMsgBody->unknown2[0] = 0x0;
|
||||
lpMsgBody->unknown2[1] = 0x1c;
|
||||
lpMsgBody->unknown2[2] = 0x6c;
|
||||
lpMsgBody->unknown2[3] = 0x50;
|
||||
lpMsgBody->unknown2[4] = 0x9;
|
||||
|
||||
lpMsgBody->dpidAppServer2 = dpidServer;
|
||||
lpMsgBody->unknown3[0] = 0x0;
|
||||
lpMsgBody->unknown3[0] = 0x0;
|
||||
lpMsgBody->unknown3[0] = 0x20;
|
||||
lpMsgBody->unknown3[0] = 0x0;
|
||||
lpMsgBody->unknown3[0] = 0x0;
|
||||
|
||||
lpMsgBody->dpidAppServer3 = dpidServer;
|
||||
lpMsgBody->unknown4[0] = 0x30;
|
||||
lpMsgBody->unknown4[1] = 0xb;
|
||||
lpMsgBody->unknown4[2] = 0x0;
|
||||
|
||||
lpMsgBody->unknown4[3] = NS_GetNsMagic( This->dp2->lpNameServerData ) -
|
||||
0x02000000;
|
||||
TRACE( "Setting first magic to 0x%08lx\n", lpMsgBody->unknown4[3] );
|
||||
|
||||
lpMsgBody->unknown4[4] = 0x0;
|
||||
lpMsgBody->unknown4[5] = 0x0;
|
||||
lpMsgBody->unknown4[6] = 0x0;
|
||||
|
||||
#if 0
|
||||
lpMsgBody->unknown4[7] = NS_GetOtherMagic( This->dp2->lpNameServerData )
|
||||
#else
|
||||
lpMsgBody->unknown4[7] = NS_GetNsMagic( This->dp2->lpNameServerData );
|
||||
#endif
|
||||
TRACE( "Setting second magic to 0x%08lx\n", lpMsgBody->unknown4[7] );
|
||||
|
||||
lpMsgBody->unknown4[8] = 0x0;
|
||||
lpMsgBody->unknown4[9] = 0x0;
|
||||
lpMsgBody->unknown4[10] = 0x0;
|
||||
lpMsgBody->unknown4[11] = 0x0;
|
||||
|
||||
lpMsgBody->unknown5[0] = 0x0;
|
||||
lpMsgBody->unknown5[1] = 0x0;
|
||||
|
||||
/* Send the message */
|
||||
{
|
||||
DPSP_SENDDATA data;
|
||||
|
||||
data.dwFlags = DPSEND_GUARANTEED;
|
||||
data.idPlayerTo = 0; /* Name server */
|
||||
data.idPlayerFrom = dpidServer; /* Sending from session server */
|
||||
data.lpMessage = lpMsg;
|
||||
data.dwMessageSize = dwMsgSize;
|
||||
data.bSystemMessage = TRUE; /* Allow reply to be sent */
|
||||
data.lpISP = This->dp2->spData.lpISP;
|
||||
|
||||
TRACE( "Sending forward player request with 0x%08lx\n", dpidServer );
|
||||
|
||||
lpMsg = DP_MSG_ExpectReply( This, &data,
|
||||
DPMSG_WAIT_60_SECS,
|
||||
DPMSGCMD_GETNAMETABLEREPLY,
|
||||
&lpMsg, &dwMsgSize );
|
||||
}
|
||||
|
||||
/* Need to examine the data and extract the new player id */
|
||||
if( lpMsg != NULL )
|
||||
{
|
||||
FIXME( "Name Table reply received: stub\n" );
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
|
||||
* not seem to offer any way of uniquely differentiating between replies of the same type
|
||||
* relative to the request sent. There is an implicit assumption that there will be no
|
||||
* ordering issues on sends and receives from the opposite machine. No wonder MS is not
|
||||
* a networking company.
|
||||
*/
|
||||
static
|
||||
LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA lpData,
|
||||
DWORD dwWaitTime, WORD wReplyCommandId,
|
||||
LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
|
||||
{
|
||||
HRESULT hr;
|
||||
HANDLE hMsgReceipt;
|
||||
DP_MSG_REPLY_STRUCT_LIST replyStructList;
|
||||
DWORD dwWaitReturn;
|
||||
|
||||
/* Setup for receipt */
|
||||
hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList,
|
||||
wReplyCommandId );
|
||||
|
||||
TRACE( "Sending msg and expecting cmd %u in reply within %lu ticks\n",
|
||||
wReplyCommandId, dwWaitTime );
|
||||
hr = (*This->dp2->spData.lpCB->Send)( lpData );
|
||||
|
||||
if( FAILED(hr) )
|
||||
{
|
||||
ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The reply message will trigger the hMsgReceipt event effectively switching
|
||||
* control back to this thread. See DP_MSG_ReplyReceived.
|
||||
*/
|
||||
dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
|
||||
if( dwWaitReturn != WAIT_OBJECT_0 )
|
||||
{
|
||||
ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clean Up */
|
||||
return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
|
||||
}
|
||||
|
||||
/* Determine if there is a matching request for this incoming message and then copy
|
||||
* all important data. It is quite silly to have to copy the message, but the documents
|
||||
* indicate that a copy is taken. Silly really.
|
||||
*/
|
||||
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
|
||||
LPCVOID lpcMsgBody, DWORD dwMsgBodySize )
|
||||
{
|
||||
LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
|
||||
|
||||
#if 0
|
||||
if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
|
||||
{
|
||||
DebugBreak();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to
|
||||
* avoid problems.
|
||||
*/
|
||||
EnterCriticalSection( &This->unk->DP_lock );
|
||||
DPQ_REMOVE_ENTRY( This->dp2->replysExpected, replysExpected, replyExpected.wExpectedReply,\
|
||||
==, wCommandId, lpReplyList );
|
||||
LeaveCriticalSection( &This->unk->DP_lock );
|
||||
|
||||
if( lpReplyList != NULL )
|
||||
{
|
||||
lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize;
|
||||
lpReplyList->replyExpected.lpReplyMsg = HeapAlloc( GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
dwMsgBodySize );
|
||||
CopyMemory( lpReplyList->replyExpected.lpReplyMsg,
|
||||
lpcMsgBody, dwMsgBodySize );
|
||||
|
||||
/* Signal the thread which sent the message that it has a reply */
|
||||
SetEvent( lpReplyList->replyExpected.hReceipt );
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR( "No receipt event set - only expecting in reply mode\n" );
|
||||
DebugBreak();
|
||||
}
|
||||
}
|
||||
|
||||
void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf )
|
||||
{
|
||||
LPVOID lpMsg;
|
||||
LPDPMSG_SENDENVELOPE lpMsgBody;
|
||||
DWORD dwMsgSize;
|
||||
|
||||
dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
|
||||
|
||||
lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
|
||||
|
||||
lpMsgBody = (LPDPMSG_SENDENVELOPE)( (BYTE*)lpMsg +
|
||||
This->dp2->spData.dwSPHeaderSize );
|
||||
|
||||
/* Compose dplay message envelope */
|
||||
lpMsgBody->dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
lpMsgBody->wCommandId = DPMSGCMD_JUSTENVELOPE;
|
||||
lpMsgBody->wVersion = DPMSGVER_DP6;
|
||||
|
||||
/* Send the message to ourselves */
|
||||
{
|
||||
DPSP_SENDDATA data;
|
||||
|
||||
data.dwFlags = 0;
|
||||
data.idPlayerTo = dpidSelf; /* Sending to session server */
|
||||
data.idPlayerFrom = 0; /* Sending from session server */
|
||||
data.lpMessage = lpMsg;
|
||||
data.dwMessageSize = dwMsgSize;
|
||||
data.bSystemMessage = TRUE; /* Allow reply to be sent */
|
||||
data.lpISP = This->dp2->spData.lpISP;
|
||||
|
||||
lpMsg = DP_MSG_ExpectReply( This, &data,
|
||||
DPMSG_WAIT_5_SECS,
|
||||
DPMSGCMD_JUSTENVELOPE,
|
||||
&lpMsg, &dwMsgSize );
|
||||
}
|
||||
}
|
||||
|
||||
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
|
||||
LPCVOID lpMsgBody, DWORD dwMsgBodySize )
|
||||
{
|
||||
LPCDPMSG_FORWARDADDPLAYERNACK lpcErrorMsg;
|
||||
|
||||
lpcErrorMsg = (LPCDPMSG_FORWARDADDPLAYERNACK)lpMsgBody;
|
||||
|
||||
ERR( "Received error message %u. Error is %s\n",
|
||||
wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
|
||||
DebugBreak();
|
||||
}
|
223
reactos/lib/dplayx/dplayx_messages.h
Normal file
223
reactos/lib/dplayx/dplayx_messages.h
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPLAYX_MESSAGES__
|
||||
#define __WINE_DPLAYX_MESSAGES__
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "dplay.h"
|
||||
#include "rpc.h" /* For GUID */
|
||||
|
||||
#include "dplay_global.h"
|
||||
|
||||
DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
|
||||
HANDLE hDeath, HANDLE hConnRead );
|
||||
|
||||
HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
|
||||
LPDPID lpdipidAllocatedId );
|
||||
HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer );
|
||||
|
||||
void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId,
|
||||
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
|
||||
void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
|
||||
LPCVOID lpMsgBody, DWORD dwMsgBodySize );
|
||||
void DP_MSG_ToSelf( IDirectPlay2AImpl* This, DPID dpidSelf );
|
||||
|
||||
/* Timings -> 1000 ticks/sec */
|
||||
#define DPMSG_WAIT_5_SECS 5000
|
||||
#define DPMSG_WAIT_30_SECS 30000
|
||||
#define DPMSG_WAIT_60_SECS 60000
|
||||
#define DPMSG_DEFAULT_WAIT_TIME DPMSG_WAIT_30_SECS
|
||||
|
||||
/* Message types etc. */
|
||||
#include "pshpack1.h"
|
||||
|
||||
/* Non provided messages for DPLAY - guess work which may be wrong :( */
|
||||
#define DPMSGCMD_ENUMSESSIONSREPLY 1
|
||||
#define DPMSGCMD_ENUMSESSIONSREQUEST 2
|
||||
#define DPMSGCMD_GETNAMETABLEREPLY 3 /* Contains all existing players in session */
|
||||
|
||||
#define DPMSGCMD_REQUESTNEWPLAYERID 5
|
||||
|
||||
#define DPMSGCMD_NEWPLAYERIDREPLY 7
|
||||
#define DPMSGCMD_CREATESESSION 8 /* Might be a create nameserver or new player msg */
|
||||
#define DPMSGCMD_CREATENEWPLAYER 9
|
||||
#define DPMSGCMD_SYSTEMMESSAGE 10
|
||||
#define DPMSGCMD_DELETEPLAYER 11
|
||||
#define DPMSGCMD_DELETEGROUP 12
|
||||
|
||||
#define DPMSGCMD_ENUMGROUPS 17
|
||||
|
||||
#define DPMSGCMD_FORWARDADDPLAYER 19
|
||||
|
||||
#define DPMSGCMD_PLAYERCHAT 22
|
||||
|
||||
#define DPMSGCMD_FORWARDADDPLAYERNACK 36
|
||||
|
||||
#define DPMSGCMD_JUSTENVELOPE 1000
|
||||
#define DPMSGCMD_JUSTENVELOPEREPLY 1001
|
||||
|
||||
/* This is what DP 6 defines it as. Don't know what it means. All messages
|
||||
* defined below are DPMSGVER_DP6.
|
||||
*/
|
||||
#define DPMSGVER_DP6 11
|
||||
|
||||
/* MAGIC number at the start of all dplay packets ("play" in ASCII) */
|
||||
#define DPMSGMAGIC_DPLAYMSG 0x79616c70
|
||||
|
||||
/* All messages sent from the system are sent with this at the beginning of
|
||||
* the message.
|
||||
* Size is 8 bytes
|
||||
*/
|
||||
typedef struct tagDPMSG_SENDENVELOPE
|
||||
{
|
||||
DWORD dwMagic;
|
||||
WORD wCommandId;
|
||||
WORD wVersion;
|
||||
} DPMSG_SENDENVELOPE, *LPDPMSG_SENDENVELOPE;
|
||||
typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
|
||||
|
||||
/* System messages exchanged between players seems to have this
|
||||
* payload envelope on top of the basic envelope
|
||||
*/
|
||||
typedef struct tagDPMSG_SYSMSGENVELOPE
|
||||
{
|
||||
DWORD dwPlayerFrom;
|
||||
DWORD dwPlayerTo;
|
||||
} DPMSG_SYSMSGENVELOPE, *LPDPMSG_SYSMSGENVELOPE;
|
||||
typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
|
||||
|
||||
/* Reply sent in response to an enumsession request */
|
||||
typedef struct tagDPMSG_ENUMSESSIONSREPLY
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
#if 0
|
||||
DWORD dwSize; /* Size of DPSESSIONDESC2 struct */
|
||||
DWORD dwFlags; /* Sessions flags */
|
||||
|
||||
GUID guidInstance; /* Not 100% sure this is what it is... */
|
||||
|
||||
GUID guidApplication;
|
||||
|
||||
DWORD dwMaxPlayers;
|
||||
DWORD dwCurrentPlayers;
|
||||
|
||||
BYTE unknown[36];
|
||||
#else
|
||||
DPSESSIONDESC2 sd;
|
||||
#endif
|
||||
|
||||
DWORD dwUnknown; /* Seems to be equal to 0x5c which is a "\\" */
|
||||
/* Encryption package string? */
|
||||
|
||||
/* At the end we have ... */
|
||||
/* WCHAR wszSessionName[1]; Var length with NULL terminal */
|
||||
|
||||
} DPMSG_ENUMSESSIONSREPLY, *LPDPMSG_ENUMSESSIONSREPLY;
|
||||
typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY;
|
||||
|
||||
/* Msg sent to find out what sessions are available */
|
||||
typedef struct tagDPMSG_ENUMSESSIONSREQUEST
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
GUID guidApplication;
|
||||
|
||||
DWORD dwPasswordSize; /* A Guess. This is 0x00000000. */
|
||||
/* This might be the name server DPID which
|
||||
is needed for the reply */
|
||||
|
||||
DWORD dwFlags; /* dwFlags from EnumSessions */
|
||||
|
||||
} DPMSG_ENUMSESSIONSREQUEST, *LPDPMSG_ENUMSESSIONSREQUEST;
|
||||
typedef const DPMSG_ENUMSESSIONSREQUEST* LPCDPMSG_ENUMSESSIONSREQUEST;
|
||||
|
||||
/* Size is 146 received - with 18 or 20 bytes header = ~128 bytes */
|
||||
typedef struct tagDPMSG_CREATESESSION
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
} DPMSG_CREATESESSION, *LPDPMSG_CREATESESSION;
|
||||
typedef const DPMSG_CREATESESSION* LPCDPMSG_CREATESESSION;
|
||||
|
||||
/* 12 bytes msg */
|
||||
typedef struct tagDPMSG_REQUESTNEWPLAYERID
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
DWORD dwFlags; /* dwFlags used for CreatePlayer */
|
||||
|
||||
} DPMSG_REQUESTNEWPLAYERID, *LPDPMSG_REQUESTNEWPLAYERID;
|
||||
typedef const DPMSG_REQUESTNEWPLAYERID* LPCDPMSG_REQUESTNEWPLAYERID;
|
||||
|
||||
/* 48 bytes msg */
|
||||
typedef struct tagDPMSG_NEWPLAYERIDREPLY
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
DPID dpidNewPlayerId;
|
||||
|
||||
/* Assume that this is data that is tacked on to the end of the message
|
||||
* that comes from the SP remote data stored that needs to be propagated.
|
||||
*/
|
||||
BYTE unknown[36]; /* This appears to always be 0 - not sure though */
|
||||
} DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
|
||||
typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
|
||||
|
||||
typedef struct tagDPMSG_FORWARDADDPLAYER
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
|
||||
DWORD unknown; /* 0 */
|
||||
|
||||
DPID dpidAppServer; /* Remote application server id */
|
||||
DWORD unknown2[5]; /* 0x0, 0x1c, 0x6c, 0x50, 0x9 */
|
||||
|
||||
DPID dpidAppServer2; /* Remote application server id again !? */
|
||||
DWORD unknown3[5]; /* 0x0, 0x0, 0x20, 0x0, 0x0 */
|
||||
|
||||
DPID dpidAppServer3; /* Remote application server id again !? */
|
||||
|
||||
DWORD unknown4[12]; /* ??? - Is this a clump of 5 and then 8? */
|
||||
/* NOTE: 1 byte in front of the two 0x??090002 entries changes!
|
||||
* Is it a timestamp of some sort? 1st always smaller than
|
||||
* other...
|
||||
*/
|
||||
#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
|
||||
|
||||
BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! ( 0x0, 0x0) */
|
||||
|
||||
} DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER;
|
||||
typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER;
|
||||
|
||||
/* This is an error message that can be received. Not sure if this is
|
||||
* specifically for a forward add player or for all errors
|
||||
*/
|
||||
typedef struct tagDPMSG_FORWARDADDPLAYERNACK
|
||||
{
|
||||
DPMSG_SENDENVELOPE envelope;
|
||||
HRESULT errorCode;
|
||||
} DPMSG_FORWARDADDPLAYERNACK, *LPDPMSG_FORWARDADDPLAYERNACK;
|
||||
typedef const DPMSG_FORWARDADDPLAYERNACK* LPCDPMSG_FORWARDADDPLAYERNACK;
|
||||
|
||||
#include "poppack.h"
|
||||
|
||||
#endif
|
216
reactos/lib/dplayx/dplayx_queue.h
Normal file
216
reactos/lib/dplayx/dplayx_queue.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/* A queue definition based on sys/queue.h TAILQ definitions
|
||||
*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NOTES
|
||||
* o Linked list implementation for dplay/dplobby. Based off of the BSD
|
||||
* version found in <sys/queue.h>
|
||||
* o Port it to <wine/list.h> ?
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPLAYX_QUEUE_H
|
||||
#define __WINE_DPLAYX_QUEUE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
||||
#define DPQ_INSERT(a,b,c) DPQ_INSERT_IN_TAIL(a,b,c)
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define DPQ_HEAD(type) \
|
||||
struct { \
|
||||
struct type *lpQHFirst; /* first element */ \
|
||||
struct type **lpQHLast; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define DPQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *lpQNext; /* next element */ \
|
||||
struct type **lpQPrev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define DPQ_INIT(head) \
|
||||
do{ \
|
||||
(head).lpQHFirst = NULL; \
|
||||
(head).lpQHLast = &(head).lpQHFirst; \
|
||||
} while(0)
|
||||
|
||||
/* Front of the queue */
|
||||
#define DPQ_FIRST( head ) ( (head).lpQHFirst )
|
||||
|
||||
/* Check if the queue has any elements */
|
||||
#define DPQ_IS_EMPTY( head ) ( DPQ_FIRST(head) == NULL )
|
||||
|
||||
/* Next entry -- FIXME: Convert everything over to this macro ... */
|
||||
#define DPQ_NEXT( elem ) (elem).lpQNext
|
||||
|
||||
#define DPQ_IS_ENDOFLIST( elem ) \
|
||||
( DPQ_NEXT(elem) == NULL )
|
||||
|
||||
/* Insert element at end of queue */
|
||||
#define DPQ_INSERT_IN_TAIL(head, elm, field) \
|
||||
do { \
|
||||
(elm)->field.lpQNext = NULL; \
|
||||
(elm)->field.lpQPrev = (head).lpQHLast; \
|
||||
*(head).lpQHLast = (elm); \
|
||||
(head).lpQHLast = &(elm)->field.lpQNext; \
|
||||
} while(0)
|
||||
|
||||
/* Remove element from the queue */
|
||||
#define DPQ_REMOVE(head, elm, field) \
|
||||
do { \
|
||||
if (((elm)->field.lpQNext) != NULL) \
|
||||
(elm)->field.lpQNext->field.lpQPrev = \
|
||||
(elm)->field.lpQPrev; \
|
||||
else \
|
||||
(head).lpQHLast = (elm)->field.lpQPrev; \
|
||||
*(elm)->field.lpQPrev = (elm)->field.lpQNext; \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to DPQ_HEAD struct
|
||||
* elm - how to find the next element
|
||||
* field - to be concatenated to rc to compare with fieldToCompare
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* fieldCompareOperator - The logical operator to compare field and
|
||||
* fieldToCompare.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
|
||||
do { \
|
||||
(rc) = DPQ_FIRST(head); /* NULL head? */ \
|
||||
\
|
||||
while( rc ) \
|
||||
{ \
|
||||
/* What we're searching for? */ \
|
||||
if( (rc)->field fieldCompareOperator (fieldToCompare) ) \
|
||||
{ \
|
||||
break; /* rc == correct element */ \
|
||||
} \
|
||||
\
|
||||
/* End of list check */ \
|
||||
if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \
|
||||
{ \
|
||||
rc = NULL; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to DPQ_HEAD struct
|
||||
* elm - how to find the next element
|
||||
* field - to be concatenated to rc to compare with fieldToCompare
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* compare_cb - Callback to invoke to determine if comparision should continue.
|
||||
* Callback must be defined with DPQ_DECL_COMPARECB.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\
|
||||
do { \
|
||||
(rc) = DPQ_FIRST(head); /* NULL head? */ \
|
||||
\
|
||||
while( rc ) \
|
||||
{ \
|
||||
/* What we're searching for? */ \
|
||||
if( compare_cb( &((rc)->field), &(fieldToCompare) ) ) \
|
||||
{ \
|
||||
break; /* no more */ \
|
||||
} \
|
||||
\
|
||||
/* End of list check */ \
|
||||
if( ( (rc) = (rc)->elm.lpQNext ) == (head).lpQHFirst ) \
|
||||
{ \
|
||||
rc = NULL; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* How to define the method to be passed to DPQ_DELETEQ */
|
||||
#define DPQ_DECL_COMPARECB( name, type ) BOOL name( const type* elem1, const type* elem2 )
|
||||
|
||||
|
||||
/* head - pointer to DPQ_HEAD struct
|
||||
* elm - how to find the next element
|
||||
* field - to be concatenated to rc to compare with fieldToEqual
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* fieldCompareOperator - The logical operator to compare field and
|
||||
* fieldToCompare.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_REMOVE_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc )\
|
||||
do { \
|
||||
DPQ_FIND_ENTRY( head, elm, field, fieldCompareOperator, fieldToCompare, rc );\
|
||||
\
|
||||
/* Was the element found? */ \
|
||||
if( rc ) \
|
||||
{ \
|
||||
DPQ_REMOVE( head, rc, elm ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* head - pointer to DPQ_HEAD struct
|
||||
* elm - how to find the next element
|
||||
* field - to be concatenated to rc to compare with fieldToCompare
|
||||
* fieldToCompare - The value that we're comparing against
|
||||
* compare_cb - Callback to invoke to determine if comparision should continue.
|
||||
* Callback must be defined with DPQ_DECL_COMPARECB.
|
||||
* rc - Variable to put the return code. Same type as (head).lpQHFirst
|
||||
*/
|
||||
#define DPQ_REMOVE_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc )\
|
||||
do { \
|
||||
DPQ_FIND_ENTRY_CB( head, elm, field, compare_cb, fieldToCompare, rc );\
|
||||
\
|
||||
/* Was the element found? */ \
|
||||
if( rc ) \
|
||||
{ \
|
||||
DPQ_REMOVE( head, rc, elm ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* Delete the entire queue
|
||||
* head - pointer to the head of the queue
|
||||
* field - field to access the next elements of the queue
|
||||
* type - type of the pointer to the element element
|
||||
* df - a delete function to be called. Declared with DPQ_DECL_DELETECB.
|
||||
*/
|
||||
#define DPQ_DELETEQ( head, field, type, df ) \
|
||||
do \
|
||||
{ \
|
||||
while( !DPQ_IS_EMPTY(head) ) \
|
||||
{ \
|
||||
type holder = DPQ_FIRST(head); \
|
||||
DPQ_REMOVE( head, holder, field ); \
|
||||
df( holder ); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* How to define the method to be passed to DPQ_DELETEQ */
|
||||
#define DPQ_DECL_DELETECB( name, type ) void name( type elem )
|
||||
|
||||
/* Prototype of a method which just performs a HeapFree on the elem */
|
||||
DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID );
|
||||
|
||||
#endif /* __WINE_DPLAYX_QUEUE_H */
|
2012
reactos/lib/dplayx/dplobby.c
Normal file
2012
reactos/lib/dplayx/dplobby.c
Normal file
File diff suppressed because it is too large
Load diff
462
reactos/lib/dplayx/lobbysp.c
Normal file
462
reactos/lib/dplayx/lobbysp.c
Normal file
|
@ -0,0 +1,462 @@
|
|||
/* This contains the implementation of the Lobby Service
|
||||
* Providers interface required to communicate with Direct Play
|
||||
*
|
||||
* Copyright 2001 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "lobbysp.h"
|
||||
#include "dplay_global.h"
|
||||
#include "dpinit.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* Prototypes */
|
||||
static BOOL DPLSP_CreateIUnknown( LPVOID lpSP );
|
||||
static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP );
|
||||
static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp );
|
||||
static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP );
|
||||
|
||||
|
||||
/* Predefine the interface */
|
||||
typedef struct IDPLobbySPImpl IDPLobbySPImpl;
|
||||
|
||||
typedef struct tagDPLobbySPIUnknownData
|
||||
{
|
||||
LONG ulObjRef;
|
||||
CRITICAL_SECTION DPLSP_lock;
|
||||
} DPLobbySPIUnknownData;
|
||||
|
||||
typedef struct tagDPLobbySPData
|
||||
{
|
||||
IDirectPlay2Impl* dplay;
|
||||
} DPLobbySPData;
|
||||
|
||||
#define DPLSP_IMPL_FIELDS \
|
||||
LONG ulInterfaceRef; \
|
||||
DPLobbySPIUnknownData* unk; \
|
||||
DPLobbySPData* sp;
|
||||
|
||||
struct IDPLobbySPImpl
|
||||
{
|
||||
const IDPLobbySPVtbl *lpVtbl;
|
||||
DPLSP_IMPL_FIELDS
|
||||
};
|
||||
|
||||
/* Forward declaration of virtual tables */
|
||||
static const IDPLobbySPVtbl dpLobbySPVT;
|
||||
|
||||
HRESULT DPLSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
|
||||
{
|
||||
TRACE( " for %s\n", debugstr_guid( riid ) );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( IDPLobbySPImpl ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
|
||||
This->lpVtbl = &dpLobbySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
if( DPLSP_CreateIUnknown( *ppvObj ) &&
|
||||
DPLSP_CreateDPLobbySP( *ppvObj, dp )
|
||||
)
|
||||
{
|
||||
IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Initialize failed, destroy it */
|
||||
DPLSP_DestroyDPLobbySP( *ppvObj );
|
||||
DPLSP_DestroyIUnknown( *ppvObj );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return DPERR_NOMEMORY;
|
||||
}
|
||||
|
||||
static BOOL DPLSP_CreateIUnknown( LPVOID lpSP )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
|
||||
|
||||
This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
|
||||
|
||||
if ( This->unk == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
InitializeCriticalSection( &This->unk->DPLSP_lock );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPLSP_DestroyIUnknown( LPVOID lpSP )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
|
||||
|
||||
DeleteCriticalSection( &This->unk->DPLSP_lock );
|
||||
HeapFree( GetProcessHeap(), 0, This->unk );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPLSP_CreateDPLobbySP( LPVOID lpSP, IDirectPlay2Impl* dp )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
|
||||
|
||||
This->sp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->sp) ) );
|
||||
|
||||
if ( This->sp == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
This->sp->dplay = dp;
|
||||
|
||||
/* Normally we should be keeping a reference, but since only the dplay
|
||||
* interface that created us can destroy us, we do not keep a reference
|
||||
* to it (ie we'd be stuck with always having one reference to the dplay
|
||||
* object, and hence us, around).
|
||||
* NOTE: The dp object does reference count us.
|
||||
*
|
||||
* FIXME: This is a kludge to get around a problem where a queryinterface
|
||||
* is used to get a new interface and then is closed. We will then
|
||||
* reference garbage. However, with this we will never deallocate
|
||||
* the interface we store. The correct fix is to require all
|
||||
* DP internal interfaces to use the This->dp2 interface which
|
||||
* should be changed to This->dp
|
||||
*/
|
||||
IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DPLSP_DestroyDPLobbySP( LPVOID lpSP )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)lpSP;
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, This->sp );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI DPLSP_QueryInterface
|
||||
( LPDPLOBBYSP iface,
|
||||
REFIID riid,
|
||||
LPVOID* ppvObj
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
|
||||
|
||||
*ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof( *This ) );
|
||||
|
||||
if( *ppvObj == NULL )
|
||||
{
|
||||
return DPERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
CopyMemory( *ppvObj, This, sizeof( *This ) );
|
||||
(*(IDPLobbySPImpl**)ppvObj)->ulInterfaceRef = 0;
|
||||
|
||||
if( IsEqualGUID( &IID_IDPLobbySP, riid ) )
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)*ppvObj;
|
||||
This->lpVtbl = &dpLobbySPVT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported interface */
|
||||
HeapFree( GetProcessHeap(), 0, *ppvObj );
|
||||
*ppvObj = NULL;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IDPLobbySP_AddRef( (LPDPLOBBYSP)*ppvObj );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static
|
||||
ULONG WINAPI DPLSP_AddRef
|
||||
( LPDPLOBBYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
|
||||
ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef );
|
||||
ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
|
||||
|
||||
TRACE( "ref count incremented to %lu:%lu for %p\n",
|
||||
ulInterfaceRefCount, ulObjRefCount, This );
|
||||
|
||||
return ulObjRefCount;
|
||||
}
|
||||
|
||||
static
|
||||
ULONG WINAPI DPLSP_Release
|
||||
( LPDPLOBBYSP iface )
|
||||
{
|
||||
ULONG ulInterfaceRefCount, ulObjRefCount;
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
|
||||
ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef );
|
||||
ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
|
||||
|
||||
TRACE( "ref count decremented to %lu:%lu for %p\n",
|
||||
ulInterfaceRefCount, ulObjRefCount, This );
|
||||
|
||||
/* Deallocate if this is the last reference to the object */
|
||||
if( ulObjRefCount == 0 )
|
||||
{
|
||||
DPLSP_DestroyDPLobbySP( This );
|
||||
DPLSP_DestroyIUnknown( This );
|
||||
}
|
||||
|
||||
if( ulInterfaceRefCount == 0 )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, This );
|
||||
}
|
||||
|
||||
return ulInterfaceRefCount;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_AddGroupToGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_ADDREMOTEGROUPTOGROUP argtg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, argtg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_AddPlayerToGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, arptg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_CreateGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_CREATEREMOTEGROUP crg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, crg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_CreateGroupInGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_CREATEREMOTEGROUPINGROUP crgig
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, crgig );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_DeleteGroupFromGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, drgfg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_DeletePlayerFromGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, drpfg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_DestroyGroup
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_DESTROYREMOTEGROUP drg
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, drg );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_EnumSessionsResponse
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_ENUMSESSIONSRESPONSE er
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, er );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_GetSPDataPointer
|
||||
( LPDPLOBBYSP iface,
|
||||
LPVOID* lplpData
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, lplpData );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_HandleMessage
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_HANDLEMESSAGE hm
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, hm );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_SendChatMessage
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_CHATMESSAGE cm
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, cm );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_SetGroupName
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_SETREMOTEGROUPNAME srgn
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, srgn );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_SetPlayerName
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_SETREMOTEPLAYERNAME srpn
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, srpn );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_SetSessionDesc
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_SETSESSIONDESC ssd
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, ssd );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_SetSPDataPointer
|
||||
( LPDPLOBBYSP iface,
|
||||
LPVOID lpData
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, lpData );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
static
|
||||
HRESULT WINAPI IDPLobbySPImpl_StartSession
|
||||
( LPDPLOBBYSP iface,
|
||||
LPSPDATA_STARTSESSIONCOMMAND ssc
|
||||
)
|
||||
{
|
||||
IDPLobbySPImpl *This = (IDPLobbySPImpl *)iface;
|
||||
FIXME( "(%p)->(%p):stub\n", This, ssc );
|
||||
return DP_OK;
|
||||
}
|
||||
|
||||
|
||||
static const IDPLobbySPVtbl dpLobbySPVT =
|
||||
{
|
||||
|
||||
DPLSP_QueryInterface,
|
||||
DPLSP_AddRef,
|
||||
DPLSP_Release,
|
||||
|
||||
IDPLobbySPImpl_AddGroupToGroup,
|
||||
IDPLobbySPImpl_AddPlayerToGroup,
|
||||
IDPLobbySPImpl_CreateGroup,
|
||||
IDPLobbySPImpl_CreateGroupInGroup,
|
||||
IDPLobbySPImpl_DeleteGroupFromGroup,
|
||||
IDPLobbySPImpl_DeletePlayerFromGroup,
|
||||
IDPLobbySPImpl_DestroyGroup,
|
||||
IDPLobbySPImpl_EnumSessionsResponse,
|
||||
IDPLobbySPImpl_GetSPDataPointer,
|
||||
IDPLobbySPImpl_HandleMessage,
|
||||
IDPLobbySPImpl_SendChatMessage,
|
||||
IDPLobbySPImpl_SetGroupName,
|
||||
IDPLobbySPImpl_SetPlayerName,
|
||||
IDPLobbySPImpl_SetSessionDesc,
|
||||
IDPLobbySPImpl_SetSPDataPointer,
|
||||
IDPLobbySPImpl_StartSession
|
||||
|
||||
};
|
520
reactos/lib/dplayx/lobbysp.h
Normal file
520
reactos/lib/dplayx/lobbysp.h
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* Copyright 2001 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_LOBBY_SP_H
|
||||
#define __WINE_LOBBY_SP_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "dplobby.h"
|
||||
|
||||
/* GUID for IDPLobbySP {5A4E5A20-2CED-11d0-A889-00A0C905433C} */
|
||||
DEFINE_GUID(IID_IDPLobbySP, 0x5a4e5a20, 0x2ced, 0x11d0, 0xa8, 0x89, 0x0, 0xa0, 0xc9, 0x5, 0x43, 0x3c);
|
||||
typedef struct IDPLobbySP *LPDPLOBBYSP;
|
||||
|
||||
/* For SP. Top 16 bits is dplay, bottom 16 is SP */
|
||||
#define DPLSP_MAJORVERSION 0x00050000
|
||||
|
||||
typedef struct SPDATA_ADDGROUPTOGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwParentID;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_ADDGROUPTOGROUP, *LPSPDATA_ADDGROUPTOGROUP;
|
||||
|
||||
typedef struct SPDATA_ADDPLAYERTOGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwPlayerID;
|
||||
} SPDATA_ADDPLAYERTOGROUP, *LPSPDATA_ADDPLAYERTOGROUP;
|
||||
|
||||
typedef struct SPDATA_ADDREMOTEGROUPTOGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwAnchorID;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwParentID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwGroupFlags;
|
||||
} SPDATA_ADDREMOTEGROUPTOGROUP, *LPSPDATA_ADDREMOTEGROUPTOGROUP;
|
||||
|
||||
typedef struct SPDATA_ADDREMOTEPLAYERTOGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwPlayerID;
|
||||
DWORD dwPlayerFlags;
|
||||
LPDPNAME lpName;
|
||||
} SPDATA_ADDREMOTEPLAYERTOGROUP, *LPSPDATA_ADDREMOTEPLAYERTOGROUP;
|
||||
|
||||
typedef struct SPDATA_BUILDPARENTALHEIRARCHY
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwMessage;
|
||||
DWORD dwParentID;
|
||||
} SPDATA_BUILDPARENTALHEIRARCHY, *LPSPDATA_BUILDPARENTALHEIRARCHY;
|
||||
|
||||
typedef struct SPDATA_CLOSE
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
} SPDATA_CLOSE, *LPSPDATA_CLOSE;
|
||||
|
||||
typedef struct SPDATA_CREATEGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_CREATEGROUP, *LPSPDATA_CREATEGROUP;
|
||||
|
||||
typedef struct SPDATA_CREATEGROUPINGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwParentID;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_CREATEGROUPINGROUP, *LPSPDATA_CREATEGROUPINGROUP;
|
||||
|
||||
typedef struct SPDATA_CREATEREMOTEGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_CREATEREMOTEGROUP, *LPSPDATA_CREATEREMOTEGROUP;
|
||||
|
||||
typedef struct SPDATA_CREATEREMOTEGROUPINGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwParentID;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_CREATEREMOTEGROUPINGROUP, *LPSPDATA_CREATEREMOTEGROUPINGROUP;
|
||||
|
||||
typedef struct SPDATA_CREATEPLAYER
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
LPDPNAME lpName;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_CREATEPLAYER, *LPSPDATA_CREATEPLAYER;
|
||||
|
||||
typedef struct SPDATA_DELETEGROUPFROMGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwParentID;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_DELETEGROUPFROMGROUP, *LPSPDATA_DELETEGROUPFROMGROUP;
|
||||
|
||||
typedef struct SPDATA_DELETEPLAYERFROMGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwPlayerID;
|
||||
} SPDATA_DELETEPLAYERFROMGROUP, *LPSPDATA_DELETEPLAYERFROMGROUP;
|
||||
|
||||
typedef struct SPDATA_DELETEREMOTEGROUPFROMGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwParentID;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_DELETEREMOTEGROUPFROMGROUP, *LPSPDATA_DELETEREMOTEGROUPFROMGROUP;
|
||||
|
||||
typedef struct SPDATA_DELETEREMOTEPLAYERFROMGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwPlayerID;
|
||||
} SPDATA_DELETEREMOTEPLAYERFROMGROUP, *LPSPDATA_DELETEREMOTEPLAYERFROMGROUP;
|
||||
|
||||
typedef struct SPDATA_DESTROYGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_DESTROYGROUP, *LPSPDATA_DESTROYGROUP;
|
||||
|
||||
typedef struct SPDATA_DESTROYREMOTEGROUP
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_DESTROYREMOTEGROUP, *LPSPDATA_DESTROYREMOTEGROUP;
|
||||
|
||||
typedef struct SPDATA_DESTROYPLAYER
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
} SPDATA_DESTROYPLAYER, *LPSPDATA_DESTROYPLAYER;
|
||||
|
||||
typedef struct SPDATA_ENUMSESSIONS
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
LPDPSESSIONDESC2 lpsd;
|
||||
DWORD dwTimeout;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_ENUMSESSIONS, *LPSPDATA_ENUMSESSIONS;
|
||||
|
||||
typedef struct SPDATA_ENUMSESSIONSRESPONSE
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPSESSIONDESC2 lpsd;
|
||||
} SPDATA_ENUMSESSIONSRESPONSE, *LPSPDATA_ENUMSESSIONSRESPONSE;
|
||||
|
||||
typedef struct SPDATA_GETCAPS
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwFlags;
|
||||
LPDPCAPS lpcaps;
|
||||
} SPDATA_GETCAPS, *LPSPDATA_GETCAPS;
|
||||
|
||||
typedef struct SPDATA_GETGROUPCONNECTIONSETTINGS
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDWORD lpdwBufferSize;
|
||||
LPVOID lpBuffer;
|
||||
} SPDATA_GETGROUPCONNECTIONSETTINGS, *LPSPDATA_GETGROUPCONNECTIONSETTINGS;
|
||||
|
||||
typedef struct SPDATA_GETGROUPDATA
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDWORD lpdwDataSize;
|
||||
LPVOID lpData;
|
||||
} SPDATA_GETGROUPDATA, *LPSPDATA_GETGROUPDATA;
|
||||
|
||||
typedef struct SPDATA_GETPLAYERCAPS
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwFlags;
|
||||
DWORD dwPlayerID;
|
||||
LPDPCAPS lpcaps;
|
||||
} SPDATA_GETPLAYERCAPS, *LPSPDATA_GETPLAYERCAPS;
|
||||
|
||||
typedef struct SPDATA_GETPLAYERDATA
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
LPDWORD lpdwDataSize;
|
||||
LPVOID lpData;
|
||||
} SPDATA_GETPLAYERDATA, *LPSPDATA_GETPLAYERDATA;
|
||||
|
||||
typedef struct SPDATA_HANDLEMESSAGE
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFromID;
|
||||
DWORD dwToID;
|
||||
LPVOID lpBuffer;
|
||||
DWORD dwBufSize;
|
||||
} SPDATA_HANDLEMESSAGE, *LPSPDATA_HANDLEMESSAGE;
|
||||
|
||||
typedef struct SPDATA_OPEN
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
LPDPSESSIONDESC2 lpsd;
|
||||
DWORD dwFlags;
|
||||
LPCDPCREDENTIALS lpCredentials;
|
||||
} SPDATA_OPEN, *LPSPDATA_OPEN;
|
||||
|
||||
typedef struct SPDATA_SEND
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwFromID;
|
||||
DWORD dwToID;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpBuffer;
|
||||
DWORD dwBufSize;
|
||||
} SPDATA_SEND, *LPSPDATA_SEND;
|
||||
|
||||
typedef struct SPDATA_CHATMESSAGE
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwFromID;
|
||||
DWORD dwToID;
|
||||
DWORD dwFlags;
|
||||
LPDPCHAT lpChat;
|
||||
} SPDATA_CHATMESSAGE, *LPSPDATA_CHATMESSAGE;
|
||||
|
||||
typedef struct SPDATA_SETGROUPCONNECTIONSETTINGS
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDPLCONNECTION lpConn;
|
||||
} SPDATA_SETGROUPCONNECTIONSETTINGS, *LPSPDATA_SETGROUPCONNECTIONSETTINGS;
|
||||
|
||||
typedef struct SPDATA_SETGROUPDATA
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETGROUPDATA, *LPSPDATA_SETGROUPDATA;
|
||||
|
||||
typedef struct SPDATA_SETGROUPNAME
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETGROUPNAME, *LPSPDATA_SETGROUPNAME;
|
||||
|
||||
typedef struct SPDATA_SETREMOTEGROUPNAME
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwGroupID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETREMOTEGROUPNAME, *LPSPDATA_SETREMOTEGROUPNAME;
|
||||
|
||||
typedef struct SPDATA_SETPLAYERDATA
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
LPVOID lpData;
|
||||
DWORD dwDataSize;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETPLAYERDATA, *LPSPDATA_SETPLAYERDATA;
|
||||
|
||||
typedef struct SPDATA_SETPLAYERNAME
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETPLAYERNAME, *LPSPDATA_SETPLAYERNAME;
|
||||
|
||||
typedef struct SPDATA_SETREMOTEPLAYERNAME
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwPlayerID;
|
||||
LPDPNAME lpName;
|
||||
DWORD dwFlags;
|
||||
} SPDATA_SETREMOTEPLAYERNAME, *LPSPDATA_SETREMOTEPLAYERNAME;
|
||||
|
||||
typedef struct SPDATA_SETSESSIONDESC
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPSESSIONDESC2 lpsd;
|
||||
} SPDATA_SETSESSIONDESC, *LPSPDATA_SETSESSIONDESC;
|
||||
|
||||
typedef struct SPDATA_SHUTDOWN
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
} SPDATA_SHUTDOWN, *LPSPDATA_SHUTDOWN;
|
||||
|
||||
typedef struct SPDATA_STARTSESSION
|
||||
{
|
||||
DWORD dwSize;
|
||||
LPDPLOBBYSP lpISP;
|
||||
DWORD dwFlags;
|
||||
DWORD dwGroupID;
|
||||
} SPDATA_STARTSESSION, *LPSPDATA_STARTSESSION;
|
||||
|
||||
typedef struct SPDATA_STARTSESSIONCOMMAND
|
||||
{
|
||||
DWORD dwFlags;
|
||||
DWORD dwGroupID;
|
||||
DWORD dwHostID;
|
||||
LPDPLCONNECTION lpConn;
|
||||
} SPDATA_STARTSESSIONCOMMAND, *LPSPDATA_STARTSESSIONCOMMAND;
|
||||
|
||||
/* Prototypes for callbacks returned by DPLSPInit */
|
||||
typedef HRESULT (WINAPI *LPSP_ADDGROUPTOGROUP)(LPSPDATA_ADDGROUPTOGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_ADDPLAYERTOGROUP)(LPSPDATA_ADDPLAYERTOGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_BUILDPARENTALHEIRARCHY)(LPSPDATA_BUILDPARENTALHEIRARCHY);
|
||||
typedef HRESULT (WINAPI *LPSP_CLOSE)(LPSPDATA_CLOSE);
|
||||
typedef HRESULT (WINAPI *LPSP_CREATEGROUP)(LPSPDATA_CREATEGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_CREATEGROUPINGROUP)(LPSPDATA_CREATEGROUPINGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_CREATEPLAYER)(LPSPDATA_CREATEPLAYER);
|
||||
typedef HRESULT (WINAPI *LPSP_DELETEGROUPFROMGROUP)(LPSPDATA_DELETEGROUPFROMGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_DELETEPLAYERFROMGROUP)(LPSPDATA_DELETEPLAYERFROMGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_DESTROYGROUP)(LPSPDATA_DESTROYGROUP);
|
||||
typedef HRESULT (WINAPI *LPSP_DESTROYPLAYER)(LPSPDATA_DESTROYPLAYER);
|
||||
typedef HRESULT (WINAPI *LPSP_ENUMSESSIONS)(LPSPDATA_ENUMSESSIONS);
|
||||
typedef HRESULT (WINAPI *LPSP_GETCAPS)(LPSPDATA_GETCAPS);
|
||||
typedef HRESULT (WINAPI *LPSP_GETGROUPCONNECTIONSETTINGS)(LPSPDATA_GETGROUPCONNECTIONSETTINGS);
|
||||
typedef HRESULT (WINAPI *LPSP_GETGROUPDATA)(LPSPDATA_GETGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPSP_GETPLAYERCAPS)(LPSPDATA_GETPLAYERCAPS);
|
||||
typedef HRESULT (WINAPI *LPSP_GETPLAYERDATA)(LPSPDATA_GETPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPSP_HANDLEMESSAGE)(LPSPDATA_HANDLEMESSAGE);
|
||||
typedef HRESULT (WINAPI *LPSP_OPEN)(LPSPDATA_OPEN);
|
||||
typedef HRESULT (WINAPI *LPSP_SEND)(LPSPDATA_SEND);
|
||||
typedef HRESULT (WINAPI *LPSP_SENDCHATMESSAGE)(LPSPDATA_CHATMESSAGE);
|
||||
typedef HRESULT (WINAPI *LPSP_SETGROUPCONNECTIONSETTINGS)(LPSPDATA_SETGROUPCONNECTIONSETTINGS);
|
||||
typedef HRESULT (WINAPI *LPSP_SETGROUPDATA)(LPSPDATA_SETGROUPDATA);
|
||||
typedef HRESULT (WINAPI *LPSP_SETGROUPNAME)(LPSPDATA_SETGROUPNAME);
|
||||
typedef HRESULT (WINAPI *LPSP_SETPLAYERDATA)(LPSPDATA_SETPLAYERDATA);
|
||||
typedef HRESULT (WINAPI *LPSP_SETPLAYERNAME)(LPSPDATA_SETPLAYERNAME);
|
||||
typedef HRESULT (WINAPI *LPSP_SHUTDOWN)(LPSPDATA_SHUTDOWN);
|
||||
typedef HRESULT (WINAPI *LPSP_STARTSESSION)(LPSPDATA_STARTSESSION);
|
||||
|
||||
/* Callback table for dplay to call into service provider */
|
||||
typedef struct SP_CALLBACKS
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
LPSP_ADDGROUPTOGROUP AddGroupToGroup;
|
||||
LPSP_ADDPLAYERTOGROUP AddPlayerToGroup;
|
||||
LPSP_BUILDPARENTALHEIRARCHY BuildParentalHeirarchy;
|
||||
LPSP_CLOSE Close;
|
||||
LPSP_CREATEGROUP CreateGroup;
|
||||
LPSP_CREATEGROUPINGROUP CreateGroupInGroup;
|
||||
LPSP_CREATEPLAYER CreatePlayer;
|
||||
LPSP_DELETEGROUPFROMGROUP DeleteGroupFromGroup;
|
||||
LPSP_DELETEPLAYERFROMGROUP DeletePlayerFromGroup;
|
||||
LPSP_DESTROYGROUP DestroyGroup;
|
||||
LPSP_DESTROYPLAYER DestroyPlayer;
|
||||
LPSP_ENUMSESSIONS EnumSessions;
|
||||
LPSP_GETCAPS GetCaps;
|
||||
LPSP_GETGROUPCONNECTIONSETTINGS GetGroupConnectionSettings;
|
||||
LPSP_GETGROUPDATA GetGroupData;
|
||||
LPSP_GETPLAYERCAPS GetPlayerCaps;
|
||||
LPSP_GETPLAYERDATA GetPlayerData;
|
||||
LPSP_OPEN Open;
|
||||
LPSP_SEND Send;
|
||||
LPSP_SENDCHATMESSAGE SendChatMessage;
|
||||
LPSP_SETGROUPCONNECTIONSETTINGS SetGroupConnectionSettings;
|
||||
LPSP_SETGROUPDATA SetGroupData;
|
||||
LPSP_SETGROUPNAME SetGroupName;
|
||||
LPSP_SETPLAYERDATA SetPlayerData;
|
||||
LPSP_SETPLAYERNAME SetPlayerName;
|
||||
LPSP_SHUTDOWN Shutdown;
|
||||
LPSP_STARTSESSION StartSession;
|
||||
} SP_CALLBACKS, *LPSP_CALLBACKS;
|
||||
|
||||
typedef struct SPDATA_INIT
|
||||
{
|
||||
LPSP_CALLBACKS lpCB;
|
||||
DWORD dwSPVersion;
|
||||
LPDPLOBBYSP lpISP;
|
||||
LPDPADDRESS lpAddress;
|
||||
} SPDATA_INIT, *LPSPDATA_INIT;
|
||||
|
||||
typedef HRESULT (WINAPI *LPSP_INIT)(LPSPDATA_INIT);
|
||||
HRESULT WINAPI DPLSPInit(LPSPDATA_INIT);
|
||||
|
||||
/* Define the COM interface */
|
||||
#define INTERFACE IDPLobbySP
|
||||
DECLARE_INTERFACE_(IDPLobbySP,IUnknown)
|
||||
{
|
||||
/*** IUnknown methods ***/
|
||||
STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
|
||||
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release)(THIS) PURE;
|
||||
/*** IDPLobbySP methods ***/
|
||||
STDMETHOD(AddGroupToGroup)(THIS_ LPSPDATA_ADDREMOTEGROUPTOGROUP argtg ) PURE;
|
||||
STDMETHOD(AddPlayerToGroup)(THIS_ LPSPDATA_ADDREMOTEPLAYERTOGROUP arptg ) PURE;
|
||||
STDMETHOD(CreateGroup)(THIS_ LPSPDATA_CREATEREMOTEGROUP crg ) PURE;
|
||||
STDMETHOD(CreateGroupInGroup)(THIS_ LPSPDATA_CREATEREMOTEGROUPINGROUP crgig ) PURE;
|
||||
STDMETHOD(DeleteGroupFromGroup)(THIS_ LPSPDATA_DELETEREMOTEGROUPFROMGROUP drgfg ) PURE;
|
||||
STDMETHOD(DeletePlayerFromGroup)(THIS_ LPSPDATA_DELETEREMOTEPLAYERFROMGROUP drpfg ) PURE;
|
||||
STDMETHOD(DestroyGroup)(THIS_ LPSPDATA_DESTROYREMOTEGROUP drg ) PURE;
|
||||
STDMETHOD(EnumSessionsResponse)(THIS_ LPSPDATA_ENUMSESSIONSRESPONSE er ) PURE;
|
||||
STDMETHOD(GetSPDataPointer)(THIS_ LPVOID * lplpData ) PURE;
|
||||
STDMETHOD(HandleMessage)(THIS_ LPSPDATA_HANDLEMESSAGE hm ) PURE;
|
||||
STDMETHOD(SendChatMessage)(THIS_ LPSPDATA_CHATMESSAGE cm ) PURE;
|
||||
STDMETHOD(SetGroupName)(THIS_ LPSPDATA_SETREMOTEGROUPNAME srgn ) PURE;
|
||||
STDMETHOD(SetPlayerName)(THIS_ LPSPDATA_SETREMOTEPLAYERNAME srpn ) PURE;
|
||||
STDMETHOD(SetSessionDesc)(THIS_ LPSPDATA_SETSESSIONDESC ssd ) PURE;
|
||||
STDMETHOD(SetSPDataPointer)(THIS_ LPVOID lpData ) PURE;
|
||||
STDMETHOD(StartSession)(THIS_ LPSPDATA_STARTSESSIONCOMMAND ssc ) PURE;
|
||||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#if !defined (__cplusplus) || defined(CINTERFACE)
|
||||
/*** IUnknown methods ***/
|
||||
#define IDPLobbySP_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IDPLobbySP_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IDPLobbySP_Release(p) (p)->lpVtbl->Release(p)
|
||||
|
||||
/*** IDPLobbySP methods ***/
|
||||
#define IDPLobbySP_AddGroupToGroup(p,a) (p)->lpVtbl->AddGroupToGroup(p,a)
|
||||
#define IDPLobbySP_AddPlayerToGroup(p,a) (p)->lpVtbl->AddPlayerToGroup(p,a)
|
||||
#define IDPLobbySP_CreateGroup(p,a) (p)->lpVtbl->CreateGroup(p,a)
|
||||
#define IDPLobbySP_CreateGroupInGroup(p,a) (p)->lpVtbl->CreateGroupInGroup(p,a)
|
||||
#define IDPLobbySP_DeleteGroupFromGroup(p,a) (p)->lpVtbl->DeleteGroupFromGroup(p,a)
|
||||
#define IDPLobbySP_DeletePlayerFromGroup(p,a) (p)->lpVtbl->DeletePlayerFromGroup(p,a)
|
||||
#define IDPLobbySP_DestroyGroup(p,a) (p)->lpVtbl->DestroyGroup(p,a)
|
||||
#define IDPLobbySP_EnumSessionsResponse(p,a) (p)->lpVtbl->EnumSessionsResponse(p,a)
|
||||
#define IDPLobbySP_GetSPDataPointer(p,a) (p)->lpVtbl->GetSPDataPointer(p,a)
|
||||
#define IDPLobbySP_HandleMessage(p,a) (p)->lpVtbl->HandleMessage(p,a)
|
||||
#define IDPLobbySP_SetGroupName(p,a) (p)->lpVtbl->SetGroupName(p,a)
|
||||
#define IDPLobbySP_SetPlayerName(p,a) (p)->lpVtbl->SetPlayerName(p,a)
|
||||
#define IDPLobbySP_SetSessionDesc(p,a) (p)->lpVtbl->SetSessionDesc(p,a)
|
||||
#define IDPLobbySP_StartSession(p,a) (p)->lpVtbl->StartSession(p,a)
|
||||
#define IDPLobbySP_SetSPDataPointer(p,a) (p)->lpVtbl->SetSPDataPointer(p,a)
|
||||
#endif
|
||||
|
||||
/* This variable is exported from the DLL at ordinal 6 to be accessed by the
|
||||
* SP directly. This is the same variable that the DP SP will use.
|
||||
*/
|
||||
extern DWORD gdwDPlaySPRefCount;
|
||||
|
||||
#endif
|
425
reactos/lib/dplayx/name_server.c
Normal file
425
reactos/lib/dplayx/name_server.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/* DPLAYX.DLL name server implementation
|
||||
*
|
||||
* Copyright 2000-2001 - Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE: Methods with the NS_ prefix are name server methods */
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/debug.h"
|
||||
#include "mmsystem.h"
|
||||
|
||||
#include "dplayx_global.h"
|
||||
#include "name_server.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_messages.h"
|
||||
#include "dplayx_queue.h"
|
||||
|
||||
/* FIXME: Need to create a crit section, store and use it */
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplay);
|
||||
|
||||
/* NS specific structures */
|
||||
struct NSCacheData
|
||||
{
|
||||
DPQ_ENTRY(NSCacheData) next;
|
||||
|
||||
DWORD dwTime; /* Time at which data was last known valid */
|
||||
LPDPSESSIONDESC2 data;
|
||||
|
||||
LPVOID lpNSAddrHdr;
|
||||
|
||||
};
|
||||
typedef struct NSCacheData NSCacheData, *lpNSCacheData;
|
||||
|
||||
struct NSCache
|
||||
{
|
||||
lpNSCacheData present; /* keep track of what is to be looked at when walking */
|
||||
|
||||
DPQ_HEAD(NSCacheData) first;
|
||||
|
||||
BOOL bNsIsLocal;
|
||||
LPVOID lpLocalAddrHdr; /* FIXME: Not yet used */
|
||||
LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */
|
||||
};
|
||||
typedef struct NSCache NSCache, *lpNSCache;
|
||||
|
||||
/* Function prototypes */
|
||||
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
|
||||
|
||||
/* Name Server functions
|
||||
* ---------------------
|
||||
*/
|
||||
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
|
||||
{
|
||||
#if 0
|
||||
/* FIXME: Remove this method? */
|
||||
DPLAYX_SetLocalSession( lpsd );
|
||||
#endif
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
lpCache->bNsIsLocal = TRUE;
|
||||
}
|
||||
|
||||
void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
lpCache->bNsIsLocal = FALSE;
|
||||
}
|
||||
|
||||
static DPQ_DECL_COMPARECB( cbUglyPig, GUID )
|
||||
{
|
||||
return IsEqualGUID( elem1, elem2 );
|
||||
}
|
||||
|
||||
/* Store the given NS remote address for future reference */
|
||||
/* FIXME: LPDPMSG_ENUMSESSIONSREPLY should be const */
|
||||
void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr,
|
||||
DWORD dwHdrSize,
|
||||
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
|
||||
LPVOID lpNSInfo )
|
||||
{
|
||||
DWORD len;
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
lpNSCacheData lpCacheNode;
|
||||
|
||||
TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpMsg, lpNSInfo );
|
||||
|
||||
/* See if we can find this session. If we can, remove it as it's a dup */
|
||||
DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
|
||||
lpMsg->sd.guidInstance, lpCacheNode );
|
||||
|
||||
if( lpCacheNode != NULL )
|
||||
{
|
||||
TRACE( "Duplicate session entry for %s removed - updated version kept\n",
|
||||
debugstr_guid( &lpCacheNode->data->guidInstance ) );
|
||||
cbDeleteNSNodeFromHeap( lpCacheNode );
|
||||
}
|
||||
|
||||
/* Add this to the list */
|
||||
lpCacheNode = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpCacheNode ) );
|
||||
|
||||
if( lpCacheNode == NULL )
|
||||
{
|
||||
ERR( "no memory for NS node\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
dwHdrSize );
|
||||
CopyMemory( lpCacheNode->lpNSAddrHdr, lpcNSAddrHdr, dwHdrSize );
|
||||
|
||||
lpCacheNode->data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpCacheNode->data) ) );
|
||||
|
||||
if( lpCacheNode->data == NULL )
|
||||
{
|
||||
ERR( "no memory for SESSIONDESC2\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
|
||||
len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL );
|
||||
if ((lpCacheNode->data->lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0, len )))
|
||||
{
|
||||
WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1,
|
||||
lpCacheNode->data->lpszSessionNameA, len, NULL, NULL );
|
||||
}
|
||||
|
||||
lpCacheNode->dwTime = timeGetTime();
|
||||
|
||||
DPQ_INSERT(lpCache->first, lpCacheNode, next );
|
||||
|
||||
lpCache->present = lpCacheNode;
|
||||
|
||||
/* Use this message as an opportunity to weed out any old sessions so
|
||||
* that we don't enum them again
|
||||
*/
|
||||
NS_PruneSessionCache( lpNSInfo );
|
||||
}
|
||||
|
||||
LPVOID NS_GetNSAddr( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
FIXME( ":quick stub\n" );
|
||||
|
||||
/* Ok. Cheat and don't search for the correct stuff just take the first.
|
||||
* FIXME: In the future how are we to know what is _THE_ enum we used?
|
||||
* This is going to have to go into dplay somehow. Perhaps it
|
||||
* comes back with app server id for the join command! Oh...that
|
||||
* must be it. That would make this method obsolete once that's
|
||||
* in place.
|
||||
*/
|
||||
#if 1
|
||||
return lpCache->first.lpQHFirst->lpNSAddrHdr;
|
||||
#else
|
||||
/* FIXME: Should convert over to this */
|
||||
return lpCache->bNsIsLocal ? lpCache->lpLocalAddrHdr
|
||||
: lpCache->lpRemoteAddrHdr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get the magic number associated with the Name Server */
|
||||
DWORD NS_GetNsMagic( LPVOID lpNSInfo )
|
||||
{
|
||||
LPDWORD lpHdrInfo = (LPDWORD)NS_GetNSAddr( lpNSInfo );
|
||||
|
||||
return lpHdrInfo[1];
|
||||
}
|
||||
|
||||
/* Get the magic number associated with the non NS end */
|
||||
DWORD NS_GetOtherMagic( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
return ((LPDWORD)lpCache->lpLocalAddrHdr)[1];
|
||||
}
|
||||
|
||||
void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
lpCache->lpLocalAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize );
|
||||
|
||||
CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize );
|
||||
}
|
||||
|
||||
/* This function is responsible for sending a request for all other known
|
||||
nameservers to send us what sessions they have registered locally
|
||||
*/
|
||||
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
|
||||
DWORD dwFlags,
|
||||
LPSPINITDATA lpSpData )
|
||||
|
||||
{
|
||||
DPSP_ENUMSESSIONSDATA data;
|
||||
LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
|
||||
|
||||
TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
|
||||
|
||||
/* Get the SP to deal with sending the EnumSessions request */
|
||||
FIXME( ": not all data fields are correct\n" );
|
||||
|
||||
data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ); /*FIXME!*/
|
||||
data.lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
data.dwMessageSize );
|
||||
data.lpISP = lpSpData->lpISP;
|
||||
data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) ? TRUE : FALSE;
|
||||
|
||||
|
||||
lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
|
||||
|
||||
/* Setup EnumSession request message */
|
||||
lpMsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
lpMsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREQUEST;
|
||||
lpMsg->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
lpMsg->dwPasswordSize = 0; /* FIXME: If enumerating passwords..? */
|
||||
lpMsg->dwFlags = dwFlags;
|
||||
|
||||
CopyMemory( &lpMsg->guidApplication, lpcGuid, sizeof( *lpcGuid ) );
|
||||
|
||||
return (lpSpData->lpCB->EnumSessions)( &data );
|
||||
}
|
||||
|
||||
/* Delete a name server node which has been allocated on the heap */
|
||||
DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
|
||||
{
|
||||
/* NOTE: This proc doesn't deal with the walking pointer */
|
||||
|
||||
/* FIXME: Memory leak on data (contained ptrs) */
|
||||
HeapFree( GetProcessHeap(), 0, elem->data );
|
||||
HeapFree( GetProcessHeap(), 0, elem->lpNSAddrHdr );
|
||||
HeapFree( GetProcessHeap(), 0, elem );
|
||||
}
|
||||
|
||||
/* Render all data in a session cache invalid */
|
||||
void NS_InvalidateSessionCache( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
if( lpCache == NULL )
|
||||
{
|
||||
ERR( ": invalidate nonexistent cache\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
|
||||
|
||||
/* NULL out the walking pointer */
|
||||
lpCache->present = NULL;
|
||||
|
||||
lpCache->bNsIsLocal = FALSE;
|
||||
|
||||
}
|
||||
|
||||
/* Create and initialize a session cache */
|
||||
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpCache ) );
|
||||
|
||||
*lplpNSInfo = lpCache;
|
||||
|
||||
if( lpCache == NULL )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPQ_INIT(lpCache->first);
|
||||
lpCache->present = NULL;
|
||||
|
||||
lpCache->bNsIsLocal = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Delete a session cache */
|
||||
void NS_DeleteSessionCache( LPVOID lpNSInfo )
|
||||
{
|
||||
NS_InvalidateSessionCache( (lpNSCache)lpNSInfo );
|
||||
}
|
||||
|
||||
/* Reinitialize the present pointer for this cache */
|
||||
void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
|
||||
{
|
||||
((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
|
||||
}
|
||||
|
||||
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
|
||||
{
|
||||
LPDPSESSIONDESC2 lpSessionDesc;
|
||||
lpNSCache lpCache = (lpNSCache)lpNSInfo;
|
||||
|
||||
/* FIXME: The pointers could disappear when walking if a prune happens */
|
||||
|
||||
/* Test for end of the list */
|
||||
if( lpCache->present == NULL )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lpSessionDesc = lpCache->present->data;
|
||||
|
||||
/* Advance tracking pointer */
|
||||
lpCache->present = lpCache->present->next.lpQNext;
|
||||
|
||||
return lpSessionDesc;
|
||||
}
|
||||
|
||||
/* This method should check to see if there are any sessions which are
|
||||
* older than the criteria. If so, just delete that information.
|
||||
*/
|
||||
/* FIXME: This needs to be called by some periodic timer */
|
||||
void NS_PruneSessionCache( LPVOID lpNSInfo )
|
||||
{
|
||||
lpNSCache lpCache = lpNSInfo;
|
||||
|
||||
const DWORD dwPresentTime = timeGetTime();
|
||||
const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */
|
||||
|
||||
/* This silly little algorithm is based on the fact we keep entries in
|
||||
* the queue in a time based order. It also assumes that it is not possible
|
||||
* to wrap around over yourself (which is not unreasonable).
|
||||
* The if statements verify if the first entry in the queue is less
|
||||
* than dwPrunePeriod old depending on the "clock" roll over.
|
||||
*/
|
||||
for( ;; )
|
||||
{
|
||||
lpNSCacheData lpFirstData;
|
||||
|
||||
if( DPQ_IS_EMPTY(lpCache->first) )
|
||||
{
|
||||
/* Nothing to prune */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Deal with time in a wrap around safe manner - unsigned arithmetic.
|
||||
* Check the difference in time */
|
||||
if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod )
|
||||
{
|
||||
/* First entry has not expired yet; don't prune */
|
||||
break;
|
||||
}
|
||||
|
||||
lpFirstData = DPQ_FIRST(lpCache->first);
|
||||
DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next );
|
||||
cbDeleteNSNodeFromHeap( lpFirstData );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* NAME SERVER Message stuff */
|
||||
void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
|
||||
LPVOID* lplpReplyData,
|
||||
LPDWORD lpdwReplySize,
|
||||
IDirectPlay2Impl* lpDP )
|
||||
{
|
||||
LPDPMSG_ENUMSESSIONSREPLY rmsg;
|
||||
DWORD dwVariableSize;
|
||||
DWORD dwVariableLen;
|
||||
/* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */
|
||||
BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
|
||||
|
||||
FIXME( ": few fixed + need to check request for response\n" );
|
||||
|
||||
if (bAnsi)
|
||||
{
|
||||
dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
|
||||
lpDP->dp2->lpSessionDesc->lpszSessionNameA,
|
||||
-1, NULL, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->lpszSessionName ) + 1;
|
||||
}
|
||||
|
||||
dwVariableSize = dwVariableLen * sizeof( WCHAR );
|
||||
|
||||
*lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize +
|
||||
sizeof( *rmsg ) + dwVariableSize;
|
||||
*lplpReplyData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
*lpdwReplySize );
|
||||
|
||||
rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData +
|
||||
lpDP->dp2->spData.dwSPHeaderSize);
|
||||
|
||||
rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
|
||||
rmsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREPLY;
|
||||
rmsg->envelope.wVersion = DPMSGVER_DP6;
|
||||
|
||||
CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
|
||||
sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
|
||||
rmsg->dwUnknown = 0x0000005c;
|
||||
if( bAnsi )
|
||||
{
|
||||
MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->lpszSessionNameA, -1,
|
||||
(LPWSTR)(rmsg+1), dwVariableLen );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->lpszSessionName );
|
||||
}
|
||||
}
|
61
reactos/lib/dplayx/name_server.h
Normal file
61
reactos/lib/dplayx/name_server.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2000 Peter Hunnisett
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __WINE_DPLAYX_NAMESERVER
|
||||
#define __WINE_DPLAYX_NAMESERVER
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "dplay.h"
|
||||
#include "dplaysp.h"
|
||||
#include "dplayx_messages.h"
|
||||
#include "dplay_global.h"
|
||||
|
||||
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
|
||||
void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo );
|
||||
void NS_AddRemoteComputerAsNameServer( LPCVOID lpNSAddrHdr,
|
||||
DWORD dwHdrSize,
|
||||
LPDPMSG_ENUMSESSIONSREPLY lpMsg,
|
||||
LPVOID lpNSInfo );
|
||||
LPVOID NS_GetNSAddr( LPVOID lpNSInfo );
|
||||
DWORD NS_GetNsMagic( LPVOID lpNSInfo );
|
||||
DWORD NS_GetOtherMagic( LPVOID lpNSInfo );
|
||||
void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize );
|
||||
|
||||
void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
|
||||
LPVOID* lplpReplyData,
|
||||
LPDWORD lpdwReplySize,
|
||||
IDirectPlay2Impl* lpDP );
|
||||
|
||||
HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
|
||||
DWORD dwFlags,
|
||||
LPSPINITDATA lpSpData );
|
||||
|
||||
|
||||
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo );
|
||||
void NS_DeleteSessionCache( LPVOID lpNSInfo );
|
||||
void NS_InvalidateSessionCache( LPVOID lpNSInfo );
|
||||
|
||||
|
||||
void NS_ResetSessionEnumeration( LPVOID lpNSInfo );
|
||||
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo );
|
||||
void NS_PruneSessionCache( LPVOID lpNSInfo );
|
||||
|
||||
#endif /* __WINE_DPLAYX_NAMESERVER */
|
556
reactos/lib/dplayx/regsvr.c
Normal file
556
reactos/lib/dplayx/regsvr.c
Normal file
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
* self-registerable dll functions for dplayx.dll
|
||||
*
|
||||
* Copyright (C) 2003 John K. Hohm
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winerror.h"
|
||||
|
||||
#include "dplay.h"
|
||||
#include "dplobby.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dplayx);
|
||||
|
||||
/*
|
||||
* Near the bottom of this file are the exported DllRegisterServer and
|
||||
* DllUnregisterServer, which make all this worthwhile.
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* interface for self-registering
|
||||
*/
|
||||
struct regsvr_interface
|
||||
{
|
||||
IID const *iid; /* NULL for end of list */
|
||||
LPCSTR name; /* can be NULL to omit */
|
||||
IID const *base_iid; /* can be NULL to omit */
|
||||
int num_methods; /* can be <0 to omit */
|
||||
CLSID const *ps_clsid; /* can be NULL to omit */
|
||||
CLSID const *ps_clsid32; /* can be NULL to omit */
|
||||
};
|
||||
|
||||
static HRESULT register_interfaces(struct regsvr_interface const *list);
|
||||
static HRESULT unregister_interfaces(struct regsvr_interface const *list);
|
||||
|
||||
struct regsvr_coclass
|
||||
{
|
||||
CLSID const *clsid; /* NULL for end of list */
|
||||
LPCSTR name; /* can be NULL to omit */
|
||||
LPCSTR ips; /* can be NULL to omit */
|
||||
LPCSTR ips32; /* can be NULL to omit */
|
||||
LPCSTR ips32_tmodel; /* can be NULL to omit */
|
||||
LPCSTR progid; /* can be NULL to omit */
|
||||
LPCSTR viprogid; /* can be NULL to omit */
|
||||
LPCSTR progid_extra; /* can be NULL to omit */
|
||||
};
|
||||
|
||||
static HRESULT register_coclasses(struct regsvr_coclass const *list);
|
||||
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
|
||||
|
||||
/***********************************************************************
|
||||
* static string constants
|
||||
*/
|
||||
static WCHAR const interface_keyname[10] = {
|
||||
'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
|
||||
static WCHAR const base_ifa_keyname[14] = {
|
||||
'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
|
||||
'e', 0 };
|
||||
static WCHAR const num_methods_keyname[11] = {
|
||||
'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
|
||||
static WCHAR const ps_clsid_keyname[15] = {
|
||||
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
|
||||
'i', 'd', 0 };
|
||||
static WCHAR const ps_clsid32_keyname[17] = {
|
||||
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
|
||||
'i', 'd', '3', '2', 0 };
|
||||
static WCHAR const clsid_keyname[6] = {
|
||||
'C', 'L', 'S', 'I', 'D', 0 };
|
||||
static WCHAR const curver_keyname[7] = {
|
||||
'C', 'u', 'r', 'V', 'e', 'r', 0 };
|
||||
static WCHAR const ips_keyname[13] = {
|
||||
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
|
||||
0 };
|
||||
static WCHAR const ips32_keyname[15] = {
|
||||
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
|
||||
'3', '2', 0 };
|
||||
static WCHAR const progid_keyname[7] = {
|
||||
'P', 'r', 'o', 'g', 'I', 'D', 0 };
|
||||
static WCHAR const viprogid_keyname[25] = {
|
||||
'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
|
||||
'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
|
||||
0 };
|
||||
static char const tmodel_valuename[] = "ThreadingModel";
|
||||
|
||||
/***********************************************************************
|
||||
* static helper functions
|
||||
*/
|
||||
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
|
||||
static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
|
||||
WCHAR const *value);
|
||||
static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
|
||||
char const *value);
|
||||
static LONG register_progid(WCHAR const *clsid,
|
||||
char const *progid, char const *curver_progid,
|
||||
char const *name, char const *extra);
|
||||
static LONG recursive_delete_key(HKEY key);
|
||||
static LONG recursive_delete_keyA(HKEY base, char const *name);
|
||||
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
|
||||
|
||||
/***********************************************************************
|
||||
* register_interfaces
|
||||
*/
|
||||
static HRESULT register_interfaces(struct regsvr_interface const *list)
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
HKEY interface_key;
|
||||
|
||||
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_return;
|
||||
|
||||
for (; res == ERROR_SUCCESS && list->iid; ++list) {
|
||||
WCHAR buf[39];
|
||||
HKEY iid_key;
|
||||
|
||||
StringFromGUID2(list->iid, buf, 39);
|
||||
res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_close_interface_key;
|
||||
|
||||
if (list->name) {
|
||||
res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
|
||||
(CONST BYTE*)(list->name),
|
||||
strlen(list->name) + 1);
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
}
|
||||
|
||||
if (list->base_iid) {
|
||||
register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
}
|
||||
|
||||
if (0 <= list->num_methods) {
|
||||
static WCHAR const fmt[3] = { '%', 'd', 0 };
|
||||
HKEY key;
|
||||
|
||||
res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
|
||||
wsprintfW(buf, fmt, list->num_methods);
|
||||
res = RegSetValueExW(key, NULL, 0, REG_SZ,
|
||||
(CONST BYTE*)buf,
|
||||
(lstrlenW(buf) + 1) * sizeof(WCHAR));
|
||||
RegCloseKey(key);
|
||||
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
}
|
||||
|
||||
if (list->ps_clsid) {
|
||||
register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
}
|
||||
|
||||
if (list->ps_clsid32) {
|
||||
register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
|
||||
if (res != ERROR_SUCCESS) goto error_close_iid_key;
|
||||
}
|
||||
|
||||
error_close_iid_key:
|
||||
RegCloseKey(iid_key);
|
||||
}
|
||||
|
||||
error_close_interface_key:
|
||||
RegCloseKey(interface_key);
|
||||
error_return:
|
||||
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* unregister_interfaces
|
||||
*/
|
||||
static HRESULT unregister_interfaces(struct regsvr_interface const *list)
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
HKEY interface_key;
|
||||
|
||||
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
|
||||
KEY_READ | KEY_WRITE, &interface_key);
|
||||
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
|
||||
if (res != ERROR_SUCCESS) goto error_return;
|
||||
|
||||
for (; res == ERROR_SUCCESS && list->iid; ++list) {
|
||||
WCHAR buf[39];
|
||||
|
||||
StringFromGUID2(list->iid, buf, 39);
|
||||
res = recursive_delete_keyW(interface_key, buf);
|
||||
}
|
||||
|
||||
RegCloseKey(interface_key);
|
||||
error_return:
|
||||
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* register_coclasses
|
||||
*/
|
||||
static HRESULT register_coclasses(struct regsvr_coclass const *list)
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
HKEY coclass_key;
|
||||
|
||||
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_return;
|
||||
|
||||
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
|
||||
WCHAR buf[39];
|
||||
HKEY clsid_key;
|
||||
|
||||
StringFromGUID2(list->clsid, buf, 39);
|
||||
res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
|
||||
|
||||
if (list->name) {
|
||||
res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
|
||||
(CONST BYTE*)(list->name),
|
||||
strlen(list->name) + 1);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
}
|
||||
|
||||
if (list->ips) {
|
||||
res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
}
|
||||
|
||||
if (list->ips32) {
|
||||
HKEY ips32_key;
|
||||
|
||||
res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL,
|
||||
&ips32_key, NULL);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
|
||||
res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
|
||||
(CONST BYTE*)list->ips32,
|
||||
lstrlenA(list->ips32) + 1);
|
||||
if (res == ERROR_SUCCESS && list->ips32_tmodel)
|
||||
res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
|
||||
(CONST BYTE*)list->ips32_tmodel,
|
||||
strlen(list->ips32_tmodel) + 1);
|
||||
RegCloseKey(ips32_key);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
}
|
||||
|
||||
if (list->progid) {
|
||||
res = register_key_defvalueA(clsid_key, progid_keyname,
|
||||
list->progid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
|
||||
res = register_progid(buf, list->progid, NULL,
|
||||
list->name, list->progid_extra);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
}
|
||||
|
||||
if (list->viprogid) {
|
||||
res = register_key_defvalueA(clsid_key, viprogid_keyname,
|
||||
list->viprogid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
|
||||
res = register_progid(buf, list->viprogid, list->progid,
|
||||
list->name, list->progid_extra);
|
||||
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
|
||||
}
|
||||
|
||||
error_close_clsid_key:
|
||||
RegCloseKey(clsid_key);
|
||||
}
|
||||
|
||||
error_close_coclass_key:
|
||||
RegCloseKey(coclass_key);
|
||||
error_return:
|
||||
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* unregister_coclasses
|
||||
*/
|
||||
static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
|
||||
{
|
||||
LONG res = ERROR_SUCCESS;
|
||||
HKEY coclass_key;
|
||||
|
||||
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
|
||||
KEY_READ | KEY_WRITE, &coclass_key);
|
||||
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
|
||||
if (res != ERROR_SUCCESS) goto error_return;
|
||||
|
||||
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
|
||||
WCHAR buf[39];
|
||||
|
||||
StringFromGUID2(list->clsid, buf, 39);
|
||||
res = recursive_delete_keyW(coclass_key, buf);
|
||||
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
|
||||
|
||||
if (list->progid) {
|
||||
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
|
||||
}
|
||||
|
||||
if (list->viprogid) {
|
||||
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
|
||||
}
|
||||
}
|
||||
|
||||
error_close_coclass_key:
|
||||
RegCloseKey(coclass_key);
|
||||
error_return:
|
||||
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* regsvr_key_guid
|
||||
*/
|
||||
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
|
||||
{
|
||||
WCHAR buf[39];
|
||||
|
||||
StringFromGUID2(guid, buf, 39);
|
||||
return register_key_defvalueW(base, name, buf);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* regsvr_key_defvalueW
|
||||
*/
|
||||
static LONG register_key_defvalueW(
|
||||
HKEY base,
|
||||
WCHAR const *name,
|
||||
WCHAR const *value)
|
||||
{
|
||||
LONG res;
|
||||
HKEY key;
|
||||
|
||||
res = RegCreateKeyExW(base, name, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &key, NULL);
|
||||
if (res != ERROR_SUCCESS) return res;
|
||||
res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
|
||||
(lstrlenW(value) + 1) * sizeof(WCHAR));
|
||||
RegCloseKey(key);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* regsvr_key_defvalueA
|
||||
*/
|
||||
static LONG register_key_defvalueA(
|
||||
HKEY base,
|
||||
WCHAR const *name,
|
||||
char const *value)
|
||||
{
|
||||
LONG res;
|
||||
HKEY key;
|
||||
|
||||
res = RegCreateKeyExW(base, name, 0, NULL, 0,
|
||||
KEY_READ | KEY_WRITE, NULL, &key, NULL);
|
||||
if (res != ERROR_SUCCESS) return res;
|
||||
res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
|
||||
lstrlenA(value) + 1);
|
||||
RegCloseKey(key);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* regsvr_progid
|
||||
*/
|
||||
static LONG register_progid(
|
||||
WCHAR const *clsid,
|
||||
char const *progid,
|
||||
char const *curver_progid,
|
||||
char const *name,
|
||||
char const *extra)
|
||||
{
|
||||
LONG res;
|
||||
HKEY progid_key;
|
||||
|
||||
res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
|
||||
NULL, 0, KEY_READ | KEY_WRITE, NULL,
|
||||
&progid_key, NULL);
|
||||
if (res != ERROR_SUCCESS) return res;
|
||||
|
||||
if (name) {
|
||||
res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
|
||||
(CONST BYTE*)name, strlen(name) + 1);
|
||||
if (res != ERROR_SUCCESS) goto error_close_progid_key;
|
||||
}
|
||||
|
||||
if (clsid) {
|
||||
res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_progid_key;
|
||||
}
|
||||
|
||||
if (curver_progid) {
|
||||
res = register_key_defvalueA(progid_key, curver_keyname,
|
||||
curver_progid);
|
||||
if (res != ERROR_SUCCESS) goto error_close_progid_key;
|
||||
}
|
||||
|
||||
if (extra) {
|
||||
HKEY extra_key;
|
||||
|
||||
res = RegCreateKeyExA(progid_key, extra, 0,
|
||||
NULL, 0, KEY_READ | KEY_WRITE, NULL,
|
||||
&extra_key, NULL);
|
||||
if (res == ERROR_SUCCESS)
|
||||
RegCloseKey(extra_key);
|
||||
}
|
||||
|
||||
error_close_progid_key:
|
||||
RegCloseKey(progid_key);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* recursive_delete_key
|
||||
*/
|
||||
static LONG recursive_delete_key(HKEY key)
|
||||
{
|
||||
LONG res;
|
||||
WCHAR subkey_name[MAX_PATH];
|
||||
DWORD cName;
|
||||
HKEY subkey;
|
||||
|
||||
for (;;) {
|
||||
cName = sizeof(subkey_name) / sizeof(WCHAR);
|
||||
res = RegEnumKeyExW(key, 0, subkey_name, &cName,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
|
||||
res = ERROR_SUCCESS; /* presumably we're done enumerating */
|
||||
break;
|
||||
}
|
||||
res = RegOpenKeyExW(key, subkey_name, 0,
|
||||
KEY_READ | KEY_WRITE, &subkey);
|
||||
if (res == ERROR_FILE_NOT_FOUND) continue;
|
||||
if (res != ERROR_SUCCESS) break;
|
||||
|
||||
res = recursive_delete_key(subkey);
|
||||
RegCloseKey(subkey);
|
||||
if (res != ERROR_SUCCESS) break;
|
||||
}
|
||||
|
||||
if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* recursive_delete_keyA
|
||||
*/
|
||||
static LONG recursive_delete_keyA(HKEY base, char const *name)
|
||||
{
|
||||
LONG res;
|
||||
HKEY key;
|
||||
|
||||
res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
|
||||
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
|
||||
if (res != ERROR_SUCCESS) return res;
|
||||
res = recursive_delete_key(key);
|
||||
RegCloseKey(key);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* recursive_delete_keyW
|
||||
*/
|
||||
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
|
||||
{
|
||||
LONG res;
|
||||
HKEY key;
|
||||
|
||||
res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
|
||||
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
|
||||
if (res != ERROR_SUCCESS) return res;
|
||||
res = recursive_delete_key(key);
|
||||
RegCloseKey(key);
|
||||
return res;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* coclass list
|
||||
*/
|
||||
static struct regsvr_coclass const coclass_list[] = {
|
||||
{ &CLSID_DirectPlay,
|
||||
"DirectPlay Object",
|
||||
NULL,
|
||||
"dplayx.dll",
|
||||
"Both"
|
||||
},
|
||||
{ &CLSID_DirectPlayLobby,
|
||||
"DirectPlayLobby Object",
|
||||
NULL,
|
||||
"dplayx.dll",
|
||||
"Both"
|
||||
},
|
||||
{ NULL } /* list terminator */
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* interface list
|
||||
*/
|
||||
|
||||
static struct regsvr_interface const interface_list[] = {
|
||||
{ NULL } /* list terminator */
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* DllRegisterServer (DPLAYX.@)
|
||||
*/
|
||||
HRESULT WINAPI DllRegisterServer(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
hr = register_coclasses(coclass_list);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = register_interfaces(interface_list);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllUnregisterServer (DPLAYX.@)
|
||||
*/
|
||||
HRESULT WINAPI DllUnregisterServer(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
hr = unregister_coclasses(coclass_list);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = unregister_interfaces(interface_list);
|
||||
return hr;
|
||||
}
|
27
reactos/lib/dplayx/version.rc
Normal file
27
reactos/lib/dplayx/version.rc
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2001 Ove Kaaven
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define WINE_OLESELFREGISTER
|
||||
#define WINE_FILEDESCRIPTION_STR "Wine DirectPlay"
|
||||
#define WINE_FILENAME_STR "dplayx.dll"
|
||||
#define WINE_FILEVERSION 5,3,0,900
|
||||
#define WINE_FILEVERSION_STR "5.3.0.900"
|
||||
#define WINE_PRODUCTVERSION 5,3,0,900
|
||||
#define WINE_PRODUCTVERSION_STR "5.3"
|
||||
|
||||
#include "wine/wine_common_ver.rc"
|
Loading…
Reference in a new issue