C++ Rename File # C:\Windows\System32\Drivers - c++

SOLVED: have a look on the later posts
TASK: rename a file called TabletFilter.sys ( its my graphic tablet driver ) because windows 8 (my OS) apps needs an other driver then photoshop for the pin pressure. And I want to write a c++ program that just rename all driver files to .old
The code based on the rename example from cplusplus.com
#include <stdio.h>
int main ()
{
int result;
char oldname[] ="TabletFilter.sys";
char newname[] ="TabletFilter.sys.old";
result= rename( oldname , newname );
if ( result == 0 )
puts ( "File successfully renamed" );
else{
result= rename( newname , oldname );
if( result == 0)
puts ( "File successfully renamed" );
else
perror( "Error renaming file" );
}
return 0;
}
I tried "run as Admin" as well, but I still get
Error renaming file: No such file or directory
what can I do?
EDIT:
The file is definitly in the same folder ... i copyed them both there... even at c:\windows\ i tryed it ... and i use a manifest
Executable: TabletRenameDriver.exe
Manifest: TabletRenameDriver.exe.manifest
Sample application manifest file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="TabletRenameDriver"
type="win32"/>
<description>Description of your application</description>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
i tryed uiAccess true and false.
Yes I have a problem with the rights
The driver is loaded but iam still able to change his name ... dont know why, but its possbile. I tryed it. I want to solve this problem with c++ so pls dont tell me that there are many script languages out there that can handle the problem very well ;-) I know this

The error message
No such file or directory
Means that the current directory does not contain files names "TabletFilter.sys" or "TabletFilter.sys.old".
What you can do is either:
Specify the full path to the file.
Ensure that the current directory, when your code executes, is the directory that contains your file.
However, even when you do this, your program may very well fail. You may not have sufficient rights to modify the contents of that folder. And the file you are trying to rename may well be locked if the OS has loaded the driver.
And as #Hans points out, the file system redirector could very well be confounding matters for you. The best way to avoid that is to us a 64 bit process.
I see no reason for using a C++ program here. Renaming files is a task best suited to a scripting language.

Many of those drivers are needed by Windows to startup. If you did succeed in renaming them, bad things will happen to your machine when you restart - namely your machine would not boot.
As a general rule, leave all of the stuff in C:\Windows alone, but this advice is ten-fold more important for the C:\Windows\drivers directory. Touch this folder and anything in it at your peril.

Thanks for all your help
I finished my programm and it works perfectly now
note: added "requireAdministrator" uiAccess="false" via VS2012 Settings
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
void main ()
{
bool success = false;
bool somethingWentWrong = false;
PVOID OldValue = NULL;
if( Wow64DisableWow64FsRedirection(&OldValue) )
{
success = MoveFile("C:\\Windows\\System32\\Drivers\\TabletFilter.sys", "C:\\Windows\\System32\\Drivers\\TabletFilter.sys.old");
if(success){
puts("from .sys to .sys.old");
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys.old");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf.old");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat.old");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat not found"); somethingWentWrong = true;}
}else{
puts("from .sys.old to .sys");
success = MoveFile("C:\\Windows\\System32\\Drivers\\TabletFilter.sys.old", "C:\\Windows\\System32\\Drivers\\TabletFilter.sys");
if(!success){ puts("ERROR: C:\\Windows\\System32\\Drivers\\TabletFilter.sys.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat.old not found"); somethingWentWrong = true;}
}
if(somethingWentWrong){
puts ( "ERROR: File were set to standart!" );
success = MoveFile("C:\\Windows\\System32\\Drivers\\TabletFilter.sys.old", "C:\\Windows\\System32\\Drivers\\TabletFilter.sys");
if(!success){ puts("ERROR: C:\\Windows\\System32\\Drivers\\TabletFilter.sys.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.sys.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.inf.old not found"); somethingWentWrong = true;}
success = MoveFile("C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat.old", "C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat");
if(!success){ puts("ERROR: C:\\Windows\\System32\\DriverStore\\FileRepository\\tabletfilter.inf_amd64_e7d03235d8288d3b\\TabletFilter.cat.old not found"); somethingWentWrong = true;}
}else
puts ( "File successfully renamed" );
Wow64RevertWow64FsRedirection(OldValue);
}
for(unsigned long tick = GetTickCount() / 1000; tick + 2 > GetTickCount() / 1000;){
}
}
With only 48 lines of code ... can a script be shorter?
PS: Revisiting this post after some time, I think there are quite a few ways to approach this issue differently. However, the main point still stands: If you want to do something like this, you have to run with admin permissions ... and maybe use loops, lists/vectors and some proper string manipulation :-P

Related

How can I iterate over a directory and identify or omit NTFS junctions (symlink-ish)

I have some code to list the files in a directory. For Windows Systems, I'm hoping to end up with a list of files and folders that matches what you'd see in Windows Explorer. For example, when I list C:\ on Server 2016, I want to have the Users folder but not the Documents and Settings junction. Currently I'm getting both, with no apparent way of differentiating between them.
My current code looks like this:
boost::filesystem::directory_iterator itr(dir);
boost::filesystem::directory_iterator end;
Poco::SharedPtr<Poco::JSON::Array> fileList(new Poco::JSON::Array);
for (; itr != end; ++itr) {
boost::filesystem::path entryPath = itr->path();
Poco::File file(entryPath.string());
// ...
I tried the Poco isLink() method, but it returns false for junctions.
I also tried Poco::DirectoryIterator, which gives the same behavior as Boost, and Poco::SortedDirectoryIterator, which always throws File access error: sharing violation: \pagefile.sys when reading C:\.
Ideally, this code should include symlinks on Linux and MacOS systems, while ignoring junctions on Windows.
Here's what I eventually came up with. It isn't a perfect solution - it's more of a heuristic than a proper identifier - but it seems to work well enough for my use case:
#ifdef _WIN32
#include <windows.h>
#endif
bool FileController::isNtfsJunction(const std::string& dirPath) const {
#ifdef _WIN32
DWORD attrs = GetFileAttributesA(dirPath.c_str());
if (INVALID_FILE_ATTRIBUTES == attrs) {
DWORD err = GetLastError();
logger.error("Could not determine if path is NTFS Junction: %s. Error: %s", dirPath, err);
return false;
}
return attrs & FILE_ATTRIBUTE_DIRECTORY &&
attrs & FILE_ATTRIBUTE_REPARSE_POINT &&
attrs & FILE_ATTRIBUTE_HIDDEN &&
attrs & FILE_ATTRIBUTE_SYSTEM;
#else
return false;
#endif
}

On Windows QDir::mkpath and QFile::rename report success despite failing

I'm trying to add auto-update functionality to the app I'm working on. My solution works well on Linux, but I'm running into weird problems on Windows.
After unpacking the update package I'm trying to move it to the destination directory using the following function:
inline void recursiveMoveOrCopy(QDir source, QDir dest, bool move)
{
auto files = source.entryInfoList(QDir::Files);
auto dirs = source.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
// move / copy files
bool success = QDir{}.mkpath(dest.path());
if (!success){
throw std::runtime_error(qs("Could not crate directory %1")
.arg(dest.path()).toStdString());
}
qDebug()<<"created directory"<<dest.path();
dumpvar(QDir{}.exists(dest.path()));
for (auto& file: files){
QString sourcePath = file.filePath();
QString fileName = file.fileName();
QString destPath = dest.filePath(fileName);
QString backupPath = destPath + "_bck";
bool success;
bool backup = false;
if (QFile::exists(destPath))
backup = QFile::rename(destPath, backupPath);
ON_EXIT{
if (backup) {
QFile::remove(destPath);
QFile::rename(backupPath, destPath);
}
};
if (move) success = QFile::rename(sourcePath, destPath);
else success = QFile::copy(sourcePath, destPath);
qDebug()<<qs("move from %1 to %2 was %3").arg(sourcePath, destPath, success?"successful":"not sucessful");
if (success && backup){
QFile::remove(backupPath);
backup = false;
}
if (!success){
throw std::runtime_error(qs("Failed to %1 file %2 to %3")
.arg(move?"move":"copy")
.arg(sourcePath)
.arg(destPath)
.toStdString());
}
}
// recursively move/copy dirs
for (auto &dir: dirs) recursiveMoveOrCopy(dir.filePath(), dest.filePath(dir.fileName()), move);
}
I made a small package for testing with just 2 files and 1 directory:
$ tree .
.
├── katalog
│   └── plik
└── plik2
When I try to install this "update" the following is written to debug output by the move function:
"moving C:/Users/piotrek/AppData/Local/Temp/dres-update-image to C:/Program Files (x86)/DRES"
created directory "C:/Program Files (x86)/DRES"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/plik2 to C:/Program Files (x86)/DRES/plik2 was successful"
created directory "C:/Program Files (x86)/DRES/katalog"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/katalog/plik to C:/Program Files (x86)/DRES/katalog/plik was successful"
As in: every single operation succeeded. But when I look into the target directory, the directory katalog doesn't exist (the file plik2 does however).
Note that even though the directory does NOT exist, QDir::exists reports that it does.
It's not a permission problem, when I was testing this I modified C:/Program Files (x86)/DRES to give Everyone full access.
Please tell me I'm not crazy. What the hell is going on here?
EDIT: Thanks to Rudolfs' suggestion to use Process Monitor I discovered the the files are actually being written to C:\Users\piotrek\AppData\Local\VirtualStore\Program Files (x86)\DRES. What exactly is going on here and how do I fix this?
Ok, I figured it out.
I had to use the following code to disable VirtualStore virtualization for the whole app:
#ifdef Q_OS_WIN32
#include <windows.h>
QString getWinError()
{
DWORD dw = GetLastError();
LPWSTR lpMsgBuf = NULL;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
0, NULL );
QString str = QString::fromWCharArray(lpMsgBuf);
LocalFree(lpMsgBuf);
return str;
}
bool disableVirtualStore()
{
HANDLE token;
DWORD tokenInformation = 0;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)){
qWarning()<<getWinError();
return FALSE;
}
ON_EXIT{
CloseHandle(token);
};
if(!SetTokenInformation(token, TokenVirtualizationEnabled,
&tokenInformation, sizeof(tokenInformation))) {
qWarning()<<getWinError();
return FALSE;
}
return TRUE;
}
#endif
Now I can normally write to all folders that I have write access to, and since Windows no longer lies to me about having write access, I can start an elevated helper app to move files to folders where I don't have write permission.

/usr/bin/env: node: No such file or directory , c++

i am writing some functions on c++ for compiler less to css.
i installed nodejs, less.
i created a less file test.less
#color: red;
a{color:#color;}
when i run command on terminal:
lessc test.less test.css
it created a files css with name is test.css, but when i run this command via c++, it return a error. please help me. this is my c++ function:
std::string shell_exec( std::string cmd )
{
std::string result = "";
FILE* pipe = popen(cmd.c_str(), "r");
if (pipe == NULL)
{
return result;
}
char buffer[128];
while(!feof(pipe))
{
if(fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
pclose(pipe);
return result;
}
shell_exec("lessc test.less test.css");
i got a error:
/usr/bin/env: node: No such file or directory
/usr/bin/node is existed.
================ UPDATE: Fixed==================
Thank you #Bass Jobsen , #Lightness Races in Orbit
i fixed by add absolute path to lessc and nodejs
shell_exec("/usr/bin/node /usr/bin/lessc test.less test.css");
From: https://unix.stackexchange.com/a/29620
The advantage of #!/usr/bin/env python is that it will use whatever
python executable appears first in the user's $PATH.
So you should add node to the $PATH of the user that runs your script, see: https://stackoverflow.com/a/13210246/1596547
Notice that i can not compile your code, but i can when using the following code:
int main()
{
std::string r = shell_exec("lessc test.less test.css");
}
Probably also use using namespace std and string instead of std:string.

stat() doesn't find a file in c++

on Linux 12.04
I have an executable file located in say:
/a/b/exe
and a config file on
/a/b/config
when doing:
cd /a/b/
./exe
everything's ok and the stat function finds the file config on /a/b/
HOWEVER,when running from root
/a/b/exe
the stat doesn't find the config file
any idea why?
it makes it impossible to run the binary using a script that isn't ran from the folder of the exe.
Edit
The call looks like this:
struct stat stFileInfo;
bool blnReturn;
int intStat;
// Attempt to get the file attributes
intStat = stat(strFilename.c_str(),&stFileInfo);
if(intStat == 0) {
// We were able to get the file attributes
// so the file obviously exists.
blnReturn = true;
} else {
// We were not able to get the file attributes.
// This may mean that we don't have permission to
// access the folder which contains this file. If you
// need to do that level of checking, lookup the
// return values of stat which will give you
// more details on why stat failed.
blnReturn = false;
}
In first case cd ..., run exe you change current working directory before executing the program, in second case you launch exe without changing current working directory, and I think in your program you use a relative path to open your config(for example ./config or just config) and it can't find it from current working directory. easiest workaround is to change working directory at start of your app:
int main(int argc, char** argv) {
std::string s( argv[0] ); // path to the program
std::string::size_type n = s.rfind( '/' );
if( n != std::string::npos ) {
std::system( ("cd " + s.substr(0, n)).c_str() );
}
// rest of your code
}

TinyXml to parse conf file

I`m try to realize how to use TinyXML library.
I have to parse this conf file:
<?xml version="1.0" encoding="UTF-8"?>
<Client>
<port num = "20035">
<server_addr ip="127.0.0.1">
<AV_list>
<AV>
<AVNAME>BitDefender</AVNAME>>
<AVPATH> C:\Program Files\Common Files\BitDefender\BitDefender Threat Scanner\av64bit_26308\bdc.exe </AVPATH>
<AVMASK>0x80000000</AVMASK>
<AVCOMMANDLINE> %avpath% \log=%avlog% %scanpath% </AVCOMMANDLINE>
<AVREGEX>(%scanpath%.*?)+(([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,4})+(.+[a-zA-Z_])</AVREGEX>
<AVLOG>C:\log\bd_log.txt</AVLOG>
</AV>
</AV_list>
</Client>
And c++ code
#include "stdafx.h"
#include "iostream"
#include "tinyxml.h"
int main(int argc, char* argv[])
{
TiXmlDocument doc( "D:\\client_conf.xml" );
bool loadOkay = doc.LoadFile();
if ( loadOkay )
printf("Yes \n");
else
printf("No \n");
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlText* pText;
TiXmlHandle hRoot(0);
pElem = hDoc.FirstChildElement().Element();
if (!pElem)
printf("error element");
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChild("server_addr").Element();
const char* info = pElem->Attribute("ip");
printf( "%s \n", info);
pElem = hRoot.FirstChild("port").Element();
info = pElem->Attribute("num");
printf( "%s \n", info);
system("pause");
return 0;
}
Now I can get first two param, but dont figure out how to reach "AV_list" block. Any help will be appreciated. (:
Have a look at the TinyXml Documentation. Your friend is the TiXmlNode Class Reference. You may use most of the Node functions also on TiXmlElements.
You already use the FirstChild() function to get the first child of an element; use the NextSibling() function to iterate over all elements. You can also use the NextSiblingElement() function to get the element directly.
Antother more sophisticated solution would be to use XPath to retrieve elements from the xml file. There is TinyXPath that builds on top of TinyXML. It needs some knowledge of XPath but it might be worth it. (XPath standard)