wok-next view syslinux/stuff/iso2exe/win32.c @ rev 14263

syslinux/iso2exe: tiny edits
author Paul Issott <paul@slitaz.org>
date Sun Mar 31 22:55:34 2013 +0100 (2013-03-31)
parents 5ed4d6b2d690
children bf8be127c60b
line source
1 #include <windows.h>
2 #include <winnt.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
7 #define BOOTSTRAP_SECTOR_COUNT_OFFSET 28
9 static int fullread(int fd, char *p, int n)
10 {
11 int i, j;
12 for (i = 0; n > 0; i += j, n -= j) {
13 j = read(fd, p + i, n);
14 if (j <= 0) break;
15 }
16 return i;
17 }
19 static int fullwrite(int fd, char *p, int n)
20 {
21 int i, j;
22 for (i = 0; n > 0; i += j, n -= j) {
23 j = write(fd, p + i, n);
24 if (j <= 0) break;
25 }
26 return i;
27 }
29 static void exec16bits(char *isoFileName)
30 {
31 int fdiso, fdtmp, i;
32 long buffer[512/4];
33 char tmpFileName[MAX_PATH], *p;
35 strcpy(tmpFileName, isoFileName);
36 p = strrchr(tmpFileName, '\\');
37 if (!p++) p = tmpFileName;
38 strcpy(p, "tazboot.exe");
39 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
40 fdtmp = open(tmpFileName, O_WRONLY|O_BINARY|O_CREAT,0555);
41 for (i = 0; i < 0x8000; i += sizeof(buffer)) {
42 fullread(fdiso, (char *) buffer, sizeof(buffer));
43 if (i == 0) buffer[15] = 0; // kill PE header
44 fullwrite(fdtmp, (char *) buffer, sizeof(buffer));
45 }
46 close(fdiso);
47 close(fdtmp);
48 execl(tmpFileName, isoFileName);
49 }
51 static int iswinnt(void)
52 {
53 OSVERSIONINFOA Version;
54 Version.dwOSVersionInfoSize = sizeof(Version);
55 return (GetVersionEx(&Version) &&
56 Version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS); // not Win9x
57 }
59 static int ishybrid(char *isoFileName)
60 {
61 int fdiso;
62 char buffer[2048];
63 unsigned long magic = 0;
65 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
66 if (lseek(fdiso, 17 * 2048L, SEEK_SET) != -1 &&
67 fullread(fdiso, buffer, 2048) == 2048 &&
68 strncmp(buffer+23,"EL TORITO SPECIFICATION",23) == 0) {
69 unsigned long lba = * (unsigned long *) (buffer + 71);
71 if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
72 fullread(fdiso, buffer, 2048) == 2048 &&
73 * (unsigned long *) (buffer + 0) == 1 &&
74 * (unsigned long *) (buffer + 30) == 0x88AA55) {
75 lba = * (unsigned long *) (buffer + 40);
76 if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
77 fullread(fdiso, buffer, 2048) == 2048)
78 magic = * (unsigned long *) (buffer + 64);
79 }
80 }
81 close(fdiso);
82 return (magic == 1886961915);
83 }
85 #define MODE_READ 0
86 #define MODE_WRITE 1
87 static int rdwrsector(int mode, int drive, unsigned long startingsector,
88 unsigned long count, char *buffer)
89 {
90 HANDLE hDevice;
91 DWORD result;
92 char devname[sizeof("\\\\.\\PhysicalDrive0")];
94 if (drive >= 128) {
95 strcpy(devname, "\\\\.\\PhysicalDrive0");
96 devname[17] += drive - 128;
97 }
98 else {
99 strcpy(devname, "\\\\.\\A:");
100 devname[4] += drive;
101 }
102 hDevice = CreateFile (devname, GENERIC_READ,
103 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
104 if (hDevice == INVALID_HANDLE_VALUE)
105 return -1;
106 SetFilePointer(hDevice, (startingsector*512), NULL, FILE_BEGIN);
107 if (mode == MODE_READ) {
108 if (!ReadFile(hDevice, buffer, 512*count, &result, NULL))
109 result = -1;
110 }
111 else {
112 if (!WriteFile(hDevice, buffer, 512*count, &result, NULL))
113 result = -1;
114 }
115 CloseHandle(hDevice);
116 return result;
117 }
119 static void rawrite(unsigned long drive, char *isoFileName)
120 {
121 int fdiso, s, dev, isohybrid = -1;
122 char buffer[2048];
124 if (drive == 0) return;
125 for (dev = 128; (drive & 1) == 0; dev++)
126 drive >>= 1;
127 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
128 for (s = 0;;) {
129 int s, n = fullread(fdiso, buffer, sizeof(buffer));
130 if (n <= 0) break;
131 n = (n+511)/512;
132 if (s == 0) isohybrid = buffer[69];
133 rdwrsector(MODE_WRITE, dev, s, n, buffer);
134 if (s == isohybrid)
135 rdwrsector(MODE_WRITE, dev, 0, 1, buffer);
136 s += n;
137 }
138 close(fdiso);
139 }
141 static unsigned long drives(void)
142 {
143 int i, mask, result;
144 char buffer[512];
145 for (i = result = 0, mask = 1; i < 8; i++, mask <<= 1) {
146 if (rdwrsector(MODE_READ, i+128, 0, 1, buffer) != -1)
147 result |= mask;
148 }
149 return result;
150 }
152 static void writefloppy(char *isoFileName)
153 {
154 char buffer[512];
155 int i, n, fd;
157 buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
158 fd = open(isoFileName, O_RDONLY|O_BINARY);
159 if (fd != -1) {
160 read(fd, buffer, sizeof(buffer));
161 n = buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET];
162 if (n != 0 &&
163 lseek(fd, * (unsigned long *) (buffer + 60) - (512 * n),
164 SEEK_SET) != -1) {
165 for (i = 0; i < n; i++) {
166 fullread(fd, buffer, 512);
167 if (i == 1) strncpy(buffer, isoFileName, 512);
168 rdwrsector(MODE_WRITE, 0, i, 1, buffer);
169 }
170 }
171 close(fd);
172 }
173 }
175 //TODO #define VCPI_LINUX_LOADER The DOS/EXE loader can boot in VM86 using VCPI API
176 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
177 LPSTR lpCmdLine, int nCmdShow)
178 {
179 char isoFileName[MAX_PATH];
180 char header[32];
181 int fd;
182 int usbkeyicon = MB_ICONASTERISK;
183 char *usbkeymsg = "You can either:\n\n"
184 "- create a SliTaz USB boot key or a boot memory card.\n"
185 " (note that this will be read only like a CDROM.\n"
186 " The Slitaz utility 'tazusb' can be used later to create\n"
187 " a true read/write USB key).\n\n"
188 "- create a SliTaz bootstrap floppy for the ISO image\n"
189 " on the hard disk.\n"
190 "\nDo you want to create a boot key now ?";
192 GetModuleFileName(hInstance, isoFileName, MAX_PATH);
193 if (!iswinnt()) {
194 #ifdef VCPI_LINUX_LOADER
195 exec16bits(isoFileName);
196 #else
197 MessageBox(NULL,"No support for Win9x yet.\n"
198 "Retry in DOS mode without emm386.\n",
199 "Sorry", MB_OK|MB_ICONERROR);
200 exit(1);
201 #endif
202 }
203 if (!ishybrid(isoFileName)) {
204 if (MessageBox(NULL,"Not an isolinux hybrid ISO.\n"
205 "This ISO image will not boot\n"
206 "from the media that you create !",
207 "Will not boot !",
208 MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL)
209 exit(0);
210 }
211 header[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
212 fd = open(isoFileName, O_RDONLY|O_BINARY);
213 if (fd != -1) {
214 read(fd, header, sizeof(header));
215 close(fd);
216 }
217 if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] == 0) { // No floppy bootstrap available
218 usbkeyicon = MB_ICONQUESTION;
219 usbkeymsg = "Do you want to create a boot key ?";
220 }
221 if (MessageBox(NULL,usbkeymsg, "Create a boot stick ?",
222 MB_YESNO|usbkeyicon) == IDYES) {
223 unsigned long base, new;
224 int retry;
226 if (MessageBox(NULL,"Step 1: unplug the USB stick.",
227 "Drive detection 1/2",
228 MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
229 exit(0);
230 base = drives();
231 if (MessageBox(NULL,"Step 2: plug the USB stick in.",
232 "Drive detection 2/2",
233 MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
234 exit(0);
235 retry = 0;
236 do {
237 Sleep(1000); // ms
238 new = drives();
239 } while (new == base && retry++ < 10);
240 if (new == base) {
241 MessageBox(NULL,"No USB stick found.","Sorry",
242 MB_OK|MB_ICONERROR);
243 exit(1);
244 }
245 rawrite(base ^ new, isoFileName);
246 }
247 if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] != 0 &&
248 MessageBox(NULL,"Do you want to create a bootstrap floppy ?",
249 "Create a bootstrap floppy ?",
250 MB_YESNO|MB_ICONQUESTION) == IDYES &&
251 MessageBox(NULL,"Insert a floppy disk in drive now",
252 "Insert floppy",
253 MB_OKCANCEL|MB_ICONEXCLAMATION) != IDCANCEL) {
255 // Create a 9k bootstrap with vfat, ext2 & ntfs drivers
256 // to boot the ISO image on hard disk
257 writefloppy(isoFileName);
258 }
259 }