862 lines
21 KiB
C++
862 lines
21 KiB
C++
/***************************************************************************
|
|
*
|
|
* Copyright (C) 2001 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
|
|
|
|
DWORD g_dwHoldRand; // current random number sequence
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// Defines
|
|
//=============================================================================
|
|
#define MAX_RESOURCE_STRING_LENGTH _MAX_PATH
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// 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)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
|
|
|
|
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())
|
|
{
|
|
if (SUCCEEDED(COM_Init()))
|
|
{
|
|
//
|
|
// Attempt to initialize process-global items.
|
|
//
|
|
if (! InitializeProcessGlobals())
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize globals!");
|
|
|
|
COM_Free();
|
|
DNOSIndirectionDeinit();
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize COM indirection layer!" );
|
|
fResult = FALSE;
|
|
|
|
DNOSIndirectionDeinit();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to initialize OS indirection layer!");
|
|
fResult = FALSE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
{
|
|
//
|
|
// Ignore.
|
|
//
|
|
break;
|
|
}
|
|
|
|
case DLL_THREAD_DETACH:
|
|
{
|
|
//
|
|
// Ignore.
|
|
//
|
|
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();
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return fResult;
|
|
} // DllMain
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DllRegisterServer"
|
|
//=============================================================================
|
|
// DllRegisterServer
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Registers the DP8Sim COM object.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: HRESULT
|
|
// S_OK - Successfully unregistered DP8Sim.
|
|
// E_FAIL - Failed unregistering DP8Sim.
|
|
//=============================================================================
|
|
HRESULT WINAPI DllRegisterServer(void)
|
|
{
|
|
CRegistry RegObject;
|
|
|
|
|
|
//
|
|
// Register the control COM object CLSID.
|
|
//
|
|
if (! RegObject.Register(L"DP8SimControl.1",
|
|
L"DirectPlay8 Network Simulator Control Object",
|
|
L"dp8sim.dll",
|
|
CLSID_DP8SimControl,
|
|
L"DP8SimControl"))
|
|
{
|
|
DPFX(DPFPREP, 0, "Could not register DP8SimControl object!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
return S_OK;
|
|
} // 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)
|
|
{
|
|
CRegistry RegObject;
|
|
|
|
|
|
//
|
|
// Unregister the control class.
|
|
//
|
|
if (! RegObject.UnRegister(CLSID_DP8SimControl))
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to unregister DP8Sim control object!");
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
} // 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 completely off of the C run-time source.
|
|
//
|
|
// 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_dwHoldRand = dwSeed;
|
|
} // InitializeGlobalRand
|
|
|
|
|
|
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "GetGlobalRand"
|
|
//=============================================================================
|
|
// GetGlobalRand
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Description: Generates a pseudo-random number, 0 through 32767.
|
|
//
|
|
// Based completely off of the C run-time source.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: Pseudo-random number.
|
|
//=============================================================================
|
|
WORD GetGlobalRand(void)
|
|
{
|
|
WORD wResult;
|
|
|
|
|
|
DNEnterCriticalSection(&g_csGlobalsLock);
|
|
|
|
//
|
|
// This version wasn't generating a sequence to my liking:
|
|
//
|
|
// With % to drop set to 01, % kept = 96, % dropped = 3
|
|
// With % to drop set to 02, % kept = 94, % dropped = 5
|
|
// With % to drop set to 03, % kept = 94, % dropped = 5
|
|
// With % to drop set to 04, % kept = 94, % dropped = 5
|
|
// With % to drop set to 05, % kept = 93, % dropped = 6
|
|
// With % to drop set to 06, % kept = 93, % dropped = 6
|
|
// With % to drop set to 07, % kept = 92, % dropped = 7
|
|
// With % to drop set to 08, % kept = 91, % dropped = 8
|
|
// With % to drop set to 09, % kept = 90, % dropped = 9
|
|
// With % to drop set to 10, % kept = 87, % dropped = 12
|
|
// With % to drop set to 11, % kept = 85, % dropped = 14
|
|
// With % to drop set to 12, % kept = 85, % dropped = 14
|
|
// With % to drop set to 13, % kept = 85, % dropped = 14
|
|
// With % to drop set to 14, % kept = 85, % dropped = 14
|
|
// With % to drop set to 15, % kept = 85, % dropped = 14
|
|
// With % to drop set to 16, % kept = 85, % dropped = 14
|
|
// With % to drop set to 17, % kept = 85, % dropped = 14
|
|
// With % to drop set to 18, % kept = 82, % dropped = 17
|
|
// With % to drop set to 19, % kept = 82, % dropped = 17
|
|
// With % to drop set to 20, % kept = 80, % dropped = 19
|
|
//
|
|
//g_dwHoldRand = ((g_dwHoldRand * 214013L + 2531011L) >> 16) & 0x7fff;
|
|
//wResult = (WORD) g_dwHoldRand;
|
|
|
|
|
|
//
|
|
// So I use this one instead:
|
|
//
|
|
// With % to drop set to 01, % kept = 99, % dropped = 00
|
|
// With % to drop set to 02, % kept = 98, % dropped = 01
|
|
// With % to drop set to 03, % kept = 97, % dropped = 02
|
|
// With % to drop set to 04, % kept = 96, % dropped = 03
|
|
// With % to drop set to 05, % kept = 95, % dropped = 04
|
|
// With % to drop set to 06, % kept = 94, % dropped = 05
|
|
// With % to drop set to 07, % kept = 92, % dropped = 07
|
|
// With % to drop set to 08, % kept = 90, % dropped = 09
|
|
// With % to drop set to 09, % kept = 87, % dropped = 12
|
|
// With % to drop set to 10, % kept = 87, % dropped = 12
|
|
// With % to drop set to 11, % kept = 86, % dropped = 13
|
|
// With % to drop set to 12, % kept = 85, % dropped = 14
|
|
// With % to drop set to 13, % kept = 84, % dropped = 15
|
|
// With % to drop set to 14, % kept = 84, % dropped = 15
|
|
// With % to drop set to 15, % kept = 84, % dropped = 15
|
|
// With % to drop set to 16, % kept = 84, % dropped = 15
|
|
// With % to drop set to 17, % kept = 83, % dropped = 16
|
|
// With % to drop set to 18, % kept = 82, % dropped = 17
|
|
// With % to drop set to 19, % kept = 81, % dropped = 18
|
|
// With % to drop set to 20, % kept = 80, % dropped = 19
|
|
//
|
|
g_dwHoldRand = ((g_dwHoldRand * 1103515245L + 12345L) >> 16) & 0x7fff;
|
|
wResult = (WORD) g_dwHoldRand;
|
|
|
|
|
|
DNLeaveCriticalSection(&g_csGlobalsLock);
|
|
|
|
return wResult;
|
|
} // 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;
|
|
|
|
|
|
DNASSERT(ppvObj != NULL);
|
|
|
|
|
|
if (! IsEqualCLSID(rclsid, CLSID_DP8SimControl))
|
|
{
|
|
//
|
|
// We play COM registration games, so we could get called with pretty
|
|
// much any service provider's CLSID.
|
|
//
|
|
|
|
if ((! IsEqualCLSID(rclsid, CLSID_DP8SP_TCPIP)) &&
|
|
(! IsEqualCLSID(rclsid, CLSID_DP8SP_IPX)) &&
|
|
(! IsEqualCLSID(rclsid, CLSID_DP8SP_MODEM)) &&
|
|
(! IsEqualCLSID(rclsid, CLSID_DP8SP_SERIAL)))
|
|
{
|
|
/*
|
|
//
|
|
// Return an error.
|
|
//
|
|
hr = E_UNEXPECTED;
|
|
goto Failure;
|
|
*/
|
|
|
|
//
|
|
// Print a warning.
|
|
//
|
|
DPFX(DPFPREP, 0, "Unrecognized service provider class ID, continuing...");
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// 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
|
|
{
|
|
//
|
|
// Create the object instance.
|
|
//
|
|
pDP8SimSP = new CDP8SimSP(&rclsid);
|
|
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)
|
|
{
|
|
if (IsEqualCLSID(rclsid, CLSID_DP8SimControl))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// We play COM registration games, so we could get called with pretty
|
|
// much any service provider's CLSID.
|
|
//
|
|
|
|
if ((IsEqualCLSID(rclsid, CLSID_DP8SP_TCPIP)) ||
|
|
(IsEqualCLSID(rclsid, CLSID_DP8SP_IPX)) ||
|
|
(IsEqualCLSID(rclsid, CLSID_DP8SP_MODEM)) ||
|
|
(IsEqualCLSID(rclsid, CLSID_DP8SP_SERIAL)))
|
|
{
|
|
//
|
|
// One of the usual DPlay8 SPs.
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DPFX(DPFPREP, 1, "Got unexpected service provider CLSID, pretending to implement.");
|
|
|
|
return TRUE;
|
|
} // IsClassImplemented
|