Best way for inter-process communication

Just starting out? Need help? Post your questions and find answers here.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Best way for inter-process communication

Post by Seldon »

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! :)
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

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
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

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.
quidquid Latine dictum sit altum videtur
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

I have to agree with freak. Named pipes are probably the simplest method. If you choose to use shared memory over a filemap you'll end up having to synchronize your processes which can lead to more complicated code.
Seldon
Enthusiast
Enthusiast
Posts: 405
Joined: Fri Aug 22, 2003 7:12 am
Location: Italia

Post by Seldon »

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.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

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?
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
thefool
Always Here
Always Here
Posts: 5875
Joined: Sat Aug 30, 2003 5:58 pm
Location: Denmark

Post by thefool »

info how about the pipes
User avatar
graves
Enthusiast
Enthusiast
Posts: 160
Joined: Wed Oct 03, 2007 2:38 pm
Location: To the deal with a pepper

Post by graves »

Inf0Byt3 wrote:I've noticed so far that you need administrator priviledges to use meory mapped files.
I'm using mapped files on all my applications from longtime, and no problems with user privileges on NT, 2K and XP.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

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

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
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Thank you so much for taking the time to answer, it's now perfectly clear.
I'm using mapped files on all my applications from longtime, and no problems with user privileges on NT, 2K and XP.
Tried this. Made a service with PBOSL libs and used the code from the forum to create some procedures to syncronize fixed strings.

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)
User avatar
graves
Enthusiast
Enthusiast
Posts: 160
Joined: Wed Oct 03, 2007 2:38 pm
Location: To the deal with a pepper

Post by graves »

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.
Yes, I'm using always:

Code: Select all

MAPfile  = CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,filesize,filename)
The first "0" parameter is the LPSECURITY_ATTRIBUTES, as explained in http://msdn2.microsoft.com/en-us/library/aa366537.aspx
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.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

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.

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
A sender and a receiver for strings that work in admin account.

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"
Thanks for reading.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

The only thing I notice is that you do not appear to be passing your SECURITY_ATTRIBUTES structure to the CreateFileMapping_() function.

Could this be the problem?
I may look like a mule, but I'm not a complete ass.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

:oops:

But it's not that. It didn't work even when I passed it correctly.

But I made it work :D. 8) 8) 8)

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)
And this is the sender (user mode app)

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
Man why the heck did microsoft made all this bull$it when they could spend that money in making onecare better? I mean heck, it could have been soooo simple without all this "security" cr@p. What I mean is that this is simply useless. This won't stop nobody. Even a dumbass (look at my avatar :lol: ) can beat it.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

What did you do to make it work?
I may look like a mule, but I'm not a complete ass.
Post Reply