My problem i am having is trying to figure out why this program is not imaging the drives that i have asked it to process.
The following happen :
input : C:\windd64>windd64.exe /if:\\.\PhysicalDrive0 /of:D:\image.raw /buffer:100
Output : Complete
This is not the issue, the issue is when i try to re-write that image to another drive or even the same drive, this is the error that it gives me.
input : C:\windd64>windd64.exe /if:D:\image.raw /of:\\.\PhysicalDrive0 /buffer:100
output : Out destination error : 87
What should i modify or what even seems to be the problem here. No i dont want to use something else i would %100 prefer to remain using this code. This seems the be very efficient in alot of ways, thankyou!
Github Link :
https://github.com/luisgf/windd
Code for windd64.cpp
#include "windd64.h"
LPVOID xmalloc(size_t size) {
LPVOID ptr = malloc(size);
if (!ptr) {
wprintf(L"xmalloc(%d): Memory allocation error\n", size);
exit(-1);
}
return ptr;
}
VOID Usage(LPCTSTR ProgName) {
wprintf(L"Usage: %s /if:INPUT /of:OUTPUT /buffer:200\n\n", ProgName);
wprintf(L"Parameters:\n");
wprintf(L"/?\t\t Show this help\n");
wprintf(L"/if\t\t Input block device or file. Like \\\\.\\PhysicalDrive0\n");
wprintf(L"/of\t\t Source block device or file. Like D:\\image.windd\n");
wprintf(L"/buffer\t\t Amount of memory to use as buffer. In Mb, default=100\n");
wprintf(L"/ibs\t\t Input block size (in bytes)\n");
wprintf(L"/obs\t\t Output block size (in bytes)\n");
wprintf(L"/bs\t\t Block size (Input & Output), overwrite ibs and obs (in bytes)\n");
wprintf(L"/skip\t\t Skip n bytes at input start\n");
wprintf(L"/seek\t\t Seek n bytes at output\n");
wprintf(L"/nd\t\t Hide the disclaimer banner.\n");
wprintf(L"/v\t\t Verbose Output. Show more info about reader/writer parameters.\n");
wprintf(L"\n\n");
exit(0);
}
VOID Disclaimer() {
wprintf(L"WARNING: This program commes without warranty and can damage your computer\n");
wprintf(L"if used incorrectly. Use with caution.\n\n");
}
DWORD WINAPI ReadSect(LPVOID lpParam)
{
DWORD dwRead;
BOOL rs = FALSE;
DWORD dwWaitResult;
PDATA data = NULL;
PTPARAMS param = (PTPARAMS)lpParam;
LONGLONG CurrentOffset = param->StartOffset;
DWORD BytesToRead = MB_TO_BYTES(20);
if (param->Verbose)
wprintf(L"Reader(): StartOffset %lu, EndOffset: %lu, Size %lu, SectorSize: %lu\n", param->StartOffset, param->EndOffset, param->DiskSize, param->SectorSize);
if (param->StartOffset) {
LARGE_INTEGER liStart;
liStart.QuadPart = param->StartOffset;
SetFilePointerEx(param->hDev, liStart, NULL, FILE_BEGIN);
}
while (CurrentOffset != param->EndOffset) {
if (param->cola->size > param->MemBuff) {
Sleep(100);
}
else {
if (param->EndOffset - CurrentOffset EndOffset - CurrentOffset);
data = (PDATA)xmalloc(sizeof(DATA));
data->size = BytesToRead;
data->ptr = (LPVOID)xmalloc(data->size);
rs = ReadFile(param->hDev, data->ptr, data->size, &dwRead, 0);
if (dwRead != data->size) {
wprintf(L"Error reading at offset: %lu\n", CurrentOffset);
return -1;
}
dwWaitResult = WaitForSingleObject(param->Mutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
__try {
param->cola->ptr->push(data);
param->cola->size += BytesToRead;
param->DataProcessed += BytesToRead;
}
__finally {
ReleaseMutex(param->Mutex);
}
break;
}
CurrentOffset += BytesToRead;
wprintf(L"\rCompleted: %.2f %%", (float)((float)(CurrentOffset * 100) / (float)param->DiskSize));
}
}
if (param->Verbose)
wprintf(L"\rData Readed: %lu bytes\n", param->DataProcessed);
return rs;
}
DWORD WINAPI WriteSect(LPVOID lpParam)
{
PTPARAMS param = (PTPARAMS)lpParam;
DWORD dwWaitResult;
PDATA data = NULL;
BOOL rs = FALSE;
ULONGLONG CurrentOffset = param->StartOffset;
if (param->Verbose)
wprintf(L"Writer(): StartOffset %lu, EndOffset: %lu, Size %lu, SectorSize: %lu\n", param->StartOffset, param->EndOffset, param->DiskSize, param->SectorSize);
if (param->StartOffset) {
LARGE_INTEGER liStart;
liStart.QuadPart = param->StartOffset;
SetFilePointerEx(param->hDev, liStart, NULL, FILE_BEGIN);
}
while (CurrentOffset != param->EndOffset) {
dwWaitResult = WaitForSingleObject(param->Mutex, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
__try {
if (param->cola->size == 0) {
Sleep(100);
}
else {
data = (PDATA)param->cola->ptr->front();
DWORD written;
rs = WriteFile(param->hDev, data->ptr, data->size, &written, NULL);
if (written > 0 && written size) {
wprintf(L"\nError, Out of space at destination.\n");
exit(-1);
}
if (!rs) {
wprintf(L"\nError Writing to destination. %lu\n", GetLastError());
exit(-1);
}
param->cola->ptr->pop();
param->cola->size -= data->size;
param->DataProcessed += data->size;
CurrentOffset += data->size;
free(data->ptr);
free(data);
data = NULL;
}
}
__finally {
ReleaseMutex(param->Mutex);
}
break;
}
}
if (param->Verbose)
wprintf(L"Data Writed: %lu bytes\n", param->DataProcessed);
return rs;
}
BOOL GetDescriptorGeometry(HANDLE hDevice, PDWORD SectorSize, PLONGLONG DiskSize) {
BOOL bResult = FALSE;
DWORD junk = 0;
DISK_GEOMETRY_EX pdg = { 0 };
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR pAlignmentDescriptor = { 0 };
STORAGE_PROPERTY_QUERY Query;
ZeroMemory(&Query, sizeof(STORAGE_PROPERTY_QUERY));
Query.PropertyId = StorageAccessAlignmentProperty;
bResult = DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&Query, sizeof(STORAGE_PROPERTY_QUERY),
&pAlignmentDescriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
&junk, NULL);
if (bResult) {
*SectorSize = pAlignmentDescriptor.BytesPerPhysicalSector;
}
bResult = DeviceIoControl(hDevice,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL, 0,
&pdg, sizeof(pdg),
&junk,
(LPOVERLAPPED)NULL);
if (bResult) {
if (!*SectorSize)
*SectorSize = pdg.Geometry.BytesPerSector;
*DiskSize = pdg.DiskSize.QuadPart;
}
else {
LARGE_INTEGER FileSize;
GetFileSizeEx(hDevice, &FileSize);
*SectorSize = 4096;
*DiskSize = FileSize.QuadPart;
bResult = TRUE;
if (!FileSize.QuadPart) {
wprintf(L"Unable to get descriptor Geometry\n");
bResult = FALSE;
}
}
return bResult;
}
BOOL OpenDescriptors(LPTSTR InDev, LPTSTR OutDev, PHANDLE hInDev, PHANDLE hOutDev)
{
DWORD desired_mask = (DWORD)(GENERIC_READ | GENERIC_WRITE);
DWORD acces_mask = (DWORD)(FILE_SHARE_READ | FILE_SHARE_WRITE);
*hInDev = CreateFileW(InDev, desired_mask, acces_mask, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
if (*hInDev == INVALID_HANDLE_VALUE)
{
wprintf(L"Open source descriptor error: %lu", GetLastError());
CloseHandle(*hInDev);
return FALSE;
}
SetFilePointer(*hInDev, 0, 0, FILE_BEGIN);
*hOutDev = CreateFile(OutDev, desired_mask, acces_mask, 0, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING, 0);
if (*hOutDev == INVALID_HANDLE_VALUE)
{
wprintf(L"Out destination descriptor error: %lu", GetLastError());
CloseHandle(*hOutDev);
return FALSE;
}
SetFilePointer(*hOutDev, 0, 0, FILE_BEGIN);
return TRUE;
}
BOOL ParseProgramArguments(PARGUMENTS pParams, DWORD args, _TCHAR **argv) {
LPCTSTR param = NULL;
if (args Verbose = FALSE;
pParams->NoDisclaimer = FALSE;
pParams->dwBuff = MB_TO_BYTES(100);
pParams->dwSkip = 0;
pParams->dwSeek = 0;
for (DWORD i = 1; i sInDev = (LPTSTR)(param += 3);
}
if (!_wcsnicmp(param, L"of:", 3)) {
pParams->sOutDev = (LPTSTR)(param += 3);
}
if (!_wcsnicmp(param, L"bs:", 3)) {
LPCTSTR dwBs = (param += 3);
pParams->dwOutBs = pParams->dwInBs = wcstol(dwBs, NULL, 10);
}
if (!_wcsnicmp(param, L"ibs:", 4)) {
LPCTSTR dwBs = (param += 4);
pParams->dwOutBs = pParams->dwInBs = wcstol(dwBs, NULL, 10);
}
if (!_wcsnicmp(param, L"obs:", 4)) {
LPCTSTR dwBs = (param += 4);
pParams->dwOutBs = wcstol(dwBs, NULL, 10);
}
if (!_wcsnicmp(param, L"buffer:", 7)) {
LPCTSTR dwBuff = (param += 7);
pParams->dwBuff = MB_TO_BYTES(wcstol(dwBuff, NULL, 10));
}
if (!_wcsnicmp(param, L"skip:", 5)) {
LPCTSTR dwSkip = (param += 5);
pParams->dwSkip = wcstol(dwSkip, NULL, 10);
}
if (!_wcsnicmp(param, L"seek:", 5)) {
LPCTSTR dwSeek = (param += 5);
pParams->dwSeek = wcstol(dwSeek, NULL, 10);
}
if (!_wcsnicmp(param, L"nd", 2)) {
pParams->NoDisclaimer = TRUE;
}
if (!_wcsnicmp(param, L"v", 1)) {
pParams->Verbose = TRUE;
}
}
if (!pParams->sInDev) {
wprintf(L"Input (/if) parameter missing.\n");
return FALSE;
}
if (!pParams->sOutDev) {
wprintf(L"Output (/of) parameter missing.\n");
return FALSE;
}
if (!pParams->dwBuff) {
pParams->dwBuff = MB_TO_BYTES(100);
}
if (pParams->dwInBs && (pParams->dwInBs dwInBs % 512) > 0)) {
wprintf(L"Input block size must be multiple of 512.\n");
return FALSE;
}
if (pParams->dwOutBs && (pParams->dwOutBs dwOutBs % 512) > 0)) {
wprintf(L"Output block size must be multiple of 512.\n");
return FALSE;
}
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
ARGUMENTS params = { 0 };
HANDLE hInDev = NULL;
HANDLE hOutDev = NULL;
LONGLONG DiskSize = { 0 };
DWORD SectorSize;
std::queue cola;
HANDLE hMutex;
HANDLE hThread[2] = { 0 };
DWORD ThreadID[2] = { 0 };
if (!ParseProgramArguments(¶ms, argc, argv)) {
return 1;
}
BQUEUE data = { &cola, 0};
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken);
DWORD infoLen;
TOKEN_ELEVATION elevation;
GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &infoLen);
if (!elevation.TokenIsElevated)
{
wprintf(L"This program must run in elevated mode\n");
return -1;
}
#else
#error you are using an old version of sdk or not supported operating system
#endif
if (!OpenDescriptors(params.sInDev, params.sOutDev, &hInDev, &hOutDev))
{
return -1;
}
if (!GetDescriptorGeometry(hInDev, &SectorSize, &DiskSize))
{
return -1;
}
hMutex = CreateMutex(NULL, FALSE, NULL);
if (hMutex == NULL)
{
wprintf(L"CreateMutex() error: %d\n", GetLastError());
return -1;
}
wprintf(L">>> windd %s - By Luis Gonzalez Fernandez\n", VERSION);
if (!params.NoDisclaimer)
Disclaimer();
wprintf(L"%s => %s\n", params.sInDev, params.sOutDev);
TPARAMS ReaderParams = { 0 };
ReaderParams.hDev = hInDev;
ReaderParams.cola = &data;
ReaderParams.StartOffset = params.dwSkip;
ReaderParams.EndOffset = DiskSize;
if (params.dwInBs)
ReaderParams.SectorSize = params.dwInBs;
else
ReaderParams.SectorSize = SectorSize;
ReaderParams.MemBuff = params.dwBuff;
ReaderParams.Mutex = hMutex;
ReaderParams.DiskSize = DiskSize;
ReaderParams.DataProcessed = 0;
ReaderParams.Verbose = params.Verbose;
hThread[0] = CreateThread(NULL, 0, ReadSect, &ReaderParams, 0, &ThreadID[0]);
TPARAMS WriterParams = { 0 };
WriterParams.hDev = hOutDev;
WriterParams.cola = &data;
WriterParams.StartOffset = params.dwSeek;
WriterParams.EndOffset = (DiskSize + params.dwSeek - params.dwSkip);
if (params.dwOutBs)
WriterParams.SectorSize = params.dwOutBs;
else
WriterParams.SectorSize = SectorSize;
WriterParams.Mutex = hMutex;
WriterParams.DiskSize = DiskSize;
WriterParams.DataProcessed = 0;
WriterParams.Verbose = params.Verbose;
hThread[1] = CreateThread(NULL, 0, WriteSect, &WriterParams, 0, &ThreadID[1]);
WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
if (ReaderParams.DataProcessed == WriterParams.DataProcessed)
wprintf(L"Done!\n");
else
wprintf(L"Error, %lu bytes are not copied.\n", (ReaderParams.DataProcessed - WriterParams.DataProcessed));
CloseHandle(hInDev);
CloseHandle(hOutDev);
return 0;
}
Here is the header file respectively :
#pragma once
#include "targetver.h"
#include
#include
#include
#include
#include
#define VERSION L"v1.0.3"
#define MB_TO_BYTES(x) (x * 1024 * 1024)
typedef struct _bqueue {
std::queue *ptr; LONGLONG size; } BQUEUE, *PBQUEUE;
typedef struct tParams {
HANDLE hDev; HANDLE Mutex; DWORD SectorSize; DWORD MemBuff; LONGLONG StartOffset; LONGLONG EndOffset; LONGLONG DiskSize; LONGLONG DataProcessed; PBQUEUE cola; BOOL Verbose; } TPARAMS, *PTPARAMS;
typedef struct ProgArgumentss {
LPTSTR sInDev;
LPTSTR sOutDev;
DWORD dwInBs;
DWORD dwOutBs;
DWORD dwBuff;
DWORD dwSkip;
DWORD dwSeek;
BOOL NoDisclaimer;
BOOL Verbose;
} ARGUMENTS, *PARGUMENTS;
typedef struct _data {
LPVOID ptr; DWORD size; } DATA, *PDATA;
What I have tried:
I have tried reformatting the destination drive, i have tried going from drive to drive many of times i have tried deleting partitions and making new ones i have tried almost everything i can think of that i know of at least.