Leaked source code of windows server 2003
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.

850 lines
24 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. OLESRVR.CPP
  5. Abstract:
  6. "Main" file for wbemcore.dll: implements all DLL entry points.
  7. Classes defined and implemeted:
  8. CWbemLocator
  9. History:
  10. raymcc 16-Jul-96 Created.
  11. raymcc 05-May-97 Security extensions
  12. --*/
  13. #include "precomp.h"
  14. #include <stdio.h>
  15. #include <time.h>
  16. #include <initguid.h>
  17. #include <wbemcore.h>
  18. #include <intprov.h>
  19. #include <genutils.h>
  20. #include <wbemint.h>
  21. #include <windows.h>
  22. #include <helper.h>
  23. // {A83EF168-CA8D-11d2-B33D-00104BCC4B4A}
  24. DEFINE_GUID(CLSID_IntProv,
  25. 0xa83ef168, 0xca8d, 0x11d2, 0xb3, 0x3d, 0x0, 0x10, 0x4b, 0xcc, 0x4b, 0x4a);
  26. LPTSTR g_pWorkDir = 0;
  27. LPTSTR g_pDbDir = 0;
  28. LPTSTR g_pAutorecoverDir = 0;
  29. DWORD g_dwQueueSize = 1;
  30. HINSTANCE g_hInstance;
  31. BOOL g_bDontAllowNewConnections = FALSE;
  32. IWbemEventSubsystem_m4* g_pEss_m4 = NULL;
  33. bool g_bDefaultMofLoadingNeeded = false;
  34. IClassFactory* g_pContextFac = NULL;
  35. IClassFactory* g_pPathFac = NULL;
  36. IClassFactory* g_pQueryFact = NULL;
  37. BOOL g_ShutdownCalled = FALSE;
  38. extern "C" HRESULT APIENTRY Shutdown(BOOL bProcessShutdown, BOOL bIsSystemShutdown);
  39. extern "C" HRESULT APIENTRY Reinitialize(DWORD dwReserved);
  40. BOOL IsWhistlerPersonal ( ) ;
  41. BOOL IsWhistlerProfessional ( ) ;
  42. void UpdateArbitratorValues ( ) ;
  43. //***************************************************************************
  44. //
  45. // DllMain
  46. //
  47. // Dll entry point function. Called when wbemcore.dll is loaded into memory.
  48. // Performs basic system initialization on startup and system shutdown on
  49. // unload. See ConfigMgr::InitSystem and ConfigMgr::Shutdown in cfgmgr.h for
  50. // more details.
  51. //
  52. // PARAMETERS:
  53. //
  54. // HINSTANCE hinstDLL The handle to our DLL.
  55. // DWORD dwReason DLL_PROCESS_ATTACH on load,
  56. // DLL_PROCESS_DETACH on shutdown,
  57. // DLL_THREAD_ATTACH/DLL_THREAD_DETACH otherwise.
  58. // LPVOID lpReserved Reserved
  59. //
  60. // RETURN VALUES:
  61. //
  62. // TRUE is successful, FALSE if a fatal error occured.
  63. // NT behaves very ugly if FALSE is returned.
  64. //
  65. //***************************************************************************
  66. BOOL WINAPI DllMain(
  67. HINSTANCE hinstDLL,
  68. DWORD dwReason,
  69. LPVOID lpReserved
  70. )
  71. {
  72. if (dwReason == DLL_PROCESS_ATTACH)
  73. {
  74. g_hInstance = hinstDLL;
  75. if (CStaticCritSec::anyFailure()) return FALSE;
  76. }
  77. else if (dwReason == DLL_PROCESS_DETACH)
  78. {
  79. DEBUGTRACE((LOG_WBEMCORE, "wbemcore!DllMain(DLL_PROCESS_DETACH)\n"));
  80. #ifdef DBG
  81. if (!RtlDllShutdownInProgress())
  82. {
  83. if (!gClientCounter.OkToUnload()) DebugBreak();
  84. }
  85. #endif /*DBG*/
  86. }
  87. else if ( dwReason == DLL_THREAD_ATTACH )
  88. {
  89. TlsSetValue(CCoreQueue::GetSecFlagTlsIndex(),(LPVOID)1);
  90. }
  91. return TRUE;
  92. }
  93. //***************************************************************************
  94. //
  95. // class CFactory
  96. //
  97. // Generic implementation of IClassFactory for CWbemLocator.
  98. //
  99. // See Brockschmidt for details of IClassFactory interface.
  100. //
  101. //***************************************************************************
  102. enum InitType {ENSURE_INIT, ENSURE_INIT_WAIT_FOR_CLIENT, OBJECT_HANDLES_OWN_INIT};
  103. template<class TObj>
  104. class CFactory : public IClassFactory
  105. {
  106. public:
  107. CFactory(BOOL bUser, InitType it);
  108. ~CFactory();
  109. //
  110. // IUnknown members
  111. //
  112. STDMETHODIMP QueryInterface(REFIID, LPVOID *);
  113. STDMETHODIMP_(ULONG) AddRef(void);
  114. STDMETHODIMP_(ULONG) Release(void);
  115. //
  116. // IClassFactory members
  117. //
  118. STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID *);
  119. STDMETHODIMP LockServer(BOOL);
  120. private:
  121. ULONG m_cRef;
  122. InitType m_it;
  123. BOOL m_bUser;
  124. LIST_ENTRY m_Entry;
  125. };
  126. /////////////////////////////////////////////////////////////////////////////
  127. //
  128. // Count number of objects and number of locks on this DLL.
  129. //
  130. ULONG g_cObj = 0;
  131. ULONG g_cLock = 0;
  132. long g_lInitCount = -1; // 0 DURING INTIALIZATION, 1 OR MORE LATER ON!
  133. static CWbemCriticalSection g_csInit;
  134. bool g_bPreviousFail = false;
  135. HRESULT g_hrLastEnsuredInitializeError = WBEM_S_NO_ERROR;
  136. HRESULT EnsureInitialized()
  137. {
  138. if(g_bPreviousFail)
  139. return g_hrLastEnsuredInitializeError;
  140. g_csInit.Enter();
  141. OnDeleteObjIf0<CWbemCriticalSection,
  142. void (CWbemCriticalSection::*)(void),
  143. &CWbemCriticalSection::Leave> LeaveMe(&g_csInit);
  144. // If we have been shut down by WinMgmt, bail out.
  145. if(g_bDontAllowNewConnections)
  146. {
  147. return CO_E_SERVER_STOPPING;
  148. }
  149. //Check again! Previous connection could have been holding us off, and
  150. //may have failed!
  151. if(g_bPreviousFail)
  152. return g_hrLastEnsuredInitializeError;
  153. HRESULT hres;
  154. if(InterlockedIncrement(&g_lInitCount) == 0)
  155. {
  156. // Init Systems
  157. hres = ConfigMgr::InitSystem();
  158. if(FAILED(hres))
  159. {
  160. g_bPreviousFail = true;
  161. g_hrLastEnsuredInitializeError = hres;
  162. ConfigMgr::FatalInitializationError(hres);
  163. return hres;
  164. }
  165. LeaveMe.dismiss();
  166. g_csInit.Leave();
  167. // Get WINMGMT to run
  168. hres = ConfigMgr::SetReady();
  169. if(FAILED(hres))
  170. {
  171. g_bPreviousFail = true;
  172. g_hrLastEnsuredInitializeError = hres;
  173. ConfigMgr::FatalInitializationError(hres);
  174. return hres;
  175. }
  176. // if here, everything is OK
  177. g_bPreviousFail = false;
  178. g_hrLastEnsuredInitializeError = WBEM_S_NO_ERROR;
  179. InterlockedIncrement(&g_lInitCount);
  180. }
  181. else
  182. {
  183. InterlockedDecrement(&g_lInitCount);
  184. }
  185. return S_OK;
  186. }
  187. //***************************************************************************
  188. //
  189. // DllGetClassObject
  190. //
  191. // Standard OLE In-Process Server entry point to return an class factory
  192. // instance. Before returning a class factory, this function performs an
  193. // additional round of initialization --- see ConfigMgr::SetReady in cfgmgr.h
  194. //
  195. // PARAMETERS:
  196. //
  197. // IN RECLSID rclsid The CLSID of the object whose class factory is
  198. // required.
  199. // IN REFIID riid The interface required from the class factory.
  200. // OUT LPVOID* ppv Destination for the class factory.
  201. //
  202. // RETURNS:
  203. //
  204. // S_OK Success
  205. // E_NOINTERFACE An interface other that IClassFactory was asked for
  206. // E_OUTOFMEMORY
  207. // E_FAILED Initialization failed, or an unsupported clsid was
  208. // asked for.
  209. //
  210. //***************************************************************************
  211. extern "C"
  212. HRESULT APIENTRY DllGetClassObject(
  213. REFCLSID rclsid,
  214. REFIID riid,
  215. LPVOID * ppv
  216. )
  217. {
  218. HRESULT hr;
  219. //
  220. // Check that we can provide the interface.
  221. //
  222. if (IID_IUnknown != riid && IID_IClassFactory != riid)
  223. return ResultFromScode(E_NOINTERFACE);
  224. IClassFactory *pFactory;
  225. //
  226. // Verify the caller is asking for our type of object.
  227. //
  228. if (CLSID_InProcWbemLevel1Login == rclsid)
  229. {
  230. pFactory = new CFactory<CWbemLevel1Login>(TRUE, OBJECT_HANDLES_OWN_INIT);
  231. }
  232. else if(CLSID_ActualWbemAdministrativeLocator == rclsid)
  233. {
  234. pFactory = new CFactory<CWbemAdministrativeLocator>(FALSE, OBJECT_HANDLES_OWN_INIT);
  235. }
  236. else if(CLSID_ActualWbemAuthenticatedLocator == rclsid)
  237. {
  238. pFactory = new CFactory<CWbemAuthenticatedLocator>(TRUE, OBJECT_HANDLES_OWN_INIT);
  239. }
  240. else if(CLSID_ActualWbemUnauthenticatedLocator == rclsid)
  241. {
  242. pFactory = new CFactory<CWbemUnauthenticatedLocator>(TRUE, OBJECT_HANDLES_OWN_INIT);
  243. }
  244. else if(CLSID_IntProv == rclsid)
  245. {
  246. pFactory = new CFactory<CIntProv>(TRUE, ENSURE_INIT_WAIT_FOR_CLIENT);
  247. }
  248. else if(CLSID_IWmiCoreServices == rclsid)
  249. {
  250. pFactory = new CFactory<CCoreServices>(FALSE, ENSURE_INIT);
  251. }
  252. else
  253. {
  254. return E_FAIL;
  255. }
  256. if (!pFactory)
  257. return ResultFromScode(E_OUTOFMEMORY);
  258. hr = pFactory->QueryInterface(riid, ppv);
  259. if (FAILED(hr))
  260. delete pFactory;
  261. return hr;
  262. }
  263. //***************************************************************************
  264. //
  265. // DllCanUnloadNow
  266. //
  267. // Standard OLE entry point for server shutdown request. Allows shutdown
  268. // only if no outstanding objects or locks are present.
  269. //
  270. // RETURN VALUES:
  271. //
  272. // S_OK May unload now.
  273. // S_FALSE May not.
  274. //
  275. //***************************************************************************
  276. extern "C"
  277. HRESULT APIENTRY DllCanUnloadNow(void)
  278. {
  279. DEBUGTRACE((LOG_WBEMCORE,"+ DllCanUnloadNow()\n"));
  280. if(!IsDcomEnabled())
  281. return S_FALSE;
  282. if(IsNtSetupRunning())
  283. {
  284. DEBUGTRACE((LOG_WBEMCORE, "- DllCanUnloadNow() returning S_FALSE because setup is running\n"));
  285. return S_FALSE;
  286. }
  287. if(gClientCounter.OkToUnload())
  288. {
  289. Shutdown(FALSE,FALSE); // NO Process , NO System
  290. DEBUGTRACE((LOG_WBEMCORE, "- DllCanUnloadNow() S_OK\n"));
  291. _DBG_ASSERT(gClientCounter.OkToUnload());
  292. return S_OK;
  293. }
  294. else
  295. {
  296. DEBUGTRACE((LOG_WBEMCORE, "- DllCanUnloadNow() S_FALSE\n"));
  297. return S_FALSE;
  298. }
  299. }
  300. //***************************************************************************
  301. //
  302. // UpdateBackupReg
  303. //
  304. // Updates the backup default options in registry.
  305. //
  306. // RETURN VALUES:
  307. //
  308. //***************************************************************************
  309. void UpdateBackupReg()
  310. {
  311. HKEY hKey = 0;
  312. if (RegOpenKey(HKEY_LOCAL_MACHINE, WBEM_REG_WINMGMT, &hKey) == ERROR_SUCCESS) // SEC:REVIEWED 2002-03-22 : OK
  313. {
  314. char szBuff[20];
  315. DWORD dwSize = sizeof(szBuff);
  316. unsigned long ulType = REG_SZ;
  317. if ((RegQueryValueEx(hKey, __TEXT("Backup Interval Threshold"), 0, &ulType, (unsigned char*)szBuff, &dwSize) == ERROR_SUCCESS) && (strcmp(szBuff, "60") == 0)) // SEC:REVIEWED 2002-03-22 : OK
  318. {
  319. RegSetValueEx(hKey, __TEXT("Backup Interval Threshold"), 0, REG_SZ, (const BYTE*)(__TEXT("30")), (2+1) * sizeof(TCHAR)); // SEC:REVIEWED 2002-03-22 : OK
  320. }
  321. RegCloseKey(hKey);
  322. }
  323. }
  324. //***************************************************************************
  325. //
  326. // UpdateBackupReg
  327. //
  328. // Updates the unchecked task count value for the arbitrator.
  329. //
  330. // RETURN VALUES:
  331. //
  332. //***************************************************************************
  333. #define ARB_DEFAULT_TASK_COUNT_LESSTHAN_SERVER 50
  334. #define ARB_DEFAULT_TASK_COUNT_GREATERHAN_SERVER 250
  335. void UpdateArbitratorValues ()
  336. {
  337. HKEY hKey = 0;
  338. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WBEM_REG_WINMGMT, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) // SEC:REVIEWED 2002-03-22 : OK
  339. {
  340. DWORD dwValue = 0 ;
  341. DWORD dwSize = sizeof (DWORD) ;
  342. DWORD ulType = 0 ;
  343. if ((RegQueryValueEx(hKey, __TEXT("Unchecked Task Count"), 0, &ulType, LPBYTE(&dwValue), &dwSize) == ERROR_SUCCESS) ) // SEC:REVIEWED 2002-03-22 : OK
  344. {
  345. if ( !IsWhistlerPersonal ( ) && !IsWhistlerProfessional ( ) && ( dwValue == ARB_DEFAULT_TASK_COUNT_LESSTHAN_SERVER ) )
  346. {
  347. DWORD dwNewValue = ARB_DEFAULT_TASK_COUNT_GREATERHAN_SERVER ;
  348. RegSetValueEx(hKey, __TEXT("Unchecked Task Count"), 0, REG_DWORD, (const BYTE*)&dwNewValue, sizeof(DWORD)); // SEC:REVIEWED 2002-03-22 : OK
  349. }
  350. }
  351. else
  352. {
  353. //
  354. // Registry key non-existent
  355. //
  356. if ( !IsWhistlerPersonal ( ) && !IsWhistlerProfessional ( ) )
  357. {
  358. DWORD dwNewValue = ARB_DEFAULT_TASK_COUNT_GREATERHAN_SERVER ;
  359. RegSetValueEx(hKey, __TEXT("Unchecked Task Count"), 0, REG_DWORD, (const BYTE*)&dwNewValue, sizeof(DWORD)); // SEC:REVIEWED 2002-03-22 : OK
  360. }
  361. else
  362. {
  363. DWORD dwNewValue = ARB_DEFAULT_TASK_COUNT_LESSTHAN_SERVER ;
  364. RegSetValueEx(hKey, __TEXT("Unchecked Task Count"), 0, REG_DWORD, (const BYTE*)&dwNewValue, sizeof(DWORD)); // SEC:REVIEWED 2002-03-22 : OK
  365. }
  366. }
  367. RegCloseKey(hKey);
  368. }
  369. }
  370. //***************************************************************************
  371. //
  372. // BOOL IsWhistlerPersonal ()
  373. //
  374. // Returns true if machine is running Whistler Personal
  375. //
  376. //
  377. //***************************************************************************
  378. BOOL IsWhistlerPersonal ()
  379. {
  380. BOOL bRet = TRUE ;
  381. OSVERSIONINFOEXW verInfo ;
  382. verInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFOEX ) ;
  383. if ( GetVersionExW ( (LPOSVERSIONINFOW) &verInfo ) == TRUE )
  384. {
  385. if ( ( verInfo.wSuiteMask != VER_SUITE_PERSONAL ) && ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) )
  386. {
  387. bRet = FALSE ;
  388. }
  389. }
  390. return bRet ;
  391. }
  392. //***************************************************************************
  393. //
  394. // BOOL IsWhistlerProfessional ()
  395. //
  396. // Returns true if machine is running Whistler Professional
  397. //
  398. //
  399. //***************************************************************************
  400. BOOL IsWhistlerProfessional ()
  401. {
  402. BOOL bRet = TRUE ;
  403. OSVERSIONINFOEXW verInfo ;
  404. verInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFOEX ) ;
  405. if ( GetVersionExW ( (LPOSVERSIONINFOW) &verInfo ) == TRUE )
  406. {
  407. if ( ( verInfo.wProductType != VER_NT_WORKSTATION ) && ( verInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) )
  408. {
  409. bRet = FALSE ;
  410. }
  411. }
  412. return bRet ;
  413. }
  414. //***************************************************************************
  415. //
  416. // DllRegisterServer
  417. //
  418. // Standard OLE entry point for registering the server.
  419. //
  420. // RETURN VALUES:
  421. //
  422. // S_OK Registration was successful
  423. // E_FAIL Registration failed.
  424. //
  425. //***************************************************************************
  426. extern "C"
  427. HRESULT APIENTRY DllRegisterServer(void)
  428. {
  429. TCHAR* szModel = (IsDcomEnabled() ? __TEXT("Both") : __TEXT("Apartment"));
  430. RegisterDLL(g_hInstance, CLSID_ActualWbemAdministrativeLocator, __TEXT(""), szModel,
  431. NULL);
  432. RegisterDLL(g_hInstance, CLSID_ActualWbemAuthenticatedLocator, __TEXT(""), szModel, NULL);
  433. RegisterDLL(g_hInstance, CLSID_ActualWbemUnauthenticatedLocator, __TEXT(""), szModel, NULL);
  434. RegisterDLL(g_hInstance, CLSID_InProcWbemLevel1Login, __TEXT(""), szModel, NULL);
  435. RegisterDLL(g_hInstance, CLSID_IntProv, __TEXT(""), szModel, NULL);
  436. RegisterDLL(g_hInstance, CLSID_IWmiCoreServices, __TEXT(""), szModel, NULL);
  437. // Write the setup time into the registry. This isnt actually needed
  438. // by dcom, but the code did need to be stuck in some place which
  439. // is called upon setup
  440. long lRes;
  441. DWORD ignore;
  442. HKEY key;
  443. lRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // SEC:REVIEWED 2002-03-22 : OK, inherits ACEs from higher key
  444. WBEM_REG_WINMGMT,
  445. NULL,
  446. NULL,
  447. REG_OPTION_NON_VOLATILE,
  448. KEY_READ | KEY_WRITE,
  449. NULL,
  450. &key,
  451. &ignore);
  452. if(lRes == ERROR_SUCCESS)
  453. {
  454. SYSTEMTIME st;
  455. GetSystemTime(&st); // get the gmt time
  456. TCHAR cTime[MAX_PATH];
  457. // convert to localized format!
  458. lRes = GetDateFormat(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, &st,
  459. NULL, cTime, MAX_PATH);
  460. if(lRes)
  461. {
  462. StringCchCat(cTime, MAX_PATH, __TEXT(" GMT"));
  463. lRes = RegSetValueEx(key, __TEXT("SetupDate"), 0, REG_SZ, // SEC:REVIEWED 2002-03-22 : OK
  464. (BYTE *)cTime, (lstrlen(cTime)+1) * sizeof(TCHAR)); // SEC:REVIEWED 2002-03-22 : OK
  465. }
  466. lRes = GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &st,
  467. NULL, cTime, MAX_PATH);
  468. if(lRes)
  469. {
  470. StringCchCat(cTime, MAX_PATH, __TEXT(" GMT"));
  471. lRes = RegSetValueEx(key, __TEXT("SetupTime"), 0, REG_SZ, // SEC:REVIEWED 2002-03-22 : OK
  472. (BYTE *)cTime, (lstrlen(cTime)+1) * sizeof(TCHAR)); // SEC:REVIEWED 2002-03-22 : OK
  473. }
  474. CloseHandle(key);
  475. }
  476. UpdateBackupReg();
  477. UpdateArbitratorValues ( ) ;
  478. return S_OK;
  479. }
  480. //***************************************************************************
  481. //
  482. // DllUnregisterServer
  483. //
  484. // Standard OLE entry point for unregistering the server.
  485. //
  486. // RETURN VALUES:
  487. //
  488. // S_OK Unregistration was successful
  489. // E_FAIL Unregistration failed.
  490. //
  491. //***************************************************************************
  492. extern "C"
  493. HRESULT APIENTRY DllUnregisterServer(void)
  494. {
  495. UnRegisterDLL(CLSID_ActualWbemAdministrativeLocator, NULL);
  496. UnRegisterDLL(CLSID_ActualWbemAuthenticatedLocator, NULL);
  497. UnRegisterDLL(CLSID_ActualWbemUnauthenticatedLocator, NULL);
  498. UnRegisterDLL(CLSID_InProcWbemLevel1Login, NULL);
  499. UnRegisterDLL(CLSID_IntProv, NULL);
  500. UnRegisterDLL(CLSID_IWmiCoreServices, NULL);
  501. HKEY hKey;
  502. long lRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, // SEC:REVIEWED 2002-03-22 : OK
  503. WBEM_REG_WINMGMT,
  504. 0, KEY_ALL_ACCESS, &hKey); // SEC:REVIEWED 2002-03-22 : OK
  505. if(lRes == ERROR_SUCCESS)
  506. {
  507. RegDeleteValue(hKey, __TEXT("SetupDate"));
  508. RegDeleteValue(hKey, __TEXT("SetupTime"));
  509. RegCloseKey(hKey);
  510. }
  511. return S_OK;
  512. }
  513. //***************************************************************************
  514. //
  515. // CFactory::CFactory
  516. //
  517. // Constructs the class factory given the CLSID of the objects it is supposed
  518. // to create.
  519. //
  520. //***************************************************************************
  521. template<class TObj>
  522. CFactory<TObj>::CFactory(BOOL bUser, InitType it)
  523. {
  524. m_cRef = 0;
  525. m_bUser = bUser;
  526. m_it = it;
  527. gClientCounter.AddClientPtr(&m_Entry);
  528. }
  529. //***************************************************************************
  530. //
  531. // CFactory::~CFactory
  532. //
  533. // Destructor.
  534. //
  535. //***************************************************************************
  536. template<class TObj>
  537. CFactory<TObj>::~CFactory()
  538. {
  539. gClientCounter.RemoveClientPtr(&m_Entry);
  540. }
  541. //***************************************************************************
  542. //
  543. // CFactory::QueryInterface, AddRef and Release
  544. //
  545. // Standard IUnknown methods.
  546. //
  547. //***************************************************************************
  548. template<class TObj>
  549. STDMETHODIMP CFactory<TObj>::QueryInterface(REFIID riid, LPVOID * ppv)
  550. {
  551. *ppv = 0;
  552. if (IID_IUnknown==riid || IID_IClassFactory==riid)
  553. {
  554. *ppv = this;
  555. AddRef();
  556. return NOERROR;
  557. }
  558. return ResultFromScode(E_NOINTERFACE);
  559. }
  560. template<class TObj>
  561. ULONG CFactory<TObj>::AddRef()
  562. {
  563. return ++m_cRef;
  564. }
  565. template<class TObj>
  566. ULONG CFactory<TObj>::Release()
  567. {
  568. if (0 != --m_cRef)
  569. return m_cRef;
  570. delete this;
  571. return 0;
  572. }
  573. //***************************************************************************
  574. //
  575. // CFactory::CreateInstance
  576. //
  577. // As mandated by IClassFactory, creates a new instance of its object
  578. // (CWbemLocator).
  579. //
  580. // PARAMETERS:
  581. //
  582. // LPUNKNOWN pUnkOuter IUnknown of the aggregator. Must be NULL.
  583. // REFIID riid Interface ID required.
  584. // LPVOID * ppvObj Destination for the interface pointer.
  585. //
  586. // RETURN VALUES:
  587. //
  588. // S_OK Success
  589. // CLASS_E_NOAGGREGATION pUnkOuter must be NULL
  590. // E_NOINTERFACE No such interface supported.
  591. //
  592. //***************************************************************************
  593. template<class TObj>
  594. STDMETHODIMP CFactory<TObj>::CreateInstance(
  595. LPUNKNOWN pUnkOuter,
  596. REFIID riid,
  597. LPVOID * ppvObj)
  598. {
  599. TObj* pObj;
  600. HRESULT hr;
  601. // Defaults
  602. *ppvObj=NULL;
  603. if(m_it == ENSURE_INIT || m_it == ENSURE_INIT_WAIT_FOR_CLIENT)
  604. {
  605. hr = EnsureInitialized();
  606. if(FAILED(hr)) return hr;
  607. if(m_it == ENSURE_INIT_WAIT_FOR_CLIENT)
  608. {
  609. // Wait until user-ready
  610. hr = ConfigMgr::WaitUntilClientReady();
  611. if(FAILED(hr)) return hr;
  612. }
  613. }
  614. // We aren't supporting aggregation.
  615. if (pUnkOuter)
  616. return CLASS_E_NOAGGREGATION;
  617. pObj = new TObj;
  618. if (!pObj)
  619. return E_OUTOFMEMORY;
  620. //
  621. // Initialize the object and verify that it can return the
  622. // interface in question.
  623. //
  624. hr = pObj->QueryInterface(riid, ppvObj);
  625. //
  626. // Kill the object if initial creation or Init failed.
  627. //
  628. if (FAILED(hr))
  629. delete pObj;
  630. return hr;
  631. }
  632. //***************************************************************************
  633. //
  634. // CFactory::LockServer
  635. //
  636. // Increments or decrements the lock count of the server. The DLL will not
  637. // unload while the lock count is positive.
  638. //
  639. // PARAMETERS:
  640. //
  641. // BOOL fLock If TRUE, locks; otherwise, unlocks.
  642. //
  643. // RETURN VALUES:
  644. //
  645. // S_OK
  646. //
  647. //***************************************************************************
  648. template<class TObj>
  649. STDMETHODIMP CFactory<TObj>::LockServer(BOOL fLock)
  650. {
  651. if (fLock)
  652. InterlockedIncrement((LONG *) &g_cLock);
  653. else
  654. InterlockedDecrement((LONG *) &g_cLock);
  655. return NOERROR;
  656. }
  657. void WarnESSOfShutdown(LONG lSystemShutDown)
  658. {
  659. if(g_lInitCount != -1)
  660. {
  661. IWbemEventSubsystem_m4* pEss = ConfigMgr::GetEssSink();
  662. if(pEss)
  663. {
  664. pEss->LastCallForCore(lSystemShutDown);
  665. pEss->Release();
  666. }
  667. }
  668. }
  669. //
  670. // we can have Shutdown called twice in a row, because
  671. // DllCanUnloadNow will do that, once triggered by CoFreeUnusedLibraries
  672. //
  673. extern "C"
  674. HRESULT APIENTRY Shutdown(BOOL bProcessShutdown, BOOL bIsSystemShutdown)
  675. {
  676. CEnterWbemCriticalSection enterCs(&g_csInit);
  677. if (!bIsSystemShutdown)
  678. {
  679. DEBUGTRACE((LOG_WBEMCORE, " wbemcore!Shutdown(%d)"
  680. " g_ShutdownCalled = %d g_lInitCount = %d)\n",
  681. bProcessShutdown, g_ShutdownCalled,g_lInitCount));
  682. }
  683. if (g_ShutdownCalled) {
  684. return S_OK;
  685. } else {
  686. g_ShutdownCalled = TRUE;
  687. }
  688. if(bProcessShutdown)
  689. {
  690. WarnESSOfShutdown((LONG)bIsSystemShutdown);
  691. }
  692. if(g_lInitCount == -1)
  693. {
  694. return S_OK;
  695. }
  696. if(!bProcessShutdown)
  697. WarnESSOfShutdown((LONG)bIsSystemShutdown);
  698. g_lInitCount = -1;
  699. ConfigMgr::Shutdown(bProcessShutdown,bIsSystemShutdown);
  700. if (!bIsSystemShutdown)
  701. {
  702. DEBUGTRACE((LOG_WBEMCORE,"****** WinMgmt Shutdown ******************\n"));
  703. }
  704. return S_OK;
  705. }
  706. extern "C" HRESULT APIENTRY Reinitialize(DWORD dwReserved)
  707. {
  708. if(g_ShutdownCalled)
  709. {
  710. CEnterWbemCriticalSection enterCs(&g_csInit);
  711. DEBUGTRACE((LOG_WBEMCORE, "wbemcore!Reinitialize(%d) (g_ShutdownCalled = %d)\n",
  712. dwReserved, g_ShutdownCalled));
  713. if(g_ShutdownCalled == FALSE)
  714. return S_OK;
  715. g_dwQueueSize = 1;
  716. g_pEss_m4 = NULL;
  717. g_lInitCount = -1;
  718. g_bDefaultMofLoadingNeeded = false;
  719. g_bDontAllowNewConnections = FALSE;
  720. g_pContextFac = NULL;
  721. g_pPathFac = NULL;
  722. g_pQueryFact = NULL;
  723. g_ShutdownCalled = FALSE;
  724. g_bPreviousFail = false;
  725. g_hrLastEnsuredInitializeError = WBEM_S_NO_ERROR;
  726. }
  727. return S_OK;
  728. }