How to access specific address of a USB drive - winapi

I need to access the partition table of a USB stick and change the first byte of partition 0 to make it bootable. And I also want to copy a bin file to a specific address of that USB drive. So can any one tell me how to perform these kind of tasks?
I badly in need of some examples... If you could provide any links of such kinds of works it would be great. I am working in C.
I am in the beginning stage. Here is my code:
// DeviceIoControl.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
BOOL GetMBR(PARTITION_INFORMATION *pdg)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
hDevice = CreateFile(TEXT("\\\\.\\H:"), // drive to open
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL // do not copy file attributes
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed!\n");
return (FALSE);
}
bResult = DeviceIoControl(
hDevice, // device to be queried
IOCTL_DISK_GET_PARTITION_INFO, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # bytes returned
(LPOVERLAPPED) NULL // synchronous I/O
);
CloseHandle(hDevice);
return (bResult);
}
int _tmain(int argc, _TCHAR* argv[])
{
PARTITION_INFORMATION pdg; // disk drive geometry structure
BOOL bResult; // generic results flag
ULONGLONG DiskSize; // size of the drive, in bytes
bResult = GetMBR(&pdg);
if (bResult)
{
printf ("BootIndicator %lld\n", pdg.BootIndicator);
printf ("HiddenSectors %lld\n", pdg.HiddenSectors);
printf ("PartitionLength %u\n", pdg.PartitionLength);
printf ("PartitionNumber %u\n", pdg.PartitionNumber);
printf ("PartitionType %x\n", pdg.PartitionType);
printf ("RecognizedPartition %s\n", pdg.RecognizedPartition);
printf ("RewritePartition %ld.\n", pdg.RewritePartition);
printf ("StartingOffset %lld\n", pdg.StartingOffset);
}
else
{
printf ("PARTITION INFORMATION failed. Error %ld.\n", GetLastError ());
}
getchar();
return ((int)bResult);
}

Do you have to do it in code? You can use the built-in diskpart tool to make a USB drive bootable by following this tutorial.

Related

StorPortGetDeviceInformation yields error and thus cannot use it

I am trying to get my harddisk serial ID by using StorPortGetDeviceInformation, but it gives me an error: identifier StorPortGetDeviceInformation is undefined. I am also seeing an error such as "Error (active) E0020 identifier "PRTL_RUN_ONCE_INIT_FN" is undefined mutante C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\km\ntddk.h 2225 "
I would be happy if someone could take a look at see why this does not work. Below is the code I am using (from an empty Driver Project created in Visual Studio 2022):
#include <Windows.h>
#include <storport.h>
#include <stdio.h>
#include <ntddk.h>
int main()
{
// Enumerate the physical drives on the system
for (int i = 0; i < 256; i++)
{
// Open a handle to the storage device
WCHAR deviceName[32];
swprintf_s(deviceName, L"\\\\.\\PhysicalDrive%d", i);
HANDLE hDevice = CreateFile(deviceName,
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
continue;
}
// Allocate a buffer to hold the serial ID
ULONG serialIdSize = sizeof(STORAGE_DEVICE_ID_DESCRIPTOR);
PSTORAGE_DEVICE_ID_DESCRIPTOR pSerialId =
(PSTORAGE_DEVICE_ID_DESCRIPTOR)malloc(serialIdSize);
if (pSerialId == NULL)
{
printf("Failed to allocate buffer.\n");
CloseHandle(hDevice);
return 1;
}
// Retrieve the serial ID
ULONG bytesReturned;
if (!StorPortGetDeviceInformation(hDevice,
StorageDeviceIdDescriptor, pSerialId, serialIdSize, &bytesReturned))
{
printf("Failed to get device information.\n");
free(pSerialId);
CloseHandle(hDevice);
return 1;
}
// Print the serial ID
printf("Serial ID of disk %d: %S\n", i, pSerialId->Identifiers[0].Identifier);
// Clean up
free(pSerialId);
CloseHandle(hDevice);
}
return 0;
}
What I done so far:
Created an empty driver project
Installed WDK and can be found in C:\Program Files (x86)\Windows Kits\10
Tried to link against the storport.lib library at C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\km\x64\storport.lib
What I expected:
I can call StorPortGetDeviceInformation from my driver.

Format of the serial number of a physical harddrive retrieved using DeviceIoControl()

I retrieve the serial number of the physical hard-drive using the function DeviceIoControl following the suggestions from Blacktempel in this post. Getting the number works fine in principle, but I (still) have trouble with the format of the serial number as it keeps changing from computer to computer and with time. Also I experienced a format change on some computers between running the program as normal user or as admin.
For example, I retrieved a number with the following format:
WD-WCAZAF632086
when I tested the program first and after a few weeks it looks like:
2020202057202d4443575a414641333630323638
This is still the same number, only the characters have been replaced by their hex codes and swapped pair-wise. I've encountered different formats like a normal string with the characters exchanged pair-wise. Among other values, I need to check this number to verify if a software license is valid for a certain computer. Having an instable and unknown format is annoying and if the format changes to something I'm not yet aware of, I risk that the software license check fails although the license is still valid.
Does anyone know how to get the serial number in a stable format, or how to predict the format so it can be adapted for comparison?
Here is minimal C++ example of code that I used to retrieve the serial number of the first physical disc. I build it using Visual Studio 2015:
#include "stdafx.h"
#include "Windows.h"
#include <string>
#include <vector>
#include <iostream>
bool GetDeviceString(std::string &serialnumber)
{
HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); // Get Handle to device
if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
return false;
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned;
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
{
}
// Alloc the output buffer
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer.data(), dwOutBufferSize,
&dwBytesReturned, NULL))
{
// handle error, do cleanup and return
}
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
// Finally, get the serial number
serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
}
}
int main()
{
std::string serialnumber;
if (GetDeviceString(serialnumber))
{
std::cout << "serial number of first disc: " << serialnumber << std::endl;
}
else
{
std::cout << "Failed!" << std::endl;
}
std::cin.ignore();
return 0;
}

Windows Named Pipe is invalid

I have no idea why this pipe is invalid. everything seems fine to me. This is just a test, i don't write or read from it. Anyone can tell me what's wrong?
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define BUFSIZE 4096
int main()
{
HANDLE hPipe;
LPTSTR Pipename = TEXT("\\\\.\\pipe\\mypipe");
printf("Start Server\n");
for(;;)
{
hPipe = CreateNamedPipe( Pipename,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
BUFSIZE,
BUFSIZE,
NMPWAIT_USE_DEFAULT_WAIT,
NULL );
if ( hPipe == INVALID_HANDLE_VALUE )
{
printf("CreatePipe failed");
return 0;
}
CloseHandle(hPipe);
}
return 1;
}
Without more detail about the error it is difficult to help. However, as a general rule create the server using CreateNamedPipe then use ConnectNamedPipe.
On the client side you can now use CreateFile, which ConnectNamedPipe is waiting for on the server side.

turn on LED using C

I want to turn on a LED using C, meaning that I want to write on parallel port.
but the code doesn't work.
I use char ledStatus instead of BYTE ledStatus. is there any difference??
what is the problem in this code?
#include <windows.h>
#include <conio.h>
#include <staio.h>
#define LED_ON 1
int main()
{
HANDLE h;
unsigned long dwSize=1;
int success;
h = CreateFile(
L"LPT1",
GENERIC_WRITE, // access (read-write) mode
0, // share mode
NULL, // pointer to security attributes
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL // handle to file with attributes to copy
);
if (INVALID_HANDLE_VALUE == h)
{
//Handle Error
printf("CreateFile failed with error %d\n", GetLastError());
exit(1);
}
else
{
printf("CreateFile1 Successful\n");
}
char ledStatus;
// turn on LED
ledStatus = LED_ON;
success = WriteFile(h, &ledStatus, 1, &dwSize, NULL);
if (success)
{
printf("File Write Successful - %i bytes\n", dwSize);
}
else
{
printf("File Write Failed\n");
}
// close port
CloseHandle(h);
return 0;
}
Your question is very poorly documented, you didn't describe what signal you used or how you wired the LED. Lots of ways to get that wrong. But you have no hope of making it work with the standard Windows parallel driver. It was written to interface parallel devices like printers. Which requires handshaking to clock a byte to the device. The driver turns on the STROBE signal, the device must turn on the ACK signal to acknowledge it copied the byte. That of course doesn't happen, the WriteFile() calls only fill a buffer in the driver.
You'll need another driver to directly control the output lines, Inpout32 is a common choice. Find essential advice in Jan Axelson's book, also includes a link to Inpout32.

WriteFile() with WRITE_THROUGH is slow on system disk

On Windows Server 2008 R2 the following very simple program behaves different on system disk and on any other disk. Seems that on system disk FILE_FLAG_WRITE_THROUGH makes something ...
On disk C: (system disk, commodity SATA, no RAID)
$ time ./test.exe
real 1m8.281s
user 0m0.000s
sys 0m0.015s
On disk E: (another physical SATA disk)
$ time ./test.exe
real 0m5.445s
user 0m0.000s
sys 0m0.000s
-
#include <stdio.h>
#include <windows.h>
#define BUFFER_SIZE 1024
#define ITERATIONS 10240
#define FILEFLAGS FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH
BYTE buff[BUFFER_SIZE];
BOOL SyncWriteFile(HANDLE fd,
LPCVOID buf,
DWORD to_write) {
DWORD written = 0, already_written = 0;
BOOL res = FALSE;
while(written < to_write) {
res = WriteFile(fd,
(BYTE*)buf + written,
to_write - written,
&already_written,
NULL);
if (FALSE == res)
return FALSE;
else
written += already_written;
}
return TRUE;
}
void main()
{
HANDLE hFile;
int i;
hFile = CreateFile(TEXT("test"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILEFLAGS,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Could not create test file.");
exit(1);
}
for(i=0; i<ITERATIONS; i++) {
SyncWriteFile(hFile, buff, sizeof(buff));
}
CloseHandle(hFile);
}
What's going on?
Can somebody try to reproduce this on Win Server?
It was weird behavior of Samsung SATA 500GB disk (dying?) with SD15 firmware. We've fixed eventually this with dd utility and new disk. Everything works ok now. Sorry for "false alarm".

Resources