Programatically registering .dll's on Windows Vista (using DllRegisterServer) - windows

Instead of calling regsvr32.exe, one can register a .DLL using the following steps:
HINSTANCE hLib = ::LoadLibraryEx(dllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
HRESULT (STDAPICALLTYPE* lpDllEntryPoint)(void);
(FARPROC&)lpDllEntryPoint = ::GetProcAddress(hLib, "DllRegisterServer");
const HRESULT hRes = (*lpDllEntryPoint)();
This works fine on Windows XP. Regrettably, it fails on Vista, but only with some specific DLLs. hRes becomes E_ACCESSDENIED. I guess this is a security issue. Does anyone know how to register a .DLL from code on Windows Vista?
Note: I was logged in as administrator when running this code.

COM registration requires write access to the HKEY_LOCAL_MACHINE part of the registry.
Under UAC, write access to the HKEY_LOCAL_MACHINE requires an elevated administrator.
The easiest way to get an elevated process is to create it with a manifest that specifies 'requireAdministrator' access. - Look under the Project Properties -> Configuration Properties->Linker->Manifest File->UAC Execution Level to set the correct setting.
This means you will probably want to split your EXE into two parts. The 'normal' asInvoker part, and, when self registration is detected as a requirement, an elevated InstallMyself part. When the non elevated part detects a first-run type condition, it needs to use ShellExecute(Ex) to execute the FirstInstall.exe part - using CreateProcess or some other API will simply fail with a insufficient privilege error. ShellExecute will present the UAC prompt.
It is possible to use Application Isolation to load COM dll's without any registration step at all.
Is is unfortunate that the cause cannot be determined. However, if you are interested in doing further research, a tool that will help a lot would be Process Monitor from SysInternals. Process Monitor can log all the File, Registry and other access for a process, including all success and fail codes making it a lot easier to debug problems like this without having to resort to deeper means of reverse engineering.

Regrettably, I couldn't get this to work for all DLLs, even with Chris Becke's excellent tips. I didn't want to spend too much time solving the problem, so now I simply call regsvr32.exe. I expect this .exe to be present on all Windows machines, so I guess it is a good enough solution.

Related

Get administrator privilegs in Qt during runtime [duplicate]

Is it possible to get a C++ application running in Windows to request administrator privileges from the operating system at run time?
I know it can be done at compile time, but can't seem to find anywhere whether it can be done at run time.
Thanks for your help!
EDIT: What if I want the current instance to have elevated privileges? For example, I might have data stored in memory which I want to keep.
If you want the application to always elevate, you can give it a manifest, either by building one in (not compiling technically) or by putting an external manifest in the same folder as the exe. If you want to decide, as a person, to run it elevated, you right click the exe or short cut and choose Run As Administrator. If you are launching it from code, then as #vcsjones comments, you use the runas verb when you launch that process. For example:
ShellExecute( NULL,
"runas",
"c:\\windows\\notepad.exe",
" c:\\temp\\report.txt",
NULL, // default dir
SW_SHOWNORMAL
);
You can elevate a process only during its creation. When a process already runs, there's no way to change its security token: it either runs elevated or not.
If your application needs to perform an administrative task, and it usually runs non-elevated, you have to create another .exe which will request elevation with its manifest. To start a process elevated, you have to use ShellExecute or ShellExecuteEx function. From your main process you will need a way to pass the commands to that new process that will run elevated.
For more information about UAC, read Designing UAC Applications for Windows Vista series.
Not quite, but you can do the opposite—you can drop privileges if you already have them. So, you can have your program start out running as an Administrator, using one of the methods listed by Kate Gregory. Then, drop your unneeded privileges; see Dropping privileges in C++ on Windows for how to do that.
Add a manifest file into your EXE as described here.
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Your process (and threads) have a token assinged to them. That token already have all your groups set up. Under UAC, the Administrator group is disabled. UAC will remove that disabled group so you end up with a full administrator token.
To acheive the same, you must have the TCB priviledge. In other words, to elevate a process at runtime, you will need help from a process running under the SYSTEM account, and Microsoft isn't providing one, nor an API to control the current UAC implementation. Otherwise, it would defeat the purpose.
For the sake of completness, there is a whitelist of process that can perform some elevated operations without prompting. In short, your executable needs :
To be signed by Microsoft
To perform predefined operations, like with IFileOperation
The best explanation I found is this hack. It has been fixed since then, but is sheds some light on the whole thing.

Is Windows registry redirection a "bad thing"?

I have my own installer program which I use to install several applications I have written.
I have been updating this program to avoid the application's data file updates going to the user's VirtualStore, as I read this was a "bad thing". I am doing this by storing the program and common data files separately in their correct locations, instead of sticking everything in Program Files like we used to do in the days of XP.
I am also now using SHGetFolderPath (yes, it's deprecated, but I still need to support my XP users), to get known folders instead of trawling the registry, which is another "bad thing" (I read).
The next thing I was trying to do was rewrite the installer code to avoid registry redirection to Wow6432Node when writing stuff to HKLM, as I thought this was another "bad thing".
However, although I could put the application specific stuff that goes there (like the install folder, if the user decides to install in other than the default), the killer is the need to put the uninstall info in HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall. For 32-bit stuff running on a 64-bit system, this is redirected to Wow6432Node. I don't see any way round this - is it in fact possible?
UAC registry redirection could reasonably be described as a "bad thing" because it is designed specifically to provide compatibility with improperly written software, i.e., software that assumes it is going to be run with administrator privilege.
WOW64 registry redirection is a different beast; it's designed to provide compatibility with properly written 32-bit software. If your software is 32-bit, and has no specific need to be 64-bit aware, there's nothing wrong with letting it run in the emulation environment as-is, including allowing registry settings to be redirected to Wow6432Node.
You can bypass WOW64 registry redirection if necessary, but you shouldn't do this arbitrarily, only if there is a specific reason. If WOW64 redirection worries you, the only good alternative is to provide a 64-bit version of your program.
This is a very "BAD THING" !
Microsoft solves a security problem by hiding thing at another place !
I've created a programm to ask the user for some additional parameters (language, directory for lessons) during installation of the app. I tested the programm profoundly, and the registry entries were made perfectly. However during setup the entries were hidden at some strange place!
If Microsoft wants to redirect these enties it should at least be some option to be set.
Never hide things, and think they will not notice, because it's transparant.
Doing this properly would involve an option to be set, so users are aware of the redirection !

install on windows 7 troubleshoot compatibility PCA - "This program might not have installed correctly”

Well, I'm using Visual C++ 2010 Express and ResEdit
for my midi sequencer's SETUP app.
Win32 API, no MFC, some custom window and control classes and such.
Now that I got Windows 7, my dang SETUP program is broke.
Windows gives me the ole "Did this app install correctly??" thingy.
Which implies that SOMEthing is wrong with my installer.
I'm tryin' to figure out what that might be...
I've seen these 2 SO threads:
"This program might not have installed correctly"
"This program might not have installed correctly" message in Windows 7 RC
Which have lead me to these places:
http://msdn.microsoft.com/en-us/library/dd371711(VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb756937.aspx
http://msdn.microsoft.com/en-us/library/aa905330.aspx#wvduac_topic3
http://blogs.msdn.com/b/cjacks/archive/2009/06/18/pca-changes-for-windows-7-how-to-tell-us-you-are-not-an-installer-take-2-because-we-changed-the-rules-on-you.aspx
http://community.flexerasoftware.com/archive/index.php?t-189007.html
Only registry entries I use are the standard uninstall spot and
associations for filetypes.
SETUP writes a dat.cfg file in program files\pianocheater dir
that points to where all the app's data is. (just a text file with a path in it)
(And an etc.cfg for a temp dir within that data dir to use.)
So I'm only READING from programfiles\pianocheater post SETUP.
Can anybody think of why Windows wouldn't like the install?
Source code is at http://shazware.com/_etc/SETUP_PIANOCHEATER.cpp
It uses my library of window, control classes similar in spirit to mfc.
I could send useful parts of it, too.
It's not toooo bad for a setup app.
Should be pretty ledgible for a win32 guy/gal.
I could uuuuuse some he'p...:/
Oh yeah, I should point out that Go() is the entry point instead of main().
The DBG()s just do OutputDebugString() and seem to all run just fine.
TStr is just a big char[MAX_PATH] (and I don't do unicode)
And the trick PROBably is that I'm on win7 64 bit, but this is a 32 bit app.
I'm pretty sure I'm using the registry correctly for assoc's and uninstall spot, though.
So is THE thing I SHOULD do the manifest xml thing?
Or is there a more correct way to do things?
thanks much,
...Steve
First off, check whether that message is a false positive or not. The message you're seeing is designed to use heuristics (which can be wrong!) to determine if an installer failed due to Windows Vista/7 compatibility issues. If your installer is in fact compatible with Windows 7/Vista, then all you need to do is add a manifest declaring itself compatible. You'll also want to add a requestedExecutionLevel entry to your manifest as well to request elevation.
If your installer is in fact failing, of course, then you ought to fix that first.
Finally, if the error is showing up because a launcher executable exits early or something like that, consider suppressing installer detection by adding the appropriate manifest entries to the launcher as well (you may be able to use a requestedExecutionLevel of asInvoker if the launcher doesn't need administrative access; the presence of a requestedExecutionLevel manifest entry should suppress installer detection). Note that you should make sure you use ShellExecute to invoke your main installer process, not CreateProcess, or UAC may not elevate the child process.

What are the differences between "Run as administrator" and a manifest with requireAdministrator?

I've written a program with a manifest that includes requireAdministrator. On Windows 7 systems with UAC enabled, Windows pops up a dialog asking for permissions, as it should. Works great.
If a user starts my program by right-clicking it and choosing "Run as administrator", then Windows 7 also pops up a dialog asking for permissions. However, there are some slight differences in how my program operates in some of the more esoteric parts of my program.
So what are the differences between "Run as administrator" and a manifest with requireAdministrator? Any links to documentation that describe differences would be appreciated.
Edit: This is with UAC enabled.
Edit: As promised below is the full explanation of the difference I'm seeing.
I'm using the EasyHook library to inject a DLL into another process. When my application is run with "Run as administrator", the injected process crashes and EasyHook returns the error "Unknown error in injected assembler code". None of the code in my DLL gets a chance to execute; the crash occurs before then. (Moreover, the crash occurs even if I strip the DLL down to nothing)
If I run my program normally (i.e., elevated via requireAdministrator), everything works fine.
My application is composed of a few different executables. The process that the user launches is not the same process that performs the injection.
With the information given there would be no differences in the permissions between the two processes.
If you request an execution level of "requireAdministrator" via the applications manifest your application will either be launched with the full access token of an administrator or not at all if the user denies consent (see Create and Embed an Application Manifest (UAC) for further information).
The same will happen when a user chooses Run as Administrator.
The only difference is the way that the process is started. When you start an executable from the shell, e.g. by double-clicking in Explorer or by selecting Run as Administrator from the context menu, the shell will call ShellExecute to actually start process execution. The whole process of elevation is hidden inside this function. Kenny Kerr describes this process in more details in Windows Vista for Developers – Part 4 – User Account Control:
ShellExecute first calls CreateProcess to attempt to create the new process. CreateProcess does all the work of checking application compatibility settings, application manifests, runtime loaders, etc. If it determines that the application requires elevation but the calling process is not elevated then CreateProcess fails with ERROR_ELEVATION_REQUIRED. ShellExecute then calls the Application Information service to handle the elevation prompt and creation of the elevated process since the calling process obviously doesn’t have the necessary permissions to perform such a task. The Application Information service ultimately calls CreateProcessAsUser with an unrestricted administrator token.
If on the other hand you want to create an elevated process regardless of what application information is available then you can specify the little-known “runas” verb with ShellExecute. This has the effect of requesting elevation regardless of what an application’s manifest and compatibility information might prescribe. The runas verb is not actually new to Windows Vista. It was available on Windows XP and Windows 2003 and was often used to create a restricted token directly from the shell. This behavior has however changed. Here is a simple example:
::ShellExecute(0, // owner window
L"runas",
L"C:\\Windows\\Notepad.exe",
0, // params
0, // directory
SW_SHOWNORMAL);
So essentially starting an executable using the Run as Administrator option means that ShellExecute bypasses the checks for compatibility settings, application manifests etc and directly requests elevation.
Kenny Kerr's article also has sample code to query the current process' token for its permission using the OpenProcessToken function. Possibly you can use the example to identify that there are no differences in the way your process is elevated.
I'm definitely curious to know which differences you are observing as I strongly doubt they are related to elevation.
As a last thing: Can you double check that you really request a level of requireAdministrator and not by mistake only a level of highestAvailable?
One possible difference might be the rarely used/understood/deliberately-chosen uiAccess attribute. Can you create two manifests, one with uiAccess=false and one with uiAccess=true, then tell us whether one of them gives the same behaviour as you see with right-click-run-as-admin?
The EasyHook documentation for the RemoteHooking class' IsAdministrator property mentions:
Due to UAC on Windows Vista, this property in general will be false even if the user is in the builtin-admin group. As you can't hook without administrator privileges you should just set the UAC level of your application to requireAdministrator.
It's hard to imagine why this is happening, but it is conceivable (especially as you are seeing it happen!) that assets, processes, assemblies, &c, with possibly different trust levels and so forth, will not inherit the elevation of your main app. Setting the requireAdministrator flag may handle/enforce this globally across the entire scope of resources and dependencies. Would love to know how this turns out.
I thought I was seeing a difference between these as well. However, it turned out that in my case the issue was this:
When I click "Run as Administrator" from my file browser (Q-Dir), the working directory is different than when I try simply double clicking an application with requireAdministrator set in the manifest. This changed the behavior of some buggy DLLs I had received. In fact, it turned out that 100% of the differences I saw were due to running from different working directories (specifically, it mattered whether I was on C: drive or a different drive letter) and that the method of getting the program to run as administrator had nothing to do with it.
It's an issue that is specific to my computer's exact configuration, but it is a possible clue into the type of thing that might be happening (or might have happened 7 years ago . . . )

Detecting registry virtualization

I have a set of C# (v2) apps and I am struggling with registry virtualization in Win7 (and to a lesser extent Vista).
I have a shared registry configuration area that my applications need to access in HKLM\Software\Company... Prior to Vista, everything was just written to and read from that location as needed.
The code appropriately detected failures to write to that registry key and would fall back appropriately (writing to HKCU instead and notifying the user that the settings they had applied would only affect the current user).
In Vista, registry virtualization broke all of this because the access check we were using for the HKLM write would "succeed" silently and virtualize to HKCR\VirtualStore\Machine... instead. In this case, the user would think that they had saved machine-wide configuration, but had instead only written to the virtual store.
Sadly, even attempting to enumerate the permissions on the HKLM reg key explicitly returns results indicating that the user has access whether they do or not.
When we added Vista support, the workaround we used was to perform a probe write to HKLM... and then check in HKCR\VirtualStore\Machine... for the same value and note that virtualization had occurred if the value was found.
Win7 seems to have broken this (again) because queries against the explicit virtual location (HKCR) now show merged results from the HKLM location even if the write was not virtualized.
Does anyone have any suggestions for working around this?
Constraints:
- I need a solution that works without requiring elevation (when I don't have administrator level permissions I will fallback to a per-user configuration in HKCU but I need to be able to detect this case reliably).
It needs to work with a v2 C# app (One option I have seen for C++ code is to embed a manifest which disables virtualization for the .exe but I haven't been able to do that in C# V2 see disable folder virtualization in windows).
It needs to work without an "installer" (this precludes the ability to disable virtualization on the registry key that we need ala the REG FLAGS... command).
This is an excellently put question, +1 (Why is it community wiki, it deserves points!)
In general, there are a set of rules (which [as you've run into] will vary over time) which control whether UAC [and thus implicitly Registry] virtualization are in play.
Some salient parts of the Registry Virtualization rulesets documentation in MSDN are:
[as jeffamaphone says] if the manifest has a requestedPrivileges/requestedExecutionLevel set, it's turned off. You dont seem to have ruled out adding a manifest, so can you please indicate why this won't work for you? (You say "I haven't been able to do that in C# V2" - there is an Add Item option to add an application manifest file, and that's available in VS2005)
if the exe is running 64 bit, its off by default
if it's not an interactive process (such as a service, or hosted in IIS etc.), it's off
If you're not in a position to influence any of the above, which is the ideal, and you thus want to detect whether UAC virtualisation applies in the current context, use this answer to a what might at first not appeat to be a related question. (Obviously you'd still need to decide whether it applies to the specific key you're operating on, which is a moving target which you obviously wouldnt want to implement code that needs to track changes if it can at all be avoided - but in most cases it should be relatively clear.)
You can enable / disable virtualization on a per key basis, according to this, but it tells you to use a command line tool. But there must be a way to do it programmatically.
It might be easiest just to turn off virtualization in your app completely by setting requestedExecutionLevel in your manifest. You can try highestAvailable, but that might mean your app always runs as Administrator. It seems to imply just setting it to asInvoker will turn off virtualization. See also.
Note that HKCR is a virtualized store itself, a combination of HKLM\Software\Classes and HKCU\Software\Classes.
The best approach would be to not even let the registry virtualization take place. Firstly check to see the user is is elevated at runtime and then you can notify the user that changes will only be applied to the current user before they even start making changes.
By detecting if you are an elevated administrator in the first place you can simply avoid writing to HKLM when it's going to be virtualized.
Example:
private bool IsAdministrator
{
get
{
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
}
Note: I don't code in C#, example is lifted from question How can I detect if my process is running UAC-elevated or not?
I had a similar problem and the introduction of a manifest solved it.
I was relying on the registry security to prevent the (Win32) application from creating keys in the HKLM/Software/Wow6432Node when running as standard user, and was quite surprised to see that it was succeceding regardless, but no key was present and it was created instead under this new VirtualStore area.
The registry virtualization is switched off when the PE manifest is found to contain information related to the security. To not require elevation of privileges my manifest contains the following node:
<trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker">
</requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
For the executable to be compatible with Vista and XP, apparently each node in the TrustInfo section must contain the namespace:
<ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
<ms_asmv2:security>
<ms_asmv2:requestedPrivileges>
<ms_asmv2:requestedExecutionLevel level="asInvoker">
</ms_asmv2:requestedExecutionLevel>
</ms_asmv2:requestedPrivileges>
</ms_asmv2:security>
</ms_asmv2:trustInfo>
Once the manifest was correctly embedded in my .exe (it took me a couple of attempts by modifying the appropriate properties of the project), the program was at last failing as I was expecting.
For managed code, the manifest can be included as a post-build step by running the mt.exe tool. For instance, as reported in the MSDN article
mt.exe –manifest YourFile.manifest –outputresource:YourApp.exe;#1
I prefer using the manifest approach rather than modifying the flags of the registry nodes using reg.exe as explained in this article as this makes the behaviour consistent on all machines.
Hope that helps (even if, after having read the date of the original posting, I'm pretty sure the problem has been solved long ago!!)
Alberto

Resources