Bug 1418131: Part 1 - Add Windows Security Center info to nsSystemInfo; r?jimm, r?erahm draft
authorAaron Klotz <aklotz@mozilla.com>
Thu, 16 Nov 2017 17:59:51 -0700
changeset 710225 3eb29bb01f66e11e509b8a7fe04df160fd559cde
parent 710168 c35272ba2006ecc8bc10099242f7b4c5c0f805d0
child 710226 318965ea303ec48d52b5b7dc51a152d6ef857d12
push id92787
push useraklotz@mozilla.com
push dateFri, 08 Dec 2017 22:37:13 +0000
reviewersjimm, erahm
bugs1418131
milestone59.0a1
Bug 1418131: Part 1 - Add Windows Security Center info to nsSystemInfo; r?jimm, r?erahm MozReview-Commit-ID: 7XUAIesDpRu
xpcom/base/moz.build
xpcom/base/nsSystemInfo.cpp
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -83,16 +83,19 @@ EXPORTS += [
     'nsWeakPtr.h',
     'nsWeakReference.h',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     EXPORTS += [
         'nsWindowsHelpers.h',
     ]
+    OS_LIBS += [
+        'wscapi',
+    ]
 
 EXPORTS.mozilla += [
     'AutoRestore.h',
     'AvailableMemoryTracker.h',
     'ClearOnShutdown.h',
     'CountingAllocatorBase.h',
     'CycleCollectedJSContext.h',
     'CycleCollectedJSRuntime.h',
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -9,19 +9,22 @@
 #include "nsSystemInfo.h"
 #include "prsystem.h"
 #include "prio.h"
 #include "mozilla/SSE.h"
 #include "mozilla/arm.h"
 #include "mozilla/Sprintf.h"
 
 #ifdef XP_WIN
+#include <comutil.h>
 #include <time.h>
+#include <iwscapi.h>
 #include <windows.h>
 #include <winioctl.h>
+#include <wscapi.h>
 #include "base/scoped_handle_win.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIObserverService.h"
 #include "nsWindowsHelpers.h"
 #endif
 
@@ -230,16 +233,139 @@ nsresult GetCountryCode(nsAString& aCoun
   }
 
   // numChars includes null terminator
   aCountryCode.Truncate(numChars - 1);
   return NS_OK;
 }
 
 } // namespace
+
+static HRESULT
+EnumWSCProductList(nsAString& aOutput, NotNull<IWSCProductList*> aProdList)
+{
+  MOZ_ASSERT(aOutput.IsEmpty());
+
+  LONG count;
+  HRESULT hr = aProdList->get_Count(&count);
+  if (FAILED(hr)) {
+    return hr;
+  }
+
+  for (LONG index = 0; index < count; ++index) {
+    RefPtr<IWscProduct> product;
+    hr = aProdList->get_Item(index, getter_AddRefs(product));
+    if (FAILED(hr)) {
+      return hr;
+    }
+
+    _bstr_t bName;
+    hr = product->get_ProductName(bName.GetAddress());
+    if (FAILED(hr)) {
+      return hr;
+    }
+
+    WSC_SECURITY_PRODUCT_STATE state;
+    hr = product->get_ProductState(&state);
+    if (FAILED(hr)) {
+      return hr;
+    }
+
+    // We only care about products that are active
+    if (state == WSC_SECURITY_PRODUCT_STATE_OFF ||
+        state == WSC_SECURITY_PRODUCT_STATE_SNOOZED) {
+      continue;
+    }
+
+    if (!aOutput.IsEmpty()) {
+      aOutput.AppendLiteral(u";");
+    }
+
+    nsDependentString name((wchar_t*)bName, bName.length());
+    aOutput.Append(name);
+  }
+
+  return S_OK;
+}
+
+static nsresult
+GetWindowsSecurityCenterInfo(nsAString& aAVInfo, nsAString& aAntiSpyInfo,
+                             nsAString& aFirewallInfo)
+{
+  aAVInfo.Truncate();
+  aAntiSpyInfo.Truncate();
+  aFirewallInfo.Truncate();
+
+  MOZ_ASSERT(XRE_IsParentProcess());
+  if (!XRE_IsParentProcess()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  const CLSID clsid = __uuidof(WSCProductList);
+  const IID iid = __uuidof(IWSCProductList);
+
+  // NB: A separate instance of IWSCProductList is needed for each distinct
+  // security provider type; MSDN says that we cannot reuse the same object
+  // and call Initialize() to pave over the previous data.
+
+  // 1. Antivirus
+  RefPtr<IWSCProductList> prodList;
+  HRESULT hr = ::CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, iid,
+                                  getter_AddRefs(prodList));
+  if (FAILED(hr)) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  hr = prodList->Initialize(WSC_SECURITY_PROVIDER_ANTIVIRUS);
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  hr = EnumWSCProductList(aAVInfo, WrapNotNull(prodList.get()));
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // 2. Anti-spyware
+  hr = ::CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, iid,
+                          getter_AddRefs(prodList));
+  if (FAILED(hr)) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  hr = prodList->Initialize(WSC_SECURITY_PROVIDER_ANTISPYWARE);
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  hr = EnumWSCProductList(aAntiSpyInfo, WrapNotNull(prodList.get()));
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // 3. Firewall
+  hr = ::CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, iid,
+                          getter_AddRefs(prodList));
+  if (FAILED(hr)) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  hr = prodList->Initialize(WSC_SECURITY_PROVIDER_FIREWALL);
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  hr = EnumWSCProductList(aFirewallInfo, WrapNotNull(prodList.get()));
+  if (FAILED(hr)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
 #endif // defined(XP_WIN)
 
 #ifdef XP_MACOSX
 static nsresult GetAppleModelId(nsAutoCString& aModelId)
 {
   size_t numChars = 0;
   size_t result = sysctlbyname("hw.model", nullptr, &numChars, nullptr, 0);
   if (result != 0 || !numChars) {
@@ -687,16 +813,44 @@ nsSystemInfo::Init()
 
   uint32_t installYear = 0;
   if (NS_SUCCEEDED(GetInstallYear(installYear))) {
     rv = SetPropertyAsUint32(NS_LITERAL_STRING("installYear"), installYear);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
+
+  nsAutoString avInfo, antiSpyInfo, firewallInfo;
+  if (NS_SUCCEEDED(GetWindowsSecurityCenterInfo(avInfo, antiSpyInfo,
+                                                firewallInfo))) {
+    if (!avInfo.IsEmpty()) {
+      rv = SetPropertyAsAString(NS_LITERAL_STRING("registeredAntiVirus"),
+                                avInfo);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+
+    if (!antiSpyInfo.IsEmpty()) {
+      rv = SetPropertyAsAString(NS_LITERAL_STRING("registeredAntiSpyware"),
+                                antiSpyInfo);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+
+    if (!firewallInfo.IsEmpty()) {
+      rv = SetPropertyAsAString(NS_LITERAL_STRING("registeredFirewall"),
+                                firewallInfo);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+  }
 #endif
 
 #if defined(XP_MACOSX)
   nsAutoString countryCode;
   if (NS_SUCCEEDED(GetSelectedCityInfo(countryCode))) {
     rv = SetPropertyAsAString(NS_LITERAL_STRING("countryCode"), countryCode);
     NS_ENSURE_SUCCESS(rv, rv);
   }