Using CreateFile To Access a Drive Partition - c++

I have admin rights and have no problem getting a valid handle and ultimately reading an entire hard drive via:
IntPtr handle = CreateFile(#"\\.\PHYSICALDRIVE1", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
I can also get a valid handle when I try to open a directory of that drive:
IntPtr handle = CreateFile(#"\\.\Z:\\", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
But I cannot get a valid handle when I try to simply open a partition of that drive:
IntPtr handle = CreateFile(#"\\.\Z:", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
GetLastWin32Error returns access denied (5).
Of course if I offline the drive, then I get "The system cannot find the file specified."
I've tried everything I could think of with different partitions, different options etc. to no available.

I found the answer myself. Let me correct myself in pointing out that CreateFile(#"\.\Z:" is opening a Volume, not necessarily a partition. However, I could not even open a volume.
Until I added FILE_SHARE_WRITE to the options as follows:
IntPtr handle = CreateFile(#"\.\Z:", GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
That was the key to getting a valid handle. This is certainly not intuitive!
Why this should be the case is only known by Microsoft I guess.

I would like to point out that the documentation of CreateFile says the following about FILE_SHARE_WRITE:
Enables subsequent open operations on a file or device to request write access.
Otherwise, other processes cannot open the file or device if they request write access.
If this flag is not specified, but the file or device has been opened for write access or has a file mapping with write access, the function fails.

Related

Get filename mapped into memory by the address it's mapped to

assuming there's the following code -
HANDLE h = CreateFile(L"some_dll.dll", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE map = CreateFileMapping(h, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID res = MapViewOfFileEx(map, 0, 0, 0, 0, 0);
Is it possible to extract 'some_dll', given the address it's mapped to, using c++ ?
When trying to debug this executable using windbg, it seems that it doesn't extract the module well too
Yes, this is exactly what GetMappedFileName is for:
Checks whether the specified address is within a memory-mapped file in the address space of the specified process. If so, the function returns the name of the memory-mapped file.
PS: there's no reason for windbg to show the name of a memory mapped file that isn't a loaded module, even if the file happens to be a DLL.

OpenFileById fails with ERROR_ACCESS_DENIED

I'm working on a product where OpenFileById() fails with ERROR_ACCESS_DENIED on files and folders that are otherwise accessible (meaning a CreateFile() on the same file or folder specified by path with the same access level / share mode, etc. succeeds).
I'm using backup semantics so I could also get a handle to folders; SE_BACKUP_NAME and SE_RESTORE_NAME privileges are enabled. This code works everywhere else other than this one machine (Windows 8.1).
The process is running as a service under local system, I tried having them change that to a different account with admin privileges and that didn't work either. Files / folders in question haven't been open for deletion (which is one case when this function will fail with ERROR_ACCESS_DENIED as per documentation).
I don't have physical access to this machine so can't kernel debug or anything like that. Has anyone run into this before?
Here's what I'm trying to do in a nutshell:
hRoot = ::CreateFileA(szRootPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hRoot != INVALID_HANDLE_VALUE)
{
FILE_ID_DESCRIPTOR fileId;
fileId.dwSize = sizeof(fileId);
fileId.Type = FileIdType;
fileId.FileId.QuadPart = nId;
hFile = ::OpenFileById(hRoot, &fileId, SYNCHRONIZE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, FILE_FLAG_BACKUP_SEMANTICS);
if (hFile != INVALID_HANDLE_VALUE)
{
...
::CloseHandle(hFile);
}
::CloseHandle(hRoot);
}
Apparently this is caused by a third party software product's kernel components (can't really go into specifics)

Get modification time of locked folder with boost::filesystem::last_write_time

When I'm using
time_t t = last_write_time("C:\\System Volume Information");
I get the following exception:
boost::filesystem::last_write_time: Access denied: "C:\System Volume Information"
Nevertheless, Windows Explorer is able to get access to that information. It looks like Boost requires extra access to the folder, and that's the reason the code doesn't work.
Is it possible to make a workaround somehow?
Edit. Here's a citation from libs\filesystem\src\operations.cpp:1312:
handle_wrapper hw(
create_file_handle(p.c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
I don't see what's wrong with it yet.
That folder is off limits even to users with an Admin account, it contains restore points. Not that you couldn't change the ACL with such an account but that is of course not the correct solution. Trying to open a handle on the directory is too heavy-handed, use FindFirstFile() instead. Like this:
WIN32_FIND_DATA info;
auto hdl = FindFirstFile(L"C:\\System Volume Information", &info);
if (hdl == INVALID_HANDLE_VALUE) throw win32_error(GetLastError());
SYSTEMTIME time;
FileTimeToSystemTime(&info.ftLastWriteTime, &time);
// etc..
//...
FindClose(hdl);

Trying to open display device handle to change brightness on Windows XP using C++

I am trying to write a C++/WinAPI code to change a monitor brightness. The code must be compatible with Windows XP so I can't use APIs like SetMonitorBrightness. So I thought to try out IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS but I can't seem to even get a device handle.
HANDLE hDevice = ::CreateFile(_T("\\\\.\\LCD"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0, NULL);
if(hDevice != INVALID_HANDLE_VALUE)
{
//Do work here
::CloseHandle(hDevice);
}
else
{
nOSErr = ::GetLastError();
//Get code 2
}
I tried various combinations of GENERIC_READ, GENERIC_WRITE and FILE_SHARE_READ, FILE_SHARE_WRITE flags but I always get error code 2 when CreateFile is called.
So what am I doing wrong here?
You know that not all devices support this API, right? Your laptop probably supports it because it allows software adjustment of its screen brightness, perhaps even with function keys on the keyboard. Your other machine (the one running Windows 7) probably doesn't support it, so calling CreateHandle with \\\\.\\LCD doesn't get you anything useful. It has nothing to do with the operating system and everything to do with the hardware and/or the video drivers.

Memory mapping physical disks and volumes

In Windows it's possible to open devices and volumes via CreateFile(). I've used this successfully before to ReadFile() from devices, but now I want to switch to memory-mapping. In the following code, I receive INVALID_HANDLE_VALUE for the value of b, and c is set to 87, ERROR_INVALID_PARAMETER.
HANDLE a = ::CreateFileA("\\\\.\\h:", GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY | FILE_FLAG_NO_BUFFERING, NULL);
HANDLE b = ::CreateFileMappingA(a, NULL, PAGE_READONLY, 0, 0, NULL);
DWORD c = ::GetLastError();
How can I get this to work?
You can't. CreateFileMapping can only create a mapping to a file. Take a look at the difference in the documentation between the hFile parameter for ReadFile and for CreateFileMapping. For ReadFile it lists all the different types of handles it accepts (which includes devices), for CreateFileMapping it only lists files.