Sign in to follow this  
Followers 0
SkinnyWhiteGuy

Advanced API DllCall Errors

29 posts in this topic

#1 ·  Posted (edited)

I am trying to learn a little more about Windows system calls, and some of the more advanced things I can do with them. In doing that, I've run into a snag, and I was wondering if anyone could help me out. I am trying to change Permissions on a few Registry Keys. I have just about everything working, but right at the end, it errors out, stating I have an "invalid parameter" (ERROR_INVALID_PARAMETER). If have checked those parameters (3 of them) every way I know how, I double check, recheck again, and still nothing.

The call that's failing is RegSetKeySecurity(). It takes in a handle of an already open registry key, a dword stating what your going to Set, and then the Security Descriptor to apply to that key. After I create the Security Descriptor, I test if it is ok with IsValidSecurityDescriptor, and it passes that check, so I know it should be ok. I copied my registry opening call above it (RegOpenKeyEx()) to another file, read other keys, counted subkeys, closed the key, etc... And the middle parameter, for all my searching, is just 4. But, even with all this checking and knowing things should be right, it still errors out with the invalid parameter.

I'm still stumped. I'm going to post here the code that's erroring out specifically, and attach the entire script too. I hope someone else can figure this out, I'm just stumped.

Local $handle = DllStructCreate ("ptr")
$err = DllCall("Advapi32.dll", "long", "RegOpenKeyEx", _
    "ptr", 0x80000002, _
    "str", $npath, _ ; string containing path to Registry Key to be opened
    "dword", 0, _
    "long", $WRITE_DAC, _
    "ptr", DllStructGetPtr ($handle))
If $err[0] <> 0 Then
    ConsoleWrite('RegOpenKeyEx Failed with error ' & $err[0] & @CRLF)
    MsgBox(0,'Error','RegOpenKeyEx Failed with error ' & $err[0])
    Exit
EndIf
$err = DllCall("Advapi32.dll","long","RegSetKeySecurity", _
        "ptr", DllStructGetData($handle,1), _
        "dword", $WRITE_DAC, _
        "ptr", DllStructGetPtr($sdout))
If $err[0] <> 0 Then
    ConsoleWrite('RegSetKeySecurity Failed with error ' & $err[0] & @CRLF)
    DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))
    MsgBox(0,'Error','RegSetKeySecurity Failed with error ' & $err[0])
    Exit
EndIf

DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))

Thank anyone for any and all help they can give me. Like I said, this is just for my learning, and I do know of other solutions (mscacls.exe, the COM object that ptrex has shown), but none of those solutions can be easily installed/used, plus they use these same methods to do what they do, so I might as well cut out the middle man. Not to mention I don't want to have to install any more files, I like one file that can do everything I need it too, and I'm so close to that.

regmodifytest.au3

Edited by SkinnyWhiteGuy

Share this post


Link to post
Share on other sites



I am trying to learn a little more about Windows system calls, and some of the more advanced things I can do with them. In doing that, I've run into a snag, and I was wondering if anyone could help me out. I am trying to change Permissions on a few Registry Keys. I have just about everything working, but right at the end, it errors out, stating I have an "invalid parameter" (ERROR_INVALID_PARAMETER). If have checked those parameters (3 of them) every way I know how, I double check, recheck again, and still nothing.

The call that's failing is RegSetKeySecurity(). It takes in a handle of an already open registry key, a dword stating what your going to Set, and then the Security Descriptor to apply to that key. After I create the Security Descriptor, I test if it is ok with IsValidSecurityDescriptor, and it passes that check, so I know it should be ok. I copied my registry opening call above it (RegOpenKeyEx()) to another file, read other keys, counted subkeys, closed the key, etc... And the middle parameter, for all my searching, is just 4. But, even with all this checking and knowing things should be right, it still errors out with the invalid parameter.

I'm still stumped. I'm going to post here the code that's erroring out specifically, and attach the entire script too. I hope someone else can figure this out, I'm just stumped.

Local $handle = DllStructCreate ("ptr")
$err = DllCall("Advapi32.dll", "long", "RegOpenKeyEx", _
    "ptr", 0x80000002, _
    "str", $npath, _ ; string containing path to Registry Key to be opened
    "dword", 0, _
    "long", $WRITE_DAC, _
    "ptr", DllStructGetPtr ($handle))
If $err[0] <> 0 Then
    ConsoleWrite('RegOpenKeyEx Failed with error ' & $err[0] & @CRLF)
    MsgBox(0,'Error','RegOpenKeyEx Failed with error ' & $err[0])
    Exit
EndIf
$err = DllCall("Advapi32.dll","long","RegSetKeySecurity", _
        "ptr", DllStructGetData($handle,1), _
        "dword", $WRITE_DAC, _
        "ptr", DllStructGetPtr($sdout))
If $err[0] <> 0 Then
    ConsoleWrite('RegSetKeySecurity Failed with error ' & $err[0] & @CRLF)
    DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))
    MsgBox(0,'Error','RegSetKeySecurity Failed with error ' & $err[0])
    Exit
EndIf

DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))

Thank anyone for any and all help they can give me. Like I said, this is just for my learning, and I do know of other solutions (mscacls.exe, the COM object that ptrex has shown), but none of those solutions can be easily installed/used, plus they use these same methods to do what they do, so I might as well cut out the middle man. Not to mention I don't want to have to install any more files, I like one file that can do everything I need it too, and I'm so close to that.

When you get it working please share this :) I would love to have a way to set permissions in registry (but on files aswell) that doesn't use external files.

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites

DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))

Maybe it's this parameter which should be a pointer like this

DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetPtr($handle,1))


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Maybe you should use SetACL from the command line or pure AutoIt SetACL!

http://www.autoitscript.com/forum/index.ph...t=0#entry385049

Like I said, this is just for my learning, and I do know of other solutions (mscacls.exe, the COM object that ptrex has shown), but none of those solutions can be easily installed/used, plus they use these same methods to do what they do, so I might as well cut out the middle man. Not to mention I don't want to have to install any more files, I like one file that can do everything I need it too, and I'm so close to that.

@martin:

Tried that, still no love, and now another thing with a similar call isn't wanting to give me all my data back. I'm getting no love from these Reg Functions, I tell you...

Share this post


Link to post
Share on other sites

@martin:

Tried that, still no love, and now another thing with a similar call isn't wanting to give me all my data back. I'm getting no love from these Reg Functions, I tell you...

What version of AutoIt are you using?

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Latest Production, 3.2.10.0. I did get my other problem fixed (wasn't opening the key with the right requested permissions), so I no longer have 2 problems.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Where is the struct for this ptr? "ptr", DllStructGetPtr($sdout))

Edit:

NVM, I see the .au3.

Edit2:

In the .au3 file...

For $i = 1 To $apath[0]
    $npath &= $apath

$apath is an array, but you're treating it like a string.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Thanks for spotting that SmOke_N, but that still didn't solve the main issue I'm having (though that would have been nice...)

Share this post


Link to post
Share on other sites

Well, I changed the middle part of the call to RegSetKeySecurity to the following, and got a little further:

$test = DllStructCreate("dword")
DllStructSetData($test,1,$DACL_SECURITY_INFORMATION)
    
$err = DllCall("Advapi32.dll","long","RegSetKeySecurity", _
        "ptr", DllStructGetData($handle,1), _
        "dword", DllStructGetPtr($test), _
        "ptr", DllStructGetPtr($sdout))
If $err[0] <> 0 Then
    ConsoleWrite('RegSetKeySecurity Failed with error ' & $err[0] & @CRLF)
    DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))
    MsgBox(0,'Error','RegSetKeySecurity Failed with error ' & $err[0])
    Exit
EndIf

This gives error 1314 with all the other code the same, which according to MSDN is ERROR_PRIVILEGE_NOT_HELD, A required privilege is not held by the client. I'm still researching that out, but I may need to use some Security functions relating to Tokens on the thread and all.

Share this post


Link to post
Share on other sites

You don't need a DllStruct to hold a DWORD. Not only that, you pass the pointer of the structure, not the value. This is just plain wrong on 32-bit Windows and possibly a crash on 64-bit Windows.

Share this post


Link to post
Share on other sites

Well, that's what I thought too, but just using either my $DACL_SECURITY_INFORMATION or it's value according to my Dev-C++ files (4), instead of the above code, I get error 87, invalid parameter. Passing in the struct pointer as above seemingly gets me further (or at least a different error code), and according to this link, (which is for a different API call, I know) it might be a simple matter of adding a privilege (simple, hah!).

Oh, and I know I didn't mention this before, but I am working in a x64 environment, no crashes "before" that error, but afterwards, I always get a crash of AutoIt. I'm willing to bet it's due to some variable I use before that code that I'm not properly freeing. If anyone has a helpful hint as to which one that might be, I'd be very grateful.

One step forward, two steps backward....

Share this post


Link to post
Share on other sites

Your variable $handle should be using the "hwnd"/"hwnd*" type as appropriate (HWND is now not specific for HWND's but handles in general). Don't over-complicate the code by using DllStruct stuff when DllCall()'s basic types will work.

Share this post


Link to post
Share on other sites

Thanks for the heads up on the hwnd info. I can't seem to get hwnd* working (probably my own fault too), all I really managed to do was to replace all "ptr" with "hwnd", and it still does the same thing as before (at least it didn't crash earlier), and I saved the resulting info from the RegKeyOpenEx to a $shandle variable. like this:

Local $handle = DllStructCreate ("hwnd")
$err = DllCall("Advapi32.dll", "long", "RegOpenKeyEx", _
    "hwnd", $HKEY_LOCAL_MACHINE, _
    "str", $npath, _
    "dword", 0, _
    "long", $WRITE_DAC, _
    "hwnd", DllStructGetPtr ($handle))
If $err[0] <> 0 Then
    ConsoleWrite('RegOpenKeyEx Failed with error ' & $err[0] & @CRLF)
    MsgBox(0,'Error','RegOpenKeyEx Failed with error ' & $err[0])
    Exit
EndIf
Local $shandle = DllStructGetData($handle,1)
    
ConsoleWrite("I am here" & @CRLF)
$test = DllStructCreate("dword")
DllStructSetData($test,1,$DACL_SECURITY_INFORMATION)

$err = DllCall("Advapi32.dll","long","RegSetKeySecurity", _
        "hwnd", $shandle, _
        "dword", DllStructGetPtr($test), _
        "ptr", DllStructGetPtr($sdout))
If $err[0] <> 0 Then
    ConsoleWrite('RegSetKeySecurity Failed with error ' & $err[0] & @CRLF)
    DllCall('AdvAPI32.dll','Long','RegCloseKey','hwnd',$shandle)
    MsgBox(0,'Error','RegSetKeySecurity Failed with error ' & $err[0])
    Exit
EndIf
    
ConsoleWrite("I am here" & @CRLF)

DllCall('AdvAPI32.dll','Long','RegCloseKey','hwnd',$shandle)

I tried every combination of hwnd* in there I could think of, removed the DllStruct stuff, and all I usually got was ERROR_INVALID_HANDLE (6), The handle is invalid. If not that error, I just got the same two as before, invalid parameter, or privilege not held by client. So, I'm still trying, but with more correct syntax (at least in areas).

Share this post


Link to post
Share on other sites

Stop using DllStruct. YOU DO NOT NEED IT. That's what the last sentence of my previous post is trying to get you to understand.

Share this post


Link to post
Share on other sites

Thanks for that extra WHACK to my head, I finally got it working with the HWND* and no DllStruct. I thought I had tried everything to do that, but I guess I was wrong. I'm still getting error 87 with just passing $DACL_SECURITY_INFORMATION into RegSetKeySecurity, and error 1314 when passing in a pointer to the struct above, so I'm still having the same issue.

Thanks for your help.

Share this post


Link to post
Share on other sites

Upon further testing, I don't think removing all the DllStruct stuff had the desired affect at all.

To test this, I made this simple example script:

Global Const $WRITE_DAC = 0x40000 ; 0x40000L
    $npath = "SOFTWARE"

    Local $handle
    $err = DllCall("Advapi32.dll", "long", "RegOpenKeyEx", _
        "hwnd", 0x80000002, _
        "str", $npath, _
        "dword", 0, _
        "long", $WRITE_DAC, _
        "hwnd*", $handle)
    If $err[0] <> 0 Then
        ConsoleWrite('RegOpenKeyEx Failed with error ' & $err[0] & @CRLF)
        MsgBox(0,'Error','RegOpenKeyEx Failed with error ' & $err[0])
        Exit
    EndIf
    ConsoleWrite("I am here" & @CRLF)
    $err = DllCall('AdvAPI32.dll','Long','RegCloseKey','hwnd*',$handle)
    If $err[0] <> 0 Then
        ConsoleWrite('RegCloseKey Failed with error ' & $err[0] & @CRLF)
        MsgBox(0,'Error','RegCloseKey Failed with error ' & $err[0])
        Exit
    EndIf
    ConsoleWrite("I am here" & @CRLF)oÝ÷ ÙW«ÊȦ¦WX­².×hÊ)zr,Í=Ù#M`©ÝrZ,z+kmm§$ëHç©ëmx®º+ê)ïjX©Ýàèx"¶X¤zØb±«­¢+Ù±½°
½¹ÍÐÀÌØí]I%Q}ôÁàÐÀÀÀÀìÁàÐÀÀÀÁ0($ÀÌØí¹ÁÑ ôÅÕ½ÐíM
UI%QdÅÕ½Ðì((%1½°ÀÌØí¡¹±ô±±MÑÉÕÑ
ÉÑ ÅÕ½Ðí¡Ý¹ÅÕ½Ðì¤($ÀÌØíÉÈô±±
±° ÅÕ½ÐíÙÁ¤Ìȹ±°ÅÕ½Ðì°ÅÕ½Ðí±½¹ÅÕ½Ðì°ÅÕ½ÐíI=Á¹-åàÅÕ½Ðì°|($$ÅÕ½Ðí¡Ý¹ÅÕ½Ðì°ÁààÀÀÀÀÀÀÈ°|($$ÅÕ½ÐíÍÑÈÅÕ½Ðì°ÀÌØí¹ÁÑ °|($$ÅÕ½ÐíݽÉÅÕ½Ðì°À°|($$ÅÕ½Ðí±½¹ÅÕ½Ðì°ÀÌØí]I%Q}°|($$ÅÕ½ÐíÁÑÈÅÕ½Ðì°±±MÑÉÕÑÑAÑÈ ÀÌØí¡¹±¤¤(%%ÀÌØíÉÉlÁt±ÐìÐìÀQ¡¸($%
½¹Í½±]É¥Ñ ÌäíI=Á¹-åà¥±Ý¥Ñ ÉɽÈÌäìµÀìÀÌØíÉÉlÁtµÀì
I1¤($%5Í  ½à À°ÌäíÉɽÈÌäì°ÌäíI=Á¹-åà¥±Ý¥Ñ ÉɽÈÌäìµÀìÀÌØíÉÉlÁt¤($%á¥Ð(%¹%(%
½¹Í½±]É¥Ñ ÅÕ½Ðí$´¡ÉÅÕ½ÐìµÀì
I1¤($ÀÌØíÉÈô±±
±° ÌäíÙA$Ìȹ±°Ìäì°Ìäí1½¹Ìäì°ÌäíI
±½Í-äÌäì°Ìäí¡Ý¹Ìäì±±±MÑÉÕÑÑÑ ÀÌØí¡¹±°Ä¤¤(%%ÀÌØíÉÉlÁt±ÐìÐìÀQ¡¸($%
½¹Í½±]É¥Ñ ÌäíI
±½Í-ä¥±Ý¥Ñ ÉɽÈÌäìµÀìÀÌØíÉÉlÁtµÀì
I1¤($%5Í  ½à À°ÌäíÉɽÈÌäì°ÌäíI
±½Í-ä¥±Ý¥Ñ ÉɽÈÌäìµÀìÀÌØíÉÉlÁt¤($%á¥Ð(%¹%(%
½¹Í½±]É¥Ñ ÅÕ½Ðí$´¡ÉÅÕ½ÐìµÀì
I1¤

I get no errors, it works and everything. I'm not sure if this means there is a bug with using * as pointers, or if I'm just doing something bass-ackwards, but it doesn't seem to want to work the way it's supposed to.

Share this post


Link to post
Share on other sites

There are so many things wrong with the first example.

Global Const $WRITE_DAC = 0x40000; 0x40000L
    $npath = "SOFTWARE"

    Local $handle
    $err = DllCall("Advapi32.dll", "long", "RegOpenKeyEx", _
        "hwnd", 0x80000002, _

Don't use magic numbers. This isn't a bug but it's just poor coding.

"str", $npath, _
        "dword", 0, _
        "long", $WRITE_DAC, _
        "hwnd*", $handle)

Re-read the documentation for DllCall() again. Parameters are not modified by reference. Passing $handle here does NOTHING. You have to retrieve the value from the array returned by DllCall(). Throughout the entire life of your script, $handle has the initial value AutoIt gives it.

$err = DllCall('AdvAPI32.dll','Long','RegCloseKey','hwnd*',$handle)

This is wrong. RegCloseKey() expects a handle, not a pointer to a handle.

Share this post


Link to post
Share on other sites

*WHACKS head into keyboad repeatedly for personal stupidity*

Thanks for reminding me that the returning array has the results I've been needing. I try not to use "magic numbers" either (attached code to first post here shows the same number as a variable). The test code I posted for that is now working, but my initial code fixed up still doesn't work, it's still either error 87 or 1314. Back to the drawing board.

Share this post


Link to post
Share on other sites

Increase what privileges you're trying to open the key with. Go with the STANDARD_RIGHTS_REQUIRED, if it doesn't work try STANDARD_RIGHTS_ALL and failing that go for KEY_ALL_ACCESS. Once you find which blanket rights access you need, look up the individual privileges the blanket provides and start trying to narrow it back down to only the rights you need to do what you want.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0