Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendplay.c
Go to the documentation of this file.
00001 /* Direct Play 2,3,4 Implementation 00002 * 00003 * Copyright 1998,1999,2000,2001 - Peter Hunnisett 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 #include "config.h" 00021 #include "wine/port.h" 00022 00023 #include <stdarg.h> 00024 #include <string.h> 00025 00026 #define NONAMELESSUNION 00027 #define NONAMELESSSTRUCT 00028 #include "windef.h" 00029 #include "winerror.h" 00030 #include "winbase.h" 00031 #include "winnt.h" 00032 #include "winreg.h" 00033 #include "winnls.h" 00034 #include "wine/unicode.h" 00035 #include "wine/debug.h" 00036 00037 #include "dpinit.h" 00038 #include "dplayx_global.h" 00039 #include "name_server.h" 00040 #include "dplayx_queue.h" 00041 #include "dplaysp.h" 00042 #include "dplay_global.h" 00043 00044 WINE_DEFAULT_DEBUG_CHANNEL(dplay); 00045 00046 /* FIXME: Should this be externed? */ 00047 extern HRESULT DPL_CreateCompoundAddress 00048 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, 00049 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface ); 00050 00051 00052 /* Local function prototypes */ 00053 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid ); 00054 static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid, 00055 LPDPNAME lpName, DWORD dwFlags, 00056 HANDLE hEvent, BOOL bAnsi ); 00057 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi ); 00058 static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags, 00059 LPVOID lpData, DWORD dwDataSize ); 00060 00061 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid, 00062 LPDPNAME lpName, DWORD dwFlags, 00063 DPID idParent, BOOL bAnsi ); 00064 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, 00065 LPVOID lpData, DWORD dwDataSize ); 00066 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName ); 00067 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid ); 00068 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId, 00069 DWORD dwPlayerType, 00070 LPCDPNAME lpName, 00071 DWORD dwFlags, 00072 LPVOID lpContext ); 00073 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid ); 00074 static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType, 00075 LPCDPNAME lpName, DWORD dwFlags, 00076 LPVOID lpContext ); 00077 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid ); 00078 00079 /* Forward declarations of virtual tables */ 00080 static const IDirectPlay2Vtbl directPlay2AVT; 00081 static const IDirectPlay3Vtbl directPlay3AVT; 00082 static const IDirectPlay4Vtbl directPlay4AVT; 00083 00084 static const IDirectPlay2Vtbl directPlay2WVT; 00085 static const IDirectPlay3Vtbl directPlay3WVT; 00086 static const IDirectPlay4Vtbl directPlay4WVT; 00087 00088 /* Helper methods for player/group interfaces */ 00089 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup 00090 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 00091 DPID idPlayer, BOOL bAnsi ); 00092 static HRESULT WINAPI DP_IF_CreatePlayer 00093 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer, 00094 LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, 00095 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ); 00096 static HRESULT WINAPI DP_IF_DestroyGroup 00097 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi ); 00098 static HRESULT WINAPI DP_IF_DestroyPlayer 00099 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi ); 00100 static HRESULT WINAPI DP_IF_EnumGroupPlayers 00101 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance, 00102 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 00103 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); 00104 static HRESULT WINAPI DP_IF_EnumGroups 00105 ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 00106 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 00107 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); 00108 static HRESULT WINAPI DP_IF_EnumPlayers 00109 ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 00110 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 00111 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); 00112 static HRESULT WINAPI DP_IF_GetGroupData 00113 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 00114 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi ); 00115 static HRESULT WINAPI DP_IF_GetGroupName 00116 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 00117 LPDWORD lpdwDataSize, BOOL bAnsi ); 00118 static HRESULT WINAPI DP_IF_GetPlayerData 00119 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 00120 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi ); 00121 static HRESULT WINAPI DP_IF_GetPlayerName 00122 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 00123 LPDWORD lpdwDataSize, BOOL bAnsi ); 00124 static HRESULT WINAPI DP_IF_SetGroupName 00125 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName, 00126 DWORD dwFlags, BOOL bAnsi ); 00127 static HRESULT WINAPI DP_IF_SetPlayerData 00128 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 00129 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ); 00130 static HRESULT WINAPI DP_IF_SetPlayerName 00131 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName, 00132 DWORD dwFlags, BOOL bAnsi ); 00133 static HRESULT WINAPI DP_IF_AddGroupToGroup 00134 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup ); 00135 static HRESULT WINAPI DP_IF_CreateGroup 00136 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup, 00137 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 00138 DWORD dwFlags, BOOL bAnsi ); 00139 static HRESULT WINAPI DP_IF_CreateGroupInGroup 00140 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup, 00141 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, 00142 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ); 00143 static HRESULT WINAPI DP_IF_AddPlayerToGroup 00144 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 00145 DPID idPlayer, BOOL bAnsi ); 00146 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup 00147 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup ); 00148 static HRESULT WINAPI DP_SetSessionDesc 00149 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc, 00150 DWORD dwFlags, BOOL bInitial, BOOL bAnsi ); 00151 static HRESULT WINAPI DP_SecureOpen 00152 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 00153 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials, 00154 BOOL bAnsi ); 00155 static HRESULT WINAPI DP_SendEx 00156 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 00157 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 00158 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi ); 00159 static HRESULT WINAPI DP_IF_Receive 00160 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo, 00161 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi ); 00162 static HRESULT WINAPI DP_IF_GetMessageQueue 00163 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 00164 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi ); 00165 static HRESULT WINAPI DP_SP_SendEx 00166 ( IDirectPlay2Impl* This, DWORD dwFlags, 00167 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 00168 LPVOID lpContext, LPDWORD lpdwMsgID ); 00169 static HRESULT WINAPI DP_IF_SetGroupData 00170 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 00171 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ); 00172 static HRESULT WINAPI DP_IF_GetPlayerCaps 00173 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps, 00174 DWORD dwFlags ); 00175 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi ); 00176 static HRESULT WINAPI DP_IF_CancelMessage 00177 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags, 00178 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi ); 00179 static HRESULT WINAPI DP_IF_EnumGroupsInGroup 00180 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance, 00181 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 00182 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); 00183 static HRESULT WINAPI DP_IF_GetGroupParent 00184 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup, 00185 BOOL bAnsi ); 00186 static HRESULT WINAPI DP_IF_GetCaps 00187 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags ); 00188 static HRESULT WINAPI DP_IF_EnumSessions 00189 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 00190 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 00191 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ); 00192 static HRESULT WINAPI DP_IF_InitializeConnection 00193 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi ); 00194 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP, 00195 LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName, 00196 DWORD dwFlags, LPVOID lpContext ); 00197 static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, 00198 LPDWORD lpdwBufSize ); 00199 00200 00201 00202 static inline DPID DP_NextObjectId(void); 00203 static DPID DP_GetRemoteNextObjectId(void); 00204 00205 00206 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc, 00207 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi ); 00208 00209 00210 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp ); 00211 static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ); 00212 static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ); 00213 00214 00215 00216 00217 00218 00219 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */ 00220 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported 00221 we don't have to change much */ 00222 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */ 00223 00224 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */ 00225 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN ) 00226 00227 /* Strip out all dwFlags values for CREATEPLAYER msg */ 00228 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0 00229 00230 static LONG kludgePlayerGroupId = 1000; 00231 00232 /* ------------------------------------------------------------------ */ 00233 00234 00235 static BOOL DP_CreateIUnknown( LPVOID lpDP ) 00236 { 00237 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP; 00238 00239 This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) ); 00240 if ( This->unk == NULL ) 00241 { 00242 return FALSE; 00243 } 00244 00245 InitializeCriticalSection( &This->unk->DP_lock ); 00246 00247 return TRUE; 00248 } 00249 00250 static BOOL DP_DestroyIUnknown( LPVOID lpDP ) 00251 { 00252 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP; 00253 00254 DeleteCriticalSection( &This->unk->DP_lock ); 00255 HeapFree( GetProcessHeap(), 0, This->unk ); 00256 00257 return TRUE; 00258 } 00259 00260 static BOOL DP_CreateDirectPlay2( LPVOID lpDP ) 00261 { 00262 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP; 00263 00264 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) ); 00265 if ( This->dp2 == NULL ) 00266 { 00267 return FALSE; 00268 } 00269 00270 This->dp2->bConnectionOpen = FALSE; 00271 00272 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE; 00273 00274 This->dp2->bHostInterface = FALSE; 00275 00276 DPQ_INIT(This->dp2->receiveMsgs); 00277 DPQ_INIT(This->dp2->sendMsgs); 00278 DPQ_INIT(This->dp2->replysExpected); 00279 00280 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) ) 00281 { 00282 /* FIXME: Memory leak */ 00283 return FALSE; 00284 } 00285 00286 /* Provide an initial session desc with nothing in it */ 00287 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(), 00288 HEAP_ZERO_MEMORY, 00289 sizeof( *This->dp2->lpSessionDesc ) ); 00290 if( This->dp2->lpSessionDesc == NULL ) 00291 { 00292 /* FIXME: Memory leak */ 00293 return FALSE; 00294 } 00295 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc ); 00296 00297 /* We are emulating a dp 6 implementation */ 00298 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION; 00299 00300 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 00301 sizeof( *This->dp2->spData.lpCB ) ); 00302 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB ); 00303 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION; 00304 00305 /* This is the pointer to the service provider */ 00306 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP, 00307 (LPVOID*)&This->dp2->spData.lpISP, This ) ) 00308 ) 00309 { 00310 /* FIXME: Memory leak */ 00311 return FALSE; 00312 } 00313 00314 /* Setup lobby provider information */ 00315 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION; 00316 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 00317 sizeof( *This->dp2->dplspData.lpCB ) ); 00318 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB ); 00319 00320 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP, 00321 (LPVOID*)&This->dp2->dplspData.lpISP, This ) ) 00322 ) 00323 { 00324 /* FIXME: Memory leak */ 00325 return FALSE; 00326 } 00327 00328 return TRUE; 00329 } 00330 00331 /* Definition of the global function in dplayx_queue.h. # 00332 * FIXME: Would it be better to have a dplayx_queue.c for this function? */ 00333 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID ) 00334 { 00335 HeapFree( GetProcessHeap(), 0, elem ); 00336 } 00337 00338 /* Function to delete the list of groups with this interface. Needs to 00339 * delete the group and player lists associated with this group as well 00340 * as the group data associated with this group. It should not delete 00341 * player data as that is shared with the top player list and will be 00342 * deleted with that. 00343 */ 00344 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList ); 00345 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList ) 00346 { 00347 DPQ_DELETEQ( elem->lpGData->groups, groups, 00348 lpGroupList, cbDeleteElemFromHeap ); 00349 DPQ_DELETEQ( elem->lpGData->players, players, 00350 lpPlayerList, cbDeleteElemFromHeap ); 00351 HeapFree( GetProcessHeap(), 0, elem->lpGData ); 00352 HeapFree( GetProcessHeap(), 0, elem ); 00353 } 00354 00355 /* Function to delete the list of players with this interface. Needs to 00356 * delete the player data for all players as well. 00357 */ 00358 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList ); 00359 DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList ) 00360 { 00361 HeapFree( GetProcessHeap(), 0, elem->lpPData ); 00362 HeapFree( GetProcessHeap(), 0, elem ); 00363 } 00364 00365 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP ) 00366 { 00367 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP; 00368 00369 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE ) 00370 { 00371 TerminateThread( This->dp2->hEnumSessionThread, 0 ); 00372 CloseHandle( This->dp2->hEnumSessionThread ); 00373 } 00374 00375 /* Finish with the SP - have it shutdown */ 00376 if( This->dp2->spData.lpCB->ShutdownEx ) 00377 { 00378 DPSP_SHUTDOWNDATA data; 00379 00380 TRACE( "Calling SP ShutdownEx\n" ); 00381 00382 data.lpISP = This->dp2->spData.lpISP; 00383 00384 (*This->dp2->spData.lpCB->ShutdownEx)( &data ); 00385 } 00386 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */ 00387 { 00388 TRACE( "Calling obsolete SP Shutdown\n" ); 00389 (*This->dp2->spData.lpCB->Shutdown)(); 00390 } 00391 00392 /* Unload the SP (if it exists) */ 00393 if( This->dp2->hServiceProvider != 0 ) 00394 { 00395 FreeLibrary( This->dp2->hServiceProvider ); 00396 } 00397 00398 /* Unload the Lobby Provider (if it exists) */ 00399 if( This->dp2->hDPLobbyProvider != 0 ) 00400 { 00401 FreeLibrary( This->dp2->hDPLobbyProvider ); 00402 } 00403 00404 #if 0 00405 DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem ); 00406 DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem ); 00407 #endif 00408 00409 /* FIXME: Need to delete receive and send msgs queue contents */ 00410 00411 NS_DeleteSessionCache( This->dp2->lpNameServerData ); 00412 00413 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc ); 00414 00415 IDirectPlaySP_Release( This->dp2->spData.lpISP ); 00416 00417 /* Delete the contents */ 00418 HeapFree( GetProcessHeap(), 0, This->dp2 ); 00419 00420 return TRUE; 00421 } 00422 00423 static BOOL DP_CreateDirectPlay3( LPVOID lpDP ) 00424 { 00425 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP; 00426 00427 This->dp3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp3) ) ); 00428 if ( This->dp3 == NULL ) 00429 { 00430 return FALSE; 00431 } 00432 00433 return TRUE; 00434 } 00435 00436 static BOOL DP_DestroyDirectPlay3( LPVOID lpDP ) 00437 { 00438 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP; 00439 00440 /* Delete the contents */ 00441 HeapFree( GetProcessHeap(), 0, This->dp3 ); 00442 00443 return TRUE; 00444 } 00445 00446 static BOOL DP_CreateDirectPlay4( LPVOID lpDP ) 00447 { 00448 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP; 00449 00450 This->dp4 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp4) ) ); 00451 if ( This->dp4 == NULL ) 00452 { 00453 return FALSE; 00454 } 00455 00456 return TRUE; 00457 } 00458 00459 static BOOL DP_DestroyDirectPlay4( LPVOID lpDP ) 00460 { 00461 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP; 00462 00463 /* Delete the contents */ 00464 HeapFree( GetProcessHeap(), 0, This->dp4 ); 00465 00466 return TRUE; 00467 } 00468 00469 00470 /* Create a new interface */ 00471 extern 00472 HRESULT DP_CreateInterface 00473 ( REFIID riid, LPVOID* ppvObj ) 00474 { 00475 TRACE( " for %s\n", debugstr_guid( riid ) ); 00476 00477 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 00478 sizeof( IDirectPlay2Impl ) ); 00479 00480 if( *ppvObj == NULL ) 00481 { 00482 return DPERR_OUTOFMEMORY; 00483 } 00484 00485 if( IsEqualGUID( &IID_IDirectPlay2, riid ) ) 00486 { 00487 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj; 00488 This->lpVtbl = &directPlay2WVT; 00489 } 00490 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) ) 00491 { 00492 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj; 00493 This->lpVtbl = &directPlay2AVT; 00494 } 00495 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) ) 00496 { 00497 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj; 00498 This->lpVtbl = &directPlay3WVT; 00499 } 00500 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) ) 00501 { 00502 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj; 00503 This->lpVtbl = &directPlay3AVT; 00504 } 00505 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) ) 00506 { 00507 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj; 00508 This->lpVtbl = &directPlay4WVT; 00509 } 00510 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) ) 00511 { 00512 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj; 00513 This->lpVtbl = &directPlay4AVT; 00514 } 00515 else 00516 { 00517 /* Unsupported interface */ 00518 HeapFree( GetProcessHeap(), 0, *ppvObj ); 00519 *ppvObj = NULL; 00520 00521 return E_NOINTERFACE; 00522 } 00523 00524 /* Initialize it */ 00525 if ( DP_CreateIUnknown( *ppvObj ) && 00526 DP_CreateDirectPlay2( *ppvObj ) && 00527 DP_CreateDirectPlay3( *ppvObj ) && 00528 DP_CreateDirectPlay4( *ppvObj ) 00529 ) 00530 { 00531 IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj ); 00532 00533 return S_OK; 00534 } 00535 00536 /* Initialize failed, destroy it */ 00537 DP_DestroyDirectPlay4( *ppvObj ); 00538 DP_DestroyDirectPlay3( *ppvObj ); 00539 DP_DestroyDirectPlay2( *ppvObj ); 00540 DP_DestroyIUnknown( *ppvObj ); 00541 00542 HeapFree( GetProcessHeap(), 0, *ppvObj ); 00543 00544 *ppvObj = NULL; 00545 return DPERR_NOMEMORY; 00546 } 00547 00548 00549 /* Direct Play methods */ 00550 00551 /* Shared between all dplay types */ 00552 static HRESULT WINAPI DP_QueryInterface 00553 ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj ) 00554 { 00555 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 00556 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj ); 00557 00558 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 00559 sizeof( *This ) ); 00560 00561 if( *ppvObj == NULL ) 00562 { 00563 return DPERR_OUTOFMEMORY; 00564 } 00565 00566 CopyMemory( *ppvObj, This, sizeof( *This ) ); 00567 (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0; 00568 00569 if( IsEqualGUID( &IID_IDirectPlay2, riid ) ) 00570 { 00571 IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj; 00572 This->lpVtbl = &directPlay2WVT; 00573 } 00574 else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) ) 00575 { 00576 IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj; 00577 This->lpVtbl = &directPlay2AVT; 00578 } 00579 else if( IsEqualGUID( &IID_IDirectPlay3, riid ) ) 00580 { 00581 IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj; 00582 This->lpVtbl = &directPlay3WVT; 00583 } 00584 else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) ) 00585 { 00586 IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj; 00587 This->lpVtbl = &directPlay3AVT; 00588 } 00589 else if( IsEqualGUID( &IID_IDirectPlay4, riid ) ) 00590 { 00591 IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj; 00592 This->lpVtbl = &directPlay4WVT; 00593 } 00594 else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) ) 00595 { 00596 IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj; 00597 This->lpVtbl = &directPlay4AVT; 00598 } 00599 else 00600 { 00601 /* Unsupported interface */ 00602 HeapFree( GetProcessHeap(), 0, *ppvObj ); 00603 *ppvObj = NULL; 00604 00605 return E_NOINTERFACE; 00606 } 00607 00608 IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj ); 00609 00610 return S_OK; 00611 } 00612 00613 /* Shared between all dplay types */ 00614 static ULONG WINAPI DP_AddRef 00615 ( LPDIRECTPLAY3 iface ) 00616 { 00617 ULONG ulInterfaceRefCount, ulObjRefCount; 00618 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 00619 00620 ulObjRefCount = InterlockedIncrement( &This->unk->ulObjRef ); 00621 ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef ); 00622 00623 TRACE( "ref count incremented to %lu:%lu for %p\n", 00624 ulInterfaceRefCount, ulObjRefCount, This ); 00625 00626 return ulObjRefCount; 00627 } 00628 00629 static ULONG WINAPI DP_Release 00630 ( LPDIRECTPLAY3 iface ) 00631 { 00632 ULONG ulInterfaceRefCount, ulObjRefCount; 00633 00634 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 00635 00636 ulObjRefCount = InterlockedDecrement( &This->unk->ulObjRef ); 00637 ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef ); 00638 00639 TRACE( "ref count decremented to %lu:%lu for %p\n", 00640 ulInterfaceRefCount, ulObjRefCount, This ); 00641 00642 /* Deallocate if this is the last reference to the object */ 00643 if( ulObjRefCount == 0 ) 00644 { 00645 /* If we're destroying the object, this must be the last ref 00646 of the last interface */ 00647 DP_DestroyDirectPlay4( This ); 00648 DP_DestroyDirectPlay3( This ); 00649 DP_DestroyDirectPlay2( This ); 00650 DP_DestroyIUnknown( This ); 00651 } 00652 00653 /* Deallocate the interface */ 00654 if( ulInterfaceRefCount == 0 ) 00655 { 00656 HeapFree( GetProcessHeap(), 0, This ); 00657 } 00658 00659 return ulObjRefCount; 00660 } 00661 00662 static inline DPID DP_NextObjectId(void) 00663 { 00664 return (DPID)InterlockedIncrement( &kludgePlayerGroupId ); 00665 } 00666 00667 /* *lplpReply will be non NULL iff there is something to reply */ 00668 HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody, 00669 DWORD dwMessageBodySize, LPCVOID lpcMessageHeader, 00670 WORD wCommandId, WORD wVersion, 00671 LPVOID* lplpReply, LPDWORD lpdwMsgSize ) 00672 { 00673 TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n", 00674 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId, 00675 wVersion ); 00676 00677 switch( wCommandId ) 00678 { 00679 /* Name server needs to handle this request */ 00680 case DPMSGCMD_ENUMSESSIONSREQUEST: 00681 { 00682 /* Reply expected */ 00683 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This ); 00684 00685 break; 00686 } 00687 00688 /* Name server needs to handle this request */ 00689 case DPMSGCMD_ENUMSESSIONSREPLY: 00690 { 00691 /* No reply expected */ 00692 NS_AddRemoteComputerAsNameServer( lpcMessageHeader, 00693 This->dp2->spData.dwSPHeaderSize, 00694 (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody, 00695 This->dp2->lpNameServerData ); 00696 break; 00697 } 00698 00699 case DPMSGCMD_REQUESTNEWPLAYERID: 00700 { 00701 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = 00702 (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody; 00703 00704 LPDPMSG_NEWPLAYERIDREPLY lpReply; 00705 00706 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply ); 00707 00708 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize ); 00709 00710 FIXME( "Ignoring dwFlags 0x%08lx in request msg\n", 00711 lpcMsg->dwFlags ); 00712 00713 /* Setup the reply */ 00714 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) + 00715 This->dp2->spData.dwSPHeaderSize ); 00716 00717 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; 00718 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY; 00719 lpReply->envelope.wVersion = DPMSGVER_DP6; 00720 00721 lpReply->dpidNewPlayerId = DP_NextObjectId(); 00722 00723 TRACE( "Allocating new playerid 0x%08lx from remote request\n", 00724 lpReply->dpidNewPlayerId ); 00725 00726 break; 00727 } 00728 00729 case DPMSGCMD_GETNAMETABLEREPLY: 00730 case DPMSGCMD_NEWPLAYERIDREPLY: 00731 { 00732 00733 #if 0 00734 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY ) 00735 DebugBreak(); 00736 #endif 00737 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 00738 00739 break; 00740 } 00741 00742 #if 1 00743 case DPMSGCMD_JUSTENVELOPE: 00744 { 00745 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] ); 00746 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 ); 00747 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 00748 } 00749 #endif 00750 00751 case DPMSGCMD_FORWARDADDPLAYER: 00752 { 00753 #if 0 00754 DebugBreak(); 00755 #endif 00756 #if 1 00757 TRACE( "Sending message to self to get my addr\n" ); 00758 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */ 00759 #endif 00760 break; 00761 } 00762 00763 case DPMSGCMD_FORWARDADDPLAYERNACK: 00764 { 00765 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 00766 break; 00767 } 00768 00769 default: 00770 { 00771 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId ); 00772 DebugBreak(); 00773 break; 00774 } 00775 } 00776 00777 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */ 00778 00779 return DP_OK; 00780 } 00781 00782 00783 static HRESULT WINAPI DP_IF_AddPlayerToGroup 00784 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 00785 DPID idPlayer, BOOL bAnsi ) 00786 { 00787 lpGroupData lpGData; 00788 lpPlayerList lpPList; 00789 lpPlayerList lpNewPList; 00790 00791 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n", 00792 This, lpMsgHdr, idGroup, idPlayer, bAnsi ); 00793 00794 /* Find the group */ 00795 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 00796 { 00797 return DPERR_INVALIDGROUP; 00798 } 00799 00800 /* Find the player */ 00801 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 00802 { 00803 return DPERR_INVALIDPLAYER; 00804 } 00805 00806 /* Create a player list (ie "shortcut" ) */ 00807 lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) ); 00808 if( lpNewPList == NULL ) 00809 { 00810 return DPERR_CANTADDPLAYER; 00811 } 00812 00813 /* Add the shortcut */ 00814 lpPList->lpPData->uRef++; 00815 lpNewPList->lpPData = lpPList->lpPData; 00816 00817 /* Add the player to the list of players for this group */ 00818 DPQ_INSERT(lpGData->players,lpNewPList,players); 00819 00820 /* Let the SP know that we've added a player to the group */ 00821 if( This->dp2->spData.lpCB->AddPlayerToGroup ) 00822 { 00823 DPSP_ADDPLAYERTOGROUPDATA data; 00824 00825 TRACE( "Calling SP AddPlayerToGroup\n" ); 00826 00827 data.idPlayer = idPlayer; 00828 data.idGroup = idGroup; 00829 data.lpISP = This->dp2->spData.lpISP; 00830 00831 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); 00832 } 00833 00834 /* Inform all other peers of the addition of player to the group. If there are 00835 * no peers keep this event quiet. 00836 * Also, if this event was the result of another machine sending it to us, 00837 * don't bother rebroadcasting it. 00838 */ 00839 if( ( lpMsgHdr == NULL ) && 00840 This->dp2->lpSessionDesc && 00841 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 00842 { 00843 DPMSG_ADDPLAYERTOGROUP msg; 00844 msg.dwType = DPSYS_ADDPLAYERTOGROUP; 00845 00846 msg.dpIdGroup = idGroup; 00847 msg.dpIdPlayer = idPlayer; 00848 00849 /* FIXME: Correct to just use send effectively? */ 00850 /* FIXME: Should size include data w/ message or just message "header" */ 00851 /* FIXME: Check return code */ 00852 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 0, 0, NULL, NULL, bAnsi ); 00853 } 00854 00855 return DP_OK; 00856 } 00857 00858 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup 00859 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer ) 00860 { 00861 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 00862 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, TRUE ); 00863 } 00864 00865 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup 00866 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer ) 00867 { 00868 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 00869 return DP_IF_AddPlayerToGroup( This, NULL, idGroup, idPlayer, FALSE ); 00870 } 00871 00872 static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi ) 00873 { 00874 HRESULT hr = DP_OK; 00875 00876 TRACE("(%p)->(%u)\n", This, bAnsi ); 00877 00878 /* FIXME: Need to find a new host I assume (how?) */ 00879 /* FIXME: Need to destroy all local groups */ 00880 /* FIXME: Need to migrate all remotely visible players to the new host */ 00881 00882 /* Invoke the SP callback to inform of session close */ 00883 if( This->dp2->spData.lpCB->CloseEx ) 00884 { 00885 DPSP_CLOSEDATA data; 00886 00887 TRACE( "Calling SP CloseEx\n" ); 00888 00889 data.lpISP = This->dp2->spData.lpISP; 00890 00891 hr = (*This->dp2->spData.lpCB->CloseEx)( &data ); 00892 00893 } 00894 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */ 00895 { 00896 TRACE( "Calling SP Close (obsolete interface)\n" ); 00897 00898 hr = (*This->dp2->spData.lpCB->Close)(); 00899 } 00900 00901 return hr; 00902 } 00903 00904 static HRESULT WINAPI DirectPlay2AImpl_Close 00905 ( LPDIRECTPLAY2A iface ) 00906 { 00907 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 00908 return DP_IF_Close( This, TRUE ); 00909 } 00910 00911 static HRESULT WINAPI DirectPlay2WImpl_Close 00912 ( LPDIRECTPLAY2 iface ) 00913 { 00914 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 00915 return DP_IF_Close( This, FALSE ); 00916 } 00917 00918 static 00919 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid, 00920 LPDPNAME lpName, DWORD dwFlags, 00921 DPID idParent, BOOL bAnsi ) 00922 { 00923 lpGroupData lpGData; 00924 00925 /* Allocate the new space and add to end of high level group list */ 00926 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) ); 00927 00928 if( lpGData == NULL ) 00929 { 00930 return NULL; 00931 } 00932 00933 DPQ_INIT(lpGData->groups); 00934 DPQ_INIT(lpGData->players); 00935 00936 /* Set the desired player ID - no sanity checking to see if it exists */ 00937 lpGData->dpid = *lpid; 00938 00939 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi ); 00940 00941 /* FIXME: Should we check that the parent exists? */ 00942 lpGData->parent = idParent; 00943 00944 /* FIXME: Should we validate the dwFlags? */ 00945 lpGData->dwFlags = dwFlags; 00946 00947 TRACE( "Created group id 0x%08lx\n", *lpid ); 00948 00949 return lpGData; 00950 } 00951 00952 /* This method assumes that all links to it are already deleted */ 00953 static void 00954 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid ) 00955 { 00956 lpGroupList lpGList; 00957 00958 TRACE( "(%p)->(0x%08lx)\n", This, dpid ); 00959 00960 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList ); 00961 00962 if( lpGList == NULL ) 00963 { 00964 ERR( "DPID 0x%08lx not found\n", dpid ); 00965 return; 00966 } 00967 00968 if( --(lpGList->lpGData->uRef) ) 00969 { 00970 FIXME( "Why is this not the last reference to group?\n" ); 00971 DebugBreak(); 00972 } 00973 00974 /* Delete player */ 00975 DP_DeleteDPNameStruct( &lpGList->lpGData->name ); 00976 HeapFree( GetProcessHeap(), 0, lpGList->lpGData ); 00977 00978 /* Remove and Delete Player List object */ 00979 HeapFree( GetProcessHeap(), 0, lpGList ); 00980 00981 } 00982 00983 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid ) 00984 { 00985 lpGroupList lpGroups; 00986 00987 TRACE( "(%p)->(0x%08lx)\n", This, dpid ); 00988 00989 if( dpid == DPID_SYSTEM_GROUP ) 00990 { 00991 return This->dp2->lpSysGroup; 00992 } 00993 else 00994 { 00995 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups ); 00996 } 00997 00998 if( lpGroups == NULL ) 00999 { 01000 return NULL; 01001 } 01002 01003 return lpGroups->lpGData; 01004 } 01005 01006 static HRESULT WINAPI DP_IF_CreateGroup 01007 ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup, 01008 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 01009 DWORD dwFlags, BOOL bAnsi ) 01010 { 01011 lpGroupData lpGData; 01012 01013 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", 01014 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, 01015 dwFlags, bAnsi ); 01016 01017 /* If the name is not specified, we must provide one */ 01018 if( DPID_UNKNOWN == *lpidGroup ) 01019 { 01020 /* If we are the name server, we decide on the group ids. If not, we 01021 * must ask for one before attempting a creation. 01022 */ 01023 if( This->dp2->bHostInterface ) 01024 { 01025 *lpidGroup = DP_NextObjectId(); 01026 } 01027 else 01028 { 01029 *lpidGroup = DP_GetRemoteNextObjectId(); 01030 } 01031 } 01032 01033 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags, 01034 DPID_NOPARENT_GROUP, bAnsi ); 01035 01036 if( lpGData == NULL ) 01037 { 01038 return DPERR_CANTADDPLAYER; /* yes player not group */ 01039 } 01040 01041 if( DPID_SYSTEM_GROUP == *lpidGroup ) 01042 { 01043 This->dp2->lpSysGroup = lpGData; 01044 TRACE( "Inserting system group\n" ); 01045 } 01046 else 01047 { 01048 /* Insert into the system group */ 01049 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) ); 01050 lpGroup->lpGData = lpGData; 01051 01052 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups ); 01053 } 01054 01055 /* Something is now referencing this data */ 01056 lpGData->uRef++; 01057 01058 /* Set all the important stuff for the group */ 01059 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize ); 01060 01061 /* FIXME: We should only create the system group if GetCaps returns 01062 * DPCAPS_GROUPOPTIMIZED. 01063 */ 01064 01065 /* Let the SP know that we've created this group */ 01066 if( This->dp2->spData.lpCB->CreateGroup ) 01067 { 01068 DPSP_CREATEGROUPDATA data; 01069 DWORD dwCreateFlags = 0; 01070 01071 TRACE( "Calling SP CreateGroup\n" ); 01072 01073 if( *lpidGroup == DPID_NOPARENT_GROUP ) 01074 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP; 01075 01076 if( lpMsgHdr == NULL ) 01077 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; 01078 01079 if( dwFlags & DPGROUP_HIDDEN ) 01080 dwCreateFlags |= DPLAYI_GROUP_HIDDEN; 01081 01082 data.idGroup = *lpidGroup; 01083 data.dwFlags = dwCreateFlags; 01084 data.lpSPMessageHeader = lpMsgHdr; 01085 data.lpISP = This->dp2->spData.lpISP; 01086 01087 (*This->dp2->spData.lpCB->CreateGroup)( &data ); 01088 } 01089 01090 /* Inform all other peers of the creation of a new group. If there are 01091 * no peers keep this event quiet. 01092 * Also if this message was sent to us, don't rebroadcast. 01093 */ 01094 if( ( lpMsgHdr == NULL ) && 01095 This->dp2->lpSessionDesc && 01096 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 01097 { 01098 DPMSG_CREATEPLAYERORGROUP msg; 01099 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 01100 01101 msg.dwPlayerType = DPPLAYERTYPE_GROUP; 01102 msg.dpId = *lpidGroup; 01103 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */ 01104 msg.lpData = lpData; 01105 msg.dwDataSize = dwDataSize; 01106 msg.dpnName = *lpGroupName; 01107 msg.dpIdParent = DPID_NOPARENT_GROUP; 01108 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags ); 01109 01110 /* FIXME: Correct to just use send effectively? */ 01111 /* FIXME: Should size include data w/ message or just message "header" */ 01112 /* FIXME: Check return code */ 01113 DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 01114 0, 0, NULL, NULL, bAnsi ); 01115 } 01116 01117 return DP_OK; 01118 } 01119 01120 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup 01121 ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName, 01122 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) 01123 { 01124 *lpidGroup = DPID_UNKNOWN; 01125 01126 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup, 01127 lpGroupName, lpData, dwDataSize, dwFlags, TRUE ); 01128 } 01129 01130 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup 01131 ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, 01132 LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) 01133 { 01134 *lpidGroup = DPID_UNKNOWN; 01135 01136 return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup, 01137 lpGroupName, lpData, dwDataSize, dwFlags, FALSE ); 01138 } 01139 01140 01141 static void 01142 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, 01143 LPVOID lpData, DWORD dwDataSize ) 01144 { 01145 /* Clear out the data with this player */ 01146 if( dwFlags & DPSET_LOCAL ) 01147 { 01148 if ( lpGData->dwLocalDataSize != 0 ) 01149 { 01150 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData ); 01151 lpGData->lpLocalData = NULL; 01152 lpGData->dwLocalDataSize = 0; 01153 } 01154 } 01155 else 01156 { 01157 if( lpGData->dwRemoteDataSize != 0 ) 01158 { 01159 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData ); 01160 lpGData->lpRemoteData = NULL; 01161 lpGData->dwRemoteDataSize = 0; 01162 } 01163 } 01164 01165 /* Reallocate for new data */ 01166 if( lpData != NULL ) 01167 { 01168 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 01169 sizeof( dwDataSize ) ); 01170 CopyMemory( lpNewData, lpData, dwDataSize ); 01171 01172 if( dwFlags & DPSET_LOCAL ) 01173 { 01174 lpGData->lpLocalData = lpData; 01175 lpGData->dwLocalDataSize = dwDataSize; 01176 } 01177 else 01178 { 01179 lpGData->lpRemoteData = lpNewData; 01180 lpGData->dwRemoteDataSize = dwDataSize; 01181 } 01182 } 01183 01184 } 01185 01186 /* This function will just create the storage for the new player. */ 01187 static 01188 lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid, 01189 LPDPNAME lpName, DWORD dwFlags, 01190 HANDLE hEvent, BOOL bAnsi ) 01191 { 01192 lpPlayerData lpPData; 01193 01194 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi ); 01195 01196 /* Allocate the storage for the player and associate it with list element */ 01197 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) ); 01198 if( lpPData == NULL ) 01199 { 01200 return NULL; 01201 } 01202 01203 /* Set the desired player ID */ 01204 lpPData->dpid = *lpid; 01205 01206 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi ); 01207 01208 lpPData->dwFlags = dwFlags; 01209 01210 /* If we were given an event handle, duplicate it */ 01211 if( hEvent != 0 ) 01212 { 01213 if( !DuplicateHandle( GetCurrentProcess(), hEvent, 01214 GetCurrentProcess(), &lpPData->hEvent, 01215 0, FALSE, DUPLICATE_SAME_ACCESS ) 01216 ) 01217 { 01218 /* FIXME: Memory leak */ 01219 ERR( "Can't duplicate player msg handle %p\n", hEvent ); 01220 } 01221 } 01222 01223 /* Initialize the SP data section */ 01224 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData(); 01225 01226 TRACE( "Created player id 0x%08lx\n", *lpid ); 01227 01228 return lpPData; 01229 } 01230 01231 /* Delete the contents of the DPNAME struct */ 01232 static void 01233 DP_DeleteDPNameStruct( LPDPNAME lpDPName ) 01234 { 01235 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->lpszShortNameA ); 01236 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->lpszLongNameA ); 01237 } 01238 01239 /* This method assumes that all links to it are already deleted */ 01240 static void 01241 DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid ) 01242 { 01243 lpPlayerList lpPList; 01244 01245 TRACE( "(%p)->(0x%08lx)\n", This, dpid ); 01246 01247 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList ); 01248 01249 if( lpPList == NULL ) 01250 { 01251 ERR( "DPID 0x%08lx not found\n", dpid ); 01252 return; 01253 } 01254 01255 /* Verify that this is the last reference to the data */ 01256 if( --(lpPList->lpPData->uRef) ) 01257 { 01258 FIXME( "Why is this not the last reference to player?\n" ); 01259 DebugBreak(); 01260 } 01261 01262 /* Delete player */ 01263 DP_DeleteDPNameStruct( &lpPList->lpPData->name ); 01264 01265 CloseHandle( lpPList->lpPData->hEvent ); 01266 HeapFree( GetProcessHeap(), 0, lpPList->lpPData ); 01267 01268 /* Delete Player List object */ 01269 HeapFree( GetProcessHeap(), 0, lpPList ); 01270 } 01271 01272 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid ) 01273 { 01274 lpPlayerList lpPlayers; 01275 01276 TRACE( "(%p)->(0x%08lx)\n", This, dpid ); 01277 01278 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers ); 01279 01280 return lpPlayers; 01281 } 01282 01283 /* Basic area for Dst must already be allocated */ 01284 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi ) 01285 { 01286 if( lpSrc == NULL ) 01287 { 01288 ZeroMemory( lpDst, sizeof( *lpDst ) ); 01289 lpDst->dwSize = sizeof( *lpDst ); 01290 return TRUE; 01291 } 01292 01293 if( lpSrc->dwSize != sizeof( *lpSrc) ) 01294 { 01295 return FALSE; 01296 } 01297 01298 /* Delete any existing pointers */ 01299 HeapFree( GetProcessHeap(), 0, lpDst->lpszShortNameA ); 01300 HeapFree( GetProcessHeap(), 0, lpDst->lpszLongNameA ); 01301 01302 /* Copy as required */ 01303 CopyMemory( lpDst, lpSrc, lpSrc->dwSize ); 01304 01305 if( bAnsi ) 01306 { 01307 if( lpSrc->lpszShortNameA ) 01308 { 01309 lpDst->lpszShortNameA = HeapAlloc( GetProcessHeap(), 0, 01310 strlen(lpSrc->lpszShortNameA)+1 ); 01311 strcpy( lpDst->lpszShortNameA, lpSrc->lpszShortNameA ); 01312 } 01313 if( lpSrc->lpszLongNameA ) 01314 { 01315 lpDst->lpszLongNameA = HeapAlloc( GetProcessHeap(), 0, 01316 strlen(lpSrc->lpszLongNameA)+1 ); 01317 strcpy( lpDst->lpszLongNameA, lpSrc->lpszLongNameA ); 01318 } 01319 } 01320 else 01321 { 01322 if( lpSrc->lpszShortNameA ) 01323 { 01324 lpDst->lpszShortName = HeapAlloc( GetProcessHeap(), 0, 01325 (strlenW(lpSrc->lpszShortName)+1)*sizeof(WCHAR) ); 01326 strcpyW( lpDst->lpszShortName, lpSrc->lpszShortName ); 01327 } 01328 if( lpSrc->lpszLongNameA ) 01329 { 01330 lpDst->lpszLongName = HeapAlloc( GetProcessHeap(), 0, 01331 (strlenW(lpSrc->lpszLongName)+1)*sizeof(WCHAR) ); 01332 strcpyW( lpDst->lpszLongName, lpSrc->lpszLongName ); 01333 } 01334 } 01335 01336 return TRUE; 01337 } 01338 01339 static void 01340 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags, 01341 LPVOID lpData, DWORD dwDataSize ) 01342 { 01343 /* Clear out the data with this player */ 01344 if( dwFlags & DPSET_LOCAL ) 01345 { 01346 if ( lpPData->dwLocalDataSize != 0 ) 01347 { 01348 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData ); 01349 lpPData->lpLocalData = NULL; 01350 lpPData->dwLocalDataSize = 0; 01351 } 01352 } 01353 else 01354 { 01355 if( lpPData->dwRemoteDataSize != 0 ) 01356 { 01357 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData ); 01358 lpPData->lpRemoteData = NULL; 01359 lpPData->dwRemoteDataSize = 0; 01360 } 01361 } 01362 01363 /* Reallocate for new data */ 01364 if( lpData != NULL ) 01365 { 01366 LPVOID lpNewData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 01367 sizeof( dwDataSize ) ); 01368 CopyMemory( lpNewData, lpData, dwDataSize ); 01369 01370 if( dwFlags & DPSET_LOCAL ) 01371 { 01372 lpPData->lpLocalData = lpData; 01373 lpPData->dwLocalDataSize = dwDataSize; 01374 } 01375 else 01376 { 01377 lpPData->lpRemoteData = lpNewData; 01378 lpPData->dwRemoteDataSize = dwDataSize; 01379 } 01380 } 01381 01382 } 01383 01384 static HRESULT WINAPI DP_IF_CreatePlayer 01385 ( IDirectPlay2Impl* This, 01386 LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */ 01387 LPDPID lpidPlayer, 01388 LPDPNAME lpPlayerName, 01389 HANDLE hEvent, 01390 LPVOID lpData, 01391 DWORD dwDataSize, 01392 DWORD dwFlags, 01393 BOOL bAnsi ) 01394 { 01395 HRESULT hr = DP_OK; 01396 lpPlayerData lpPData; 01397 lpPlayerList lpPList; 01398 DWORD dwCreateFlags = 0; 01399 01400 TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", 01401 This, lpidPlayer, lpPlayerName, hEvent, lpData, 01402 dwDataSize, dwFlags, bAnsi ); 01403 01404 if( dwFlags == 0 ) 01405 { 01406 dwFlags = DPPLAYER_SPECTATOR; 01407 } 01408 01409 if( lpidPlayer == NULL ) 01410 { 01411 return DPERR_INVALIDPARAMS; 01412 } 01413 01414 01415 /* Determine the creation flags for the player. These will be passed 01416 * to the name server if requesting a player id and to the SP when 01417 * informing it of the player creation 01418 */ 01419 { 01420 if( dwFlags & DPPLAYER_SERVERPLAYER ) 01421 { 01422 if( *lpidPlayer == DPID_SERVERPLAYER ) 01423 { 01424 /* Server player for the host interface */ 01425 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER; 01426 } 01427 else if( *lpidPlayer == DPID_NAME_SERVER ) 01428 { 01429 /* Name server - master of everything */ 01430 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER); 01431 } 01432 else 01433 { 01434 /* Server player for a non host interface */ 01435 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER; 01436 } 01437 } 01438 01439 if( lpMsgHdr == NULL ) 01440 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; 01441 } 01442 01443 /* Verify we know how to handle all the flags */ 01444 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) || 01445 ( dwFlags & DPPLAYER_SPECTATOR ) 01446 ) 01447 ) 01448 { 01449 /* Assume non fatal failure */ 01450 ERR( "unknown dwFlags = 0x%08lx\n", dwFlags ); 01451 } 01452 01453 /* If the name is not specified, we must provide one */ 01454 if( *lpidPlayer == DPID_UNKNOWN ) 01455 { 01456 /* If we are the session master, we dish out the group/player ids */ 01457 if( This->dp2->bHostInterface ) 01458 { 01459 *lpidPlayer = DP_NextObjectId(); 01460 } 01461 else 01462 { 01463 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer ); 01464 01465 if( FAILED(hr) ) 01466 { 01467 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) ); 01468 return hr; 01469 } 01470 } 01471 } 01472 else 01473 { 01474 /* FIXME: Would be nice to perhaps verify that we don't already have 01475 * this player. 01476 */ 01477 } 01478 01479 /* FIXME: Should we be storing these dwFlags or the creation ones? */ 01480 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags, 01481 hEvent, bAnsi ); 01482 01483 if( lpPData == NULL ) 01484 { 01485 return DPERR_CANTADDPLAYER; 01486 } 01487 01488 /* Create the list object and link it in */ 01489 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) ); 01490 if( lpPList == NULL ) 01491 { 01492 FIXME( "Memory leak\n" ); 01493 return DPERR_CANTADDPLAYER; 01494 } 01495 01496 lpPData->uRef = 1; 01497 lpPList->lpPData = lpPData; 01498 01499 /* Add the player to the system group */ 01500 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players ); 01501 01502 /* Update the information and send it to all players in the session */ 01503 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize ); 01504 01505 /* Let the SP know that we've created this player */ 01506 if( This->dp2->spData.lpCB->CreatePlayer ) 01507 { 01508 DPSP_CREATEPLAYERDATA data; 01509 01510 data.idPlayer = *lpidPlayer; 01511 data.dwFlags = dwCreateFlags; 01512 data.lpSPMessageHeader = lpMsgHdr; 01513 data.lpISP = This->dp2->spData.lpISP; 01514 01515 TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n", 01516 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader ); 01517 01518 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data ); 01519 } 01520 01521 if( FAILED(hr) ) 01522 { 01523 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) ); 01524 return hr; 01525 } 01526 01527 /* Now let the SP know that this player is a member of the system group */ 01528 if( This->dp2->spData.lpCB->AddPlayerToGroup ) 01529 { 01530 DPSP_ADDPLAYERTOGROUPDATA data; 01531 01532 data.idPlayer = *lpidPlayer; 01533 data.idGroup = DPID_SYSTEM_GROUP; 01534 data.lpISP = This->dp2->spData.lpISP; 01535 01536 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" ); 01537 01538 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); 01539 } 01540 01541 if( FAILED(hr) ) 01542 { 01543 ERR( "Failed to add player to sys group with sp: %s\n", 01544 DPLAYX_HresultToString(hr) ); 01545 return hr; 01546 } 01547 01548 #if 1 01549 if( This->dp2->bHostInterface == FALSE ) 01550 { 01551 /* Let the name server know about the creation of this player */ 01552 /* FIXME: Is this only to be done for the creation of a server player or 01553 * is this used for regular players? If only for server players, move 01554 * this call to DP_SecureOpen(...); 01555 */ 01556 #if 0 01557 TRACE( "Sending message to self to get my addr\n" ); 01558 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */ 01559 #endif 01560 01561 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer); 01562 } 01563 #else 01564 /* Inform all other peers of the creation of a new player. If there are 01565 * no peers keep this quiet. 01566 * Also, if this was a remote event, no need to rebroadcast it. 01567 */ 01568 if( ( lpMsgHdr == NULL ) && 01569 This->dp2->lpSessionDesc && 01570 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 01571 { 01572 DPMSG_CREATEPLAYERORGROUP msg; 01573 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 01574 01575 msg.dwPlayerType = DPPLAYERTYPE_PLAYER; 01576 msg.dpId = *lpidPlayer; 01577 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */ 01578 msg.lpData = lpData; 01579 msg.dwDataSize = dwDataSize; 01580 msg.dpnName = *lpPlayerName; 01581 msg.dpIdParent = DPID_NOPARENT_GROUP; 01582 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags ); 01583 01584 /* FIXME: Correct to just use send effectively? */ 01585 /* FIXME: Should size include data w/ message or just message "header" */ 01586 /* FIXME: Check return code */ 01587 hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, 01588 sizeof( msg ), 0, 0, NULL, NULL, bAnsi ); 01589 } 01590 #endif 01591 01592 return hr; 01593 } 01594 01595 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer 01596 ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, 01597 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) 01598 { 01599 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01600 01601 if( dwFlags & DPPLAYER_SERVERPLAYER ) 01602 { 01603 *lpidPlayer = DPID_SERVERPLAYER; 01604 } 01605 else 01606 { 01607 *lpidPlayer = DPID_UNKNOWN; 01608 } 01609 01610 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 01611 lpData, dwDataSize, dwFlags, TRUE ); 01612 } 01613 01614 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer 01615 ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, 01616 HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags ) 01617 { 01618 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01619 01620 if( dwFlags & DPPLAYER_SERVERPLAYER ) 01621 { 01622 *lpidPlayer = DPID_SERVERPLAYER; 01623 } 01624 else 01625 { 01626 *lpidPlayer = DPID_UNKNOWN; 01627 } 01628 01629 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 01630 lpData, dwDataSize, dwFlags, FALSE ); 01631 } 01632 01633 static DPID DP_GetRemoteNextObjectId(void) 01634 { 01635 FIXME( ":stub\n" ); 01636 01637 /* Hack solution */ 01638 return DP_NextObjectId(); 01639 } 01640 01641 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup 01642 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 01643 DPID idPlayer, BOOL bAnsi ) 01644 { 01645 HRESULT hr = DP_OK; 01646 01647 lpGroupData lpGData; 01648 lpPlayerList lpPList; 01649 01650 TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n", 01651 This, lpMsgHdr, idGroup, idPlayer, bAnsi ); 01652 01653 /* Find the group */ 01654 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 01655 { 01656 return DPERR_INVALIDGROUP; 01657 } 01658 01659 /* Find the player */ 01660 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 01661 { 01662 return DPERR_INVALIDPLAYER; 01663 } 01664 01665 /* Remove the player shortcut from the group */ 01666 DPQ_REMOVE_ENTRY( lpGData->players, players, lpPData->dpid, ==, idPlayer, lpPList ); 01667 01668 if( lpPList == NULL ) 01669 { 01670 return DPERR_INVALIDPLAYER; 01671 } 01672 01673 /* One less reference */ 01674 lpPList->lpPData->uRef--; 01675 01676 /* Delete the Player List element */ 01677 HeapFree( GetProcessHeap(), 0, lpPList ); 01678 01679 /* Inform the SP if they care */ 01680 if( This->dp2->spData.lpCB->RemovePlayerFromGroup ) 01681 { 01682 DPSP_REMOVEPLAYERFROMGROUPDATA data; 01683 01684 TRACE( "Calling SP RemovePlayerFromGroup\n" ); 01685 01686 data.idPlayer = idPlayer; 01687 data.idGroup = idGroup; 01688 data.lpISP = This->dp2->spData.lpISP; 01689 01690 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data ); 01691 } 01692 01693 /* Need to send a DELETEPLAYERFROMGROUP message */ 01694 FIXME( "Need to send a message\n" ); 01695 01696 return hr; 01697 } 01698 01699 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup 01700 ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer ) 01701 { 01702 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01703 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, TRUE ); 01704 } 01705 01706 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup 01707 ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer ) 01708 { 01709 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01710 return DP_IF_DeletePlayerFromGroup( This, NULL, idGroup, idPlayer, FALSE ); 01711 } 01712 01713 typedef struct _DPRGOPContext 01714 { 01715 IDirectPlay3Impl* This; 01716 BOOL bAnsi; 01717 DPID idGroup; 01718 } DPRGOPContext, *lpDPRGOPContext; 01719 01720 static BOOL CALLBACK 01721 cbRemoveGroupOrPlayer( 01722 DPID dpId, 01723 DWORD dwPlayerType, 01724 LPCDPNAME lpName, 01725 DWORD dwFlags, 01726 LPVOID lpContext ) 01727 { 01728 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext; 01729 01730 TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n", 01731 dpId, dwPlayerType, lpCtxt->idGroup ); 01732 01733 if( dwPlayerType == DPPLAYERTYPE_GROUP ) 01734 { 01735 if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup, 01736 dpId ) 01737 ) 01738 ) 01739 { 01740 ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n", 01741 dpId, lpCtxt->idGroup ); 01742 } 01743 } 01744 else 01745 { 01746 if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This, 01747 NULL, lpCtxt->idGroup, 01748 dpId, lpCtxt->bAnsi ) 01749 ) 01750 ) 01751 { 01752 ERR( "Unable to delete player 0x%08lx from grp 0x%08lx\n", 01753 dpId, lpCtxt->idGroup ); 01754 } 01755 } 01756 01757 return TRUE; /* Continue enumeration */ 01758 } 01759 01760 static HRESULT WINAPI DP_IF_DestroyGroup 01761 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi ) 01762 { 01763 lpGroupData lpGData; 01764 DPRGOPContext context; 01765 01766 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n", 01767 This, lpMsgHdr, idGroup, bAnsi ); 01768 01769 /* Find the group */ 01770 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 01771 { 01772 return DPERR_INVALIDPLAYER; /* yes player */ 01773 } 01774 01775 context.This = (IDirectPlay3Impl*)This; 01776 context.bAnsi = bAnsi; 01777 context.idGroup = idGroup; 01778 01779 /* Remove all players that this group has */ 01780 DP_IF_EnumGroupPlayers( This, idGroup, NULL, 01781 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi ); 01782 01783 /* Remove all links to groups that this group has since this is dp3 */ 01784 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL, 01785 cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi ); 01786 01787 /* Remove this group from the parent group - if it has one */ 01788 if( ( idGroup != DPID_SYSTEM_GROUP ) && 01789 ( lpGData->parent != DPID_SYSTEM_GROUP ) 01790 ) 01791 { 01792 DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent, 01793 idGroup ); 01794 } 01795 01796 /* Now delete this group data and list from the system group */ 01797 DP_DeleteGroup( This, idGroup ); 01798 01799 /* Let the SP know that we've destroyed this group */ 01800 if( This->dp2->spData.lpCB->DeleteGroup ) 01801 { 01802 DPSP_DELETEGROUPDATA data; 01803 01804 FIXME( "data.dwFlags is incorrect\n" ); 01805 01806 data.idGroup = idGroup; 01807 data.dwFlags = 0; 01808 data.lpISP = This->dp2->spData.lpISP; 01809 01810 (*This->dp2->spData.lpCB->DeleteGroup)( &data ); 01811 } 01812 01813 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" ); 01814 01815 return DP_OK; 01816 } 01817 01818 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup 01819 ( LPDIRECTPLAY2A iface, DPID idGroup ) 01820 { 01821 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01822 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE ); 01823 } 01824 01825 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup 01826 ( LPDIRECTPLAY2 iface, DPID idGroup ) 01827 { 01828 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01829 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE ); 01830 } 01831 01832 typedef struct _DPFAGContext 01833 { 01834 IDirectPlay2Impl* This; 01835 DPID idPlayer; 01836 BOOL bAnsi; 01837 } DPFAGContext, *lpDPFAGContext; 01838 01839 static HRESULT WINAPI DP_IF_DestroyPlayer 01840 ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi ) 01841 { 01842 DPFAGContext cbContext; 01843 01844 FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n", 01845 This, lpMsgHdr, idPlayer, bAnsi ); 01846 01847 if( This->dp2->connectionInitialized == NO_PROVIDER ) 01848 { 01849 return DPERR_UNINITIALIZED; 01850 } 01851 01852 if( DP_FindPlayer( This, idPlayer ) == NULL ) 01853 { 01854 return DPERR_INVALIDPLAYER; 01855 } 01856 01857 /* FIXME: If the player is remote, we must be the host to delete this */ 01858 01859 cbContext.This = This; 01860 cbContext.idPlayer = idPlayer; 01861 cbContext.bAnsi = bAnsi; 01862 01863 /* Find each group and call DeletePlayerFromGroup if the player is a 01864 member of the group */ 01865 DP_IF_EnumGroups( This, NULL, cbDeletePlayerFromAllGroups, 01866 (LPVOID)&cbContext, DPENUMGROUPS_ALL, bAnsi ); 01867 01868 /* Now delete player and player list from the sys group */ 01869 DP_DeletePlayer( This, idPlayer ); 01870 01871 /* Let the SP know that we've destroyed this group */ 01872 if( This->dp2->spData.lpCB->DeletePlayer ) 01873 { 01874 DPSP_DELETEPLAYERDATA data; 01875 01876 FIXME( "data.dwFlags is incorrect\n" ); 01877 01878 data.idPlayer = idPlayer; 01879 data.dwFlags = 0; 01880 data.lpISP = This->dp2->spData.lpISP; 01881 01882 (*This->dp2->spData.lpCB->DeletePlayer)( &data ); 01883 } 01884 01885 FIXME( "Send a DELETEPLAYERORGROUP msg\n" ); 01886 01887 return DP_OK; 01888 } 01889 01890 static BOOL CALLBACK 01891 cbDeletePlayerFromAllGroups( 01892 DPID dpId, 01893 DWORD dwPlayerType, 01894 LPCDPNAME lpName, 01895 DWORD dwFlags, 01896 LPVOID lpContext ) 01897 { 01898 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext; 01899 01900 if( dwPlayerType == DPPLAYERTYPE_GROUP ) 01901 { 01902 DP_IF_DeletePlayerFromGroup( lpCtxt->This, NULL, dpId, lpCtxt->idPlayer, 01903 lpCtxt->bAnsi ); 01904 01905 /* Enumerate all groups in this group since this will normally only 01906 * be called for top level groups 01907 */ 01908 DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This, 01909 dpId, NULL, 01910 cbDeletePlayerFromAllGroups, 01911 (LPVOID)lpContext, DPENUMGROUPS_ALL, 01912 lpCtxt->bAnsi ); 01913 01914 } 01915 else 01916 { 01917 ERR( "Group callback has dwPlayerType = 0x%08lx\n", dwPlayerType ); 01918 } 01919 01920 return TRUE; 01921 } 01922 01923 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer 01924 ( LPDIRECTPLAY2A iface, DPID idPlayer ) 01925 { 01926 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01927 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE ); 01928 } 01929 01930 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer 01931 ( LPDIRECTPLAY2 iface, DPID idPlayer ) 01932 { 01933 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 01934 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE ); 01935 } 01936 01937 static HRESULT WINAPI DP_IF_EnumGroupPlayers 01938 ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance, 01939 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 01940 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ) 01941 { 01942 lpGroupData lpGData; 01943 lpPlayerList lpPList; 01944 01945 FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n", 01946 This, idGroup, lpguidInstance, lpEnumPlayersCallback2, 01947 lpContext, dwFlags, bAnsi ); 01948 01949 if( This->dp2->connectionInitialized == NO_PROVIDER ) 01950 { 01951 return DPERR_UNINITIALIZED; 01952 } 01953 01954 /* Find the group */ 01955 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 01956 { 01957 return DPERR_INVALIDGROUP; 01958 } 01959 01960 if( DPQ_IS_EMPTY( lpGData->players ) ) 01961 { 01962 return DP_OK; 01963 } 01964 01965 lpPList = DPQ_FIRST( lpGData->players ); 01966 01967 /* Walk the players in this group */ 01968 for( ;; ) 01969 { 01970 /* We do not enum the name server or app server as they are of no 01971 * concequence to the end user. 01972 */ 01973 if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) && 01974 ( lpPList->lpPData->dpid != DPID_SERVERPLAYER ) 01975 ) 01976 { 01977 01978 /* FIXME: Need to add stuff for dwFlags checking */ 01979 01980 if( !lpEnumPlayersCallback2( lpPList->lpPData->dpid, DPPLAYERTYPE_PLAYER, 01981 &lpPList->lpPData->name, 01982 lpPList->lpPData->dwFlags, 01983 lpContext ) 01984 ) 01985 { 01986 /* User requested break */ 01987 return DP_OK; 01988 } 01989 } 01990 01991 if( DPQ_IS_ENDOFLIST( lpPList->players ) ) 01992 { 01993 break; 01994 } 01995 01996 lpPList = DPQ_NEXT( lpPList->players ); 01997 } 01998 01999 return DP_OK; 02000 } 02001 02002 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers 02003 ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance, 02004 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02005 LPVOID lpContext, DWORD dwFlags ) 02006 { 02007 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02008 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance, 02009 lpEnumPlayersCallback2, lpContext, 02010 dwFlags, TRUE ); 02011 } 02012 02013 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers 02014 ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance, 02015 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02016 LPVOID lpContext, DWORD dwFlags ) 02017 { 02018 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02019 return DP_IF_EnumGroupPlayers( This, idGroup, lpguidInstance, 02020 lpEnumPlayersCallback2, lpContext, 02021 dwFlags, FALSE ); 02022 } 02023 02024 /* NOTE: This only enumerates top level groups (created with CreateGroup) */ 02025 static HRESULT WINAPI DP_IF_EnumGroups 02026 ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 02027 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02028 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ) 02029 { 02030 return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, 02031 DPID_SYSTEM_GROUP, lpguidInstance, 02032 lpEnumPlayersCallback2, lpContext, 02033 dwFlags, bAnsi ); 02034 } 02035 02036 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups 02037 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, 02038 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02039 LPVOID lpContext, DWORD dwFlags ) 02040 { 02041 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02042 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2, 02043 lpContext, dwFlags, TRUE ); 02044 } 02045 02046 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups 02047 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, 02048 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02049 LPVOID lpContext, DWORD dwFlags ) 02050 { 02051 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02052 return DP_IF_EnumGroups( This, lpguidInstance, lpEnumPlayersCallback2, 02053 lpContext, dwFlags, FALSE ); 02054 } 02055 02056 static HRESULT WINAPI DP_IF_EnumPlayers 02057 ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 02058 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02059 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ) 02060 { 02061 return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance, 02062 lpEnumPlayersCallback2, lpContext, 02063 dwFlags, bAnsi ); 02064 } 02065 02066 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers 02067 ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, 02068 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02069 LPVOID lpContext, DWORD dwFlags ) 02070 { 02071 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02072 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2, 02073 lpContext, dwFlags, TRUE ); 02074 } 02075 02076 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers 02077 ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, 02078 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 02079 LPVOID lpContext, DWORD dwFlags ) 02080 { 02081 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02082 return DP_IF_EnumPlayers( This, lpguidInstance, lpEnumPlayersCallback2, 02083 lpContext, dwFlags, FALSE ); 02084 } 02085 02086 /* This function should call the registered callback function that the user 02087 passed into EnumSessions for each entry available. 02088 */ 02089 static void DP_InvokeEnumSessionCallbacks 02090 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 02091 LPVOID lpNSInfo, 02092 DWORD dwTimeout, 02093 LPVOID lpContext ) 02094 { 02095 LPDPSESSIONDESC2 lpSessionDesc; 02096 02097 FIXME( ": not checking for conditions\n" ); 02098 02099 /* Not sure if this should be pruning but it's convenient */ 02100 NS_PruneSessionCache( lpNSInfo ); 02101 02102 NS_ResetSessionEnumeration( lpNSInfo ); 02103 02104 /* Enumerate all sessions */ 02105 /* FIXME: Need to indicate ANSI */ 02106 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL ) 02107 { 02108 TRACE( "EnumSessionsCallback2 invoked\n" ); 02109 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) ) 02110 { 02111 return; 02112 } 02113 } 02114 02115 /* Invoke one last time to indicate that there is no more to come */ 02116 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ); 02117 } 02118 02119 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext ) 02120 { 02121 EnumSessionAsyncCallbackData* data = (EnumSessionAsyncCallbackData*)lpContext; 02122 HANDLE hSuicideRequest = data->hSuicideRequest; 02123 DWORD dwTimeout = data->dwTimeout; 02124 02125 TRACE( "Thread started with timeout = 0x%08lx\n", dwTimeout ); 02126 02127 for( ;; ) 02128 { 02129 HRESULT hr; 02130 02131 /* Sleep up to dwTimeout waiting for request to terminate thread */ 02132 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 ) 02133 { 02134 TRACE( "Thread terminating on terminate request\n" ); 02135 break; 02136 } 02137 02138 /* Now resend the enum request */ 02139 hr = NS_SendSessionRequestBroadcast( &data->requestGuid, 02140 data->dwEnumSessionFlags, 02141 data->lpSpData ); 02142 02143 if( FAILED(hr) ) 02144 { 02145 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) ); 02146 /* FIXME: Should we kill this thread? How to inform the main thread? */ 02147 } 02148 02149 } 02150 02151 TRACE( "Thread terminating\n" ); 02152 02153 /* Clean up the thread data */ 02154 CloseHandle( hSuicideRequest ); 02155 HeapFree( GetProcessHeap(), 0, lpContext ); 02156 02157 /* FIXME: Need to have some notification to main app thread that this is 02158 * dead. It would serve two purposes. 1) allow sync on termination 02159 * so that we don't actually send something to ourselves when we 02160 * become name server (race condition) and 2) so that if we die 02161 * abnormally something else will be able to tell. 02162 */ 02163 02164 return 1; 02165 } 02166 02167 static void DP_KillEnumSessionThread( IDirectPlay2Impl* This ) 02168 { 02169 /* Does a thread exist? If so we were doing an async enum session */ 02170 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE ) 02171 { 02172 TRACE( "Killing EnumSession thread %p\n", 02173 This->dp2->hEnumSessionThread ); 02174 02175 /* Request that the thread kill itself nicely */ 02176 SetEvent( This->dp2->hKillEnumSessionThreadEvent ); 02177 CloseHandle( This->dp2->hKillEnumSessionThreadEvent ); 02178 02179 /* We no longer need to know about the thread */ 02180 CloseHandle( This->dp2->hEnumSessionThread ); 02181 02182 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE; 02183 } 02184 } 02185 02186 static HRESULT WINAPI DP_IF_EnumSessions 02187 ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 02188 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 02189 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ) 02190 { 02191 HRESULT hr = DP_OK; 02192 02193 TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n", 02194 This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags, 02195 bAnsi ); 02196 02197 /* Can't enumerate if the interface is already open */ 02198 if( This->dp2->bConnectionOpen ) 02199 { 02200 return DPERR_GENERIC; 02201 } 02202 02203 #if 1 02204 /* The loading of a lobby provider _seems_ to require a backdoor loading 02205 * of the service provider to also associate with this DP object. This is 02206 * because the app doesn't seem to have to call EnumConnections and 02207 * InitializeConnection for the SP before calling this method. As such 02208 * we'll do their dirty work for them with a quick hack so as to always 02209 * load the TCP/IP service provider. 02210 * 02211 * The correct solution would seem to involve creating a dialog box which 02212 * contains the possible SPs. These dialog boxes most likely follow SDK 02213 * examples. 02214 */ 02215 if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized ) 02216 { 02217 LPVOID lpConnection; 02218 DWORD dwSize; 02219 02220 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" ); 02221 02222 if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) ) 02223 { 02224 ERR( "Can't build compound addr\n" ); 02225 return DPERR_GENERIC; 02226 } 02227 02228 hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection, 02229 0, bAnsi ); 02230 if( FAILED(hr) ) 02231 { 02232 return hr; 02233 } 02234 02235 /* Free up the address buffer */ 02236 HeapFree( GetProcessHeap(), 0, lpConnection ); 02237 02238 /* The SP is now initialized */ 02239 This->dp2->bSPInitialized = TRUE; 02240 } 02241 #endif 02242 02243 02244 /* Use the service provider default? */ 02245 if( dwTimeout == 0 ) 02246 { 02247 DPCAPS spCaps; 02248 spCaps.dwSize = sizeof( spCaps ); 02249 02250 DP_IF_GetCaps( This, &spCaps, 0 ); 02251 dwTimeout = spCaps.dwTimeout; 02252 02253 /* The service provider doesn't provide one either! */ 02254 if( dwTimeout == 0 ) 02255 { 02256 /* Provide the TCP/IP default */ 02257 dwTimeout = DPMSG_WAIT_5_SECS; 02258 } 02259 } 02260 02261 if( dwFlags & DPENUMSESSIONS_STOPASYNC ) 02262 { 02263 DP_KillEnumSessionThread( This ); 02264 return hr; 02265 } 02266 02267 /* FIXME: Interface locking sucks in this method */ 02268 if( ( dwFlags & DPENUMSESSIONS_ASYNC ) ) 02269 { 02270 /* Enumerate everything presently in the local session cache */ 02271 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2, 02272 This->dp2->lpNameServerData, dwTimeout, 02273 lpContext ); 02274 02275 02276 /* See if we've already created a thread to service this interface */ 02277 if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE ) 02278 { 02279 DWORD dwThreadId; 02280 02281 /* Send the first enum request inline since the user may cancel a dialog 02282 * if one is presented. Also, may also have a connecting return code. 02283 */ 02284 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication, 02285 dwFlags, &This->dp2->spData ); 02286 02287 if( !FAILED(hr) ) 02288 { 02289 EnumSessionAsyncCallbackData* lpData 02290 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpData ) ); 02291 /* FIXME: need to kill the thread on object deletion */ 02292 lpData->lpSpData = &This->dp2->spData; 02293 02294 CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) ); 02295 lpData->dwEnumSessionFlags = dwFlags; 02296 lpData->dwTimeout = dwTimeout; 02297 02298 This->dp2->hKillEnumSessionThreadEvent = 02299 CreateEventW( NULL, TRUE, FALSE, NULL ); 02300 02301 if( !DuplicateHandle( GetCurrentProcess(), 02302 This->dp2->hKillEnumSessionThreadEvent, 02303 GetCurrentProcess(), 02304 &lpData->hSuicideRequest, 02305 0, FALSE, DUPLICATE_SAME_ACCESS ) 02306 ) 02307 { 02308 ERR( "Can't duplicate thread killing handle\n" ); 02309 } 02310 02311 TRACE( ": creating EnumSessionsRequest thread\n" ); 02312 02313 This->dp2->hEnumSessionThread = CreateThread( NULL, 02314 0, 02315 DP_EnumSessionsSendAsyncRequestThread, 02316 lpData, 02317 0, 02318 &dwThreadId ); 02319 } 02320 } 02321 } 02322 else 02323 { 02324 /* Invalidate the session cache for the interface */ 02325 NS_InvalidateSessionCache( This->dp2->lpNameServerData ); 02326 02327 /* Send the broadcast for session enumeration */ 02328 hr = NS_SendSessionRequestBroadcast( &lpsd->guidApplication, 02329 dwFlags, 02330 &This->dp2->spData ); 02331 02332 02333 SleepEx( dwTimeout, FALSE ); 02334 02335 DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2, 02336 This->dp2->lpNameServerData, dwTimeout, 02337 lpContext ); 02338 } 02339 02340 return hr; 02341 } 02342 02343 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions 02344 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 02345 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 02346 LPVOID lpContext, DWORD dwFlags ) 02347 { 02348 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02349 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2, 02350 lpContext, dwFlags, TRUE ); 02351 } 02352 02353 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions 02354 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 02355 LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 02356 LPVOID lpContext, DWORD dwFlags ) 02357 { 02358 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02359 return DP_IF_EnumSessions( This, lpsd, dwTimeout, lpEnumSessionsCallback2, 02360 lpContext, dwFlags, FALSE ); 02361 } 02362 02363 static HRESULT WINAPI DP_IF_GetPlayerCaps 02364 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps, 02365 DWORD dwFlags ) 02366 { 02367 DPSP_GETCAPSDATA data; 02368 02369 TRACE("(%p)->(0x%08lx,%p,0x%08lx)\n", This, idPlayer, lpDPCaps, dwFlags); 02370 02371 /* Query the service provider */ 02372 data.idPlayer = idPlayer; 02373 data.dwFlags = dwFlags; 02374 data.lpCaps = lpDPCaps; 02375 data.lpISP = This->dp2->spData.lpISP; 02376 02377 return (*This->dp2->spData.lpCB->GetCaps)( &data ); 02378 } 02379 02380 static HRESULT WINAPI DP_IF_GetCaps 02381 ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags ) 02382 { 02383 return DP_IF_GetPlayerCaps( This, DPID_ALLPLAYERS, lpDPCaps, dwFlags ); 02384 } 02385 02386 static HRESULT WINAPI DirectPlay2AImpl_GetCaps 02387 ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags ) 02388 { 02389 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02390 return DP_IF_GetCaps( This, lpDPCaps, dwFlags ); 02391 } 02392 02393 static HRESULT WINAPI DirectPlay2WImpl_GetCaps 02394 ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags ) 02395 { 02396 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02397 return DP_IF_GetCaps( This, lpDPCaps, dwFlags ); 02398 } 02399 02400 static HRESULT WINAPI DP_IF_GetGroupData 02401 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 02402 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi ) 02403 { 02404 lpGroupData lpGData; 02405 DWORD dwRequiredBufferSize; 02406 LPVOID lpCopyDataFrom; 02407 02408 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n", 02409 This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi ); 02410 02411 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 02412 { 02413 return DPERR_INVALIDGROUP; 02414 } 02415 02416 /* How much buffer is required? */ 02417 if( dwFlags & DPSET_LOCAL ) 02418 { 02419 dwRequiredBufferSize = lpGData->dwLocalDataSize; 02420 lpCopyDataFrom = lpGData->lpLocalData; 02421 } 02422 else 02423 { 02424 dwRequiredBufferSize = lpGData->dwRemoteDataSize; 02425 lpCopyDataFrom = lpGData->lpRemoteData; 02426 } 02427 02428 /* Is the user requesting to know how big a buffer is required? */ 02429 if( ( lpData == NULL ) || 02430 ( *lpdwDataSize < dwRequiredBufferSize ) 02431 ) 02432 { 02433 *lpdwDataSize = dwRequiredBufferSize; 02434 return DPERR_BUFFERTOOSMALL; 02435 } 02436 02437 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize ); 02438 02439 return DP_OK; 02440 } 02441 02442 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData 02443 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 02444 LPDWORD lpdwDataSize, DWORD dwFlags ) 02445 { 02446 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02447 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize, 02448 dwFlags, TRUE ); 02449 } 02450 02451 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData 02452 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 02453 LPDWORD lpdwDataSize, DWORD dwFlags ) 02454 { 02455 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02456 return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize, 02457 dwFlags, FALSE ); 02458 } 02459 02460 static HRESULT WINAPI DP_IF_GetGroupName 02461 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 02462 LPDWORD lpdwDataSize, BOOL bAnsi ) 02463 { 02464 lpGroupData lpGData; 02465 LPDPNAME lpName = (LPDPNAME)lpData; 02466 DWORD dwRequiredDataSize; 02467 02468 FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n", 02469 This, idGroup, lpData, lpdwDataSize, bAnsi ); 02470 02471 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 02472 { 02473 return DPERR_INVALIDGROUP; 02474 } 02475 02476 dwRequiredDataSize = lpGData->name.dwSize; 02477 02478 if( lpGData->name.lpszShortNameA ) 02479 { 02480 dwRequiredDataSize += strlen( lpGData->name.lpszShortNameA ) + 1; 02481 } 02482 02483 if( lpGData->name.lpszLongNameA ) 02484 { 02485 dwRequiredDataSize += strlen( lpGData->name.lpszLongNameA ) + 1; 02486 } 02487 02488 if( ( lpData == NULL ) || 02489 ( *lpdwDataSize < dwRequiredDataSize ) 02490 ) 02491 { 02492 *lpdwDataSize = dwRequiredDataSize; 02493 return DPERR_BUFFERTOOSMALL; 02494 } 02495 02496 /* Copy the structure */ 02497 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize ); 02498 02499 if( lpGData->name.lpszShortNameA ) 02500 { 02501 strcpy( ((char*)lpName)+lpGData->name.dwSize, 02502 lpGData->name.lpszShortNameA ); 02503 } 02504 else 02505 { 02506 lpName->lpszShortNameA = NULL; 02507 } 02508 02509 if( lpGData->name.lpszShortNameA ) 02510 { 02511 strcpy( ((char*)lpName)+lpGData->name.dwSize, 02512 lpGData->name.lpszLongNameA ); 02513 } 02514 else 02515 { 02516 lpName->lpszLongNameA = NULL; 02517 } 02518 02519 return DP_OK; 02520 } 02521 02522 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName 02523 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 02524 LPDWORD lpdwDataSize ) 02525 { 02526 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02527 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE ); 02528 } 02529 02530 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName 02531 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 02532 LPDWORD lpdwDataSize ) 02533 { 02534 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02535 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE ); 02536 } 02537 02538 static HRESULT WINAPI DP_IF_GetMessageCount 02539 ( IDirectPlay2Impl* This, DPID idPlayer, 02540 LPDWORD lpdwCount, BOOL bAnsi ) 02541 { 02542 FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi ); 02543 return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer, 02544 DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL, 02545 bAnsi ); 02546 } 02547 02548 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount 02549 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount ) 02550 { 02551 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02552 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, TRUE ); 02553 } 02554 02555 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount 02556 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount ) 02557 { 02558 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02559 return DP_IF_GetMessageCount( This, idPlayer, lpdwCount, FALSE ); 02560 } 02561 02562 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress 02563 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize ) 02564 { 02565 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02566 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize ); 02567 return DP_OK; 02568 } 02569 02570 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress 02571 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize ) 02572 { 02573 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02574 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize ); 02575 return DP_OK; 02576 } 02577 02578 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps 02579 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, 02580 DWORD dwFlags ) 02581 { 02582 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02583 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags ); 02584 } 02585 02586 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps 02587 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, 02588 DWORD dwFlags ) 02589 { 02590 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02591 return DP_IF_GetPlayerCaps( This, idPlayer, lpPlayerCaps, dwFlags ); 02592 } 02593 02594 static HRESULT WINAPI DP_IF_GetPlayerData 02595 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 02596 LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi ) 02597 { 02598 lpPlayerList lpPList; 02599 DWORD dwRequiredBufferSize; 02600 LPVOID lpCopyDataFrom; 02601 02602 TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n", 02603 This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi ); 02604 02605 if( This->dp2->connectionInitialized == NO_PROVIDER ) 02606 { 02607 return DPERR_UNINITIALIZED; 02608 } 02609 02610 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 02611 { 02612 return DPERR_INVALIDPLAYER; 02613 } 02614 02615 /* How much buffer is required? */ 02616 if( dwFlags & DPSET_LOCAL ) 02617 { 02618 dwRequiredBufferSize = lpPList->lpPData->dwLocalDataSize; 02619 lpCopyDataFrom = lpPList->lpPData->lpLocalData; 02620 } 02621 else 02622 { 02623 dwRequiredBufferSize = lpPList->lpPData->dwRemoteDataSize; 02624 lpCopyDataFrom = lpPList->lpPData->lpRemoteData; 02625 } 02626 02627 /* Is the user requesting to know how big a buffer is required? */ 02628 if( ( lpData == NULL ) || 02629 ( *lpdwDataSize < dwRequiredBufferSize ) 02630 ) 02631 { 02632 *lpdwDataSize = dwRequiredBufferSize; 02633 return DPERR_BUFFERTOOSMALL; 02634 } 02635 02636 CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize ); 02637 02638 return DP_OK; 02639 } 02640 02641 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData 02642 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 02643 LPDWORD lpdwDataSize, DWORD dwFlags ) 02644 { 02645 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02646 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize, 02647 dwFlags, TRUE ); 02648 } 02649 02650 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData 02651 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 02652 LPDWORD lpdwDataSize, DWORD dwFlags ) 02653 { 02654 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02655 return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize, 02656 dwFlags, FALSE ); 02657 } 02658 02659 static HRESULT WINAPI DP_IF_GetPlayerName 02660 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 02661 LPDWORD lpdwDataSize, BOOL bAnsi ) 02662 { 02663 lpPlayerList lpPList; 02664 LPDPNAME lpName = (LPDPNAME)lpData; 02665 DWORD dwRequiredDataSize; 02666 02667 FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI\n", 02668 This, idPlayer, lpData, lpdwDataSize, bAnsi ); 02669 02670 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 02671 { 02672 return DPERR_INVALIDPLAYER; 02673 } 02674 02675 dwRequiredDataSize = lpPList->lpPData->name.dwSize; 02676 02677 if( lpPList->lpPData->name.lpszShortNameA ) 02678 { 02679 dwRequiredDataSize += strlen( lpPList->lpPData->name.lpszShortNameA ) + 1; 02680 } 02681 02682 if( lpPList->lpPData->name.lpszLongNameA ) 02683 { 02684 dwRequiredDataSize += strlen( lpPList->lpPData->name.lpszLongNameA ) + 1; 02685 } 02686 02687 if( ( lpData == NULL ) || 02688 ( *lpdwDataSize < dwRequiredDataSize ) 02689 ) 02690 { 02691 *lpdwDataSize = dwRequiredDataSize; 02692 return DPERR_BUFFERTOOSMALL; 02693 } 02694 02695 /* Copy the structure */ 02696 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize ); 02697 02698 if( lpPList->lpPData->name.lpszShortNameA ) 02699 { 02700 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize, 02701 lpPList->lpPData->name.lpszShortNameA ); 02702 } 02703 else 02704 { 02705 lpName->lpszShortNameA = NULL; 02706 } 02707 02708 if( lpPList->lpPData->name.lpszShortNameA ) 02709 { 02710 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize, 02711 lpPList->lpPData->name.lpszLongNameA ); 02712 } 02713 else 02714 { 02715 lpName->lpszLongNameA = NULL; 02716 } 02717 02718 return DP_OK; 02719 } 02720 02721 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName 02722 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 02723 LPDWORD lpdwDataSize ) 02724 { 02725 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02726 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE ); 02727 } 02728 02729 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName 02730 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 02731 LPDWORD lpdwDataSize ) 02732 { 02733 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02734 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE ); 02735 } 02736 02737 static HRESULT WINAPI DP_GetSessionDesc 02738 ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize, 02739 BOOL bAnsi ) 02740 { 02741 DWORD dwRequiredSize; 02742 02743 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi ); 02744 02745 if( This->dp2->connectionInitialized == NO_PROVIDER ) 02746 { 02747 return DPERR_UNINITIALIZED; 02748 } 02749 02750 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) ) 02751 { 02752 return DPERR_INVALIDPARAMS; 02753 } 02754 02755 /* FIXME: Get from This->dp2->lpSessionDesc */ 02756 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi ); 02757 02758 if ( ( lpData == NULL ) || 02759 ( *lpdwDataSize < dwRequiredSize ) 02760 ) 02761 { 02762 *lpdwDataSize = dwRequiredSize; 02763 return DPERR_BUFFERTOOSMALL; 02764 } 02765 02766 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi ); 02767 02768 return DP_OK; 02769 } 02770 02771 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc 02772 ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize ) 02773 { 02774 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02775 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE ); 02776 } 02777 02778 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc 02779 ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize ) 02780 { 02781 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02782 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE ); 02783 } 02784 02785 /* Intended only for COM compatibility. Always returns an error. */ 02786 static HRESULT WINAPI DirectPlay2AImpl_Initialize 02787 ( LPDIRECTPLAY2A iface, LPGUID lpGUID ) 02788 { 02789 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02790 TRACE("(%p)->(%p): stub\n", This, lpGUID ); 02791 return DPERR_ALREADYINITIALIZED; 02792 } 02793 02794 /* Intended only for COM compatibility. Always returns an error. */ 02795 static HRESULT WINAPI DirectPlay2WImpl_Initialize 02796 ( LPDIRECTPLAY2 iface, LPGUID lpGUID ) 02797 { 02798 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02799 TRACE("(%p)->(%p): stub\n", This, lpGUID ); 02800 return DPERR_ALREADYINITIALIZED; 02801 } 02802 02803 02804 static HRESULT WINAPI DP_SecureOpen 02805 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 02806 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials, 02807 BOOL bAnsi ) 02808 { 02809 HRESULT hr = DP_OK; 02810 02811 FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n", 02812 This, lpsd, dwFlags, lpSecurity, lpCredentials ); 02813 02814 if( This->dp2->bConnectionOpen ) 02815 { 02816 TRACE( ": rejecting already open connection.\n" ); 02817 return DPERR_ALREADYINITIALIZED; 02818 } 02819 02820 /* If we're enumerating, kill the thread */ 02821 DP_KillEnumSessionThread( This ); 02822 02823 if( dwFlags & DPOPEN_CREATE ) 02824 { 02825 /* Rightoo - this computer is the host and the local computer needs to be 02826 the name server so that others can join this session */ 02827 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData ); 02828 02829 This->dp2->bHostInterface = TRUE; 02830 02831 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi ); 02832 if( FAILED( hr ) ) 02833 { 02834 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) ); 02835 return hr; 02836 } 02837 } 02838 02839 /* Invoke the conditional callback for the service provider */ 02840 if( This->dp2->spData.lpCB->Open ) 02841 { 02842 DPSP_OPENDATA data; 02843 02844 FIXME( "Not all data fields are correct. Need new parameter\n" ); 02845 02846 data.bCreate = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE; 02847 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL 02848 : NS_GetNSAddr( This->dp2->lpNameServerData ); 02849 data.lpISP = This->dp2->spData.lpISP; 02850 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE; 02851 data.dwOpenFlags = dwFlags; 02852 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags; 02853 02854 hr = (*This->dp2->spData.lpCB->Open)(&data); 02855 if( FAILED( hr ) ) 02856 { 02857 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) ); 02858 return hr; 02859 } 02860 } 02861 02862 { 02863 /* Create the system group of which everything is a part of */ 02864 DPID systemGroup = DPID_SYSTEM_GROUP; 02865 02866 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL, 02867 NULL, 0, 0, TRUE ); 02868 02869 } 02870 02871 if( dwFlags & DPOPEN_JOIN ) 02872 { 02873 DPID dpidServerId = DPID_UNKNOWN; 02874 02875 /* Create the server player for this interface. This way we can receive 02876 * messages for this session. 02877 */ 02878 /* FIXME: I suppose that we should be setting an event for a receive 02879 * type of thing. That way the messaging thread could know to wake 02880 * up. DPlay would then trigger the hEvent for the player the 02881 * message is directed to. 02882 */ 02883 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL, 02884 0, 02885 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi ); 02886 02887 } 02888 else if( dwFlags & DPOPEN_CREATE ) 02889 { 02890 DPID dpidNameServerId = DPID_NAME_SERVER; 02891 02892 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL, 02893 0, DPPLAYER_SERVERPLAYER, bAnsi ); 02894 } 02895 02896 if( FAILED(hr) ) 02897 { 02898 ERR( "Couldn't create name server/system player: %s\n", 02899 DPLAYX_HresultToString(hr) ); 02900 } 02901 02902 return hr; 02903 } 02904 02905 static HRESULT WINAPI DirectPlay2AImpl_Open 02906 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags ) 02907 { 02908 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02909 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags ); 02910 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, TRUE ); 02911 } 02912 02913 static HRESULT WINAPI DirectPlay2WImpl_Open 02914 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags ) 02915 { 02916 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02917 TRACE("(%p)->(%p,0x%08lx)\n", This, lpsd, dwFlags ); 02918 return DP_SecureOpen( This, lpsd, dwFlags, NULL, NULL, FALSE ); 02919 } 02920 02921 static HRESULT WINAPI DP_IF_Receive 02922 ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo, 02923 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi ) 02924 { 02925 LPDPMSG lpMsg = NULL; 02926 02927 FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n", 02928 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi ); 02929 02930 if( This->dp2->connectionInitialized == NO_PROVIDER ) 02931 { 02932 return DPERR_UNINITIALIZED; 02933 } 02934 02935 if( dwFlags == 0 ) 02936 { 02937 dwFlags = DPRECEIVE_ALL; 02938 } 02939 02940 /* If the lpData is NULL, we must be peeking the message */ 02941 if( ( lpData == NULL ) && 02942 !( dwFlags & DPRECEIVE_PEEK ) 02943 ) 02944 { 02945 return DPERR_INVALIDPARAMS; 02946 } 02947 02948 if( dwFlags & DPRECEIVE_ALL ) 02949 { 02950 lpMsg = This->dp2->receiveMsgs.lpQHFirst; 02951 02952 if( !( dwFlags & DPRECEIVE_PEEK ) ) 02953 { 02954 FIXME( "Remove from queue\n" ); 02955 } 02956 } 02957 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) || 02958 ( dwFlags & DPRECEIVE_FROMPLAYER ) 02959 ) 02960 { 02961 FIXME( "Find matching message 0x%08lx\n", dwFlags ); 02962 } 02963 else 02964 { 02965 ERR( "Hmmm..dwFlags 0x%08lx\n", dwFlags ); 02966 } 02967 02968 if( lpMsg == NULL ) 02969 { 02970 return DPERR_NOMESSAGES; 02971 } 02972 02973 /* Copy into the provided buffer */ 02974 CopyMemory( lpData, lpMsg->msg, *lpdwDataSize ); 02975 02976 return DP_OK; 02977 } 02978 02979 static HRESULT WINAPI DirectPlay2AImpl_Receive 02980 ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo, 02981 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize ) 02982 { 02983 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02984 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, 02985 lpData, lpdwDataSize, TRUE ); 02986 } 02987 02988 static HRESULT WINAPI DirectPlay2WImpl_Receive 02989 ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo, 02990 DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize ) 02991 { 02992 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 02993 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, 02994 lpData, lpdwDataSize, FALSE ); 02995 } 02996 02997 static HRESULT WINAPI DirectPlay2AImpl_Send 02998 ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize ) 02999 { 03000 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03001 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 03002 0, 0, NULL, NULL, TRUE ); 03003 } 03004 03005 static HRESULT WINAPI DirectPlay2WImpl_Send 03006 ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize ) 03007 { 03008 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03009 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 03010 0, 0, NULL, NULL, FALSE ); 03011 } 03012 03013 static HRESULT WINAPI DP_IF_SetGroupData 03014 ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 03015 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) 03016 { 03017 lpGroupData lpGData; 03018 03019 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n", 03020 This, idGroup, lpData, dwDataSize, dwFlags, bAnsi ); 03021 03022 /* Parameter check */ 03023 if( ( lpData == NULL ) && 03024 ( dwDataSize != 0 ) 03025 ) 03026 { 03027 return DPERR_INVALIDPARAMS; 03028 } 03029 03030 /* Find the pointer to the data for this player */ 03031 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 03032 { 03033 return DPERR_INVALIDOBJECT; 03034 } 03035 03036 if( !(dwFlags & DPSET_LOCAL) ) 03037 { 03038 FIXME( "Was this group created by this interface?\n" ); 03039 /* FIXME: If this is a remote update need to allow it but not 03040 * send a message. 03041 */ 03042 } 03043 03044 DP_SetGroupData( lpGData, dwFlags, lpData, dwDataSize ); 03045 03046 /* FIXME: Only send a message if this group is local to the session otherwise 03047 * it will have been rejected above 03048 */ 03049 if( !(dwFlags & DPSET_LOCAL) ) 03050 { 03051 FIXME( "Send msg?\n" ); 03052 } 03053 03054 return DP_OK; 03055 } 03056 03057 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData 03058 ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 03059 DWORD dwDataSize, DWORD dwFlags ) 03060 { 03061 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03062 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE ); 03063 } 03064 03065 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData 03066 ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 03067 DWORD dwDataSize, DWORD dwFlags ) 03068 { 03069 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03070 return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE ); 03071 } 03072 03073 static HRESULT WINAPI DP_IF_SetGroupName 03074 ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName, 03075 DWORD dwFlags, BOOL bAnsi ) 03076 { 03077 lpGroupData lpGData; 03078 03079 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup, 03080 lpGroupName, dwFlags, bAnsi ); 03081 03082 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 03083 { 03084 return DPERR_INVALIDGROUP; 03085 } 03086 03087 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi ); 03088 03089 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */ 03090 FIXME( "Message not sent and dwFlags ignored\n" ); 03091 03092 return DP_OK; 03093 } 03094 03095 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName 03096 ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName, 03097 DWORD dwFlags ) 03098 { 03099 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03100 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE ); 03101 } 03102 03103 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName 03104 ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName, 03105 DWORD dwFlags ) 03106 { 03107 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03108 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE ); 03109 } 03110 03111 static HRESULT WINAPI DP_IF_SetPlayerData 03112 ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 03113 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) 03114 { 03115 lpPlayerList lpPList; 03116 03117 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n", 03118 This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi ); 03119 03120 /* Parameter check */ 03121 if( ( lpData == NULL ) && 03122 ( dwDataSize != 0 ) 03123 ) 03124 { 03125 return DPERR_INVALIDPARAMS; 03126 } 03127 03128 /* Find the pointer to the data for this player */ 03129 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 03130 { 03131 return DPERR_INVALIDPLAYER; 03132 } 03133 03134 if( !(dwFlags & DPSET_LOCAL) ) 03135 { 03136 FIXME( "Was this group created by this interface?\n" ); 03137 /* FIXME: If this is a remote update need to allow it but not 03138 * send a message. 03139 */ 03140 } 03141 03142 DP_SetPlayerData( lpPList->lpPData, dwFlags, lpData, dwDataSize ); 03143 03144 if( !(dwFlags & DPSET_LOCAL) ) 03145 { 03146 FIXME( "Send msg?\n" ); 03147 } 03148 03149 return DP_OK; 03150 } 03151 03152 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData 03153 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 03154 DWORD dwDataSize, DWORD dwFlags ) 03155 { 03156 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03157 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize, 03158 dwFlags, TRUE ); 03159 } 03160 03161 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData 03162 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 03163 DWORD dwDataSize, DWORD dwFlags ) 03164 { 03165 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03166 return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize, 03167 dwFlags, FALSE ); 03168 } 03169 03170 static HRESULT WINAPI DP_IF_SetPlayerName 03171 ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName, 03172 DWORD dwFlags, BOOL bAnsi ) 03173 { 03174 lpPlayerList lpPList; 03175 03176 TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", 03177 This, idPlayer, lpPlayerName, dwFlags, bAnsi ); 03178 03179 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 03180 { 03181 return DPERR_INVALIDGROUP; 03182 } 03183 03184 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi ); 03185 03186 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */ 03187 FIXME( "Message not sent and dwFlags ignored\n" ); 03188 03189 return DP_OK; 03190 } 03191 03192 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName 03193 ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName, 03194 DWORD dwFlags ) 03195 { 03196 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03197 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE ); 03198 } 03199 03200 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName 03201 ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName, 03202 DWORD dwFlags ) 03203 { 03204 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03205 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE ); 03206 } 03207 03208 static HRESULT WINAPI DP_SetSessionDesc 03209 ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc, 03210 DWORD dwFlags, BOOL bInitial, BOOL bAnsi ) 03211 { 03212 DWORD dwRequiredSize; 03213 LPDPSESSIONDESC2 lpTempSessDesc; 03214 03215 TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n", 03216 This, lpSessDesc, dwFlags, bInitial, bAnsi ); 03217 03218 if( This->dp2->connectionInitialized == NO_PROVIDER ) 03219 { 03220 return DPERR_UNINITIALIZED; 03221 } 03222 03223 if( dwFlags ) 03224 { 03225 return DPERR_INVALIDPARAMS; 03226 } 03227 03228 /* Only the host is allowed to update the session desc */ 03229 if( !This->dp2->bHostInterface ) 03230 { 03231 return DPERR_ACCESSDENIED; 03232 } 03233 03234 /* FIXME: Copy into This->dp2->lpSessionDesc */ 03235 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi ); 03236 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize ); 03237 03238 if( lpTempSessDesc == NULL ) 03239 { 03240 return DPERR_OUTOFMEMORY; 03241 } 03242 03243 /* Free the old */ 03244 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc ); 03245 03246 This->dp2->lpSessionDesc = lpTempSessDesc; 03247 03248 /* Set the new */ 03249 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi ); 03250 03251 /* If this is an external invocation of the interface, we should be 03252 * letting everyone know that things have changed. Otherwise this is 03253 * just an initialization and it doesn't need to be propagated. 03254 */ 03255 if( !bInitial ) 03256 { 03257 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" ); 03258 } 03259 03260 return DP_OK; 03261 } 03262 03263 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc 03264 ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags ) 03265 { 03266 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03267 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE ); 03268 } 03269 03270 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc 03271 ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags ) 03272 { 03273 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; 03274 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE ); 03275 } 03276 03277 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */ 03278 DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi ) 03279 { 03280 DWORD dwSize = 0; 03281 03282 if( lpSessDesc == NULL ) 03283 { 03284 /* Hmmm..don't need any size? */ 03285 ERR( "NULL lpSessDesc\n" ); 03286 return dwSize; 03287 } 03288 03289 dwSize += sizeof( *lpSessDesc ); 03290 03291 if( bAnsi ) 03292 { 03293 if( lpSessDesc->lpszSessionNameA ) 03294 { 03295 dwSize += lstrlenA( lpSessDesc->lpszSessionNameA ) + 1; 03296 } 03297 03298 if( lpSessDesc->lpszPasswordA ) 03299 { 03300 dwSize += lstrlenA( lpSessDesc->lpszPasswordA ) + 1; 03301 } 03302 } 03303 else /* UNICODE */ 03304 { 03305 if( lpSessDesc->lpszSessionName ) 03306 { 03307 dwSize += sizeof( WCHAR ) * 03308 ( lstrlenW( lpSessDesc->lpszSessionName ) + 1 ); 03309 } 03310 03311 if( lpSessDesc->lpszPassword ) 03312 { 03313 dwSize += sizeof( WCHAR ) * 03314 ( lstrlenW( lpSessDesc->lpszPassword ) + 1 ); 03315 } 03316 } 03317 03318 return dwSize; 03319 } 03320 03321 /* Assumes that contugous buffers are already allocated. */ 03322 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest, 03323 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi ) 03324 { 03325 BYTE* lpStartOfFreeSpace; 03326 03327 if( lpSessionDest == NULL ) 03328 { 03329 ERR( "NULL lpSessionDest\n" ); 03330 return; 03331 } 03332 03333 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) ); 03334 03335 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc ); 03336 03337 if( bAnsi ) 03338 { 03339 if( lpSessionSrc->lpszSessionNameA ) 03340 { 03341 lstrcpyA( (LPSTR)lpStartOfFreeSpace, 03342 lpSessionDest->lpszSessionNameA ); 03343 lpSessionDest->lpszSessionNameA = (LPSTR)lpStartOfFreeSpace; 03344 lpStartOfFreeSpace += 03345 lstrlenA( (LPSTR)lpSessionDest->lpszSessionNameA ) + 1; 03346 } 03347 03348 if( lpSessionSrc->lpszPasswordA ) 03349 { 03350 lstrcpyA( (LPSTR)lpStartOfFreeSpace, 03351 lpSessionDest->lpszPasswordA ); 03352 lpSessionDest->lpszPasswordA = (LPSTR)lpStartOfFreeSpace; 03353 lpStartOfFreeSpace += 03354 lstrlenA( (LPSTR)lpSessionDest->lpszPasswordA ) + 1; 03355 } 03356 } 03357 else /* UNICODE */ 03358 { 03359 if( lpSessionSrc->lpszSessionName ) 03360 { 03361 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, 03362 lpSessionDest->lpszSessionName ); 03363 lpSessionDest->lpszSessionName = (LPWSTR)lpStartOfFreeSpace; 03364 lpStartOfFreeSpace += sizeof(WCHAR) * 03365 ( lstrlenW( (LPWSTR)lpSessionDest->lpszSessionName ) + 1 ); 03366 } 03367 03368 if( lpSessionSrc->lpszPassword ) 03369 { 03370 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, 03371 lpSessionDest->lpszPassword ); 03372 lpSessionDest->lpszPassword = (LPWSTR)lpStartOfFreeSpace; 03373 lpStartOfFreeSpace += sizeof(WCHAR) * 03374 ( lstrlenW( (LPWSTR)lpSessionDest->lpszPassword ) + 1 ); 03375 } 03376 } 03377 } 03378 03379 03380 static HRESULT WINAPI DP_IF_AddGroupToGroup 03381 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup ) 03382 { 03383 lpGroupData lpGParentData; 03384 lpGroupData lpGData; 03385 lpGroupList lpNewGList; 03386 03387 TRACE( "(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup ); 03388 03389 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL ) 03390 { 03391 return DPERR_INVALIDGROUP; 03392 } 03393 03394 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL ) 03395 { 03396 return DPERR_INVALIDGROUP; 03397 } 03398 03399 /* Create a player list (ie "shortcut" ) */ 03400 lpNewGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewGList ) ); 03401 if( lpNewGList == NULL ) 03402 { 03403 return DPERR_CANTADDPLAYER; 03404 } 03405 03406 /* Add the shortcut */ 03407 lpGData->uRef++; 03408 lpNewGList->lpGData = lpGData; 03409 03410 /* Add the player to the list of players for this group */ 03411 DPQ_INSERT( lpGData->groups, lpNewGList, groups ); 03412 03413 /* Send a ADDGROUPTOGROUP message */ 03414 FIXME( "Not sending message\n" ); 03415 03416 return DP_OK; 03417 } 03418 03419 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup 03420 ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup ) 03421 { 03422 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03423 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup ); 03424 } 03425 03426 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup 03427 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup ) 03428 { 03429 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03430 return DP_IF_AddGroupToGroup( This, idParentGroup, idGroup ); 03431 } 03432 03433 static HRESULT WINAPI DP_IF_CreateGroupInGroup 03434 ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup, 03435 LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, 03436 DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) 03437 { 03438 lpGroupData lpGParentData; 03439 lpGroupList lpGList; 03440 lpGroupData lpGData; 03441 03442 TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", 03443 This, idParentGroup, lpidGroup, lpGroupName, lpData, 03444 dwDataSize, dwFlags, bAnsi ); 03445 03446 /* Verify that the specified parent is valid */ 03447 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, 03448 idParentGroup ) ) == NULL 03449 ) 03450 { 03451 return DPERR_INVALIDGROUP; 03452 } 03453 03454 lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName, 03455 dwFlags, idParentGroup, bAnsi ); 03456 03457 if( lpGData == NULL ) 03458 { 03459 return DPERR_CANTADDPLAYER; /* yes player not group */ 03460 } 03461 03462 /* Something else is referencing this data */ 03463 lpGData->uRef++; 03464 03465 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize ); 03466 03467 /* The list has now been inserted into the interface group list. We now 03468 need to put a "shortcut" to this group in the parent group */ 03469 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) ); 03470 if( lpGList == NULL ) 03471 { 03472 FIXME( "Memory leak\n" ); 03473 return DPERR_CANTADDPLAYER; /* yes player not group */ 03474 } 03475 03476 lpGList->lpGData = lpGData; 03477 03478 DPQ_INSERT( lpGParentData->groups, lpGList, groups ); 03479 03480 /* Let the SP know that we've created this group */ 03481 if( This->dp2->spData.lpCB->CreateGroup ) 03482 { 03483 DPSP_CREATEGROUPDATA data; 03484 03485 TRACE( "Calling SP CreateGroup\n" ); 03486 03487 data.idGroup = *lpidGroup; 03488 data.dwFlags = dwFlags; 03489 data.lpSPMessageHeader = lpMsgHdr; 03490 data.lpISP = This->dp2->spData.lpISP; 03491 03492 (*This->dp2->spData.lpCB->CreateGroup)( &data ); 03493 } 03494 03495 /* Inform all other peers of the creation of a new group. If there are 03496 * no peers keep this quiet. 03497 */ 03498 if( This->dp2->lpSessionDesc && 03499 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 03500 { 03501 DPMSG_CREATEPLAYERORGROUP msg; 03502 03503 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 03504 msg.dwPlayerType = DPPLAYERTYPE_GROUP; 03505 msg.dpId = *lpidGroup; 03506 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */ 03507 msg.lpData = lpData; 03508 msg.dwDataSize = dwDataSize; 03509 msg.dpnName = *lpGroupName; 03510 03511 /* FIXME: Correct to just use send effectively? */ 03512 /* FIXME: Should size include data w/ message or just message "header" */ 03513 /* FIXME: Check return code */ 03514 DP_SendEx( (IDirectPlay2Impl*)This, 03515 DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 03516 0, 0, NULL, NULL, bAnsi ); 03517 } 03518 03519 return DP_OK; 03520 } 03521 03522 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup 03523 ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup, 03524 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 03525 DWORD dwFlags ) 03526 { 03527 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03528 03529 *lpidGroup = DPID_UNKNOWN; 03530 03531 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, 03532 lpGroupName, lpData, dwDataSize, dwFlags, 03533 TRUE ); 03534 } 03535 03536 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup 03537 ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup, 03538 LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 03539 DWORD dwFlags ) 03540 { 03541 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03542 03543 *lpidGroup = DPID_UNKNOWN; 03544 03545 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, 03546 lpGroupName, lpData, dwDataSize, 03547 dwFlags, FALSE ); 03548 } 03549 03550 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup 03551 ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup ) 03552 { 03553 lpGroupList lpGList; 03554 lpGroupData lpGParentData; 03555 03556 TRACE("(%p)->(0x%08lx,0x%08lx)\n", This, idParentGroup, idGroup ); 03557 03558 /* Is the parent group valid? */ 03559 if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL ) 03560 { 03561 return DPERR_INVALIDGROUP; 03562 } 03563 03564 /* Remove the group from the parent group queue */ 03565 DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList ); 03566 03567 if( lpGList == NULL ) 03568 { 03569 return DPERR_INVALIDGROUP; 03570 } 03571 03572 /* Decrement the ref count */ 03573 lpGList->lpGData->uRef--; 03574 03575 /* Free up the list item */ 03576 HeapFree( GetProcessHeap(), 0, lpGList ); 03577 03578 /* Should send a DELETEGROUPFROMGROUP message */ 03579 FIXME( "message not sent\n" ); 03580 03581 return DP_OK; 03582 } 03583 03584 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup 03585 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup ) 03586 { 03587 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03588 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup ); 03589 } 03590 03591 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup 03592 ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup ) 03593 { 03594 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03595 return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup ); 03596 } 03597 03598 static 03599 BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, 03600 LPDWORD lpdwBufSize ) 03601 { 03602 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; 03603 HRESULT hr; 03604 03605 dpCompoundAddress.dwDataSize = sizeof( GUID ); 03606 memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider, 03607 sizeof( GUID ) ) ; 03608 dpCompoundAddress.lpData = lpcSpGuid; 03609 03610 *lplpAddrBuf = NULL; 03611 *lpdwBufSize = 0; 03612 03613 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, 03614 lpdwBufSize, TRUE ); 03615 03616 if( hr != DPERR_BUFFERTOOSMALL ) 03617 { 03618 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); 03619 return FALSE; 03620 } 03621 03622 /* Now allocate the buffer */ 03623 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 03624 *lpdwBufSize ); 03625 03626 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, 03627 lpdwBufSize, TRUE ); 03628 if( FAILED(hr) ) 03629 { 03630 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); 03631 return FALSE; 03632 } 03633 03634 return TRUE; 03635 } 03636 03637 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections 03638 ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags ) 03639 { 03640 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03641 TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags ); 03642 03643 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */ 03644 if( dwFlags == 0 ) 03645 { 03646 dwFlags = DPCONNECTION_DIRECTPLAY; 03647 } 03648 03649 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) || 03650 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) 03651 ) 03652 { 03653 return DPERR_INVALIDFLAGS; 03654 } 03655 03656 if( !lpEnumCallback || !*lpEnumCallback ) 03657 { 03658 return DPERR_INVALIDPARAMS; 03659 } 03660 03661 /* Enumerate DirectPlay service providers */ 03662 if( dwFlags & DPCONNECTION_DIRECTPLAY ) 03663 { 03664 HKEY hkResult; 03665 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; 03666 LPCSTR guidDataSubKey = "Guid"; 03667 char subKeyName[51]; 03668 DWORD dwIndex, sizeOfSubKeyName=50; 03669 FILETIME filetime; 03670 03671 /* Need to loop over the service providers in the registry */ 03672 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 03673 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 03674 { 03675 /* Hmmm. Does this mean that there are no service providers? */ 03676 ERR(": no service providers?\n"); 03677 return DP_OK; 03678 } 03679 03680 03681 /* Traverse all the service providers we have available */ 03682 for( dwIndex=0; 03683 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 03684 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 03685 ++dwIndex, sizeOfSubKeyName=51 ) 03686 { 03687 03688 HKEY hkServiceProvider; 03689 GUID serviceProviderGUID; 03690 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 03691 char returnBuffer[51]; 03692 WCHAR buff[51]; 03693 DPNAME dpName; 03694 BOOL bBuildPass; 03695 03696 LPVOID lpAddressBuffer = NULL; 03697 DWORD dwAddressBufferSize = 0; 03698 03699 TRACE(" this time through: %s\n", subKeyName ); 03700 03701 /* Get a handle for this particular service provider */ 03702 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 03703 &hkServiceProvider ) != ERROR_SUCCESS ) 03704 { 03705 ERR(": what the heck is going on?\n" ); 03706 continue; 03707 } 03708 03709 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 03710 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 03711 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 03712 { 03713 ERR(": missing GUID registry data members\n" ); 03714 continue; 03715 } 03716 03717 /* FIXME: Check return types to ensure we're interpreting data right */ 03718 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) ); 03719 CLSIDFromString( buff, &serviceProviderGUID ); 03720 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 03721 03722 /* Fill in the DPNAME struct for the service provider */ 03723 dpName.dwSize = sizeof( dpName ); 03724 dpName.dwFlags = 0; 03725 dpName.lpszShortNameA = subKeyName; 03726 dpName.lpszLongNameA = NULL; 03727 03728 /* Create the compound address for the service provider. 03729 * NOTE: This is a gruesome architectural scar right now. DP 03730 * uses DPL and DPL uses DP. Nasty stuff. This may be why the 03731 * native dll just gets around this little bit by allocating an 03732 * 80 byte buffer which isn't even filled with a valid compound 03733 * address. Oh well. Creating a proper compound address is the 03734 * way to go anyways despite this method taking slightly more 03735 * heap space and realtime :) */ 03736 03737 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID, 03738 &lpAddressBuffer, 03739 &dwAddressBufferSize ); 03740 if( !bBuildPass ) 03741 { 03742 ERR( "Can't build compound addr\n" ); 03743 return DPERR_GENERIC; 03744 } 03745 03746 /* The enumeration will return FALSE if we are not to continue */ 03747 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 03748 &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) ) 03749 { 03750 return DP_OK; 03751 } 03752 } 03753 } 03754 03755 /* Enumerate DirectPlayLobby service providers */ 03756 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) 03757 { 03758 HKEY hkResult; 03759 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers"; 03760 LPCSTR guidDataSubKey = "Guid"; 03761 char subKeyName[51]; 03762 DWORD dwIndex, sizeOfSubKeyName=50; 03763 FILETIME filetime; 03764 03765 /* Need to loop over the service providers in the registry */ 03766 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 03767 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 03768 { 03769 /* Hmmm. Does this mean that there are no service providers? */ 03770 ERR(": no service providers?\n"); 03771 return DP_OK; 03772 } 03773 03774 03775 /* Traverse all the lobby providers we have available */ 03776 for( dwIndex=0; 03777 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 03778 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 03779 ++dwIndex, sizeOfSubKeyName=51 ) 03780 { 03781 03782 HKEY hkServiceProvider; 03783 GUID serviceProviderGUID; 03784 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 03785 char returnBuffer[51]; 03786 WCHAR buff[51]; 03787 DPNAME dpName; 03788 HRESULT hr; 03789 03790 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; 03791 LPVOID lpAddressBuffer = NULL; 03792 DWORD dwAddressBufferSize = 0; 03793 03794 TRACE(" this time through: %s\n", subKeyName ); 03795 03796 /* Get a handle for this particular service provider */ 03797 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 03798 &hkServiceProvider ) != ERROR_SUCCESS ) 03799 { 03800 ERR(": what the heck is going on?\n" ); 03801 continue; 03802 } 03803 03804 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 03805 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 03806 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 03807 { 03808 ERR(": missing GUID registry data members\n" ); 03809 continue; 03810 } 03811 03812 /* FIXME: Check return types to ensure we're interpreting data right */ 03813 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) ); 03814 CLSIDFromString( buff, &serviceProviderGUID ); 03815 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 03816 03817 /* Fill in the DPNAME struct for the service provider */ 03818 dpName.dwSize = sizeof( dpName ); 03819 dpName.dwFlags = 0; 03820 dpName.lpszShortNameA = subKeyName; 03821 dpName.lpszLongNameA = NULL; 03822 03823 /* Create the compound address for the service provider. 03824 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP 03825 nast stuff. This may be why the native dll just gets around this little bit by 03826 allocating an 80 byte buffer which isn't even a filled with a valid compound 03827 address. Oh well. Creating a proper compound address is the way to go anyways 03828 despite this method taking slightly more heap space and realtime :) */ 03829 03830 dpCompoundAddress.guidDataType = DPAID_LobbyProvider; 03831 dpCompoundAddress.dwDataSize = sizeof( GUID ); 03832 dpCompoundAddress.lpData = &serviceProviderGUID; 03833 03834 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 03835 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL ) 03836 { 03837 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); 03838 return hr; 03839 } 03840 03841 /* Now allocate the buffer */ 03842 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize ); 03843 03844 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 03845 &dwAddressBufferSize, TRUE ) ) != DP_OK ) 03846 { 03847 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); 03848 return hr; 03849 } 03850 03851 /* The enumeration will return FALSE if we are not to continue */ 03852 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 03853 &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) ) 03854 { 03855 return DP_OK; 03856 } 03857 } 03858 } 03859 03860 return DP_OK; 03861 } 03862 03863 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections 03864 ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags ) 03865 { 03866 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03867 FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags ); 03868 return DP_OK; 03869 } 03870 03871 static HRESULT WINAPI DP_IF_EnumGroupsInGroup 03872 ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance, 03873 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 03874 LPVOID lpContext, DWORD dwFlags, BOOL bAnsi ) 03875 { 03876 lpGroupList lpGList; 03877 lpGroupData lpGData; 03878 03879 FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n", 03880 This, idGroup, lpguidInstance, lpEnumPlayersCallback2, 03881 lpContext, dwFlags, bAnsi ); 03882 03883 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL ) 03884 { 03885 return DPERR_INVALIDGROUP; 03886 } 03887 03888 if( DPQ_IS_EMPTY( lpGData->groups ) ) 03889 { 03890 return DP_OK; 03891 } 03892 03893 lpGList = DPQ_FIRST( lpGData->groups ); 03894 03895 for( ;; ) 03896 { 03897 /* FIXME: Should check dwFlags for match here */ 03898 03899 if( !(*lpEnumPlayersCallback2)( lpGList->lpGData->dpid, DPPLAYERTYPE_GROUP, 03900 &lpGList->lpGData->name, dwFlags, 03901 lpContext ) ) 03902 { 03903 return DP_OK; /* User requested break */ 03904 } 03905 03906 if( DPQ_IS_ENDOFLIST( lpGList->groups ) ) 03907 { 03908 break; 03909 } 03910 03911 lpGList = DPQ_NEXT( lpGList->groups ); 03912 03913 } 03914 03915 return DP_OK; 03916 } 03917 03918 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup 03919 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance, 03920 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, 03921 DWORD dwFlags ) 03922 { 03923 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03924 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance, 03925 lpEnumPlayersCallback2, lpContext, dwFlags, 03926 TRUE ); 03927 } 03928 03929 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup 03930 ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance, 03931 LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, 03932 DWORD dwFlags ) 03933 { 03934 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03935 return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance, 03936 lpEnumPlayersCallback2, lpContext, dwFlags, 03937 FALSE ); 03938 } 03939 03940 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings 03941 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize ) 03942 { 03943 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03944 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize ); 03945 return DP_OK; 03946 } 03947 03948 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings 03949 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize ) 03950 { 03951 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 03952 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize ); 03953 return DP_OK; 03954 } 03955 03956 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress( 03957 REFGUID guidDataType, 03958 DWORD dwDataSize, 03959 LPCVOID lpData, 03960 LPVOID lpContext ) 03961 { 03962 /* Looking for the GUID of the provider to load */ 03963 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) || 03964 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) ) 03965 ) 03966 { 03967 TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n", 03968 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize ); 03969 03970 if( dwDataSize != sizeof( GUID ) ) 03971 { 03972 ERR( "Invalid sp/lp guid size 0x%08lx\n", dwDataSize ); 03973 } 03974 03975 memcpy( lpContext, lpData, dwDataSize ); 03976 03977 /* There shouldn't be more than 1 GUID/compound address */ 03978 return FALSE; 03979 } 03980 03981 /* Still waiting for what we want */ 03982 return TRUE; 03983 } 03984 03985 03986 /* Find and perform a LoadLibrary on the requested SP or LP GUID */ 03987 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp ) 03988 { 03989 UINT i; 03990 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; 03991 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers"; 03992 LPCSTR guidDataSubKey = "Guid"; 03993 LPCSTR majVerDataSubKey = "dwReserved1"; 03994 LPCSTR minVerDataSubKey = "dwReserved2"; 03995 LPCSTR pathSubKey = "Path"; 03996 03997 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) ); 03998 03999 /* FIXME: Cloned code with a quick hack. */ 04000 for( i=0; i<2; i++ ) 04001 { 04002 HKEY hkResult; 04003 LPCSTR searchSubKey; 04004 char subKeyName[51]; 04005 DWORD dwIndex, sizeOfSubKeyName=50; 04006 FILETIME filetime; 04007 04008 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey ); 04009 *lpbIsDpSp = (i == 0) ? TRUE : FALSE; 04010 04011 04012 /* Need to loop over the service providers in the registry */ 04013 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 04014 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 04015 { 04016 /* Hmmm. Does this mean that there are no service providers? */ 04017 ERR(": no service providers?\n"); 04018 return 0; 04019 } 04020 04021 /* Traverse all the service providers we have available */ 04022 for( dwIndex=0; 04023 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 04024 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 04025 ++dwIndex, sizeOfSubKeyName=51 ) 04026 { 04027 04028 HKEY hkServiceProvider; 04029 GUID serviceProviderGUID; 04030 DWORD returnType, sizeOfReturnBuffer = 255; 04031 char returnBuffer[256]; 04032 WCHAR buff[51]; 04033 DWORD dwTemp, len; 04034 04035 TRACE(" this time through: %s\n", subKeyName ); 04036 04037 /* Get a handle for this particular service provider */ 04038 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 04039 &hkServiceProvider ) != ERROR_SUCCESS ) 04040 { 04041 ERR(": what the heck is going on?\n" ); 04042 continue; 04043 } 04044 04045 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 04046 NULL, &returnType, (LPBYTE)returnBuffer, 04047 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 04048 { 04049 ERR(": missing GUID registry data members\n" ); 04050 continue; 04051 } 04052 04053 /* FIXME: Check return types to ensure we're interpreting data right */ 04054 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) ); 04055 CLSIDFromString( buff, &serviceProviderGUID ); 04056 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 04057 04058 /* Determine if this is the Service Provider that the user asked for */ 04059 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) ) 04060 { 04061 continue; 04062 } 04063 04064 if( i == 0 ) /* DP SP */ 04065 { 04066 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 ); 04067 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); 04068 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len ); 04069 } 04070 04071 sizeOfReturnBuffer = 255; 04072 04073 /* Get dwReserved1 */ 04074 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey, 04075 NULL, &returnType, (LPBYTE)returnBuffer, 04076 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 04077 { 04078 ERR(": missing dwReserved1 registry data members\n") ; 04079 continue; 04080 } 04081 04082 if( i == 0 ) 04083 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) ); 04084 04085 sizeOfReturnBuffer = 255; 04086 04087 /* Get dwReserved2 */ 04088 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey, 04089 NULL, &returnType, (LPBYTE)returnBuffer, 04090 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 04091 { 04092 ERR(": missing dwReserved1 registry data members\n") ; 04093 continue; 04094 } 04095 04096 if( i == 0 ) 04097 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) ); 04098 04099 sizeOfReturnBuffer = 255; 04100 04101 /* Get the path for this service provider */ 04102 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey, 04103 NULL, NULL, (LPBYTE)returnBuffer, 04104 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS ) 04105 { 04106 ERR(": missing PATH registry data members: 0x%08lx\n", dwTemp ); 04107 continue; 04108 } 04109 04110 TRACE( "Loading %s\n", returnBuffer ); 04111 return LoadLibraryA( returnBuffer ); 04112 } 04113 } 04114 04115 return 0; 04116 } 04117 04118 static 04119 HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider ) 04120 { 04121 HRESULT hr; 04122 LPDPSP_SPINIT SPInit; 04123 04124 /* Initialize the service provider by calling SPInit */ 04125 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" ); 04126 04127 if( SPInit == NULL ) 04128 { 04129 ERR( "Service provider doesn't provide SPInit interface?\n" ); 04130 FreeLibrary( hServiceProvider ); 04131 return DPERR_UNAVAILABLE; 04132 } 04133 04134 TRACE( "Calling SPInit (DP SP entry point)\n" ); 04135 04136 hr = (*SPInit)( &This->dp2->spData ); 04137 04138 if( FAILED(hr) ) 04139 { 04140 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); 04141 FreeLibrary( hServiceProvider ); 04142 return hr; 04143 } 04144 04145 /* FIXME: Need to verify the sanity of the returned callback table 04146 * using IsBadCodePtr */ 04147 This->dp2->bSPInitialized = TRUE; 04148 04149 /* This interface is now initialized as a DP object */ 04150 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER; 04151 04152 /* Store the handle of the module so that we can unload it later */ 04153 This->dp2->hServiceProvider = hServiceProvider; 04154 04155 return hr; 04156 } 04157 04158 static 04159 HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider ) 04160 { 04161 HRESULT hr; 04162 LPSP_INIT DPLSPInit; 04163 04164 /* Initialize the service provider by calling SPInit */ 04165 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" ); 04166 04167 if( DPLSPInit == NULL ) 04168 { 04169 ERR( "Service provider doesn't provide DPLSPInit interface?\n" ); 04170 FreeLibrary( hLobbyProvider ); 04171 return DPERR_UNAVAILABLE; 04172 } 04173 04174 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" ); 04175 04176 hr = (*DPLSPInit)( &This->dp2->dplspData ); 04177 04178 if( FAILED(hr) ) 04179 { 04180 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); 04181 FreeLibrary( hLobbyProvider ); 04182 return hr; 04183 } 04184 04185 /* FIXME: Need to verify the sanity of the returned callback table 04186 * using IsBadCodePtr */ 04187 04188 This->dp2->bDPLSPInitialized = TRUE; 04189 04190 /* This interface is now initialized as a lobby object */ 04191 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER; 04192 04193 /* Store the handle of the module so that we can unload it later */ 04194 This->dp2->hDPLobbyProvider = hLobbyProvider; 04195 04196 return hr; 04197 } 04198 04199 static HRESULT WINAPI DP_IF_InitializeConnection 04200 ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi ) 04201 { 04202 HMODULE hServiceProvider; 04203 HRESULT hr; 04204 GUID guidSP; 04205 const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */ 04206 BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */ 04207 04208 TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi ); 04209 04210 if( dwFlags != 0 ) 04211 { 04212 return DPERR_INVALIDFLAGS; 04213 } 04214 04215 /* Find out what the requested SP is and how large this buffer is */ 04216 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection, 04217 dwAddrSize, &guidSP ); 04218 04219 if( FAILED(hr) ) 04220 { 04221 ERR( "Invalid compound address?\n" ); 04222 return DPERR_UNAVAILABLE; 04223 } 04224 04225 /* Load the service provider */ 04226 hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp ); 04227 04228 if( hServiceProvider == 0 ) 04229 { 04230 ERR( "Unable to load service provider\n" ); 04231 return DPERR_UNAVAILABLE; 04232 } 04233 04234 if( bIsDpSp ) 04235 { 04236 /* Fill in what we can of the Service Provider required information. 04237 * The rest was be done in DP_LoadSP 04238 */ 04239 This->dp2->spData.lpAddress = lpConnection; 04240 This->dp2->spData.dwAddressSize = dwAddrSize; 04241 This->dp2->spData.lpGuid = &guidSP; 04242 04243 hr = DP_InitializeDPSP( This, hServiceProvider ); 04244 } 04245 else 04246 { 04247 This->dp2->dplspData.lpAddress = lpConnection; 04248 04249 hr = DP_InitializeDPLSP( This, hServiceProvider ); 04250 } 04251 04252 if( FAILED(hr) ) 04253 { 04254 return hr; 04255 } 04256 04257 return DP_OK; 04258 } 04259 04260 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection 04261 ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags ) 04262 { 04263 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04264 04265 /* This may not be externally invoked once either an SP or LP is initialized */ 04266 if( This->dp2->connectionInitialized != NO_PROVIDER ) 04267 { 04268 return DPERR_ALREADYINITIALIZED; 04269 } 04270 04271 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE ); 04272 } 04273 04274 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection 04275 ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags ) 04276 { 04277 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04278 04279 /* This may not be externally invoked once either an SP or LP is initialized */ 04280 if( This->dp2->connectionInitialized != NO_PROVIDER ) 04281 { 04282 return DPERR_ALREADYINITIALIZED; 04283 } 04284 04285 return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE ); 04286 } 04287 04288 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen 04289 ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 04290 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials ) 04291 { 04292 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */ 04293 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE ); 04294 } 04295 04296 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen 04297 ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 04298 LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials ) 04299 { 04300 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* Yes a dp 2 interface */ 04301 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE ); 04302 } 04303 04304 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage 04305 ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage ) 04306 { 04307 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04308 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage ); 04309 return DP_OK; 04310 } 04311 04312 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage 04313 ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage ) 04314 { 04315 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04316 FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage ); 04317 return DP_OK; 04318 } 04319 04320 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings 04321 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection ) 04322 { 04323 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04324 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection ); 04325 return DP_OK; 04326 } 04327 04328 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings 04329 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection ) 04330 { 04331 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04332 FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection ); 04333 return DP_OK; 04334 } 04335 04336 static HRESULT WINAPI DirectPlay3AImpl_StartSession 04337 ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup ) 04338 { 04339 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04340 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup ); 04341 return DP_OK; 04342 } 04343 04344 static HRESULT WINAPI DirectPlay3WImpl_StartSession 04345 ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup ) 04346 { 04347 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04348 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup ); 04349 return DP_OK; 04350 } 04351 04352 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags 04353 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags ) 04354 { 04355 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04356 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags ); 04357 return DP_OK; 04358 } 04359 04360 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags 04361 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags ) 04362 { 04363 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04364 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags ); 04365 return DP_OK; 04366 } 04367 04368 static HRESULT WINAPI DP_IF_GetGroupParent 04369 ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup, 04370 BOOL bAnsi ) 04371 { 04372 lpGroupData lpGData; 04373 04374 TRACE("(%p)->(0x%08lx,%p,%u)\n", This, idGroup, lpidGroup, bAnsi ); 04375 04376 if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL ) 04377 { 04378 return DPERR_INVALIDGROUP; 04379 } 04380 04381 *lpidGroup = lpGData->dpid; 04382 04383 return DP_OK; 04384 } 04385 04386 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent 04387 ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup ) 04388 { 04389 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04390 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE ); 04391 } 04392 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent 04393 ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup ) 04394 { 04395 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04396 return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE ); 04397 } 04398 04399 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount 04400 ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize ) 04401 { 04402 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04403 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize ); 04404 return DP_OK; 04405 } 04406 04407 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount 04408 ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize ) 04409 { 04410 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04411 FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize ); 04412 return DP_OK; 04413 } 04414 04415 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags 04416 ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags ) 04417 { 04418 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04419 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags ); 04420 return DP_OK; 04421 } 04422 04423 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags 04424 ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags ) 04425 { 04426 IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface; 04427 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags ); 04428 return DP_OK; 04429 } 04430 04431 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner 04432 ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner ) 04433 { 04434 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04435 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner ); 04436 return DP_OK; 04437 } 04438 04439 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner 04440 ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner ) 04441 { 04442 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04443 FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner ); 04444 return DP_OK; 04445 } 04446 04447 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner 04448 ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner ) 04449 { 04450 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04451 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner ); 04452 return DP_OK; 04453 } 04454 04455 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner 04456 ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner ) 04457 { 04458 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04459 FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner ); 04460 return DP_OK; 04461 } 04462 04463 static HRESULT WINAPI DP_SendEx 04464 ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 04465 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 04466 LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi ) 04467 { 04468 lpPlayerList lpPList; 04469 lpGroupData lpGData; 04470 BOOL bValidDestination = FALSE; 04471 04472 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p,%u)" 04473 ": stub\n", 04474 This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority, 04475 dwTimeout, lpContext, lpdwMsgID, bAnsi ); 04476 04477 /* FIXME: Add parameter checking */ 04478 /* FIXME: First call to this needs to aquire a message id which will be 04479 * used for multiple sends 04480 */ 04481 04482 /* NOTE: Can't send messages to yourself - this will be trapped in receive */ 04483 04484 /* Verify that the message is being sent from a valid local player. The 04485 * from player may be anonymous DPID_UNKNOWN 04486 */ 04487 if( idFrom != DPID_UNKNOWN ) 04488 { 04489 if( ( lpPList = DP_FindPlayer( This, idFrom ) ) == NULL ) 04490 { 04491 WARN( "INFO: Invalid from player 0x%08lx\n", idFrom ); 04492 return DPERR_INVALIDPLAYER; 04493 } 04494 } 04495 04496 /* Verify that the message is being sent to a valid player, group or to 04497 * everyone. If it's valid, send it to those players. 04498 */ 04499 if( idTo == DPID_ALLPLAYERS ) 04500 { 04501 bValidDestination = TRUE; 04502 04503 /* See if SP has the ability to multicast. If so, use it */ 04504 if( This->dp2->spData.lpCB->SendToGroupEx ) 04505 { 04506 FIXME( "Use group sendex to group 0\n" ); 04507 } 04508 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */ 04509 { 04510 FIXME( "Use obsolete group send to group 0\n" ); 04511 } 04512 else /* No multicast, multiplicate */ 04513 { 04514 /* Send to all players we know about */ 04515 FIXME( "Send to all players using EnumPlayersInGroup\n" ); 04516 } 04517 } 04518 04519 if( ( !bValidDestination ) && 04520 ( DP_FindPlayer( This, idTo ) != NULL ) 04521 ) 04522 { 04523 bValidDestination = TRUE; 04524 04525 /* Have the service provider send this message */ 04526 /* FIXME: Could optimize for local interface sends */ 04527 return DP_SP_SendEx( This, dwFlags, lpData, dwDataSize, dwPriority, 04528 dwTimeout, lpContext, lpdwMsgID ); 04529 } 04530 04531 if( ( !bValidDestination ) && 04532 ( ( lpGData = DP_FindAnyGroup( This, idTo ) ) != NULL ) 04533 ) 04534 { 04535 bValidDestination = TRUE; 04536 04537 /* See if SP has the ability to multicast. If so, use it */ 04538 if( This->dp2->spData.lpCB->SendToGroupEx ) 04539 { 04540 FIXME( "Use group sendex\n" ); 04541 } 04542 else if( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */ 04543 { 04544 FIXME( "Use obsolete group send to group\n" ); 04545 } 04546 else /* No multicast, multiplicate */ 04547 { 04548 FIXME( "Send to all players using EnumPlayersInGroup\n" ); 04549 } 04550 04551 #if 0 04552 if( bExpectReply ) 04553 { 04554 DWORD dwWaitReturn; 04555 04556 This->dp2->hReplyEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); 04557 04558 dwWaitReturn = WaitForSingleObject( hReplyEvent, dwTimeout ); 04559 if( dwWaitReturn != WAIT_OBJECT_0 ) 04560 { 04561 ERR( "Wait failed 0x%08lx\n", dwWaitReturn ); 04562 } 04563 } 04564 #endif 04565 } 04566 04567 if( !bValidDestination ) 04568 { 04569 return DPERR_INVALIDPLAYER; 04570 } 04571 else 04572 { 04573 /* FIXME: Should return what the send returned */ 04574 return DP_OK; 04575 } 04576 } 04577 04578 04579 static HRESULT WINAPI DirectPlay4AImpl_SendEx 04580 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, 04581 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 04582 LPVOID lpContext, LPDWORD lpdwMsgID ) 04583 { 04584 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */ 04585 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 04586 dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE ); 04587 } 04588 04589 static HRESULT WINAPI DirectPlay4WImpl_SendEx 04590 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, 04591 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 04592 LPVOID lpContext, LPDWORD lpdwMsgID ) 04593 { 04594 IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface; /* yes downcast to 2 */ 04595 return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 04596 dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE ); 04597 } 04598 04599 static HRESULT WINAPI DP_SP_SendEx 04600 ( IDirectPlay2Impl* This, DWORD dwFlags, 04601 LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, 04602 LPVOID lpContext, LPDWORD lpdwMsgID ) 04603 { 04604 LPDPMSG lpMElem; 04605 04606 FIXME( ": stub\n" ); 04607 04608 /* FIXME: This queuing should only be for async messages */ 04609 04610 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) ); 04611 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); 04612 04613 CopyMemory( lpMElem->msg, lpData, dwDataSize ); 04614 04615 /* FIXME: Need to queue based on priority */ 04616 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs ); 04617 04618 return DP_OK; 04619 } 04620 04621 static HRESULT WINAPI DP_IF_GetMessageQueue 04622 ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 04623 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi ) 04624 { 04625 HRESULT hr = DP_OK; 04626 04627 FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n", 04628 This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi ); 04629 04630 /* FIXME: Do we need to do idFrom and idTo sanity checking here? */ 04631 /* FIXME: What about sends which are not immediate? */ 04632 04633 if( This->dp2->spData.lpCB->GetMessageQueue ) 04634 { 04635 DPSP_GETMESSAGEQUEUEDATA data; 04636 04637 FIXME( "Calling SP GetMessageQueue - is it right?\n" ); 04638 04639 /* FIXME: None of this is documented :( */ 04640 04641 data.lpISP = This->dp2->spData.lpISP; 04642 data.dwFlags = dwFlags; 04643 data.idFrom = idFrom; 04644 data.idTo = idTo; 04645 data.lpdwNumMsgs = lpdwNumMsgs; 04646 data.lpdwNumBytes = lpdwNumBytes; 04647 04648 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data ); 04649 } 04650 else 04651 { 04652 FIXME( "No SP for GetMessageQueue - fake some data\n" ); 04653 } 04654 04655 return hr; 04656 } 04657 04658 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue 04659 ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, 04660 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes ) 04661 { 04662 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04663 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs, 04664 lpdwNumBytes, TRUE ); 04665 } 04666 04667 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue 04668 ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, 04669 LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes ) 04670 { 04671 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04672 return DP_IF_GetMessageQueue( This, idFrom, idTo, dwFlags, lpdwNumMsgs, 04673 lpdwNumBytes, FALSE ); 04674 } 04675 04676 static HRESULT WINAPI DP_IF_CancelMessage 04677 ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags, 04678 DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi ) 04679 { 04680 HRESULT hr = DP_OK; 04681 04682 FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n", 04683 This, dwMsgID, dwFlags, bAnsi ); 04684 04685 if( This->dp2->spData.lpCB->Cancel ) 04686 { 04687 DPSP_CANCELDATA data; 04688 04689 TRACE( "Calling SP Cancel\n" ); 04690 04691 /* FIXME: Undocumented callback */ 04692 04693 data.lpISP = This->dp2->spData.lpISP; 04694 data.dwFlags = dwFlags; 04695 data.lprglpvSPMsgID = NULL; 04696 data.cSPMsgID = dwMsgID; 04697 data.dwMinPriority = dwMinPriority; 04698 data.dwMaxPriority = dwMaxPriority; 04699 04700 hr = (*This->dp2->spData.lpCB->Cancel)( &data ); 04701 } 04702 else 04703 { 04704 FIXME( "SP doesn't implement Cancel\n" ); 04705 } 04706 04707 return hr; 04708 } 04709 04710 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage 04711 ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags ) 04712 { 04713 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04714 04715 if( dwFlags != 0 ) 04716 { 04717 return DPERR_INVALIDFLAGS; 04718 } 04719 04720 if( dwMsgID == 0 ) 04721 { 04722 dwFlags |= DPCANCELSEND_ALL; 04723 } 04724 04725 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE ); 04726 } 04727 04728 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage 04729 ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags ) 04730 { 04731 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04732 04733 if( dwFlags != 0 ) 04734 { 04735 return DPERR_INVALIDFLAGS; 04736 } 04737 04738 if( dwMsgID == 0 ) 04739 { 04740 dwFlags |= DPCANCELSEND_ALL; 04741 } 04742 04743 return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, FALSE ); 04744 } 04745 04746 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority 04747 ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority, 04748 DWORD dwFlags ) 04749 { 04750 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04751 04752 if( dwFlags != 0 ) 04753 { 04754 return DPERR_INVALIDFLAGS; 04755 } 04756 04757 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority, 04758 dwMaxPriority, TRUE ); 04759 } 04760 04761 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority 04762 ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority, 04763 DWORD dwFlags ) 04764 { 04765 IDirectPlay4Impl *This = (IDirectPlay4Impl *)iface; 04766 04767 if( dwFlags != 0 ) 04768 { 04769 return DPERR_INVALIDFLAGS; 04770 } 04771 04772 return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority, 04773 dwMaxPriority, FALSE ); 04774 } 04775 04776 /* Note: Hack so we can reuse the old functions without compiler warnings */ 04777 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 04778 # define XCAST(fun) (typeof(directPlay2WVT.fun)) 04779 #else 04780 # define XCAST(fun) (void*) 04781 #endif 04782 04783 static const IDirectPlay2Vtbl directPlay2WVT = 04784 { 04785 XCAST(QueryInterface)DP_QueryInterface, 04786 XCAST(AddRef)DP_AddRef, 04787 XCAST(Release)DP_Release, 04788 04789 DirectPlay2WImpl_AddPlayerToGroup, 04790 DirectPlay2WImpl_Close, 04791 DirectPlay2WImpl_CreateGroup, 04792 DirectPlay2WImpl_CreatePlayer, 04793 DirectPlay2WImpl_DeletePlayerFromGroup, 04794 DirectPlay2WImpl_DestroyGroup, 04795 DirectPlay2WImpl_DestroyPlayer, 04796 DirectPlay2WImpl_EnumGroupPlayers, 04797 DirectPlay2WImpl_EnumGroups, 04798 DirectPlay2WImpl_EnumPlayers, 04799 DirectPlay2WImpl_EnumSessions, 04800 DirectPlay2WImpl_GetCaps, 04801 DirectPlay2WImpl_GetGroupData, 04802 DirectPlay2WImpl_GetGroupName, 04803 DirectPlay2WImpl_GetMessageCount, 04804 DirectPlay2WImpl_GetPlayerAddress, 04805 DirectPlay2WImpl_GetPlayerCaps, 04806 DirectPlay2WImpl_GetPlayerData, 04807 DirectPlay2WImpl_GetPlayerName, 04808 DirectPlay2WImpl_GetSessionDesc, 04809 DirectPlay2WImpl_Initialize, 04810 DirectPlay2WImpl_Open, 04811 DirectPlay2WImpl_Receive, 04812 DirectPlay2WImpl_Send, 04813 DirectPlay2WImpl_SetGroupData, 04814 DirectPlay2WImpl_SetGroupName, 04815 DirectPlay2WImpl_SetPlayerData, 04816 DirectPlay2WImpl_SetPlayerName, 04817 DirectPlay2WImpl_SetSessionDesc 04818 }; 04819 #undef XCAST 04820 04821 /* Note: Hack so we can reuse the old functions without compiler warnings */ 04822 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 04823 # define XCAST(fun) (typeof(directPlay2AVT.fun)) 04824 #else 04825 # define XCAST(fun) (void*) 04826 #endif 04827 04828 static const IDirectPlay2Vtbl directPlay2AVT = 04829 { 04830 XCAST(QueryInterface)DP_QueryInterface, 04831 XCAST(AddRef)DP_AddRef, 04832 XCAST(Release)DP_Release, 04833 04834 DirectPlay2AImpl_AddPlayerToGroup, 04835 DirectPlay2AImpl_Close, 04836 DirectPlay2AImpl_CreateGroup, 04837 DirectPlay2AImpl_CreatePlayer, 04838 DirectPlay2AImpl_DeletePlayerFromGroup, 04839 DirectPlay2AImpl_DestroyGroup, 04840 DirectPlay2AImpl_DestroyPlayer, 04841 DirectPlay2AImpl_EnumGroupPlayers, 04842 DirectPlay2AImpl_EnumGroups, 04843 DirectPlay2AImpl_EnumPlayers, 04844 DirectPlay2AImpl_EnumSessions, 04845 DirectPlay2AImpl_GetCaps, 04846 DirectPlay2AImpl_GetGroupData, 04847 DirectPlay2AImpl_GetGroupName, 04848 DirectPlay2AImpl_GetMessageCount, 04849 DirectPlay2AImpl_GetPlayerAddress, 04850 DirectPlay2AImpl_GetPlayerCaps, 04851 DirectPlay2AImpl_GetPlayerData, 04852 DirectPlay2AImpl_GetPlayerName, 04853 DirectPlay2AImpl_GetSessionDesc, 04854 DirectPlay2AImpl_Initialize, 04855 DirectPlay2AImpl_Open, 04856 DirectPlay2AImpl_Receive, 04857 DirectPlay2AImpl_Send, 04858 DirectPlay2AImpl_SetGroupData, 04859 DirectPlay2AImpl_SetGroupName, 04860 DirectPlay2AImpl_SetPlayerData, 04861 DirectPlay2AImpl_SetPlayerName, 04862 DirectPlay2AImpl_SetSessionDesc 04863 }; 04864 #undef XCAST 04865 04866 04867 /* Note: Hack so we can reuse the old functions without compiler warnings */ 04868 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 04869 # define XCAST(fun) (typeof(directPlay3AVT.fun)) 04870 #else 04871 # define XCAST(fun) (void*) 04872 #endif 04873 04874 static const IDirectPlay3Vtbl directPlay3AVT = 04875 { 04876 XCAST(QueryInterface)DP_QueryInterface, 04877 XCAST(AddRef)DP_AddRef, 04878 XCAST(Release)DP_Release, 04879 04880 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup, 04881 XCAST(Close)DirectPlay2AImpl_Close, 04882 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup, 04883 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer, 04884 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup, 04885 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup, 04886 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer, 04887 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers, 04888 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups, 04889 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers, 04890 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions, 04891 XCAST(GetCaps)DirectPlay2AImpl_GetCaps, 04892 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData, 04893 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName, 04894 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount, 04895 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress, 04896 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps, 04897 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData, 04898 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName, 04899 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc, 04900 XCAST(Initialize)DirectPlay2AImpl_Initialize, 04901 XCAST(Open)DirectPlay2AImpl_Open, 04902 XCAST(Receive)DirectPlay2AImpl_Receive, 04903 XCAST(Send)DirectPlay2AImpl_Send, 04904 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData, 04905 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName, 04906 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData, 04907 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName, 04908 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc, 04909 04910 DirectPlay3AImpl_AddGroupToGroup, 04911 DirectPlay3AImpl_CreateGroupInGroup, 04912 DirectPlay3AImpl_DeleteGroupFromGroup, 04913 DirectPlay3AImpl_EnumConnections, 04914 DirectPlay3AImpl_EnumGroupsInGroup, 04915 DirectPlay3AImpl_GetGroupConnectionSettings, 04916 DirectPlay3AImpl_InitializeConnection, 04917 DirectPlay3AImpl_SecureOpen, 04918 DirectPlay3AImpl_SendChatMessage, 04919 DirectPlay3AImpl_SetGroupConnectionSettings, 04920 DirectPlay3AImpl_StartSession, 04921 DirectPlay3AImpl_GetGroupFlags, 04922 DirectPlay3AImpl_GetGroupParent, 04923 DirectPlay3AImpl_GetPlayerAccount, 04924 DirectPlay3AImpl_GetPlayerFlags 04925 }; 04926 #undef XCAST 04927 04928 /* Note: Hack so we can reuse the old functions without compiler warnings */ 04929 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 04930 # define XCAST(fun) (typeof(directPlay3WVT.fun)) 04931 #else 04932 # define XCAST(fun) (void*) 04933 #endif 04934 static const IDirectPlay3Vtbl directPlay3WVT = 04935 { 04936 XCAST(QueryInterface)DP_QueryInterface, 04937 XCAST(AddRef)DP_AddRef, 04938 XCAST(Release)DP_Release, 04939 04940 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup, 04941 XCAST(Close)DirectPlay2WImpl_Close, 04942 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup, 04943 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer, 04944 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup, 04945 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup, 04946 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer, 04947 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers, 04948 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups, 04949 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers, 04950 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions, 04951 XCAST(GetCaps)DirectPlay2WImpl_GetCaps, 04952 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData, 04953 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName, 04954 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount, 04955 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress, 04956 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps, 04957 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData, 04958 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName, 04959 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc, 04960 XCAST(Initialize)DirectPlay2WImpl_Initialize, 04961 XCAST(Open)DirectPlay2WImpl_Open, 04962 XCAST(Receive)DirectPlay2WImpl_Receive, 04963 XCAST(Send)DirectPlay2WImpl_Send, 04964 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData, 04965 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName, 04966 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData, 04967 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName, 04968 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc, 04969 04970 DirectPlay3WImpl_AddGroupToGroup, 04971 DirectPlay3WImpl_CreateGroupInGroup, 04972 DirectPlay3WImpl_DeleteGroupFromGroup, 04973 DirectPlay3WImpl_EnumConnections, 04974 DirectPlay3WImpl_EnumGroupsInGroup, 04975 DirectPlay3WImpl_GetGroupConnectionSettings, 04976 DirectPlay3WImpl_InitializeConnection, 04977 DirectPlay3WImpl_SecureOpen, 04978 DirectPlay3WImpl_SendChatMessage, 04979 DirectPlay3WImpl_SetGroupConnectionSettings, 04980 DirectPlay3WImpl_StartSession, 04981 DirectPlay3WImpl_GetGroupFlags, 04982 DirectPlay3WImpl_GetGroupParent, 04983 DirectPlay3WImpl_GetPlayerAccount, 04984 DirectPlay3WImpl_GetPlayerFlags 04985 }; 04986 #undef XCAST 04987 04988 /* Note: Hack so we can reuse the old functions without compiler warnings */ 04989 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 04990 # define XCAST(fun) (typeof(directPlay4WVT.fun)) 04991 #else 04992 # define XCAST(fun) (void*) 04993 #endif 04994 static const IDirectPlay4Vtbl directPlay4WVT = 04995 { 04996 XCAST(QueryInterface)DP_QueryInterface, 04997 XCAST(AddRef)DP_AddRef, 04998 XCAST(Release)DP_Release, 04999 05000 XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup, 05001 XCAST(Close)DirectPlay2WImpl_Close, 05002 XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup, 05003 XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer, 05004 XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup, 05005 XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup, 05006 XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer, 05007 XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers, 05008 XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups, 05009 XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers, 05010 XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions, 05011 XCAST(GetCaps)DirectPlay2WImpl_GetCaps, 05012 XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData, 05013 XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName, 05014 XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount, 05015 XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress, 05016 XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps, 05017 XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData, 05018 XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName, 05019 XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc, 05020 XCAST(Initialize)DirectPlay2WImpl_Initialize, 05021 XCAST(Open)DirectPlay2WImpl_Open, 05022 XCAST(Receive)DirectPlay2WImpl_Receive, 05023 XCAST(Send)DirectPlay2WImpl_Send, 05024 XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData, 05025 XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName, 05026 XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData, 05027 XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName, 05028 XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc, 05029 05030 XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup, 05031 XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup, 05032 XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup, 05033 XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections, 05034 XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup, 05035 XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings, 05036 XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection, 05037 XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen, 05038 XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage, 05039 XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings, 05040 XCAST(StartSession)DirectPlay3WImpl_StartSession, 05041 XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags, 05042 XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent, 05043 XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount, 05044 XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags, 05045 05046 DirectPlay4WImpl_GetGroupOwner, 05047 DirectPlay4WImpl_SetGroupOwner, 05048 DirectPlay4WImpl_SendEx, 05049 DirectPlay4WImpl_GetMessageQueue, 05050 DirectPlay4WImpl_CancelMessage, 05051 DirectPlay4WImpl_CancelPriority 05052 }; 05053 #undef XCAST 05054 05055 05056 /* Note: Hack so we can reuse the old functions without compiler warnings */ 05057 #if !defined(__STRICT_ANSI__) && defined(__GNUC__) 05058 # define XCAST(fun) (typeof(directPlay4AVT.fun)) 05059 #else 05060 # define XCAST(fun) (void*) 05061 #endif 05062 static const IDirectPlay4Vtbl directPlay4AVT = 05063 { 05064 XCAST(QueryInterface)DP_QueryInterface, 05065 XCAST(AddRef)DP_AddRef, 05066 XCAST(Release)DP_Release, 05067 05068 XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup, 05069 XCAST(Close)DirectPlay2AImpl_Close, 05070 XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup, 05071 XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer, 05072 XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup, 05073 XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup, 05074 XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer, 05075 XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers, 05076 XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups, 05077 XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers, 05078 XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions, 05079 XCAST(GetCaps)DirectPlay2AImpl_GetCaps, 05080 XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData, 05081 XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName, 05082 XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount, 05083 XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress, 05084 XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps, 05085 XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData, 05086 XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName, 05087 XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc, 05088 XCAST(Initialize)DirectPlay2AImpl_Initialize, 05089 XCAST(Open)DirectPlay2AImpl_Open, 05090 XCAST(Receive)DirectPlay2AImpl_Receive, 05091 XCAST(Send)DirectPlay2AImpl_Send, 05092 XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData, 05093 XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName, 05094 XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData, 05095 XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName, 05096 XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc, 05097 05098 XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup, 05099 XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup, 05100 XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup, 05101 XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections, 05102 XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup, 05103 XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings, 05104 XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection, 05105 XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen, 05106 XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage, 05107 XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings, 05108 XCAST(StartSession)DirectPlay3AImpl_StartSession, 05109 XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags, 05110 XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent, 05111 XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount, 05112 XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags, 05113 05114 DirectPlay4AImpl_GetGroupOwner, 05115 DirectPlay4AImpl_SetGroupOwner, 05116 DirectPlay4AImpl_SendEx, 05117 DirectPlay4AImpl_GetMessageQueue, 05118 DirectPlay4AImpl_CancelMessage, 05119 DirectPlay4AImpl_CancelPriority 05120 }; 05121 #undef XCAST 05122 05123 extern 05124 HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, 05125 DPID idPlayer, 05126 LPVOID* lplpData ) 05127 { 05128 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); 05129 05130 if( lpPlayer == NULL ) 05131 { 05132 return DPERR_INVALIDPLAYER; 05133 } 05134 05135 *lplpData = lpPlayer->lpPData->lpSPPlayerData; 05136 05137 return DP_OK; 05138 } 05139 05140 extern 05141 HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, 05142 DPID idPlayer, 05143 LPVOID lpData ) 05144 { 05145 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); 05146 05147 if( lpPlayer == NULL ) 05148 { 05149 return DPERR_INVALIDPLAYER; 05150 } 05151 05152 lpPlayer->lpPData->lpSPPlayerData = lpData; 05153 05154 return DP_OK; 05155 } 05156 05157 /*************************************************************************** 05158 * DirectPlayEnumerateAW 05159 * 05160 * The pointer to the structure lpContext will be filled with the 05161 * appropriate data for each service offered by the OS. These services are 05162 * not necessarily available on this particular machine but are defined 05163 * as simple service providers under the "Service Providers" registry key. 05164 * This structure is then passed to lpEnumCallback for each of the different 05165 * services. 05166 * 05167 * This API is useful only for applications written using DirectX3 or 05168 * worse. It is superseded by IDirectPlay3::EnumConnections which also 05169 * gives information on the actual connections. 05170 * 05171 * defn of a service provider: 05172 * A dynamic-link library used by DirectPlay to communicate over a network. 05173 * The service provider contains all the network-specific code required 05174 * to send and receive messages. Online services and network operators can 05175 * supply service providers to use specialized hardware, protocols, communications 05176 * media, and network resources. 05177 * 05178 */ 05179 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, 05180 LPDPENUMDPCALLBACKW lpEnumCallbackW, 05181 LPVOID lpContext) 05182 { 05183 HKEY hkResult; 05184 static const WCHAR searchSubKey[] = { 05185 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\', 05186 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\', 05187 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\', 05188 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 }; 05189 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 }; 05190 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 }; 05191 05192 DWORD dwIndex; 05193 FILETIME filetime; 05194 05195 char *descriptionA = NULL; 05196 DWORD max_sizeOfDescriptionA = 0; 05197 WCHAR *descriptionW = NULL; 05198 DWORD max_sizeOfDescriptionW = 0; 05199 05200 if (!lpEnumCallbackA && !lpEnumCallbackW) 05201 { 05202 return DPERR_INVALIDPARAMS; 05203 } 05204 05205 /* Need to loop over the service providers in the registry */ 05206 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey, 05207 0, KEY_READ, &hkResult) != ERROR_SUCCESS) 05208 { 05209 /* Hmmm. Does this mean that there are no service providers? */ 05210 ERR(": no service provider key in the registry - check your Wine installation !!!\n"); 05211 return DPERR_GENERIC; 05212 } 05213 05214 /* Traverse all the service providers we have available */ 05215 dwIndex = 0; 05216 while (1) 05217 { 05218 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */ 05219 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR); 05220 HKEY hkServiceProvider; 05221 GUID serviceProviderGUID; 05222 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ]; 05223 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent); 05224 LONG ret_value; 05225 05226 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 05227 NULL, NULL, NULL, &filetime); 05228 if (ret_value == ERROR_NO_MORE_ITEMS) 05229 break; 05230 else if (ret_value != ERROR_SUCCESS) 05231 { 05232 ERR(": could not enumerate on service provider key.\n"); 05233 return DPERR_EXCEPTION; 05234 } 05235 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName)); 05236 05237 /* Open the key for this service provider */ 05238 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS) 05239 { 05240 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName)); 05241 continue; 05242 } 05243 05244 /* Get the GUID from the registry */ 05245 if (RegQueryValueExW(hkServiceProvider, guidKey, 05246 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS) 05247 { 05248 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName)); 05249 continue; 05250 } 05251 if (sizeOfGuidKeyContent != sizeof(guidKeyContent)) 05252 { 05253 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent)); 05254 continue; 05255 } 05256 CLSIDFromString(guidKeyContent, &serviceProviderGUID ); 05257 05258 /* The enumeration will return FALSE if we are not to continue. 05259 * 05260 * Note: on my windows box, major / minor version is 6 / 0 for all service providers 05261 * and have no relations to any of the two dwReserved1 and dwReserved2 keys. 05262 * I think that it simply means that they are in-line with DirectX 6.0 05263 */ 05264 if (lpEnumCallbackA) 05265 { 05266 DWORD sizeOfDescription = 0; 05267 05268 /* Note that this the the A case of this function, so use the A variant to get the description string */ 05269 if (RegQueryValueExA(hkServiceProvider, "DescriptionA", 05270 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS) 05271 { 05272 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName)); 05273 continue; 05274 } 05275 if (sizeOfDescription > max_sizeOfDescriptionA) 05276 { 05277 HeapFree(GetProcessHeap(), 0, descriptionA); 05278 max_sizeOfDescriptionA = sizeOfDescription; 05279 descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA); 05280 } 05281 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription); 05282 RegQueryValueExA(hkServiceProvider, "DescriptionA", 05283 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription); 05284 05285 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext)) 05286 goto end; 05287 } 05288 else 05289 { 05290 DWORD sizeOfDescription = 0; 05291 05292 if (RegQueryValueExW(hkServiceProvider, descW, 05293 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS) 05294 { 05295 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName)); 05296 continue; 05297 } 05298 if (sizeOfDescription > max_sizeOfDescriptionW) 05299 { 05300 HeapFree(GetProcessHeap(), 0, descriptionW); 05301 max_sizeOfDescriptionW = sizeOfDescription; 05302 descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW); 05303 } 05304 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription); 05305 RegQueryValueExW(hkServiceProvider, descW, 05306 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription); 05307 05308 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext)) 05309 goto end; 05310 } 05311 05312 dwIndex++; 05313 } 05314 05315 end: 05316 HeapFree(GetProcessHeap(), 0, descriptionA); 05317 HeapFree(GetProcessHeap(), 0, descriptionW); 05318 05319 return DP_OK; 05320 } 05321 05322 /*************************************************************************** 05323 * DirectPlayEnumerate [DPLAYX.9] 05324 * DirectPlayEnumerateA [DPLAYX.2] 05325 */ 05326 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext ) 05327 { 05328 TRACE("(%p,%p)\n", lpEnumCallback, lpContext); 05329 05330 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext); 05331 } 05332 05333 /*************************************************************************** 05334 * DirectPlayEnumerateW [DPLAYX.3] 05335 */ 05336 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) 05337 { 05338 TRACE("(%p,%p)\n", lpEnumCallback, lpContext); 05339 05340 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext); 05341 } 05342 05343 typedef struct tagCreateEnum 05344 { 05345 LPVOID lpConn; 05346 LPCGUID lpGuid; 05347 } CreateEnumData, *lpCreateEnumData; 05348 05349 /* Find and copy the matching connection for the SP guid */ 05350 static BOOL CALLBACK cbDPCreateEnumConnections( 05351 LPCGUID lpguidSP, 05352 LPVOID lpConnection, 05353 DWORD dwConnectionSize, 05354 LPCDPNAME lpName, 05355 DWORD dwFlags, 05356 LPVOID lpContext) 05357 { 05358 lpCreateEnumData lpData = (lpCreateEnumData)lpContext; 05359 05360 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) ) 05361 { 05362 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) ); 05363 05364 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 05365 dwConnectionSize ); 05366 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize ); 05367 05368 /* Found the record that we were looking for */ 05369 return FALSE; 05370 } 05371 05372 /* Haven't found what were looking for yet */ 05373 return TRUE; 05374 } 05375 05376 05377 /*************************************************************************** 05378 * DirectPlayCreate [DPLAYX.1] 05379 * 05380 */ 05381 HRESULT WINAPI DirectPlayCreate 05382 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk) 05383 { 05384 HRESULT hr; 05385 LPDIRECTPLAY3A lpDP3A; 05386 CreateEnumData cbData; 05387 05388 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk ); 05389 05390 if( pUnk != NULL ) 05391 { 05392 return CLASS_E_NOAGGREGATION; 05393 } 05394 05395 /* Create an IDirectPlay object. We don't support that so we'll cheat and 05396 give them an IDirectPlay2A object and hope that doesn't cause problems */ 05397 if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK ) 05398 { 05399 return DPERR_UNAVAILABLE; 05400 } 05401 05402 if( IsEqualGUID( &GUID_NULL, lpGUID ) ) 05403 { 05404 /* The GUID_NULL means don't bind a service provider. Just return the 05405 interface as is */ 05406 return DP_OK; 05407 } 05408 05409 /* Bind the desired service provider since lpGUID is non NULL */ 05410 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) ); 05411 05412 /* We're going to use a DP3 interface */ 05413 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A, 05414 (LPVOID*)&lpDP3A ); 05415 if( FAILED(hr) ) 05416 { 05417 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) ); 05418 return hr; 05419 } 05420 05421 cbData.lpConn = NULL; 05422 cbData.lpGuid = lpGUID; 05423 05424 /* We were given a service provider, find info about it... */ 05425 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections, 05426 &cbData, DPCONNECTION_DIRECTPLAY ); 05427 if( ( FAILED(hr) ) || 05428 ( cbData.lpConn == NULL ) 05429 ) 05430 { 05431 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) ); 05432 IDirectPlayX_Release( lpDP3A ); 05433 return DPERR_UNAVAILABLE; 05434 } 05435 05436 /* Initialize the service provider */ 05437 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 ); 05438 if( FAILED(hr) ) 05439 { 05440 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) ); 05441 HeapFree( GetProcessHeap(), 0, cbData.lpConn ); 05442 IDirectPlayX_Release( lpDP3A ); 05443 return hr; 05444 } 05445 05446 /* Release our version of the interface now that we're done with it */ 05447 IDirectPlayX_Release( lpDP3A ); 05448 HeapFree( GetProcessHeap(), 0, cbData.lpConn ); 05449 05450 return DP_OK; 05451 } Generated on Sun May 27 2012 04:21:37 for ReactOS by
1.7.6.1
|