Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
10a04e74
Commit
10a04e74
authored
Oct 19, 2000
by
Peter Hunnisett
Committed by
Alexandre Julliard
Oct 19, 2000
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Add proper message reply mechanism and sp player data storage
- More implementation and fixes
parent
23a5b79f
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
617 additions
and
216 deletions
+617
-216
dpclassfactory.c
dlls/dplayx/dpclassfactory.c
+1
-1
dplay.c
dlls/dplayx/dplay.c
+159
-83
dplay_global.h
dlls/dplayx/dplay_global.h
+26
-4
dplaysp.c
dlls/dplayx/dplaysp.c
+125
-53
dplayx_messages.c
dlls/dplayx/dplayx_messages.c
+244
-56
dplayx_messages.h
dlls/dplayx/dplayx_messages.h
+59
-16
dplobby.c
dlls/dplayx/dplobby.c
+3
-3
No files found.
dlls/dplayx/dpclassfactory.c
View file @
10a04e74
...
...
@@ -77,7 +77,7 @@ static IClassFactoryImpl DP_and_DPL_CF = {&DP_and_DPL_Vtbl, 1 };
/*******************************************************************************
* DPLAYX_DllGetClassObject [DPLAYX.
?
]
* DPLAYX_DllGetClassObject [DPLAYX.
11
]
* Retrieves DP or DPL class object from a DLL object
*
* NOTES
...
...
dlls/dplayx/dplay.c
View file @
10a04e74
...
...
@@ -160,6 +160,8 @@ static HRESULT WINAPI DP_IF_EnumSessions
(
IDirectPlay2Impl
*
This
,
LPDPSESSIONDESC2
lpsd
,
DWORD
dwTimeout
,
LPDPENUMSESSIONSCALLBACK2
lpEnumSessionsCallback2
,
LPVOID
lpContext
,
DWORD
dwFlags
,
BOOL
bAnsi
);
static
HRESULT
WINAPI
DP_IF_InitializeConnection
(
IDirectPlay3Impl
*
This
,
LPVOID
lpConnection
,
DWORD
dwFlags
,
BOOL
bAnsi
);
static
BOOL
CALLBACK
cbDPCreateEnumConnections
(
LPCGUID
lpguidSP
,
LPVOID
lpConnection
,
DWORD
dwConnectionSize
,
LPCDPNAME
lpName
,
DWORD
dwFlags
,
LPVOID
lpContext
);
...
...
@@ -174,7 +176,7 @@ static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
LPCDPSESSIONDESC2
srcSessDesc
,
BOOL
bAnsi
);
static
HMODULE
DP_LoadSP
(
LPCGUID
lpcGuid
,
LPSPINITDATA
lpSpData
);
static
HMODULE
DP_LoadSP
(
LPCGUID
lpcGuid
,
LPSPINITDATA
lpSpData
,
LPBOOL
lpbIsDpSp
);
...
...
@@ -241,6 +243,7 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
DPQ_INIT
(
This
->
dp2
->
receiveMsgs
);
DPQ_INIT
(
This
->
dp2
->
sendMsgs
);
DPQ_INIT
(
This
->
dp2
->
replysExpected
);
if
(
!
NS_InitializeSessionCache
(
&
This
->
dp2
->
lpNameServerData
)
)
{
...
...
@@ -504,14 +507,14 @@ static HRESULT WINAPI DP_QueryInterface
TRACE
(
"(%p)->(%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObj
);
*
ppvObj
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
IDirectPlay2Impl
)
);
sizeof
(
*
This
)
);
if
(
*
ppvObj
==
NULL
)
{
return
DPERR_OUTOFMEMORY
;
}
CopyMemory
(
*
ppvObj
,
iface
,
sizeof
(
IDirectPlay2Impl
)
);
CopyMemory
(
*
ppvObj
,
This
,
sizeof
(
*
This
)
);
(
*
(
IDirectPlay2Impl
**
)
ppvObj
)
->
ulInterfaceRef
=
0
;
if
(
IsEqualGUID
(
&
IID_IDirectPlay2
,
riid
)
)
...
...
@@ -613,25 +616,22 @@ static inline DPID DP_NextObjectId(void)
}
/* *lplpReply will be non NULL iff there is something to reply */
HRESULT
DP_HandleMessage
(
IDirectPlay2Impl
*
This
,
LPCVOID
lpMessageBody
,
DWORD
dwMessageBodySize
,
LPCVOID
lpMessageHeader
,
HRESULT
DP_HandleMessage
(
IDirectPlay2Impl
*
This
,
LPCVOID
lp
c
MessageBody
,
DWORD
dwMessageBodySize
,
LPCVOID
lp
c
MessageHeader
,
WORD
wCommandId
,
WORD
wVersion
,
LPVOID
*
lplpReply
,
LPDWORD
lpdwMsgSize
)
{
TRACE
(
"(%p)->(%p,0x%08lx,%p,%u,%u)
\n
"
,
This
,
lp
MessageBody
,
dwMessageBodySize
,
lp
MessageHeader
,
wCommandId
,
This
,
lp
cMessageBody
,
dwMessageBodySize
,
lpc
MessageHeader
,
wCommandId
,
wVersion
);
DebugBreak
();
switch
(
wCommandId
)
{
case
DPMSGCMD_REQUESTNEWPLAYERID
:
{
#if 0
LPCDPMSG_REQUESTNEWPLAYERID
lpcMsg
=
(LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody;
#endif
(
LPCDPMSG_REQUESTNEWPLAYERID
)
lp
c
MessageBody
;
LPDPMSG_NEWPLAYERIDREPLY
lpReply
;
*
lpdwMsgSize
=
This
->
dp2
->
spData
.
dwSPHeaderSize
+
sizeof
(
*
lpReply
);
...
...
@@ -640,25 +640,8 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
HEAP_ZERO_MEMORY
,
*
lpdwMsgSize
);
FIXME
(
"Ignoring dwFlags in request msg
\n
"
);
#if 0
/* This is just a test. See how large the SPData is and send it */
{
LPVOID lpData;
DWORD dwDataSize;
HRESULT hr;
hr = IDirectPlaySP_GetSPData( This->dp2->spData.lpISP, &lpData,
&dwDataSize, DPSET_REMOTE );
if( FAILED(hr) )
{
ERR( "Unable to get remote SPData %s\n", DPLAYX_HresultToString(hr) );
}
}
#endif
FIXME
(
"Ignoring dwFlags 0x%08lx in request msg
\n
"
,
lpcMsg
->
dwFlags
);
/* Setup the reply */
lpReply
=
(
LPDPMSG_NEWPLAYERIDREPLY
)(
(
BYTE
*
)(
*
lplpReply
)
+
...
...
@@ -676,29 +659,25 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
break
;
}
case
DPMSGCMD_GETNAMETABLEREPLY
:
case
DPMSGCMD_NEWPLAYERIDREPLY
:
{
if
(
This
->
dp2
->
hMsgReceipt
)
{
/* This is a hack only */
This
->
dp2
->
lpMsgReceived
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
dwMessageBodySize
);
CopyMemory
(
This
->
dp2
->
lpMsgReceived
,
lpMessageBody
,
dwMessageBodySize
);
SetEvent
(
This
->
dp2
->
hMsgReceipt
);
}
else
{
ERR
(
"No receipt event set - only expecting in reply mode
\n
"
);
}
DP_MSG_ReplyReceived
(
This
,
wCommandId
,
lpcMessageBody
,
dwMessageBodySize
);
break
;
}
case
DPMSGCMD_FORWARDADDPLAYERNACK
:
{
DP_MSG_ErrorReceived
(
This
,
wCommandId
,
lpcMessageBody
,
dwMessageBodySize
);
break
;
}
default
:
{
FIXME
(
"Unknown wCommandId %u. Ignoring message
\n
"
,
wCommandId
);
DebugBreak
();
break
;
}
}
...
...
@@ -873,6 +852,8 @@ lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
/* FIXME: Should we validate the dwFlags? */
lpGData
->
dwFlags
=
dwFlags
;
TRACE
(
"Created group id 0x%08lx
\n
"
,
*
lpid
);
return
lpGData
;
}
...
...
@@ -968,6 +949,7 @@ static HRESULT WINAPI DP_IF_CreateGroup
if
(
DPID_SYSTEM_GROUP
==
*
lpidGroup
)
{
This
->
dp2
->
lpSysGroup
=
lpGData
;
TRACE
(
"Inserting system group
\n
"
);
}
else
{
...
...
@@ -1149,6 +1131,11 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
}
}
/* Initialize the SP data section */
lpPData
->
lpSPPlayerData
=
DPSP_CreateSPPlayerData
();
TRACE
(
"Created player id 0x%08lx
\n
"
,
*
lpid
);
return
lpPData
;
}
...
...
@@ -1325,6 +1312,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
HANDLE
hr
=
DP_OK
;
lpPlayerData
lpPData
;
lpPlayerList
lpPList
;
DWORD
dwCreateFlags
=
0
;
TRACE
(
"(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)
\n
"
,
This
,
lpidPlayer
,
lpPlayerName
,
hEvent
,
lpData
,
...
...
@@ -1340,6 +1328,35 @@ static HRESULT WINAPI DP_IF_CreatePlayer
return
DPERR_INVALIDPARAMS
;
}
/* Determine the creation flags for the player. These will be passed
* to the name server if requesting a player id and to the SP when
* informing it of the player creation
*/
{
if
(
dwFlags
&
DPPLAYER_SERVERPLAYER
)
{
if
(
*
lpidPlayer
==
DPID_SERVERPLAYER
)
{
/* Server player for the host interface */
dwCreateFlags
|=
DPLAYI_PLAYER_APPSERVER
;
}
else
if
(
*
lpidPlayer
==
DPID_NAME_SERVER
)
{
/* Name server - master of everything */
dwCreateFlags
|=
(
DPLAYI_PLAYER_NAMESRVR
|
DPLAYI_PLAYER_SYSPLAYER
);
}
else
{
/* Server player for a non host interface */
dwCreateFlags
|=
DPLAYI_PLAYER_SYSPLAYER
;
}
}
if
(
lpMsgHdr
==
NULL
)
dwCreateFlags
|=
DPLAYI_PLAYER_PLAYERLOCAL
;
}
/* Verify we know how to handle all the flags */
if
(
!
(
(
dwFlags
&
DPPLAYER_SERVERPLAYER
)
||
(
dwFlags
&
DPPLAYER_SPECTATOR
)
...
...
@@ -1360,7 +1377,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
}
else
{
hr
=
DP_MSG_SendRequestPlayerId
(
This
,
dwFlags
,
lpidPlayer
);
hr
=
DP_MSG_SendRequestPlayerId
(
This
,
dw
Create
Flags
,
lpidPlayer
);
if
(
FAILED
(
hr
)
)
{
...
...
@@ -1376,6 +1393,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
*/
}
/* FIXME: Should we be storing these dwFlags or the creation ones? */
lpPData
=
DP_CreatePlayer
(
This
,
lpidPlayer
,
lpPlayerName
,
dwFlags
,
hEvent
,
bAnsi
);
...
...
@@ -1406,28 +1424,15 @@ static HRESULT WINAPI DP_IF_CreatePlayer
if
(
This
->
dp2
->
spData
.
lpCB
->
CreatePlayer
)
{
DPSP_CREATEPLAYERDATA
data
;
DWORD
dwCreateFlags
=
0
;
TRACE
(
"Calling SP CreatePlayer
\n
"
);
if
(
(
dwFlags
&
DPPLAYER_SERVERPLAYER
)
&&
(
*
lpidPlayer
==
DPID_SERVERPLAYER
)
)
dwCreateFlags
|=
DPLAYI_PLAYER_APPSERVER
;
if
(
(
dwFlags
&
DPPLAYER_SERVERPLAYER
)
&&
(
*
lpidPlayer
==
DPID_NAME_SERVER
)
)
dwCreateFlags
|=
(
DPLAYI_PLAYER_NAMESRVR
|
DPLAYI_PLAYER_SYSPLAYER
);
if
(
lpMsgHdr
==
NULL
)
dwCreateFlags
|=
DPLAYI_PLAYER_PLAYERLOCAL
;
data
.
idPlayer
=
*
lpidPlayer
;
data
.
dwFlags
=
dwCreateFlags
;
data
.
lpSPMessageHeader
=
lpMsgHdr
;
data
.
lpISP
=
This
->
dp2
->
spData
.
lpISP
;
TRACE
(
"Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p
\n
"
,
*
lpidPlayer
,
data
.
dwFlags
,
data
.
lpSPMessageHeader
);
hr
=
(
*
This
->
dp2
->
spData
.
lpCB
->
CreatePlayer
)(
&
data
);
}
...
...
@@ -1453,11 +1458,22 @@ static HRESULT WINAPI DP_IF_CreatePlayer
if
(
FAILED
(
hr
)
)
{
ERR
(
"Failed to add player to sys groupwith sp: %s
\n
"
,
ERR
(
"Failed to add player to sys group
with sp: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
return
hr
;
}
#if 1
if
(
This
->
dp2
->
bHostInterface
==
FALSE
)
{
/* Let the name server know about the creation of this player */
/* FIXME: Is this only to be done for the creation of a server player or
* is this used for regular players? If only for server players, move
* this call to DP_SecureOpen(...);
*/
hr
=
DP_MSG_ForwardPlayerCreation
(
This
,
*
lpidPlayer
);
}
#else
/* Inform all other peers of the creation of a new player. If there are
* no peers keep this quiet.
* Also, if this was a remote event, no need to rebroadcast it.
...
...
@@ -1484,6 +1500,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
hr
=
DP_SendEx
(
This
,
DPID_SERVERPLAYER
,
DPID_ALLPLAYERS
,
0
,
&
msg
,
sizeof
(
msg
),
0
,
0
,
NULL
,
NULL
,
bAnsi
);
}
#endif
return
hr
;
}
...
...
@@ -2055,7 +2072,8 @@ static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
/* Does a thread exist? If so we were doing an async enum session */
if
(
This
->
dp2
->
hEnumSessionThread
!=
INVALID_HANDLE_VALUE
)
{
TRACE
(
"Killing EnumSession thread
\n
"
);
TRACE
(
"Killing EnumSession thread %u
\n
"
,
This
->
dp2
->
hEnumSessionThread
);
/* Request that the thread kill itself nicely */
SetEvent
(
This
->
dp2
->
hKillEnumSessionThreadEvent
);
...
...
@@ -2094,7 +2112,12 @@ static HRESULT WINAPI DP_IF_EnumSessions
DP_IF_GetCaps
(
This
,
&
spCaps
,
0
);
dwTimeout
=
spCaps
.
dwTimeout
;
/* FIXME: If it's still 0, we need to provide the IP default */
/* The service provider doesn't provide one either! */
if
(
dwTimeout
==
0
)
{
/* Provide the TCP/IP default */
dwTimeout
=
DPMSG_WAIT_5_SECS
;
}
}
if
(
dwFlags
&
DPENUMSESSIONS_STOPASYNC
)
...
...
@@ -2725,6 +2748,7 @@ static HRESULT WINAPI DP_SecureOpen
hr
=
DP_IF_CreatePlayer
(
This
,
NULL
,
&
dpidServerId
,
NULL
,
0
,
NULL
,
0
,
DPPLAYER_SERVERPLAYER
|
DPPLAYER_LOCAL
,
bAnsi
);
}
else
if
(
dwFlags
&
DPOPEN_CREATE
)
{
...
...
@@ -3792,7 +3816,7 @@ BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
/* Find and perform a LoadLibrary on the requested SP or LP GUID */
static
HMODULE
DP_LoadSP
(
LPCGUID
lpcGuid
,
LPSPINITDATA
lpSpData
)
static
HMODULE
DP_LoadSP
(
LPCGUID
lpcGuid
,
LPSPINITDATA
lpSpData
,
LPBOOL
lpbIsDpSp
)
{
UINT
i
;
LPCSTR
spSubKey
=
"SOFTWARE
\\
Microsoft
\\
DirectPlay
\\
Service Providers"
;
...
...
@@ -3814,6 +3838,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
FILETIME
filetime
;
(
i
==
0
)
?
(
searchSubKey
=
spSubKey
)
:
(
searchSubKey
=
lpSubKey
);
*
lpbIsDpSp
=
(
i
==
0
)
?
TRUE
:
FALSE
;
/* Need to loop over the service providers in the registry */
...
...
@@ -3910,6 +3935,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
continue
;
}
TRACE
(
"Loading %s
\n
"
,
returnBuffer
);
return
LoadLibraryA
(
returnBuffer
);
}
}
...
...
@@ -3917,18 +3943,17 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
return
0
;
}
static
HRESULT
WINAPI
D
irectPlay3AImpl
_InitializeConnection
(
LPDIRECTPLAY3A
iface
,
LPVOID
lpConnection
,
DWORD
dwFlags
)
static
HRESULT
WINAPI
D
P_IF
_InitializeConnection
(
IDirectPlay3Impl
*
This
,
LPVOID
lpConnection
,
DWORD
dwFlags
,
BOOL
bAnsi
)
{
HMODULE
hServiceProvider
;
HRESULT
hr
;
LPDPSP_SPINIT
SPInit
;
GUID
guidSP
;
DWORD
dwAddrSize
=
80
;
/* FIXME: Need to calculate it correctly */
ICOM_THIS
(
IDirectPlay3Impl
,
iface
);
const
DWORD
dwAddrSize
=
80
;
/* FIXME: Need to calculate it correctly */
BOOL
bIsDpSp
;
/* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
TRACE
(
"(%p)->(%p,0x%08lx
)
\n
"
,
This
,
lpConnection
,
dwFlags
);
TRACE
(
"(%p)->(%p,0x%08lx
,%u)
\n
"
,
This
,
lpConnection
,
dwFlags
,
bAnsi
);
if
(
dwFlags
!=
0
)
{
...
...
@@ -3958,7 +3983,7 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
This
->
dp2
->
spData
.
lpGuid
=
&
guidSP
;
/* Load the service provider */
hServiceProvider
=
DP_LoadSP
(
&
guidSP
,
&
This
->
dp2
->
spData
);
hServiceProvider
=
DP_LoadSP
(
&
guidSP
,
&
This
->
dp2
->
spData
,
&
bIsDpSp
);
if
(
hServiceProvider
==
0
)
{
...
...
@@ -3966,22 +3991,35 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
return
DPERR_UNAVAILABLE
;
}
/* Initialize the service provider by calling SPInit */
SPInit
=
(
LPDPSP_SPINIT
)
GetProcAddress
(
hServiceProvider
,
"SPInit"
);
if
(
bIsDpSp
)
{
/* Initialize the service provider by calling SPInit */
SPInit
=
(
LPDPSP_SPINIT
)
GetProcAddress
(
hServiceProvider
,
"SPInit"
);
}
else
{
/* Initialize the service provider by calling SPInit */
SPInit
=
(
LPDPSP_SPINIT
)
GetProcAddress
(
hServiceProvider
,
"DPLSPInit"
);
}
if
(
SPInit
==
NULL
)
{
ERR
(
"Service provider doesn't provide SPInit interface?
\n
"
);
ERR
(
"Service provider doesn't provide %s interface?
\n
"
,
bIsDpSp
?
"SPInit"
:
"DPLSPInit"
);
FreeLibrary
(
hServiceProvider
);
return
DPERR_UNAVAILABLE
;
}
TRACE
(
"Calling SPInit
\n
"
);
TRACE
(
"Calling %s (SP entry point)
\n
"
,
bIsDpSp
?
"SPInit"
:
"DPLSPInit"
);
/* FIXME: Need to break this out into a seperate routine for DP SP and
* DPL SP as they actually use different stuff...
*/
hr
=
(
*
SPInit
)(
&
This
->
dp2
->
spData
);
if
(
FAILED
(
hr
)
)
{
ERR
(
"SP Initialization failed: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
ERR
(
"
DP/DPL
SP Initialization failed: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
FreeLibrary
(
hServiceProvider
);
return
hr
;
}
...
...
@@ -3995,12 +4033,18 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
return
DP_OK
;
}
static
HRESULT
WINAPI
DirectPlay3AImpl_InitializeConnection
(
LPDIRECTPLAY3A
iface
,
LPVOID
lpConnection
,
DWORD
dwFlags
)
{
ICOM_THIS
(
IDirectPlay3Impl
,
iface
);
return
DP_IF_InitializeConnection
(
This
,
lpConnection
,
dwFlags
,
TRUE
);
}
static
HRESULT
WINAPI
DirectPlay3WImpl_InitializeConnection
(
LPDIRECTPLAY3
iface
,
LPVOID
lpConnection
,
DWORD
dwFlags
)
{
ICOM_THIS
(
IDirectPlay3Impl
,
iface
);
FIXME
(
"(%p)->(%p,0x%08lx): stub
\n
"
,
This
,
lpConnection
,
dwFlags
);
return
DP_OK
;
return
DP_IF_InitializeConnection
(
This
,
lpConnection
,
dwFlags
,
FALSE
);
}
static
HRESULT
WINAPI
DirectPlay3AImpl_SecureOpen
...
...
@@ -4846,9 +4890,42 @@ static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
};
#undef XCAST
extern
HRESULT
DP_GetSPPlayerData
(
IDirectPlay2Impl
*
lpDP
,
DPID
idPlayer
,
LPVOID
*
lplpData
)
{
lpPlayerList
lpPlayer
=
DP_FindPlayer
(
lpDP
,
idPlayer
);
if
(
lpPlayer
==
NULL
)
{
return
DPERR_INVALIDPLAYER
;
}
*
lplpData
=
lpPlayer
->
lpPData
->
lpSPPlayerData
;
return
DP_OK
;
}
extern
HRESULT
DP_SetSPPlayerData
(
IDirectPlay2Impl
*
lpDP
,
DPID
idPlayer
,
LPVOID
lpData
)
{
lpPlayerList
lpPlayer
=
DP_FindPlayer
(
lpDP
,
idPlayer
);
if
(
lpPlayer
==
NULL
)
{
return
DPERR_INVALIDPLAYER
;
}
lpPlayer
->
lpPData
->
lpSPPlayerData
=
lpData
;
return
DP_OK
;
}
/***************************************************************************
* DirectPlayEnumerateA
(DPLAYX.2)
* DirectPlayEnumerateA
[DPLAYX.2][DPLAYX.9][DPLAY.2]
*
* The pointer to the structure lpContext will be filled with the
* appropriate data for each service offered by the OS. These services are
...
...
@@ -4980,7 +5057,7 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
}
/***************************************************************************
* DirectPlayEnumerateW
(DPLAYX.3)
* DirectPlayEnumerateW
[DPLAYX.3]
*
*/
HRESULT
WINAPI
DirectPlayEnumerateW
(
LPDPENUMDPCALLBACKW
lpEnumCallback
,
LPVOID
lpContext
)
...
...
@@ -5027,7 +5104,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections(
/***************************************************************************
* DirectPlayCreate
(DPLAYX.1) (DPLAY.1)
* DirectPlayCreate
[DPLAYX.1][DPLAY.1]
*
*/
HRESULT
WINAPI
DirectPlayCreate
...
...
@@ -5044,7 +5121,6 @@ HRESULT WINAPI DirectPlayCreate
return
CLASS_E_NOAGGREGATION
;
}
/* Create an IDirectPlay object. We don't support that so we'll cheat and
give them an IDirectPlay2A object and hope that doesn't cause problems */
if
(
DP_CreateInterface
(
&
IID_IDirectPlay2A
,
(
LPVOID
*
)
lplpDP
)
!=
DP_OK
)
...
...
dlls/dplayx/dplay_global.h
View file @
10a04e74
...
...
@@ -35,6 +35,21 @@ typedef struct tagEnumSessionAsyncCallbackData
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 */
...
...
@@ -53,6 +68,9 @@ struct PlayerData
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
;
...
...
@@ -137,10 +155,8 @@ typedef struct tagDirectPlay2Data
BOOL
bConnectionInitialized
;
/* proof of concept for message reception */
HANDLE
hMsgReceipt
;
LPVOID
lpMsgReceived
;
/* Expected messages queue */
DPQ_HEAD
(
tagDP_MSG_REPLY_STRUCT_LIST
)
replysExpected
;
}
DirectPlay2Data
;
typedef
struct
tagDirectPlay3Data
...
...
@@ -192,5 +208,11 @@ HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
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 */
dlls/dplayx/dplaysp.c
View file @
10a04e74
...
...
@@ -26,7 +26,6 @@ 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
;
...
...
@@ -46,8 +45,6 @@ typedef struct tagDirectPlaySPData
IDirectPlay2Impl
*
dplay
;
/* FIXME: This should perhaps be iface not impl */
LPVOID
lpPlayerData
;
/* FIXME: Need to figure out how this actually behaves */
DWORD
dwPlayerDataSize
;
}
DirectPlaySPData
;
#define DPSP_IMPL_FIELDS \
...
...
@@ -64,7 +61,15 @@ struct IDirectPlaySPImpl
/* Forward declaration of virtual tables */
static
ICOM_VTABLE
(
IDirectPlaySP
)
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
...
...
@@ -165,6 +170,15 @@ static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
*/
/* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
/* 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
;
}
...
...
@@ -200,14 +214,14 @@ static HRESULT WINAPI DPSP_QueryInterface
TRACE
(
"(%p)->(%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObj
);
*
ppvObj
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
IDirectPlaySPImpl
)
);
sizeof
(
*
This
)
);
if
(
*
ppvObj
==
NULL
)
{
return
DPERR_OUTOFMEMORY
;
}
CopyMemory
(
*
ppvObj
,
iface
,
sizeof
(
IDirectPlaySPImpl
)
);
CopyMemory
(
*
ppvObj
,
This
,
sizeof
(
*
This
)
);
(
*
(
IDirectPlaySPImpl
**
)
ppvObj
)
->
ulInterfaceRef
=
0
;
if
(
IsEqualGUID
(
&
IID_IDirectPlaySP
,
riid
)
)
...
...
@@ -363,18 +377,50 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
DWORD
dwFlags
)
{
HRESULT
hr
;
LPDP_SPPLAYERDATA
lpPlayerData
;
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
TRACE
(
"Called on process 0x%08lx
\n
"
,
GetCurrentProcessId
()
);
FIXME
(
"(%p)->(0x%08lx,%p,%p,0x%08lx): stub
\n
"
,
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
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
)
{
if
(
lpPlayerData
->
lpPlayerLocalData
)
{
HeapFree
(
GetProcessHeap
(),
0
,
lpPlayerData
->
lpPlayerLocalData
);
}
*
lplpData
=
This
->
sp
->
lpPlayerData
;
*
lpdwDataSize
=
This
->
sp
->
dwPlayerDataSize
;
*
lplpData
=
lpPlayerData
->
lpPlayerLocalData
;
*
lpdwDataSize
=
lpPlayerData
->
dwPlayerLocalDataSize
;
}
else
if
(
dwFlags
==
DPSET_REMOTE
)
{
if
(
lpPlayerData
->
lpPlayerRemoteData
)
{
HeapFree
(
GetProcessHeap
(),
0
,
lpPlayerData
->
lpPlayerRemoteData
);
}
return
DP_OK
;
*
lplpData
=
lpPlayerData
->
lpPlayerRemoteData
;
*
lpdwDataSize
=
lpPlayerData
->
dwPlayerRemoteDataSize
;
}
if
(
*
lplpData
==
NULL
)
{
hr
=
DPERR_GENERIC
;
}
return
hr
;
}
static
HRESULT
WINAPI
IDirectPlaySPImpl_HandleMessage
...
...
@@ -391,7 +437,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
TRACE
(
"Called on process 0x%08lx
\n
"
,
GetCurrentProcessId
()
);
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
FIXME
(
"(%p)->(%p,0x%08lx,%p): mostly stub
\n
"
,
This
,
lpMessageBody
,
dwMessageBodySize
,
lpMessageHeader
);
...
...
@@ -409,6 +455,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
switch
(
lpMsg
->
wCommandId
)
{
/* Name server needs to handle this request */
/* FIXME: This should be done in direct play handler */
case
DPMSGCMD_ENUMSESSIONSREQUEST
:
{
DPSP_REPLYDATA
data
;
...
...
@@ -430,6 +477,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
}
/* Name server needs to handle this request */
/* FIXME: This should be done in direct play handler */
case
DPMSGCMD_ENUMSESSIONSREPLY
:
{
NS_SetRemoteComputerAsNameServer
(
lpMessageHeader
,
...
...
@@ -438,14 +486,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
This
->
sp
->
dplay
->
dp2
->
lpNameServerData
);
/* No reply expected */
hr
=
DP_OK
;
break
;
}
case
DPMSGCMD_GETNAMETABLE
:
case
DPMSGCMD_GETNAMETABLEREPLY
:
case
DPMSGCMD_NEWPLAYERIDREPLY
:
case
DPMSGCMD_REQUESTNEWPLAYERID
:
/* Pass everything else to Direct Play */
default:
{
DPSP_REPLYDATA
data
;
...
...
@@ -453,9 +500,9 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
data
.
dwMessageSize
=
0
;
/* Pass this message to the dplay interface to handle */
DP_HandleMessage
(
This
->
sp
->
dplay
,
lpMessageBody
,
dwMessageBodySize
,
lpMessageHeader
,
wCommandId
,
wVersion
,
&
data
.
lpMessage
,
&
data
.
dwMessageSize
);
hr
=
DP_HandleMessage
(
This
->
sp
->
dplay
,
lpMessageBody
,
dwMessageBodySize
,
lpMessageHeader
,
wCommandId
,
wVersion
,
&
data
.
lpMessage
,
&
data
.
dwMessageSize
);
/* Do we want a reply? */
if
(
data
.
lpMessage
!=
NULL
)
...
...
@@ -476,10 +523,6 @@ static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
break
;
}
default:
FIXME
(
"Unknown Command of %u and size 0x%08lx
\n
"
,
lpMsg
->
wCommandId
,
dwMessageBodySize
);
}
#if 0
...
...
@@ -736,22 +779,40 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
DWORD
dwFlags
)
{
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
HRESULT
hr
;
LPDP_SPPLAYERDATA
lpPlayerEntry
;
LPVOID
lpPlayerData
;
/* FIXME: I'm not sure if this stuff should be associated with the DPlay
* player lists. How else would this stuff get deleted?
*/
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
TRACE
(
"Called on process 0x%08lx
\n
"
,
GetCurrentProcessId
()
);
FIXME
(
"(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub
\n
"
,
/* TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
TRACE
(
"(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)
\n
"
,
This
,
idPlayer
,
lpData
,
dwDataSize
,
dwFlags
);
This
->
sp
->
lpPlayerData
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
dwDataSize
);
hr
=
DP_GetSPPlayerData
(
This
->
sp
->
dplay
,
idPlayer
,
(
LPVOID
*
)
&
lpPlayerEntry
);
if
(
FAILED
(
hr
)
)
{
/* Player must not exist */
return
DPERR_INVALIDPLAYER
;
}
This
->
sp
->
dwPlayerDataSize
=
dwDataSize
;
CopyMemory
(
This
->
sp
->
lpPlayerData
,
lpData
,
dwDataSize
);
lpPlayerData
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
dwDataSize
)
;
CopyMemory
(
lpPlayerData
,
lpData
,
dwDataSize
);
return
DP_OK
;
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
...
...
@@ -777,15 +838,16 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
DWORD
dwFlags
)
{
HRESULT
hr
=
DP_OK
;
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
TRACE
(
"Called on process 0x%08lx
\n
"
,
GetCurrentProcessId
()
);
/* 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 !=
0
)
if( dwFlags !=
DPSET_REMOTE
)
{
return DPERR_INVALIDPARAMS;
}
...
...
@@ -794,7 +856,7 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
* thing?
*/
if
(
dwFlags
!=
0
)
if
(
dwFlags
!=
DPSET_REMOTE
)
{
FIXME
(
"Undocumented dwFlags 0x%08lx used
\n
"
,
dwFlags
);
}
...
...
@@ -807,14 +869,24 @@ static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
{
*
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
DP_OK
;
return
hr
;
}
static
HRESULT
WINAPI
IDirectPlaySPImpl_SetSPData
...
...
@@ -828,13 +900,13 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
ICOM_THIS
(
IDirectPlaySPImpl
,
iface
);
TRACE
(
"Called on process 0x%08lx
\n
"
,
GetCurrentProcessId
()
);
/* 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 !=
0
)
if( dwFlags !=
DPSET_REMOTE
)
{
return DPERR_INVALIDPARAMS;
}
...
...
@@ -843,35 +915,23 @@ static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
/* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
* thing?
*/
if
(
dwFlags
!=
0
)
if
(
dwFlags
!=
DPSET_REMOTE
)
{
FIXME
(
"Undocumented dwFlags 0x%08lx used
\n
"
,
dwFlags
);
}
#endif
if
(
dwFlags
==
DPSET_REMOTE
)
{
lpSpData
=
DPLAYX_PrivHeapAlloc
(
HEAP_ZERO_MEMORY
,
dwDataSize
);
}
else
{
lpSpData
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
dwDataSize
);
}
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
)
{
/* FIXME: This doesn't strictly make sense as there is no means to share
* this shared data. Must be misinterpreting something...
*/
if
(
This
->
sp
->
lpSpRemoteData
)
{
DPLAYX_PrivHeapFree
(
This
->
sp
->
lpSpRemoteData
);
HeapFree
(
GetProcessHeap
(),
0
,
This
->
sp
->
lpSpRemoteData
);
}
/* NOTE: dwDataSize is also stored in the heap structure */
This
->
sp
->
dwSpRemoteDataSize
=
dwDataSize
;
This
->
sp
->
lpSpRemoteData
=
lpSpData
;
}
...
...
@@ -923,3 +983,15 @@ static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
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
)
);
}
dlls/dplayx/dplayx_messages.c
View file @
10a04e74
...
...
@@ -27,8 +27,11 @@ typedef struct tagMSGTHREADINFO
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
...
...
@@ -139,6 +142,42 @@ end_of_thread:
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
=
CreateEventA
(
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
)
...
...
@@ -146,7 +185,6 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
LPVOID
lpMsg
;
LPDPMSG_REQUESTNEWPLAYERID
lpMsgBody
;
DWORD
dwMsgSize
;
DWORD
dwWaitReturn
;
HRESULT
hr
=
DP_OK
;
dwMsgSize
=
This
->
dp2
->
spData
.
dwSPHeaderSize
+
sizeof
(
*
lpMsgBody
);
...
...
@@ -156,19 +194,16 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
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
;
/* FIXME: Need to have a more advanced queuing system as this needs to
* block on send until we get response. Otherwise we need to be
* able to ensure we can pick out the exact response. Of course,
* with something as non critical as this, would it matter? The
* id has been effectively reserved for this session...
*/
{
/* Send the message */
{
DPSP_SENDDATA
data
;
data
.
dwFlags
=
DPSEND_GUARANTEED
;
...
...
@@ -179,37 +214,20 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
data
.
bSystemMessage
=
TRUE
;
/* Allow reply to be sent */
data
.
lpISP
=
This
->
dp2
->
spData
.
lpISP
;
/* Setup for receipt */
This
->
dp2
->
hMsgReceipt
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
TRACE
(
"Asking for player id w/ dwFlags 0x%08lx
\n
"
,
lpMsgBody
->
dwFlags
);
TRACE
(
"Sending request for player id
\n
"
);
hr
=
(
*
This
->
dp2
->
spData
.
lpCB
->
Send
)(
&
data
);
if
(
FAILED
(
hr
)
)
{
ERR
(
"Request for new playerID send failed: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
return
DPERR_NOCONNECTION
;
}
}
dwWaitReturn
=
WaitForSingleObject
(
This
->
dp2
->
hMsgReceipt
,
30000
);
if
(
dwWaitReturn
!=
WAIT_OBJECT_0
)
{
ERR
(
"Wait failed 0x%08lx
\n
"
,
dwWaitReturn
);
hr
=
DPERR_TIMEOUT
;
DP_MSG_ExpectReply
(
This
,
&
data
,
DPMSG_DEFAULT_WAIT_TIME
,
DPMSGCMD_NEWPLAYERIDREPLY
,
&
lpMsg
,
&
dwMsgSize
);
}
CloseHandle
(
This
->
dp2
->
hMsgReceipt
);
This
->
dp2
->
hMsgReceipt
=
0
;
/* Need to examine the data and extract the new player id */
if
(
!
FAILED
(
hr
)
)
{
LPCDPMSG_NEWPLAYERIDREPLY
lpcReply
;
lpcReply
=
(
LPCDPMSG_NEWPLAYERIDREPLY
)
This
->
dp2
->
lpMsgReceived
;
lpcReply
=
(
LPCDPMSG_NEWPLAYERIDREPLY
)
lpMsg
;
*
lpdpidAllocatedId
=
lpcReply
->
dpidNewPlayerId
;
...
...
@@ -217,47 +235,217 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
/* 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?
*/
#if 0
/* Set the passed service provider data */
IDirectPlaySP_SetSPData( This->dp2->spData.lpISP, data,
msgsize, DPSET_REMOTE );
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, dpidServer, (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
HeapFree
(
GetProcessHeap
(),
0
,
This
->
dp2
->
lpMsgReceived
);
This
->
dp2
->
lpMsgReceived
=
NULL
;
/* 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
]
=
0x1e090002
;
lpMsgBody
->
unknown4
[
4
]
=
0x0
;
lpMsgBody
->
unknown4
[
5
]
=
0x0
;
lpMsgBody
->
unknown4
[
6
]
=
0x0
;
lpMsgBody
->
unknown4
[
7
]
=
0x32090002
;
lpMsgBody
->
unknown4
[
8
]
=
0x0
;
lpMsgBody
->
unknown4
[
9
]
=
0x0
;
lpMsgBody
->
unknown4
[
10
]
=
0x0
;
lpMsgBody
->
unknown4
[
11
]
=
0x0
;
lpMsgBody
->
unknown4
[
12
]
=
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
;
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
(
"Request for new playerID send failed: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
return
NULL
;
}
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
);
}
/* This function seems to cause a trap in the SP. It would seem unnecessary */
/* FIXME: Remove this method if not required */
HRESULT
DP_MSG_OpenStream
(
IDirectPlay2AImpl
*
This
)
/* Determine if there is a matching request for this incomming 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
)
{
HRESULT
hr
;
DPSP_SENDDATA
data
;
LPDP_MSG_REPLY_STRUCT_LIST
lpReplyList
;
data
.
dwFlags
=
DPSEND_OPENSTREAM
;
data
.
idPlayerTo
=
0
;
/* Name server */
data
.
idPlayerFrom
=
0
;
/* From DP itself */
data
.
lpMessage
=
NULL
;
data
.
dwMessageSize
=
This
->
dp2
->
spData
.
dwSPHeaderSize
;
data
.
bSystemMessage
=
FALSE
;
/* FIXME? */
data
.
lpISP
=
This
->
dp2
->
spData
.
lpISP
;
#if 0
if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
{
DebugBreak();
}
#endif
hr
=
(
*
This
->
dp2
->
spData
.
lpCB
->
Send
)(
&
data
);
/* 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
(
FAILED
(
hr
)
)
if
(
lpReplyList
!=
NULL
)
{
ERR
(
"Request for open stream send failed: %s
\n
"
,
DPLAYX_HresultToString
(
hr
)
);
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
();
}
}
/* FIXME: hack to give some time for channel to open */
SleepEx
(
1000
/* 1 sec */
,
FALSE
);
void
DP_MSG_ErrorReceived
(
IDirectPlay2AImpl
*
This
,
WORD
wCommandId
,
LPCVOID
lpMsgBody
,
DWORD
dwMsgBodySize
)
{
LPCDPMSG_FORWARDADDPLAYERNACK
lpcErrorMsg
;
return
hr
;
lpcErrorMsg
=
(
LPCDPMSG_FORWARDADDPLAYERNACK
)
lpMsgBody
;
ERR
(
"Received error message %u. Error is %s
\n
"
,
wCommandId
,
DPLAYX_HresultToString
(
lpcErrorMsg
->
errorCode
)
);
DebugBreak
();
}
dlls/dplayx/dplayx_messages.h
View file @
10a04e74
...
...
@@ -11,6 +11,20 @@
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
);
/* 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"
...
...
@@ -18,12 +32,12 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
/* 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
#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
...
...
@@ -31,9 +45,9 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
#define DPMSGCMD_ENUMGROUPS 17
#define DPMSGCMD_
GETNAMETABLE
19
#define DPMSGCMD_
FORWARDADDPLAYER
19
#define DPMSGCMD_
GETNAMETABLEREPLY 29
#define DPMSGCMD_
FORWARDADDPLAYERNACK 36
/* This is what DP 6 defines it as. Don't know what it means. All messages
* defined below are DPMSGVER_DP6.
...
...
@@ -45,9 +59,8 @@ DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart,
/* All messages sent from the system are sent with this at the beginning of
* the message.
* Size is 8 bytes
*/
/* Size is 8 bytes */
typedef
struct
tagDPMSG_SENDENVELOPE
{
DWORD
dwMagic
;
...
...
@@ -56,6 +69,9 @@ typedef struct tagDPMSG_SENDENVELOPE
}
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
;
...
...
@@ -63,7 +79,7 @@ typedef struct tagDPMSG_SYSMSGENVELOPE
}
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
;
...
...
@@ -93,13 +109,14 @@ typedef struct tagDPMSG_ENUMSESSIONSREPLY
}
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
normally
0x00000000. */
DWORD
dwPasswordSize
;
/* A Guess. This is 0x00000000. */
/* This might be the name server DPID which
is needed for the reply */
...
...
@@ -131,24 +148,50 @@ typedef struct tagDPMSG_NEWPLAYERIDREPLY
DPMSG_SENDENVELOPE
envelope
;
DPID
dpidNewPlayerId
;
#if 1
/* 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 */
#endif
}
DPMSG_NEWPLAYERIDREPLY
,
*
LPDPMSG_NEWPLAYERIDREPLY
;
typedef
const
DPMSG_NEWPLAYERIDREPLY
*
LPCDPMSG_NEWPLAYERIDREPLY
;
#include "poppack.h"
typedef
struct
tagDPMSG_FORWARDADDPLAYER
{
DPMSG_SENDENVELOPE
envelope
;
DWORD
unknown
;
/* 0 */
HRESULT
DP_MSG_SendRequestPlayerId
(
IDirectPlay2AImpl
*
This
,
DWORD
dwFlags
,
LPDPID
lpdipidAllocatedId
);
DPID
dpidAppServer
;
/* Remote application server id */
DWORD
unknown2
[
5
];
/* ??? */
#define FORWARDADDPLAYER_UNKNOWN2_INIT { 0x0, 0x1c, 0x6c, 0x50, 0x9 }
DPID
dpidAppServer2
;
/* Remote application server id again !? */
DWORD
unknown3
[
5
];
/* ??? */
#define FORWARDADDPLAYER_UNKNOWN3_INIT { 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 infront of the two 0x??090002 entries changes! */
#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
/* FIXME: I don't think that this is a needed method
*/
HRESULT
DP_MSG_OpenStream
(
IDirectPlay2AImpl
*
This
);
BYTE
unknown5
[
2
];
/* 2 bytes at the end. This may be a part of something!
*/
#define FORWARDADDPLAYER_UNKNOWN5_INIT { 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
dlls/dplayx/dplobby.c
View file @
10a04e74
...
...
@@ -343,15 +343,15 @@ static HRESULT WINAPI DPL_QueryInterface
TRACE
(
"(%p)->(%s,%p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppvObj
);
*
ppvObj
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
IDirectPlayLobbyWImpl
)
);
sizeof
(
*
This
)
);
if
(
*
ppvObj
==
NULL
)
{
return
DPERR_OUTOFMEMORY
;
}
CopyMemory
(
*
ppvObj
,
iface
,
sizeof
(
IDirectPlayLobbyWImpl
)
);
(
*
(
IDirectPlayLobby
W
Impl
**
)
ppvObj
)
->
ulInterfaceRef
=
0
;
CopyMemory
(
*
ppvObj
,
This
,
sizeof
(
*
This
)
);
(
*
(
IDirectPlayLobby
A
Impl
**
)
ppvObj
)
->
ulInterfaceRef
=
0
;
if
(
IsEqualGUID
(
&
IID_IDirectPlayLobby
,
riid
)
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment