Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

498 lines
19 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Server.cpp
  6. * Content: DNET server interface routines
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/21/99 mjn Created
  12. * 12/23/99 mjn Hand all NameTable update sends from Host to worker thread
  13. * 12/28/99 mjn Moved Async Op stuff to Async.h
  14. * 01/06/00 mjn Moved NameTable stuff to NameTable.h
  15. * 01/14/00 mjn Added pvUserContext to Host API call
  16. * 01/16/00 mjn Moved User callback stuff to User.h
  17. * 01/22/00 mjn Implemented DestroyClient in API
  18. * 01/28/00 mjn Implemented ReturnBuffer in API
  19. * 02/01/00 mjn Implemented GetCaps and SetCaps in API
  20. * 02/01/00 mjn Implement Player/Group context values
  21. * 02/15/00 mjn Use INFO flags in SetServerInfo and return context in GetClientInfo
  22. * 02/17/00 mjn Implemented GetPlayerContext and GetGroupContext
  23. * 03/17/00 rmt Added new caps functions
  24. * 04/04/00 mjn Added TerminateSession to API
  25. * 04/05/00 mjn Modified DestroyClient
  26. * 04/06/00 mjn Added GetClientAddress to API
  27. * mjn Added GetHostAddress to API
  28. * 04/18/00 rmt Added additional paramtere validation
  29. * 04/19/00 mjn SendTo API call accepts a range of DPN_BUFFER_DESCs and a count
  30. * 04/24/00 mjn Updated Group and Info operations to use CAsyncOp's
  31. * 05/31/00 mjn Added operation specific SYNC flags
  32. * 06/23/00 mjn Removed dwPriority from SendTo() API call
  33. * 07/09/00 mjn Cleaned up DN_SetServerInfo()
  34. * 07/09/00 rmt Bug #38323 - RegisterLobby needs a DPNHANDLE parameter.
  35. * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  36. * 10/11/00 mjn Take locks for CNameTableEntry::PackInfo()
  37. * mjn Check deleted list in DN_GetClientInfo()
  38. * 01/22/01 mjn Check closing instead of disconnecting in DN_GetClientInfo()
  39. * 07/24/01 mjn Added DPNBUILD_NOPARAMVAL compile flag
  40. *@@END_MSINTERNAL
  41. *
  42. ***************************************************************************/
  43. #include "dncorei.h"
  44. #ifndef DPNBUILD_NOSERVER
  45. //**********************************************************************
  46. // Constant definitions
  47. //**********************************************************************
  48. //**********************************************************************
  49. // Macro definitions
  50. //**********************************************************************
  51. //**********************************************************************
  52. // Structure definitions
  53. //**********************************************************************
  54. //**********************************************************************
  55. // Variable definitions
  56. //**********************************************************************
  57. typedef STDMETHODIMP ServerQueryInterface( IDirectPlay8Server *pInterface, DP8REFIID riid, LPVOID *ppvObj );
  58. typedef STDMETHODIMP_(ULONG) ServerAddRef( IDirectPlay8Server *pInterface );
  59. typedef STDMETHODIMP_(ULONG) ServerRelease( IDirectPlay8Server *pInterface );
  60. typedef STDMETHODIMP ServerInitialize( IDirectPlay8Server *pInterface, LPVOID const lpvUserContext, const PFNDPNMESSAGEHANDLER lpfn, const DWORD dwFlags );
  61. typedef STDMETHODIMP ServerEnumServiceProviders( IDirectPlay8Server *pInterface,const GUID *const pguidServiceProvider,const GUID *const pguidApplication,DPN_SERVICE_PROVIDER_INFO *const pSPInfoBuffer,DWORD *const pcbEnumData,DWORD *const pcReturned,const DWORD dwFlags);
  62. typedef STDMETHODIMP ServerCancelAsyncOperation( IDirectPlay8Server *pInterface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags );
  63. typedef STDMETHODIMP ServerGetSendQueueInfo( IDirectPlay8Server *pInterface, const DPNID dpnid,DWORD *const lpdwNumMsgs, DWORD *const lpdwNumBytes, const DWORD dwFlags );
  64. typedef STDMETHODIMP ServerGetApplicationDesc( IDirectPlay8Server *pInterface,DPN_APPLICATION_DESC *const pAppDescBuffer,DWORD *const lpcbDataSize,const DWORD dwFlags );
  65. typedef STDMETHODIMP ServerSetApplicationDesc( IDirectPlay8Server *pInterface, const DPN_APPLICATION_DESC *const lpad, const DWORD dwFlags );
  66. typedef STDMETHODIMP ServerGetHostAddress( IDirectPlay8Server *pInterface, IDirectPlay8Address **const prgpAddress, DWORD *const pcAddress,const DWORD dwFlags);
  67. typedef STDMETHODIMP ServerHost( IDirectPlay8Server *pInterface,const DPN_APPLICATION_DESC *const pdnAppDesc,IDirectPlay8Address **const prgpDeviceInfo,const DWORD cDeviceInfo,const DPN_SECURITY_DESC *const pdnSecurity,const DPN_SECURITY_CREDENTIALS *const pdnCredentials,void *const pvPlayerContext,const DWORD dwFlags);
  68. typedef STDMETHODIMP ServerSendTo( IDirectPlay8Server *pInterface, const DPNID dnid, const DPN_BUFFER_DESC *const prgBufferDesc,const DWORD cBufferDesc,const DWORD dwTimeOut, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
  69. typedef STDMETHODIMP ServerCreateGroup( IDirectPlay8Server *pInterface, const DPN_GROUP_INFO *const pdpnGroupInfo,void *const pvGroupContext,void *const pvAsyncContext,DPNHANDLE *const phAsyncHandle,const DWORD dwFlags);
  70. typedef STDMETHODIMP ServerDestroyGroup( IDirectPlay8Server *pInterface, const DPNID idGroup,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
  71. typedef STDMETHODIMP ServerAddClientToGroup( IDirectPlay8Server *pInterface, const DPNID idGroup, const DPNID idClient,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
  72. typedef STDMETHODIMP ServerRemoveClientFromGroup( IDirectPlay8Server *pInterface, const DPNID idGroup, const DPNID idClient,PVOID const pvUserContext,DPNHANDLE *const lpAsyncHandle,const DWORD dwFlags);
  73. typedef STDMETHODIMP ServerSetGroupInfo(IDirectPlay8Server *pInterface, const DPNID dpnid,DPN_GROUP_INFO *const pdpnGroupInfo,PVOID const pvAsyncContext,DPNHANDLE *const phAsyncHandle, const DWORD dwFlags);
  74. typedef STDMETHODIMP ServerGetGroupInfo(IDirectPlay8Server *pInterface, const DPNID dpnid,DPN_GROUP_INFO *const pdpnGroupInfo,DWORD *const pdwSize,const DWORD dwFlags);
  75. typedef STDMETHODIMP ServerEnumClientsAndGroups( IDirectPlay8Server *pInterface, DPNID *const lprgdnid, DWORD *const lpcdnid, const DWORD dwFlags );
  76. typedef STDMETHODIMP ServerEnumGroupMembers( IDirectPlay8Server *pInterface, const DPNID dnid, DPNID *const lprgdnid, DWORD *const lpcdnid, const DWORD dwFlags );
  77. typedef STDMETHODIMP ServerClose( IDirectPlay8Server *pInterface,const DWORD dwFlags);
  78. typedef STDMETHODIMP ServerDestroyClient( IDirectPlay8Server *pInterface,const DPNID dnid,const void *const pvDestroyData,const DWORD dwDestroyDataSize,const DWORD dwFlags);
  79. typedef STDMETHODIMP ServerReturnBuffer( IDirectPlay8Server *pInterface, const DPNHANDLE hBufferHandle,const DWORD dwFlags);
  80. typedef STDMETHODIMP ServerGetCaps(IDirectPlay8Server *pInterface,DPN_CAPS *const pdnCaps,const DWORD dwFlags);
  81. typedef STDMETHODIMP ServerSetCaps(IDirectPlay8Server *pInterface,const DPN_CAPS *const pdnCaps,const DWORD dwFlags);
  82. typedef STDMETHODIMP ServerGetPlayerContext(IDirectPlay8Server *pInterface,const DPNID dpnid,PVOID *const ppvPlayerContext,const DWORD dwFlags);
  83. typedef STDMETHODIMP ServerGetGroupContext(IDirectPlay8Server *pInterface,const DPNID dpnid,PVOID *const ppvGroupContext,const DWORD dwFlags);
  84. typedef STDMETHODIMP ServerSetSPCaps(IDirectPlay8Server *pInterface,const GUID * const pguidSP, const DPN_SP_CAPS *const pdpspCaps, const DWORD dwFlags );
  85. typedef STDMETHODIMP ServerGetSPCaps(IDirectPlay8Server *pInterface,const GUID * const pguidSP, DPN_SP_CAPS *const pdpspCaps,const DWORD dwFlags);
  86. typedef STDMETHODIMP ServerGetConnectionInfo(IDirectPlay8Server *pInterface,const DPNID dpnid, DPN_CONNECTION_INFO *const pdpConnectionInfo,const DWORD dwFlags);
  87. typedef STDMETHODIMP ServerRegisterLobby(IDirectPlay8Server *pInterface,const DPNHANDLE dpnHandle,IDirectPlay8LobbiedApplication *const pIDP8LobbiedApplication,const DWORD dwFlags);
  88. //
  89. // VTable for server interface
  90. //
  91. IDirectPlay8ServerVtbl DN_ServerVtbl =
  92. {
  93. (ServerQueryInterface*) DN_QueryInterface,
  94. (ServerAddRef*) DN_AddRef,
  95. (ServerRelease*) DN_Release,
  96. (ServerInitialize*) DN_Initialize,
  97. (ServerEnumServiceProviders*) DN_EnumServiceProviders,
  98. (ServerCancelAsyncOperation*) DN_CancelAsyncOperation,
  99. (ServerGetSendQueueInfo*) DN_GetSendQueueInfo,
  100. (ServerGetApplicationDesc*) DN_GetApplicationDesc,
  101. DN_SetServerInfo,
  102. DN_GetClientInfo,
  103. DN_GetClientAddress,
  104. (ServerGetHostAddress*) DN_GetHostAddress,
  105. (ServerSetApplicationDesc*) DN_SetApplicationDesc,
  106. (ServerHost*) DN_Host,
  107. (ServerSendTo*) DN_SendTo,
  108. (ServerCreateGroup*) DN_CreateGroup,
  109. (ServerDestroyGroup*) DN_DestroyGroup,
  110. (ServerAddClientToGroup*) DN_AddClientToGroup,
  111. (ServerRemoveClientFromGroup*) DN_RemoveClientFromGroup,
  112. (ServerSetGroupInfo*) DN_SetGroupInfo,
  113. (ServerGetGroupInfo*) DN_GetGroupInfo,
  114. (ServerEnumClientsAndGroups*) DN_EnumClientsAndGroups,
  115. (ServerEnumGroupMembers*) DN_EnumGroupMembers,
  116. (ServerClose*) DN_Close,
  117. (ServerDestroyClient*) DN_DestroyPlayer,
  118. (ServerReturnBuffer*) DN_ReturnBuffer,
  119. (ServerGetPlayerContext*) DN_GetPlayerContext,
  120. (ServerGetGroupContext*) DN_GetGroupContext,
  121. (ServerGetCaps*) DN_GetCaps,
  122. (ServerSetCaps*) DN_SetCaps,
  123. (ServerSetSPCaps*) DN_SetSPCaps,
  124. (ServerGetSPCaps*) DN_GetSPCaps,
  125. (ServerGetConnectionInfo*) DN_GetConnectionInfo,
  126. (ServerRegisterLobby*) DN_RegisterLobby
  127. };
  128. //**********************************************************************
  129. // Function prototypes
  130. //**********************************************************************
  131. //**********************************************************************
  132. // Function definitions
  133. //**********************************************************************
  134. // DN_SetServerInfo
  135. //
  136. // Set the info for the server and propagate to client players
  137. #undef DPF_MODNAME
  138. #define DPF_MODNAME "DN_SetServerInfo"
  139. STDMETHODIMP DN_SetServerInfo(IDirectPlay8Server *pInterface,
  140. const DPN_PLAYER_INFO *const pdpnPlayerInfo,
  141. PVOID const pvAsyncContext,
  142. DPNHANDLE *const phAsyncHandle,
  143. const DWORD dwFlags)
  144. {
  145. DIRECTNETOBJECT *pdnObject;
  146. HRESULT hResultCode;
  147. DPNHANDLE hAsyncOp;
  148. PWSTR pwszName;
  149. DWORD dwNameSize;
  150. PVOID pvData;
  151. DWORD dwDataSize;
  152. CNameTableEntry *pLocalPlayer;
  153. BOOL fConnected;
  154. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pdpnPlayerInfo [0x%p], pvAsyncContext [0x%p], phAsyncHandle [0x%p], dwFlags [0x%lx]",
  155. pInterface,pdpnPlayerInfo,pvAsyncContext,phAsyncHandle,dwFlags);
  156. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  157. DNASSERT(pdnObject != NULL);
  158. #ifndef DPNBUILD_NOPARAMVAL
  159. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  160. {
  161. if( FAILED( hResultCode = DN_ValidateSetServerInfo( pInterface , pdpnPlayerInfo, pvAsyncContext, phAsyncHandle, dwFlags ) ) )
  162. {
  163. DPFX(DPFPREP, 0, "Error validating setserverinfo params hr=[0x%lx]", hResultCode );
  164. DPF_RETURN( hResultCode );
  165. }
  166. }
  167. #endif // !DPNBUILD_NOPARAMVAL
  168. // Check to ensure message handler registered
  169. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
  170. {
  171. DPFERR( "Object is not initialized" );
  172. DPF_RETURN(DPNERR_UNINITIALIZED);
  173. }
  174. pLocalPlayer = NULL;
  175. if ((pdpnPlayerInfo->dwInfoFlags & DPNINFO_NAME) && (pdpnPlayerInfo->pwszName))
  176. {
  177. pwszName = pdpnPlayerInfo->pwszName;
  178. dwNameSize = (wcslen(pwszName) + 1) * sizeof(WCHAR);
  179. }
  180. else
  181. {
  182. pwszName = NULL;
  183. dwNameSize = 0;
  184. }
  185. if ((pdpnPlayerInfo->dwInfoFlags & DPNINFO_DATA) && (pdpnPlayerInfo->pvData) && (pdpnPlayerInfo->dwDataSize))
  186. {
  187. pvData = pdpnPlayerInfo->pvData;
  188. dwDataSize = pdpnPlayerInfo->dwDataSize;
  189. }
  190. else
  191. {
  192. pvData = NULL;
  193. dwDataSize = 0;
  194. }
  195. //
  196. // If we are connected, we will update our entry.
  197. // Otherwise, we will just update the DefaultPlayer.
  198. //
  199. DNEnterCriticalSection(&pdnObject->csDirectNetObject);
  200. if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED)
  201. {
  202. fConnected = TRUE;
  203. }
  204. else
  205. {
  206. fConnected = FALSE;
  207. }
  208. DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
  209. if (fConnected)
  210. {
  211. if ((hResultCode = pdnObject->NameTable.GetLocalPlayerRef( &pLocalPlayer )) != DPN_OK)
  212. {
  213. DPFERR( "Could not get local player reference" );
  214. DisplayDNError(0,hResultCode);
  215. goto Failure;
  216. }
  217. DPFX(DPFPREP, 3,"Host is updating server info");
  218. hResultCode = DNHostUpdateInfo( pdnObject,
  219. pLocalPlayer->GetDPNID(),
  220. pwszName,
  221. dwNameSize,
  222. pvData,
  223. dwDataSize,
  224. pdpnPlayerInfo->dwInfoFlags,
  225. pvAsyncContext,
  226. pLocalPlayer->GetDPNID(),
  227. 0,
  228. &hAsyncOp,
  229. dwFlags );
  230. if ((hResultCode != DPN_OK) && (hResultCode != DPNERR_PENDING))
  231. {
  232. DPFERR("Could not request host to update group");
  233. }
  234. else
  235. {
  236. if (!(dwFlags & DPNSETSERVERINFO_SYNC))
  237. {
  238. DPFX(DPFPREP, 3,"Async Handle [0x%lx]",hAsyncOp);
  239. *phAsyncHandle = hAsyncOp;
  240. //
  241. // Release Async HANDLE since this operation has already completed (!)
  242. //
  243. CAsyncOp* pAsyncOp;
  244. if (SUCCEEDED(pdnObject->HandleTable.Destroy( hAsyncOp, (PVOID*)&pAsyncOp )))
  245. {
  246. // Release the HandleTable reference
  247. pAsyncOp->Release();
  248. }
  249. pAsyncOp = NULL;
  250. hAsyncOp = 0;
  251. }
  252. }
  253. pLocalPlayer->Release();
  254. pLocalPlayer = NULL;
  255. }
  256. else
  257. {
  258. DNASSERT(pdnObject->NameTable.GetDefaultPlayer() != NULL);
  259. // This function takes the lock internally
  260. pdnObject->NameTable.GetDefaultPlayer()->UpdateEntryInfo(pwszName,dwNameSize,pvData,dwDataSize,pdpnPlayerInfo->dwInfoFlags, FALSE);
  261. hResultCode = DPN_OK;
  262. }
  263. Exit:
  264. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  265. return(hResultCode);
  266. Failure:
  267. if (pLocalPlayer)
  268. {
  269. pLocalPlayer->Release();
  270. pLocalPlayer = NULL;
  271. }
  272. goto Exit;
  273. }
  274. // DN_GetClientInfo
  275. //
  276. // Retrieve client info from the local nametable.
  277. #undef DPF_MODNAME
  278. #define DPF_MODNAME "DN_GetClientInfo"
  279. STDMETHODIMP DN_GetClientInfo(IDirectPlay8Server *pInterface,
  280. const DPNID dpnid,
  281. DPN_PLAYER_INFO *const pdpnPlayerInfo,
  282. DWORD *const pdwSize,
  283. const DWORD dwFlags)
  284. {
  285. DIRECTNETOBJECT *pdnObject;
  286. CNameTableEntry *pNTEntry;
  287. CPackedBuffer packedBuffer;
  288. HRESULT hResultCode;
  289. DPFX(DPFPREP, 2,"Parameters: dpnid [0x%lx], pdpnPlayerInfo [0x%p], dwFlags [0x%lx]",
  290. dpnid,pdpnPlayerInfo,dwFlags);
  291. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  292. DNASSERT(pdnObject != NULL);
  293. #ifndef DPNBUILD_NOPARAMVAL
  294. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  295. {
  296. if( FAILED( hResultCode = DN_ValidateGetClientInfo( pInterface , dpnid, pdpnPlayerInfo, pdwSize, dwFlags ) ) )
  297. {
  298. DPFX(DPFPREP, 0, "Error validating getclientinfo params hr=[0x%lx]", hResultCode );
  299. DPF_RETURN( hResultCode );
  300. }
  301. }
  302. #endif // DPNBUILD_NOPARAMVAL
  303. // Check to ensure message handler registered
  304. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
  305. {
  306. DPFERR( "Object is not initialized" );
  307. DPF_RETURN(DPNERR_UNINITIALIZED);
  308. }
  309. if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
  310. {
  311. DPFERR("Object is connecting / starting to host" );
  312. DPF_RETURN(DPNERR_CONNECTING);
  313. }
  314. if ( !(pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTED | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) )
  315. {
  316. DPFERR("You must be connected / disconnecting to use this function" );
  317. DPF_RETURN(DPNERR_NOCONNECTION);
  318. }
  319. pNTEntry = NULL;
  320. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry)) != DPN_OK)
  321. {
  322. DPFERR("Could not retrieve name table entry");
  323. DisplayDNError(0,hResultCode);
  324. //
  325. // Try deleted list
  326. //
  327. if ((hResultCode = pdnObject->NameTable.FindDeletedEntry(dpnid,&pNTEntry)) != DPN_OK)
  328. {
  329. DPFERR("Could not find player in deleted list either");
  330. DisplayDNError(0,hResultCode);
  331. hResultCode = DPNERR_INVALIDPLAYER;
  332. goto Failure;
  333. }
  334. }
  335. packedBuffer.Initialize(pdpnPlayerInfo,*pdwSize);
  336. pNTEntry->Lock();
  337. if (pNTEntry->IsGroup() || pNTEntry->IsHost())
  338. {
  339. DPFERR( "Specified ID is invalid" );
  340. pNTEntry->Unlock();
  341. hResultCode = DPNERR_INVALIDPLAYER;
  342. goto Failure;
  343. }
  344. hResultCode = pNTEntry->PackInfo(&packedBuffer);
  345. pNTEntry->Unlock();
  346. pNTEntry->Release();
  347. pNTEntry = NULL;
  348. if ((hResultCode == DPN_OK) || (hResultCode == DPNERR_BUFFERTOOSMALL))
  349. {
  350. *pdwSize = packedBuffer.GetSizeRequired();
  351. }
  352. Exit:
  353. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  354. return(hResultCode);
  355. Failure:
  356. if (pNTEntry)
  357. {
  358. pNTEntry->Release();
  359. pNTEntry = NULL;
  360. }
  361. goto Exit;
  362. }
  363. #undef DPF_MODNAME
  364. #define DPF_MODNAME "DN_GetClientAddress"
  365. STDMETHODIMP DN_GetClientAddress(IDirectPlay8Server *pInterface,
  366. const DPNID dpnid,
  367. IDirectPlay8Address **const ppAddress,
  368. const DWORD dwFlags)
  369. {
  370. DIRECTNETOBJECT *pdnObject;
  371. CNameTableEntry *pNTEntry;
  372. IDirectPlay8Address *pAddress;
  373. HRESULT hResultCode;
  374. DPFX(DPFPREP, 2,"Parameters : pInterface [0x%p], dpnid [0x%lx], ppAddress [0x%p], dwFlags [0x%lx]",
  375. pInterface,dpnid,ppAddress,dwFlags);
  376. pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface);
  377. DNASSERT(pdnObject != NULL);
  378. #ifndef DPNBUILD_NOPARAMVAL
  379. if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION )
  380. {
  381. if( FAILED( hResultCode = DN_ValidateGetClientAddress( pInterface , dpnid, ppAddress, dwFlags ) ) )
  382. {
  383. DPFX(DPFPREP, 0, "Error validating getclientaddress params hr=[0x%lx]", hResultCode );
  384. DPF_RETURN( hResultCode );
  385. }
  386. }
  387. #endif // DPNBUILD_NOPARAMVAL
  388. // Check to ensure message handler registered
  389. if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED))
  390. {
  391. DPFERR( "Object is not initialized" );
  392. DPF_RETURN(DPNERR_UNINITIALIZED);
  393. }
  394. if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING )
  395. {
  396. DPFERR("Object is connecting / starting to host" );
  397. DPF_RETURN(DPNERR_CONNECTING);
  398. }
  399. if ( !(pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTED | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) )
  400. {
  401. DPFERR("You must be connected / disconnecting to use this function" );
  402. DPF_RETURN(DPNERR_NOCONNECTION);
  403. }
  404. pNTEntry = NULL;
  405. pAddress = NULL;
  406. if ((hResultCode = pdnObject->NameTable.FindEntry(dpnid,&pNTEntry)) != DPN_OK)
  407. {
  408. DPFERR("Could not find NameTableEntry");
  409. DisplayDNError(0,hResultCode);
  410. hResultCode = DPNERR_INVALIDPLAYER;
  411. goto Failure;
  412. }
  413. if ((pNTEntry->GetAddress() == NULL) || (pNTEntry->IsGroup()) || !pNTEntry->IsAvailable())
  414. {
  415. DPFERR( "Specified player is not valid" );
  416. hResultCode = DPNERR_INVALIDPLAYER;
  417. goto Failure;
  418. }
  419. hResultCode = IDirectPlay8Address_Duplicate(pNTEntry->GetAddress(),ppAddress);
  420. pNTEntry->Release();
  421. pNTEntry = NULL;
  422. Exit:
  423. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  424. return(hResultCode);
  425. Failure:
  426. if (pNTEntry)
  427. {
  428. pNTEntry->Release();
  429. pNTEntry = NULL;
  430. }
  431. goto Exit;
  432. }
  433. #endif // DPNBUILD_NOSERVER