You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
995 lines
23 KiB
995 lines
23 KiB
/***************************************************************************
|
|
*
|
|
* Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dp8simdllmain.cpp
|
|
*
|
|
* Content: DP8SIM DLL entry points.
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ======== ======== =========
|
|
* 04/23/01 VanceO Created.
|
|
*
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "dp8simi.h"
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// External globals
|
|
//=============================================================================
|
|
volatile LONG g_lOutstandingInterfaceCount = 0; // number of outstanding interfaces
|
|
|
|
HINSTANCE g_hDLLInstance = NULL; // handle to this DLL instance
|
|
|
|
DNCRITICAL_SECTION g_csGlobalsLock; // lock protecting all of the following globals
|
|
CBilink g_blDP8SimSPObjs; // bilink of all the DP8SimSP interface objects
|
|
CBilink g_blDP8SimControlObjs; // bilink of all the DP8SimControl interface objects
|
|
|
|
UINT g_uiRandShr3 = 0; // global holding value for Shr3 random number sequence generator
|
|
UINT g_uiRandCong = 0; // global holding value for congruential random number sequence generator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Supported SPs table
|
|
//=============================================================================
|
|
typedef struct _SUPPORTEDSP
|
|
{
|
|
const CLSID * pclsidFakeSP; // pointer to class ID for fake SP
|
|
const CLSID * pclsidRealSP; // pointer to class ID for real SP
|
|
const WCHAR * pwszVerIndProgID; // version independent prog ID for fake SP COM object, must match the sub key for pwszServiceProviderKey
|
|
const WCHAR * pwszProgID; // prog ID for fake SP COM object
|
|
const WCHAR * pwszDesc; // description for fake SP COM object
|
|
const WCHAR * pwszServiceProviderKey; // service provider key string, sub key must match pwszVerIndProgID
|
|
UINT uiFriendlyNameResourceID; // ID of fake SP's name string resource
|
|
} SUPPORTEDSP;
|
|
|
|
const SUPPORTEDSP c_aSupportedSPs[] =
|
|
{
|
|
{
|
|
(&CLSID_NETWORKSIMULATOR_DP8SP_TCPIP),
|
|
(&CLSID_DP8SP_TCPIP),
|
|
L"DP8SimTCPIP",
|
|
L"DP8SimTCPIP.1",
|
|
L"DirectPlay8 Network Simulator TCP/IP Service Provider",
|
|
DPN_REG_LOCAL_SP_SUBKEY L"\\DP8SimTCPIP",
|
|
IDS_FRIENDLYNAME_TCPIP,
|
|
},
|
|
};
|
|
|
|
#define NUM_SUPPORTED_SPS (sizeof(c_aSupportedSPs) / sizeof(c_aSupportedSPs[0]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Defines
|
|
//=============================================================================
|
|
#define MAX_RESOURCE_STRING_LENGTH _MAX_PATH
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Macros
|
|
//=============================================================================
|
|
|
|
// 3-shift register generator
|
|
//
|
|
// Original comments:
|
|
// SHR3 is a 3-shift-register generator with period 2^32-1. It uses
|
|
// y(n)=y(n-1)(I+L^17)(I+R^13)(I+L^5), with the y's viewed as binary vectors,
|
|
// L the 32x32 binary matrix that shifts a vector left 1, and R its transpose.
|
|
// SHR3 seems to pass all except those related to the binary rank test, since
|
|
// 32 successive values, as binary vectors, must be linearly independent,
|
|
// while 32 successive truly random 32-bit integers, viewed as binary vectors,
|
|
// will be linearly independent only about 29% of the time.
|
|
#define RANDALG_SHR3() (g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 << 17), g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 >> 13), g_uiRandShr3 = g_uiRandShr3 ^ (g_uiRandShr3 << 5))
|
|
|
|
// Congruential generator
|
|
//
|
|
// Original comments:
|
|
// CONG is a congruential generator with the widely used 69069 multiplier:
|
|
// x(n)=69069x(n-1)+1234567. It has period 2^32. The leading half of its 32
|
|
// bits seem to pass tests, but bits in the last half are too regular.
|
|
#define RANDALG_CONG() (g_uiRandCong = 69069UL * g_uiRandCong + 1234567UL)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Local prototypes
|
|
//=============================================================================
|
|
BOOL InitializeProcessGlobals(void);
|
|
void CleanupProcessGlobals(void);
|
|
HRESULT LoadAndAllocString(UINT uiResourceID, WCHAR ** pwszString);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DllMain"
|
|
//=============================================================================
|
|
// DllMain
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: DLL entry point.
|
|
//
|
|
// Arguments:
|
|
// HINSTANCE hDllInst - Handle to this DLL module.
|
|
// DWORD dwReason - Reason for calling this function.
|
|
// LPVOID lpvReserved - Reserved.
|
|
//
|
|
// Returns: TRUE if all goes well, FALSE otherwise.
|
|
//=============================================================================
|
|
BOOL WINAPI DllMain(HINSTANCE hDllInst,
|
|
DWORD dwReason,
|
|
LPVOID lpvReserved)
|
|
{
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
DPFX(DPFPREP, 2, "====> ENTER: DLLMAIN(%p): Process Attach: %08lx, tid=%08lx",
|
|
DllMain, GetCurrentProcessId(), GetCurrentThreadId());
|
|
|
|
|
|
DNASSERT(g_hDLLInstance == NULL);
|
|
g_hDLLInstance = hDllInst;
|
|
|
|
|
|
//
|
|
// Attempt to initialize the OS abstraction layer.
|
|
//
|
|
if (! DNOSIndirectionInit(0))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize OS indirection layer!");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Attempt to initialize COM.
|
|
//
|
|
if (FAILED(COM_Init()))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize COM indirection layer!");
|
|
DNOSIndirectionDeinit();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Attempt to initialize process-global items.
|
|
//
|
|
if (! InitializeProcessGlobals())
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize globals!");
|
|
COM_Free();
|
|
DNOSIndirectionDeinit();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// We don't need thread attach/detach messages.
|
|
//
|
|
DisableThreadLibraryCalls(hDllInst);
|
|
|
|
return TRUE;
|
|
break;
|
|
}
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
{
|
|
DPFX(DPFPREP, 2, "====> EXIT: DLLMAIN(%p): Process Detach %08lx, tid=%08lx",
|
|
DllMain, GetCurrentProcessId(), GetCurrentThreadId());
|
|
|
|
|
|
DNASSERT(g_hDLLInstance != NULL);
|
|
g_hDLLInstance = NULL;
|
|
|
|
|
|
CleanupProcessGlobals();
|
|
COM_Free();
|
|
DNOSIndirectionDeinit();
|
|
|
|
return TRUE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
} // DllMain
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DllRegisterServer"
|
|
//=============================================================================
|
|
// DllRegisterServer
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Registers the DP8Sim COM object.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: HRESULT
|
|
// S_OK - Successfully registered DP8Sim.
|
|
// E_FAIL - Failed registering DP8Sim.
|
|
//=============================================================================
|
|
HRESULT WINAPI DllRegisterServer(void)
|
|
{
|
|
HRESULT hr;
|
|
CRegistry RegObject;
|
|
DWORD dwLength;
|
|
DWORD dwSimulatedSP;
|
|
char szLocalPath[_MAX_PATH + 1];
|
|
WCHAR wszLocalPath[_MAX_PATH + 1];
|
|
WCHAR * pwszFriendlyName = NULL;
|
|
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
szLocalPath[dwLength] = '\0';
|
|
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;
|
|
}
|
|
|
|
|
|
//
|
|
// Register the control COM object CLSID.
|
|
//
|
|
if (! RegObject.Register(L"DP8SimControl.1",
|
|
L"DirectPlay8 Network Simulator Control Object",
|
|
wszLocalPath,
|
|
&CLSID_DP8SimControl,
|
|
L"DP8SimControl"))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not register DP8SimControl object!");
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Register all of the simulated SPs.
|
|
//
|
|
for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
|
|
{
|
|
if (! RegObject.Register(c_aSupportedSPs[dwSimulatedSP].pwszProgID,
|
|
c_aSupportedSPs[dwSimulatedSP].pwszDesc,
|
|
wszLocalPath,
|
|
c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP,
|
|
c_aSupportedSPs[dwSimulatedSP].pwszVerIndProgID))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not register simulated SP %u object!",
|
|
dwSimulatedSP);
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
hr = LoadAndAllocString(c_aSupportedSPs[dwSimulatedSP].uiFriendlyNameResourceID,
|
|
&pwszFriendlyName);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not load friendly name string (err = 0x%lx)!", hr);
|
|
goto Failure;
|
|
}
|
|
|
|
if (! RegObject.Open(HKEY_LOCAL_MACHINE, c_aSupportedSPs[dwSimulatedSP].pwszServiceProviderKey, FALSE, TRUE))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not open service provider key!");
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
RegObject.WriteString(DPN_REG_KEYNAME_FRIENDLY_NAME, pwszFriendlyName);
|
|
RegObject.WriteGUID(DPN_REG_KEYNAME_GUID, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP));
|
|
RegObject.Close();
|
|
|
|
DNFree(pwszFriendlyName);
|
|
pwszFriendlyName = NULL;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
if (pwszFriendlyName != NULL)
|
|
{
|
|
DNFree(pwszFriendlyName);
|
|
pwszFriendlyName = NULL;
|
|
}
|
|
|
|
goto Exit;
|
|
} // DllRegisterServer
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DllUnregisterServer"
|
|
//=============================================================================
|
|
// DllUnregisterServer
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Unregisters the DP8Sim COM object.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: HRESULT
|
|
// S_OK - Successfully unregistered DP8Sim.
|
|
// E_FAIL - Failed unregistering DP8Sim.
|
|
//=============================================================================
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
HRESULT hr;
|
|
CRegistry RegObject;
|
|
DWORD dwSimulatedSP;
|
|
|
|
|
|
//
|
|
// Unregister the control class.
|
|
//
|
|
if (! RegObject.UnRegister(&CLSID_DP8SimControl))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to unregister DP8Sim control object!");
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Unregister all of the simulated SPs.
|
|
//
|
|
|
|
if (! RegObject.Open(HKEY_LOCAL_MACHINE, DPN_REG_LOCAL_SP_SUBKEY, FALSE, FALSE, FALSE))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not open HKEY_LOCAL_MACHINE!");
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
|
|
{
|
|
if (! RegObject.UnRegister(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not unregister simulated SP %u object!",
|
|
dwSimulatedSP);
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
|
|
if (! RegObject.DeleteSubKey(c_aSupportedSPs[dwSimulatedSP].pwszVerIndProgID))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not delete simulated SP %u's key!",
|
|
dwSimulatedSP);
|
|
hr = E_FAIL;
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
RegObject.Close();
|
|
hr = S_OK;
|
|
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
//
|
|
// Rely on RegObject destructure to close registry key.
|
|
//
|
|
|
|
goto Exit;
|
|
} // DllUnregisterServer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InitializeProcessGlobals"
|
|
//=============================================================================
|
|
// InitializeProcessGlobals
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Initialize global items needed for the DLL to operate.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: TRUE if successful, FALSE if an error occurred.
|
|
//=============================================================================
|
|
BOOL InitializeProcessGlobals(void)
|
|
{
|
|
BOOL fReturn = TRUE;
|
|
BOOL fInittedGlobalLock = FALSE;
|
|
|
|
|
|
if (! DNInitializeCriticalSection(&g_csGlobalsLock))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize global lock!");
|
|
goto Failure;
|
|
}
|
|
|
|
fInittedGlobalLock = TRUE;
|
|
|
|
|
|
//
|
|
// Don't allow critical section reentry.
|
|
//
|
|
DebugSetCriticalSectionRecursionCount(&g_csGlobalsLock, 0);
|
|
|
|
|
|
if (!InitializePools())
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed initializing pools!");
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
g_blDP8SimSPObjs.Initialize();
|
|
g_blDP8SimControlObjs.Initialize();
|
|
|
|
|
|
//
|
|
// Seed the random number generator with the current time.
|
|
//
|
|
InitializeGlobalRand(GETTIMESTAMP());
|
|
|
|
|
|
Exit:
|
|
|
|
return fReturn;
|
|
|
|
|
|
Failure:
|
|
|
|
if (fInittedGlobalLock)
|
|
{
|
|
DNDeleteCriticalSection(&g_csGlobalsLock);
|
|
}
|
|
|
|
fReturn = FALSE;
|
|
|
|
goto Exit;
|
|
} // InitializeProcessGlobals
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CleanupProcessGlobals"
|
|
//=============================================================================
|
|
// CleanupProcessGlobals
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Releases global items used by DLL.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: None.
|
|
//=============================================================================
|
|
void CleanupProcessGlobals(void)
|
|
{
|
|
CBilink * pBilink;
|
|
CDP8SimSP * pDP8SimSP;
|
|
CDP8SimControl * pDP8SimControl;
|
|
|
|
|
|
if (! g_blDP8SimSPObjs.IsEmpty())
|
|
{
|
|
DNASSERT(! "DP8Sim DLL unloading without all SP objects having been released!");
|
|
|
|
//
|
|
// Force close all the objects still outstanding.
|
|
//
|
|
pBilink = g_blDP8SimSPObjs.GetNext();
|
|
while (pBilink != &g_blDP8SimSPObjs)
|
|
{
|
|
pDP8SimSP = DP8SIMSP_FROM_BILINK(pBilink);
|
|
pBilink = pBilink->GetNext();
|
|
|
|
|
|
DPFX(DPFPREP, 0, "Forcefully releasing SP object 0x%p!", pDP8SimSP);
|
|
|
|
pDP8SimSP->Close(); // ignore error
|
|
|
|
|
|
//
|
|
// Forcefully remove it from the list and delete it instead of
|
|
// using pDP8SimSP->Release().
|
|
//
|
|
pDP8SimSP->m_blList.RemoveFromList();
|
|
pDP8SimSP->UninitializeObject();
|
|
delete pDP8SimSP;
|
|
}
|
|
}
|
|
|
|
|
|
if (! g_blDP8SimControlObjs.IsEmpty())
|
|
{
|
|
DNASSERT(! "DP8Sim DLL unloading without all Control objects having been released!");
|
|
|
|
//
|
|
// Force close all the objects still outstanding.
|
|
//
|
|
pBilink = g_blDP8SimControlObjs.GetNext();
|
|
while (pBilink != &g_blDP8SimControlObjs)
|
|
{
|
|
pDP8SimControl = DP8SIMCONTROL_FROM_BILINK(pBilink);
|
|
pBilink = pBilink->GetNext();
|
|
|
|
|
|
DPFX(DPFPREP, 0, "Forcefully releasing Control object 0x%p!", pDP8SimControl);
|
|
|
|
pDP8SimControl->Close(0); // ignore error
|
|
|
|
|
|
//
|
|
// Forcefully remove it from the list and delete it instead of
|
|
// using pDP8SimControl->Release().
|
|
//
|
|
pDP8SimControl->m_blList.RemoveFromList();
|
|
pDP8SimControl->UninitializeObject();
|
|
delete pDP8SimControl;
|
|
}
|
|
}
|
|
|
|
CleanupPools();
|
|
|
|
DNDeleteCriticalSection(&g_csGlobalsLock);
|
|
} // CleanupProcessGlobals
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "LoadAndAllocString"
|
|
//=============================================================================
|
|
// LoadAndAllocString
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: DNMallocs a wide character string from the given resource ID.
|
|
//
|
|
// Arguments:
|
|
// UINT uiResourceID - Resource ID to load.
|
|
// WCHAR ** pwszString - Place to store pointer to allocated string.
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
HRESULT LoadAndAllocString(UINT uiResourceID, WCHAR ** pwszString)
|
|
{
|
|
HRESULT hr = DPN_OK;
|
|
int iLength;
|
|
|
|
|
|
if (DNGetOSType() == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
WCHAR wszTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
|
|
|
|
|
|
iLength = LoadStringW(g_hDLLInstance, uiResourceID, wszTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
|
|
if (iLength == 0)
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, 0, "Unable to load resource ID %d error 0x%x", uiResourceID, hr);
|
|
(*pwszString) = NULL;
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
(*pwszString) = (WCHAR*) DNMalloc((iLength + 1) * sizeof(WCHAR));
|
|
if ((*pwszString) == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Memory allocation failure!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
wcscpy((*pwszString), wszTmpBuffer);
|
|
}
|
|
else
|
|
{
|
|
char szTmpBuffer[MAX_RESOURCE_STRING_LENGTH];
|
|
|
|
|
|
iLength = LoadStringA(g_hDLLInstance, uiResourceID, szTmpBuffer, MAX_RESOURCE_STRING_LENGTH );
|
|
if (iLength == 0)
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, 0, "Unable to load resource ID %u (err =0x%lx)!", uiResourceID, hr);
|
|
(*pwszString) = NULL;
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
(*pwszString) = (WCHAR*) DNMalloc((iLength + 1) * sizeof(WCHAR));
|
|
if ((*pwszString) == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Memory allocation failure!");
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
hr = STR_jkAnsiToWide((*pwszString), szTmpBuffer, (iLength + 1));
|
|
if (hr == DPN_OK)
|
|
{
|
|
hr = GetLastError();
|
|
|
|
DPFX(DPFPREP, 0, "Unable to convert from ANSI to Unicode (err =0x%lx)!", hr);
|
|
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
} // LoadAndAllocString
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "InitializeGlobalRand"
|
|
//=============================================================================
|
|
// InitializeGlobalRand
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Initializes the global psuedo-random number generator, using
|
|
// the given seed value.
|
|
//
|
|
// Based off algorithms posted to usenet by George Marsaglia.
|
|
//
|
|
// Arguments:
|
|
// DWORD dwSeed - Seed to use.
|
|
//
|
|
// Returns: None.
|
|
//=============================================================================
|
|
void InitializeGlobalRand(const DWORD dwSeed)
|
|
{
|
|
//
|
|
// We don't need to hold a lock, since this should only be done once,
|
|
// during initialization time.
|
|
//
|
|
g_uiRandShr3 = dwSeed;
|
|
g_uiRandCong = dwSeed;
|
|
} // InitializeGlobalRand
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetGlobalRand"
|
|
//=============================================================================
|
|
// GetGlobalRand
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Generates a pseudo-random positive double between 0.0 and
|
|
// 1.0, inclusive.
|
|
//
|
|
// Based off algorithms posted to usenet by George Marsaglia.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: Pseudo-random number.
|
|
//=============================================================================
|
|
double GetGlobalRand(void)
|
|
{
|
|
double dResult;
|
|
|
|
|
|
DNEnterCriticalSection(&g_csGlobalsLock);
|
|
|
|
dResult = (RANDALG_CONG() + RANDALG_SHR3()) * 2.328306e-10f;
|
|
|
|
DNLeaveCriticalSection(&g_csGlobalsLock);
|
|
|
|
return dResult;
|
|
} // GetGlobalRand
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DoCreateInstance"
|
|
//=============================================================================
|
|
// DoCreateInstance
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Creates an instance of an interface. Required by the general
|
|
// purpose class factory functions.
|
|
//
|
|
// Arguments:
|
|
// LPCLASSFACTORY This - Pointer to class factory.
|
|
// LPUNKNOWN pUnkOuter - Pointer to unknown interface.
|
|
// REFCLSID rclsid - Reference of GUID of desired interface.
|
|
// REFIID riid - Reference to another GUID?
|
|
// LPVOID * ppvObj - Pointer to pointer to interface.
|
|
//
|
|
// Returns: HRESULT
|
|
//=============================================================================
|
|
HRESULT DoCreateInstance(LPCLASSFACTORY This,
|
|
LPUNKNOWN pUnkOuter,
|
|
REFCLSID rclsid,
|
|
REFIID riid,
|
|
LPVOID * ppvObj)
|
|
{
|
|
HRESULT hr;
|
|
CDP8SimSP * pDP8SimSP = NULL;
|
|
CDP8SimControl * pDP8SimControl = NULL;
|
|
DWORD dwSimulatedSP;
|
|
|
|
|
|
DNASSERT(ppvObj != NULL);
|
|
|
|
|
|
//
|
|
// See if it's the control object.
|
|
//
|
|
if (IsEqualCLSID(rclsid, CLSID_DP8SimControl))
|
|
{
|
|
//
|
|
// Create the object instance.
|
|
//
|
|
pDP8SimControl = new CDP8SimControl;
|
|
if (pDP8SimControl == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize the base object (which might fail).
|
|
//
|
|
hr = pDP8SimControl->InitializeObject();
|
|
if (hr != S_OK)
|
|
{
|
|
delete pDP8SimControl;
|
|
pDP8SimControl = NULL;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Add it to the global list.
|
|
//
|
|
DNEnterCriticalSection(&g_csGlobalsLock);
|
|
|
|
pDP8SimControl->m_blList.InsertBefore(&g_blDP8SimControlObjs);
|
|
|
|
g_lOutstandingInterfaceCount++; // update count so DllCanUnloadNow works correctly
|
|
|
|
DNLeaveCriticalSection(&g_csGlobalsLock);
|
|
|
|
|
|
//
|
|
// Get the right interface for the caller and bump the refcount.
|
|
//
|
|
hr = pDP8SimControl->QueryInterface(riid, ppvObj);
|
|
if (hr != S_OK)
|
|
{
|
|
goto Failure;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Look up the real SP we're replacing.
|
|
//
|
|
for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
|
|
{
|
|
if (IsEqualCLSID(rclsid, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP)))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we didn't find it
|
|
//
|
|
if (dwSimulatedSP >= NUM_SUPPORTED_SPS)
|
|
{
|
|
DPFX(DPFPREP, 0, "Unrecognized service provider class ID!");
|
|
hr = E_UNEXPECTED;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Create the object instance.
|
|
//
|
|
pDP8SimSP = new CDP8SimSP(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP,
|
|
c_aSupportedSPs[dwSimulatedSP].pclsidRealSP);
|
|
if (pDP8SimSP == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// Initialize the base object (which might fail).
|
|
//
|
|
hr = pDP8SimSP->InitializeObject();
|
|
if (hr != S_OK)
|
|
{
|
|
DPFX(DPFPREP, 0, "Couldn't initialize object!");
|
|
delete pDP8SimSP;
|
|
pDP8SimSP = NULL;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// Add it to the global list.
|
|
//
|
|
DNEnterCriticalSection(&g_csGlobalsLock);
|
|
|
|
pDP8SimSP->m_blList.InsertBefore(&g_blDP8SimSPObjs);
|
|
|
|
g_lOutstandingInterfaceCount++; // update count so DllCanUnloadNow works correctly
|
|
|
|
DNLeaveCriticalSection(&g_csGlobalsLock);
|
|
|
|
|
|
//
|
|
// Get the right interface for the caller and bump the refcount.
|
|
//
|
|
hr = pDP8SimSP->QueryInterface(riid, ppvObj);
|
|
if (hr != S_OK)
|
|
{
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
//
|
|
// Release the local reference to the objec(s)t. If this function was
|
|
// successful, there's still a reference in ppvObj.
|
|
//
|
|
|
|
if (pDP8SimSP != NULL)
|
|
{
|
|
pDP8SimSP->Release();
|
|
pDP8SimSP = NULL;
|
|
}
|
|
|
|
if (pDP8SimControl != NULL)
|
|
{
|
|
pDP8SimControl->Release();
|
|
pDP8SimControl = NULL;
|
|
}
|
|
|
|
return hr;
|
|
|
|
|
|
Failure:
|
|
|
|
//
|
|
// Make sure we don't hand back a pointer.
|
|
//
|
|
(*ppvObj) = NULL;
|
|
|
|
goto Exit;
|
|
} // DoCreateInstance
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "IsClassImplemented"
|
|
//=============================================================================
|
|
// IsClassImplemented
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Determine if a class is implemented in this DLL. Required by
|
|
// the general purpose class factory functions.
|
|
//
|
|
// Arguments:
|
|
// REFCLSID rclsid - Reference to class GUID.
|
|
//
|
|
// Returns: BOOL
|
|
// TRUE - This DLL implements the class.
|
|
// FALSE - This DLL doesn't implement the class.
|
|
//=============================================================================
|
|
BOOL IsClassImplemented(REFCLSID rclsid)
|
|
{
|
|
DWORD dwSimulatedSP;
|
|
|
|
|
|
if (IsEqualCLSID(rclsid, CLSID_DP8SimControl))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Check if this is a valid simulated SP.
|
|
//
|
|
for(dwSimulatedSP = 0; dwSimulatedSP < NUM_SUPPORTED_SPS; dwSimulatedSP++)
|
|
{
|
|
if (IsEqualCLSID(rclsid, *(c_aSupportedSPs[dwSimulatedSP].pclsidFakeSP)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
} // IsClassImplemented
|