#include  <windows.h>
#include "pkfuncs.h"
#include "debug.h"
#include "stringutils.h"

extern "C"
BOOL KernelIoControl(DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned);
    
bool getdiskinfo(DWORD *di)
{
    DWORD cmd[4];
    DWORD nReturned=0;
    cmd[0]=0xe; cmd[1]=0; cmd[2]=0; cmd[3]=0x40;
    if (!KernelIoControl(0x1013F98, cmd, 0x10, di, 0x40, &nReturned)) {
        error("kioctl(FLASH, diskinfo)");
        return false;
    }
    return true;
}
bool init_flash()
{
    DWORD cmd[4];
    DWORD nReturned=0;
    cmd[0]=0x1; cmd[1]=0; cmd[2]=0; cmd[3]=0;
    if (!KernelIoControl(0x1013F98, cmd, 0x10, NULL, 0, &nReturned)) {
        error("kioctl(FLASH, init)");
        return false;
    }
    return true;
}
bool start_read()
{
    DWORD cmd[4];
    DWORD nReturned=0;
    cmd[0]=0x9; cmd[1]=0; cmd[2]=0; cmd[3]=0;
    if (!KernelIoControl(0x1013F98, cmd, 0x10, NULL, 0, &nReturned)) {
        error("kioctl(FLASH, startread)");
        return false;
    }
    return true;
}
bool read_sector(DWORD secnr, BYTE *buf)
{
    start_read();
    DWORD cmd[4];
    DWORD nReturned=0;
    cmd[0]=0x5; cmd[1]=secnr; cmd[2]=0; cmd[3]=0x200;
    if (!KernelIoControl(0x1013F98, cmd, 0x10, buf, 0x200, &nReturned)) {
        error("kioctl(FLASH, read)");
        return false;
    }
    return true;

}
int WINAPI WinMain( HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
    DebugSetLogfile("bksamsungflash.log");

    BOOL bMode = SetKMode(TRUE);
    DWORD dwPerm = SetProcPermissions(0xFFFFFFFF);

    if (!init_flash()) {
        debug("error initializing flash\n");
        return false;
    }

    DWORD di[16];
    memset(di, 0, sizeof(di));
    if (!getdiskinfo(di)) {
        debug("error getting di\n");
    }
    else {
        debug("di: %s\n", hexdump((BYTE*)di, 16, 4).c_str());
    }

    HANDLE h= CreateFile(lpCmdLine, GENERIC_WRITE, FILE_SHARE_READ,
                NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (h==INVALID_HANDLE_VALUE || h==NULL) {
        error("creating %ls", lpCmdLine);
        return 1;
    }
    for (DWORD secnr= 0 ; secnr < 0x040000 ; secnr++) {
        BYTE buf[0x200];
        memset(buf, 0xaa, 0x200);
        if (!read_sector(secnr, buf)) {
            memset(buf, 0x55, 0x200);
        }
        DWORD wrote=0;
        if (!WriteFile(h, buf, 0x200, &wrote, NULL)) {
            error("write %08lx", secnr);
            CloseHandle(h);
            return 1;
        }
    }
    CloseHandle(h);

    SetProcPermissions(dwPerm);
    SetKMode(bMode);
    return 0;
}
