X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=instimg;a=blobdiff_plain;f=src%2Fmain.c;h=c2dce3b231edad0854163b544d48a239400d30db;hp=b49c9e32fb8d7f7400b41ac7a4586c6b27d781fd;hb=c81bf22901960cf05babbb157272d784f47a18f6;hpb=5ac430128e1fa0e70e1cb232bd5d756b7e8c6abf diff --git a/src/main.c b/src/main.c index b49c9e3..c2dce3b 100644 --- a/src/main.c +++ b/src/main.c @@ -1,66 +1,344 @@ #include #include +#include +#include #include +#include #include "widgets.h" #include "rawdisk.h" +#define IMG_FNAME "disk.img" + +#define WIN_XPAD 10 +#define WIN_YPAD 15 + +static int instimg(const char *devpath); +static void update_disks(void); +static void onclick(struct wgt_widget *w); +static void onmodify(struct wgt_widget *w); +static void ck_usbonly_handler(struct wgt_widget *w); + + static struct wgt_window *win; -static struct wgt_widget *lb_instto, *bn_inst, *bn_cancel, *cb_devs, *ck_usbonly; +static struct wgt_widget *lb_instto, *bn_inst, *bn_cancel, *cb_devs, *ck_usbonly, *bn_cancel_inst; + static struct rawdisk_device rawdev[64]; +static const char *items[64]; static int num_rawdev; -static void onclick(struct wgt_widget *w); -static void onmodify(struct wgt_widget *w); +static FILE *imgfile; +static long imgfile_size; +static const char *err_noimg_fmt = + "Failed to open 256boss disk image: " IMG_FNAME "\n" + "%s\n" + "\n" + "Please run this installer from the 256boss distribution directory"; +static const char *fail_err_str; int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst, char *cmdline, int showcmd) { - int i, x, y; + int x, y, width, height, max_width; MSG msg; - static const char *items[64]; + char *msgbuf, *errmsg; - if((num_rawdev = rawdisk_detect(rawdev, sizeof rawdev / sizeof *rawdev)) == -1) { + if(!(imgfile = fopen(IMG_FNAME, "rb"))) { + errmsg = strerror(errno); + msgbuf = alloca(strlen(err_noimg_fmt) + strlen(errmsg) + 1); + sprintf(msgbuf, err_noimg_fmt, errmsg); + MessageBox(0, msgbuf, "Missing disk image!", MB_OK | MB_ICONSTOP | MB_APPLMODAL); return 1; } - for(i=0; i max_width) max_width = width; y = wgt_ypos_after(cb_devs, 16); ck_usbonly = wgt_checkbox(win, "only show USB devices", 1, x, y, - WGT_AUTO, WGT_AUTO, 0); + WGT_AUTO, WGT_AUTO, ck_usbonly_handler); + if((width = wgt_xpos_after(ck_usbonly, WIN_XPAD)) > max_width) max_width = width; - y = wgt_ypos_after(ck_usbonly, 16); - bn_inst = wgt_button(win, "Install", 10, y, WGT_AUTO, WGT_AUTO, onclick); + y = wgt_ypos_after(ck_usbonly, 32); + bn_inst = wgt_button(win, "Install", 70, y, 100, WGT_AUTO, onclick); + bn_cancel = wgt_button(win, "Cancel", 230, y, 100, WGT_AUTO, onclick); - x = wgt_xpos_after(bn_inst, WGT_AUTO); - bn_cancel = wgt_button(win, "Cancel", x, y, WGT_AUTO, WGT_AUTO, onclick); + height = wgt_ypos_after(bn_inst, WIN_YPAD); - if(!num_rawdev) { - wgt_disable_widget(cb_devs); - wgt_disable_widget(bn_inst); - } + wgt_resize_window(win, max_width, height); + + update_disks(); while(GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } - wgt_destroy_window(win); + fclose(imgfile); + wgt_free_window(win); return 0; } +#define MIN_BS (4 * 1024 * 1024) + +static int instimg(const char *devpath) +{ + MSG msg; + HANDLE hdev; + DWORD wrcount; + DISK_GEOMETRY geom; + int width, max_width, height, y, sz, blksz = 512, status = -1; + char *blkbuf; + struct wgt_window *win_inst; + struct wgt_widget *w, *pbar, *ptext; + struct wgt_rect *rect; + long num_blk_done, total_blk; + int progr; + + if((hdev = CreateFile(devpath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0)) == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, + &fail_err_str, 0, 0); + return -1; + } + + /*if(rawdisk_eject(hdev) == 0) { + rawdisk_load(hdev); + }*/ + + if(DeviceIoControl(hdev, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, &geom, sizeof geom, &wrcount, 0)) { + blksz = geom.BytesPerSector; + } + + while(blksz < MIN_BS) blksz <<= 1; + + num_blk_done = 0; + total_blk = (imgfile_size + blksz - 1) / blksz; + + if(!(blkbuf = malloc(blksz))) { + CloseHandle(hdev); + fail_err_str = "failed to allocate block buffer"; + return -1; + } + + max_width = 0; + + win_inst = wgt_window("Installing ...", 320, 140); + wgt_quit_on_close(win_inst, 0); + + y = WIN_YPAD; + sprintf(blkbuf, "Device sector size: %d bytes", (int)geom.BytesPerSector); + w = wgt_label(win_inst, blkbuf, WIN_XPAD, y); + if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width; + + y = wgt_ypos_after(w, 8); + sprintf(blkbuf, "Copying in blocks of: %d bytes", blksz); + w = wgt_label(win_inst, blkbuf, WIN_XPAD, y); + if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width; + + y = wgt_ypos_after(w, 8); + sprintf(blkbuf, "Image size: %ld bytes (%ld blocks)", imgfile_size, total_blk); + w = wgt_label(win_inst, blkbuf, WIN_XPAD, y); + if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width; + + y = wgt_ypos_after(w, 8); + ptext = wgt_label(win_inst, "-/- (0%)", WIN_XPAD, y); + + y = wgt_ypos_after(ptext, 8); + pbar = wgt_progbar(win_inst, WIN_XPAD, y, width - WIN_XPAD * 2, WGT_AUTO, 0); + if((width = wgt_xpos_after(pbar, WIN_XPAD)) > max_width) max_width = width; + + y = wgt_ypos_after(pbar, 8); + bn_cancel_inst = wgt_button(win_inst, "Cancel", 100, y, WGT_AUTO, WGT_AUTO, onclick); + rect = wgt_widget_rect(bn_cancel_inst, 0); + wgt_move_widget(bn_cancel_inst, WIN_XPAD + (width - rect->width) / 2, rect->y); + + height = wgt_ypos_after(bn_cancel_inst, WIN_YPAD); + + wgt_resize_window(win_inst, max_width, height); + + /* go through any pending messages once first, to allow the window to get drawn correctly */ + while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + if(msg.message == WM_CLOSE || msg.message == WM_DESTROY) { + goto end; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + rewind(imgfile); + while((sz = fread(blkbuf, 1, blksz, imgfile)) > 0) { + if(sz < blksz) { + memset(blkbuf + sz, 0, blksz - sz); + } + SetFilePointer(hdev, num_blk_done * blksz, 0, FILE_BEGIN); + if(!WriteFile(hdev, blkbuf, blksz, &wrcount, 0)) { + DWORD err = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, + &fail_err_str, 0, 0); + goto end; + } + + num_blk_done++; + progr = num_blk_done * 100 / total_blk; + sprintf(blkbuf, "%ld/%ld (%d%%)", num_blk_done, total_blk, progr); + wgt_set_text(ptext, blkbuf); + wgt_set_progress(pbar, progr); + + while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + if(msg.message == WM_CLOSE || msg.message == WM_DESTROY) { + goto end; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + rawdisk_refresh(hdev); + + status = 0; +end: + wgt_free_window(win_inst); + + free(blkbuf); + CloseHandle(hdev); + return status; +} + +static int isusbdev(struct rawdisk_device *dev) +{ + char *ptr = dev->path; + while(*ptr) { + int i; + char buf[3]; + for(i=0; i<3; i++) { + buf[i] = tolower(ptr[i]); + } + if(memcmp(buf, "usb", 3) == 0) { + return 1; + } + ptr++; + } + return 0; +} + +static void update_disks(void) +{ + int i; + + for(i=0; i= num_rawdev) { + return; + } + + len = strlen(verify_fmt) + strlen(rawdev[sel].name) + strlen(rawdev[sel].path); + msgbuf = alloca(len + 1); + sprintf(msgbuf, verify_fmt, rawdev[sel].name, rawdev[sel].path); + + flags = MB_YESNO | MB_ICONWARNING | MB_APPLMODAL | MB_SETFOREGROUND; + if(MessageBox(0, msgbuf, "Proceed with installation?", flags) == IDYES) { + inst_running = 1; + if(instimg(rawdev[sel].path) == -1) { + int prev_len = len; + len = strlen(fail_fmt) + (fail_err_str ? strlen(fail_err_str) : strlen("unknown")); + if(len > prev_len) { + alloca(len - prev_len); + } + sprintf(msgbuf, fail_fmt, fail_err_str ? fail_err_str : "unknown"); + MessageBox(0, msgbuf, 0, MB_OK | MB_ICONSTOP | MB_APPLMODAL | MB_SETFOREGROUND); + } else { + MessageBox(0, success_str, "Done", MB_OK | MB_ICONASTERISK | MB_APPLMODAL | MB_SETFOREGROUND); + } + inst_running = 0; + } + + } else if(w == bn_cancel) { + PostQuitMessage(0); + + } else if(w == bn_cancel_inst) { + struct wgt_window *win = wgt_widget_window(w); + PostMessage(wgt_window_handle(win), WM_CLOSE, 0, 0); + } } static void onmodify(struct wgt_widget *w) @@ -71,3 +349,14 @@ static void onmodify(struct wgt_widget *w) MessageBox(0, selstr, "selected item", MB_OK); } } + +static void ck_usbonly_handler(struct wgt_widget *w) +{ + update_disks(); +} + +static int close_action(struct wgt_window *w) +{ + if(w != win) return 0; + return 1; +} \ No newline at end of file