CreateFile path error in Visual C++ - c++

for (int i = 0; i < 1000; i++)
{
sprintf_s(text, "Text from process %d\r\n", GetCurrentProcessId());
HANDLE hFile = CreateFile(_T("\\\\.\\Device\\HarddiskVolume2\\dev\\test\\test.txt"), GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD err = GetLastError();
cout << "Error opening file " << GetLastError() << " at index " << i << endl;
break;
}
SetFilePointer(hFile, GetFileSize(hFile, NULL), NULL, FILE_BEGIN);
DWORD bytes;
WriteFile(hFile, text, strlen(text), &bytes, NULL);
CloseHandle(hFile);
}
i'm trying to open write using the actual device name
\Device\HarddiskVolume2 is mapped to c:\
the folder already exist in c drive
i'm getting error opening file

Error code 3 is ERROR_PATH_NOT_FOUND. The reason you see that is because \\.\Device\HarddiskVolume2 is the path of the raw device. If you use that path, you no longer have access to the file system. What that path gives you is access to the raw disk sectors.
If you must use \\.\Device\HarddiskVolume2 to identify the drive then you need to first convert, by some means or other, to a mapped drive letter, or a DOS device path for the volume. The latter would be, in your case, \\.\HarddiskVolume2

Please refer
ERROR_PATH_NOT_FOUND
3 (0x3)
The system cannot find the path specified.
So please try to check the path is available or not ..\\Device\\HarddiskVolume2\\dev\\test\\test.txt.
this is because program unable to find the path
or try this:
..\\Device\\HarddiskVolume2\\dev\\test\\test.txt
if the path is in same directory as your exe.
Reason
While creating the file the compiler look into the path which is in the directory where the exe file is. If it is not found then Program will check into the Drive where the Program is running.
Also try to get some information from CreateFile.
hope this will help you.

Related

How to check whether a directory is readable or writable?

I want a way to know whether a directory/folder is readable or writable. I searched for a direct way to do that by a function or like that but I didn't find it.
I tried to do it indirectly as follow:
Is readable:
WIN32_FIND_DATAA dirData;
HANDLE hDir;
hDir = FindFirstFile("C:\\folder", &dirData);
if (hDir == INVALID_HANDLE_VALUE)
return false;
return true;
Is writable:
DWORD attr = GetFileAttributes(m_dirPath);
if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_READONLY)
return false;
return true;
The first code is an indirect way to know whether a directory
readable but it is not efficient because when the directory is empty
it returns 0 which is not readable.
The second code to check whether a directory is writable but it
always returns 1 which is writable although I have changed the
directory permission to read-only.
Is there a direct or indirect way to know whether a directory is readable or writable?
I want a way to know whether a directory/folder is readable or
writable.
Directly to try to open the directory with read/write access permission via CreateFile API:
HANDLE tDir = CreateFile(L"D:\\testNew", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == tDir)
printf("Open directory failed with error %d \n", GetLastError());
else
printf("Readable. \n");
tDir = CreateFile(L"D:\\testNew", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == tDir)
printf("Open directory failed with error %d \n", GetLastError());
else
printf("Writable. \n");
If it is a read-only directory you will receive access denied error when you open it with GENERIC_WRITE.
For read-only, the directory maybe set to deny current user to write, however it is not a read-only directory. At this time you will get "This directory is not read-only" result but you still can't write.
Update:
As #RaymondChen pointed out, you can confirm the desired access right to a directory more accurately using file access rights constants. Take FILE_LIST_DIRECTORY as an example:
tDir = CreateFile(L"D:\\testNew", FILE_LIST_DIRECTORY, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == tDir)
printf("Open directory failed with error %d \n", GetLastError());
else
printf("Has right to list the contents of the directory.\n");

Why does WriteFile not run more than once?

Here's my code in which I've got on an infinite loop (to my knowledge)
while(true) {
DWORD TitleID = XamGetCurrentTitleId();
std::ostringstream titleMessageSS;
titleMessageSS << "Here's the current title we're on : " << TitleID << "\n\n";
std::string titleMessage = titleMessageSS.str(); // get the string from the stream
DWORD dwBytesToWrite = (DWORD)titleMessage.size();
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
bErrorFlag = WriteFile(logFile, titleMessage.c_str(), dwBytesToWrite, &dwBytesWritten, NULL);
CloseHandle(logFile);
Sleep(30000);
}
return NULL;
Does anyone see a reason as to why this only writes just once? I've waited over 5 minutes to see if it does anything in the end to no avail.
The Flag CREATE_NEW in CreateFile prevents the update of the file because CreateFile fail with ERROR_FILE_EXISTS. Use OPEN_ALWAYS instead.
Also it will always truncate. Replace GENERIC_WRITE with FILE_APPEND_DATA if you want to add a new line at the end of your logfile.
The whole CreateFile line should be:
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Read CreateFile documentation carefully, it worth it, because it has a central role in the windows IO universe:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
look also add:
https://stackoverflow.com/a/9891875/1922748
As Martin James mentioned, from MSDN:
CREATE_NEW
Creates a new file, only if it does not already exist.
If the specified file exists, the function fails and the last-error
code is set to ERROR_FILE_EXISTS (80).
If the specified file does not exist and is a valid path to a writable
location, a new file is created.
So it seems that the handle is invalid after the first call, and hence WriteFile() fails.

how to get size of a locked file?

I've tried to use this approach:
#include <windows.h>
#include <iostream>
int main() {
LARGE_INTEGER size;
HANDLE hFile = CreateFile("c:\\pagefile.sys", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return(1);
GetFileSizeEx(hFile, &size);
CloseHandle(hFile);
std::cout << size.QuadPart << std::endl;
}
But as you see I point to "pagefile.sys" which is locked, and program encounters INVALID_HANDLE_VALUE. But non system apps can see sizes of locked files. For example total commander gives me about 1GB and it must get this value from somewhere (not to mention simple right-clicking on that file, but that is system process so file is not locked to it). So, are there any winapi calls for that case ?
I've updated code to included suggested corrections, but it still doesn't work:
#include <windows.h>
#include <iostream>
int main() {
LARGE_INTEGER size;
HANDLE hFile = CreateFile("c:\\pagefile.sys", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
std::cout << "GetLastError: " << GetLastError() << std::endl;
//says: 5 (0x5) ERROR_ACCESS_DENIED
if (hFile == INVALID_HANDLE_VALUE) return(1);
GetFileSizeEx(hFile, &size);
CloseHandle(hFile);
std::cout << size.QuadPart << std::endl;
}
You can get info out of the directory entry for a file, there is no mechanism to lock that. Which requires FindFirstFile/FindNextFile to iterate the directory. The returned WIN32_FIND_DATA.nFileSizeHigh/Low gives you the info you want.
The actual number you get is not reliable, it is merely a snapshot and it is likely to be stale. Especially so for the paging file, Windows can rapidly change its size. Getting a reliable size requires locking the file so nobody can change it, like you did. Which will not work for the paging file, the operating system keeps a hard lock on it so nobody can mess with the file content or read security sensitive data from the file.
According to MSDN, you should set the dwDesiredAccess parameter to 0 (zero) if you only want information without opening the file.

Writing raw data to a disk in windows fails with error code 83 (invalid parameter)

I have a little snippet of code that I am trying to use to write a string that is roughly 100 bytes long to a disk at the address 0x600.
UCHAR szStr[0x4C] = {0};
memcpy(szStr, "Example string", 8);
DWORD bytes, cb;
HANDLE hDisk = CreateFile("\\\\.\\I:", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDisk == INVALID_HANDLE_VALUE)
{
cout << "CreateFile error"<< endl << GetLastError();
}
if (!DeviceIoControl(hDisk, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &cb, NULL))
{
cout << "IO Error"<< endl << GetLastError();
}
if (SetFilePointer(hDisk, 0x600, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
cout << "Pointer error"<< endl << GetLastError();
}
if (!WriteFile(hDisk, szStr, 0x4C, &bytes, 0))
{
cout << "Write error" << endl << GetLastError(); //Only one that triggers (err code 87)
}
CloseHandle(hDisk);
For some reason everything is OK until I call WriteFile() which fails. GetLastError() returns a code of 83 which means INVALID_PARAMETER. I have tried debugging it by specifing a normal file on the desktop instead of the drive I:\ and the operation fires off successfully so my best guess would be the problem lies with the disk handle to the drive I:\.
I read an article by MSDN located here that explains that raw disk I/O gets blocked if you don't lock/dismount the drive first. I am confused as to why that would be a problem as in my code I call DeviceIoControl with FSCTL_LOCK_VOLUME to lock the device before I perform anything else. The disk has an active file system (FAT32/FAT16) and the 0x600 region likely lies within the filesystem, but according to the article if I lock the drive I should be able to write to it. Any idea what is going on here? Thanks!
Are you checking DeviceIoControl and SetFilePointer for an error indication?
Do you have the rights to do the operations you're attempting? Administrator account is required for raw disk writes IIRC.
Is the disk you're trying to open a system disk? (Does it contain the OS files?) If so the Lock IOCTL will fail.
If there's a page file on the disk you're trying to lock the Lock IOCTL will fail.

Invalid handle when calling IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER

Anyone out there have experience of c/c++ IOCTL calls?
Basically I'm trying to identify what port a USB memory stick is plugged into.
I have all the USB info and have volume info. Apparantly to link these 2 blocks of info I need either the driver-key or serial-number.
However when calling DeviceIoControl I'm getting invalid handle as the "last error code"
My drive USB drive mounted to a directory in c:\ (not a drive letter) See below
//get a handle on the volume
HANDLE hVolume;
DWORD dwAccessFlags;
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
hVolume = CreateFile(L"C:\_USB\MP1",
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE) {
printf("Invalid Handle");
}
//use the handle
MEDIA_SERIAL_NUMBER_DATA* pserialNumberData = new MEDIA_SERIAL_NUMBER_DATA;
wstring result;
//HANDLE hVolume = OpenVolume(vname.substr(0, vname.length() - 1).c_str());
DWORD bytesReturned = 0;
LPDWORD lpBytesReturned = &bytesReturned;
OVERLAPPED over;
LPOVERLAPPED lpOver = &over;
BOOL success = 1;
success = DeviceIoControl(
(HANDLE) hVolume, // handle to device
IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
(LPVOID) pserialNumberData, // output buffer
(DWORD) sizeof(MEDIA_SERIAL_NUMBER_DATA), // size of output buffer
(LPDWORD) lpBytesReturned, // number of bytes returned
(LPOVERLAPPED) lpOver // OVERLAPPED structure
);
wcout << L"--> GetSn() DeviceIoControl success " << success << endl;
wcout << L"--> GetSn() DeviceIoControl Last error number " << GetLastError() << endl;
wcout << L"--> GetSn() DeviceIoControl Bytes Returned " << bytesReturned << endl;
wcout << L"--> GetSn() DeviceIoControl struct size " << sizeof(MEDIA_SERIAL_NUMBER_DATA) << endl;
If you look at the Remarks section for the DeviceIoControl function, it says:
To retrieve a handle to the device, you must call the CreateFile function with either the name of a device or the name of the driver associated with a device. To specify a device name, use the following format:
\\.\DeviceName
DeviceIoControl can accept a handle to a specific device. For example, to open a handle to the logical drive A: with CreateFile, specify \\.\a:. Alternatively, you can use the names \\.\PhysicalDrive0, \\.\PhysicalDrive1, and so on, to open handles to the physical drives on a system.
You are not opening a device handle, and thus DeviceIoControl is not going to work for that case.
The first big problem I see is that the CreateFile function must be called with the FILE_FLAG_BACKUP_SEMANTICS flag in order to get a valid handle to a directory. So, for starters, try:
hVolume = CreateFile( L"C:\_USB\MP1",
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL );
Hmmm... I think the handle you get from CreateFile is the handle to the directory you mounted your drive to, rather than the drive itself. To be sure you get the handle to device you want, you should use a device path, e.g. \\.\Device\HarddiskVolume1. WinObj or DeviceTree can probably help you find the path to your usb drive.