Win32Shutdown method in WMI - C++

Viewed 73

I'm trying to call the Win32Shutdown method of Win32_OperatingSystem to cause a logout or reboot.

I'm using WMI to get Win32_OperatingSystem then I want to call its Win32Shutdown method. In this program,Win32_OperatingSystem class object uses IWbemServices::GetObject.

The problem,is that having obtained the IWbemClassObject, a call to IWbemClassObject::GetMethod for the Win32Shutdown method always returns 0x8004101e("Illegal Operation").

Did I set the SeShutdownPrivilege (SE_SHUTDOWN_NAME) correctly ?

Privileges Code:

BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    ){
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if (!LookupPrivilegeValue(NULL,            // lookup privilege on local system
                              lpszPrivilege,   // privilege to lookup
                              &luid )) {       // receives LUID of privilege
            printf("LookupPrivilegeValue error: %u for string '%s'\n",
                   GetLastError(), lpszPrivilege);
            return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege) {
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    } else {
            tp.Privileges[0].Attributes = 0;
    }

    // Enable the privilege or disable all privileges.
    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
                               (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) {
            DWORD err = GetLastError();
            printf("AdjustTokenPrivileges error: %u\n", err);
            return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
            printf("The token does not have the specified privilege. \n");
            return FALSE;
    }

    return TRUE;
}

WMI Code:

Connection has been established.

     cout << "Attempting to call Win32Shutdown using IWbemServices::GetObject..." << endl;
    BSTR MethodName = SysAllocString(L"Win32Shutdown");
    BSTR ClassName = SysAllocString(L"Win32_OperatingSystem=@"); // =@: Singleton

    IWbemClassObject* pClass = NULL;
    hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
    if (FAILED (hres)) {
            printf("GetObject Error: %u\n", GetLastError());
            return 1;
    }

    IWbemClassObject* pInParamsDefinition = NULL;
    hres = pClass->GetMethod(MethodName, 0,
                             &pInParamsDefinition, NULL);
    switch (hres) {
    case WBEM_S_NO_ERROR:
            cout << "_S_NO_ERROR: " << hex << hres << endl;
            break;
    case WBEM_E_NOT_FOUND:
            cout << "_E_NOT_FOUND: " << hex << hres << endl;
            break;
    case WBEM_E_OUT_OF_MEMORY:
            cout << "_E_OUT_OF_MEMORY: "  << hex << hres << endl;
            break;
    case 0x8004101e:
            wcout << "pClass->GetMethod returned 0x8004101e "
                  << "(Illegal operation, apparently) for '"
                  << MethodName << "'" << endl;
            break;
    default:
            cout << "unknown: "  << hex << hres << endl;
            break;
    }

    if (FAILED (hres)) {
            return 1;
    }

    IWbemClassObject* pClassInstance = NULL;
    hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
    if (FAILED (hres)) {
            printf("SpawnInstance Error: %u\n", GetLastError());
            return 1;
    }

    // Create the values for the in parameters
    VARIANT varFlags;
    VariantInit (&varFlags);
    varFlags.vt = VT_I4; // Seems to work...
    varFlags.lVal = 0x5;
    varFlags.intVal = 0x5;
    varFlags.iVal = 0x5;

    // Store the value for the in parameters
    hres = pClassInstance->Put(L"Flags", 0, &varFlags, 0);
    if (FAILED (hres)) {
            ShowPutError (hres);
            return 1;
    }
    wprintf(L"The flags: %d\n", V_INT(&varFlags));
    //reserved arg - Is this neccessary ?
    VARIANT varFlags2;
    varFlags2.vt = VT_I4;
    varFlags2.lVal = 0x0;
    hres = pClassInstance->Put(L"Reserved", 0, &varFlags2, 0);
    if (FAILED (hres)) {
            ShowPutError (hres);
            return 1;
    }
    IWbemClassObject* pOutParams = NULL;

    hres = pSvc->ExecMethod(ClassName, MethodName, 0,
                            NULL, pClassInstance, &pOutParams, NULL);
    if (FAILED(hres)) {
            // See http://msdn.microsoft.com/en-us/library/cc250949%28v=prot.10%29.aspx
            // for returned codes. This Windows error handling is ghastly.
            cout << "ExecMethod error: " << hex << hres << endl;
            return 1;
    }

    // Cleanup
    // ========
    pSvc->Release();
    pLoc->Release();
    pClass->Release();
    CoUninitialize();
1 Answers
Related