CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    I run the following code to get the video display timeout:

    Code:
    SYSTEM_POWER_POLICY spp = {0};
    DWORD dwRes = CallNtPowerInformation(SystemPowerPolicyAc, NULL, 0, &spp, sizeof(spp));
    if(dwRes != STATUS_SUCCESS)
    {
        //Error 0xC000000D or STATUS_INVALID_PARAMETER
        //An invalid parameter was passed to a service or function.
    }
    else
    {
        int nTimeout = spp.VideoTimeout;
    }
    It works on my Windows 7 but then on another laptop running Windows 7 as well it returns the error code STATUS_INVALID_PARAMETER. Does anyone have any idea why? And how to remedy it?

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    According to MSDN:
    Return value

    If the function succeeds, the return value is STATUS_SUCCESS.

    If the function fails, the return value can be one the following status codes.
    Status Meaning

    STATUS_BUFFER_TOO_SMALL

    The output buffer is of insufficient size to contain the data to be returned.

    STATUS_ACCESS_DENIED

    The caller had insufficient access rights to perform the requested action.
    So, is it dwRes having STATUS_INVALID_PARAMETER value?
    Best regards,
    Igor

  3. #3
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Yes, it is 0xC000000D. I found at this page that it is STATUS_INVALID_PARAMETER. Doing various tests I learned that if I change the size of the struct just one byte off (passed in the last parameter) the API does return 0xC000000D on my system that it normally works on. The question is why is not documented? And why does it work differently on the same OS but on different machines? Igor, I am really trying to hold myself down and refrain from writing it out what I think of Microsoft and their API writing skills.... In my development process on their platform I seriously spend 50% of the time trying to find a workaround for an API that doesn't do what it's supposed to, is poorly documented, or completely fails on some other version of their OS ...

    Although now I'm starting to believe that maybe this kernel API relegates control directly to a (video) device driver and that is why I'm getting such different results. Any ideas???

  4. #4
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Igor, I am really trying to hold myself down and refrain from writing it out what I think of Microsoft and their API writing skills.... In my development process on their platform I seriously spend 50% of the time trying to find a workaround for an API that doesn't do what it's supposed to, is poorly documented, or completely fails on some other version of their OS ...
    Well, I have to agree with you that the quality of MSDN articles on modern APIs evidently degrades compared to the former MSDN what it used to be years ago. There's one member there in SYSTEM_POWER_POLICY structure called Revision which is practically undocumented, but somehow having the structure size to depend on, I suspect. Unfortunately I was not able to find anything related to this in the internet.

    And no, I cannot see any relation between this API and video driver. In fact it should end somewhere in reading from registry, where only access rights and buffer size really matter, nothing more than that, exactly like it can be deduced from the article section.
    Best regards,
    Igor

  5. #5
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Thanks for trying, Igor. Yes, it beats me too. So I'll stop wasting more time on this and leave it at this. If anyone else gets to the bottom of this, please post it here...


    PS. On the sidenote, I'm not really privy with the new Windows 8 RT programming. Are they still using the same kernel model for those Windows 8 apps (former Metro apps) or is it a totally redesigned kernel for ARM that has no notion of WinAPIs?

  6. #6
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    What happens if you use SystemPowerPolicyCurrent? If you operate only on Ac, would that be an option?

  7. #7
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Unfortunately this doesn't happen on the machine I have easy access to. But if I have a chance to get access to it again, I'll try SystemPowerPolicyCurrent...

  8. #8
    Join Date
    Nov 2003
    Posts
    1,902

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    You could try the power scheme route:
    Code:
        UINT scheme;
        if (!GetActivePwrScheme(&scheme))
        {
            DWORD le = GetLastError();
            if (!le)
                return ERROR_UNHANDLED_ERROR;
            return le;
        }//if
    
        POWER_POLICY pp;
        if (!ReadPwrScheme(scheme, &pp))
        {
            DWORD le = GetLastError();
            if (!le)
                return ERROR_UNHANDLED_ERROR;
            return le;
        }//if
    
        pp.user.VideoTimeoutAc
        pp.user.VideoTimeoutDc
    Or you could try calling GetCurrentPowerPolicies().

    gg

  9. #9
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Thanks. Unfortunately, I can't use GetActivePwrScheme() because the code is called from a local service and that API has to be called from a user-mode code. GetCurrentPowerPolicies() works, but then the second task I need to address is changing the video timeout, but the SetCurrentPowerPolicies() API is mysteriously absent.

  10. #10
    Join Date
    Nov 2003
    Posts
    1,902

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    I know and use two methods to set the monitor timeout (in XP):
    1) Temporarily via CallNtPowerInformation(SystemPowerPolicyAc,...) (but if you look at it in control panel, it will become permanent).
    2) Permanently via power scheme API's.

    Looks like the power scheme API changed in Vista to use the PowerXXX functions (like PowerGetActiveScheme). I didn't see anything that suggested they couldn't be used from a service (or non-desktop session).

    gg

  11. #11
    Join Date
    Feb 2009
    Location
    Portland, OR
    Posts
    1,488

    Re: CallNtPowerInformation API fails with error code STATUS_INVALID_PARAMETER

    Thanks again, Codeplug. I tried everything I could on my Windows 7 and here's the results:
    (All concerning local service application)

    1. One can get global power policy settings via a call to GetCurrentPowerPolicies().

    2. To apply or change a policy setting (for either AC or DC) one needs to have a policy ID (which is an integer ID in an older version of API and a GUID since Vista.) To get that ID one needs to call an API such as GetActivePwrScheme() or PowerGetActiveScheme() for newer APIs, both of which return FALSE when called from a service. (Confirmed that.) My next idea was to enumerate all available power schemes by calling EnumPwrSchemes() or newer version PowerEnumerate() but both again failed without producing any results.

    3. I can't try setting a power scheme because I can't get an ID of an existing scheme to do that.

    4. The above might work from a local service running on Windows XP, since services used to run in a user session 0. But it obviously has to work under later OS as well, so I didn't try that approach ...


    So we arrive at a classic catch-22: To get a power scheme ID someone's code has to run from a user-mode code (not even elevated), but to set it, one's code has to run elevated (and possibly OK from a local service.)

    My next thought was go an extra mile and spawn a user-mode process from my local service, that will do all the power scheme changes (however complex and unnecessary this move can be) but then what would I do if there're no users logged on to the workstation at the time (when the service starts up)?

    So obviously someone at Microsoft didn't think all this through. If you look at the documentation to the new (Vista) power schemes, it is very scarce and some parameters don't even have links or further explanation to how to get to them.

    So my god-send solution was the CallNtPowerInformation API that seemed to solve the issue of reading/writing a power setting without affecting global power schemes (which is an added bonus -- or in other words -- it was not persistent), but evidently not every computer supports it. Again, the error code I quoted above came from a client's computer that I don't have access to. I ran several tests on that machine (through his help) and all confirmed that error code that is not even documented...

    So I'm leaving it at that. There's nothing else I can do. (Which is OK for Windows.)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured