CreateFile failing with errorcode 2, while file exists - c++

I try to open existing file via CreateFile, but it is always failing with errorcode 2 - like file doesn't exist, but it exists - it's in folder with executable.
hFile = CreateFile( argv[ 1 ], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
printf( "\nError: Unable to open file (%d)\n", GetLastError( ) );
return -1;
}
it fails even if I replace argv[1] with hardcoded filename string.
app is running as an admin.

The error code is accurate. The file cannot be found. Possible explanations include:
You used the wrong file name.
You used a relative path and the process working directory is not what you expect it to be.
If you wish to interpret the file name as being relative to the directory in which the executable resides then do that. Form an absolute path from the directory containing the executable and the specified file name.
There is no reason to expect a process working directory to be the directory in which the executable resides.

You are attempting to open a file using a relative pathname. Relative pathnames are relative to the current working directory (see GetCurrentDirectory). The current working directory is not necessarily the directory, where the executable image resides. It can be different for a number of reasons, for example:
The application was launched through a shortcut that explicitly sets the working directory.
The application called SetCurrentDirectory.
The application was launched through the command interpreter from a directory other than the executable's directory.
If you want to open a file located relative to the application's executable image, you need to construct a fully qualified pathname, based on the executable's location and the desired filename. The following code retrieves the executable's directory1):
#include <windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
#include <string>
#include <vector>
std::wstring GetExePath() {
// Retrieve fully qualified module pathname
std::vector<wchar_t> buffer( MAX_PATH );
DWORD cbSize = ::GetModuleFileNameW( nullptr, buffer.data(),
static_cast<DWORD>( buffer.size() ) );
while ( cbSize == buffer.size() ) {
buffer.resize( buffer.size() + MAX_PATH );
cbSize = ::GetModuleFileNameW( nullptr, buffer.data(),
static_cast<DWORD>( buffer.size() ) );
}
if ( cbSize == 0 ) {
throw ::GetLastError();
}
// Remove filename from fully qualified pathname
if ( ::PathRemoveFileSpecW( buffer.data() ) ) {
::PathAddBackslashW( buffer.data() );
}
// Construct string object from character buffer
std::wstring str( &buffer[0] );
return str;
}
This can be used as follows:
int wmain( int argc, const wchar_t* argv[] ) {
if ( argc <= 1 ) {
return -1;
}
std::wstring pathname = GetExePath();
pathname += argv[1];
HANDLE hFile = ::CreateFileW( pathname.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
wprintf( L"\nError: Unable to open file (%d)\n", GetLastError() );
return -1;
}
// ...
::CloseHandle( hFile );
return 0;
}
1) Code targeting Windows 8 and later should use PathCchRemoveFileSpec and PathCchAddBackslash instead.

Related

Dll Injector not detecting Dll

I recently coded an injector where as long as the dll is in the same directory as the exe injector it will inject but even when the dLL is in the same path it still returns with the error file not found.
Very new to c++ so not exactly sure how to fix it, only this I know that the problem must lie in the dll_name
The c++ code is listed here
#include <Windows.h>
#include <string>
#include <thread>
#include <libloaderapi.h>
using namespace std;
void get_proc_id(const char* window_title, DWORD &process_id)
{
GetWindowThreadProcessId(FindWindow(NULL, window_title), &process_id); // Find Process ID by using title of window
}
void error(const char* error_title, const char* error_message)
{
MessageBox(NULL, error_message, error_title, NULL);
exit(-1);
//if error occurs output false
}
bool file_exists(string file_name) // Makes sure file exists
{
struct stat buffer;
return (stat(file_name.c_str(), &buffer) == 0);
//Information goes through buffer if = 0 , it worked
//Creates random buffer of stat sturc doesnt matter what goes in - making sure function is successful, gets info about file and checks if it workeed
}
int main()
{
DWORD proc_id = NULL;
char dll_path[MAX_PATH];
const char* dll_name = "TestDll2.dll"; //Name of Dll
const char* window_title = "Untitled - Paint"; //Must Match Title Name
if (!file_exists(dll_name));
{
error("file_exists", "File does not exist");
}
if (!GetFullPathName(dll_name, MAX_PATH, dll_path, nullptr))
{
error("GetFullPathName", "Failed to get full file path");
}
get_proc_id(window_title, proc_id);
if (proc_id == NULL)
{
error("get_proc_id", "Failed to get process ID");
}
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, NULL, proc_id);
if (!h_process)
{
error("OpenProcess", "Failed to open handle to process");
}
void* allocated_memory = VirtualAllocEx(h_process, nullptr, MAX_PATH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); //Calling Virutal Allocation, passing handle to process - reserving memory by going thru reserve and need to commit to it so we can write
if (!allocated_memory)
{
error("VirtualAllocEx", "Failed to allocate memory");
}
if (!WriteProcessMemory(h_process, allocated_memory, dll_path, MAX_PATH, nullptr)) // Write DLL path into the target program
{
error("WriteProcessMemory", "Failed to write process memory");
}
//If above works we call loadlibarya which is where the dll is stored
HANDLE h_thread = CreateRemoteThread(h_process, nullptr, NULL, LPTHREAD_START_ROUTINE(LoadLibraryA), allocated_memory, NULL, nullptr);
if (!h_thread)
{
error("CreateRemoteThread", "Failed to create remote thread");
}
CloseHandle(h_process);
VirtualFreeEx(h_process, allocated_memory, NULL, MEM_RELEASE);
MessageBox(0, "Successfully Injected!", "Sucess", 0);
} ```
Try to use C++ STL function or Windows native API:
#include <string>
#include <filesystem>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
bool IsExists(const std::string &FilePathName)
{
return std::filesystem::exists(FilePathName);
}
bool IsExists(const std::string &FilePathName)
{
return PathFileExistsA(FilePathName.c_str());
}
The file is being searched in the current directory, not in the directory of the exe file. These might not be the same. You have to find the path to the exe file in order to search for files in its directory. On Windows you could do something like this:
#include <psapi.h>
// ....
HANDLE Handle = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, GetCurrentProcessId() );
if ( Handle ) {
TCHAR buffer[MAX_PATH];
if ( GetModuleFileNameEx( Handle, 0, buffer, MAX_PATH ) ) {
std::filesystem::path exePath( buffer ); // TODO this might need encoding conversion
auto exeDir = exePath.parent_path();
auto dllPath = exeDir / "TestDll2.dll";
if ( std::filesystem::exists( dllPath ) ) {
// ...
}
}
}
You can also try GetProcessImageFileName if GetModuleFileNameEx does not work. Apparently it does not work in 32-bit applications on a 64-bit system (see comments in this answer).

How to check if any file exist in specific folder?

I am using CreateProcess to copy files. Also I can catch different errors, if PC is offline, if directory does not exist.
Here is the problem I have: It returns 0 as error code, if all copying is successful and also returns 0 if there were zero files in source folder, so no copying is done. I must detect whether there are no files in source folder. How can I do it in MFC VC++ 2013?
I have spent hours trying different solutions, but my knowledge is not high enough to implement all I find on internet. So I have to ask for code, then I will understand. Thank you in advance.
This is code I use:
temp_dest = _T("/min /c xcopy \"D:\\Test\\*.*\" \"") + m_destination + _T("\" /Y /E /Q");
LPTSTR temp_dest2 = (LPTSTR)(LPCTSTR)temp_dest;
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(STARTUPINFO));
memset(&pinfo, 0, sizeof(PROCESS_INFORMATION));
sinfo.dwFlags = STARTF_USESHOWWINDOW;
sinfo.wShowWindow = SW_HIDE;
BOOL bSucess = CreateProcess(L"C:\\Windows\\System32\\cmd.exe", temp_dest2, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &sinfo, &pinfo);
DWORD dwCode;
TerminateProcess(pinfo.hProcess, 2);
GetExitCodeProcess(pinfo.hProcess, &dwCode);
TCHAR msg2[100];
StringCbPrintf(msg2, 100, TEXT("%X"), dwCode);
MessageBox(msg2, (LPCWSTR)L"DWCode 2", MB_OK | MB_ICONERROR);
if (dwCode == 4)
{
MessageBox((LPCWSTR)L"DW 4", (LPCWSTR)L"Path not found", MB_OK | MB_ICONERROR);
}
if (dwCode == 2)
{
MessageBox((LPCWSTR)L"DW 4", (LPCWSTR)L"PC Offline", MB_OK | MB_ICONERROR);
}
If you can use directory_iterator from <filesystem> header file introduced in C++17:
bool IsEmptyDirectory( const wchar_t* dir )
{
return std::filesystem::directory_iterator( std::filesystem::path( dir ) )
== std::filesystem::directory_iterator();
}
May be needed std::experimental::filesystem instead of std::filesystem.
I have tried to port it to VC 2013, but only char version seems to compile
bool IsEmptyDirectory( const char* dir )
{
return std::tr2::sys::directory_iterator( std::tr2::sys::path( dir ) )
== std::tr2::sys::directory_iterator();
}
If you want (or have) to use WinAPI:
bool IsEmptyDirectory( const wchar_t* dir )
{
wstring mask( dir);
mask += L"\\*";
WIN32_FIND_DATA data;
HANDLE find_handle = FindFirstFile( mask.c_str(), &data );
if ( find_handle == INVALID_HANDLE_VALUE )
{
// Probably there is no directory with given path.
// Pretend that it is empty.
return true;
}
bool empty = true;
do
{
// Any entry but . and .. means non empty folder.
if ( wcscmp( data.cFileName, L"." ) != 0 && wcscmp( data.cFileName, L".." ) != 0 )
empty = false;
} while ( empty && FindNextFile( find_handle, &data ) );
FindClose( find_handle );
return empty;
}
You can use the WIN32 function GetFileAttributes(..) to check if a file exists or not:
if (GetFileAttributes("C:\\test.txt") != INVALID_FILE_ATTRIBUTES)
{
/* C:\test.txt is existing */
}
Another way just might be trying to open the file (and if successful to close it again).

Finding where a symbolic link points to (Windows)

I use FindFirstFile() and co-functions to browse the contents of C:\example\dir. I know that a file read can be a symbolic link, a junction, etc by checking whether d.dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0. However, I haven't found a way to follow the link and see the location it is pointing to. Is that even possible?
To find the target of a symbolic link, you have to open the symbolic link. The object manager dereferences the link and returns a handle to the target location. Calling GetFinalPathNameByHandle on that handle returns the pathname of the target.
The following implementation returns the target location, given a symbolic link:
std::wstring GetLinkTarget( const std::wstring& a_Link ) {
// Define smart pointer type for automatic HANDLE cleanup.
typedef std::unique_ptr<std::remove_pointer<HANDLE>::type,
decltype( &::CloseHandle )> FileHandle;
// Open file for querying only (no read/write access).
FileHandle h( ::CreateFileW( a_Link.c_str(), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ),
&::CloseHandle );
if ( h.get() == INVALID_HANDLE_VALUE ) {
h.release();
throw std::runtime_error( "CreateFileW() failed." );
}
const size_t requiredSize = ::GetFinalPathNameByHandleW( h.get(), nullptr, 0,
FILE_NAME_NORMALIZED );
if ( requiredSize == 0 ) {
throw std::runtime_error( "GetFinalPathNameByHandleW() failed." );
}
std::vector<wchar_t> buffer( requiredSize );
::GetFinalPathNameByHandleW( h.get(), buffer.data(),
static_cast<DWORD>( buffer.size() ),
FILE_NAME_NORMALIZED );
return std::wstring( buffer.begin(), buffer.end() - 1 );
}
Note: For details about the RAII wrapper based on std::unique_ptr see std::unique_ptr, deleters and the Win32 API.

Add/Remove bytes from end of file on Windows

So, I've looked around, but couldn't find a way to remove bytes from the end of a file without rewriting the entire file. I found that a truncate function works for linux, but didn't find anything for windows. Now, obviously, to expand a file, I can just pad the end with null bytes, but for reducing a file's size, is it literally necessary to rewrite the whole file on windows? or is there a function, maybe in windows.h, that allows me, like truncate on linux, to reassign a file's size?
EDIT: I did just find the function _chdir(int,long), and I'm reading on how to use it.
EDIT: And, why exactly did fstream leave out this vital function?
EDIT: Ok, so it appears that _chdir() will not work (I forgot to mention this, btw), because the function must support files larger than 4 GB - i.e., I'm using 64bit file pointers. I thought that would be inherent, but after reading the arguments to chsize, the length is not size_t.
You truncate a file by calling SetFilePointer or SetFilePointerEx to the desired location followed by SetEndOfFile. The following shows how a truncate function can be implemented:
bool truncate( HANDLE hFile, LARGE_INTEGER NewSize ) {
LARGE_INTEGER Size = { 0 };
if ( GetFileSizeEx( hFile, &Size ) ) {
LARGE_INTEGER Distance = { 0 };
// Negative values move the pointer backward in the file
Distance.QuadPart = NewSize.QuadPart - Size.QuadPart;
return ( SetFilePointerEx( hFile, Distance, NULL, FILE_END ) &&
SetEndOfFile( hFile ) );
}
return false;
}
// Helper function taking a file name instead of a HANDLE
bool truncate( const std::wstring& PathName, LARGE_INTEGER NewSize ) {
HANDLE hFile = CreateFileW( PathName.c_str(), GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) {
return false;
}
bool Success = truncate( hFile, NewSize );
CloseHandle( hFile );
return Success;
}
EDIT: Shorter Version
The truncate function can be shortened to the following:
bool truncate( HANDLE hFile, LARGE_INTEGER NewSize ) {
return ( SetFilePointerEx( hFile, NewSize, NULL, FILE_BEGIN ) &&
SetEndOfFile( hFile ) );
}
If you would rather want to pass the amount of bytes by which to shrink the file, the following implementation can be used:
bool truncate( HANDLE hFile, LARGE_INTEGER ShrinkBy ) {
ShrinkBy.QuadPart = -ShrinkBy.QuadPart;
return ( SetFilePointerEx( hFile, ShrinkBy, NULL, FILE_END ) &&
SetEndOfFile( hFile ) );
}
To grow a file, open the file using CreateFile with a dwDesiredAccess that contains FILE_APPEND_DATA. Using SetFilePointer again to set the file pointer to the end of file you can then write new data calling WriteFile. For an example, see Appending One File to Another File.
EDIT: Growing a file without writing to it
If you don't care about the file contents beyond the original file size you can apply the same sequence as shown for truncating a file to extend it:
bool SetFileSize( HANDLE hFile, LARGE_INTEGER NewSize ) {
return ( SetFilePointerEx( hFile, NewSize, NULL, FILE_BEGIN ) &&
SetEndOfFile( hFile ) );
}
This is documented behavior for SetEndOfFile:
The SetEndOfFile function can be used to truncate or extend a file. If the file is extended, the contents of the file between the old end of the file and the new end of the file are not defined.
You probably want the SetEndOfFile function.
EDIT: This should work with files larger than 4GB. Use the SetFilePointerEx function for that.
To remove bytes from end of file on Windows:
FSUTIL file seteof <filename> <new size>
To add (null)bytes to end of (existing)file:
FSUTIL file seteof <filename> <new size>
No need to copy/"rewrite the whole file on windows"

c++ check if file is empty

I got a project in C++ which I need to edit. This is a declaration of variable:
// Attachment
OFSTRUCT ofstruct;
HFILE hFile = OpenFile( mmsHandle->hTemporalFileName , &ofstruct , OF_READ );
DWORD hFileSize = GetFileSize( (HANDLE) hFile , NULL );
LPSTR hFileBuffer = (LPSTR)GlobalAlloc(GPTR, sizeof(CHAR) * hFileSize );
DWORD hFileSizeReaded = 0;
ReadFile( (HANDLE) hFile , hFileBuffer, hFileSize, &hFileSizeReaded, NULL );
CloseHandle( (HANDLE) hFile );
I need to check if the file is attached (I suppose I need to check if hFile has any value), but don't know how. I tried with hFile == NULL but this doesn't do the job.
Thanks,
Ile
Compare hFile with HFILE_ERROR (not with NULL!). Also, you should change OpenFile to CreateFile and call it properly, OpenFile has long been deprecated. In fact MSDN clearly states:
OpenFile Function
Only use this function with 16-bit
versions of Windows. For newer
applications, use the CreateFile
function.
When you make this change, you will get a HANDLE back, which you should compare with INVALID_HANDLE_VALUE.
Update: Correct way to get a file's size:
LARGE_INTEGER fileSize={0};
// You may want to use a security descriptor, tweak file sharing, etc...
// But this is a boiler plate file open
HANDLE hFile=CreateFile(mmsHandle->hTemporalFileName,GENERIC_READ,0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile!=INVALID_HANDLE_VALUE && GetFileSizeEx(hFile,&fileSize) &&
fileSize.QuadPart!=0)
{
// The file has size
}
else
{
// The file is missing or size==0 (or an error occurred getting its size)
}
// Do whatever else and don't forget to close the file handle when done!
if (hFile!=INVALID_HANDLE_VALUE)
CloseHandle(hFile);
Before you open the file you can try this:
WIN32_FIND_DATA wfd;
HANDLE h = FindFirstFile(filename, &wfd);
if (h != INVALID_FILE_HANDLE)
{
// file exists
if (wfd.nFileSizeHigh != 0 || wfd.nFileSizeLow != 0)
{
// file is not empty
}
FindClose(h)
}