Use slc.dll for activation status on Vista+

The WMI approach is incredibly slow, taking around ~3000ms in my unactivated
Vista and 7 VMs, and activated 7 Core 2 Duo laptop. Using slc.dll directly takes
1300-1500ms on Vista, and interestingly, exactly 31ms on both 7 installs. (Why
is Vista still so slow here?)
This commit is contained in:
Adam Demasi 2024-09-29 21:53:24 +09:30
parent 94cf287758
commit 7a35bf7b16
No known key found for this signature in database
GPG key ID: 5D3B26B3D58C7D91
2 changed files with 88 additions and 25 deletions

33
include/slpublic.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef GUID SLID;
typedef PVOID HSLC;
DEFINE_GUID(WINDOWS_SLID, 0x55c92734, 0xd682, 0x4d71, 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f);
typedef enum _tagSLLICENSINGSTATUS {
SL_LICENSING_STATUS_UNLICENSED,
SL_LICENSING_STATUS_LICENSED,
SL_LICENSING_STATUS_IN_GRACE_PERIOD,
SL_LICENSING_STATUS_NOTIFICATION,
SL_LICENSING_STATUS_LAST
} SLLICENSINGSTATUS;
typedef struct _tagSL_LICENSING_STATUS {
SLID SkuId;
SLLICENSINGSTATUS eStatus;
DWORD dwGraceTime;
DWORD dwTotalGraceDays;
HRESULT hrReason;
UINT64 qwValidityExpiration;
} SL_LICENSING_STATUS;
#ifdef __cplusplus
}
#endif

View file

@ -4,67 +4,97 @@
#include "WMI.h"
#include "VersionInfo.h"
#include "licdll.h"
#include <slpublic.h>
#define WindowsLicensingAppId L"55c92734-d682-4d71-983e-d6ec3f16059f"
typedef HRESULT (WINAPI *_SLOpen)(HSLC *);
typedef HRESULT (WINAPI *_SLGetLicensingStatusInformation)(HSLC, const SLID *, DWORD, DWORD, UINT *, SL_LICENSING_STATUS **);
typedef HRESULT (WINAPI *_SLClose)(HSLC);
enum {
LicenseStatusUnlicensed,
LicenseStatusLicensed,
LicenseStatusOOBGrace,
LicenseStatusOOTGrace,
LicenseStatusNonGenuineGrace,
LicenseStatusNotification,
LicenseStatusExtendedGrace
};
static _SLOpen $SLOpen;
static _SLClose $SLClose;
static _SLGetLicensingStatusInformation $SLGetLicensingStatusInformation;
static BOOL g_loadedLicenseStatus = FALSE;
static BOOL g_isActivated = TRUE;
PLUGIN_METHOD(IsActivated) {
PLUGIN_INIT();
// Activation is irrelevant prior to XP
if (!IsOSVersionOrLater(5, 1)) {
pushint(1);
if (g_loadedLicenseStatus || !IsOSVersionOrLater(5, 1)) {
pushint(g_isActivated);
return;
}
g_loadedLicenseStatus = TRUE;
if (IsOSVersionOrLater(6, 0)) {
// Vista+: Ask the Software Licensing Service
VARIANT value;
HRESULT hr = QueryWMIProperty(L"SELECT LicenseStatus FROM SoftwareLicensingProduct WHERE ApplicationID = '" WindowsLicensingAppId L"'", L"LicenseStatus", &value);
if (!SUCCEEDED(hr)) {
// Treat as success because we can't determine the status
if (!$SLOpen) {
HMODULE slc = LoadLibrary(L"slc.dll");
$SLOpen = (_SLOpen)GetProcAddress(slc, "SLOpen");
$SLClose = (_SLClose)GetProcAddress(slc, "SLClose");
$SLGetLicensingStatusInformation = (_SLGetLicensingStatusInformation)GetProcAddress(slc, "SLGetLicensingStatusInformation");
}
if (!$SLOpen || !$SLClose || !$SLGetLicensingStatusInformation) {
TRACE(L"Failed to load slc.dll");
pushint(1);
return;
}
pushint(value.intVal == LicenseStatusLicensed);
VariantClear(&value);
HSLC slc;
SL_LICENSING_STATUS *status;
UINT count;
HRESULT hr = $SLOpen(&slc);
if (!SUCCEEDED(hr)) {
goto end_slc;
}
hr = $SLGetLicensingStatusInformation(slc, &WINDOWS_SLID, 0, 0, &count, &status);
if (!SUCCEEDED(hr) || count == 0) {
goto end_slc;
}
g_isActivated = status->eStatus == SL_LICENSING_STATUS_LICENSED;
end_slc:
if (status) {
LocalFree(status);
}
if (slc) {
$SLClose(slc);
}
} else {
// XP: Use private API
ICOMLicenseAgent *agent;
HRESULT hr = CoCreateInstance(&CLSID_COMLicenseAgent, NULL, CLSCTX_INPROC_SERVER, &IID_ICOMLicenseAgent, (void **)&agent);
if (!SUCCEEDED(hr)) {
goto end;
TRACE(L"COMLicenseAgent load failed: %x", hr);
goto end_xp;
}
ULONG result;
hr = ICOMLicenseAgent_Initialize(agent, 0xC475, 3, NULL, &result);
if (!SUCCEEDED(hr) || result != 0) {
pushint(1);
goto end;
TRACE(L"COMLicenseAgent init failed: %x", hr);
goto end_xp;
}
ULONG wpaLeft, evalLeft;
hr = ICOMLicenseAgent_GetExpirationInfo(agent, &wpaLeft, &evalLeft);
if (!SUCCEEDED(hr)) {
pushint(1);
goto end;
TRACE(L"COMLicenseAgent GetExpirationInfo failed: %x", hr);
goto end_xp;
}
pushint(wpaLeft == MAXLONG);
g_isActivated = wpaLeft == MAXLONG;
end:
end_xp:
if (agent) {
ICOMLicenseAgent_Release(agent);
}
}
pushint(g_isActivated);
}