SkinnyWhiteGuy Posted December 7, 2007 Share Posted December 7, 2007 (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 December 7, 2007 by SkinnyWhiteGuy Link to comment Share on other sites More sharing options...
MadBoy Posted December 7, 2007 Share Posted December 7, 2007 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) Link to comment Share on other sites More sharing options...
weaponx Posted December 7, 2007 Share Posted December 7, 2007 Maybe you should use SetACL from the command line or pure AutoIt SetACL!http://www.autoitscript.com/forum/index.ph...t=0#entry385049 Link to comment Share on other sites More sharing options...
martin Posted December 7, 2007 Share Posted December 7, 2007 DllCall('AdvAPI32.dll','Long','RegCloseKey','ptr',DllStructGetData($handle,1))Maybe it's this parameter which should be a pointer like thisDllCall('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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 7, 2007 Author Share Posted December 7, 2007 Maybe you should use SetACL from the command line or pure AutoIt SetACL!http://www.autoitscript.com/forum/index.ph...t=0#entry385049Like 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... Link to comment Share on other sites More sharing options...
martin Posted December 7, 2007 Share Posted December 7, 2007 @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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 7, 2007 Author Share Posted December 7, 2007 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. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted December 7, 2007 Moderators Share Posted December 7, 2007 (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 December 7, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 7, 2007 Author Share Posted December 7, 2007 Thanks for spotting that SmOke_N, but that still didn't solve the main issue I'm having (though that would have been nice...) Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
Valik Posted December 9, 2007 Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 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.... Link to comment Share on other sites More sharing options...
Valik Posted December 9, 2007 Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 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). Link to comment Share on other sites More sharing options...
Valik Posted December 9, 2007 Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 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: expandcollapse popupGlobal 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. Link to comment Share on other sites More sharing options...
Valik Posted December 9, 2007 Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
SkinnyWhiteGuy Posted December 9, 2007 Author Share Posted December 9, 2007 *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. Link to comment Share on other sites More sharing options...
Valik Posted December 9, 2007 Share Posted December 9, 2007 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. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now