text: #include "precomp.h"
  #include "ClassFac.h"
  #include <arrTempl.h>
  
  DWORD WMIScriptClassFactory::m_scriptsStarted = 0;
   
  DWORD WMIScriptClassFactory::m_scriptsAllowed = 300;
  
  bool WMIScriptClassFactory::m_bIsScriptsAllowedInitialized = false;
  bool WMIScriptClassFactory::m_bWeDeadNow = false;
  
  
  DWORD WMIScriptClassFactory::m_timerID = 0;
  
  HRESULT WMIScriptClassFactory::CreateInstance(IUnknown* pOuter, REFIID riid, void** ppv)
  {
      if (!m_bIsScriptsAllowedInitialized)
          FindScriptsAllowed();
      
      HRESULT hr = CClassFactory<CScriptConsumer>::CreateInstance(pOuter, riid, ppv);
  
      return hr;
  }
  
  // our time has come.  Curl up & die.
  void CALLBACK WMIScriptClassFactory::TimeoutProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 
  {
      CoSuspendClassObjects();
      KillTimer(NULL, m_timerID);
      m_timerID = 0;
      m_bWeDeadNow = true;
  }
  
  bool WMIScriptClassFactory::LimitReached(void)
  {
      return m_bWeDeadNow;
  }
  
  // determine number of scripts we're allowed to run
  // from the class registration object
  void WMIScriptClassFactory::FindScriptsAllowed(void)
  {    
      m_bIsScriptsAllowedInitialized = true;
      HRESULT hr;
      IWbemLocator* pLocator;
  
      if (SUCCEEDED(hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, 
                                            IID_IWbemLocator, (void**)&pLocator)))
      {
          CReleaseMe releaseLocator(pLocator);
  
          BSTR bstrNamespace;
          bstrNamespace = SysAllocString(L"root\\CIMv2");
          
          if (bstrNamespace)
          {
              IWbemServices* pNamespace;
              CSysFreeMe freeBstr(bstrNamespace);
              hr = pLocator->ConnectServer(bstrNamespace,  NULL, NULL, NULL, 0, NULL, NULL, &pNamespace);
              if (SUCCEEDED(hr))
              {
                  CReleaseMe relNamespace(pNamespace);
  
                  BSTR bstrClassName;
                  bstrClassName = SysAllocString(L"ScriptingStandardConsumerSetting=@");
                  if (bstrClassName)
                  {
                      IWbemClassObject* pRegistration = NULL;
                      CSysFreeMe freeTheClassNames(bstrClassName);               
                      hr = pNamespace->GetObject(bstrClassName, 0, NULL, &pRegistration, NULL);
                      if (SUCCEEDED(hr))
                      {
                          CReleaseMe relRegistration(pRegistration);
  
                          VARIANT v;
                          VariantInit(&v);
  
                          if (SUCCEEDED(pRegistration->Get(L"MaximumScripts", 0, &v, NULL, NULL))
                              && ((v.vt == VT_I4) || (v.vt == VT_UI4))
                              && (v.ulVal > 0))
                          {
                              m_scriptsAllowed = (DWORD)v.ulVal;
                              VariantClear(&v);
                          }
  
                          if (SUCCEEDED(hr = pRegistration->Get(L"Timeout", 0, &v, NULL, NULL))
                              && (v.vt == VT_I4))
                          {
                              // maximum to prevent overflow, doc'd in MOF
                              if ((((DWORD)v.lVal) <= 71000) && ((DWORD)v.lVal > 0))
                              {
                                  UINT nMilliseconds = (DWORD)v.lVal * 1000 * 60;
                                  m_timerID = SetTimer(NULL, 0, nMilliseconds, TimeoutProc);
                              }
                          }
                      }
                  }
              }
          }
      }
  }
  
  // after the specified number of scripts have been run
  // we suspend the class object
  // note that access to m_scriptsStarted is not serialized.
  // this should not cause a problem, m_scripts allowed does not change
  // after instanciation, and if we blow it, it just means we allow
  // an extra script to be run, or call CoSuspend an extra time.
  void WMIScriptClassFactory::IncrementScriptsRun(void)
  {    
      InterlockedIncrement((long*)&m_scriptsStarted);
  
      if (m_scriptsStarted >= m_scriptsAllowed)
      {
          CoSuspendClassObjects();
          m_bWeDeadNow = true;
      }
  }
  
  
  