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 720641 fd4c9ec8b95df25186571e7551a06d389d98f9f5
parent 719729 8460d515739cc6609f985a9ece90711700818f06
child 720642 dfa65957af47853fe51dea97a1d481306d107471
child 720749 b4883101f3274df55b4f0331331e1e3ec6cf053c
push id95599
push useraklotz@mozilla.com
push dateMon, 15 Jan 2018 23:25:57 +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
@@ -84,16 +84,20 @@ EXPORTS += [
     'nsWeakPtr.h',
     'nsWeakReference.h',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     EXPORTS += [
         'nsWindowsHelpers.h',
     ]
+    if CONFIG['CC_TYPE'] != 'gcc':
+        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,25 +9,33 @@
 #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>
+#ifndef __MINGW32__
+#include <iwscapi.h>
+#endif // __MINGW32__
 #include <windows.h>
 #include <winioctl.h>
+#ifndef __MINGW32__
+#include <wscapi.h>
+#endif // __MINGW32__
 #include "base/scoped_handle_win.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIObserverService.h"
 #include "nsWindowsHelpers.h"
+
 #endif
 
 #ifdef XP_MACOSX
 #include "MacHelpers.h"
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
@@ -230,16 +238,118 @@ nsresult GetCountryCode(nsAString& aCoun
   }
 
   // numChars includes null terminator
   aCountryCode.Truncate(numChars - 1);
   return NS_OK;
 }
 
 } // namespace
+
+#ifndef __MINGW32__
+
+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;
+    }
+
+    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;
+    }
+
+    _bstr_t bName;
+    hr = product->get_ProductName(bName.GetAddress());
+    if (FAILED(hr)) {
+      return hr;
+    }
+
+    if (!aOutput.IsEmpty()) {
+      aOutput.AppendLiteral(u";");
+    }
+
+    aOutput.Append((wchar_t*)bName, bName.length());
+  }
+
+  return S_OK;
+}
+
+static nsresult
+GetWindowsSecurityCenterInfo(nsAString& aAVInfo, nsAString& aAntiSpyInfo,
+                             nsAString& aFirewallInfo)
+{
+  aAVInfo.Truncate();
+  aAntiSpyInfo.Truncate();
+  aFirewallInfo.Truncate();
+
+  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.
+
+  WSC_SECURITY_PROVIDER providerTypes[] = { WSC_SECURITY_PROVIDER_ANTIVIRUS,
+                                            WSC_SECURITY_PROVIDER_ANTISPYWARE,
+                                            WSC_SECURITY_PROVIDER_FIREWALL };
+
+  // Each output must match the corresponding entry in providerTypes.
+  nsAString* outputs[] = { &aAVInfo, &aAntiSpyInfo, &aFirewallInfo };
+
+  static_assert(ArrayLength(providerTypes) == ArrayLength(outputs),
+                "Length of providerTypes and outputs arrays must match");
+
+  for (uint32_t index = 0; index < ArrayLength(providerTypes); ++index) {
+    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(providerTypes[index]);
+    if (FAILED(hr)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    hr = EnumWSCProductList(*outputs[index], WrapNotNull(prodList.get()));
+    if (FAILED(hr)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
+  return NS_OK;
+}
+
+#endif // __MINGW32__
+
 #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 +797,46 @@ 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;
     }
   }
+
+#ifndef __MINGW32__
+  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 // __MINGW32__
 #endif
 
 #if defined(XP_MACOSX)
   nsAutoString countryCode;
   if (NS_SUCCEEDED(GetSelectedCityInfo(countryCode))) {
     rv = SetPropertyAsAString(NS_LITERAL_STRING("countryCode"), countryCode);
     NS_ENSURE_SUCCESS(rv, rv);
   }