Wrong result for base64 string of HMAC_SHA1 using Crypto*** API - winapi

I'm trying to use the winapi crypto api to get a base64 encoded hash. I copied and modified to get the function below. I got it from here mostly - https://msdn.microsoft.com/en-us/library/windows/desktop/aa382379(v=vs.85).aspx
Running it with calcHmacSha1("message", "key") should give IIjfdNXyFGtIFGyvSWU3fp0L46Q=. However it gives me SlLDwKvAoGBJ0atki7QFfj/181k=, the non base64 version it gives is 4a 52 c3 c0 ab c0 a0 60 49 d1 ab 64 8b b4 05 7e 3f f5 f3 59. This is a same situation encountered here - CryptoAPI returns incorrect result for HMAC_SHA1 - however his solution does not work for key's greater then 16 characters, and that is my need.
#pragma comment (lib, "Crypt32.lib")
#include <wincrypt.h>
std::string calcHmacSha1(std::string msg, std::string key) {
std::string hash;
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
std::vector<BYTE> keybytebuffer(key.begin(), key.end());
// http://msdn.microsoft.com/en-us/library/Aa379863
HCRYPTPROV hProv = NULL;
HCRYPTHASH hHash = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHmacHash = NULL;
PBYTE pbHash = NULL;
DWORD dwDataLen = 0;
BYTE* Data1 = &keybytebuffer[0]; // {0x6b,0x65,0x79};
BYTE* Data2 = &msgbytebuffer[0]; // {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO HmacInfo;
//--------------------------------------------------------------------
// Zero the HMAC_INFO structure and use the SHA1 algorithm for
// hashing.
debug_log("sizeof(Data2)", sizeof(Data2));
debug_log("sizeof(BYTE)", sizeof(BYTE));
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_SHA1;
//--------------------------------------------------------------------
// Acquire a handle to the default RSA cryptographic service provider.
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
debug_log(" Error in AcquireContext 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Derive a symmetric key from a hash object by performing the
// following steps:
// 1. Call CryptCreateHash to retrieve a handle to a hash object.
// 2. Call CryptHashData to add a text string (password) to the
// hash object.
// 3. Call CryptDeriveKey to create the symmetric key from the
// hashed password derived in step 2.
// You will use the key later to create an HMAC hash object.
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) {
debug_log("Error in CryptCreateHash 0x%08x \n", GetLastError());
goto ErrorExit;
}
if (!CryptHashData(hHash, Data1, key.length() * sizeof(BYTE), 0)) {
debug_log("Error in CryptHashData 1 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey)) {
debug_log("Error in CryptDeriveKey 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Create an HMAC by performing the following steps:
// 1. Call CryptCreateHash to create a hash object and retrieve
// a handle to it.
// 2. Call CryptSetHashParam to set the instance of the HMAC_INFO
// structure into the hash object.
// 3. Call CryptHashData to compute a hash of the message.
// 4. Call CryptGetHashParam to retrieve the size, in bytes, of
// the hash.
// 5. Call malloc to allocate memory for the hash.
// 6. Call CryptGetHashParam again to retrieve the HMAC hash.
if (!CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHmacHash)) {
debug_log("Error in CryptCreateHash key 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptSetHashParam(hHmacHash, HP_HMAC_INFO, (BYTE*)&HmacInfo, 0)) {
debug_log("Error in CryptSetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
if (!CryptHashData(hHmacHash, Data2, msg.length() * sizeof(BYTE), 0)) {
debug_log("Error in CryptHashData 2 0x%08x", GetLastError());
goto ErrorExit;
}
//--------------------------------------------------------------------
// Call CryptGetHashParam twice. Call it the first time to retrieve
// the size, in bytes, of the hash. Allocate memory. Then call
// CryptGetHashParam again to retrieve the hash value.
if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, NULL, &dwDataLen, 0)) {
debug_log("Error in CryptGetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
pbHash = (BYTE*)malloc(dwDataLen);
if(NULL == pbHash) {
debug_log("unable to allocate memory\n");
goto ErrorExit;
}
if (!CryptGetHashParam(hHmacHash, HP_HASHVAL, pbHash, &dwDataLen, 0)) {
debug_log("Error in CryptGetHashParam 0x%08x", GetLastError());
goto ErrorExit;
}
DWORD base64Size = 0;
if (!CryptBinaryToString(pbHash, dwDataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &base64Size)) {
debug_log("Error in CryptBinaryToString 1 0x%08x", GetLastError());
goto ErrorExit;
};
WCHAR* base64 = new WCHAR[ base64Size + 1 ];
if (!CryptBinaryToString(pbHash, dwDataLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64, &base64Size)) {
debug_log("Error in CryptBinaryToString 2 0x%08x", GetLastError());
goto ErrorExit;
};
hash = string_cast<std::string>(base64);
delete[] base64;
debug_log("hash:", hash);
// printf("The hash is: ");
// char chash[512];
// for(DWORD i = 0 ; i < dwDataLen ; i++) {
// printf("%.2x ",pbHash[i]);
// }
MessageBox(NULL, L"hi", L"cap", 0);
// Free resources.
ErrorExit:
if(hHmacHash) CryptDestroyHash(hHmacHash);
if(hKey) CryptDestroyKey(hKey);
if(hHash) CryptDestroyHash(hHash);
if(hProv) CryptReleaseContext(hProv, 0);
if(pbHash) free(pbHash);
return hash;
}

the function work correct, not need fix it. but you not take to account what is key here used for HMAC - not direct your string key, but first, based on your string key, RC4 key created and HMAC calculated for this binary RC4 key.
different keys -> different hash.
windows not let direct use string keys. it algorithm is better - first convert weak string key to more strong binary key. however if you want use string key and got result for it - can use code like this:
#define BLOCK_SIZE 64
BOOL hmac(PCSTR key, PCSTR message, ALG_ID Algid)
{
UCHAR i_key_pad[BLOCK_SIZE], o_key_pad[BLOCK_SIZE];
HCRYPTPROV hProv;
HCRYPTHASH hHash;
ULONG len = (ULONG)strlen(key), cb;
BOOL f;
if (f = CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
if (len > BLOCK_SIZE)
{
if (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash))
{
f = CryptHashData(hHash, (PBYTE)key, len, 0) &&
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&len, &(cb = sizeof(len)), 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)(key = (PCSTR)alloca(len)), &len, 0);
CryptDestroyHash(hHash);
}
}
if (f)
{
ULONG i = BLOCK_SIZE;
do
{
UCHAR c = --i < len ? key[i] : 0;
i_key_pad[i] = 0x36 ^ c;
o_key_pad[i] = 0x5c ^ c;
} while (i);
if (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash))
{
f = CryptHashData(hHash, i_key_pad, sizeof(i_key_pad), 0) &&
CryptHashData(hHash, (PBYTE)message, (ULONG)strlen(message), 0) &&
CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&len, &(cb = sizeof(len)), 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)(key = (PCSTR)alloca(len)), &len, 0);
CryptDestroyHash(hHash);
if (f && (f = CryptCreateHash(hProv, Algid, 0, 0, &hHash)))
{
f = CryptHashData(hHash, o_key_pad, sizeof(o_key_pad), 0) &&
CryptHashData(hHash, (PBYTE)key, len, 0) &&
CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)key, &len, 0);
CryptDestroyHash(hHash);
if (f && len)
{
DbgPrint("\nThe hash is: ");
do
{
DbgPrint("%02x", (UCHAR)*key++);
} while (--len);
DbgPrint("\n");
}
}
}
}
CryptReleaseContext(hProv, 0);
}
return f;
}
//The hash is: 2088df74d5f2146b48146caf4965377e9d0be3a4
hmac("key","message", CALG_SHA1);

Related

KNEM cookie and declared region

First question is PROT_WRITE and PROT_READ i wasn't able to find anywhere and it's giving me a hard time compiling. I replaced with 0 and 1 but it doesn't seem to work.
Second, "rejected (unexisting region cookie)"
int rank;
MPI_Init( &argc, &argv );
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Win win;
int knem_fd = open("/dev/knem", O_RDWR);
int err;
uint64_t size = 64;
if( rank == 0 ){
char *inbuf = malloc(size);
for( int i = 0; i < size; i++ )
inbuf[i] = rand() % 26 + 97;
print_array( inbuf, size, '0' );
struct knem_cmd_create_region create;
struct knem_cmd_param_iovec knem_iov[1];
knem_iov[0].base = (uint64_t)&inbuf;
knem_iov[0].len = size;
create.iovec_array = (uintptr_t) &knem_iov[0];
create.iovec_nr = 1;
create.flags = KNEM_FLAG_SINGLEUSE;
//create.protection = 1;
err = ioctl( knem_fd, KNEM_CMD_CREATE_REGION, &create );
MPI_Send( &(create.cookie), 1, MPI_UINT64_T, 1, 0, MPI_COMM_WORLD );
MPI_Barrier( MPI_COMM_WORLD );
} else if( rank == 1 ){
char *obuf = malloc(size);
int err;
struct knem_cmd_copy copy;
struct knem_cmd_create_region create;
struct knem_cmd_param_iovec knem_iov[1];
knem_iov[0].base = (uint64_t)&obuf;
knem_iov[0].len = size;
create.iovec_array = (uintptr_t) &knem_iov[0];
create.iovec_nr = 1;
//create.protection = 0;
create.flags = KNEM_FLAG_SINGLEUSE;
err = ioctl( knem_fd, KNEM_CMD_CREATE_REGION, &create );
MPI_Recv( &(copy.src_cookie), 1, MPI_UINT64_T, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );
copy.src_offset = 0;
copy.dst_cookie = create.cookie;
copy.dst_offset = 0;
copy.flags = 0;
err = ioctl(knem_fd, KNEM_CMD_COPY, &copy);
print_array( obuf, size, '1' );
MPI_Barrier( MPI_COMM_WORLD );
}
0 and 1 both create a region, 0 sends its cookie to 1 and 1 goes in grab data from 0. I checked the received cookie is the same as the send cookie, but it just failed to find the declared region.
PROT_READ and PROT_WRITE are mmap flags, you need to include sys/mman.h to get them. In the second part of the code, you need to set copy.src_cookie to create.cookie (or just use an inline copy to avoid creating that region at all since it'll be destroyed immediately because of the SINGLEUSE flag). Also, make sure ou check the return values of all ioctl before continuing. Copy cannot work if create.cookie wasn't initialized because the create ioctl failed.

How to find MFT Record Number of file in c++?

In linux there is the fstat system call which gives the inode number of a filedescriptor.
Is there any system call or winapi function which would give MFT Record Number of a given file, from its HANDLE or file path?
If there isn't any function or system call so how should I reach to the MFT Record of a file in MFT Table?
for got MFT Record Number for given file need use FileInternalInformation - here returned FILE_INTERNAL_INFORMATION. really this is 48 low bit MftRecordIndex and 16 high bit SequenceNumber
struct
{
LONGLONG MftRecordIndex : 48;
LONGLONG SequenceNumber : 16;
};
look also MFT_SEGMENT_REFERENCE - this is same struct
then for got MFT Record use FSCTL_GET_NTFS_FILE_RECORD as input data - FileReferenceNumber - this is FILE_INTERNAL_INFORMATION.IndexNumber but(!) only low 48 bits(MftRecordIndex) so you need zero high 16 bits(SequenceNumber) and then use FILE_INTERNAL_INFORMATION in place NTFS_FILE_RECORD_INPUT_BUFFER for know NTFS_FILE_RECORD_OUTPUT_BUFFER size - you need first get NTFS_VOLUME_DATA_BUFFER with help FSCTL_GET_NTFS_VOLUME_DATA and use NTFS_VOLUME_DATA_BUFFER.BytesPerFileRecordSegment
NTSTATUS Test(POBJECT_ATTRIBUTES poa)
{
HANDLE hFile, hVolume = 0;
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtOpenFile(&hFile, SYNCHRONIZE, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (0 <= status)
{
union
{
FILE_INTERNAL_INFORMATION fii;
NTFS_FILE_RECORD_INPUT_BUFFER nfrib;
struct
{
LONGLONG MftRecordIndex : 48;
LONGLONG SequenceNumber : 16;
};
};
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, &fii, sizeof(fii), FileInternalInformation)))
{
//need open '\Device\HarddiskVolume<N>' or '<X>:'
status = OpenVolume(hFile, &hVolume);
}
NtClose(hFile);
if (0 <= status)
{
NTFS_VOLUME_DATA_BUFFER nvdb;
if (0 <= (status = NtFsControlFile(hVolume, 0, 0, 0, &iosb, FSCTL_GET_NTFS_VOLUME_DATA, 0, 0, &nvdb, sizeof(nvdb))))
{
DWORD cb = FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER,
FileRecordBuffer[nvdb.BytesPerFileRecordSegment]);
PNTFS_FILE_RECORD_OUTPUT_BUFFER pnfrob = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)alloca(cb);
SequenceNumber = 0;
if (0 <= (status = NtFsControlFile(hVolume, 0, 0, 0, &iosb,
FSCTL_GET_NTFS_FILE_RECORD, &nfrib, sizeof nfrib, pnfrob, cb)))
{
NTFS_FILE_RECORD_HEADER* pnfrh = (NTFS_FILE_RECORD_HEADER*)pnfrob->FileRecordBuffer;;
}
}
NtClose(hVolume);
}
}
return status;
}
NTFS_FILE_RECORD_HEADER - this is FILE_RECORD_SEGMENT_HEADER (i take self structs name from here)

SetupDiEnumDeviceInterfaces returns ERROR_INVALID_PARAMETER when querying bluetooth devices

I'm trying to get a HANDLE from a Bluetooth Low Energy device by using CreateFile().
Therefore I need to extract the device path of the device.
I get an ERROR_INVALID_PARAMETER error when calling SetupDiEnumDeviceInterfaces. It seems that the second parameter (DeviceInfoData) has a problem.
Any ideas what the problem could be?
EDITED: Simplified code
HDEVINFO hDevInfo;
DWORD i;
// Create a HDEVINFO with all present devices.
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_BLUETOOTH, 0, 0, DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
// Insert error handling here.
return;//1;
}
PSP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA;
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
{
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
char detailDataBuf[0x100];
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detailDataBuf;
ULONG length;
ULONG requiredLength = 0;
bool bResult = FALSE;
for(DWORD j = 0; j < 10; j++ )
{
SP_DEVICE_INTERFACE_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(hDevInfo, DeviceInfoData, &GUID_DEVCLASS_BLUETOOTH, j, &interfaceData );
if (!bResult) {
int lastError = GetLastError(); // always returns ERROR 259
continue;
}
// Get the size of the buffer required to receive the device info
SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, NULL, 0, &requiredLength, NULL );
if( requiredLength >= sizeof( detailDataBuf ) )
break;
// Get the name of the device
detailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA );
length = requiredLength;
bResult = SetupDiGetDeviceInterfaceDetail(hDevInfo, &interfaceData, detailData, length, &requiredLength, NULL ) != 0;
if( !bResult )
break;
}
}
EDITED2:
Passing in NULL for DeviceInfoData: This simple case always returns false
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_BLUETOOTH, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
bool bResult = FALSE;
for(DWORD j = 0; j < 10; j++ )
{
SP_DEVICE_INTERFACE_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVCLASS_BLUETOOTH, j, &interfaceData );
if (!bResult) {
int lastError = GetLastError(); // ERROR 259
continue;
}
}
The documentation says:
DeviceInfoData [in, optional]
A pointer to an SP_DEVINFO_DATA structure that specifies a device information element in DeviceInfoSet.
In other words, it must point to an element of deviceInfo, which the pointer you are passing doesn't. If you don't want to filter the results to the interfaces of a specific device in the device information set, pass NULL.
(Note that this is an input parameter, as indicated by the "in" tag. The output is passed via the fifth parameter, DeviceInterfaceData.)

MapViewOfFile chunked loading of file

I want to map file into memory with chunk size equal system granularity. First chunk read without error and all others fails with error 5 (ERROR_ACCESS_DENIED). I tried run program with administrator privileges.
My code:
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hFile = CreateFile( TEXT("db.txt"),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("[ERROR] File opening error %d\n", GetLastError());
return 1;
}
printf("[DONE] File opened successfully.\n");
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMap == NULL) {
printf("[ERROR] Create mapping error %d\n", GetLastError());
return 2;
}
printf("[DONE] Create mapping successfully.\n");
LARGE_INTEGER file_size = { };
if (!GetFileSizeEx(hFile, &file_size)) {
printf("[ERROR] Getiing filesize error %d\n", GetLastError());
return 3;
}
printf("[DONE] Getting file size.\n");
SYSTEM_INFO info = { };
GetSystemInfo(&info);
printf("[DONE] Getting system memory granularity %d.\n", info.dwAllocationGranularity);
DWORD offset = 0;
int size = 0;
do {
char* ENTRY = (char*)MapViewOfFile(hMap, FILE_MAP_READ, HIWORD(offset), LOWORD(offset), info.dwAllocationGranularity);
if (ENTRY == NULL) {
printf("[ERROR] Map entry error %d\n", GetLastError());
} else {
printf("[DONE] MAPPING PART WITH OFFSET %d\n", offset);
//printf("%s\n", ENTRY);
}
if (offset + info.dwAllocationGranularity < file_size.QuadPart) {
offset += info.dwAllocationGranularity;
} else {
offset = file_size.QuadPart;
}
//offset += size;
UnmapViewOfFile(ENTRY);
} while (offset < file_size.QuadPart);
CloseHandle(hMap);
CloseHandle(hFile);
system("pause");
return 0;
}
How I fix it?
You're using HIWORD and LOWORD for the offset in the call to MapViewOfFile, but these only take a 32-bit value and split it into two 16-bit halves - what you want is a 64-bit value split into two 32-bit halves.
Instead you need HIDWORD and LODWORD, which are defined in <intsafe.h>:
#define LODWORD(_qw) ((DWORD)(_qw))
#define HIDWORD(_qw) ((DWORD)(((_qw) >> 32) & 0xffffffff))
Like so:
char* ENTRY = (char*)MapViewOfFile(hMap, FILE_MAP_READ, HIDWORD(offset), LODWORD(offset), info.dwAllocationGranularity);
You need this even though your offset variable is 32 bit (in which case, HIDWORD will just return 0 and the full value of offset is passed as the low-order DWORD).

access denied error from WriteFile to physical disk, win7

I am trying to write some data to an SD card from a specific physical sector. I received a code to do this from a company and they say it works ok on windows-xp. This is the same case with WriteFile error #5 "denied access" under win Vista/seven
Here is the part writing the data to SD card (in my cae drv value is 'F'). Reading from others, I added locking and dismont but the lock fails (and dismount too). I'm not so familiar with windows programming. Can anybody tell me what's wrong in this code? Thanks for any help. (BTW I;m locking 3GiB)
u32 HDD_write(u8 drv, u32 SecAddr, u32 blocks, u8 *buf)
{
u32 ret = 0;
u32 ldistanceLow, ldistanceHigh, dwpointer, bytestoread, numread;
char cur_drv[100];
HANDLE g_hDevice;
sprintf(cur_drv, "\\\\.\\%c:",drv); // , (u32)drv);
g_hDevice = CreateFile(cur_drv, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(g_hDevice == INVALID_HANDLE_VALUE)
return 0;
// lock and dismount
ret = LockFile(g_hDevice, 0, 0, 3 * 1023 * 1023 * 1023, 0);
printf("ret = %d", ret);
DeviceIoControl(g_hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, NULL, NULL);
printf("error = %d", GetLastError());
ldistanceLow = SecAddr << 9;
ldistanceHigh = SecAddr >> (32-9);
dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN);
if(dwpointer != 0xFFFFFFFF) {
bytestoread = blocks * 512;
ret = WriteFile(g_hDevice, buf, bytestoread, (unsigned long *)&numread, NULL);
if(ret) ret = 1;
else {
ret = 0;
printf("error = %d", GetLastError());
}
}
CloseHandle(g_hDevice);
return ret;
}
I solved this problem several days ago and forgot to check my question here.
This is the code I used. We need GENERIC_READ also for block device when creating the file (for partitioned disk). and the key was dismount first and then lock.
u32 HDD_write(u8 drv, u32 SecAddr, u32 blocks, u8 *buf) {
u32 ret = 0;
u32 ldistanceLow, ldistanceHigh, dwpointer, bytestoread, numread;
char cur_drv[100];
HANDLE g_hDevice;
DWORD status;
//sprintf(cur_drv, "\\\\.\\PhysicalDrive%d", drv);
sprintf(cur_drv, "\\\\.\\%c:",drv);
g_hDevice = CreateFile(cur_drv, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(g_hDevice == INVALID_HANDLE_VALUE)
return 0;
// dismout and lock added by ckim
if (!DeviceIoControl(g_hDevice, FSCTL_DISMOUNT_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
DWORD err = GetLastError();
printf("Error %d attempting to dismount volume, error code\n",err);
}
// lock volume
if (!DeviceIoControl(g_hDevice, FSCTL_LOCK_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
{
printf("Error %d attempting to lock device\n", GetLastError());
}
ldistanceLow = SecAddr << 9;
ldistanceHigh = SecAddr >> (32-9);
dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN);
if(dwpointer != 0xFFFFFFFF) {
bytestoread = blocks * 512;
ret = WriteFile(g_hDevice, buf, bytestoread, (unsigned long *)&numread, NULL);
if(ret) ret = 1;
else {
ret = 0;
printf("error = %d", GetLastError());
}
}
CloseHandle(g_hDevice);
return ret;
}

Resources