有没有办法在Windows 7上以编程方式激活Windows

时间:2016-10-21 11:49:04

标签: c windows winapi visual-c++

我正在开发一个需要在Windows 7 PC上激活Windows的项目。我使用Windows软件许可API编写了下面的代码。 MSDN说下面使用的三个函数需要Windows 8或Windows Server 2012,这表明这些函数在Windows 7上不可用。但是如果我打开了在我的C:\ Windows \ System32中的depends.exe中的slc.dll Windows 7机器,我做SLOpen和SLClose功能。但不是SLActivateProduct。

当我构建程序时,我收到链接器错误:

1>  main.cpp
1>main.obj : error LNK2019: unresolved external symbol _SLActivateProduct@28 referenced in function _main
1>activate_windows.exe : fatal error LNK1120: 1 unresolved externals

这在链接时如何工作?我认为这意味着slc.lib(见下面的代码)没有SLActivateProduct函数?

这个程序不需要用C语言编写,所以我可以从脚本中调用任何东西。任何人都知道在Windows 7上是否有任何方法可以做到这一点?它必须是一种可以通过运行脚本来启动的编程方式。

以下代码:

#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>

#include <stdio.h>

// lib to use
#pragma comment(lib, "slc.lib")

int main() {

  // slmgr.vbs has:
  // private const WindowsAppId = "55c92734-d682-4d71-983e-d6ec3f16059f"
    // Windows AppId for SLID:  {55c92734-d682-4d71-983e-d6ec3f16059f} - this is a GUID
    const SLID SLID_WINDOWS = {0x55c92734, 0xd682, 0x4d71, 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f};

    HSLC hslc;
    HRESULT hr = SLOpen(&hslc);
    if (SUCCEEDED(hr))
    {
        // try to activate windows
        hr = SLActivateProduct(hslc, &SLID_WINDOWS, 0, NULL, NULL, NULL, 0);
        switch(hr) {
        case E_INVALIDARG:
            printf("SLActivateProduct - one or more arguments are not valid\n");
            break;
        case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;
        case SL_E_PKEY_NOT_INSTALLED:
            printf("SLActivateProduct - The product key is not available\n");
            break;
        case SL_E_PRODUCT_SKU_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case S_OK:
            printf("SLActivateProduct - returned S_OK\n");
            break;
        default:
            printf("SLActivateProduct - unknown return code\n");
            break;
        }
        hr=SLClose(hslc);
    }
}

1 个答案:

答案 0 :(得分:2)

SLActivateProduct()在Windows 7上根本不可用,即使您可以在编译时链接到它(显然您不能,因为您的slc.lib版本缺少该引用)。

但是,您可以使用SLActivateProduct()在运行时动态加载GetProcAddress()。这将使您超越链接器错误(直到您更新开发环境)并允许您的代码至少在Windows 8及更高版本上运行。

仅供参考,sliddefs.h定义WINDOWS_SLID常量,因此您无需在代码中手动定义它。

尝试更像这样的事情:

#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>

#include <stdio.h>

// lib to use
#pragma comment(lib, "slc.lib")

// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE { 
  SL_ACTIVATION_TYPE_DEFAULT           = 0,
  SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY  = 1
} SL_ACTIVATION_TYPE;

typedef struct _tagSL_ACTIVATION_INFO_HEADER {
  DWORD              cbSize;
  SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/

typedef HRESULT WINAPI (*LPFN_SLActivateProduct)(HSLC, const SLID*, UINT, const PVOID, const SL_ACTIVATION_INFO_HEADER*, PCWSTR, WORD);

int main()
{
    LPFN_SLActivateProduct lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slc.dll")), "SLActivateProduct");
    if (!lpSLActivateProduct)
    {
        printf("SLActivateProduct - The product cannot be activated on this system\n");
        return 0;
    }

    HSLC hslc;

    HRESULT hr = SLOpen(&hslc);
    if (FAILED(hr))
    {
        printf("SLOpen - unknown return code 0x%08X\n", hr);
        return 0;
    }

    // try to activate windows
    hr = lpSLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
    switch(hr)
    {
        case E_INVALIDARG:
            printf("SLActivateProduct - one or more arguments are not valid\n");
            break;

        case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case SL_E_PKEY_NOT_INSTALLED:
            printf("SLActivateProduct - The product key is not available\n");
            break;

        case SL_E_PRODUCT_SKU_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case S_OK:
            printf("SLActivateProduct - returned S_OK\n");
            break;

        default:
            printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
            break;
    }

    hr = SLClose(hslc);

    return 0;
}

更新:毕竟,在Windows 7上可以看到SLActivateProduct() IS 。就像MSDN所说的那样,它只是位于slcext.dll而不是slc.dll。您可以相应地调整GetProcAddress()电话:

LPFN_SLActivateProduct lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slc.dll")), "SLActivateProduct");
if (!lpSLActivateProduct)
{
    // TODO: if SLCEXT.DLL is not already loaded, use LoadLibrary() instead of GetModuleHandle()...
    lpSLActivateProduct = (LPFN_SLActivateProduct) GetProcAddress(GetModuleHandle(TEXT("slcext.dll")), "SLActivateProduct");
}
if (!lpSLActivateProduct)
{
    printf("SLActivateProduct - The product cannot be activated on this system\n");
    return 0;
}

更新:如果稍后将更新到slc.lib不再缺少对SLActivateProduct()的引用的开发环境,则可以删除显式调用到GetProcAddress(),而是使用链接器的delay loaded DLLs feature。这允许您编写代码 - 如果您是静态链接,但随后链接器将注入特殊代码,在运行时第一次调用DLL函数时将为您调用GetProcAddress()。这将允许您在“静态”调用函数之前检查操作系统版本,允许您的应用程序仍然在较旧的Windows版本上运行,但仅在Windows 7 +上执行激活。

#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>

#include <stdio.h>

// lib to use
#pragma comment(lib, "slc.lib")

// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE { 
  SL_ACTIVATION_TYPE_DEFAULT           = 0,
  SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY  = 1
} SL_ACTIVATION_TYPE;

typedef struct _tagSL_ACTIVATION_INFO_HEADER {
  DWORD              cbSize;
  SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/

int main()
{
    OSVERSIONINFO osi = {0};
    osi.dwOSVersionInfoSize = sizeof(osi).
    GetVersionEx(&osi);

    if ((osi.dwMajorVersion < 6) || ((osi.dwMajorVersion == 6) && (dwMinorVersion < 1)))
    {
        printf("SLActivateProduct - The product cannot be activated on this system\n");
        return 0;
    }

    // alternatively:
    /*
    #include <VersionHelpers.h>

    if (!IsWindows7OrGreater())
    {
        printf("SLActivateProduct - The product cannot be activated on this system\n");
        return 0;
    }
    */

    HSLC hslc;

    HRESULT hr = SLOpen(&hslc);
    if (FAILED(hr))
    {
        printf("SLOpen - unknown return code 0x%08X\n", hr);
        return 0;
    }

    // try to activate windows
    hr = SLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
    switch(hr)
    {
        case E_INVALIDARG:
            printf("SLActivateProduct - one or more arguments are not valid\n");
            break;

        case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case SL_E_PKEY_NOT_INSTALLED:
            printf("SLActivateProduct - The product key is not available\n");
            break;

        case SL_E_PRODUCT_SKU_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case S_OK:
            printf("SLActivateProduct - returned S_OK\n");
            break;

        default:
            printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
            break;
    }

    hr = SLClose(hslc);

    return 0;
}

但是,要解决slc.dll vs slcext.dll问题,您可以使用delay-load failure hook检测SLActivateProduct()中何时找不到slc.dll,然后从slcext.dll加载它。

实际上,这是首选方案,因为它还提供了另一个机会 - 它允许您完全删除操作系统版本检查!如果在任一DLL中找不到SLActivateProduct(),则可以返回指向自定义用户定义函数的指针。当代码调用SLActivateProduct()时,如果它调用该函数,它只能返回E_NOTIMPLmain()可以在其switch语句中处理:

#include <Windows.h>
#include <Slpublic.h>
#include <slerror.h>
#include <sliddefs.h>

#include <stdio.h>
#include <delayimp.h> 

// lib to use
#pragma comment(lib, "slc.lib")

// if your version of Slpublic.h does not define these then uncomment this...
/*
typedef enum _tagSL_ACTIVATION_TYPE { 
  SL_ACTIVATION_TYPE_DEFAULT           = 0,
  SL_ACTIVATION_TYPE_ACTIVE_DIRECTORY  = 1
} SL_ACTIVATION_TYPE;

typedef struct _tagSL_ACTIVATION_INFO_HEADER {
  DWORD              cbSize;
  SL_ACTIVATION_TYPE type;
} SL_ACTIVATION_INFO_HEADER;
*/

HRESULT WINAPI Dummy_SLActivateProduct(HSLC, const SLID*, UINT, const PVOID, const SL_ACTIVATION_INFO_HEADER*, PCWSTR, WORD)
{
    return E_NOTIMPL;
}

HMODULE hSlcExtDll = NULL;

FARPROC WINAPI MyDliFailureHook(unsigned dliNotify, PDelayLoadInfo  pdli)
{
    if ((dliNotify == dliFailGetProc) && (pdli->dlp.fImportByName) && (lstrcmpA(pdli->dlp.szProcName, "SLActivateProduct") == 0))
    {
        hSlcExtDll = LoadLibrary("slcext.dll");
        FARPROC fn = GetProcAddress(hSlcExtDll, "SLActivateProduct");
        if (!fn) fn = &Dummy_SLActivateProduct;
        return fn;
    }

    return NULL;
}

int main()
{
    __pfnDliFailureHook2 = &MyDliFailureHook; 

    HSLC hslc;

    HRESULT hr = SLOpen(&hslc);
    if (FAILED(hr))
    {
        printf("SLOpen - unknown return code 0x%08X\n", hr);
        return 0;
    }

    // try to activate windows
    hr = SLActivateProduct(hslc, &WINDOWS_SLID, 0, NULL, NULL, NULL, 0);
    switch(hr)
    {
        case E_NOTIMPL:
            printf("SLActivateProduct - The product cannot be activated on this system\n");
            break;

        case E_INVALIDARG:
            printf("SLActivateProduct - one or more arguments are not valid\n");
            break;

        case SL_E_PUBLISHING_LICENSE_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case SL_E_PKEY_NOT_INSTALLED:
            printf("SLActivateProduct - The product key is not available\n");
            break;

        case SL_E_PRODUCT_SKU_NOT_INSTALLED:
            printf("SLActivateProduct - The license is not installed\n");
            break;

        case S_OK:
            printf("SLActivateProduct - returned S_OK\n");
            break;

        default:
            printf("SLActivateProduct - unknown return code 0x%08X\n", hr);
            break;
    }

    hr = SLClose(hslc);

    return 0;
}