In a 32bit application, I have to copy a file to the 64bit system folder
(C:\Windows\System32\ instead of C:\Windows\SysWOW64\)
For this, I tried to get the folder using the WinAPI function SHGetKnownFolderPath with parameter FOLDERID_ProgramFilesX64 (GUID: 6D809377-6AF0-444b-8957-A3773F02200E).
But unfortunately, this is not allowed (as mentioned in the remarks section) and the function result correctly is 'file not found'.
Is there a way to accomplish this?
You are requesting the PROGRAM FILES folder, not the SYSTEM folder. Look at FOLDERID_System and FOLDERID_SystemX86 instead.
Alternatively, use FOLDERID_Windows to get the Windows installation folder, and then append the special SysNative alias to the end of it, let the File System Redirector locate the actual folder for you, per the documentation:
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. This mechanism is flexible and easy to use, therefore, it is the recommended mechanism to bypass file system redirection. Note that 64-bit applications cannot use the Sysnative alias as it is a virtual directory not a real one.
I'm confused why you would try FOLDERID_ProgramFilesX64 when you say you want the System32 folder, since the former would (if it worked) give you the Program Files folder. For the System32 folder, you want the GetSystemDirectory function.
You can use the catchily-named Wow64DisableWow64FsRedirection function to disable WOW64 redirection, which allow your 32-bit app to actually access the 64 bit system folder. Then use Wow64RevertWow64FsRedirection to restore the redirection once you're done.
Also note that it's not actually recommended to store your own files in the System folder any more (and hasn't been for quite some time), as this note in the docs for GetSystemDirectory says:
Applications should not create files in the system directory. If the
user is running a shared version of the operating system, the
application does not have write access to the system directory.
Related
Forgive me if the title is not so accurate.
I have met some problem when I am doing something related to COM server and registry redirection and not quite sure is my understanding is correct or not. Hoping anyone could share some light on it. Thanks in advance.
Basically a COM server has been registered in the registry before anyone can use its service. On a 64bit Windows OS, there could be 2 possible views in the registry table, one is for default and the other for the WOW64 view. For example, first registry key is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID{GUID}\LocalServer32 and the other is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32.
And depends on the process bitness (64bit vs. 32bit) that either one can be read by default, and also we can use KEY_WOW64_64KEY or KEY_WOW64_32KEY (as: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx) to access the other alternative registry key.
What I need is that, I want to get the LocalServer32 executable file by reading the registry key and this can work. The problem is that, for the executable file path I read back, do I need to do the file path translation (in order to get the correct value) depending on which view I get the value from? For example, if the file path is got from COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32 and the file path is: C:\Windows\System32\abc.exe, do I need to translate the path to: C:\Windows\SysWow64\abc.exe? Or do I need to translate C:\Program Files\abc.exe to C:\Program Files(x86).exe?
Another question is that, if, for some registry key for COM, the values set in the two Views are different (for example, one has C:\Program Files\abc.exe and the other has C:\Program Files(x86)\abc.exe), then when the COM server is started, how could svchost.exe know which one to start, C:\Program Files\abc.exe or C:\Program Files(x86)\abc.exe? Does anyone know the logic for svchost.exe to determine this? Use the first one if it exists otherwise use the second one?
Thanks a lot.
A 64-bit version of Windows already has all the features in place to make it unnecessary for you to take care of it yourself. You just need to keep the rules in mind when you troubleshoot problems.
First is the registry redirector, it ensures that a 32-bit client program cannot accidentally read keys that contain configuration information that's only appropriate for 64-bit programs. You already know it, most of the HKLM\Software registry accesses are redirected to HKLM\Software\Wow6432Node. This redirection is already in place when the COM server is registered, a 32-bit installer is automatically redirected to write the keys to Wow6432Node instead. The installer is completely unaware that Wow6432Node even exists. Everything falls together automatically, the installer is redirected and the COM server client is redirected as well. All that you care about is knowing where to look to verify that the install was done properly, you do have to look at HKLM\Software\Wow6432Node\Classes\CLSID with Regedit.exe to find the keys back.
File redirection works much the same way, any access to c:\windows\system32 is redirected to c:\windows\syswow64, from c:\program files to c:\program files (x86). And very similarly, a 32-bit installer doesn't have to know beans about this, it can simply use the legacy 32-bit path names. Same for any 32-bit client program, it will be redirected the same way. All that you care about is knowing where to look for a file to verify the installer.
This can only go wrong if bitness is mixed, a 64-bit program reading registry keys or files installed by a 32-bit program. Or the other way around. Like it does with your troubleshooting tools, like Explorer, Regedit and SysInternals' Process Monitor. In general something that should be strongly avoided in COM, most servers are in-process servers and running 32-bit code in a 64-bit process is not possible. The biggest reason that the registry and file redirectors exist in the first place.
Windows has several "virtual folders" and "special folders" (Wikipedia's names for them) that change the way the file system works. For example, the Desktop folder acts like the root of the file system hierarchy in some circumstances, even though C:/ is the drive, also called the partition, that the entire file system is on, and therefore logically Desktop should be under C:/. Screenshots: There are also the Library folders. Also, with msysGit and Cygwin on your computer, the program's folder then magically becomes the root of the file system.
I'm sure there are instances on other OS's, but I only really work with Windows, although it seems Linux is much less abstracted.
How do applications do this? Is it just a really complicated shell script, or something that only affects certain programs (Wikipedia says Desktop is only the root folder in Windows Explorer, for example)? Is it similar to how on Linux all folders are "mounted", even the root folder? Even if the OS developers don't usually give away their secrets, I would still like to know the basic method, if possible.
So, wikipedia's entry for special folder says that:
The Desktop virtual folder is the root of the Windows Shell namespace,
which contains other virtual folders.
This is not the same as saying it's "the root of the file system hierarchy". Windows has a set of set of virtual folders. All of these are nested under Desktop.
For Win7 and up, the default filesystem layout is actually:
Desktop -> C:\Users\(username)\Desktop
My Documents -> C:\Users\(username)\Documents
Downloads -> C:\Users\(username)\Downloads
These aliases mean something to the explorer shell, but not at the filesystem level (open cmd.exe and see what I mean).
At the filesystem level, and to an application, the filesystem path is what is going to matter. It takes extra API calls (the use of SHGetSpecialFolderPath()) to figure out where on the filesystem that special folder lives; the app only cares about where in the filesystem it needs to target.
As for Cygwin, I strongly suspect that it's doing something totally different. Unix has a special call, chroot(), that really does modify the root for the currently running shell. This means that applications running under that shell have absolutely no knowledge of the directory structure below the chroot()'d path, and this is generally done for security reasons. In fact, this is usually referred to as a chroot jail, because it isn't an alias or a virtual directory, and can't be escaped from (unless there's a bug in the kernel).
I have a 32-bit windows old application (with the C/Win32 source) that creates its data file in the same folder where the executable is.
Because the application has no installation program and the user can place the executable wherever he/she wants, the application has a dialog to inform the user where its data is located.
But under Microsoft Vista/Seven if the user puts the application in the Program Files or any other system-protected folder the data file gets virtualized and moved to a virtual-store.
If, under Vista/Seven, I still want to inform the user where the data file is located:
(without preventing virtualization in the manifest file)
How can I know (programatically) if the data file is virtualized? Or if the folder where the executable is located implies that data file will be virtualized?
Assuming I know the data file is virtualized, how can I know (programatically) the location of the virtual folder, to show it in the information dialog?
I have found the following question very close to what I'm asking but it doesn't show the solution (if any) of knowing when virtualization is taking place for a file, and where it gets virtualized.
How to detect file redirection to the Windows VirtualStore?
Virtualization is transparent to the app. The only way to know whether it is being virtualized is to ask the OS, per the answer in the question you linked to (use GetTokenInformation() with the TokenVirtualizationEnabled flag), but there is no way (that I know of) of asking the OS where the virtualized items are actually stored, as it may be different from one OS version to the next. You will have to do some research and then hard-code the paths for each given OS that your app detects at runtime.
If you are going to update your code to detect virtualization, then you are better off updating the code to play nicer with UAC instead. Stop storing your files where they do not belong, and start storing them where Microsoft wants you to store them. In this case, within the user's profile instead. Use SHGetFolderPath() or related function to locate the user's CSIDL_LOCAL_APPDATA folder (or SHGetKnownFolderPath() on Vista+ to locate the FOLDERID_LocalAppData folder), then create a subfolder underneath it for your app to store its data files in.
I'm currently writing some test code in C++ that messes around with PE files to understand its file format structure. My project is set to compile to 64 bit. In my code I open %SystemRoot%\system32\calc.exe and read the IMAGE_DOS_HEADER and IMAGE_NT_HEADERS structures. At the same time I have the same calc.exe opened in Notepad++ with the hex editor plugin. I compared the values my code reads with Notepad++ and noticed they were different. I copied calc.exe from System32 to C:\Temp\calc.exe, and now the values match.
Notepad++ seems to be a 32 bit application (haven't checked the PE file, but since it's installed to Program Files (x86) by default, it seems to be a safe assumption to make).
Is this WinSxS at work? Or what else is causing this? And which file is actually fed to 32-bit applications opening %SystemRoot%\system32\calc.exe?
Just curious. Thanks in advance for any light shed on this.
Yes, this is the WOW redirector. You'll see that there is a calc.exe in C:\Windows\SysWOW64 as well. That's the file that is opened when you use the %SystemRoot%\System32\calc.exe path.
This can be temporarily disabled to access the 64-bit version of the file with Wow64DisableWow64FsRedirection
More details can be found at File System Redirector
If I remember well, when a 32bit apps tries to open system32 directory, it's automatically redirected to syswow64 dir.
Disabling WowFs redirection is unnecessary and sometimes is not even an option (for instance, when you are attempting to get Notepad++ to open files in the system32 directory). You can use the virtual directory %windir%\Sysnative instead of %windir%\System32 (you will not see it in explorer, but you can type it in the address bar)
WOW64 is implemented in three DLLs: wow64.dll, wow64cpu.dll, and wow64win.dll (and 32-bit NTDLL). Redirection (among other things) is implemented in wow64.dll, CPU emulation / helper routines in wow64cpu.dll, and wow64win.dll contains thunks to win32k.sys (the kernel mode driver responsible for the windows GUI).
Trying to find third issue in the database with no luck.
So, I'm developing on a 64bit system (windows seven).
I'm making a simple console programme that check if a dll is present on the windows system. in that case I check in the system32 folder and then, in the sysWOW64 folder.
The pro gramme is 32bit application.
On a 32bit target platform, I can check normally the win32dll, as the SysWOW64 directory doesn't exist, no problem.
Bit when it execute on a 64bit system I can check the win32 directory, but the sysWOW64 directory always me point to the system32 directory.
It seems that on 64bit system there is a kind of redirection.
I'm trying to use the "Wow64DisableWow64FsRedirection" but I have "error C3861: 'Wow64DisableWow64FsRedirection': identifier not found" when I compile.
So there are two questions:
In winbase.h this function is disabled, how to get it work ?
How to determine if I'm currently on a 32 or 64 bit system as programme is running?
You don't have to search for DLLs. LoadLibrary() and LoadLibraryEx() will automatically search all relevant folders for you.
The search order is as follows:
The directory from which the application loaded.
The system directory.
The 16-bit system directory.
The Windows directory
The current directory.
The directories that are listed in the PATH environment variable.
If you're sure that you want to disable the redirection you can do so with Wow64DisableWow64FsRedirection as you mentioned. To make it "work", you have to set
#define _WIN32_WINNT 0x0501 (or higher)
before you include windows.h
About How to determine if i'm currently on a 32 or 64 bit system, I think that you could check the size of an int pointer...
int bits = IntPtr.Size * 8;
Console.WriteLine( "{0}-bit", bits );
While not perhaps what you're looking for, slightly wasteful if you know those are the only two places the file could be located, and possibly wouldn't work if the user has modified them (Although a whole host of other things will have broken for the user too), you could simply use the %Path% environmental variable.