How to use IOCTL_DISK_GROW_PARTITION? - c++

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

Related

Change SACL on Named Pipe

I have C++ code that change SACL of a folder as it is expected. The things become strange when I want to change SACL of an exsiting Named Pipe, the code executes successful but when I check it via Get-Acl -Path \\.\pipe\lsass -Audit | fl it returns error number 87 which is ERROR_INVALID_PARAMETER and SACL does not work. The error may be caused by setting not zero to OVERLAPPED structure according to MS Support Site but it barely helping in setting SACL.
StackOverFlow wants me to add some details, so I will write some water here
Maybe I messed up with some of the rights to provide to SetSecurityInfo and it is specifical to Named Pipes or I need to suspend it before change SACL?
using namespace std;
int main()
{
SetSecurityPrivilage(TRUE); // Got SeSecurityPrivilage
//HANDLE hPipe = CreateFile(L"C\:\\Users\\simp\\Desktop\\test", ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); // Folder SACL testing
HANDLE hPipe = CreateFile(L"\\\\.\\pipe\\lsass", ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING, NULL, NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
PACL pOldSACL = NULL;
if (GetSecurityInfo(hPipe, SE_KERNEL_OBJECT, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &pOldSACL, NULL) == ERROR_SUCCESS)
{
// SACL
TRUSTEE trusteeSACL[1];
trusteeSACL[0].TrusteeForm = TRUSTEE_IS_NAME;
trusteeSACL[0].TrusteeType = TRUSTEE_IS_GROUP;
trusteeSACL[0].ptstrName = (LPWCH)(L"Everyone");
trusteeSACL[0].MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
trusteeSACL[0].pMultipleTrustee = NULL;
EXPLICIT_ACCESS explicit_access_listSACL[1];
ZeroMemory(&explicit_access_listSACL[0], sizeof(EXPLICIT_ACCESS));
explicit_access_listSACL[0].grfAccessMode = SET_AUDIT_SUCCESS;
//explicit_access_listSACL[0].grfAccessMode = SET_AUDIT_FAILURE;
explicit_access_listSACL[0].grfAccessPermissions = ACCESS_SYSTEM_SECURITY;
explicit_access_listSACL[0].grfInheritance = NO_INHERITANCE;
explicit_access_listSACL[0].Trustee = trusteeSACL[0];
PACL pNewSACL = NULL;
if (SetEntriesInAcl(1, explicit_access_listSACL, pOldSACL, &pNewSACL) == ERROR_SUCCESS)
{
if (SetSecurityInfo(hPipe, SE_KERNEL_OBJECT, SACL_SECURITY_INFORMATION, NULL, NULL, NULL, pNewSACL) == ERROR_SUCCESS)
{
printf("%s\n", "SACL SetSecurityInfo IS WORKS");
}
else
{
//Error handling
printf("%s%d\n", "SetSecurityInfo SACL", GetLastError());
}
LocalFree(pNewSACL);
}
else
{
//Error handling
printf("%s%d\n", "SetEntriesInAcl", GetLastError());
}
LocalFree(pOldSACL);
}
else
{
//Error
printf("%s%d\n", "GetSecurityInfo SACL", GetLastError());
}
}
else
{
//Error handling
printf("%s%d", "Incorrect handle", GetLastError());
}
CloseHandle(hPipe);
Actually, the code is doing it's job. Then you compile and run this, you will change SACL of a pipe as well as a file. My mistake was in this part:
explicit_access_listSACL[0].grfAccessPermissions = ACCESS_SYSTEM_SECURITY;
Which means that logs will be generate only when user will request ACCESS_SYSTEM_SECURITY rights to a pipe, so change it to your needs. However, the reason behind 87 error is still unknown.

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

How to convert L"\\\\.\\C:" to L"\\\\.\\PhysicalDrive0"

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?

ReadFile function returning error code 50 - Request not supported

I want to read the data received by the network adapters by calling the "ReadFile" API. I got the handle from the CreateFile function. When I call the ReadFile with the obtained handle, it is always returning the error code 50 (Request not supported).
I see in the WinObj tool for the network adapter driver and it is showing that it supports (Read/Write). I searched online but could not exactly figure out what is causing the issue.
DWORD lpNumberOfBytesRead = 0;
char buf[1600] = { 0 };
size_t size = 1522;
HANDLE hFile;
hFile = CreateFile("\\\\.\\{7A1C62D4-2FE2-49D6-9090-DFA5FF1F8395}", GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM , 0);
if (hFile == TUNFD_INVALID_VALUE) {
int errcode = GetLastError();
DisplayError(errCode);
return -1;
}
if (ReadFile(hFile, buf, (DWORD)size, &lpNumberOfBytesRead, NULL) == 0) {
int errcode = GetLastError();
DisplayError(errCode);
return -1;
}
Attached
WinObj screenshot showing access permission

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.