OpenFileById fails with ERROR_ACCESS_DENIED - c++

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)

Related

SetNamedSecurityInfo: Setting DACL for Object works, but does not persist after system restart

In Windows 7, I'm trying to give a user group the ability read/write access to a specific disk connected through SCSI so they can run a utility that reads/writes to that disk. I'm trying to do this through modifying the DACL of the disk object using SetNamedSecurityInfo using C++.
string devicePath = "\\?\scsi#disk&ven_wsi&prod_drs1100p#6&383ae3b6&0&000300#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
PSID ppsidOwner, ppsidGroup;
PACL ppDacl = NULL, ppSacl = NULL;
PSECURITY_DESCRIPTOR ppSecurityDescriptor = NULL;
char objName[200];
strcpy(objName, devicePath.c_str());
// Get SecurityInfo
GetNamedSecurityInfoA(objName, 1, DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, &ppsidOwner, &ppsidGroup, &ppDacl, NULL, &ppSecurityDescriptor);
// Build ACE
EXPLICIT_ACCESS str_ACE;
DWORD rightsMask = STANDARD_RIGHTS_ALL | GENERIC_ALL | GENERIC_WRITE | GENERIC_READ;
BuildExplicitAccessWithNameA(&str_ACE, "DRS Operators", rightsMask, GRANT_ACCESS, NO_INHERITANCE);
PACL newPACL;
// Set ACE then Set SecurityInfo
SetEntriesInAclA(1, &str_ACE, ppDacl, &newPACL);
SetNamedSecurityInfoA(objName, 1, DACL_SECURITY_INFORMATION, NULL, NULL, newPACL, NULL);
The code I wrote seems to work, which I have confirmed by using GetNamedSecurityInfoA on the object before and after I change the DACL, then passing the received SecurityDescriptors to ConvertSecurityDescriptorToStringSecurityDescriptorA, and making sure that they have changed. After running through this code, I'm able to log in as any user in the "DRS Operators" user group and am able to read/write to the disk.
The only problem I'm having is that the changes to the DACL do not persist after the system shuts down. After a restart, the DACL is set back to what it was before I ran through the code above (which I checked by using GetNamedSecurityInfoA). Does anyone here have an idea of why the changes aren't persisting?

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);

Using CreateFile To Access a Drive Partition

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.

Checking windows file permissions

I'm trying to figure out how to check if a directory can be changed to without actually changing to the directory.
On a posix system I would do:
if (access("/some/path", X_OK) == 0) {
// okay!
}
If only Windows was so simple ....
I've taken a look at the documentation or GetFileSecurity, but I can't seem to wrap my head around Windows ACLs and what I actually have to check for to ensure a directory can be changed to.
The only way to be sure if an operation will succeed is to actually try the operation.
However, SetCurrentDirectory will fail if you don't have FILE_TRAVERSE or SYNCHRONIZE permissions for the folder in question. So you can test this using CreateFile without actually changing the directory.
bool TestForSetCurrentDirPermission(LPCWSTR pszDir)
{
HANDLE hDir = CreateFile(pszDir, FILE_TRAVERSE | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hDir != INVALID_HANDLE_VALUE) CloseHandle(hDir);
return hDir != INVALID_HANDLE_VALUE;
}

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.