C++ - How to read system files - c++

I'm trying to find a file that starts with "silabs-cdc" in "C:\\Windows\\System32\\DriverStore\\FileRepository"
DIR *dir;
struct dirent *ent;
if ((dir = opendir(path.c_str())) != NULL) { // FAILED
while ((ent = readdir(dir)) != NULL)
{
std::string fln = ent->d_name;
if(fln.substr(0,10) == "silabs-cdc")
{
// I found it
break;
}
}
closedir(dir);
}
but on windows vista the opendir always ends up with error as the folder did not exist (but it exists!), windows xp, windows 10 works just fine. I also tried findfirstfile function, but same result.
Is there any system folder protection? Is it possible to get through it - programmatically?
BTW: non system folders works fine, path to the folder is correct
EDIT: running program as admin will do nothing

Based on our comment exchange, it looks like on Vista, you built a 32 bit executable, but the drivers were installed as 64 bit drivers. The WOW64 redirection facility means that even though you tried to open a path under C:\Windows\System32, you actually opened a path under C:\Windows\SysWOW64. You could explicitly disable the redirection or you could build your executable to match the bittedness of the system, as a 64 bit executable will not be subject to redirection.

Related

boost::filesystem How to handle directories with no permissions

I am running into an error while trying to enumerate a directory using boost::filesystem.
The error appears when I try to enumerate a directory for which I have no permissions on an SMB shared directory - ie, I have RW on the share but a subdirectory on the share is access denied.
Platform etc:
Windows 10.
C++ 17 code.
Visual Studio 2019.
Unicode VS project (thus the use of std::wstring).
Shared folders from a Samba server running on Linux.
Sample code below, then details of the fail.
int enumerate(const std::wstring dir_to_enumerate) {
if (directory.size() == 0)
return -1;
boost::filesystem::path dir_to_enumerate(dir_to_enumerate);
boost::system::error_code ec;
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
if (ec.value())
return -4;
if ( ! boost::filesystem::is_directory(dir_to_enumerate))
return -3;
boost::filesystem::directory_iterator it{ dir_to_enumerate };
while (it != boost::filesystem::directory_iterator{}) {
// ... do stuff
}
return 0;
}
Consider a folder C:\temp2 with permissions removed for my account. The test
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
reliably detects C:\temp2 is not accessible.
Consider a folder "temp2" located on a Samba share T:. This folder on the Linux box is /data/temp2. So the directory passed into the function is L"T:\temp2", and that corresponds to location /data/temp2 on the Linux filesystem.
Samba itself shares the location R/W.
If on the Linux server the EXT4 permissions of the directory /data/temp2 are R/W (mode 700, or 750, or 755 you get the idea) for my account then everything works as expected, I can enumerate the contents of T:\temp2
The problem shows up detecting the following case reliably:
If I set the EXT4 permissions on the directory /data/temp2 to denied (mode 000) then the above code behaves unpredictably...
Sometimes, most of the time, the test
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
detects T:\temp2 is not accessible.
But occasionally exists() returns true, and we fall thru to testing the boost::filesystem::error_code value.
However the error_code never indicates an error.
In this case the line
boost::filesystem::directory_iterator it{ dir_to_enumerate };
always throws. I can't figure out exactly what it is throwing.
I'm pulling my hair out. Can anyone tell me what I am missing, or even just what the directory_iterator initializer is throwing?
(And... if I may be so forward: please do not tell me to just use std::filesystem. On Visual Studio 2019, and AFAIK C++17 itself, std::filesystem is incomplete. Boost::filesystem works better.)

Compiling 32-bit programs and calling 64-bit programs on 64-bit systems

My system is 64 bit.
I have a program calls a command "bcdedit.exe"
c++ code:
ShellExecuteA(NULL, "open", "cmd.exe", "/c bcdedit.exe /?", NULL, SW_SHOWNORMAL);
I compiled to 32 bit
When I run it back "file not find"
When I compiled to 64 bit, run passed
The same problem exists in go
go code:
cmd := exec.Command("cmd.exe","/c","bcdedit.exe /?")
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
}
fmt.Println(string(out))
I found "bcdedit.exe" in another directory:
C:\\Windows\\WinSxS\\amd64_microsoft-windows-b..iondata-cmdlinetool_31bf3856ad364e35_10.0.17134.471_none_69b0e05efb5a4702\\bcdedit.exe
When I call the command in this directory, all passed
This directory is different on every PC
How do I run the 32-bit compiled program for this command on each PC
So your code attempts to launch "bcdedit.exe". From the command line, the only location of bcdedit.exe in your PATH environment is the Windows System directory, c:\Windows\System32.
When you compile your code as 32-bit and run it on a 64-bit system, your process's view of the file system will change. Namely, the process view of the C:\Windows\System32 is replaced by the contents of C:\Windows\SysWOW64 - where only 32-bit DLLs and EXEs are located. However.... There is no 32-bit version bcdedit.exe located in this folder. (If you want to simulate this, go run c:\windows\syswow64\cmd.exe - you won't be able to find bcdedit.exe in the c:\windows\system32 folder anymore).
You probably need something like this: How to retrieve correct path of either system32 or SysWOW64?
Format your ShellExecute function to directly specificy the SysWow64 path for both bcdedit.exe and cmd.exe. Or as others have suggested, just compile for 64-bit.

WINAPI: File exists check fail

I want to check if a certain file exists in the specified location. I have been trying multiple solutions for that but seem like none of them work properly, since all of them return false.
There is no doubt that the file exists in the specified location.
Executable is being run as administrator, so I'm having the appropriate permissions.
Code I used:
#include <io.h>
#include <string>
#include <Shlwapi.h>
std::string str = "C:\WINDOWS\System32\iluminated.dll";
unsigned long attrib = GetFileAttributes(str.c_str());
bool exists1 = (attrib != INVALID_FILE_ATTRIBUTES &&
!(attrib & FILE_ATTRIBUTE_DIRECTORY)) &&
GetLastError() != ERROR_FILE_NOT_FOUND; // false
bool exists2 = ( _access( str.c_str(), 0 ) != -1 ); // false
bool exists3 = PathFileExists(str.c_str()) != 0; // false
Is there anything I'm doing wrong?
You should use double back slashes for paths, since if you use single back slashes in a string they are interpreted as command symbols (line \n, for example):
"C:\\WINDOWS\\System32\\iluminated.dll"
Alternatively, you can use forward slashes, they work on most operating systems:
"C:/WINDOWS/System32/iluminated.dll"
I found the answer. Turns out Windows is always redirecting system32 to syswow64 while trying to access in 64-bit Windows. I had to use SysNative directory, even though it doesnt exist - Windows redirects it to the proper system32 directory.
Since Visual Studio 2012, application projects default to “Any CPU
32-bit preferred”. If you run such an executable on a 64-bit Windows
operating system, then it will start as a 32-bit process and be
affected by WOW64 file system redirection.
When a 32-bit process on 64-bit Windows tries to access
"C:\Windows\System32", WOW64 redirects it to "C:\Windows\SysWOW64".
There are several ways to access the real "C:\Windows\System32"
directory:
Use "C:\Windows\SysNative", which WOW64 redirects to "C:\Windows\System32" even though it does not appear in directory
listings. This is an easy way and unlikely to cause problems.
Use Wow64DisableWow64FsRedirection and Wow64RevertWow64FsRedirection.
Use a 64-bit process.
Source: https://social.msdn.microsoft.com/Forums/en-US/c54f8368-035e-478e-b988-b180a3c7e3da/file-not-found-for-existing-file-in-system32-directory?forum=csharpgeneral

stat not returning properly on centos 7?

So I am running a C++ app, built with CMake (not by me). It works fine on other people testing with it, but not found anyone to test on centos7 yet.
The issue seems to arrise at this snippet of code:
struct stat fileStat;
if ( stat( pszFilePath, &fileStat) == -1 )
{
DEBUG_ERR(( "Can't open input dir [%s]\n", pszFilePath ));
return( false );
}
Which is the first part of the ReadFileInfo call here:
time_t dateChange;
DWORD dwSize;
if ( ! CFileList::ReadFileInfo( GetFilePath(), dateChange, dwSize ))
{
DEBUG_ERR(( "Can't get stats info for file '%s'\n", static_cast<LPCTSTR>(GetFilePath()) ));
return false;
}
Now, pszFilePath is many value, a few examples are:
'scripts/sphere_template_vend.scp'
'scripts/sphere_serv_triggers.scp'
The application is owned by root, the whole folder it all sits in is owned by root. The scripts folder is there and has read/write permissions as do all files (all also owned by root)
Running the application triggers both errors in the above code, there is nothing before them that influences anything.
Im not a C++ developer and do not have the tools to compile with debugs for checking the current path and so on, but I see no reason why it throws these errors. The files exist, the files are accessible, no one else seems to have this problem.
I do have cPanel on the server, but it shouldn't be causing any issues as I am using root user and also keeping out of the /home/ directory
Anyone know of any issue this could be because of? I tried with a '/sphere/' prepending the paths but it still has the same issue, it seems the application does not have access to the files (the application oddly reports line errors within the files it says it cannot read, but they do not match, so assuming its not correct).
Issue reported on the Github for the project here: https://github.com/Sphereserver/Source/issues/64
But no one seems to know whats going on

Get working directory on Windows Phone

How to get the current working directory on windows phone?
_wgetcwd and GetCurrentDirectory are not supported on windows phone.
Windows Store Apps don't have the notion of a "current directory" (the OS sets it to be the install location and doesn't let you change it).
The more interesting question is what you want to do with the working directory. Ordinarily, you would use WinRT StorageFile APIs to read and write files, but if you want to use CreateFile or fopen then you can get the path from a WinRT StorageFolder:
void foo()
{
using namespace Windows::ApplicationModel;
using namespace Windows::Storage;
auto installLocation = std::wstring(Package::Current->InstalledLocation->Path->Data());
auto dataLocation = std::wstring(ApplicationData::Current->LocalFolder->Path->Data());
OutputDebugString((installLocation + L"\r\n" + dataLocation).c_str());
}
For my test app, this prints
d:\temp\UniversalScratch\UniversalScratch\UniversalScratch.Windows\bin\x86\Debug\AppX
C:\Users\Peter\AppData\Local\Packages\257de9ed-b378-4811-98e6-226e15a3f7f0_tp1tpcm9wdwpy\LocalState
If you use fopen (or fopen_s) with a relative filename, it will be relative to your install package.