Jump to content

Recommended Posts

Posted

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!

Posted
 

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, '')
 
Posted
 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
Posted

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!
Posted

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?
Posted

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
Posted

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

Posted

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. 

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
Posted

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.

Posted

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.

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
×
×
  • Create New...