Sign in to follow this  
Followers 0
SSzretter

how to create tagSECURITY_ATTRIBUTES (security identifier) for _WinAPI calls?

20 posts in this topic

Specifically, I am using the _WinAPI_CreateFileMapping call, and want to make sure a different user on the same machine is able to receive messages via _WinAPI_OpenFileMapping.     I am receiving errors when I try to open the file mapping (invalid handle error #6).      I am thinking it's because of the security settings.    I found this post, which talks about file mappings and allowing cross user access.    The solution was to create a NULL security identifier (not passing null, but passing a valid security identifier, containing null):

SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.NullSid, null);

The question is, how do I create this in AutoIT, and pass it in to _WinAPI_CreateFileMapping ?

Thanks!

Share this post


Link to post
Share on other sites



 

Update -- here is some of the code I am using / my attempt to create the security object:

   Sending script (running as local user):

        Local $sid = _Security__StringSidToSid("S-1-0")     ; also tried S-1-1

        $hMapping = _WinAPI_CreateFileMapping(-1, 2048, 'MyFileMapping',0x0004,$sid)  ;it seems to accept the sid

         DllStructSetData($tData, 1, "IDL")  ; if($hMapping)  send the message...

 

   In the receiving service script (running as system account):

            $hMapping = _WinAPI_OpenFileMapping('MyFileMapping') ; also tried passing read only ,0x0004 - in any case, returns 0x0000 file handle / 0 error 0 extended!

                                                 ;  at one point I was receiving a 1305 error code but I cant seem to duplicate that anymore

            ;  if($hMapping) ... this is how I am trying to receive the message:

             $pAddress = _WinAPI_MapViewOfFile($hMapping)
              $tData = DllStructCreate('wchar[1024]', $pAddress)
              $Text = DllStructGetData($tData, 1)
              DllStructSetData($tData, 1, '')
 

Share this post


Link to post
Share on other sites
 Thanks, so I tried this:
   Local Const $tagSTRUCT1 = "struct;int var1;byte var2;endstruct"
   Local $sid = DllStructCreate($tagSTRUCT1)
   DllStructSetData($sid, "var1", 0) ; public enum WellKnownSidType {  NullSid  = 0
   DllStructSetData($sid, "var1", null)
 
I also tried it without the var 2 / null.
 
While it seems to accept this on the sending side, the receiving side is still the same - I cant get a valid handle reference when calling _WinAPI_OpenFileMapping

Share this post


Link to post
Share on other sites

So you are just ignoring what I posted?

 

Isn't your suggestion in what I last posted?

Share this post


Link to post
Share on other sites

Ok, yes, it is there for 'all' to see, but I will try:

You said DllStructCreate($tagSECURITY_ATTRIBUTES)

$tagSECURITY_ATTRIBUTES is not defined, so I did a little research and in my post (Today, 08:22 PM)   I pasted some code which I believe clearly shows your DllStructCreate():

    Local Const $tagSTRUCT1 = "struct;int var1;byte var2;endstruct"
    Local $sid = DllStructCreate($tagSTRUCT1)
 
SO, maybe I am missing something else you posted (or maybe I just missed the point)?     If so, I would greatly appreciate clarification.
Thanks for your time!

Share this post


Link to post
Share on other sites

Actually, no, I was not, so I added that.  I have these 3 includes related to WinAPI now:

#include <WinAPIFiles.au3>
#include <WinAPI.au3>
#include <WinApiEx.au3>
 
I tried the 3 different variations above and my receiver is still not getting a valid handle for _WinAPI_OpenFileMapping.    The sender is supposedly sending though (no error at least).
 
Also, just to be sure, I added my receiver code inside my sender (using different variable names).   I confirmed that I am in fact able to receive the sent message, so I know the sender is working.
It seems to be the receiver is not able to get to the file mapping.  I also tried running the receiver as a simplified script, running as the user (instead of a service).   Interestingly, it was able to open the file mapping, but then the 'DllStructGetData' came back blank (same code that works when I run it in the sender script).
 
So, I am thinking this is still some sort of security setting issue, and I just need to figure out how to set the security attributes in autoit?

Share this post


Link to post
Share on other sites

Thanks, this is going to be long, but here is the 'receiver' , which is running as a windows service:

#NoTrayIcon
#RequireAdmin

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=Beta
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_icon=CHAgent.ico
#AutoIt3Wrapper_Compression=4
#AutoIt3Wrapper_Change2CUI=Y
#AutoIt3Wrapper_Run_Debug_Mode=Y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****


;================================================================================
;;INCLUDES
;;================================================================================
#include <INet.au3>
#include <EditConstants.au3>
#include <Array.au3>
#include <Process.au3>
#include <Misc.au3>
#include <WinAPIFiles.au3>
#include <WinAPI.au3>
#include <WinApiEx.au3>
#include "services.au3"
#include <Constants.au3>
#Include <Timers.au3>
#include "Startup.au3"


;;================================================================================
;;Only one occurence can run
;;================================================================================
_Singleton("CHAgentService",0)

;;================================================================================
;;VARIABLE DEFINITION
;;================================================================================
Dim $MainLog = @TempDir & "\chagentserv.log"
Dim $sServiceName = "CHAgentService"

$bAU3ServiceDebug=True


logprint("script started")

If $cmdline[0] > 0 Then
    Switch $cmdline[1]
      Case "install", "-i", "/i"
         InstallService()
      Case "remove", "-u", "/u", "uninstall"
         RemoveService()
      Case Else
         ConsoleWrite(" - - - Help - - - " & @CRLF)
         ConsoleWrite("params : " & @CRLF)
         ConsoleWrite(" -i : install service" & @CRLF)
         ConsoleWrite(" -u : remove service" & @CRLF)
         ConsoleWrite(" - - - - - - - - " & @CRLF)
         Exit
    EndSwitch
Else
    _Service_init($sServiceName)
    Exit
EndIf

Func _main($iArg, $sArgs)
   If Not _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) Then
       logprint("Error sending running status, exiting")
       _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0)
       Exit
    EndIf



   Local $pAddress
   Local $tData
   Local $Text
   Local $hMapping
   $bServiceRunning = True ; REQUIRED
   While $bServiceRunning ; REQUIRED  ( dont change variable name ) ; there are several ways to find that service have to be stoped - $Running flag in loop is the first method
      #region --> insert your running code here

      If $hMapping Then
         $Text = DllStructGetData($tData, 1)
         DllStructSetData($tData, 1, '')
         If $Text Then
            logprint($Text & @CRLF)
         Else
            logprint("no message")
         EndIf
      Else
         ; try to open it        *************** THIS IS THE CODE THAT DOES NOT WORK, I RECEIVE error 0, extended 0 and hmapping 0x0000
         $hMapping = _WinAPI_OpenFileMapping('MyFileMapping') ;,0x0004   tried this parameter also no difference
         If Not $hMapping Then
            logprint("not able to open file mapping!" & "er:" & @error & "ex:" & @extended & "h:" & $hMapping)
         Else
            $pAddress = _WinAPI_MapViewOfFile($hMapping)
            $tData = DllStructCreate('wchar[1024]', $pAddress)
         EndIf
      EndIf



      Sleep (10000)

      #endregion  --> insert your running code here
   WEnd


   ; *** CLEANUP (service stop cleanup)
 
   _WinAPI_UnmapViewOfFile($pAddress)
   _WinAPI_CloseHandle($hMapping)

   _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 1000)
   DllCallbackFree($tServiceMain)
   DllCallbackFree($tServiceCtrl)
   _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0)
   DllClose($hAdvapi32_DLL)
   DllClose($hKernel32_DLL)
   $bServiceRunning = False;
EndFunc   ;==>main


Func _Sleep($delay)
   Local $result = DllCall($hKernel32_DLL, "none", "Sleep", "dword", $delay)
EndFunc ;==>_Sleep

Func logprint($text, $nolog = 0)
   If $bAU3ServiceDebug Then
        If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
        FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text)
        ConsoleWrite ($text &@CRLF)
   EndIf
    Return 0
 EndFunc   ;==>logprint

Func InstallService()
   If $cmdline[0] > 1 Then
      $sServiceName = $cmdline[2]
   EndIf


    logprint("InstallService("&$sServiceName &"): Installing service, please wait")
    _Service_Create($sServiceName, $sServiceName, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_SEVERE, '"' & @ScriptFullPath & '"')
    If @error Then
        logprint("InstallService(): Problem installing service, Error number is " & @error & @CRLF & " message : " & _WinAPI_GetLastErrorMessage())
    Else
        logprint("InstallService(): Installation of service successful")
        _Service_Start($sServiceName)
    EndIf
    Exit
 EndFunc   ;==>InstallService

Func RemoveService()
    _Service_Stop($sServiceName)
    _Service_Delete($sServiceName)
    If Not @error Then
      logprint("RemoveService(): service removed successfully" & @CRLF)
    EndIf

    Exit
EndFunc   ;==>RemoveService

Func _exit()
    _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0);
EndFunc   ;==>_exit

Func StopTimer()
    _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, $iServiceCounter)
    $iServiceCounter += -100
EndFunc   ;==>StopTimer
Func _Stopping()
    _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 3000)
EndFunc   ;==>_Stopping

Here is the 'sender', which is running as background process as the user:

#NoTrayIcon

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Version=Beta
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_icon=CHLAgent.ico
#AutoIt3Wrapper_Compression=4
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Opt("mustdeclarevars",1)


;================================================================================
;;INCLUDES
;;================================================================================
#include <EditConstants.au3>
#include <Array.au3>
#include <Process.au3>
#include <Misc.au3>
#include <WinAPIFiles.au3>
#include <WinAPI.au3>
#include <WinApiEx.au3>
#include <Constants.au3>
#Include <Timers.au3>



;;================================================================================
;;Only one occurence can run
;;================================================================================
_Singleton("CHLAgent",0)

;;================================================================================
;;VARIABLE DEFINITION
;;================================================================================
Global $bAU3ServiceDebug=True

logprint("script started")

If $cmdline[0] > 0 Then
    Switch $cmdline[1]
      Case "install", "-i", "/i"

      Case "remove", "-u", "/u", "uninstall"

      Case Else
         ConsoleWrite(" - - - Help - - - " & @CRLF)
         ConsoleWrite(" - - - - - - - - " & @CRLF)
         Exit
    EndSwitch
Else

   Local $hMapping
   Local $pAddress
   Local $tData
   Local $Text
Local $hMapping2

   Local $sid = _Security__StringSidToSid("S-1-1")
   ;Local Const $tagSTRUCT1 = "struct;int var1;byte var2;endstruct"
   ;Local $sid = DllStructCreate($tagSTRUCT1)
   ;DllStructSetData($sid, "var1", 0) ; public enum WellKnownSidType {  NullSid  = 0
   ;DllStructSetData($sid, "var2", null)
   logprint("sid:" & @error)


   Dim $bServiceRunning = True
   While $bServiceRunning 
      #region --> insert your running code here

      If Not $hMapping Then


         $hMapping = _WinAPI_CreateFileMapping(-1, 2048, 'MyFileMapping',0x0004,$sid)

         If Not $hMapping Or @extended Then
            logprint("not able to create file mapping!" & "er:" & @error & "ex:" & @extended)
         Else
            $pAddress = _WinAPI_MapViewOfFile($hMapping)
            $tData = DllStructCreate('wchar[1024]', $pAddress)
         EndIf
      Else
         ; file mapping good, send message
         If (_Timer_GetIdleTime() > 30000) Then
            DllStructSetData($tData, 1, "IDL")
         Else
            DllStructSetData($tData, 1, "ACT")
         EndIf
         logprint("sent message")
      EndIf





; *** THIS IS TEST CODE TO SEE IF WE CAN RECEIVE IN THE SAME SCRIPT, WHICH YES, WE CAN, THIS WORKS:
      If $hMapping2 Then
         $Text = DllStructGetData($tData, 1)
         DllStructSetData($tData, 1, '')
         If $Text Then
            logprint($Text & @CRLF)
         EndIf
      Else
         ; try to open it
         $hMapping2 = _WinAPI_OpenFileMapping('MyFileMapping') ;,0x0004
         If Not $hMapping2 Then
            logprint("not able to create file mapping!" & "er:" & @error & "ex:" & @extended & "h:" & $hMapping2)
         Else
            $pAddress = _WinAPI_MapViewOfFile($hMapping2)
            $tData = DllStructCreate('wchar[1024]', $pAddress)
         EndIf
      EndIf







      Sleep (10000)

      #endregion  --> insert your running code here
   WEnd

   $bServiceRunning = False;

   _WinAPI_UnmapViewOfFile($pAddress)
   _WinAPI_CloseHandle($hMapping)

   Exit
EndIf


Func _Sleep($delay)
   Local $result = DllCall($hKernel32_DLL, "none", "Sleep", "dword", $delay)
EndFunc ;==>_Sleep

Func logprint($text)
   Dim $MainLog = @TempDir & "\chlagent.log"
   If $bAU3ServiceDebug Then
        If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
        FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text)
        ConsoleWrite ($text &@CRLF)
   EndIf
    Return 0
EndFunc   ;==>logprint

Share this post


Link to post
Share on other sites

What keeps your script running? Everything seems to have an exit in it. I don't see either script as something that starts and then does a couple of functions and then just ends.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

It's a windows service.   That part of the script works fine.   You will notice all the 'logprint' calls, it writes to a log file, which is how I debug it.   That's how I know I am getting an invalid handle, I can see it being logged.     SO, to be clear,  _main IS being called, it is called by windows when it starts the service.    The script stays running because there is a while loop inside main. 

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

How about something like this?

Local $tSecurity = DllStructCreate("int Length;ptr Descriptor;int InheritHandle") ; $tagSECURITY_ATTRIBUTES
DllStructSetData($tSecurity, 1, DllStructGetSize($tSecurity))
DllStructSetData($tSecurity, 2, 0)
 $hMapping = _WinAPI_CreateFileMapping(-1, 2048, 'MyFileMapping',0x0004, DllStructGetPtr($tSecurity))
Edited by KaFu

Share this post


Link to post
Share on other sites

Thanks, that looks promising, but did not work.   Same result, no handle (0x0000) in the service.   I wish there was a way I could view the activity/permissions - I tried filemon (process monitor) but it does not appear in there.

Share this post


Link to post
Share on other sites

Honestly, I am not sure if it's possible to share between system/user, but I thought it might be possible based on that link in my first post.  

In that msdn thread, they talk about the 'null' security and it sounds like it's a common issue - by default win32api uses null security which means no one else can access the filemapping.    They then explain that you have to create a 'NULL descriptor'.    There was mention of the SecurityIdentifier' method, and also ConvertStringSecurityDescriptorToSecurityDescriptor.  

 I am sure you are correct, that require admin would work, but then the user would have to be an Admin / have admin privs, or it will likely cause UAC to keep nagging.  I have to avoid that, so I just need a simple way for the two scripts to communicate locally.

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