Reputation: 7483
Ok, this is making me crazy. I'm writing a simple program that walks down the directory tree looking at the sizes of all files on my drive. Pretty tame stuff.
But I noticed that I wasn't getting the answer I expected. Turns out my code is skipping some directories. To start, here's a (simplified) version of my code:
#include <stdio.h>
#include <Windows.h>
int main()
{
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(L"c:\\Windows\\System32\\wbem\\*.*", &fd);
if (h != INVALID_HANDLE_VALUE)
{
BOOL b;
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
printf("d: %S\n", fd.cFileName);
//else
// printf("f: %S\n", fd.cFileName);
b = FindNextFile(h, &fd);
} while (b != FALSE);
FindClose(h);
}
}
The output I am getting is pretty much what you would expect:
d: .
d: ..
d: AutoRecover
d: en-US
d: Logs
d: Repository
d: tmf
d: xml
However, from a command prompt in c:\Windows\System32\wbem, dir /ad
gives me:
06/15/2016 07:20 PM <DIR> .
06/15/2016 07:20 PM <DIR> ..
04/14/2016 05:40 PM <DIR> AutoRecover
03/24/2011 03:52 PM <DIR> en-US
07/13/2009 06:34 PM <DIR> Logs
07/13/2009 09:08 PM <DIR> MOF
02/20/2017 10:32 PM <DIR> Performance
02/23/2017 03:59 AM <DIR> Repository
07/13/2009 06:36 PM <DIR> tmf
07/13/2009 07:20 PM <DIR> xml
0 File(s) 0 bytes
10 Dir(s) 171,203,104,768 bytes free
A close examination reveals that the Performance
and MOF
directories are not listed in my output. Huh?
Clearly something is different about these directories. But what?
dir
output, we can see that they are not junctions.I'm stumped. I've even gone so far as to run chkdsk /f
to see if my directory tables are screwed up. Other than some Cleaning up 472 unused index entries from index $SII of file 0x9. Cleaning up 472 unused index entries from index $SDH of file 0x9.
it didn't find anything.
I've tried using FindFileEx with various options, but I still can't get these directories to appear.
I can't think what else to try. What would cause these directories to appear for dir
but not for FindFile
? And (more importantly) how can I get them to appear in FindFile?
FWIW:
Upvotes: 0
Views: 873
Reputation: 595329
Your code is trying to access the 64-bit System32
folder.
I'm guessing your code is compiled as 32-bit, thus you would actually be accessing the 32-bit SysWOW64
folder instead due to the File System Redirector. On my Win7 x64 machine, the missing folders (MOF
and Performance
) only exist in the 64-bit System32\wbem
folder, but not in the 32-bit SysWOW64\wbem
folder.
If 32-bit code wants to access the 64-bit System32
folder, it has to use WOW64's special Sysnative
alias to avoid redirection, eg:
HANDLE h = FindFirstFile(L"c:\\Windows\\Sysnative\\wbem\\*.*", &fd);
Use IsWow64Process()
to know if your code is running inside of the WOW64 emulator or not.
With that said, you should not hard-code the c:\\Windows
path, either. Not all users install Windows to that path. Use GetWindowsDirectory()
, SHGetFolderPath(CSIDL_WINDOWS)
, or SHGetKnownFolderPath(FOLDERID_Windows)
instead to get the actual path.
Try something more like this:
bool IsRunningInWow64()
{
#ifndef _WIN64
BOOL bIsWow64 = FALSE;
if (IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64)
return true;
#endif
return false;
}
...
WCHAR szMask[MAX_PATH];
if (IsRunningInWow64())
{
// Must be a 32-bit process running on a 64-bit system.
// Use the 'Sysnative' alias...
GetWindowsDirectory(szMask, MAX_PATH);
// or: SHGetFolderPath(..., CSIDL_WINDOWS, ...);
// or: SHGetKnownFolderPath(FOLDERID_Windows, ...);
PathAppend(szMask, L"Sysnative");
}
else
{
// Must be either:
// - A 32-bit process running on a 32-bit system.
// - A 64-bit process running on a 64-bit system.
// Use the standard 'System32' path...
GetSystemDirectory(szMask, MAX_PATH);
// or: SHGetFolderPath(..., CSIDL_SYSTEM, ...);
// or: SHGetKnownFolderPath(FOLDERID_System, ...);
}
PathAppend(szMask, L"wbem");
PathAppend(szMask, L"*.*");
HANDLE h = FindFirstFile(szMask, &fd);
Upvotes: 3