Thanks for any suggestion!
Best way for inter-process communication
Best way for inter-process communication
Since I'm going to make my first program as a Windows 'service', I've to choose a method to make the 'service' send few bytes of string data to an helper program that it is meant to work with (as I don't want the service open its own GUI). I'm thinking to use a memory mapped file, or maybe to send data from the service through a window message (WM_USER) , if that is possible.
Thanks for any suggestion!
Thanks for any suggestion!
Unless you're certain that your WM_USER or WM_APP messages won't interfere with any other applications it's best that you register a unique message using RegisterWindowMessage_().
There are many ways to perform interprocess communication:
File Mapping
Shared Memory
Anonymous Pipes
Named Pipes
Mailslots
Clipboard
Dynamic Data Exchange
Object Linking and Embedding
Dynamic-Link Libraries
Remote Procedure Call
Netbios
Window messaging is the simplest but can also be dangerous if your messages are not unique.
Win32.hlp has a whole section on this.
http://www.master-creating.de/purebasic ... winapi.exe
There are many ways to perform interprocess communication:
File Mapping
Shared Memory
Anonymous Pipes
Named Pipes
Mailslots
Clipboard
Dynamic Data Exchange
Object Linking and Embedding
Dynamic-Link Libraries
Remote Procedure Call
Netbios
Window messaging is the simplest but can also be dangerous if your messages are not unique.
Win32.hlp has a whole section on this.
http://www.master-creating.de/purebasic ... winapi.exe
Keep in mind that in Vista, window messages cannot be sent across different levels of elevation.
So if your service runs with more rights than a normal application (which is often the case),
this kind of communication will fail.
I would go for a memory mapped file, or named pipes. I personally prefer
pipes, as they are a good way to create a simple sequential communication
between the programs.
If security is important you have to keep in mind that the shared resource could
be accessed/locked/deleted by an attacker before your helper program even gets to run.
To prevent this, make sure the right permissions are set with the SECURITY_ATTRIBUTES
structure that is an argument of the functions that create such shared objects.
So if your service runs with more rights than a normal application (which is often the case),
this kind of communication will fail.
I would go for a memory mapped file, or named pipes. I personally prefer
pipes, as they are a good way to create a simple sequential communication
between the programs.
If security is important you have to keep in mind that the shared resource could
be accessed/locked/deleted by an attacker before your helper program even gets to run.
To prevent this, make sure the right permissions are set with the SECURITY_ATTRIBUTES
structure that is an argument of the functions that create such shared objects.
quidquid Latine dictum sit altum videtur
Thanks for your suggestions. I think the best solution is using pipes then. I've never used them, but it seems easy:
http://www.purebasic.fr/english/viewtop ... ight=pipes
Though, since the service will be launched by the helper program by using RunProgram() function, I thought I could read the output from the service program, setting #PB_Program_Open|#PB_Program_Read as flags. What do you think ??? I guess it is still a pipe.
http://www.purebasic.fr/english/viewtop ... ight=pipes
Though, since the service will be launched by the helper program by using RunProgram() function, I thought I could read the output from the service program, setting #PB_Program_Open|#PB_Program_Read as flags. What do you think ??? I guess it is still a pipe.
I needed this advice too. I've noticed so far that you need administrator priviledges to use meory mapped files. Even it the service (that was started and installed by an admin) was creating a file, the lower priviledged process that needed to communicate with it via readfilemapping also needed admin privs. That's bad... At the end i started using network commands and made a local server and a client.
@Freak, I don't have Vista around
. Would a simple client/sever based on local networking work?
@Freak, I don't have Vista around
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
This all depends on the security settings you use. The functions that create shared objects (such as files or memory mapped files)Inf0Byt3 wrote:I needed this advice too. I've noticed so far that you need administrator priviledges to use meory mapped files. Even it the service (that was started and installed by an admin) was creating a file, the lower priviledged process that needed to communicate with it via readfilemapping also needed admin privs. That's bad... At the end i started using network commands and made a local server and a client.
@Freak, I don't have Vista around. Would a simple client/sever based on local networking work?
usually take a SECURITY_ATTRIBUTES pointer as parameters. Thats what determines the access rights.
When the contained lpSecurityDescriptor is NULL, the shared object gets the security settings
from the process that creates the object. So if your process runs as admin, only an admin can access it.
What you need to do is create your own security descriptor that grants rights to less priviledged processes
and there should be no problems.
I have not dealt that much with this myself yet, but here is a good place to start:
http://msdn2.microsoft.com/en-us/librar ... S.85).aspx
btw, all this works since Win2k, its not specific to Vista.
A client/server solution probably works, but then you have to deal with stuff like
firewall settings on the user's machine which opens a new can of worms.
quidquid Latine dictum sit altum videtur
Thank you so much for taking the time to answer, it's now perfectly clear.
E.g.
- Service starts with Windows, at user login and creates a file mapping
- Second process starts and reads the file mapping
- Repeat
- Wait for a command to be sent by second process
- Process it and write the result in another filemapping
- The second process clears the buffers and the service waits again
- Until Shutdown
I tested this on a non-admin user and at ReadFileMapping_(), the whole second process was crashing.
But now thanks to Freak I understand why it was happening.
Tried this. Made a service with PBOSL libs and used the code from the forum to create some procedures to syncronize fixed strings.I'm using mapped files on all my applications from longtime, and no problems with user privileges on NT, 2K and XP.
E.g.
- Service starts with Windows, at user login and creates a file mapping
- Second process starts and reads the file mapping
- Repeat
- Wait for a command to be sent by second process
- Process it and write the result in another filemapping
- The second process clears the buffers and the service waits again
- Until Shutdown
I tested this on a non-admin user and at ReadFileMapping_(), the whole second process was crashing.
But now thanks to Freak I understand why it was happening.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Yes, I'm using always:freak wrote:This all depends on the security settings you use. The functions that create shared objects (such as files or memory mapped files)
usually take a SECURITY_ATTRIBUTES pointer as parameters. Thats what determines the access rights.
Code: Select all
MAPfile = CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,filesize,filename)The lpSecurityDescriptor member of this structure specifies a security descriptor for a new file mapping object. If lpAttributes is NULL, the file mapping object gets a default security descriptor. The access control lists (ACL) in the default security descriptor for a file mapping object come from the primary or impersonation token of the creator. For more information, see File Mapping Security and Access Rights.
Here's what I made... I am using this in a service... but no go. I thought it's correct, but after it's created it can't be acessed :/. Any help/suggestion would be really appreciated. All I want to do is to have a service that receives commands and can respond via filemapping with any program.
A sender and a receiver for strings that work in admin account.
Thanks for reading.
Code: Select all
Structure StringIPC
s.s{#MAX_PATH}
EndStructure
#SDDL_REVISION_1 = 1
#SDDL_STRING = "S:(ML;;NW;;;LW)"
SecAttr.SECURITY_ATTRIBUTES
SecDesc.s = Space(#SECURITY_DESCRIPTOR_MIN_LENGTH)
SecAttr\nLength = SizeOf(SECURITY_ATTRIBUTES)
SecAttr\bInheritHandle = #False
SecAttr\lpSecurityDescriptor = 0
If InitializeSecurityDescriptor_(@SecAttr, #SECURITY_DESCRIPTOR_REVISION)
If SetSecurityDescriptorDacl_(@SecAttr, #True, 0, #False)
If OpenLibrary(0,"Advapi32.dll")
pSD.SECURITY_DESCRIPTOR
CallFunction(0,"ConvertStringSecurityDescriptorToSecurityDescriptor",#SDDL_STRING,#SDDL_REVISION_1,@SecAttr\lpSecurityDescriptor,#Null)
pSacl = #Null
fSaclPresent = #False
fSaclDefaulted = #False
GetSecurityDescriptorSacl_(pSD,@fSaclPresent,@pSacl,@fSaclDefaulted)
SetSecurityDescriptorSacl_(@SecAttr, #True, @pSacl, #False)
Else
MessageRequester("Error","Could not open Advapi32.dll. Please install the required file.",#MB_ICONSTOP):End
EndIf
EndIf
Else
MessageRequester("Error","Could not initialize the security descriptor.",#MB_ICONSTOP):End
EndIf
*hfm = CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(StringIPC),"map")
*ptr.StringIPC = MapViewOfFile_(*hfm,#FILE_MAP_ALL_ACCESS,0,0,0)
OpenConsole()
Repeat
Delay(500)
If *ptr\s <> ""
PrintN(*ptr\s)
EndIf
ForEver
Code: Select all
;Receiver
Structure StringIPC
s.s{#MAX_PATH}
EndStructure
*hfm = CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(StringIPC),"map")
*ptr.StringIPC = MapViewOfFile_(*hfm,#FILE_MAP_WRITE,0,0,0)
Repeat
Debug *ptr\s
ForEver
Code: Select all
;Sender
Structure StringIPC
s.s{#MAX_PATH}
EndStructure
*hfm = CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(StringIPC),"map")
*ptr.StringIPC = MapViewOfFile_(*hfm,#FILE_MAP_ALL_ACCESS,0,0,0)
*ptr\s = "test test test"
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
But it's not that. It didn't work even when I passed it correctly.
But I made it work
The service (needs PBOSL)
Code: Select all
Structure StringIPC
s.s{#MAX_PATH}
EndStructure
#SERVICE_BOOT_START = $00000000
#SERVICE_SYSTEM_START = $00000001
#SERVICE_AUTO_START = $00000002
#SERVICE_DEMAND_START = $00000003
#SERVICE_DISABLED = $00000004
;
Global ServiceName.s = "ASrv"
Global ServiceDisplayName.s = "A Service"
Global ServiceExplanation.s = "A - this service is a simple test"
;
Procedure MyServiceFunction()
sd.SECURITY_DESCRIPTOR
InitializeSecurityDescriptor_(@sd, #SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl_(@sd, #True, #Null, #False)
sa.SECURITY_ATTRIBUTES
sa\nLength = SizeOf(SECURITY_ATTRIBUTES);
sa\bInheritHandle = #False;
sa\lpSecurityDescriptor = @sd;
*m_MapHandle = CreateFileMapping_(#INVALID_HANDLE_VALUE, @sa, #PAGE_READWRITE, 0, SizeOf(StringIPC),"map")
*ptr.StringIPC = MapViewOfFile_(*m_MapHandle,#FILE_MAP_ALL_ACCESS,0,0,0)
OpenConsole()
Repeat
Delay(500)
If *ptr\s <> ""
PrintN(*ptr\s)
EndIf
ForEver
EndProcedure
Select LCase(ProgramParameter())
Case "/i"
Installservice(ServiceName,ServiceDisplayName,ProgramFilename(),ServiceExplanation,#SERVICE_AUTO_START)
End
Case "/r"
RemoveService(ServiceName)
End
EndSelect
Service(ServiceName.s,@MyServiceFunction(),0)
Code: Select all
Structure StringIPC
s.s{#MAX_PATH}
EndStructure
*m_MapHandle = CreateFileMapping_(#INVALID_HANDLE_VALUE, @sa, #PAGE_READWRITE, 0, SizeOf(StringIPC),"map")
*ptr.StringIPC = MapViewOfFile_(*m_MapHandle,#FILE_MAP_ALL_ACCESS,0,0,0)
*ptr\s = "Alex"
Code: Select all
How to install and remove:
BEAMSrv.exe /i OR BEAMSrv.exe /r
How to start/stop:
net start ASrv OR net stop ASrv
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)



