How to convert L"\\\\.\\C:" to L"\\\\.\\PhysicalDrive0" - c++

I am newbie. The code is that I copied on internet. And I don't really understand it.
I'm learning C ++, so even though the code is C, I want to switch to C ++. I need to understand the code and output the screen:
Partition Styles/Scheme: is MBR disk/drive // is GPT disk/drive // or is RAW disk/drive
Partition Number of a Disk/Drive
I put breakpoint at line below, press F5 on Visual Studio 2013 (run as admin):
DWORD part_num = szPartINF.PartitionNumber;
If I leave:
hDevice = CreateFile(L"\\\\.\\C:", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
the code runs successfully (part_num have value = 2 . It is right, because my Disk0 have 2 partitions)
And, I change to:
hDevice = CreateFile(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
the code runs fails/unsuccess (part_num = 0)
I need to use "\\\.\\PhysicalDrive0" rather than "\\\.\\C:".
I still have another problem: I use the clean command in DiskPart for My Hard Drive. When I ran the test, the code did not recognize PartitionStyle RAW correctly, because this time my hard drive was RAW DISK (and certainly not PartitionStyle MBR or PartitionStyle GPT).
Please help me.
Thanks.
#include "windows.h"
#include <stdio.h>
#include <iostream>
//////// ok, go ///////////
int main(int argc, char* argv[])
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
PARTITION_INFORMATION_EX szPartINF;
DWORD cbReturned = 0;
__try
{
hDevice = CreateFile(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
//hDevice = CreateFile(L"\\\\.\\C:", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDevice == INVALID_HANDLE_VALUE) { return FALSE; }
RtlZeroMemory(&szPartINF, sizeof(szPartINF));
if (FALSE != DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, (LPVOID)&szPartINF, sizeof(PARTITION_INFORMATION_EX), &cbReturned, NULL))
{
DWORD part_num = szPartINF.PartitionNumber;
DWORD part_style = szPartINF.PartitionStyle;
return TRUE;
}
else
{
cbReturned = GetLastError();
wprintf(L"\n%08X (%d)\n", cbReturned, cbReturned);
}
}
__finally
{
if (hDevice != INVALID_HANDLE_VALUE) { CloseHandle(hDevice); }
}
return FALSE;
bool success;
cin >> success; //for wait to close cmd.
}

"\\\\.\PhysicalDrive0" is not necessarily "\\\\.\\C:".
You can check This PC->Manage->Storage->Disk Management:
The Disk 0 means PhysicalDrive0.If you need the corresponding physical disk.You can refer to How to list physical disks?

Related

DeviceIoControl fails with error 395 to set a reparse point

Recently I posted this question and now I am trying to set a reparse point after a file modification with WordPad app. Currently I checked that the reparse point is a Microsoft tag and I can save the reparse point data in a REPARSE_DATA_BUFFER pointer before the file lose the reparse point. But when I try to set the reparse point to the file, after a file modification, I always get the 395 error with the GetLastError function after call to DeviceIoControl function using the control code FSCTL_SET_REPARSE_POINT. The error 395 doesn't appear in this System Error Codes although I found this error here that has sense. I also removed the discretionary access control list (DACL) from the file, to grants full access to the file by everyone, before try to set the reparse point but I got the same error. Here I put two fragments of my code to get and set the reparse point. I will appreciate any help.
Code to get the reparse point
HANDLE hDevice = CreateFile(
filePath.c_str(), // File path in the computer
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
rdb = (REPARSE_DATA_BUFFER*)malloc(maxReparse); // rdb was declared as: REPARSE_DATA_BUFFER* rdb;
DWORD outBufferSize = maxReparse;
DWORD bytesReturned = 0;
if (DeviceIoControl(hDevice, FSCTL_GET_REPARSE_POINT, NULL, 0, rdb, outBufferSize, &bytesReturned, NULL))
{
if (rdb != NULL)
{
if (IsReparseTagMicrosoft(rdb->ReparseTag))
{
wprintf(L"Is a Microsoft tag.\n");
}
Code to set the reparse point
LPTSTR pszObjName = const_cast<wchar_t*>(filePath.c_str()); // File path in the computer
PACL newDACL = NULL; // NULL discretionary access control list to grant full access to everyone
DWORD secInfo = SetNamedSecurityInfo(pszObjName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, newDACL, NULL);
if (secInfo == ERROR_SUCCESS)
{
HANDLE hDevice = CreateFile(filePath.c_str(),
GENERIC_ALL, //GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
size_t maxReparse = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
DWORD inBufferSize = maxReparse;
if (rdb != NULL)
{
DWORD bytesReturned = 0;
if (!DeviceIoControl(hDevice, FSCTL_SET_REPARSE_POINT, rdb, inBufferSize, NULL, 0, &bytesReturned, NULL))
{
DWORD error = GetLastError(); // Error 395
unsigned long errorUL = error;
wprintf(L"Error %lu in DeviceIoControl method.\n", errorUL);
}

Direct writing a disk results in error code 5 according to GetLastError

I am trying to direct write a USB disk in Windows. I used the CreateFile function to create a disk handle and used the WriteFile function to try to write the file. The WriteFile function failed with status code 5 (according to GetLastError). I tried to lock the disk volume by using FSCTL_DISMOUNT_VOLUME, but the volume was hidden, so I could not get its volume letter.
Code:
u8 Disk::Init()
{
char fn[24] = { 0 };
sprintf(fn, "\\\\.\\PhysicalDrive%d", (int)m_nDiskNum);
m_hDisk = CreateFileA(fn, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, 0);
if (INVALID_HANDLE_VALUE == m_hDisk)
{
return (FAIL);
}
//m_DiskInfo.Init();
return Lock();
}
u8 Disk::Lock()
{
STORAGE_DEVICE_NUMBER d1;
DWORD nr;
char dn[8], c;
if (!DeviceIoControl((HANDLE)m_hDisk, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &d1, sizeof(d1), &nr, 0))
{
return (FAIL);
}
strcpy(dn, "\\\\.\\A:");
// some volume is hided, so I cannot get its letter
for (c = 'C'; c < 'Z'; c++)
{
HANDLE hd;
STORAGE_DEVICE_NUMBER d2;
dn[4] = c;
hd = CreateFileA(dn, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0);
if (hd == INVALID_HANDLE_VALUE)
{
continue;
}
if ((!DeviceIoControl(hd, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &d2, sizeof(d2), &nr, 0)) ||
(d1.DeviceType != d2.DeviceType) ||
(d1.DeviceNumber != d2.DeviceNumber))
{
CloseHandle(hd);
continue;
}
if (!DeviceIoControl(hd, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0,
&nr, 0))
{
CloseHandle(hd);
return (FAIL);
}
m_LockedVolums.push_back(hd);
}
return (SUCC);
}
u8 Disk::UnLock()
{
for (auto it : m_LockedVolums)
{
CloseHandle(it);
}
m_LockedVolums.clear();
return (SUCC);
}
u8 Disk::WriteSector(_Out_opt_ u8 * cBuf, int nStartSec, int nSecCont/* = 1*/)
{
if (Seek(nStartSec))
{
return(FAIL);
}
unsigned long nWrited;
if ((!WriteFile((HANDLE)m_hDisk, cBuf, nSecCont * m_nBytePerSec, &nWrited, NULL))
|| (nSecCont * m_nBytePerSec != (int)nWrited))
{
return(FAIL);
}
return(SUCC);
}
I don’t think you’re properly locking the volume.
FSCTL_DISMOUNT_VOLUME IO control dismounts the file system, but I don’t think it locks it for writing. Use FSCTL_LOCK_VOLUME afterwards (or instead, if the volume has no Windows-readable filesystem and therefore wasn’t mounted) to request write access.
P.S. I think you need your app to run elevated to be able to use that API.

How to read something to the RAW disk and then write it some further in C++?

I'd like to first write something to a disk device, then read the same data and write it some further. My code looks like this:
std::string devicePath = "\\\\.\\PhysicalDrive0"; //'0' is only example here
HANDLE source = CreateFile(disk.c_str(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, NULL, NULL);
BOOST_TEST_REQUIRE(source, "Failed to create file handle.");
std::unique_ptr<CHAR[]> primaryBuffer(new CHAR[DEFAULT_FILESIZE]);
std::unique_ptr<CHAR[]> checkBuffer(new CHAR[DEFAULT_FILESIZE]);
for (auto i = 0; i < DEFAULT_FILESIZE; ++i) {
primaryBuffer[i] = 'x';
checkBuffer[i] = ' ';
}
WriteFile(source, primaryBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
//Here I move the pointer to write data in new place.
DWORD destination = SetFilePointer(source, DEFAULT_FILESIZE, NULL, FILE_BEGIN);
WriteFile(&destination, source, DEFAULT_FILESIZE, NULL, NULL);
ReadFile(source, primaryBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
ReadFile(&destination, checkBuffer.get(), DEFAULT_FILESIZE, NULL, NULL);
BOOST_TEST_MESSAGE(checkBuffer.get());
BOOST_TEST_MESSAGE(primaryBuffer.get());
Unfortunately, both buffers are different and I've tried almost everything to check what's wrong. Maybe somebody has any idea what I'm doing wrong?

When error 1224: ERROR_USER_MAPPED_FILE occurs?

I want to really understand when the ERROR_USER_MAPPED_FILE occurs. So I wrote some snippets. To reproduce the error. But it did not work. Please help me fix my code
Process 1:
HANDLE hFile = CreateFile("C:\\test\\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
I am Halting the process and I have not closed any view of the map and file handles yet in this process so that when the other process tries to open the file. I thought error 1224 will be thrown.
Process 2:
HANDLE hFile = CreateFile("C:\\test\\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
cout << "Error Code : " << GetLastError() << endl;
char buffer[1025];
DWORD bytesRead;
if (!ReadFile(hFile, buffer, 1024, &bytesRead, 0))
cout << "Error Code : " << GetLastError() << endl;
The CreateFile and ReadFile succeeds in the process 2.
Actually I am trying to handle this error 1224 separately. Which means when the file fails with error 32 I want to do something. and if the file fails with error 1224 I want to do something.
Now I must test those cases. In order to test those scenarios I should reproduce the error 1224.
I want to really understand when the ERROR_USER_MAPPED_FILE occurs
if really understand let some extra info.
at first this error returned from kernel. so it was initially NTSTATUS error code, which than translated to win32 error by RtlNtStatusToDosError. api for reverse translation not exist - because it not uniquely, but possible yourself write code, which create reverse translation map. two NTSTATUS codes is translated to ERROR_USER_MAPPED_FILE : STATUS_USER_MAPPED_FILE and STATUS_PURGE_FAILED:
if (
RtlNtStatusToDosError(STATUS_USER_MAPPED_FILE) != ERROR_USER_MAPPED_FILE
||
RtlNtStatusToDosError(STATUS_PURGE_FAILED) != ERROR_USER_MAPPED_FILE
)
{
__debugbreak();
}
for completely understand when this codes returned need look File System source code. we have fastfat example. if search for STATUS_USER_MAPPED_FILE - we can found that this code returned from 4 place:
FatSupersedeOrOverwriteFile - when we try call
ZwCreateFile with FILE_OVERWRITE_IF or FILE_SUPERSEDE
CreateOption or when we call CreateFile with CREATE_ALWAYS
FatSetEndOfFileInfo - when we call ZwSetInformationFile
with FileEndOfFileInformation or SetEndOfFile function
FatSetValidDataLengthInfo- when we call
ZwSetInformationFile with
FileValidDataLengthInformation or SetFileValidData
function (we need have SE_MANAGE_VOLUME_PRIVILEGE for this)
FatSetAllocationInfo - when we use ZwSetInformationFile
with FileAllocationInformation (no win32 api shell)
and you can note common pattern here:
if (!MmCanFileBeTruncated()) return STATUS_USER_MAPPED_FILE;
about demo code for reproduce this error - for what you need two processes ?!? single routine in single process - more than enough.
void test()
{
// for simplicity, i have access to this location as admin
STATIC_OBJECT_ATTRIBUTES(oa, "\\systemroot\\temp\\.tmp");
HANDLE hFile, hSection, hFile2;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER AllocationSize = { PAGE_SIZE };
NTSTATUS status;
if (0 <= NtCreateFile(&hFile, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, &AllocationSize, 0,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0))
{
status = NtCreateSection(&hSection, SECTION_MAP_READ|SECTION_MAP_WRITE, 0, &AllocationSize, PAGE_READWRITE, SEC_COMMIT, hFile);
if (0 <= status)
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY);
NtClose(hSection);
if (0 <= status)
{
LARGE_INTEGER Eof = {};
// SetEndOfFile win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileEndOfFileInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// no win32 api
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileAllocationInformation);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
// SetFileValidData win32 api
// we need have SE_MANAGE_VOLUME_NAME privilege, otherwise STATUS_PRIVILEGE_NOT_HELD
status = ZwSetInformationFile(hFile, &iosb, &Eof, sizeof(Eof), FileValidDataLengthInformation);
switch (status)
{
case STATUS_USER_MAPPED_FILE:
case STATUS_PRIVILEGE_NOT_HELD:
break;
default: __debugbreak();
}
//CreateFileW(L"\\\\?\\c:\\windows\\temp\\.tmp", FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, CREATE_ALWAYS, 0, 0);
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
status = NtCreateFile(&hFile2, FILE_GENERIC_WRITE|FILE_GENERIC_READ, &oa, &iosb, 0, 0,
FILE_SHARE_VALID_FLAGS, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0);
if (status != STATUS_USER_MAPPED_FILE) __debugbreak();
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
NtClose(hFile);
}
}
about STATUS_PURGE_FAILED - look like in can be returned when we call WriteFile - look here - but i can not reproduce it in test. however very rarely this error can occur - "STATUS_PURGE_FAILED" error when you perform VM replications by using SCVMM in Windows Server 2012 R2
ERROR_USER_MAPPED_FILE or error 1224 occurs when you try to delete or overwrite a file which has been mapped by other process.
Process #1
HANDLE hFile = CreateFile("C:\\test\\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (hMapFile == INVALID_HANDLE_VALUE)
return GetLastError();
mapHandles.push_back(hMapFile);
viewHandles.push_back(MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0));
Process #2
HANDLE hFile = CreateFile("C:\\test\\full.exe", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if(GetLastError() == 1224)
// File has been mapped by other process
else
// some other issue
}
In Process #2, CREATE_ALWAYS tries to overwrite a file which has been mapped. So it ends up throwing error 1224.

How to use IOCTL_DISK_GROW_PARTITION?

I'm trying to shrink my partition to the last used LCN. Has anybody used this control code?
I'm getting System Error code 87 every time in the following code:
HANDLE hDiskHandle = NULL;
DISK_GROW_PARTITION dgp;
DWORD dwBytesReturned = 0;
dgp.PartitionNumber = 2;
dgp.BytesToGrow.QuadPart = -1;
hDiskHandle = CreateFile(_T("\\.\PhysicalDrive0"), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, NULL, NULL);
if (hDiskHandle == INVALID_HANDLE_VALUE) {
int err = GetLastError();
printf("Unable to get handle on Volume, error : %d", err);
}
if (!DeviceIoControl(
hDiskHandle,
IOCTL_DISK_GROW_PARTITION,
&dgp,
sizeof dgp,
NULL,
0,
&dwBytesReturned,
NULL
)) {
int err = GetLastError();
printf("DeviceIoControl Failed, error : %d", err);;
}
My hard drive has 3 partitions (C, D, E). The E: drive is practically empty.
[OP's solution converted to answer below]
It turns out my program was fine. It started working after changing access from
GENERIC_ALL
to
GENERIC_READ | GENERIC_WRITE