2025-11-28 00:35:46 +09:00

429 lines
11 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "stdafx.h"
// TODO - TODO - TODO -TODO - TODO - TODO - TODO - TODO - TODO - TODO
//
// CLSID_FDProvider must match the value defined in FDProvider.cpp
//
// TODO - TODO - TODO -TODO - TODO - TODO - TODO - TODO - TODO - TODO
const GUID CLSID_FDProvider = { 0x8c19066a, 0x643a, 0x4586, { 0x92, 0xb2, 0xa7, 0x85, 0xb9, 0xd, 0x76, 0x6f }};
class TClassFactory:
public IClassFactory
{
public:
// IUnknown
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface(
REFIID riid,
__deref_out void** ppv);
// IClassFactory
STDMETHODIMP CreateInstance(
__in_opt IUnknown* punkOuter,
REFIID iid,
__deref_out void** ppv);
STDMETHODIMP LockServer(
BOOL fLock);
// Constructor / Destuctor
TClassFactory();
HRESULT Init();
// Public functionality
HRESULT ProcessLogoffNotification(
DWORD SessionId);
protected:
~TClassFactory();
LONG m_cRef;
IClassFactory* m_pFDProviderClassFactory;
IEXEHostControl* m_pIEXEHostControl;
}; // TClassFactory
// Forward defines
VOID __stdcall ProviderLifetimeNotificationCallback(
bool fDestructed);
// Global variables
HANDLE g_hQuitEvent = NULL;
LONG g_cHostProcessRefCount = 0;
//---------------------------------------------------------------------------
// Begin TClassFactory implemetation
//---------------------------------------------------------------------------
TClassFactory::TClassFactory():
m_cRef(1),
m_pFDProviderClassFactory(NULL),
m_pIEXEHostControl(NULL)
{
} // TClassFactory::TClassFactory
TClassFactory::~TClassFactory()
{
if (m_pFDProviderClassFactory)
{
m_pFDProviderClassFactory->Release();
m_pFDProviderClassFactory = NULL;
}
if (m_pIEXEHostControl)
{
m_pIEXEHostControl->Release();
m_pIEXEHostControl = NULL;
}
} // TClassFactory::~TClassFactory
HRESULT TClassFactory::Init()
{
HRESULT hr = S_OK;
// Load the profider that will be hosted
// and get a pointer to it's class factory
hr = CoGetClassObject(
CLSID_FDProvider,
CLSCTX_INPROC_SERVER,
NULL,
IID_IClassFactory,
(void**) &m_pFDProviderClassFactory);
// Get a pointer to IEXEHostControl exposed by
// the provider's class factory
if (S_OK == hr)
{
hr = m_pFDProviderClassFactory->QueryInterface(
__uuidof(IEXEHostControl),
(void**) &m_pIEXEHostControl);
}
// Register our liftime notification callback with the provider
if (S_OK == hr)
{
hr = m_pIEXEHostControl->RegisterProviderLifetimeNotificationCallback(
&ProviderLifetimeNotificationCallback);
}
return hr;
} // TClassFactory::Init
STDMETHODIMP_(ULONG) TClassFactory::AddRef()
{
return InterlockedIncrement(&m_cRef);
} // TClassFactory::AddRef
STDMETHODIMP_(ULONG) TClassFactory::Release()
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
{
delete this;
}
return cRef;
} // TClassFactory::Release
STDMETHODIMP TClassFactory::QueryInterface(
REFIID riid,
__deref_out_opt void** ppv)
{
HRESULT hr = S_OK;
if (ppv)
{
*ppv = NULL;
}
else
{
hr = E_INVALIDARG;
}
if (S_OK == hr)
{
if (IID_IUnknown == riid)
{
AddRef();
*ppv = (IUnknown*) this;
}
else if (IID_IClassFactory == riid)
{
AddRef();
*ppv = (IClassFactory*) this;
}
else
{
hr = E_NOINTERFACE;
}
}
return hr;
} // TClassFactory::QueryInterface
STDMETHODIMP TClassFactory::CreateInstance(
__in_opt IUnknown* pUnkownOuter,
REFIID riid,
__deref_out_opt void** ppv)
{
return m_pFDProviderClassFactory->CreateInstance(
pUnkownOuter,
riid,
ppv);
} // TClassFactory::CreateInstance
STDMETHODIMP TClassFactory::LockServer(
BOOL fLock)
{
// External calls to LockServer are passed through to
// the ProviderLifetime manager callback
if (fLock)
{
ProviderLifetimeNotificationCallback(false);
}
else
{
ProviderLifetimeNotificationCallback(true);
}
return S_OK;
} // TClassFactory::LockServer
HRESULT TClassFactory::ProcessLogoffNotification(
DWORD SessionId)
{
return m_pIEXEHostControl->LogoffNotification(SessionId);
} // TClassFactory::ProcessLogoffNotification
//---------------------------------------------------------------------------
// End TClassFactory implemetation
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Begin global function implementation
//---------------------------------------------------------------------------
VOID __stdcall ProviderLifetimeNotificationCallback(
bool fDestructed)
{
if (!fDestructed)
{
InterlockedIncrement(&g_cHostProcessRefCount);
CoAddRefServerProcess();
}
else
{
InterlockedDecrement(&g_cHostProcessRefCount);
if (CoReleaseServerProcess() == 0)
{
// If there are no provider objects
// and no Lock on the class object, let the exe exit
SetEvent(g_hQuitEvent);
}
}
} // ProviderLifetimeNotificationCallback
int __stdcall WinMain(
__in HINSTANCE hInstance,
__in_opt HINSTANCE hPrevInstance,
__in_opt LPSTR lpCmdLine,
__in int nShowCmd)
{
HRESULT hr = S_OK;
TClassFactory* pClassFactory = NULL;
ULONG hClassRegistration = NULL;
HWND hMessageWindow = NULL;
bool fWTSRegistered = false;
bool fQuit = false;
DWORD WaitResult = 0;
MSG msg = {0};
hr = CoInitializeEx(
NULL,
COINIT_MULTITHREADED);
// Create and event that will be signaled
// when all COM objects have been released
// and the process should end.
if (S_OK == hr)
{
// Create a event that will be signaled when the Host should exit
if (S_OK == hr)
{
g_hQuitEvent = CreateEvent(
NULL,
TRUE,
FALSE,
NULL);
if (!g_hQuitEvent)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
// Create our class factory
if (S_OK == hr)
{
pClassFactory = new(std::nothrow) TClassFactory();
if (!pClassFactory)
{
hr = E_OUTOFMEMORY;
}
}
if (S_OK == hr)
{
hr = pClassFactory->Init();
}
// TODO - TODO - TODO -TODO - TODO - TODO - TODO - TODO - TODO - TODO
//
// If this EXE host is converted into a Windows Service,
// the message pump and WTSRegisterSessionNotification should be
// removed and HandlerEx with SERVICE_CONTROL_SESSIONCHANGE
// should be used instead.
//
// TODO - TODO - TODO -TODO - TODO - TODO - TODO - TODO - TODO - TODO
// Create a message only window to process
// session change events that will notify us when a logoff has occured.
if (S_OK == hr)
{
hMessageWindow = CreateWindow(
L"Message",
L"",
0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
HWND_MESSAGE, // Message only window
NULL,
hInstance,
NULL);
if (!hMessageWindow)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
// Register the window for session change events
if (S_OK == hr)
{
if (WTSRegisterSessionNotification(
hMessageWindow,
NOTIFY_FOR_ALL_SESSIONS))
{
fWTSRegistered = true;
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
// Register our class factory with COM remoting
if (S_OK == hr)
{
hr = CoRegisterClassObject(
CLSID_FDProvider,
(IClassFactory*) pClassFactory,
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&hClassRegistration);
}
// Start a message pump and wait for g_hQuitEvent to be signaled
if (S_OK == hr)
{
while (!fQuit)
{
WaitResult = MsgWaitForMultipleObjectsEx(
1,
&g_hQuitEvent,
INFINITE,
QS_ALLINPUT,
MWMO_INPUTAVAILABLE);
if (WAIT_OBJECT_0 == WaitResult)
{
// g_hQuitEvent has been signaled
fQuit = true;
}
else if (WAIT_OBJECT_0 + 1 == WaitResult)
{
// Window messages are avaialble, process them
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
{
// WM_QUIT message has been posted.
fQuit = true;
}
if (WM_WTSSESSION_CHANGE == msg.message)
{
if (WTS_SESSION_LOGOFF == msg.wParam)
{
// A logoff has occured.
hr = pClassFactory->ProcessLogoffNotification((DWORD) msg.lParam);
if (S_OK != hr)
{
// if the logoff can not be processed,
// exit the process.
fQuit = true;
}
}
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
else
{
// This is unexpected, exit the process.
fQuit = true;
}
}
}
// Cleanup
if (hClassRegistration)
{
CoRevokeClassObject(hClassRegistration);
}
if (pClassFactory)
{
pClassFactory->Release();
}
if (fWTSRegistered)
{
WTSUnRegisterSessionNotification(hMessageWindow);
}
if (hMessageWindow)
{
DestroyWindow(hMessageWindow);
}
if (g_hQuitEvent)
{
CloseHandle(g_hQuitEvent);
}
CoUninitialize();
}
return hr;
} // WinMain
//---------------------------------------------------------------------------
// End global function implementation
//---------------------------------------------------------------------------