large IDirectPlay8Address patch
Rob Crittenden <[email protected]>
| Newsgroups | gmane.comp.emulators.winex.devel |
|---|---|
| Message-ID | <[email protected]> |
Attached is a patch that fills in some holes in the IDirectPlay8Address interface. I don't have any games that seem to use this functionality so I tested as best I could with the first 3 DirectPlay tutorials in the DX9 SDK. This includes my version of the patch that sparr recently submitted. It was easier for me to just leave this in. I also added a stub for DirectPlay8Peer_Host() to get one of the samples working. I found what may be 2 bugs in DirectX 9: 1. GetUserData() is supposed to return the size of the saved object in pdwBufferSize. In my testing on WinXP it returns the size of the buffer passed in rather than the size returned. 2. GetNumComponents() is supposed to be indexed from 0 but it isn't. It also reports the # of components + 1 (perhaps due to the bogus 0 entry). In windows I tried to fetch position 0 and it was undefined, go figure. I've kept my implementation compatible with how it tested on WinXP. rob
dplay.diff
(text/plain, 13.2 KB)
Index: address.c
===================================================================
RCS file: /cvsroot/winex/dlls/dpnet/address.c,v
retrieving revision 1.11
diff -u -r1.11 address.c
--- address.c 1 Apr 2004 12:09:26 -0000 1.11
+++ address.c 25 May 2004 02:33:23 -0000
@@ -67,6 +67,15 @@
if (This->spData && !This->spDataRelease) FIXME("no release for data @ %p\n", This->spData);
if (This->spData) This->spDataRelease(This->spData);
HeapFree(GetProcessHeap(), 0, This->url);
+ while (This->component != NULL) {
+ struct AddressComponent * component = This->component;
+ This->component = This->component->next;
+ HeapFree(GetProcessHeap(), 0, component->pwszName);
+ HeapFree(GetProcessHeap(), 0, component->lpvData);
+ HeapFree(GetProcessHeap(), 0, component);
+ }
+ if (This->dwDataSize > 0)
+ HeapFree(GetProcessHeap(), 0, This->pvUserData);
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
@@ -190,6 +199,46 @@
return S_OK;
}
+HRESULT WINAPI DirectPlay8Address_GetSP(PDIRECTPLAY8ADDRESS iface, GUID *pguidSP)
+{
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)\n", iface);
+ if (IsEqualGUID(&This->guidSP, &IID_IUnknown)) {
+ return DPNERR_DOESNOTEXIST;
+ }
+ memcpy(pguidSP, &This->guidSP, sizeof(GUID));
+ return S_OK;
+}
+
+HRESULT WINAPI DirectPlay8Address_GetUserData(PDIRECTPLAY8ADDRESS iface,
+ void *pvUserData,
+ PDWORD pdwBufferSize
+)
+{
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)\n", iface);
+
+ if (pvUserData == NULL && pdwBufferSize == 0) {
+ *pdwBufferSize = This->dwDataSize;
+ return DPNERR_BUFFERTOOSMALL;
+ } else {
+ if (*pdwBufferSize < This->dwDataSize) {
+ *pdwBufferSize = This->dwDataSize;
+ return DPNERR_BUFFERTOOSMALL;
+ }
+ memcpy(pvUserData, This->pvUserData, This->dwDataSize);
+ /* FIXME: in my testing DX 9 doesn't actually set this properly. It remains
+ * the size passed in!? */
+#if 0
+ *pdwBufferSize = This->dwDataSize;
+#endif
+ }
+
+ return S_OK;
+}
+
HRESULT WINAPI DirectPlay8Address_SetSP(PDIRECTPLAY8ADDRESS iface, const GUID *const pguidSP)
{
ICOM_THIS(IDirectPlay8AddressImpl, iface);
@@ -199,6 +248,184 @@
return S_OK;
}
+HRESULT WINAPI DirectPlay8Address_SetUserData(PDIRECTPLAY8ADDRESS iface,
+ const void *const pvUserData,
+ const DWORD dwDataSize)
+{
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)\n", iface);
+
+ if (pvUserData == NULL && dwDataSize != 0)
+ return DPNERR_NOTALLOWED;
+
+ if (This->dwDataSize > 0)
+ HeapFree(GetProcessHeap(), 0, This->pvUserData);
+ This->pvUserData = HeapAlloc(GetProcessHeap(), 0, dwDataSize);
+ memcpy(This->pvUserData, (void *)pvUserData, dwDataSize);
+ This->dwDataSize = dwDataSize;
+
+ return S_OK;
+}
+
+HRESULT WINAPI DirectPlay8Address_GetNumComponents(PDIRECTPLAY8ADDRESS iface, PDWORD pdwNumComponents)
+{
+ DWORD count = 1; /* DX9 returns the # of components +1 for some reason */
+ struct AddressComponent *c;
+
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%p)\n", iface, pdwNumComponents);
+
+ c = This->component;
+
+ while (c != NULL) {
+ count++;
+ c = c->next;
+ }
+
+ TRACE("(%p)->(%ld)\n", iface, count);
+
+ *pdwNumComponents = count;
+
+ return S_OK;
+}
+
+HRESULT WINAPI DirectPlay8Address_GetComponentByName(PDIRECTPLAY8ADDRESS iface,
+ const WCHAR *const pwszName,
+ void *pvBuffer,
+ PDWORD pdwBufferSize,
+ PDWORD pdwDataType)
+{
+ struct AddressComponent *component;
+ HRESULT ret = DPNERR_DOESNOTEXIST;
+
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%s, %ld)\n", iface, debugstr_w(pwszName), *pdwBufferSize);
+
+ component = This->component;
+
+ while (component != NULL) {
+ if (!strcmpW(component->pwszName, pwszName)) {
+ if (pdwBufferSize == 0) {
+ ret = DPNERR_BUFFERTOOSMALL;
+ } else if (*pdwBufferSize >= component->dwDataSize) {
+ *pdwDataType = component->dwDataType;
+ memcpy(pvBuffer, component->lpvData, component->dwDataSize);
+ ret = S_OK;
+ } else {
+ ret = DPNERR_BUFFERTOOSMALL;
+ }
+ *pdwBufferSize = component->dwDataSize;
+ }
+ component = component->next;
+ }
+
+ TRACE("returning %lx\n", ret);
+ return ret;
+}
+
+HRESULT WINAPI DirectPlay8Address_GetComponentByIndex(PDIRECTPLAY8ADDRESS iface,
+ const DWORD dwComponentID,
+ WCHAR *pwszName,
+ PDWORD pdwNameLen,
+ void *pvBuffer,
+ PDWORD pdwBufferSize,
+ PDWORD pdwDataType
+)
+{
+ struct AddressComponent *component;
+ HRESULT ret = DPNERR_DOESNOTEXIST;
+ int i = 0;
+
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%ld, %ld, %ld)\n", iface, dwComponentID, *pdwNameLen, *pdwBufferSize);
+
+ component = This->component;
+
+ while (component != NULL && i < dwComponentID - 1) {
+ i++;
+ component = component->next;
+ }
+ if (component) {
+ if (*pdwBufferSize >= component->dwDataSize && *pdwNameLen >= strlenW(component->pwszName)) {
+ *pdwDataType = component->dwDataType;
+ memcpy(pvBuffer, component->lpvData, component->dwDataSize);
+ strcpyW(pwszName, component->pwszName);
+ ret = S_OK;
+ } else {
+ ret = DPNERR_BUFFERTOOSMALL;
+ }
+ *pdwBufferSize = component->dwDataSize;
+ *pdwNameLen = strlenW(component->pwszName);
+ } else
+
+ TRACE("returning %lx\n", ret);
+
+ return ret;
+}
+
+HRESULT WINAPI DirectPlay8Address_AddComponent(PDIRECTPLAY8ADDRESS iface,
+ const WCHAR *const pwszName,
+ const void *const lpvData,
+ const DWORD dwDataSize,
+ const DWORD dwDataType)
+{
+ struct AddressComponent *component;
+
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%s, 0x%08lx, 0x%08lx)\n", iface, debugstr_w(pwszName), dwDataSize, dwDataType);
+
+ component = HeapAlloc(GetProcessHeap(), 0, sizeof(struct AddressComponent));
+ component->pwszName = HeapAlloc(GetProcessHeap(), 0, strlenW(pwszName)+1);
+ component->lpvData = HeapAlloc(GetProcessHeap(), 0, dwDataSize);
+ component->dwDataSize = dwDataSize;
+ component->dwDataType = dwDataType;
+ strcpyW(component->pwszName, pwszName);
+ memcpy(component->lpvData, lpvData, dwDataSize);
+ component->next = NULL;
+
+ /* Put new element onto the end of the list. This is necessary so the user
+ * can call GetComponentByIndex and expect the component to be stored in
+ * the order it was added. */
+ if (This->component == NULL) {
+ This->component = component;
+ } else {
+ struct AddressComponent *temp;
+ temp = This->component;
+ while (temp->next != NULL) {
+ temp = temp->next;
+ }
+ temp->next = component;
+ }
+
+ return S_OK;
+}
+
+HRESULT WINAPI DirectPlay8Address_SetDevice(PDIRECTPLAY8ADDRESS iface, const GUID *const pguidDevice)
+{
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%s)\n", iface, debugstr_guid(pguidDevice));
+ memcpy(&This->guidDevice, pguidDevice, sizeof(GUID));
+ return S_OK;
+}
+
+HRESULT WINAPI DirectPlay8Address_GetDevice(PDIRECTPLAY8ADDRESS iface, GUID *pguidDevice)
+{
+ ICOM_THIS(IDirectPlay8AddressImpl, iface);
+
+ TRACE("(%p)->(%s)\n", iface, debugstr_guid(pguidDevice));
+ if (IsEqualGUID(&This->guidDevice, &IID_IUnknown)) {
+ return DPNERR_DOESNOTEXIST;
+ }
+ memcpy(pguidDevice, &This->guidDevice, sizeof(GUID));
+ return S_OK;
+}
+
HRESULT DPNET_CreateDirectPlay8Address(IUnknown *pOuter, REFIID riid, LPVOID *ppobj)
{
IDirectPlay8AddressImpl *ipDP8A;
@@ -210,6 +437,11 @@
ICOM_VTBL(ipDP8A) = &directPlay8AddressVT;
ipDP8A->lpVtbl2 = &directPlay8AddressIPVT;
IDirectPlay8Address_AddRef((IDirectPlay8Address *)ipDP8A);
+ ipDP8A->component = NULL;
+ ipDP8A->pvUserData = NULL;
+ ipDP8A->dwDataSize = 0;
+ ipDP8A->guidDevice = IID_IUnknown;
+ ipDP8A->guidSP = IID_IUnknown;
TRACE("Created new object: %p\n", ipDP8A);
hr = IDirectPlay8Address_QueryInterface((IDirectPlay8Address *)ipDP8A, riid, ppobj);
IDirectPlay8Address_Release((IDirectPlay8Address *)ipDP8A);
@@ -259,17 +491,17 @@
(void*)0xdead7009, /* Clear */
DirectPlay8Address_GetURLW,
(void*)0xdead700b, /* GetURLA */
- (void*)0xdead700c, /* GetSP */
- (void*)0xdead700d, /* GetUserData */
+ DirectPlay8Address_GetSP,
+ DirectPlay8Address_GetUserData,
DirectPlay8Address_SetSP,
- (void*)0xdead700f, /* SetUserData */
- (void*)0xdead7010, /* GetNumComponents */
- (void*)0xdead7011, /* GetComponentByName */
- (void*)0xdead7012, /* GetComponentByIndex */
- (void*)0xdead7012, /* AddComponent */
- (void*)0xdead7013, /* SetDevice */
- (void*)0xdead7014, /* GetDevice */
- (void*)0xdead7015 /* BuildFromDirectPlay4Address */
+ DirectPlay8Address_SetUserData,
+ DirectPlay8Address_GetNumComponents,
+ DirectPlay8Address_GetComponentByName,
+ DirectPlay8Address_GetComponentByIndex,
+ DirectPlay8Address_AddComponent,
+ DirectPlay8Address_GetDevice,
+ DirectPlay8Address_SetDevice,
+ (void*)0xdead7016 /* BuildFromDirectPlay4Address */
};
static ICOM_VTABLE(IDirectPlay8AddressIP) directPlay8AddressIPVT =
Index: dplay8_private.h
===================================================================
RCS file: /cvsroot/winex/dlls/dpnet/dplay8_private.h,v
retrieving revision 1.9
diff -u -r1.9 dplay8_private.h
--- dplay8_private.h 20 Apr 2004 03:28:29 -0000 1.9
+++ dplay8_private.h 25 May 2004 02:33:24 -0000
@@ -141,6 +141,15 @@
void *dummy;
};
+struct AddressComponent
+{
+ WCHAR *pwszName;
+ void *lpvData;
+ DWORD dwDataSize;
+ DWORD dwDataType;
+ struct AddressComponent *next;
+};
+
/* a bit hacky. should be in some interface */
typedef void (*spReleaseAddressInfo)(PVOID);
/* shouldn't need to duplicate !!!! SHOULD USE URL. HACK */
@@ -154,8 +163,12 @@
DWORD ref;
/* IDriectPlay8Address / IDirectPlay8AddressIP fields */
GUID guidSP;
+ GUID guidDevice;
WCHAR *url;
+ struct AddressComponent *component;
+ void *pvUserData;
+ DWORD dwDataSize;
HANDLE hDialogMutex; /* HACK: if we are sending to this address and the
* service provider wants to show a dialogbox, it needs to
Index: peer.c
===================================================================
RCS file: /cvsroot/winex/dlls/dpnet/peer.c,v
retrieving revision 1.13
diff -u -r1.13 peer.c
--- peer.c 1 Apr 2004 12:09:26 -0000 1.13
+++ peer.c 25 May 2004 02:33:25 -0000
@@ -173,6 +173,22 @@
dwTimeOut, pvAsyncContext, phAsyncHandle, dwFlags);
}
+HRESULT WINAPI DirectPlay8Peer_Host(PDIRECTPLAY8PEER iface,
+ const DPN_APPLICATION_DESC *const pdnAppDesc,
+ IDirectPlay8Address **const prgpDeviceInfo,
+ const DWORD cDeviceInfo,
+ const DPN_SECURITY_DESC *const pdpSecurity,
+ const DPN_SECURITY_CREDENTIALS *const pdpCredentials,
+ VOID *const pvPlayerContext,
+ const DWORD dwFlags)
+{
+ ICOM_THIS(IDirectPlay8PeerImpl, iface);
+
+ TRACE("(%p)\n", iface);
+
+ return S_OK;
+}
+
static void DPNET_PEER_SetLocalPeerInfo(void *pvIface, void *pvPlayerInfo)
{
PDIRECTPLAY8PEER iface = (PDIRECTPLAY8PEER) pvIface;
@@ -264,6 +280,13 @@
return S_OK;
}
+HRESULT WINAPI DirectPlay8Peer_Close(PDIRECTPLAY8PEER iface,
+ const DWORD dwFlags)
+{
+ FIXME("(%p)->(0x%08lx): stub\n", iface, dwFlags);
+ return S_OK;
+}
+
HRESULT WINAPI DirectPlay8Peer_ReturnBuffer(PDIRECTPLAY8PEER iface, const DPNHANDLE hBufferHandle,
const DWORD dwFlags)
{
@@ -339,7 +362,7 @@
DirectPlay8Peer_Connect,
DirectPlay8Peer_SendTo,
(void*)0xdead2009, /* GetSendQueueInfo */
- (void*)0xdead200a, /* Host */
+ DirectPlay8Peer_Host, /* Host */
(void*)0xdead200b, /* GetApplicationDesc */
(void*)0xdead200c, /* SetApplicationDesc */
(void*)0xdead200d, /* CreateGroup */
@@ -354,7 +377,7 @@
DirectPlay8Peer_GetPeerInfo,
(void*)0xdead2017, /* GetPeerAddress */
(void*)0xdead2018, /* GetLocalHostAddresses */
- (void*)0xdead2019, /* Close */
+ DirectPlay8Peer_Close,
DirectPlay8Peer_EnumHosts,
(void*)0xdead201b, /* DestroyPeer */
DirectPlay8Peer_ReturnBuffer,