How do I get the 'Handle' of the Windows Service, so as to pass Memory Mapped messages from a windows application. Both written in Delphi.
The handle of the service is not what you need here. Memory mapped files are named kernel objects. So you need to agree on a name for your file mapping and use that to link your two processes.
When you call CreateFileMapping to create the file mapping, or open an existing file mapping created by the other process, you pass the name as the last argument. You'll need to use the Global\ namespace prefix to ensure that the file mapping is in the global namespace and so accessible from different sessions.
Memory mapped files are an unusual choice for IPC between service and desktop. One would more commonly expect to see named pipes or sockets.
Related
The Windows API includes a useful function called DuplicateHandle, which can be used to transfer HANDLEs (to files, registry keys, processes, mutexes, etc.) from one process to another. This is useful for a number of things, including when writing sandboxes where sometimes a broker process will open a HANDLE (that the sandboxed process can't access) and then pass that HANDLE down to the sandbox. This is similar to passing file descriptors between POSIX processes via Unix domain sockets.
Unfortunately, the documentation for DuplicateHandle doesn't mention service handles (type SC_HANDLE, used/returned by APIs like OpenSCManager) as a supported HANDLE type. Is there a way to duplicate (or otherwise transfer) those between processes?
These handles cannot be duplicated. The other process would need to call OpenSCManager.
In other words, is it possible to access a file without a handle being utilized?
You could use the CreateFile()-API to create a handle to the raw file-system and then parse the file structure by yourself (this is more work as it sounds!)
Though this would require admin-rights. This wouldn't trigger any hooks you have on CreateFile() or other file-related API-functions.
This wouldn't create a handle to the file but you still need a handle to the device.
For code running in user mode, any operation on a file will involve a handle of some kind, though not necessarily to the file in question. There are APIs that don't expose the handle to the programmer, but there is always one there.
In kernel mode, although it is usual to use handles for file operations, it is not necessary. For example, the file server component doesn't appear to open file handles when it is accessing a file on behalf of a remote user.
Is there a way to set the permissions with Named Shared Memory in Windows so that the access control is done by process rather than by user? I'd like to have one program create the memory, pass a handle or pass back a PID so that the client process can access the memory. All other processes should be denied access. Thanks
Access control is only by security principals, which can be users, groups, computers, and the like.
If you have an object that you want shared with another process, you can use DuplicateHandle.
No, because processes are not security principles.
Instead, use an unnamed file mapping and give the client process a copy of the handle using DuplicateHandle.
I always set my drivers Imagepath directly.(C:\Windows\System32\drivers\abc.sys)
But I just knew many device drivers set their ImagePath to %SystemRoot%\system32\svchost.exe -k netsvcs
This is Lanmanworkstation driver's registry hive.
I guess Lanmanworkstation driver's image file is mrxsmb.sys
But they didn't put 'System32\drivers\mrxsmb.sys'. Why.
What does svchost.exe -k netsvcs mean?
Even though there is no certain path, StartService function works well.
How does Service Manager(? i'm not sure) find the driver's image path?
Is there an advantage using this?
What if I decide to use this way, are there my driver codes should modify?
You are confusing between device drivers and services.
svchost.exe is used to share the same process between multiple services. The implementation is internal to Windows so use outside of Windows is not supported.
If you write a device driver (for hardware, or a filter driver) or do not work for Microsoft, you cannot use svchost.
The reason for the confusion is because old style (NT4), non-plug-and-play drivers can be started using the Service Control Manager APIs.
svchost is a host process for other services, contained in DLLs. The part after the "-k" indicates the service group. You can find the service DLL path in HKLM\System\CurrentControlSet\Services\LanmanWorkstation\Parameters in the ServiceDll value. I'm guessing the reason it still starts correctly if you remove the image path is because the service type is set to SERVICE_WIN32_SHARE_PROCESS, and the SCM probably ignores the image path (not sure about this).
svchost.exe is a "multi-purpose" service. It incorporates multiple services in one single exe file, each of which can be seperately controlled using e.g. services management console. The parameters to svchost.exe states the "subservice" inside the exe file.
As startService() is not a control message to the service itself but instead only the request to start a certain executable (which itself must "know" that it is a service (and wich service) and will then register with service control manager), windows will simply execute the binary that ImagePath points to.
In this case (LanManWorkstation) this binary is svchost.exe, the parameter given to it is -k netsvc. This lets svchost.exe know which of the many service it provides should be started.
As usual, the binary doesn't need to contain all the function in itself but can also load additional libraries. mrxsmb.sys may well be such a library, though I'm not sure of this point.
So this answer is more of a "how does it work in general" than a "yes, netsvc and mrxsmb.sys are LanManWorkstation".
I've developed a windows application that uses shared memory---that is---memory mapped files for interprocess communication. I have a windows service that does some processing and periodically writes data to the memory mapped file. I have a separate windows application that reads from the memory mapped file and displays the information. The application works as expected on Windows XP, XP Pro and Server 2003, but NOT on Vista.
I can see that the data being written to the memory mapped file is happening correctly by the windows service because I can open the file with a text editor and see the stored messages, but the "consumer" application can't read from the file. One interesting thing to note here, is that if I close the consumer application and restart it, it consumes the messages that were previously written to the memory mapped file.
Also, another strange thing is that I get the same behavior when I connect to the windows host using Remote Desktop and invoke/use the consumer application through remote desktop. However, if I invoke the Remote Desktop and connect to the target host's console session with the following command: mstsc -v:servername /F -console, everything works perfectly.
So that's why I think the problem is related to permissions. Can anyone comment on this?
EDIT:
The ACL that I'm using to create the memory mapped file and the Mutex objects that sychronize access is as follows:
TCHAR * szSD = TEXT("D:")
TEXT("(A;;RPWPCCDCLCSWRCWDWOGAFA;;;S-1-1-0)")
TEXT("(A;;GA;;;BG)")
TEXT("(A;;GA;;;AN)")
TEXT("(A;;GA;;;AU)")
TEXT("(A;;GA;;;LS)")
TEXT("(A;;GA;;;RD)")
TEXT("(A;;GA;;;WD)")
TEXT("(A;;GA;;;BA)");
I think this may be part of the issue.
So I found the solution to my problem:
On Windows XP, all named kernel objects such as mutex, semaphore and memory mapped objects are stored in the same namespace. So when different processes in different user sessions reference a particular object using it's name, they obtain a handle to that object. However, as a security precaution, Windows terminal services creates a separate namespace for kernel objects referenced from processes started in it's session. Windows Vista has this behavior built into it as well, so that's why my app didn't work correctly on Vista. To elaborate, I have a Windows service that runs in the null session and an application that runs in a user session, so my named objects were being created in separate namespaces.
The quick fix for this issue was to use the Global namespace by prepending "Global\" to each kernel object name that I used and that did the trick.
The prefix "Global\" may not work on shared memory. See "Impact of Session 0 Isolation on Services and Drivers in Windows Vista" for solution.
What access are you opening the shared memory section with? Try with FILE_MAP_ALL_ACCESS and work your way down. Also make sure you don't have a race condition between the producer and consumers - which one is creating the shared memory? Make sure ths is created before the other one tries to open it. One method is to create the section in the parent before you start the child process - if you are using a parent/child architecture.
Your child may need to run elevated on Vista in order to be allowed access to the shared memory. It may also be related to the window session your are using. Services run in session 0 (I think) while other apps (especially if you log in via remote desktop) may run in another session.
Have you tried moving the file to a different location. Try putting it in the 'Shared Documents' folder, this seems to be the most freely accessible folder in Vista.