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