Jump to content



Photo

Advanced API DllCall Errors


  • Please log in to reply
28 replies to this topic

#1 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 07 December 2007 - 12:56 PM

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.

AutoIt         
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.

Attached Files


Edited by SkinnyWhiteGuy, 07 December 2007 - 01:01 PM.






#2 MadBoy

MadBoy

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 829 posts

Posted 07 December 2007 - 12:58 PM

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.

AutoIt         
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.

#3 weaponx

weaponx

    I'm coming for blood, no code of conduct, no law.

  • MVPs
  • 5,366 posts

Posted 07 December 2007 - 01:24 PM

Maybe you should use SetACL from the command line or pure AutoIt SetACL!
http://www.autoitscript.com/forum/index.ph...t=0#entry385049

#4 martin

martin

    ~~\o/~~~/0\=¬''~~~

  • MVPs
  • 7,199 posts

Posted 07 December 2007 - 03:38 PM

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.

#5 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 07 December 2007 - 04:09 PM

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...

#6 martin

martin

    ~~\o/~~~/0\=¬''~~~

  • MVPs
  • 7,199 posts

Posted 07 December 2007 - 04:30 PM

@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.

#7 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 07 December 2007 - 06:27 PM

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.

#8 SmOke_N

SmOke_N

    It's not what you know ... It's what you can prove!

  • Moderators
  • 15,729 posts

Posted 07 December 2007 - 07:27 PM

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, 07 December 2007 - 07:31 PM.

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.


#9 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 07 December 2007 - 09:47 PM

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

#10 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 04:22 PM

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.

#11 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 09 December 2007 - 04:36 PM

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.

#12 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 04:54 PM

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....

#13 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 09 December 2007 - 05:05 PM

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.

#14 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 05:35 PM

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:

AutoIt         
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).

#15 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 09 December 2007 - 05:39 PM

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.

#16 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 07:00 PM

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.

#17 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 07:47 PM

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:

AutoIt         
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«ÊȦ¦Wš–X­².•×hŠÊ)zrŠ,Í=Ù#…M`©ÝrZ,z+kŠmm§$ëH‘穁ëmŠx®º+ê)ï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.

#18 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 09 December 2007 - 08:28 PM

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.

#19 SkinnyWhiteGuy

SkinnyWhiteGuy

    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 09 December 2007 - 09:13 PM

*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.

#20 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 09 December 2007 - 09:40 PM

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.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users