/*========================================================================== * * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved. * * File: session.c * Content: Methods for session management * * History: * Date By Reason * ======= ======= ====== * 2/27/97 myronth Created it * 3/12/97 myronth Implemented EnumSessions, Open, & Close * 3/31/97 myronth Removed dead code, Fixed EnumSessionReponse fn name * 4/3/97 myronth Changed CALLSP macro to CALL_LP * 5/8/97 myronth Drop lobby lock when calling the LP * 5/13/97 myronth Handle Credentials in Open, pass them to LP * 6/4/97 myronth Fixed PRV_Open to fail on DPOPEN_CREATE (#9491) ***************************************************************************/ #include "dplobpr.h" //-------------------------------------------------------------------------- // // Functions // //-------------------------------------------------------------------------- #undef DPF_MODNAME #define DPF_MODNAME "PRV_Close" HRESULT DPLAPI PRV_Close(LPDPLOBBYI_DPLOBJECT this) { SPDATA_CLOSE cd; HRESULT hr = DP_OK; DPF(7, "Entering PRV_Close"); DPF(9, "Parameters: 0x%08x", this); ENTER_DPLOBBY(); TRY { if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Setup our SPDATA structure memset(&cd, 0, sizeof(SPDATA_CLOSE)); cd.dwSize = sizeof(SPDATA_CLOSE); // Call the Close method in the SP if(CALLBACK_EXISTS(Close)) { cd.lpISP = PRV_GetDPLobbySPInterface(this); // Drop the lock so the lobby provider's receive thread can get back // in with other messages if they show up in the queue before our // CreatePlayer response (which always happens) LEAVE_DPLOBBY(); hr = CALL_LP(this, Close, &cd); ENTER_DPLOBBY(); } else { // Close is required DPF_ERR("The Lobby Provider callback for Close doesn't exist -- it's required"); ASSERT(FALSE); LEAVE_DPLOBBY(); return DPERR_UNAVAILABLE; } LEAVE_DPLOBBY(); return hr; } // PRV_Close #undef DPF_MODNAME #define DPF_MODNAME "PRV_EnumSessions" HRESULT DPLAPI PRV_EnumSessions(LPDPLOBBYI_DPLOBJECT this, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, DWORD dwFlags) { HRESULT hr = DP_OK; SPDATA_ENUMSESSIONS esd; DPF(7, "Entering PRV_EnumSessions"); DPF(9, "Parameters: 0x%08x, 0x%08x, %lu, 0x%08x", this, lpsd, dwTimeout, dwFlags); ASSERT(this); ASSERT(lpsd); ENTER_DPLOBBY(); TRY { if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Call the EnumSessions method in the SP if(CALLBACK_EXISTS(EnumSessions)) { // Clear our stack-based structure memset(&esd, 0, sizeof(SPDATA_ENUMSESSIONS)); // Set up the structure and call the callback esd.dwSize = sizeof(SPDATA_ENUMSESSIONS); esd.lpISP = PRV_GetDPLobbySPInterface(this); esd.lpsd = lpsd; esd.dwTimeout = dwTimeout; esd.dwFlags = dwFlags; // Drop the lock so the lobby provider's receive thread can get back // in with other messages if they show up in the queue before our // CreatePlayer response (which always happens) LEAVE_DPLOBBY(); hr = CALL_LP(this, EnumSessions, &esd); ENTER_DPLOBBY(); } else { // EnumSessions is required // REVIEW!!!! -- What error should we return here???? DPF_ERR("The Lobby Provider callback for EnumSessions doesn't exist -- it's required"); ASSERT(FALSE); hr = DPERR_UNAVAILABLE; } if(FAILED(hr)) { DPF_ERR("Could not invoke EnumSessions in the Service Provider"); } LEAVE_DPLOBBY(); return hr; } // PRV_EnumSessions #undef DPF_MODNAME #define DPF_MODNAME "DPLP_EnumSessionsResponse" HRESULT DPLAPI DPLP_EnumSessionsResponse(LPDPLOBBYSP lpDPLSP, LPSPDATA_ENUMSESSIONSRESPONSE lpr) { LPDPLOBBYI_DPLOBJECT this; LPMSG_ENUMSESSIONSREPLY lpBuffer = NULL; LPBYTE lpIndex = NULL; DWORD dwNameLength, dwMessageSize; HRESULT hr = DP_OK; DPF(7, "Entering DPLP_EnumSessionsResponse"); DPF(9, "Parameters: 0x%08x, 0x%08x", lpDPLSP, lpr); // Make sure the SP doesn't throw us a curve TRY { this = DPLOBJECT_FROM_INTERFACE(lpDPLSP); if( !VALID_DPLOBBY_PTR( this ) ) { DPF_ERR("SP passed invalid DPLobby object!"); return DPERR_INVALIDOBJECT; } // Validate the struct pointer if(!lpr) { DPF_ERR("SPDATA_ENUMSESSIONSRESPONSE structure pointer cannot be NULL"); return DPERR_INVALIDPARAMS; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // REVIEW!!!! -- Can we put this packing code that's duplicated // from dplay into a single function??? dwNameLength = WSTRLEN_BYTES(lpr->lpsd->lpszSessionName); // Calculate the size of the message to send back to dplay dwMessageSize = sizeof(MSG_ENUMSESSIONSREPLY); dwMessageSize += dwNameLength; lpBuffer = DPMEM_ALLOC(dwMessageSize); if (!lpBuffer) { DPF(2, "Unable to allocate memory for EnumSessions request"); return DPERR_OUTOFMEMORY; } // Set up the message SET_MESSAGE_HDR(lpBuffer); SET_MESSAGE_COMMAND(lpBuffer, DPSP_MSG_ENUMSESSIONSREPLY); lpBuffer->dpDesc = *(lpr->lpsd); // Pack strings on end lpIndex = (LPBYTE)lpBuffer+sizeof(MSG_ENUMSESSIONSREPLY); if(dwNameLength) { memcpy(lpIndex, lpr->lpsd->lpszSessionName, dwNameLength); lpBuffer->dwNameOffset = sizeof(MSG_ENUMSESSIONSREPLY); } // set string pointers to NULL - they must be set at client lpBuffer->dpDesc.lpszPassword = NULL; lpBuffer->dpDesc.lpszSessionName = NULL; // Now send it to dplay ENTER_DPLAY(); hr = HandleEnumSessionsReply(this->lpDPlayObject, (LPBYTE)lpBuffer, dwMessageSize, NULL); LEAVE_DPLAY(); // Free our buffer DPMEM_FREE(lpBuffer); return hr; } // DPLP_EnumSessionsResponse #undef DPF_MODNAME #define DPF_MODNAME "PRV_Open" HRESULT DPLAPI PRV_Open(LPDPLOBBYI_DPLOBJECT this, LPDPSESSIONDESC2 lpsd, DWORD dwFlags, LPCDPCREDENTIALS lpCredentials) { SPDATA_OPEN od; HRESULT hr = DP_OK; DPF(7, "Entering PRV_Open"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x, 0x%08x", this, lpsd, dwFlags, lpCredentials); ENTER_DPLOBBY(); TRY { if( !VALID_DPLOBBY_PTR( this ) ) { LEAVE_DPLOBBY(); return DPERR_INVALIDOBJECT; } // We cannot host a lobby session if(dwFlags & DPOPEN_CREATE) { DPF_ERR("Cannot host a lobby session"); LEAVE_DPLOBBY(); return DPERR_INVALIDFLAGS; } } EXCEPT( EXCEPTION_EXECUTE_HANDLER ) { LEAVE_DPLOBBY(); DPF_ERR( "Exception encountered validating parameters" ); return DPERR_INVALIDPARAMS; } // Setup our SPDATA structure memset(&od, 0, sizeof(SPDATA_OPEN)); od.dwSize = sizeof(SPDATA_OPEN); od.lpsd = lpsd; od.dwFlags = dwFlags; od.lpCredentials = lpCredentials; // Call the ConnectServer method in the SP if(CALLBACK_EXISTS(Open)) { od.lpISP = PRV_GetDPLobbySPInterface(this); // Drop the lock so the lobby provider's receive thread can get back // in with other messages if they show up in the queue before our // CreatePlayer response (which always happens) LEAVE_DPLOBBY(); hr = CALL_LP(this, Open, &od); ENTER_DPLOBBY(); } else { // Open is required DPF_ERR("The Lobby Provider callback for Open doesn't exist -- it's required"); ASSERT(FALSE); LEAVE_DPLOBBY(); return DPERR_UNAVAILABLE; } LEAVE_DPLOBBY(); return hr; } // PRV_Open