|
|
// DevCon2.cpp : Implementation of DLL Exports.
// Note: Proxy/Stub Information
// To merge the proxy/stub code into the object DLL, add the file
// dlldatax.c to the project. Make sure precompiled headers
// are turned off for this file, and add _MERGE_PROXYSTUB to the
// defines for the project.
//
// If you are not running WinNT4.0 or Win95 with DCOM, then you
// need to remove the following define from dlldatax.c
// #define _WIN32_WINNT 0x0400
//
// Further, if you are running MIDL without /Oicf switch, you also
// need to remove the following define from dlldatax.c.
// #define USE_STUBLESS_PROXY
//
// Modify the custom build rule for DevCon2.idl by adding the following
// files to the Outputs.
// DevCon2_p.c
// dlldata.c
// To build a separate proxy/stub DLL,
// run nmake -f DevCon2ps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "DevCon2.h"
#include "dlldatax.h"
#include "DevCon2_i.c"
#include "DeviceConsole.h"
#include "Devices.h"
#include "xStrings.h"
#include "SetupClasses.h"
#include "DeviceIcon.h"
#ifdef _MERGE_PROXYSTUB
extern "C" HINSTANCE hProxyDll; #endif
CMyModule _Module;
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_DeviceConsole, CDeviceConsole) OBJECT_ENTRY(CLSID_Devices, CDevices) OBJECT_ENTRY(CLSID_Strings, CStrings) OBJECT_ENTRY(CLSID_SetupClasses, CSetupClasses) OBJECT_ENTRY(CLSID_DeviceIcon, CDeviceIcon) END_OBJECT_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { lpReserved; #ifdef _MERGE_PROXYSTUB
if (!PrxDllMain(hInstance, dwReason, lpReserved)) return FALSE; #endif
if (dwReason == DLL_PROCESS_ATTACH) { _Module.Init(ObjectMap, hInstance, &LIBID_DEVCON2Lib); DisableThreadLibraryCalls(hInstance); } else if (dwReason == DLL_PROCESS_DETACH) _Module.Term(); return TRUE; // ok
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void) { #ifdef _MERGE_PROXYSTUB
if (PrxDllCanUnloadNow() != S_OK) return S_FALSE; #endif
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE; }
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { #ifdef _MERGE_PROXYSTUB
if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK) return S_OK; #endif
return _Module.GetClassObject(rclsid, riid, ppv); }
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void) { #ifdef _MERGE_PROXYSTUB
HRESULT hRes = PrxDllRegisterServer(); if (FAILED(hRes)) return hRes; #endif
//
// DCOM support - App registration via IDR_DEVCON2
//
_Module.UpdateRegistryFromResource(IDR_DEVCON2, TRUE); // registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE); }
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void) { #ifdef _MERGE_PROXYSTUB
PrxDllUnregisterServer(); #endif
//
// DCOM support - App cleanup via IDR_DEVCON2
//
_Module.UpdateRegistryFromResource(IDR_DEVCON2, FALSE); return _Module.UnregisterServer(TRUE); }
//
// DCOM support, allow this DLL to also run as local server
// once the server is running, it needs to cleanup after a short period of time
//
const DWORD dwTimeOut = 5000; // time for server to be idle before shutting down
static void CALLBACK ModuleTimer(HWND /*hWnd*/,UINT /*uMsg*/,UINT_PTR /*idEvent*/,DWORD /*dwTime*/) { _Module.CheckShutdown(); }
LONG CMyModule::Unlock() { LONG l = CComModule::Unlock(); //ATLTRACE("Unlock = %u\n",l);
if (bServer && (l <= (punkFact ? 1 : 0))) { //
// DCOM server
// as soon as lock count reaches 1 (punkFact), timer is reset
// if timer times out and lock count is still 1
// then we can kill the server
//
SetTimer(NULL,0,dwTimeOut,ModuleTimer); } return l; }
void CMyModule::KillServer() { if(bServer) { //
// make it a server no longer
//
CoRevokeClassObject(dwROC); bServer = FALSE; } if(punkFact) { punkFact->Release(); punkFact = NULL; } if(m_nLockCnt != 0) { DebugBreak(); } }
void CMyModule::CheckShutdown() { if(m_nLockCnt>(punkFact ? 1 : 0)) { //
// module is still in use
//
return; } //
// lock count stayed at zero for dwTimeOut ms
//
KillServer(); PostMessage(NULL, WM_QUIT, 0, 0); }
HRESULT CMyModule::InitServer(GUID & ClsId) { HRESULT hr;
hr = DllGetClassObject(ClsId, IID_IClassFactory, (LPVOID*)&punkFact); if(FAILED(hr)) { return hr; } hr = CoRegisterClassObject(ClsId, punkFact, CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &dwROC); if(FAILED(hr)) { punkFact->Release(); punkFact = NULL; return hr; } bServer = true;
return S_OK; }
void WINAPI CreateLocalServerW(HWND /*hwnd*/, HINSTANCE /*hAppInstance*/, LPWSTR pszCmdLine, int /*nCmdShow*/) { GUID ClsId; HRESULT hr; LPWSTR dup; LPWSTR p; size_t len; MSG msg;
hr = CoInitialize(NULL); if(FAILED(hr)) { return; }
//
// pszCmdLine = the class GUID we want factory for
//
p = wcschr(pszCmdLine,'{'); if(!p) { goto final; } pszCmdLine = p; p = wcschr(pszCmdLine,'}'); if(!p) { goto final; } len = p-pszCmdLine+1; dup = new WCHAR[len+1]; if(!dup) { goto final; } wcsncpy(dup,pszCmdLine,len+1); dup[len] = '\0'; hr = CLSIDFromString(dup,&ClsId); delete [] dup;
if(FAILED(hr)) { goto final; } hr = _Module.InitServer(ClsId); if(FAILED(hr)) { goto final; }
//
// now go into dispatch loop until we get a quit message
//
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } _Module.KillServer();
final: CoUninitialize(); }
#ifdef _M_IA64
//$WIN64: Don't know why _WndProcThunkProc isn't defined
extern "C" LRESULT CALLBACK _WndProcThunkProc(HWND, UINT, WPARAM, LPARAM ) { return 0; }
#endif
|