iwebck.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 14k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "private.h"
  2. #include "ssseprox.h"
  3. #include <shlguid.h>
  4. #define TF_THISMODULE TF_WEBCHECKCORE
  5. DWORD   g_idSchedThread = 0;
  6. // global containing pointer to instance of CWebcheck.  Needed to control
  7. // externals loading on demand.
  8. CWebCheck *g_pwc = NULL;
  9. //////////////////////////////////////////////////////////////////////////
  10. //
  11. // CWebCheck implementation
  12. //
  13. //////////////////////////////////////////////////////////////////////////
  14. CWebCheck::CWebCheck()
  15. {
  16.     // Maintain global object count
  17.     DllAddRef();
  18.     // Initialize object
  19.     m_cRef = 1;
  20.     // save our instance
  21.     g_pwc = this;
  22. }
  23. CWebCheck::~CWebCheck()
  24. {
  25.     // Maintain global object count
  26.     DllRelease();
  27.     // no longer available
  28.     g_pwc = NULL;
  29. }
  30. //
  31. // IUnknown members
  32. //
  33. STDMETHODIMP_(ULONG) CWebCheck::AddRef(void)
  34. {
  35. //  TraceMsg(TF_THISMODULE, "CWebCheck::AddRef m_cRef=%d", m_cRef+1);
  36.     return ++m_cRef;
  37. }
  38. STDMETHODIMP_(ULONG) CWebCheck::Release(void)
  39. {
  40. //  TraceMsg(TF_THISMODULE, "CWebCheck::Release m_cRef=%d", m_cRef-1);
  41.     if( 0L != --m_cRef )
  42.         return m_cRef;
  43.     delete this;
  44.     return 0L;
  45. }
  46. STDMETHODIMP CWebCheck::QueryInterface(REFIID riid, void ** ppv)
  47. {
  48.     *ppv=NULL;
  49.     // Validate requested interface
  50.     if (IsEqualIID(riid, IID_IUnknown))
  51.         *ppv = (IUnknown *)this;
  52.     else if (IsEqualIID(riid, IID_IOleCommandTarget))
  53.         *ppv = (IOleCommandTarget *)this;
  54.     else
  55.         return E_NOINTERFACE;
  56.     // Addref through the interface
  57.     ((LPUNKNOWN)*ppv)->AddRef();
  58.     return S_OK;
  59. }
  60. //
  61. // IOleCommandTarget members
  62. // The shell will send notifications to us through this interface.
  63. //
  64. STDMETHODIMP CWebCheck::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
  65.                                     OLECMD prgCmds[], OLECMDTEXT *pCmdText)
  66. {
  67.     if (IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
  68.     {
  69.         // We like Shell Service Object notifications...
  70.         return S_OK;
  71.     }
  72.     return(OLECMDERR_E_UNKNOWNGROUP);
  73. }
  74. STDMETHODIMP CWebCheck::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  75.                              DWORD nCmdexecopt, VARIANTARG *pvaIn,
  76.                              VARIANTARG *pvaOut)
  77. {
  78.     if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
  79.     {
  80.         // Handle Shell Service Object notifications here.
  81.         switch (nCmdID)
  82.         {
  83.             case SSOCMDID_OPEN:
  84.                 StartService(FALSE);
  85.                 break;
  86.             case SSOCMDID_CLOSE:
  87.                 StopService();
  88.                 break;
  89.         }
  90.         return S_OK;
  91.     }
  92.     
  93.     return(E_NOTIMPL);
  94. }
  95. //
  96. // IWebCheck members
  97. //
  98. // Starts the webcheck service in a process
  99. STDMETHODIMP CWebCheck::StartService(BOOL fForceExternals)
  100. {
  101.     DBG("CWebCheck::StartService entered");
  102.     // reset offline mode for all platforms except NT5
  103.     if(FALSE == g_fIsWinNT5)
  104.     {
  105.         HMODULE hWininet = GetModuleHandle(TEXT("WININET.DLL"));
  106.         if(hWininet)
  107.         {
  108.             // wininet is loaded - tell it to go online
  109.             INTERNET_CONNECTED_INFO ci;
  110.             memset(&ci, 0, sizeof(ci));
  111.             ci.dwConnectedState = INTERNET_STATE_CONNECTED;
  112.             InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci));
  113.         } 
  114.         else 
  115.         {
  116.             // wininet not loaded - blow away offline reg key so we'll
  117.             // be online when it does load
  118.             DWORD dwOffline = 0;        // FALSE => not offline
  119.             WriteRegValue(HKEY_CURRENT_USER, c_szRegPathInternetSettings,
  120.                 TEXT("GlobalUserOffline"), &dwOffline, sizeof(DWORD), REG_DWORD);
  121.         }
  122.     }
  123.     // create dialmon window
  124.     DialmonInit();
  125.     // Fire up LCE and sens if necessary
  126.     if(fForceExternals || ShouldLoadExternals())
  127.         LoadExternals();
  128.     //
  129.     // Process the Infodelivery Admin Policies on user login.  (User login coincides
  130.     // with webcheck's StartService() call.)
  131.     //
  132.     ProcessInfodeliveryPolicies();
  133.     // Initialize the Channel Screen Saver hlink proxy.
  134.     if (g_fIsWinNT)
  135.         InitSEProx();
  136.     
  137.     DBG("CWebCheck::StartService exiting");
  138.     return S_OK;
  139. }
  140. // Stops Webcheck if running.
  141. STDMETHODIMP CWebCheck::StopService(void)
  142. {
  143.     DBG("CWebCheck::StopService entered");
  144.     // kill dialmon window
  145.     DialmonShutdown();
  146.     // shut down the external bits
  147.     if(FALSE == g_fIsWinNT)
  148.         UnloadExternals();
  149.     // Release resources for the Channel Screen Saver hlink proxy.
  150.     if (g_fIsWinNT)
  151.         FreeSEProx();
  152.     DBG("CWebCheck::StopService exiting");
  153.     return S_OK;
  154. }
  155. //
  156. // load behavior: (win9x)
  157. //
  158. // "auto"   Load if on a laptop
  159. // "yes"    Load always
  160. // "no"     Load never
  161. //
  162. static const WCHAR s_szAuto[] = TEXT("auto");
  163. static const WCHAR s_szYes[] = TEXT("yes");
  164. static const WCHAR s_szNo[] = TEXT("no");
  165. BOOL CWebCheck::ShouldLoadExternals(void)
  166. {
  167.     WCHAR   szSens[16], szLce[16];
  168.     DWORD   cbData;
  169.     //
  170.     // don't load on NT
  171.     //
  172.     if(g_fIsWinNT)
  173.     {
  174.         DBG("CWebCheck::ShouldLoadExternals -> NO (NT)");
  175.         return FALSE;
  176.     }
  177.     //
  178.     // read sens/lce user settings - no setting means auto
  179.     //
  180.     cbData = sizeof(szLce);
  181.     if(ERROR_SUCCESS != SHGetValueW(HKEY_LOCAL_MACHINE, c_szRegKey, L"LoadLCE", NULL, szLce, &cbData))
  182.     {
  183.         StrCpyW(szLce, s_szAuto);
  184.     }
  185.     cbData = sizeof(szSens);
  186.     if(ERROR_SUCCESS != SHGetValueW(HKEY_LOCAL_MACHINE, c_szRegKey, L"LoadSens", NULL, szSens, &cbData))
  187.     {
  188.         StrCpyW(szSens, s_szAuto);
  189.     }
  190.     //
  191.     // if either is yes, load
  192.     //
  193.     if(0 == StrCmpIW(szLce, s_szYes) || 0 == StrCmpIW(szSens, s_szYes))
  194.     {
  195.         DBG("CWebCheck::ShouldLoadExternals -> YES (reg = yes)");
  196.         return TRUE;
  197.     }
  198.     //
  199.     // if either is auto, check for laptop
  200.     //
  201.     if(0 == StrCmpIW(szLce, s_szAuto) || 0 == StrCmpIW(szSens, s_szAuto))
  202.     {
  203.         if(SHGetMachineInfo(GMI_LAPTOP))
  204.         {
  205.             // Is a laptop - load
  206.             DBG("CWebCheck::ShouldLoadExternals -> YES (reg = auto, laptop)");
  207.             return TRUE;
  208.         }
  209.     }
  210.     // don't load
  211.     DBG("CWebCheck::ShouldLoadExternals -> NO");
  212.     return FALSE;
  213. }
  214. BOOL CWebCheck::AreExternalsLoaded(void)
  215. {
  216.     return (_hThread != NULL);
  217. }
  218. void CWebCheck::LoadExternals(void)
  219. {
  220.     DWORD dwThreadId;
  221.     DBG("CWebCheck::LoadExternals");
  222.     if(_hThread)
  223.     {
  224.         DBG("CWebCheck::LoadExternals - already loaded");
  225.         return;
  226.     }
  227.     // create initializion and termination events
  228.     _hInitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  229.     _hTerminateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  230.     if(NULL == _hInitEvent || NULL == _hTerminateEvent) {
  231.         DBG("LoadExternals failed to create termination event");
  232.         return;
  233.     }
  234.     // fire up a thread to do the work
  235.     _hThread = CreateThread(NULL, 4096, ExternalsThread, this, 0, &dwThreadId);
  236.     if(NULL == _hThread) {
  237.         DBG("LoadExternals failed to create externals thread!");
  238.         return;
  239.     }
  240.     // wait for initialization event to trigger then free it
  241.     WaitForSingleObject(_hInitEvent, INFINITE);
  242.     CloseHandle(_hInitEvent);
  243.     _hInitEvent = NULL;
  244.     DBG("CWebCheck::LoadExternals exiting");
  245.     return;
  246. }
  247. void CWebCheck::UnloadExternals(void)
  248. {
  249.     if(NULL == _hThread)
  250.     {
  251.         DBG("CWebCheck::UnloadExternals - nothing to unload");
  252.         return;
  253.     }
  254.     // tell externals thread to go away by setting termination event
  255.     SetEvent(_hTerminateEvent);
  256.     // Give thread a 10 second grace period to shut down
  257.     // don't really care if it goes away or not... our process is going away!
  258.     WaitForSingleObject(_hThread, 10000);
  259.     // clean up
  260.     CloseHandle(_hThread);
  261.     CloseHandle(_hTerminateEvent);
  262.     _hThread = NULL;
  263.     _hTerminateEvent = NULL;
  264.     return;
  265. }
  266. DWORD WINAPI ExternalsThread(LPVOID lpData)
  267. {
  268.     CWebCheck * pWebCheck = (CWebCheck *)lpData;
  269.     HINSTANCE hLCE, hSENS = NULL;
  270.     BOOL fLCEStarted = FALSE, fSENSStarted = FALSE;
  271.     DWORD dwRet;
  272.     MSG msg;
  273.     // fire up com
  274.     HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  275.     if(FAILED(hr)) {
  276.         DBG("LoadExternals: Failed to initialize COM");
  277.         SetEvent(pWebCheck->_hInitEvent);
  278.         return 0;
  279.     }
  280.     // load and start LCE
  281.     hLCE = LoadLibrary(TEXT("estier2.dll"));
  282.     DBGASSERT(hLCE, "LoadExternals: Failed to load estier2.dll");
  283.     if(hLCE) {
  284.         LCESTART startfunc;
  285.         startfunc = (LCESTART)GetProcAddress(hLCE, "LCEStartServer");
  286.         DBGASSERT(startfunc, "LoadExternals: Failed to find LCEStartServer");
  287.         if(startfunc) {
  288.             hr = startfunc();
  289.             if(SUCCEEDED(hr))
  290.                 fLCEStarted = TRUE;
  291.             DBGASSERT(fLCEStarted, "LoadExternals: Failed to start LCE");
  292.         }
  293.     }
  294.     // if LCE started sucessfully, load and start SENS
  295.     if(fLCEStarted) {
  296.         hSENS = LoadLibrary(TEXT("sens.dll"));
  297.         DBGASSERT(hSENS, "LoadExternals: Failed to load sens.dll");
  298.         if(hSENS) {
  299.             SENSSTART startfunc;
  300.             startfunc = (SENSSTART)GetProcAddress(hSENS, "SensInitialize");
  301.             DBGASSERT(startfunc, "LoadExternals: Failed to find SensInitialize");
  302.             if(startfunc) {
  303.                 if(startfunc())
  304.                     fSENSStarted = TRUE;
  305.                 DBGASSERT(fSENSStarted, "LoadExternals: Failed to start SENS");
  306.             }
  307.         }
  308.     }
  309.     // trigger initialization event to tell caller we're up and running
  310.     SetEvent(pWebCheck->_hInitEvent);
  311.     // Wait for our shutdown event but pump messages in the mean time
  312.     do {
  313.         dwRet = MsgWaitForMultipleObjects(1, &(pWebCheck->_hTerminateEvent),
  314.                     FALSE, INFINITE, QS_ALLINPUT);
  315.         if(WAIT_OBJECT_0 == dwRet) {
  316.             // got our event, drop out of do loop
  317.             break;
  318.         }
  319.         // empty the message queue...
  320.         while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  321.             TranslateMessage(&msg);
  322.             DispatchMessage(&msg);
  323.         }
  324.     } while(TRUE);
  325.     // shut down SENS
  326.     if(fSENSStarted) {
  327.         ASSERT(hSENS);
  328.         SENSSTOP stopfunc;
  329.         stopfunc = (SENSSTOP)GetProcAddress(hSENS, "SensUninitialize");
  330.         if(stopfunc) {
  331.             stopfunc();
  332.         }
  333.     }
  334.     //
  335.     // [darrenmi] beta-1 hack: Sens may have a thread sitting in its code
  336.     // at this point so it's not safe to unload sens.  Since we're in the
  337.     // process of shutting down anyway, just leave it alone and let the 
  338.     // system unload it.
  339.     //
  340.     //if(hSENS) {
  341.     //    FreeLibrary(hSENS);
  342.     //}
  343.     // shut down LCE
  344.     if(fLCEStarted) {
  345.         ASSERT(hLCE)
  346.         LCESTOP stopfunc;
  347.         stopfunc = (LCESTOP)GetProcAddress(hLCE, "LCEStopServer");
  348.         if(stopfunc) {
  349.             stopfunc();
  350.         }
  351.     }
  352.     if(hLCE) {
  353.         FreeLibrary(hLCE);
  354.     }
  355.     // clean up com goo
  356.     CoUninitialize();
  357.     return 0;
  358. }
  359. #if 0
  360. //  TODO: need similar functionality in the new world
  361. void SetNotificationMgrRestrictions(INotificationProcessMgr0 *pNotfMgrProcess)
  362. {
  363.     HRESULT hr;
  364.     INotificationProcessMgr0 *pNotProcess = pNotfMgrProcess;
  365.     // get NotificationMgr if it wasn't passed in
  366.     if (!pNotfMgrProcess)
  367.     {
  368.         hr = CoCreateInstance(CLSID_StdNotificationMgr,
  369.                           NULL,
  370.                           CLSCTX_INPROC_SERVER,
  371.                           IID_INotificationProcessMgr0,
  372.                           (void**)&pNotProcess);
  373.         DBGASSERT(SUCCEEDED(hr), "SetNotificationMgrRestrictions - failed to create notification mgr");
  374.     }
  375.     // set the restrictions
  376.     if (pNotProcess)
  377.     {
  378.         const TCHAR c_szNoScheduledUpdates[] = TEXT("NoScheduledUpdates");
  379.         THROTTLEITEM ti = {0};
  380.         ti.NotificationType = NOTIFICATIONTYPE_AGENT_START;
  381.         ti.nParallel = 3;
  382.         
  383.         // Has the user has disabled scheduled subscription updates?
  384.         DWORD dwData;
  385.         DWORD cbData = sizeof(dwData);
  386.         if ((ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegKey, c_szNoScheduledUpdates, NULL, &dwData, &cbData))
  387.             && dwData)
  388.         {
  389.             ti.dwFlags |= TF_DONT_DELIVER_SCHEDULED_ITEMS;
  390.         }
  391.         
  392.         // Has the administrator has disabled scheduled subscription updates?
  393.         if (SHRestricted2W(REST_NoScheduledUpdates, NULL, 0))
  394.         {
  395.             ti.dwFlags |= TF_DONT_DELIVER_SCHEDULED_ITEMS;
  396.         }
  397.         
  398.         // Has the administrator has excluded scheduled subscription updates
  399.         // from this time range?
  400.         DWORD dwBegin = SHRestricted2W(REST_UpdateExcludeBegin, NULL, 0);
  401.         DWORD dwEnd = SHRestricted2W(REST_UpdateExcludeEnd, NULL, 0);
  402.         if (dwBegin && dwEnd)
  403.         {
  404.             ti.dwFlags |= TF_APPLY_EXCLUDE_RANGE;
  405.             ti.stBegin.wHour = (WORD)(dwBegin / 60);
  406.             ti.stBegin.wMinute = (WORD)(dwBegin % 60);
  407.             ti.stEnd.wHour = (WORD)(dwEnd / 60);
  408.             ti.stEnd.wMinute = (WORD)(dwEnd %60);
  409.         }
  410.         // Has the admin set a minimum interval for scheduled subscription updates?
  411.         dwData = SHRestricted2W(REST_MinUpdateInterval, NULL, 0);
  412.         if (dwData)
  413.         {
  414.             ti.dwFlags |= TF_APPLY_UPDATEINTERVAL;
  415.             ti.dwMinItemUpdateInterval = dwData;
  416.         }
  417.         
  418.         hr = pNotProcess->RegisterThrottleNotificationType(1, &ti, 0, NULL, 0, 0);
  419.         DBGASSERT(SUCCEEDED(hr), "SetNotificationMgrRestrictions - failed to register throttle type & restrictions");
  420.     }
  421.     // release NotificationMgr if it wasn't passed in
  422.     if (!pNotfMgrProcess)
  423.     {
  424.         SAFERELEASE(pNotProcess);
  425.     }
  426. }
  427. #endif
  428. //
  429. // OLE bypass code
  430. //
  431. // Expose a couple of APIs to call start and stop service so loadwc doesn't
  432. // need to load up OLE at start time.
  433. //
  434. HRESULT
  435. ExtStartService(
  436.     BOOL    fForceExternals
  437.     )
  438. {
  439.     HRESULT hr = E_FAIL;
  440.     // make a webcheck object
  441.     ASSERT(NULL == g_pwc);
  442.     if(NULL == g_pwc)
  443.     {
  444.         g_pwc = new CWebCheck;
  445.         if(g_pwc)
  446.         {
  447.             hr = g_pwc->StartService(fForceExternals);
  448.         }
  449.     }
  450.     return hr;
  451. }
  452. HRESULT
  453. ExtStopService(
  454.     void
  455.     )
  456. {
  457.     HRESULT hr = E_FAIL;
  458.     if(g_pwc)
  459.     {
  460.         hr = g_pwc->StopService();
  461.         SAFERELEASE(g_pwc);
  462.     }
  463.     return hr;
  464. }