Sending IDENTIFY DEVICE COMMAND - ATA PASS THROUGH on raid - SSD - windows

My aim is to detect Solid State Drives in systems with raid configuration. Using smartmontools' following command I observe bit 434 (217) shows value 1 for SSD: smartctl -i -r ataioctl,2 /dev/csmi0,0
Attempting to read the same 512 bytes of data I am trying to send IDENTIFY DEVICE commands in following 2 ways:
Method 1 fails with DeviceIoControl() set GetLastError() as 87 (ERROR_INVALID_PARAMETER), Can you help me in understanding what could be wrong and am I on the right track?
Method 2 has info->IoctlHeader.ReturnCode = 3 which means CSMI_SAS_STATUS_INVALID_PARAMETER.(CSMI buffer provided is too small)
///////// Method 1 /////////
handle = CreateFile(L"\\\\.\\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
NULL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
printf("Unable to open handle to device , Error %u\n", GetLastError());
return 1;
}
//Allocate memory for ATA_PASS_THROUGH_EX and clear the contents
pATAData = (PATA_PASS_THROUGH_EX) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);
ZeroMemory(pATAData,dataSize);
//Fill in the IDENTIFY DEVICE query data
pATAData->Length = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
pATAData->DataTransferLength = 512;
pATAData->AtaFlags = ATA_FLAGS_DATA_IN;
pATAData->TimeOutValue = 10; //Seconds
pATAData->CurrentTaskFile[6] = 0xEC; /* send the command*/
status = DeviceIoControl( handle,
IOCTL_ATA_PASS_THROUGH,
pATAData,
dataSize, /* input buffer and size */
pATAData,
dataSize, /* output buffer and size */
&bytescopied, /* bytes copied to output buffer*/
NULL ); /* no overlapping */
//////// Method 2 //////////
BYTE portNumber = 0;
_stprintf_s(DeviceName, (sizeof(char)*128),_T("\\\\.\\Scsi%u:"),portNumber);
// get a handle to the miniport driver
handle = CreateFile(DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
NULL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
printf("Unable to open handle to device , Error %u\n", GetLastError());
return;
}
CSMI_SAS_STP_PASSTHRU_BUFFER* info = (CSMI_SAS_STP_PASSTHRU_BUFFER *) calloc(1, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER));
info->IoctlHeader.HeaderLength = sizeof(IOCTL_HEADER);
info->IoctlHeader.Timeout = CSMI_SAS_TIMEOUT;
info->IoctlHeader.ControlCode = CC_CSMI_SAS_STP_PASSTHRU;
info->IoctlHeader.Length = sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) - sizeof(IOCTL_HEADER);
info->IoctlHeader.ReturnCode = 0;
memcpy(&info->IoctlHeader.Signature, CSMI_SAS_SIGNATURE, sizeof(CSMI_SAS_SIGNATURE));
bSuccess = DeviceIoControl(handle, IOCTL_SCSI_MINIPORT, info, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER),
info, sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER),
&bytesReturned, NULL);

Related

NtReadFile not properly reading the file

I am attempting to read ntdl.dll from disk using the NtReadFile native call. A handle has already been acquired through the NtCreateFile native call. However, when I attempt to read it using NtReadFIle, it neither fails nor succeeds. I try to print out the NtStatus, but there's nothing, as it looks like the call never actually completes. It does seem to work with the ReadFile Win API call, so not quite sure why the native call isn't working.
In the debugger, it seems like an unhandled exception is raised when transitioning back to userland after making the syscall, so not sure what is going on. Below is a snippet of the code.
#define OBJ_CASE_INSENSITIVE 0x00000040
#define FILE_OPEN 0x00000001
#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_RANDOM_ACCESS 0x00000800
#define FILE_OPEN_BY_FILE_ID 0x00002000
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
SIZE_T bytesWritten = 0;
DWORD oldProtection = 0;
//HANDLE file = NULL;
HANDLE file = NULL;
ULONG fileSize = NULL;
LPDWORD bytesRead = NULL;
PVOID fileData = NULL;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING f;
IO_STATUS_BLOCK IoStatusBlock;
WCHAR ntdl[100] = L"\\?\\c:\\windows\\system32\\ntdll.dll";
WCHAR filepath[100] = L"\\??\\c:\\windows\\system32";
RtlInitUnicodeString(&f, ntdl);
InitializeObjectAttributes(&oa, &f, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS stat = NtCreateFile(&file, FILE_GENERIC_READ, &oa, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, 0, 0);
fileSize = GetFileSize(file, NULL);
fileData = HeapAlloc(GetProcessHeap(), 0, fileSize);
NTSTATUS stat1 = NtReadFile(file, NULL, NULL, NULL, &IoStatusBlock, fileData, sizeof(fileData), 0, NULL);
if (stat1 != 0)
{
printf("failed: %X\n", stat1);
}
Instead of sizeof(fileData) pass the fileSize and initialize + pass the ByteOffset value of 0.
LARGE_INTEGER liBytes = { 0 };
status = SysNtReadFile(file, NULL, NULL, NULL, &statusBlock, fileData, fileSize, &liBytes, NULL);
And, In code line
fileData = HeapAlloc(GetProcessHeap(), 0, fileSize);
the third parameter should be set HEAP_ZERO_MEMORY, not 0. See nf-heapapi-heapalloc

Using pipes in a WinDBG extension

I am writing a WinDBG extension to debug a device driver, and need to call an external binary to debug the device's firmware. I would like to show the output of this binary in the WinDBG console.
My initial idea was to simply pipe the output of the binary to a buffer and print that buffer with ControlledOutput. However, I get a 'broken pipe' error when I try to read from the pipe in my extension.
Here is how I create the external process in my extension:
SECURITY_ATTRIBUTES sAttr;
HANDLE childOutRead = NULL;
HANDLE childOutWrite = NULL;
PROCESS_INFORMATION childProcInfo;
STARTUPINFO childStartInfo;
char buf[4096];
sAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
sAttr.bInheritHandle = TRUE;
sAttr.lpSecurityDescriptor = NULL;
CreatePipe(&childOutRead, &childOutWrite, &sAttr, 0);
// don't inherit read end
SetHandleInformation(childOutRead, HANDLE_FLAG_INHERIT, 0);
ZeroMemory(&childProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&childStartInfo, sizeof(STARTUPINFO));
childStartInfo.cb = sizeof(STARTUPINFO);
childStartInfo.hStdError = childOutWrite;
childStartInfo.hStdOut = childOutWrite;
childStartInfo.hStdIn = GetStdHandle(STD_INPUT_HANDLE);
childStartInfo.dwFlags |= STARTF_USESTDHANDLES;
CreateProcessA(NULL, "myBinary.exe someArgs",
NULL, NULL, TRUE, 0, NULL, NULL,
&childStartInfo, &childProcInfo);
// close the handle not used in parent
CloseHandle(childOutWrite);
// read output
while (1) {
DWORD read;
BOOL r;
DWORD error;
r = ReadFile(childOutRead, buf, sizeof(buf), &read, NULL);
if (!r) {
error = GetLastError();
windbgPrintf("got error 0x%x\n", error);
break;
}
if (read == 0) break;
windbgPrint(buf, read);
}
ReadFile fails with error 0x6D, BROKEN_PIPE. This makes me suspect that the pipe is somehow not being inherited.
I have nearly identical code working in a test outside of WinDBG, so it must be doing something differently. How do I get pipes working in this way inside WinDBG?

CreateFileMapping returns error 193 (%1 is not a valid Win32 app)

I have a user app that opens a file and then calls CreateFileMapping. I have a driver that creates/opens the file which I have traced and successfully executes. The problem is that CreateFileMapping always returns error 193. I have successfully mapped against other files so I'm thinking must be an issue on the driver side. Windows 8.1 x64 (driver obviously 64bit) and the application as well. I have used dependency walker to check any dll issues and all seem to be fine.
Driver snippet:
InitializeObjectAttributes(&fileAttributes,
&fileName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, // RootDirectory
NULL // SecurityDescriptor
);
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
return STATUS_INVALID_DEVICE_STATE;
status = ZwCreateFile(
&context->FileHandle,
SYNCHRONIZE | FILE_GENERIC_WRITE | FILE_GENERIC_READ | DELETE,
&fileAttributes,
&ioStatus,
NULL, // alloc size = none
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_RANDOM_ACCESS |
FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE |
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DEVICE_SECURE_OPEN,
NULL, // eabuffer
0 // ealength
);
User app snippet:
LPCWSTR dev_path = L"\\\\.\\testdisk.txt";
fd = CreateFile(dev_path, FILE_GENERIC_READ | FILE_GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, // FILE_SHARE_DELETE
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE)
{
error("open device %ls failed, %s (%u)\n", dev_path, strerror(errno), GetLastError());
exit(EXIT_FAILURE);
}
mapFile = CreateFileMapping(
fd,
NULL,
PAGE_READWRITE,
0, // maximum object size (high-order DWORD)
1, // maximum object size (low-order DWORD)
NULL);
Edit 1:
The filename in the driver is #define DEV_PATH L"\\DosDevices\\C:\\testdisk.txt"
The symbolic link is #define DEV_SYMBOLIC_LINK L"\\DosDevices\\testdrive.txt" using the function WdfDeviceCreateSymbolicLink
and I set the device name to #define DEV_NAME L"\\Device\\testdrive.txt" using the function WdfDeviceInitAssignName
Edit 2:
I have updated the device and file paths. I still get 193 error when accessing the file from user space \\.\qqdevice\test.txt and if I use C:\qqdevice\test.txt then the file gets created but the driver never gets notified.
#define DEV_NAME L"\\Device\\qqdevice"
#define DEV_SYMBOLIC_LINK L"\\DosDevices\\qqdevice"
#define DEV_FILE_PATH L"\\DosDevices\\C:\\qqdevice\\test.txt"

MapViewOfFile failes with errorCode 6 (Invalid Handle)

Im trying to map the file to the memory and use MapViewOfFile(), but it failes with error code 6. I tried just about anything, I also read about big files being the problem, but the problem happens also with a 1kb file.
my code:
HANDLE hFile = CreateFile(pFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
e = GetLastError();
printf("CreateFile Errorcode %d\n", GetLastError());
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Error: could not create handle to file");
printf("CreateFileMapping error code: %d", e)
return 1;
}
printf("successfully created a Handle to try.txt");
HANDLE pMap = CreateFileMapping(hFile, NULL, PAGE_EXECUTE_READWRITE,0 ,0 ,NULL);
e = GetLastError();
if (pMap == INVALID_HANDLE_VALUE)
{
printf("Error: Unable to CreateFileMapping\n");
printf("CreateFileMapping error code: %d", e)
return 1;
}
printf("CreateFileMapping successfull.")
LPVOID lpBase MapViewOfFile(pMap, FILE_MAP_ACCESS| FILE_MAP_EXECUTE, 0, 0, 0);
e = GetLastError();
if (!lpBase)
{
printf("Error: could not map file to memory");
printf("MapViewOfFile Errorcode %d\n", GetLastError());
CloseHandle(hFile);
UnmapViewOfFile(lpBase);
printf("closed hFile handle and unmapped lpBase.")
return 1;
}
the output is the following:
> successfully created a Handle to try.txt
> createFileMapping successfull
> Error: unable to MapViewOfFile
> MapViewOfFile errorcode: 6
> closed hFile handle and unmapped lpBase.
Here:
HANDLE hFile = CreateFile(pFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Replace GENERIC_READ with GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE
Also there is no FILE_MAP_ACCESS, but FILE_MAP_ALL_ACCESS.
I tried this code and it maps test file with success, not sure what you want to do with it further. Also for inspecting problems you can also use: Procmon.exe from sysinternals - it will report you what problems occured during file manipulations.

C CreateFileMapping error 5 Access Denied ALWAYS

I would like to ask for help with WINAPI function CreateFileMapping (), which returns constantly NULL. After GetLastError() I get 5 - "ERROR_ACCESS_DENIED 5 (0x5) Access is denied". The file has been created after CreateFile with no problem, but following CreateFileMapping never has bee succesful.
int MapDestFile(LPCWSTR fPath)
{
hDestFile = CreateFile(
fPath,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hSourceFile == NULL)
{
printf("%d\n", GetLastError());
}
hDestMapFile = CreateFileMapping(
hDestFile,
NULL,
PAGE_READWRITE,
0,
10,
NULL
);
if (hDestMapFile == NULL)
{
// here always tell error number 5
printf("%d\n", GetLastError());
}
lpMapAddressDestFile = MapViewOfFile(
hDestMapFile,
FILE_MAP_WRITE,
0,
0,
0);
if (lpMapAddressDestFile == NULL)
{
printf("%d\n", GetLastError());
}
return 1;
}
I would appreciate any suggestions.
Thanks
You need to create the file with GENERIC_WRITE | GENERIC_READ to match PAGE_READWRITE.
That seems self-evident when you think about it. How can you have memory that you can read from backed by a file that you cannot read from? The documentation does call this out explicitly in any case:
PAGE_READWRITE
The file handle that the hFile parameter specifies must be created with the GENERIC_READ and GENERIC_WRITE access rights.
On top of that your error checking on the call to CreateFile is wrong. Take another look at the documentations. Error is indicated by a return value of INVALID_FILE_HANDLE.

Resources