10 #define IMG_FNAME "disk.img"
12 static int instimg(const char *devpath);
13 static void update_disks(void);
14 static void onclick(struct wgt_widget *w);
15 static void onmodify(struct wgt_widget *w);
16 static void ck_usbonly_handler(struct wgt_widget *w);
19 static struct wgt_window *win;
20 static struct wgt_widget *lb_instto, *bn_inst, *bn_cancel, *cb_devs, *ck_usbonly, *bn_cancel_inst;
22 static struct rawdisk_device rawdev[64];
23 static const char *items[64];
24 static int num_rawdev;
27 static long imgfile_size;
28 static const char *err_noimg_fmt =
29 "Failed to open 256boss disk image: " IMG_FNAME "\n"
32 "Please run this installer from the 256boss distribution directory";
35 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprevinst, char *cmdline, int showcmd)
39 char *msgbuf, *errmsg;
41 if(!(imgfile = fopen(IMG_FNAME, "rb"))) {
42 errmsg = strerror(errno);
43 msgbuf = alloca(strlen(err_noimg_fmt) + strlen(errmsg) + 1);
44 sprintf(msgbuf, err_noimg_fmt, errmsg);
45 MessageBox(0, msgbuf, "Missing disk image!", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
48 fseek(imgfile, 0, SEEK_END);
49 imgfile_size = ftell(imgfile);
51 if(!(win = wgt_window("256boss USB stick installer", 420, 170))) {
55 lb_instto = wgt_label(win, "Install to device:", 10, 20);
57 x = wgt_xpos_after(lb_instto, WGT_AUTO);
58 cb_devs = wgt_combo(win, items, num_rawdev, 0, x, 20, 270, WGT_AUTO, onmodify);
60 y = wgt_ypos_after(cb_devs, 16);
61 ck_usbonly = wgt_checkbox(win, "only show USB devices", 1, x, y,
62 WGT_AUTO, WGT_AUTO, ck_usbonly_handler);
64 y = wgt_ypos_after(ck_usbonly, 32);
65 bn_inst = wgt_button(win, "Install", 70, y, 100, WGT_AUTO, onclick);
66 bn_cancel = wgt_button(win, "Cancel", 230, y, 100, WGT_AUTO, onclick);
70 while(GetMessage(&msg, 0, 0, 0)) {
71 TranslateMessage(&msg);
72 DispatchMessage(&msg);
82 #define MIN_BS (4 * 1024 * 1024)
84 static int instimg(const char *devpath)
90 int width, max_width, height, y, sz, blksz = 512, status = -1;
92 struct wgt_window *win_inst;
93 struct wgt_widget *w, *pbar, *ptext;
94 struct wgt_rect *rect;
95 long num_blk_done, total_blk;
98 if(!(hdev = CreateFile(devpath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
99 0, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0))) {
103 if(rawdisk_eject(hdev) == 0) {
107 if(DeviceIoControl(hdev, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, &geom, sizeof geom, &wrcount, 0)) {
108 blksz = geom.BytesPerSector;
111 while(blksz < MIN_BS) blksz <<= 1;
114 total_blk = (imgfile_size + blksz - 1) / blksz;
116 if(!(blkbuf = malloc(blksz))) {
123 win_inst = wgt_window("Installing ...", 320, 140);
124 wgt_quit_on_close(win_inst, 0);
127 sprintf(blkbuf, "Device sector size: %d bytes", (int)geom.BytesPerSector);
128 w = wgt_label(win_inst, blkbuf, WIN_XPAD, y);
129 if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width;
131 y = wgt_ypos_after(w, 8);
132 sprintf(blkbuf, "Copying in blocks of: %d bytes", blksz);
133 w = wgt_label(win_inst, blkbuf, WIN_XPAD, y);
134 if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width;
136 y = wgt_ypos_after(w, 8);
137 sprintf(blkbuf, "Image size: %ld bytes (%ld blocks)", imgfile_size, total_blk);
138 w = wgt_label(win_inst, blkbuf, WIN_XPAD, y);
139 if((width = wgt_xpos_after(w, WIN_XPAD)) > max_width) max_width = width;
141 y = wgt_ypos_after(w, 8);
142 ptext = wgt_label(win_inst, "-/- (0%)", WIN_XPAD, y);
144 y = wgt_ypos_after(ptext, 8);
145 pbar = wgt_progbar(win_inst, WIN_XPAD, y, width - WIN_XPAD * 2, WGT_AUTO, 0);
146 if((width = wgt_xpos_after(pbar, WIN_XPAD)) > max_width) max_width = width;
148 y = wgt_ypos_after(pbar, 8);
149 bn_cancel_inst = wgt_button(win_inst, "Cancel", 100, y, WGT_AUTO, WGT_AUTO, onclick);
150 rect = wgt_widget_rect(bn_cancel_inst, 0);
151 wgt_move_widget(bn_cancel_inst, WIN_XPAD + (width - rect->width) / 2, rect->y);
153 height = wgt_ypos_after(bn_cancel_inst, WIN_YPAD);
155 max_width += GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
156 height += GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION);
157 wgt_resize_window(win_inst, max_width, height);
159 /* go through any pending messages once first, to allow the window to get drawn correctly */
160 while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
161 if(msg.message == WM_CLOSE || msg.message == WM_DESTROY) {
164 TranslateMessage(&msg);
165 DispatchMessage(&msg);
169 while((sz = fread(blkbuf, 1, blksz, imgfile)) > 0) {
171 memset(blkbuf + sz, 0, blksz - sz);
173 SetFilePointer(hdev, num_blk_done * blksz, 0, FILE_BEGIN);
174 WriteFile(hdev, blkbuf, blksz, &wrcount, 0);
177 progr = num_blk_done * 100 / total_blk;
178 sprintf(blkbuf, "%ld/%ld (%d%%)", num_blk_done, total_blk, progr);
179 wgt_set_text(ptext, blkbuf);
180 wgt_set_progress(pbar, progr);
182 while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
183 if(msg.message == WM_CLOSE || msg.message == WM_DESTROY) {
186 TranslateMessage(&msg);
187 DispatchMessage(&msg);
191 rawdisk_refresh(hdev);
195 wgt_free_window(win_inst);
202 static int isusbdev(struct rawdisk_device *dev)
204 char *ptr = dev->path;
209 buf[i] = tolower(ptr[i]);
211 if(memcmp(buf, "usb", 3) == 0) {
219 static void update_disks(void)
223 for(i=0; i<num_rawdev; i++) {
224 free(rawdev[i].name);
225 free(rawdev[i].path);
228 if((num_rawdev = rawdisk_detect(rawdev, sizeof rawdev / sizeof *rawdev)) == -1) {
229 MessageBox(0, "Failed to detect storage devices!", 0, MB_OK);
233 if(wgt_checkbox_checked(ck_usbonly)) {
235 while(i < num_rawdev) {
236 if(!isusbdev(rawdev + i)) {
237 free(rawdev[i].name);
238 free(rawdev[i].path);
239 rawdev[i] = rawdev[--num_rawdev];
246 for(i=0; i<num_rawdev; i++) {
247 items[i] = rawdev[i].name;
250 wgt_combo_setitems(cb_devs, items, num_rawdev);
253 wgt_enable_widget(cb_devs);
254 wgt_enable_widget(bn_inst);
256 wgt_disable_widget(cb_devs);
257 wgt_disable_widget(bn_inst);
261 static const char *verify_fmt = \
262 "You are about to install 256boss to: %s\n"
267 "Any existing data in the selected device will be lost!\n"
268 "Please verify you have selected the intended device.\n"
270 "Are you certain you wish to proceed with the installation?\n";
272 static const char *success_str = \
273 "Installation complete!\n"
275 "If the 256boss partition doesn't show up immediately,\n"
276 "please eject and re-attach the device\n";
278 static void onclick(struct wgt_widget *w)
283 static int inst_running;
286 if(inst_running) return;
288 sel = wgt_combo_selected(cb_devs);
289 if(sel < 0 || sel >= num_rawdev) {
293 len = strlen(verify_fmt) + strlen(rawdev[sel].name) + strlen(rawdev[sel].path);
294 msgbuf = alloca(len + 1);
295 sprintf(msgbuf, verify_fmt, rawdev[sel].name, rawdev[sel].path);
297 flags = MB_YESNO | MB_ICONWARNING | MB_APPLMODAL | MB_SETFOREGROUND;
298 if(MessageBox(0, msgbuf, "Proceed with installation?", flags) == IDYES) {
300 if(instimg(rawdev[sel].path) == -1) {
301 MessageBox(0, "Installation failed", 0, MB_OK | MB_ICONSTOP | MB_APPLMODAL | MB_SETFOREGROUND);
303 MessageBox(0, success_str, "Done", MB_OK | MB_ICONASTERISK | MB_APPLMODAL | MB_SETFOREGROUND);
308 } else if(w == bn_cancel) {
311 } else if(w == bn_cancel_inst) {
312 struct wgt_window *win = wgt_widget_window(w);
313 PostMessage(wgt_window_handle(win), WM_CLOSE, 0, 0);
317 static void onmodify(struct wgt_widget *w)
319 int sel = wgt_combo_selected(w);
321 const char *selstr = wgt_get_combo_item(w, sel);
322 MessageBox(0, selstr, "selected item", MB_OK);
326 static void ck_usbonly_handler(struct wgt_widget *w)
331 static int close_action(struct wgt_window *w)
333 if(w != win) return 0;