wok-next diff syslinux/stuff/iso2exe/win32.c @ rev 14261

syslinux/iso2exe: add NT+ support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Mar 30 18:36:46 2013 +0100 (2013-03-30)
parents 65b3fd0022ed
children 692d9593f959
line diff
     1.1 --- a/syslinux/stuff/iso2exe/win32.c	Thu Mar 28 11:51:42 2013 +0100
     1.2 +++ b/syslinux/stuff/iso2exe/win32.c	Sat Mar 30 18:36:46 2013 +0100
     1.3 @@ -1,6 +1,259 @@
     1.4  #include <windows.h>
     1.5 +#include <winnt.h>
     1.6 +#include <sys/types.h>
     1.7 +#include <sys/stat.h>
     1.8 +#include <fcntl.h>
     1.9  
    1.10 -int main()
    1.11 +#define BOOTSTRAP_SECTOR_COUNT_OFFSET	28
    1.12 +
    1.13 +static int fullread(int fd, char *p, int n)
    1.14  {
    1.15 -	MessageBox(NULL,"No support for Windows yet.","Sorry",MB_OK|MB_ICONERROR);
    1.16 +	int i, j;
    1.17 +	for (i = 0; n > 0; i += j, n -= j) {
    1.18 +		j = read(fd, p + i, n);
    1.19 +		if (j <= 0) break;
    1.20 +	}
    1.21 +	return i;
    1.22  }
    1.23 +
    1.24 +static int fullwrite(int fd, char *p, int n)
    1.25 +{
    1.26 +	int i, j;
    1.27 +	for (i = 0; n > 0; i += j, n -= j) {
    1.28 +		j = write(fd, p + i, n);
    1.29 +		if (j <= 0) break;
    1.30 +	}
    1.31 +	return i;
    1.32 +}
    1.33 +
    1.34 +static void exec16bits(char *isoFileName)
    1.35 +{
    1.36 +	int fdiso, fdtmp, i;
    1.37 +	long buffer[512/4];
    1.38 +	char tmpFileName[MAX_PATH], *p;
    1.39 +
    1.40 +	strcpy(tmpFileName, isoFileName);
    1.41 +	p = strrchr(tmpFileName, '\\');
    1.42 +	if (!p++) p = tmpFileName;
    1.43 +	strcpy(p, "tazboot.exe");
    1.44 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
    1.45 +	fdtmp = open(tmpFileName, O_WRONLY|O_BINARY|O_CREAT,0555);
    1.46 +	for (i = 0; i < 0x8000; i += sizeof(buffer)) {
    1.47 +		fullread(fdiso, (char *) buffer, sizeof(buffer));
    1.48 +		if (i == 0) buffer[15] = 0;	// kill PE header
    1.49 +		fullwrite(fdtmp, (char *) buffer, sizeof(buffer));
    1.50 +	}
    1.51 +	close(fdiso);
    1.52 +	close(fdtmp);
    1.53 +	execl(tmpFileName, isoFileName);
    1.54 +}
    1.55 +
    1.56 +static int iswinnt(void)
    1.57 +{
    1.58 +	OSVERSIONINFOA Version;
    1.59 +	Version.dwOSVersionInfoSize = sizeof(Version);
    1.60 +	return (GetVersionEx(&Version) &&
    1.61 +	    Version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS); // not Win9x
    1.62 +}
    1.63 +
    1.64 +static int ishybrid(char *isoFileName)
    1.65 +{
    1.66 +	int fdiso;
    1.67 +	char buffer[2048];
    1.68 +	unsigned long magic = 0;
    1.69 +	
    1.70 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
    1.71 +	if (lseek(fdiso, 17 * 2048L, SEEK_SET) != -1 &&
    1.72 +	    fullread(fdiso, buffer, 2048) == 2048 &&
    1.73 +	    strncmp(buffer+23,"EL TORITO SPECIFICATION",23) == 0) {
    1.74 +		unsigned long lba = * (unsigned long *) (buffer + 71);
    1.75 +		
    1.76 +		if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
    1.77 +		    fullread(fdiso, buffer, 2048) == 2048 &&
    1.78 +		    * (unsigned long *) (buffer + 0) == 1 &&
    1.79 +		    * (unsigned long *) (buffer + 30) == 0x88AA55) {
    1.80 +			lba = * (unsigned long *) (buffer + 40);
    1.81 +			if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
    1.82 +			    fullread(fdiso, buffer, 2048) == 2048)
    1.83 +				magic = * (unsigned long *) (buffer + 64);
    1.84 +		}
    1.85 +	}
    1.86 +	close(fdiso);
    1.87 +	return (magic == 1886961915);
    1.88 +}
    1.89 +
    1.90 +#define MODE_READ  0
    1.91 +#define MODE_WRITE 1
    1.92 +static int rdwrsector(int mode, int drive, unsigned long startingsector, 
    1.93 +		      unsigned long count, char *buffer)
    1.94 +{
    1.95 +	HANDLE hDevice;
    1.96 +	DWORD  result;
    1.97 +	char devname[sizeof("\\\\.\\PhysicalDrive0")];
    1.98 +		
    1.99 +	if (drive >= 128) {
   1.100 +		strcpy(devname, "\\\\.\\PhysicalDrive0");
   1.101 +		devname[17] += drive - 128;
   1.102 +	}
   1.103 +	else {
   1.104 +		strcpy(devname, "\\\\.\\A:");
   1.105 +		devname[4] += drive;
   1.106 +	}
   1.107 +	hDevice = CreateFile (devname, GENERIC_READ, 
   1.108 +		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
   1.109 +	if (hDevice == INVALID_HANDLE_VALUE)
   1.110 +		return -1;
   1.111 +	SetFilePointer(hDevice, (startingsector*512), NULL, FILE_BEGIN);
   1.112 +	if (mode == MODE_READ) {
   1.113 +		if (!ReadFile(hDevice, buffer, 512*count, &result, NULL))
   1.114 +			result = -1;
   1.115 +	}
   1.116 +	else {
   1.117 +		if (!WriteFile(hDevice, buffer, 512*count, &result, NULL))
   1.118 +			result = -1;
   1.119 +	}
   1.120 +	CloseHandle(hDevice);
   1.121 +	return result;
   1.122 +}
   1.123 +
   1.124 +static void rawrite(unsigned long drive, char *isoFileName)
   1.125 +{
   1.126 +	int fdiso, s, dev, isohybrid = -1;
   1.127 +	char buffer[2048];
   1.128 +	
   1.129 +	if (drive == 0) return;
   1.130 +	for (dev = 128; (drive & 1) == 0; dev++)
   1.131 +		drive >>= 1;
   1.132 +	fdiso = open(isoFileName, O_RDONLY|O_BINARY);
   1.133 +	for (s = 0;;) {
   1.134 +		int s, n = fullread(fdiso, buffer, sizeof(buffer));
   1.135 +		if (n <= 0) break;
   1.136 +		n = (n+511)/512;
   1.137 +		if (s == 0) isohybrid = buffer[69];
   1.138 +		rdwrsector(MODE_WRITE, dev, s, n, buffer);
   1.139 +		if (s == isohybrid)
   1.140 +			rdwrsector(MODE_WRITE, dev, 0, 1, buffer);
   1.141 +		s += n;
   1.142 +	}
   1.143 +	close(fdiso);
   1.144 +}
   1.145 +
   1.146 +static unsigned long drives(void)
   1.147 +{
   1.148 +	int i, mask, result;
   1.149 +	char buffer[512];
   1.150 +	for (i = result = 0, mask = 1; i < 8; i++, mask <<= 1) {
   1.151 +		if (rdwrsector(MODE_READ, i+128, 0, 1, buffer) != -1)
   1.152 +			result |= mask;
   1.153 +	}
   1.154 +	return result;
   1.155 +}
   1.156 +
   1.157 +static void writefloppy(char *isoFileName)
   1.158 +{
   1.159 +	char buffer[512];
   1.160 +	int i, n, fd;
   1.161 +
   1.162 +	buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
   1.163 +	fd = open(isoFileName, O_RDONLY|O_BINARY);
   1.164 +	if (fd != -1) {
   1.165 +		read(fd, buffer, sizeof(buffer));
   1.166 +		n = buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET];
   1.167 +		if (n != 0 &&
   1.168 +	            lseek(fd, * (unsigned long *) (buffer + 60) - (512 * n),
   1.169 +			      SEEK_SET) != -1) {
   1.170 +			for (i = 0; i < n; i++) {
   1.171 +				fullread(fd, buffer, 512);
   1.172 +				if (i == 1) strncpy(buffer, isoFileName, 512);
   1.173 +				rdwrsector(MODE_WRITE, 0, i, 1, buffer);
   1.174 +			}
   1.175 +		}
   1.176 +		close(fd);
   1.177 +	}
   1.178 +}
   1.179 +
   1.180 +//TODO #define VCPI_LINUX_LOADER The DOS/EXE loader can boot in VM86 using VCPI API
   1.181 +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   1.182 +		   LPSTR lpCmdLine, int nCmdShow)
   1.183 +{
   1.184 +	char isoFileName[MAX_PATH];
   1.185 +	char header[32];
   1.186 +	int fd;
   1.187 +	int  usbkeyicon = MB_ICONASTERISK;
   1.188 +	char *usbkeymsg = "You can either:\n\n"
   1.189 +		"- create a SliTaz USB boot key or a boot memory card.\n"
   1.190 +		"  (note that this will be read only like a CDROM.\n"
   1.191 +		"  The Slitaz utility 'tazusb' can be used later to create\n"
   1.192 +		"  a true read/write USB key).\n\n"
   1.193 +		"- create a SliTaz bootstrap floppy for the ISO image\n"
   1.194 +		"  on the hard disk.\n"
   1.195 +		"\nDo you want to create a boot key now ?";
   1.196 +	
   1.197 +	GetModuleFileName(hInstance, isoFileName, MAX_PATH);
   1.198 +	if (!iswinnt()) {
   1.199 +#ifdef VCPI_LINUX_LOADER
   1.200 +		exec16bits(isoFileName);
   1.201 +#else
   1.202 +		MessageBox(NULL,"No support for Win9x yet.\n"
   1.203 +				"Retry in DOS mode without emm386.\n",
   1.204 +			   "Sorry", MB_OK|MB_ICONERROR);
   1.205 +		exit(1);
   1.206 +#endif
   1.207 +	}
   1.208 +	if (!ishybrid(isoFileName)) {
   1.209 +		if (MessageBox(NULL,"Not an isolinux hybrid ISO.\n"
   1.210 +				    "This ISO image will not boot\n"
   1.211 +				    "from the media you will create !",
   1.212 +			   "Will not boot !", 
   1.213 +			   MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL)
   1.214 +			exit(0);
   1.215 +	}
   1.216 +	header[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
   1.217 +	fd = open(isoFileName, O_RDONLY|O_BINARY);
   1.218 +	if (fd != -1) {
   1.219 +		read(fd, header, sizeof(header));
   1.220 +		close(fd);
   1.221 +	}
   1.222 +	if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] == 0) { // No floppy bootstrap available
   1.223 +		usbkeyicon = MB_ICONQUESTION;
   1.224 +		usbkeymsg = "Do you want to create a boot key ?";
   1.225 +	}
   1.226 +	if (MessageBox(NULL,usbkeymsg, "Create a boot stick ?",
   1.227 +			MB_YESNO|usbkeyicon) == IDYES) {
   1.228 +		unsigned long base, new;
   1.229 +		int retry;
   1.230 +		
   1.231 +		if (MessageBox(NULL,"Step 1: unplug the USB stick.",
   1.232 +				"Drive detection 1/2",
   1.233 +				MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
   1.234 +			exit(0);
   1.235 +		base = drives();
   1.236 +		if (MessageBox(NULL,"Step 2: plug the USB stick in.",
   1.237 +				"Drive detection 2/2",
   1.238 +				MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
   1.239 +			exit(0);
   1.240 +		retry = 0;
   1.241 +		do {
   1.242 +			Sleep(1000); // ms
   1.243 +			new = drives();
   1.244 +		} while (new == base && retry++ < 10);
   1.245 +		if (new == base) {
   1.246 +			MessageBox(NULL,"No USB stick found.","Sorry",
   1.247 +				   MB_OK|MB_ICONERROR);
   1.248 +			exit(1);
   1.249 +		}
   1.250 +		rawrite(base ^ new, isoFileName);
   1.251 +	}
   1.252 +	if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] != 0 &&
   1.253 +	    MessageBox(NULL,"Do you want to create a bootstrap floppy ?",
   1.254 +			    "Create a bootstrap floppy ?",
   1.255 +			MB_YESNO|MB_ICONQUESTION) == IDYES &&
   1.256 +	    MessageBox(NULL,"Insert a floppy disk in drive now",
   1.257 +			    "Insert floppy",
   1.258 +			MB_OKCANCEL|MB_ICONEXCLAMATION) != IDCANCEL) {
   1.259 +
   1.260 +		// Create a 9k bootstrap with vfat, ext2 & ntfs drivers
   1.261 +		// to boot the ISO image on hard disk
   1.262 +		writefloppy(isoFileName);
   1.263 +	}
   1.264 +}