|
|
////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2000, Microsoft Corporation.
//
// All rights reserved.
//
// Module Name:
//
// WMIAdapter.cpp
//
// Abstract:
//
// implements functionality ( decides what to do :)) )
//
// History:
//
// initial a-marius
//
////////////////////////////////////////////////////////////////////////////////////
// resorces
#include "PreComp.h"
// guids
#include <initguid.h>
// debuging features
#ifndef _INC_CRTDBG
#include <crtdbg.h>
#endif _INC_CRTDBG
// new stores file/line info
#ifdef _DEBUG
#ifndef NEW
#define NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
#define new NEW
#endif NEW
#endif _DEBUG
// messages ( event log )
#include "WmiAdapterMessages.h"
#include ".\WMIAdapter\resource.h"
// declarations
#include "WMIAdapter_Service.h"
#include "WMIAdapter_App.h"
// registration
#include "Wmi_Adapter_Registry_Service.h"
// enum
#include <refreshergenerate.h>
/////////////////////////////////////////////////////////////////////////////
// VARIABLES
/////////////////////////////////////////////////////////////////////////////
// app
WmiAdapterApp _App;
// service module
WmiAdapterService _Service;
////////////////////////////////////////////////////////////////////////////
// ATL stuff
////////////////////////////////////////////////////////////////////////////
// need atl wrappers
#ifndef __ATLBASE_H__
#include <atlbase.h>
#endif __ATLBASE_H__
// need registry
#ifdef _ATL_STATIC_REGISTRY
#include <statreg.h>
#include <statreg.cpp>
#endif
#include <atlimpl.cpp>
/////////////////////////////////////////////////////////////////////////////
//
// Helpers
//
/////////////////////////////////////////////////////////////////////////////
CStaticCritSec g_cs; // synch object used to protect above globals
LONG g_lRef = 0; // count of threads attached into Run Function
__SmartHANDLE g_hDoneWorkEvt = NULL; // event to set when init/uninit is finished done ( nonsignaled )
BOOL g_bWorking = FALSE; // boolean used to tell if init/unit in progress
//Performs Initialization if necessary, waits until initialization is done if necessary.
HRESULT DoInit() { HRESULT hRes = E_FAIL;
BOOL bWait = TRUE; BOOL bDoWork = FALSE;
while (bWait) { try { ::EnterCriticalSection ( &g_cs ); } catch ( ... ) { return E_OUTOFMEMORY; }
if ( g_lRef == 0 ) { bDoWork = TRUE; g_lRef++; g_bWorking = TRUE; ::ResetEvent(g_hDoneWorkEvt); bWait = FALSE; } else { if ( g_bWorking ) { ::LeaveCriticalSection ( &g_cs ); if ( WAIT_OBJECT_0 != ::WaitForSingleObject( g_hDoneWorkEvt, INFINITE ) ) { return hRes; } } else { bWait = FALSE; g_lRef++; hRes = S_OK; } } }
::LeaveCriticalSection( &g_cs );
if (bDoWork) { if SUCCEEDED ( hRes = _App.InitKill ( ) ) { try { if SUCCEEDED ( hRes = ::CoInitializeSecurity( ( ( WmiSecurityAttributes* ) _App )->GetAbsoluteSecurityDescriptor(), -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_DYNAMIC_CLOAKING | EOAC_SECURE_REFS, NULL ) ) { try { ////////////////////////////////////////////////////////////////////////
// LOCATOR ( neccessary )
////////////////////////////////////////////////////////////////////////
if ( ! ( (WmiAdapterStuff*) _App )->m_Stuff.m_spLocator ) { hRes = ::CoCreateInstance ( __uuidof ( WbemLocator ), NULL, CLSCTX_INPROC_SERVER, __uuidof ( IWbemLocator ), (void**) & ( ( (WmiAdapterStuff*) _App )->m_Stuff.m_spLocator ) ); } } catch ( ... ) { hRes = E_UNEXPECTED; } } } catch ( ... ) { hRes = E_UNEXPECTED; } } try { ::EnterCriticalSection ( &g_cs ); } catch (...) { // no choice have to give others a chance!
::InterlockedDecrement ( &g_lRef );
g_bWorking = FALSE; ::SetEvent(g_hDoneWorkEvt);
return E_OUTOFMEMORY; }
if (FAILED(hRes)) { g_lRef--; }
g_bWorking = FALSE; ::SetEvent(g_hDoneWorkEvt); ::LeaveCriticalSection ( &g_cs ); }
return hRes; } //Performs unitialization ONLY if necessary. While unitializing sets global g_bWorking to TRUE.
void DoUninit() { BOOL bDoWork = FALSE;
try { ::EnterCriticalSection ( &g_cs ); } catch ( ... ) { return; }
if ( g_lRef == 1 ) { bDoWork = TRUE; g_bWorking = TRUE; ::ResetEvent(g_hDoneWorkEvt); } else { g_lRef--; }
::LeaveCriticalSection( &g_cs );
if (bDoWork) { try { if ( _App.m_hKill.GetHANDLE() ) { ::SetEvent ( _App.m_hKill ); }
// is refresh of registry already done ?
if ( ((WmiAdapterStuff*)_App)->RequestGet() ) { ((WmiAdapterStuff*)_App)->Generate ( FALSE ); }
////////////////////////////////////////////////////////////////////////
// LOCATOR
////////////////////////////////////////////////////////////////////////
try { ( ( WmiAdapterStuff* ) _App )->m_Stuff.m_spLocator.Release(); } catch ( ... ) { } } catch (...) { }
try { ::EnterCriticalSection ( &g_cs ); } catch ( ... ) { //gotta give others a chance to work, risk it!
::InterlockedDecrement ( &g_lRef );
g_bWorking = FALSE; ::SetEvent( g_hDoneWorkEvt ); return; }
g_lRef--; g_bWorking = FALSE; ::SetEvent( g_hDoneWorkEvt ); ::LeaveCriticalSection ( &g_cs ); } }
/////////////////////////////////////////////////////////////////////////////
//
// WIN MAIN
//
/////////////////////////////////////////////////////////////////////////////
extern "C" int WINAPI WinRun ( );
extern "C" int WINAPI _tWinMain ( HINSTANCE hInstance, HINSTANCE, LPTSTR, int ) { return WinMain ( hInstance, NULL, GetCommandLineA(), SW_SHOW ); }
extern "C" int WINAPI WinMain ( HINSTANCE, HINSTANCE, LPSTR, int ) { if ( CStaticCritSec::anyFailure () ) { //
// some critical section was not
// initialized properly due to low memory
//
return ERROR_NOT_ENOUGH_MEMORY ; }
HRESULT nRet = S_FALSE;
////////////////////////////////////////////////////////////////////////
// initialization
////////////////////////////////////////////////////////////////////////
if SUCCEEDED ( nRet = _App.InitAttributes ( ) ) { ////////////////////////////////////////////////////////////////////////
// variables
////////////////////////////////////////////////////////////////////////
WCHAR szTokens[] = L"-/";
////////////////////////////////////////////////////////////
// initialization
////////////////////////////////////////////////////////////
if SUCCEEDED ( nRet = _App.Init ( ) ) { ////////////////////////////////////////////////////////////////////////
// command line
////////////////////////////////////////////////////////////////////////
LPWSTR lpCmdLine = GetCommandLineW();
////////////////////////////////////////////////////////////////////////
// find behaviour
////////////////////////////////////////////////////////////////////////
LPCWSTR lpszToken = WmiAdapterApp::FindOneOf(lpCmdLine, szTokens); BOOL bContinue = TRUE; try { while (lpszToken != NULL && bContinue) { if (lstrcmpiW(lpszToken, L"UnregServer")==0) { ////////////////////////////////////////////////////////////////
// unregister service
////////////////////////////////////////////////////////////////
if SUCCEEDED ( nRet = _Service.UnregisterService ( ) ) { ((WmiAdapterStuff*)_App)->Generate( FALSE, UnRegistration );
////////////////////////////////////////////////////////////
// unregister registry
////////////////////////////////////////////////////////////
WmiAdapterRegistryService::__UpdateRegistrySZ( false ); }
bContinue = FALSE; } else { if (lstrcmpiW(lpszToken, L"RegServer")==0) { ////////////////////////////////////////////////////////////
// register service
////////////////////////////////////////////////////////////
if SUCCEEDED ( nRet = _Service.RegisterService ( ) ) { ////////////////////////////////////////////////////////
// create registry again
////////////////////////////////////////////////////////
WmiAdapterRegistryService::__UpdateRegistrySZ( true );
((WmiAdapterStuff*)_App)->Generate( FALSE, Registration ); }
bContinue = FALSE; } }
lpszToken = WmiAdapterApp::FindOneOf(lpszToken, szTokens); }
if ( bContinue ) { ////////////////////////////////////////////////////////////////
// previous instance
////////////////////////////////////////////////////////////////
if ( ! _App.Exists() ) { ////////////////////////////////////////////////////////
// initialization
////////////////////////////////////////////////////////
_Service.Init ( );
__SmartServiceHANDLE pSCM; if ( ( pSCM = OpenSCManager ( NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
) ) != NULL ) { __SmartServiceHANDLE pService; if ( ( pService = OpenServiceW ( pSCM, g_szAppName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG ) ) != NULL ) { LPQUERY_SERVICE_CONFIG lpQSC = NULL; DWORD dwQSC = 0L;
try { if ( ! QueryServiceConfig ( pService, lpQSC, 0, &dwQSC ) ) { if ( ERROR_INSUFFICIENT_BUFFER == ::GetLastError () ) { if ( ( lpQSC = (LPQUERY_SERVICE_CONFIG) LocalAlloc( LPTR, dwQSC ) ) != NULL ) { if ( QueryServiceConfig ( pService, lpQSC, dwQSC, &dwQSC ) != 0 ) { _App.m_bManual = ( lpQSC->dwStartType == SERVICE_DEMAND_START ); } } } } } catch ( ... ) { }
LocalFree ( lpQSC );
SERVICE_STATUS s; QueryServiceStatus ( pService, &s );
// we are service, not running ???
if( s.dwCurrentState != SERVICE_RUNNING ) { if ( ! _Service.StartService () ) { DWORD dwError = ERROR_SUCCESS; dwError = ::GetLastError();
if FAILED ( HRESULT_FROM_WIN32 ( dwError ) ) { nRet = HRESULT_FROM_WIN32 ( dwError ); } else { nRet = HRESULT_FROM_WIN32 ( ERROR_NOT_READY ); } } } else { DWORD dwError = ERROR_SUCCESS; dwError = ::GetLastError();
if FAILED ( HRESULT_FROM_WIN32 ( dwError ) ) { nRet = HRESULT_FROM_WIN32 ( dwError ); } else { nRet = HRESULT_FROM_WIN32 ( ERROR_ALREADY_EXISTS ); } } } else { DWORD dwError = ERROR_SUCCESS; dwError = ::GetLastError();
if FAILED ( HRESULT_FROM_WIN32 ( dwError ) ) { nRet = HRESULT_FROM_WIN32 ( dwError ); } else { nRet = E_FAIL; } } } else { DWORD dwError = ERROR_SUCCESS; dwError = ::GetLastError();
if FAILED ( HRESULT_FROM_WIN32 ( dwError ) ) { nRet = HRESULT_FROM_WIN32 ( dwError ); } else { nRet = E_FAIL; } } } else { ////////////////////////////////////////////////////////////
// termination
////////////////////////////////////////////////////////////
nRet = HRESULT_FROM_WIN32 ( ERROR_ALREADY_EXISTS ); } } } catch ( ... ) { // catastrophic failure
nRet = E_FAIL; }
// return
if SUCCEEDED ( nRet ) { nRet = _Service.GetServiceStatus()->dwWin32ExitCode; }
_App.Term (); } }
return nRet; }
///////////////////////////////////////////////////////////////////////////////
//
// RUN :))
//
///////////////////////////////////////////////////////////////////////////////
extern "C" int WINAPI WinRun( ) { ///////////////////////////////////////////////////////////////////////////
// INITIALIZATION
///////////////////////////////////////////////////////////////////////////
LONG lRes = ERROR_SUCCESS; HRESULT hRes = E_FAIL;
///////////////////////////////////////////////////////////////////////////
// COM INITIALIZATION
///////////////////////////////////////////////////////////////////////////
if SUCCEEDED ( hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED) ) { // mark service is running IMMEDIATELY
_Service.SetServiceStatus ( SERVICE_RUNNING );
if SUCCEEDED ( hRes = DoInit() ) { try { if ( ( lRes = _Service.Work () ) != S_OK ) { if ( _App.m_hKill.GetHANDLE() ) { ::SetEvent ( _App.m_hKill ); } }
::WaitForSingleObject ( _App.m_hKill, INFINITE ); } catch ( ... ) { lRes = E_UNEXPECTED; }
///////////////////////////////////////////////////////////////////
// do real finishing stuff ( synchronize etc )
///////////////////////////////////////////////////////////////////
DoUninit(); }
///////////////////////////////////////////////////////////////////////
// COM UNINITIALIZATION
///////////////////////////////////////////////////////////////////////
::CoUninitialize(); }
if FAILED ( hRes ) { // something was wrong in helpers
return hRes; } else { // result from real work
return ( lRes == S_FALSE ) ? S_OK : lRes; } }
|