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