SetWindowsHookEx for WH_JOURNALRECORD fails under Vista/Windows 7 - delphi

I am preparing a Delphi module, which sets a hook in a thread to record a macro:
FHandleRec := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
FHandlePlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, FPlayProc, HInstance, 0);
That works fine on WinXP, but on Vista/Windows 7 fails with ERROR_ACCESS_DENIED.
I have found in Google (this) referring (that). The quote:
A lower privilege process cannot: … Use Journal hooks to monitor a
higher privilege process.
Tried without success:
Run application as administrator. Probably the thread is started
with lower privileges than the main thread (though I am not 100%
sure)
Impersonating the thread with administrator security context
doesn’t help either.
The code sample:
if LogonUser(PWideChar(sAdminUser), PWideChar(sDomain), PWideChar(sPwd),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) then
begin
if not ImpersonateLoggedOnUser(hToken) then
raise Exception.Create('Error impersonating the user');
end;
FHandleRec := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
LogonUser and ImpersonateLoggedOnUser execute without errors.
Other possibilities to try:
Turn UAC OFF permanently. This helps, but I cannot force the module
users to do that.
A module customer signs an application and put it in a trusted
location. Not tried that, but that radically complicates the module
usage for the users.
Put the module into some signed application and distribute EXE. That
will break some core functionality.
Could you please show the code that is setting the hook under Visa / Windows 7 or suggest the working solution ?

Read the "User Interface Privilege Isolation" section of that article again more carefully. It is referring to integrity levels, not user permissions. That is why impersonating another user does not solve the problem. The integrity level is established when the process first starts and cannot be changed dynamically in code.
User Interface Privilege Isolation (UIPI) is one of the mechanisms
that helps isolate processes running as a full administrator from
processes running as an account lower than an administrator on the
same interactive desktop. UIPI is specific to the windowing and
graphics subsystem, known as USER, that supports windows and user
interface controls. UIPI prevents a lower privilege application from
using Windows messages to send input from one process to a higher
privilege process. Sending input from one process to another allows a
process to inject input into another process without the user
providing keyboard or mouse actions.
Windows Vista implements UIPI by defining a set of user interface
privilege levels in a hierarchical fashion. The nature of the levels
is such that higher privilege levels can send window messages to
applications running at lower levels. However, lower levels cannot
send window messages to application windows running at higher levels.
The user interface privilege level is at the process level. When a
process is initialized, the User subsystem calls into the security
subsystem to determine the desktop integrity level assigned in the
process’s security access token. The desktop integrity level is set by
the security subsystem when the process is created and does not
change. Therefore, the user interface privilege level is also set by
the User subsystem when the process is created and does not change.
All applications run by a standard user have the same user interface
privilege level. UIPI does not interfere or change the behavior of
window messaging between applications at the same privilege level.
UIPI comes into effect for a user who is a member of the
administrators group and may be running applications as a standard
user (sometimes referred to as a process with a filtered access token)
and also processes running with a full administrator access token on
the same desktop. UIPI prevents lower privilege processes from
accessing higher privilege processes by blocking the behavior listed
below.
Use Journal hooks to monitor a higher privilege process.
According to this article, your app needs a UAC manifest that specifies both requestedExecutionLevel=requireAdministrator and uiAccess=True. The UIAccess right is important:
By specifying UIAccess=”true” in the requestedPrivileges attribute,
the application is stating a requirement to bypass UIPI restrictions
...
A process that is launched with UIAccess rights:
Can set journal hooks.

Related

call to postmessage returns "access denied"

Using Delphi 2007...
I have an application which uses a mutex to enforce one running instance only. In the dpr unit, if the mutex already exists, I get a handle to the running instance with FindWindow, no problem so far. A second instance is commonly started by a virtual printer driver with reference to a filename on the command line. If there is a command line file reference then I want to simply post a message to the running instance and halt the new instance.
I'm using this...
PostMessage(hwnd,WM_STARTUP_MESSAGE,0,0); //hwnd as returned by FindWindow
WM_STARTUP_MESSAGE is defined as WM_APP + 6057
I have one user with the problem that the WM_STARTUP_MESSAGE is not processed in the main thread. From logging startup information in the dpr unit it was shown that the PostMessage returned false and SysErrorMessage(GetLastError) is:
Zugriff verweigert (his windows german translation is Access Denied).
I have many, many users of this application and I have only had 2 reports of this problem and cannot reproduce here. On Windows 10 here and so is at least 1 of the problem users, the other one I'm not sure of.
I am using ChangeWindowMessageFilterEx in the main form's OnCreate to allow WM_COPYDATA. I had the idea of simply including WM_STARTUP_MESSAGE there as well but that leads to a crash as that function does not like that message index value, so I presume it is reserved for a specific range of message values.
Has anyone seen this before and can offer some guidance?
Per the PostMessage() documentation:
When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).
What is User Interface Privilege Isolation (UIPI) on Vista
This is also known as UI Privilege Level Isolation (UIPI).
As part of the secure initiatuve in Vista, applications with UI will run in three different levels of privilege. Application windows can interact with others windows of the same or lower levels, but cannot interact with applications at higher level/permission.
Lower privilege modes can send messages to higher privileged applications only if explicitly allowed by the higher privilege application with a message calling ChangeWindowMessageFilter(). Also lower privileged applications can only read a HWND owned by a higher privileged application.
Internet Explorer is an example process that runs at the lowest privilege level.
Windows Integrity Mechanism Design
User Interface Privilege Isolation (UIPI) implements restrictions in the windows subsystem that prevents lower-privilege applications from sending window messages or installing hooks in higher-privilege processes. Higher-privilege applications are permitted to send window messages to lower-privilege processes. The restrictions are implemented in the SendMessage and related window message functions. Not all window messages that are sent from a lower-privilege process to a higher-privilege process are blocked. Generally, “read” type messages, for example WM_GETTEXT, can be sent from a lower-privilege to a higher-privilege window. However, write type messages, such as WM_SETTEXT, are blocked.
...
UIPI does not interfere with or change the behavior of window messaging between applications at the same privilege (or integrity) level. UIPI prevents lower-privilege processes from accessing higher-privilege processes by blocking the following behavior. A lower-privilege process cannot:
Perform a window handle validation of a process running with higher rights.
Use SendMessage or PostMessage to application windows running with higher rights. These APIs return success but silently drop the window message.
Use thread hooks to attach to a process running with higher rights.
Use journal hooks to monitor a process running with higher rights.
Perform dynamic link library (DLL) injection to a process running with higher rights.
So clearly, when the error occurs, the HWND you are posting to belongs to a process that is running at a higher integrity/privilege level than the process that is posting the message. You can use SysInternals' Process Explorer to check that.
You said the second instance of your app is being run by a virtual printer driver, so the driver is likely running at a lower integrity level than an instance of the app that is started by the user.
ChangeWidowMessageFilter/Ex() does not have any restrictions on non-system message IDs (some system messages cannot be filtered). It will certainly not crash on a user-defined message ID. If you do not have permission to change the message filter for a given HWND/MsgID, the function will simply return FALSE instead, and GetLastError() will tell you why.
If you are experiencing a crash, it is related to something else in your code.
Also, the Form's OnCreate event is not the best place to call ChangeWindowMessageFilterEx(). During the course of the program's lifetime, the Form may have to recreate its HWND dynamically, maybe even more than once. Every time a new HWND is created, you have to call ChangeWindowMessageFilterEx() again. The best way to account for that is to override the Form's virtual CreateWnd() method, eg:
type
TMyForm = class(TForm)
protected
procedure CreateWnd; override;
end;
procedure TMyForm.CreateWnd;
begin
inherited;
ChangeWindowMessageFilterEx(Handle, WM_STARTUP_MESSAGE, MSGFLT_ALLOW, nil);
end;

When is it appropriate to mark services as not stoppable?

Services can be marked as "not stoppable":
In C/C++ by specifying SERVICE_ACCEPT_STOP flag when calling SetServiceStatus (see SERVICE_STATUS for details).
If .NET, by set ServiceBase.CanStop to false.
However, is this good practice? It means that even a user with administrator privileges cannot stop such a service in a clean manner. (It would still be possible to kill it, but this would prevent proper cleanup. And if there are other services running in the same process, they would be killed as well.)
In my specific case, I have a service which controls a scientific instrument. It has been suggested to make the service not stoppable while it is acquiring data from the instrument in order to prevent losing the data being acquired. I should add that:
We grant non-administrator users the right to start/stop the service
We have program that provides a UI to start/stop this service. This program will issue a warning if the user tries to stop the service during acquisition. However, it is of course also possible to stop is with SC.EXE or the "Services" snap-in. In this case, there is no warning.
Does Microsoft (or anyone else) provide guidance?
My own stance so far is that marking a service not stoppable is a drastic measure that should be used sparingly. Acceptable uses would be:
For brief periods of time, to protect critical operations that should not be interrupted
For services that are critical for the operation or security of the OS
My example would not fall under those criteria, so should be stoppable

Converting a Delphi application to run as a service - is it necessary?

I have a delphi app that logs data from various places and writes the data to a file. The app has quite an extensive GUI to allow display of the data, configuration of the options, etc.
One user has requested that the app be changed to that it can be run as a service. His reasoning is that the app could then be started at boot time and run without any user being logged in and would be available regardless of who was logged in.
My question is this: Is there any other solution that would enable me to install the app as it now exists so that it would still run with no user logged in and still be available to all users?
My gut feeling is that converting the app to run as a service is not trivial. I assume you would need 2 apps - the "headless" service application, and a GUI that was run by users on demand that could interact with the service (comments welcome here also).
I usually create my application in such a way that it can be started as a service or as a GUI, via a commandline switch /GUI.
When the application runs with a GUI, I instantiate and start the service class "manually".
Advantages:
It'll run the same code, making it very easy to debug the service. You can just put breakpoints and step through your code without having to "attach" to a running application.
Because of the GUI, you can see what your service would be doing, and interact with it, via listviews and buttons, even on remote servers where you don't have a debugger. Having to interact with your service via logs and configurations is crappy and slow.
Example dpr, from a project that works like this:
program xxxx;
uses
SysUtils,
SvcMgr,
.......;
{$R *.res}
begin
GlobalAppId := 1;
MapMatcherController := TMapMatcherController.Create(nil);
try
if FindCmdLineSwitch('GUI',['/','-'],True) then
begin
Forms.Application.Initialize;
Forms.Application.MainFormOnTaskbar := True;
Forms.Application.CreateForm(TfrmMain, frmMain);
Forms.Application.Run;
end
else
begin
SvcMgr.Application.Initialize;
SvcMgr.Application.CreateForm(TsrvMapMatcher2, srvMapMatcher2);
SvcMgr.Application.Run;
end;
finally
MapMatcherController.Free;
end;
end.
Oh, another thing to keep in mind is that services usually run as a "system" user, which means you'll have different privileges and settings (for example drive letter mappings).
There are commercial (and free) solutions like Firedaemon, which will run (almost) any application as a service.
On a sidenote, it shouldn't really be hard to separate logic and user interface - you should've done that already when you developed the application. Just because Delphi makes it easy to write business logic in the code behind associated with the user interface, that doesn't mean you should really do it. Have a look at the presentation pattern's at Martin Fowler's site.
In general is possible to have a mixed single exe which in turn runs as a service or runs as a full GUI standard application.
How much effort your application needs to fit this category is matter of how is it designed, specially in the kind of coupling it have between business logic and user interface logic.
One great example of this kind of application comes with Delphi itself: scktsrvr.exe in your $DELPHI\bin directory runs as a GUI application or as a service (run scktsrvr.exe /install to auto-register the service and use management console to start/stop it.
in folder $DELPHI\source\db you will find the project files (scktsrvr.dpr/res, ScktCnst.pas, ScktMain.pas/dfm). Take your time to inspect how is it done and, who knows... maybe this is what you're looking for your application.
Take in account since Windows Vista interactive services are not allowed to interact with the user at his/her desktop. An administrator have to enable the interactive services detection and the user have to change to session 0 desktop in order to interact with your service (by interact it means to see and interact with your service forms)
You can try to use svrany, a tools to run an application as service.
It's parts of Server Resource Kit Tools.
try this link for 2003 server resource kit download.
It depends a little on your application, but generally it is achievable. Try this: http://iain.cx/src/nssm. Don't forget to start all services that you application depends on BEFORE you start your application as a service. Google around for info on how to do that.
You could write a simple service that starts your application. But if you care about your app future, I would go the service way. Yes, you would have to split the application in two pieces, the client/GUI part and the service itself, especially since Vista and 7 made much more difficult for a service to display a user interface for security reasons.
Services have several advantages, they run in their separate session, they can be set to run with a given user that could be different from the logged-on one, only user with proper privileges can control them, Windows can automatically restart them (or perfom other actions) when they fail.

how to map network drive for Clearcase View in Windows service?

I want to map a clearcase view on network drive inside a windows service.
I have tried with net use command, but it did not work properly.
You should be able to run the same kind of command than the one used when paths are too long, which is subst:
subst X: c:\path\to\my\View # for snapshot view
subst X: M:\myView # for dynamic view
in order to map a view to a drive letter.
This should work from within a service, provided:
you are using your Windows account (and not the "Local System account")
the dynamic view is already started (and visible in the M:\ MVFS mounting point drive)
I wish this approach would work, but it really doesn't from a service; I've beat on this problem pretty intensely to no avail. The problem is two-fold:
From a Windows service, to be able to map drives visible to other users it has to "Log on" as the "Local system" account (default) with the "Interact with desktop" property set.
To be able to talk to ClearCase, the Windows service process has to "Log on" as a normal user with ClearCase access (e.g. in the atria group typically).
So (1) and (2) are mutually exclusive, but you need to do both and can't. For (2), presumably the reason you can't "Interact with desktop" and map drives there is because you'd need a logon session / token which has to be present for mapped drives to work --associated per-user session--but services need to be able to run headless (no one logged in) where there is no "session" / token that exists.
Note that the way Rational BuildForge solves this for ClearCase is by spawning an entirely new child-process solely to allow its' service to talk to ClearCase:
https://www-304.ibm.com/support/docview.wss?uid=swg1PK50021
Also note that the "logon session" is identified by a unique token; this means that even if you have a process running as your desired user (domain\fred) that can access ClearCase, spawning a new process from there as the same user (domain\fred) may not have the same session token by default, depending on how it was created (i.e. CreateProcess() vs CreateProcessAsUser() vs CreateProcessWithLogonW()), making it ever more difficult to deal with tools you don't control. To demonstrate this, try running 'runas /user: "cmd /k \"net use\""' from a command prompt and you'll see all your network drives listed as "Unavailable"(!!).
It is possible (though explicitly not recommended by Microsoft), with great effort, to get this all to work if you can somehow manage to have a user always logged in from which to get their session token, as described here:
starting a UAC elevated process from a non-interactive service (win32/.net/powershell)
Otherwise, you'd have to emulate it like BuildForge does.
Also see:
Network drive is unavailable if mapped by service
Map a network drive to be used by a service
For this sort of problem I've typically run into it with CI servers (CC.NET / Hudson / TeamCity) that run as a Windows service. What I've had to do is ensure that somewhere before my real "job" was started, I scripted a way to map network drives by re-mapping them at runtime or mapping M:\ to an available drive letter with subst (very tedious) as VonC describes, which isn't persistent (even if you use 'net use /persistent:yes') which is what I'm guessing you were hoping for too.

Why do forms fail in Windows Services

I understand that Window's Services have no desktop, and can't access any of the user's desktops directly (indeed, they can run when there is no desktop loaded). Why is it though that launching a form in a Window's Service causes an error?
A service should run without any user interaction, so there is no need for a form. If a service has to wait around for user feedback then it probably isn't going to be doing what it is supposed to.
You have to understand three related concepts: sessions, windows stations and desktops. But because there's a one-to-one relationships between sessions and stations, we can broadly ignore stations for this discussion. A session contains a station (winSta0 being the only interactive station) and stations contain one or more desktops.
Now session architecture differs according to Windows version. For NT <= 5 (XP/2003 and everything before them) services execute in session 0 along with the interactive user's apps. This is why you can configure services to interact with the desktop in these Windows NT versions - they are in the same session. For NT >= 6 (Vista, Server 2008 going forwards), services exists in session 0 but the interactive desktop is in another session. This is what's known as "service hardening", and is basically a security fix.
So since session 0 apps cannot get at the interactive console, it makes no sense for them to attempt to display a user interface of any kind.
Just to make this more confusing, Vista has a temporary kludge to cater for this situation: if an app in session 0 tries to create a dialog, Windows will trap this and present a warning to the user so they switch to a (I presume temporary) desktop where they can interact with the dialog. However this measure is explicitly temporary and you cannot rely upon it being in future Windows releases. I've seen this working in native code, but I suspect you are in managed code and the runtime is being smart enough to catch your behaviour and deliver a metaphorical slap to the hindquarters :-).
Ummm... what and whose desktop is that form going to appear on, exactly? A 'desktop' is an operating system concept: each window handle is owned by a specific desktop within a window station belonging to a single (interactive) user. The process within which the service is executing isn't going to find the user's visible desktop in its window station. For a rather dry reference, look at MSDN.
Actually, it's even nastier. You might be able to configure permissions for the service to be able to create a desktop -- but then nobody will see it! Alternatively, you could grant the process the rights to switch desktops, and confuse the heck out of the user!
There's a setting you must enable in order to allow your Windows Service to access certain folders directly (like desktop) or show forms (including MessageBox pop-ups): "Allow service to interact with desktop"
To see this, right click on My Computer => Manage => Services and Applications => Services. Double-click on a service to access its properties. On the "Log On" tab there is a checkbox for this setting.
Here is an article for how to set it programmatically in C#
[Edit] As Stephen Martin points out in the comments: this is only valid advice for pre-Vista versions of Windows.
Because if nobody is going to see the Form, nobody is going to dismiss it - running a modal dialog is a recipe for a hang - so you want it to complain loudly when this happens rather than sit there quietly until you kill the process (or look at a stack trace to determine what'd going on). (The other obvious problem is, who is going to pick the DialogResult if there is more than one possibility?) You want to know when this is happening. (Assert dialogs that dont throw if they cant show anything are a fun way of making people mad.).
In other words, because you want to know when things are confused enough in your code that a dialog is being shown within a service context.
(I'm assuming you're using Windows Forms on .NET, eve though you didnt tag it as such)
(If you have correctly configured things such that the service is allowed to interact with the desktop, you won't get an Exception)
When a Windows Service is started it is assigned to a Window Station and Desktop according to well documented, though somewhat obscure rules. As mentioned elsewhere it is not assigned to the interactive desktop (unless it is set to interact with the desktop on a pre-Vista OS) but it definitely runs in a desktop.
It is a common misconception that services cannot use UI elements. In fact many services (such as SQL Server) have in the past used hidden windows and windows messages for thread synchronization and work distribution purposes. There is no reason that a Form cannot be shown in a service. If you are getting an error it is due to something you are doing with the form or some component that is on the form. The most likely issues have to do with whether or not you need an STA thread for your form or are you creating a message pump for your form or something similar.
While you certainly can use a form in a Windows Service you almost certainly shouldn't. There will be threading issues, cross apartment call issues, possible blocking UI issues, etc. There are a very few situations where using a window in a service is a good choice but there is a better way, with no UI, in 99.99% of all cases.
Because at the time when the operating system needs to paint the window there is nothing to draw the form on.

Resources