2025-04-27 07:49:33 -04:00

1721 lines
36 KiB
C++

/***************************************************************************
*
* Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
*
* File: controlobj.cpp
*
* Content: DP8SIM control interface wrapper object class.
*
* History:
* Date By Reason
* ======== ======== =========
* 04/24/01 VanceO Created.
*
***************************************************************************/
#include "dp8simi.h"
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::CDP8SimControl"
//=============================================================================
// CDP8SimControl constructor
//-----------------------------------------------------------------------------
//
// Description: Initializes the new CDP8SimControl object.
//
// Arguments: None.
//
// Returns: None (the object).
//=============================================================================
CDP8SimControl::CDP8SimControl(void)
{
this->m_blList.Initialize();
this->m_Sig[0] = 'D';
this->m_Sig[1] = 'P';
this->m_Sig[2] = '8';
this->m_Sig[3] = 'S';
this->m_lRefCount = 1; // someone must have a pointer to this object
this->m_dwFlags = 0;
} // CDP8SimControl::CDP8SimControl
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::~CDP8SimControl"
//=============================================================================
// CDP8SimControl destructor
//-----------------------------------------------------------------------------
//
// Description: Frees the CDP8SimControl object.
//
// Arguments: None.
//
// Returns: None.
//=============================================================================
CDP8SimControl::~CDP8SimControl(void)
{
DNASSERT(this->m_blList.IsEmpty());
DNASSERT(this->m_lRefCount == 0);
DNASSERT(this->m_dwFlags == 0);
//
// For grins, change the signature before deleting the object.
//
this->m_Sig[3] = 's';
} // CDP8SimControl::~CDP8SimControl
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::QueryInterface"
//=============================================================================
// CDP8SimControl::QueryInterface
//-----------------------------------------------------------------------------
//
// Description: Retrieves a new reference for an interfaces supported by this
// CDP8SimControl object.
//
// Arguments:
// REFIID riid - Reference to interface ID GUID.
// LPVOID * ppvObj - Place to store pointer to object.
//
// Returns: HRESULT
// S_OK - Returning a valid interface pointer.
// DPNHERR_INVALIDOBJECT - The interface object is invalid.
// DPNHERR_INVALIDPOINTER - The destination pointer is invalid.
// E_NOINTERFACE - Invalid interface was specified.
//=============================================================================
STDMETHODIMP CDP8SimControl::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
HRESULT hr = DPN_OK;
DPFX(DPFPREP, 3, "(0x%p) Parameters: (REFIID, 0x%p)", this, ppvObj);
//
// Validate the object.
//
if (! this->IsValidObject())
{
DPFX(DPFPREP, 0, "Invalid DP8SimControl object!");
hr = DPNERR_INVALIDOBJECT;
goto Failure;
}
//
// Validate the parameters.
//
if ((! IsEqualIID(riid, IID_IUnknown)) &&
(! IsEqualIID(riid, IID_IDP8SimControl)))
{
DPFX(DPFPREP, 0, "Unsupported interface!");
hr = E_NOINTERFACE;
goto Failure;
}
if ((ppvObj == NULL) ||
(IsBadWritePtr(ppvObj, sizeof(void*))))
{
DPFX(DPFPREP, 0, "Invalid interface pointer specified!");
hr = DPNERR_INVALIDPOINTER;
goto Failure;
}
//
// Add a reference, and return the interface pointer (which is actually
// just the object pointer, they line up because CDP8SimControl inherits
// from the interface declaration).
//
this->AddRef();
(*ppvObj) = this;
Exit:
DPFX(DPFPREP, 3, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
goto Exit;
} // CDP8SimControl::QueryInterface
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::AddRef"
//=============================================================================
// CDP8SimControl::AddRef
//-----------------------------------------------------------------------------
//
// Description: Adds a reference to this CDP8SimControl object.
//
// Arguments: None.
//
// Returns: New refcount.
//=============================================================================
STDMETHODIMP_(ULONG) CDP8SimControl::AddRef(void)
{
LONG lRefCount;
DNASSERT(this->IsValidObject());
//
// There must be at least 1 reference to this object, since someone is
// calling AddRef.
//
DNASSERT(this->m_lRefCount > 0);
lRefCount = InterlockedIncrement(&this->m_lRefCount);
DPFX(DPFPREP, 3, "[0x%p] RefCount [0x%lx]", this, lRefCount);
return lRefCount;
} // CDP8SimControl::AddRef
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::Release"
//=============================================================================
// CDP8SimControl::Release
//-----------------------------------------------------------------------------
//
// Description: Removes a reference to this CDP8SimControl object. When the
// refcount reaches 0, this object is destroyed.
// You must NULL out your pointer to this object after calling
// this function.
//
// Arguments: None.
//
// Returns: New refcount.
//=============================================================================
STDMETHODIMP_(ULONG) CDP8SimControl::Release(void)
{
LONG lRefCount;
DNASSERT(this->IsValidObject());
//
// There must be at least 1 reference to this object, since someone is
// calling Release.
//
DNASSERT(this->m_lRefCount > 0);
lRefCount = InterlockedDecrement(&this->m_lRefCount);
//
// Was that the last reference? If so, we're going to destroy this object.
//
if (lRefCount == 0)
{
DPFX(DPFPREP, 3, "[0x%p] RefCount hit 0, destroying object.", this);
//
// First pull it off the global list.
//
DNEnterCriticalSection(&g_csGlobalsLock);
this->m_blList.RemoveFromList();
DNASSERT(g_lOutstandingInterfaceCount > 0);
g_lOutstandingInterfaceCount--; // update count so DLL can unload now works correctly
DNLeaveCriticalSection(&g_csGlobalsLock);
//
// Make sure it's closed.
//
if (this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED)
{
//
// Assert so that the user can fix his/her broken code!
//
DNASSERT(! "DP8SimControl object being released without calling Close first!");
//
// Then go ahead and do the right thing. Ignore error, we can't do
// much about it.
//
this->Close(0);
}
//
// Then uninitialize the object.
//
this->UninitializeObject();
//
// Finally delete this (!) object.
//
delete this;
}
else
{
DPFX(DPFPREP, 3, "[0x%p] RefCount [0x%lx]", this, lRefCount);
}
return lRefCount;
} // CDP8SimControl::Release
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::Initialize"
//=============================================================================
// CDP8SimControl::Initialize
//-----------------------------------------------------------------------------
//
// Description: Initializes this DP8Sim Control interface.
//
// Arguments:
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::Initialize(const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
BOOL fHaveLock = FALSE;
BOOL fInitializedIPCObject = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%x)", this, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags == 0);
//
// Connect the shared memory.
//
hr = this->m_DP8SimIPC.Initialize();
if (hr != DPN_OK)
{
DPFX(DPFPREP, 0, "Couldn't initialize IPC object!");
goto Failure;
}
fInitializedIPCObject = TRUE;
//
// We're now initialized.
//
this->m_dwFlags |= DP8SIMCONTROLOBJ_INITIALIZED;
Exit:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
if (fInitializedIPCObject)
{
this->m_DP8SimIPC.Close();
fInitializedIPCObject = FALSE;
}
goto Exit;
} // CDP8SimControl::Initialize
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::Close"
//=============================================================================
// CDP8SimControl::Close
//-----------------------------------------------------------------------------
//
// Description: Closes this DP8Sim Control interface.
//
// Arguments:
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::Close(const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
//BOOL fHaveLock = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%x)", this, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
//fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Disconnect the shared memory.
//
this->m_DP8SimIPC.Close();
//
// Turn off the initialized flags.
//
this->m_dwFlags &= ~DP8SIMCONTROLOBJ_INITIALIZED;
DNASSERT(this->m_dwFlags == 0);
//
// Drop the lock, nobody should be touching this object now.
//
DNLeaveCriticalSection(&this->m_csLock);
//fHaveLock = FALSE;
//Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
/*
Failure:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
goto Exit;
*/
} // CDP8SimControl::Close
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::EnableControlForSP"
//=============================================================================
// CDP8SimControl::EnableControlForSP
//-----------------------------------------------------------------------------
//
// Description: Inserts the DP8Sim Control shim in front of the SP with the
// given GUID.
//
// Arguments:
// GUID * pguidSP - Pointer to GUID of SP to intercept.
// WCHAR * wszNewFriendlyName - New friendly name for intercepted SP.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::EnableControlForSP(const GUID * const pguidSP,
const WCHAR * const wszNewFriendlyName,
const DWORD dwFlags)
{
HRESULT hr;
char szLocalPath[_MAX_PATH];
WCHAR wszLocalPath[_MAX_PATH];
WCHAR wszInProcServer32[_MAX_PATH];
CRegistry RegObjectCOM;
CRegistry RegObjectDP8SP;
CRegistry RegObjectDP8SPSubkey;
DWORD dwMaxLength;
DWORD dwLength;
WCHAR * pwszTemp = NULL;
DWORD dwTemp;
GUID guidTemp;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, \"%S\" 0x%x)",
this, pguidSP, wszNewFriendlyName, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pguidSP != NULL);
DNASSERT(wszNewFriendlyName != NULL);
DNASSERT(dwFlags == 0);
#ifdef DEBUG
DNEnterCriticalSection(&this->m_csLock);
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
#endif // DEBUG
//
// Retrieve the location of this DLL.
//
dwLength = GetModuleFileNameA(g_hDLLInstance, szLocalPath, _MAX_PATH);
if (dwLength == 0)
{
DPFX(DPFPREP, 0, "Couldn't read local path!");
hr = E_FAIL;
goto Failure;
}
//
// Include NULL termination.
//
dwLength++;
//
// Convert it to Unicode.
//
hr = STR_AnsiToWide(szLocalPath, dwLength, wszLocalPath, &dwLength);
if (hr != S_OK)
{
DPFX(DPFPREP, 0, "Could not convert ANSI path to Unicode!");
goto Failure;
}
//
// Open the SP's COM object information key.
//
swprintf(wszInProcServer32, L"CLSID\\{%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}\\InProcServer32",
pguidSP->Data1, pguidSP->Data2, pguidSP->Data3,
pguidSP->Data4[0], pguidSP->Data4[1],
pguidSP->Data4[2], pguidSP->Data4[3],
pguidSP->Data4[4], pguidSP->Data4[5],
pguidSP->Data4[6], pguidSP->Data4[7]);
if (! RegObjectCOM.Open(HKEY_CLASSES_ROOT, wszInProcServer32, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open SP InProcServer32 key!");
hr = E_FAIL;
goto Failure;
}
//
// Make sure this SP hasn't already been modified.
//
dwLength = 0;
RegObjectCOM.ReadString(DP8SIM_REG_REALSPDLL, NULL, &dwLength);
if (dwLength > 0)
{
DPFX(DPFPREP, 0, "SP has already been redirected!");
hr = DP8SIMERR_ALREADYENABLEDFORSP;
goto Failure;
}
//
// Find out the size of the original DLL name.
//
dwLength = 0;
RegObjectCOM.ReadString(L"", NULL, &dwLength);
dwLength++;
pwszTemp = (WCHAR*) DNMalloc(dwLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
if (! RegObjectCOM.ReadString(L"", pwszTemp, &dwLength))
{
DPFX(DPFPREP, 0, "Couldn't read existing SP's DLL location!");
hr = E_FAIL;
goto Failure;
}
//
// Save it so we can restore it later.
//
if (! RegObjectCOM.WriteString(DP8SIM_REG_REALSPDLL, pwszTemp))
{
DPFX(DPFPREP, 0, "Couldn't save SP's existing DLL location to value \"%S\"!",
DP8SIM_REG_REALSPDLL);
hr = E_FAIL;
goto Failure;
}
DNFree(pwszTemp);
pwszTemp = NULL;
//
// Find the SP key. First allocate enough memory to hold the name the
// longest subkey.
//
if (! RegObjectDP8SP.Open(HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open DirectPlay8 SP key!");
hr = E_FAIL;
goto Failure;
}
if (! RegObjectDP8SP.GetMaxKeyLen(dwMaxLength))
{
DPFX(DPFPREP, 0, "Could not get longest SP key name length!");
hr = E_FAIL;
goto Failure;
}
dwMaxLength++;
pwszTemp = (WCHAR*) DNMalloc(dwMaxLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
//
// Walk through every key, looking for the right one.
//
dwTemp = 0;
do
{
dwLength = dwMaxLength;
if (! RegObjectDP8SP.EnumKeys(pwszTemp, &dwLength, dwTemp))
{
//
// We couldn't get the next key. Assume we're done.
//
break;
}
//
// Open the subkey.
//
if (! RegObjectDP8SPSubkey.Open((HKEY) RegObjectDP8SP, pwszTemp, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open DirectPlay8 SP sub key \"%S\"! Ignoring.", pwszTemp);
}
else
{
//
// See if the GUID matches.
//
RegObjectDP8SPSubkey.ReadGUID(DPN_REG_KEYNAME_GUID, guidTemp);
if (guidTemp == (*pguidSP))
{
//
// Found SP.
//
DPFX(DPFPREP, 5, "Found SP under sub key \"%S\".", pwszTemp);
break;
}
RegObjectDP8SPSubkey.Close();
}
//
// Got to next subkey.
//
dwTemp++;
}
while (TRUE);
//
// If we didn't find the SP, the subkey will be closed.
//
if (! RegObjectDP8SPSubkey.IsOpen())
{
DPFX(DPFPREP, 0, "Didn't find DirectPlay8 SP matching given GUID!");
hr = E_FAIL;
goto Failure;
}
//
// We don't need the main SP key or name buffer anymore.
//
RegObjectDP8SP.Close();
DNFree(pwszTemp);
pwszTemp = NULL;
//
// Find the size of the original SP friendly name.
//
dwLength = 0;
RegObjectDP8SPSubkey.ReadString(DPN_REG_KEYNAME_FRIENDLY_NAME, NULL, &dwLength);
dwLength++;
pwszTemp = (WCHAR*) DNMalloc(dwLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
if (! RegObjectDP8SPSubkey.ReadString(DPN_REG_KEYNAME_FRIENDLY_NAME, pwszTemp, &dwLength))
{
DPFX(DPFPREP, 0, "Couldn't read existing SP's friendly name!");
hr = E_FAIL;
goto Failure;
}
//
// Save it so we can restore it later.
//
if (! RegObjectDP8SPSubkey.WriteString(DP8SIM_REG_REALSPFRIENDLYNAME, pwszTemp))
{
DPFX(DPFPREP, 0, "Couldn't save SP's existing friendly name to value \"%S\"!",
DP8SIM_REG_REALSPFRIENDLYNAME);
hr = E_FAIL;
goto Failure;
}
//
// Write our replacement DLL's friendly name.
//
if (! RegObjectDP8SPSubkey.WriteString(DPN_REG_KEYNAME_FRIENDLY_NAME, wszNewFriendlyName))
{
DPFX(DPFPREP, 0, "Couldn't write our new SP friendly name to registry!");
hr = E_FAIL;
goto Failure;
}
RegObjectDP8SPSubkey.Close();
//
// Finally write our replacement DLL's location.
//
if (! RegObjectCOM.WriteString(L"", wszLocalPath))
{
DPFX(DPFPREP, 0, "Couldn't write our DLL location to registry!");
hr = E_FAIL;
goto Failure;
}
RegObjectCOM.Close();
Exit:
if (pwszTemp != NULL)
{
DNFree(pwszTemp);
pwszTemp = NULL;
}
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
//
// RegObjectCOM, RegObjectDP8SP, and RegObjectDP8SPSubkey are all
// implicitly closed by their destructors, if necessary.
//
goto Exit;
} // EnableControlForSP
#undef DPF_MODNAME
#define DPF_MODNAME "DisableControlForSP"
//=============================================================================
// CDP8SimControl::DisableControlForSP
//-----------------------------------------------------------------------------
//
// Description: Removes the DP8Sim Control shim from the SP with the given
// GUID.
//
// Arguments:
// GUID * pguidSP - Pointer to GUID of SP that should no longer be
// intercepted.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::DisableControlForSP(const GUID * const pguidSP,
const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
WCHAR wszInProcServer32[_MAX_PATH];
CRegistry RegObject;
CRegistry RegObjectSubkey;
DWORD dwMaxLength;
DWORD dwLength;
WCHAR * pwszTemp = NULL;
DWORD dwTemp;
GUID guidTemp;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%x)", this, pguidSP, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pguidSP != NULL);
DNASSERT(dwFlags == 0);
#ifdef DEBUG
DNEnterCriticalSection(&this->m_csLock);
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
#endif // DEBUG
//
// Find the SP key. First allocate enough memory to hold the name the
// longest subkey.
//
if (! RegObject.Open(HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open DirectPlay8 SP key!");
hr = E_FAIL;
goto Failure;
}
if (! RegObject.GetMaxKeyLen(dwMaxLength))
{
DPFX(DPFPREP, 0, "Could not get longest SP key name length!");
hr = E_FAIL;
goto Failure;
}
dwMaxLength++;
pwszTemp = (WCHAR*) DNMalloc(dwMaxLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
//
// Walk through every key, looking for the right one.
//
dwTemp = 0;
do
{
dwLength = dwMaxLength;
if (! RegObject.EnumKeys(pwszTemp, &dwLength, dwTemp))
{
//
// We couldn't get the next key. Assume we're done.
//
break;
}
//
// Open the subkey.
//
if (! RegObjectSubkey.Open((HKEY) RegObject, pwszTemp, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open DirectPlay8 SP sub key \"%S\"! Ignoring.", pwszTemp);
}
else
{
//
// See if the GUID matches.
//
RegObjectSubkey.ReadGUID(DPN_REG_KEYNAME_GUID, guidTemp);
if (guidTemp == (*pguidSP))
{
//
// Found SP.
//
DPFX(DPFPREP, 5, "Found SP under sub key \"%S\".", pwszTemp);
break;
}
RegObjectSubkey.Close();
}
//
// Got to next subkey.
//
dwTemp++;
}
while (TRUE);
//
// If we didn't find the SP, the subkey will be closed.
//
if (! RegObjectSubkey.IsOpen())
{
DPFX(DPFPREP, 0, "Didn't find DirectPlay8 SP matching given GUID!");
hr = E_FAIL;
goto Failure;
}
//
// We don't need the main SP key or name buffer anymore.
//
RegObject.Close();
DNFree(pwszTemp);
pwszTemp = NULL;
//
// Find the size of the original SP friendly name.
//
dwLength = 0;
RegObjectSubkey.ReadString(DP8SIM_REG_REALSPFRIENDLYNAME, NULL, &dwLength);
dwLength++;
pwszTemp = (WCHAR*) DNMalloc(dwLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
if (! RegObjectSubkey.ReadString(DP8SIM_REG_REALSPFRIENDLYNAME, pwszTemp, &dwLength))
{
DPFX(DPFPREP, 0, "Couldn't read SP's original friendly name!");
hr = E_FAIL;
goto Failure;
}
//
// Restore the value.
//
if (! RegObjectSubkey.WriteString(DPN_REG_KEYNAME_FRIENDLY_NAME, pwszTemp))
{
DPFX(DPFPREP, 0, "Couldn't restore SP's original friendly name!");
hr = E_FAIL;
goto Failure;
}
//
// Delete the restoration key.
//
if (! RegObjectSubkey.DeleteValue(DP8SIM_REG_REALSPFRIENDLYNAME))
{
DPFX(DPFPREP, 0, "Couldn't delete friendly name restoration key \"%S\"!",
DP8SIM_REG_REALSPDLL);
hr = E_FAIL;
goto Failure;
}
RegObjectSubkey.Close();
DNFree(pwszTemp);
pwszTemp = NULL;
//
// Open the SP's COM object information key.
//
swprintf(wszInProcServer32, L"CLSID\\{%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}\\InProcServer32",
pguidSP->Data1, pguidSP->Data2, pguidSP->Data3,
pguidSP->Data4[0], pguidSP->Data4[1],
pguidSP->Data4[2], pguidSP->Data4[3],
pguidSP->Data4[4], pguidSP->Data4[5],
pguidSP->Data4[6], pguidSP->Data4[7]);
if (! RegObject.Open(HKEY_CLASSES_ROOT, wszInProcServer32, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open SP InProcServer32 key!");
hr = E_FAIL;
goto Failure;
}
//
// Read the location of the original DLL.
//
dwLength = 0;
RegObject.ReadString(DP8SIM_REG_REALSPDLL, NULL, &dwLength);
dwLength++;
pwszTemp = (WCHAR*) DNMalloc(dwLength * sizeof(WCHAR));
if (pwszTemp == NULL)
{
hr = E_OUTOFMEMORY;
goto Failure;
}
if (! RegObject.ReadString(DP8SIM_REG_REALSPDLL, pwszTemp, &dwLength))
{
DPFX(DPFPREP, 0, "Couldn't read original SP's DLL location (\"%S\"), assuming DP8Sim was not enabled!",
DP8SIM_REG_REALSPDLL);
hr = DP8SIMERR_NOTENABLEDFORSP;
goto Failure;
}
//
// Restore the value.
//
if (! RegObject.WriteString(L"", pwszTemp))
{
DPFX(DPFPREP, 0, "Couldn't restore SP's original DLL location!");
hr = E_FAIL;
goto Failure;
}
//
// Delete the restoration key.
//
if (! RegObject.DeleteValue(DP8SIM_REG_REALSPDLL))
{
DPFX(DPFPREP, 0, "Couldn't delete restoration key \"%S\"!",
DP8SIM_REG_REALSPDLL);
hr = E_FAIL;
goto Failure;
}
RegObject.Close();
//
// Since we can't actually unload the wrapper from any processes already
// using it, those will continue using the current settings
//
Exit:
if (pwszTemp != NULL)
{
DNFree(pwszTemp);
pwszTemp = NULL;
}
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
//
// RegObject, and RegObjectSubkey are implicitly closed by their
// destructors, if necessary.
//
goto Exit;
} // DisableControlForSP
#undef DPF_MODNAME
#define DPF_MODNAME "GetControlEnabledForSP"
//=============================================================================
// CDP8SimControl::GetControlEnabledForSP
//-----------------------------------------------------------------------------
//
// Description: Determines whether the DP8Sim Control shim is enabled for the
// SP with the given GUID or not. TRUE is returned in pfEnabled
// if so, FALSE if not.
//
// Arguments:
// GUID * pguidSP - Pointer to GUID of SP that should be checked.
// BOOL * pfEnabled - Place to store boolean indicating status.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::GetControlEnabledForSP(const GUID * const pguidSP,
BOOL * const pfEnabled,
const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
WCHAR wszInProcServer32[_MAX_PATH];
CRegistry RegObject;
CRegistry RegObjectSubkey;
DWORD dwLength;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%p, 0x%x)",
this, pguidSP, pfEnabled, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pguidSP != NULL);
DNASSERT(pfEnabled != NULL);
DNASSERT(dwFlags == 0);
#ifdef DEBUG
DNEnterCriticalSection(&this->m_csLock);
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
#endif // DEBUG
//
// Open the SP's COM object information key.
//
swprintf(wszInProcServer32, L"CLSID\\{%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}\\InProcServer32",
pguidSP->Data1, pguidSP->Data2, pguidSP->Data3,
pguidSP->Data4[0], pguidSP->Data4[1],
pguidSP->Data4[2], pguidSP->Data4[3],
pguidSP->Data4[4], pguidSP->Data4[5],
pguidSP->Data4[6], pguidSP->Data4[7]);
if (! RegObject.Open(HKEY_CLASSES_ROOT, wszInProcServer32, FALSE, FALSE, FALSE))
{
DPFX(DPFPREP, 0, "Could not open SP InProcServer32 key!");
hr = E_FAIL;
goto Failure;
}
//
// Try reading the location of the original DLL. dwLength will stay 0 if
// the registry key could not be opened.
//
dwLength = 0;
RegObject.ReadString(DP8SIM_REG_REALSPDLL, NULL, &dwLength);
if (dwLength == 0)
{
DPFX(DPFPREP, 1, "Couldn't read original SP's DLL location (\"%S\"), assuming DP8Sim was not enabled.",
DP8SIM_REG_REALSPDLL);
(*pfEnabled) = FALSE;
}
else
{
DPFX(DPFPREP, 1, "Retrieved original SP's DLL location value size, assuming DP8Sim was enabled.");
(*pfEnabled) = TRUE;
}
RegObject.Close();
Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
//
// RegObject, and RegObjectSubkey are implicitly closed by their
// destructors, if necessary.
//
goto Exit;
} // GetControlEnabledForSP
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::GetAllParameters"
//=============================================================================
// CDP8SimControl::GetAllParameters
//-----------------------------------------------------------------------------
//
// Description: Retrieves all of the current DP8Sim settings.
//
// Arguments:
// DP8SIM_PARAMETERS * pdp8spSend - Place to store current send
// parameters.
// DP8SIM_PARAMETERS * pdp8spReceive - Place to store current receive
// parameters.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::GetAllParameters(DP8SIM_PARAMETERS * const pdp8spSend,
DP8SIM_PARAMETERS * const pdp8spReceive,
const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
//BOOL fHaveLock = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%p, 0x%x)",
this, pdp8spSend, pdp8spReceive, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pdp8spSend != NULL);
DNASSERT(pdp8spReceive != NULL);
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
//fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Retrieve the settings from the IPC object.
//
this->m_DP8SimIPC.GetAllParameters(pdp8spSend, pdp8spReceive);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
//fHaveLock = FALSE;
//Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
/*
Failure:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
goto Exit;
*/
} // CDP8SimControl::GetAllParameters
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::SetAllParameters"
//=============================================================================
// CDP8SimControl::SetAllParameters
//-----------------------------------------------------------------------------
//
// Description: Modifies the current DP8Sim settings.
//
// Arguments:
// DP8SIM_PARAMETERS * pdp8spSend - Structure containing desired send
// parameters.
// DP8SIM_PARAMETERS * pdp8spReceive - Structure containing desired
// receive parameters.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::SetAllParameters(const DP8SIM_PARAMETERS * const pdp8spSend,
const DP8SIM_PARAMETERS * const pdp8spReceive,
const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
//BOOL fHaveLock = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%p, 0x%x)",
this, pdp8spSend, pdp8spReceive, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pdp8spSend != NULL);
DNASSERT(pdp8spSend->dwMinLatencyMS <= pdp8spSend->dwMaxLatencyMS);
DNASSERT(pdp8spReceive != NULL);
DNASSERT(pdp8spReceive->dwMinLatencyMS <= pdp8spReceive->dwMaxLatencyMS);
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
//fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Store the settings with the IPC object.
//
this->m_DP8SimIPC.SetAllParameters(pdp8spSend, pdp8spReceive);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
//fHaveLock = FALSE;
//Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
/*
Failure:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
goto Exit;
*/
} // CDP8SimControl::SetAllParameters
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::GetAllStatistics"
//=============================================================================
// CDP8SimControl::GetAllStatistics
//-----------------------------------------------------------------------------
//
// Description: Retrieves all of the current DP8Sim statistics.
//
// Arguments:
// DP8SIM_STATISTICS * pdp8ssSend - Place to store current send
// statistics.
// DP8SIM_STATISTICS * pdp8ssReceive - Place to store current receive
// statistics.
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::GetAllStatistics(DP8SIM_STATISTICS * const pdp8ssSend,
DP8SIM_STATISTICS * const pdp8ssReceive,
const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
//BOOL fHaveLock = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%p, 0x%x)",
this, pdp8ssSend, pdp8ssReceive, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pdp8ssSend != NULL);
DNASSERT(pdp8ssReceive != NULL);
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
//fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Retrieve the stats from the IPC object.
//
this->m_DP8SimIPC.GetAllStatistics(pdp8ssSend, pdp8ssReceive);
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
//fHaveLock = FALSE;
//Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
/*
Failure:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
goto Exit;
*/
} // CDP8SimControl::GetAllStatistics
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::ClearAllStatistics"
//=============================================================================
// CDP8SimControl::ClearAllStatistics
//-----------------------------------------------------------------------------
//
// Description: Clears all of the current DP8Sim statistics.
//
// Arguments:
// DWORD dwFlags - Unused, must be zero.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimControl::ClearAllStatistics(const DWORD dwFlags)
{
HRESULT hr = DP8SIM_OK;
//BOOL fHaveLock = FALSE;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%x)", this, dwFlags);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(dwFlags == 0);
DNEnterCriticalSection(&this->m_csLock);
//fHaveLock = TRUE;
//
// Assert the object state.
//
DNASSERT(this->m_dwFlags & DP8SIMCONTROLOBJ_INITIALIZED);
//
// Have the IPC object clear the stats.
//
this->m_DP8SimIPC.ClearAllStatistics();
//
// Drop the lock.
//
DNLeaveCriticalSection(&this->m_csLock);
//fHaveLock = FALSE;
//Exit:
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
/*
Failure:
if (fHaveLock)
{
DNLeaveCriticalSection(&this->m_csLock);
}
goto Exit;
*/
} // CDP8SimControl::ClearAllStatistics
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::InitializeObject"
//=============================================================================
// CDP8SimControl::InitializeObject
//-----------------------------------------------------------------------------
//
// Description: Sets up the object for use like the constructor, but may
// fail with OUTOFMEMORY. Should only be called by class factory
// creation routine.
//
// Arguments: None.
//
// Returns: HRESULT
// S_OK - Initialization was successful.
// E_OUTOFMEMORY - There is not enough memory to initialize.
//=============================================================================
HRESULT CDP8SimControl::InitializeObject(void)
{
HRESULT hr;
DPFX(DPFPREP, 5, "(0x%p) Enter", this);
DNASSERT(this->IsValidObject());
//
// Create the lock.
//
if (! DNInitializeCriticalSection(&this->m_csLock))
{
hr = E_OUTOFMEMORY;
goto Failure;
}
//
// Don't allow critical section reentry.
//
DebugSetCriticalSectionRecursionCount(&this->m_csLock, 0);
hr = S_OK;
Exit:
DPFX(DPFPREP, 5, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
goto Exit;
} // CDP8SimControl::InitializeObject
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimControl::UninitializeObject"
//=============================================================================
// CDP8SimControl::UninitializeObject
//-----------------------------------------------------------------------------
//
// Description: Cleans up the object like the destructor, mostly to balance
// InitializeObject.
//
// Arguments: None.
//
// Returns: None.
//=============================================================================
void CDP8SimControl::UninitializeObject(void)
{
DPFX(DPFPREP, 5, "(0x%p) Enter", this);
DNASSERT(this->IsValidObject());
DNDeleteCriticalSection(&this->m_csLock);
DPFX(DPFPREP, 5, "(0x%p) Returning", this);
} // CDP8SimControl::UninitializeObject