176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2003 Lars Munch Christensen - All Rights Reserved 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 1998-2008 H. Peter Anvin - All Rights Reserved 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Based on the Linux installer program for SYSLINUX by H. Peter Anvin 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or modify 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * it under the terms of the GNU General Public License as published by 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Boston MA 02111-1307, USA; either version 2 of the License, or 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (at your option) any later version; incorporated herein by reference. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */ 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * syslinux-mingw.c - Win2k/WinXP installer program for SYSLINUX 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <windows.h> 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <ctype.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <getopt.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "syslinux.h" 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "libfat.h" 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "setadv.h" 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "sysexits.h" 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "syslxopt.h" 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "syslxfs.h" 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "ntfssect.h" 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifdef __GNUC__ 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman# define noreturn void __attribute__((noreturn)) 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#else 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman# define noreturn void 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid error(char *msg); 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Begin stuff for MBR code */ 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <winioctl.h> 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PART_TABLE 0x1be 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PART_SIZE 0x10 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PART_COUNT 4 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define PART_ACTIVE 0x80 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// The following struct should be in the ntddstor.h file, but I didn't have it. 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// mingw32 has <ddk/ntddstor.h>, but including that file causes all kinds 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// of other failures. mingw64 has it in <winioctl.h>. 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// Thus, instead of STORAGE_DEVICE_NUMBER, use a lower-case private 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman// definition... 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct storage_device_number { 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DEVICE_TYPE DeviceType; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ULONG DeviceNumber; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ULONG PartitionNumber; 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanBOOL GetStorageDeviceNumberByHandle(HANDLE handle, 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const struct storage_device_number *sdn) 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BOOL result = FALSE; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD count; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (DeviceIoControl(handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 0, (LPVOID) sdn, sizeof(*sdn), &count, NULL)) { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = TRUE; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("GetDriveNumber: DeviceIoControl failed"); 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (result); 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint GetBytesPerSector(HANDLE drive) 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int result = 0; 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DISK_GEOMETRY g; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD count; 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (DeviceIoControl(drive, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &g, sizeof(g), &count, NULL)) { 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = g.BytesPerSector; 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (result); 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9176d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanBOOL FixMBR(int driveNum, int partitionNum, int write_mbr, int set_active) 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman BOOL result = TRUE; 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman HANDLE drive; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char driveName[128]; 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sprintf(driveName, "\\\\.\\PHYSICALDRIVE%d", driveNum); 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drive = CreateFile(driveName, 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GENERIC_READ | GENERIC_WRITE, 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_SHARE_WRITE | FILE_SHARE_READ, 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NULL, OPEN_EXISTING, 0, NULL); 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (drive == INVALID_HANDLE_VALUE) { 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Accessing physical drive"); 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (result) { 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned char sector[SECTOR_SIZE]; 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD howMany; 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (GetBytesPerSector(drive) != SECTOR_SIZE) { 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Error: Sector size of this drive is %d; must be %d\n", 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GetBytesPerSector(drive), SECTOR_SIZE); 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (result) { 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (ReadFile(drive, sector, sizeof(sector), &howMany, NULL) == 0) { 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Reading raw drive"); 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (howMany != sizeof(sector)) { 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Error: ReadFile on drive only got %d of %d bytes\n", 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (int)howMany, sizeof(sector)); 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman // Copy over the MBR code if specified (-m) 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (write_mbr) { 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (result) { 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (syslinux_mbr_len >= PART_TABLE) { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Error: MBR will not fit; not writing\n"); 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(sector, syslinux_mbr, syslinux_mbr_len); 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman // Check that our partition is active if specified (-a) 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (set_active) { 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (sector[PART_TABLE + (PART_SIZE * (partitionNum - 1))] != 0x80) { 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int p; 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (p = 0; p < PART_COUNT; p++) 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sector[PART_TABLE + (PART_SIZE * p)] = 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (p == partitionNum - 1 ? 0x80 : 0); 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (result) { 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFilePointer(drive, 0, NULL, FILE_BEGIN); 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (WriteFile(drive, sector, sizeof(sector), &howMany, NULL) == 0) { 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Writing MBR"); 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else if (howMany != sizeof(sector)) { 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Error: WriteFile on drive only wrote %d of %d bytes\n", 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (int)howMany, sizeof(sector)); 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!CloseHandle(drive)) { 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("CloseFile on drive"); 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman result = FALSE; 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (result); 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* End stuff for MBR code */ 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst char *program; /* Name of program */ 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Check Windows version. 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * On Windows Me/98/95 you cannot open a directory, physical disk, or 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * volume using CreateFile. 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint checkver(void) 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman OSVERSIONINFO osvi; 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman GetVersionEx(&osvi); 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((osvi.dwMajorVersion > 4) || 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0))); 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Windows error function 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid error(char *msg) 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LPVOID lpMsgBuf; 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Format the Windows error message */ 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman (LPTSTR) & lpMsgBuf, 0, NULL); 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Print it */ 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "%s: %s", msg, (char *)lpMsgBuf); 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Free the buffer */ 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LocalFree(lpMsgBuf); 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Wrapper for ReadFile suitable for libfat 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint libfat_readfile(intptr_t pp, void *buf, size_t secsize, 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman libfat_sector_t sector) 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint64_t offset = (uint64_t) sector * secsize; 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LONG loword = (LONG) offset; 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LONG hiword = (LONG) (offset >> 32); 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LONG hiwordx = hiword; 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD bytes_read; 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (SetFilePointer((HANDLE) pp, loword, &hiwordx, FILE_BEGIN) != loword || 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hiword != hiwordx || 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman !ReadFile((HANDLE) pp, buf, secsize, &bytes_read, NULL) || 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bytes_read != secsize) { 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Cannot read sector %u\n", sector); 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return secsize; 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void move_file(char *pathname, char *filename) 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char new_name[strlen(opt.directory) + 16]; 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char *cp = new_name + 3; 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *sd; 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int slash = 1; 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman new_name[0] = opt.device[0]; 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman new_name[1] = ':'; 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman new_name[2] = '\\'; 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (sd = opt.directory; *sd; sd++) { 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char c = *sd; 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (c == '/' || c == '\\') { 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (slash) 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman continue; 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman c = '\\'; 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slash = 1; 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slash = 0; 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *cp++ = c; 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Skip if subdirectory == root */ 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (cp > new_name + 3) { 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!slash) 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *cp++ = '\\'; 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(cp, filename, 12); 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Delete any previous file */ 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFileAttributes(new_name, FILE_ATTRIBUTE_NORMAL); 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DeleteFile(new_name); 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!MoveFile(pathname, new_name)) { 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Failed to move %s to destination directory: %s\n", 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman filename, opt.directory); 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFileAttributes(pathname, FILE_ATTRIBUTE_READONLY | 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_SYSTEM | 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_HIDDEN); 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFileAttributes(new_name, FILE_ATTRIBUTE_READONLY | 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_SYSTEM | 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_HIDDEN); 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, char *argv[]) 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman HANDLE f_handle, d_handle; 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD bytes_read; 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD bytes_written; 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD drives; 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman UINT drive_type; 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static unsigned char sectbuf[SECTOR_SIZE]; 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char **argp; 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char drive_name[] = "\\\\.\\?:"; 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char drive_root[] = "?:\\"; 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char ldlinux_name[] = "?:\\ldlinux.sys"; 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static char ldlinuxc32_name[] = "?:\\ldlinux.c32"; 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const char *errmsg; 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct libfat_filesystem *fs; 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman libfat_sector_t s, *secp; 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman libfat_sector_t *sectors; 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ldlinux_sectors; 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t ldlinux_cluster; 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int nsectors; 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int fs_type; 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!checkver()) { 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "You need to be running at least Windows NT; use syslinux.com instead.\n"); 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman program = argv[0]; 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman parse_options(argc, argv, MODE_SYSLINUX_DOSWIN); 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!opt.device || !isalpha(opt.device[0]) || opt.device[1] != ':' 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || opt.device[2]) 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman usage(EX_USAGE, MODE_SYSLINUX_DOSWIN); 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.sectors || opt.heads || opt.reset_adv || opt.set_once 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || (opt.update_only > 0) || opt.menu_save || opt.offset) { 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "At least one specified option not yet implemented" 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman " for this installer.\n"); 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Test if drive exists */ 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drives = GetLogicalDrives(); 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(drives & (1 << (tolower(opt.device[0]) - 'a')))) { 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "No such drive %c:\n", opt.device[0]); 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Determines the drive type */ 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drive_name[4] = opt.device[0]; 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ldlinux_name[0] = opt.device[0]; 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ldlinuxc32_name[0] = opt.device[0]; 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drive_root[0] = opt.device[0]; 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman drive_type = GetDriveType(drive_root); 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Test for removeable media */ 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((drive_type == DRIVE_FIXED) && (opt.force == 0)) { 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Not a removable drive (use -f to override) \n"); 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Test for unsupported media */ 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((drive_type != DRIVE_FIXED) && (drive_type != DRIVE_REMOVABLE)) { 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Unsupported media\n"); 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * First open the drive 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman d_handle = CreateFile(drive_name, GENERIC_READ | GENERIC_WRITE, 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_SHARE_READ | FILE_SHARE_WRITE, 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NULL, OPEN_EXISTING, 0, NULL); 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (d_handle == INVALID_HANDLE_VALUE) { 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not open drive"); 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Make sure we can read the boot sector 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!ReadFile(d_handle, sectbuf, SECTOR_SIZE, &bytes_read, NULL)) { 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Reading boot sector"); 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (bytes_read != SECTOR_SIZE) { 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Could not read the whole boot sector\n"); 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Check to see that what we got was indeed an FAT/NTFS 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * boot sector/superblock 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((errmsg = syslinux_check_bootsect(sectbuf, &fs_type))) { 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "%s\n", errmsg); 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Change to normal attributes to enable deletion */ 39476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Just ignore error if the file do not exists */ 39576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFileAttributes(ldlinux_name, FILE_ATTRIBUTE_NORMAL); 39676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFileAttributes(ldlinuxc32_name, FILE_ATTRIBUTE_NORMAL); 39776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Delete the file */ 39976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Just ignore error if the file do not exists */ 40076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DeleteFile(ldlinux_name); 40176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DeleteFile(ldlinuxc32_name); 40276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Initialize the ADV -- this should be smarter */ 40476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_reset_adv(syslinux_adv); 40576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 40676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Create ldlinux.sys file */ 40776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f_handle = CreateFile(ldlinux_name, GENERIC_READ | GENERIC_WRITE, 40876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_SHARE_READ | FILE_SHARE_WRITE, 40976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NULL, CREATE_ALWAYS, 41076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | 41176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_HIDDEN, NULL); 41276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f_handle == INVALID_HANDLE_VALUE) { 41476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Unable to create ldlinux.sys"); 41576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 41676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 41776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 41876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Write ldlinux.sys file */ 41976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!WriteFile(f_handle, (const char _force *)syslinux_ldlinux, 42076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_ldlinux_len, &bytes_written, NULL) || 42176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bytes_written != syslinux_ldlinux_len) { 42276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not write ldlinux.sys"); 42376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 42476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 42576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!WriteFile(f_handle, syslinux_adv, 2 * ADV_SIZE, 42676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &bytes_written, NULL) || 42776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bytes_written != 2 * ADV_SIZE) { 42876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not write ADV to ldlinux.sys"); 42976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 43076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 43176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Now flush the media */ 43376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!FlushFileBuffers(f_handle)) { 43476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("FlushFileBuffers failed"); 43576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 43676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 43776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 43876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Map the file (is there a better way to do this?) */ 43976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ldlinux_sectors = (syslinux_ldlinux_len + 2 * ADV_SIZE + SECTOR_SIZE - 1) 44076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman >> SECTOR_SHIFT; 44176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sectors = calloc(ldlinux_sectors, sizeof *sectors); 44276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (fs_type == NTFS) { 44376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DWORD err; 44476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman S_NTFSSECT_VOLINFO vol_info; 44576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman LARGE_INTEGER vcn, lba, len; 44676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman S_NTFSSECT_EXTENT extent; 44776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 44876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman err = NtfsSectGetVolumeInfo(drive_name + 4, &vol_info); 44976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (err != ERROR_SUCCESS) { 45076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not fetch NTFS volume info"); 45176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 45276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 45376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman secp = sectors; 45476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nsectors = 0; 45576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for (vcn.QuadPart = 0; 45676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NtfsSectGetFileVcnExtent(f_handle, &vcn, &extent) == ERROR_SUCCESS; 45776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vcn = extent.NextVcn) { 45876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman err = NtfsSectLcnToLba(&vol_info, &extent.FirstLcn, &lba); 45976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (err != ERROR_SUCCESS) { 46076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not translate LDLINUX.SYS LCN to disk LBA"); 46176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 46276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 46376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman lba.QuadPart -= vol_info.PartitionLba.QuadPart; 46476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len.QuadPart = ((extent.NextVcn.QuadPart - 46576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman extent.FirstVcn.QuadPart) * 46676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman vol_info.SectorsPerCluster); 46776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (len.QuadPart-- && nsectors < ldlinux_sectors) { 46876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *secp++ = lba.QuadPart++; 46976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nsectors++; 47076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman goto map_done; 47376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 47476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fs = libfat_open(libfat_readfile, (intptr_t) d_handle); 47576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL); 47676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman secp = sectors; 47776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nsectors = 0; 47876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s = libfat_clustertosector(fs, ldlinux_cluster); 47976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (s && nsectors < ldlinux_sectors) { 48076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *secp++ = s; 48176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman nsectors++; 48276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s = libfat_nextsector(fs, s); 48376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 48476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman libfat_close(fs); 48576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanmap_done: 48676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 48776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 48876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Patch ldlinux.sys and the boot sector 48976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 49076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_patch(sectors, nsectors, opt.stupid_mode, opt.raid_mode, opt.directory, NULL); 49176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 49276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 49376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Rewrite the file 49476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 49576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (SetFilePointer(f_handle, 0, NULL, FILE_BEGIN) != 0 || 49676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman !WriteFile(f_handle, syslinux_ldlinux, syslinux_ldlinux_len, 49776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &bytes_written, NULL) 49876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman || bytes_written != syslinux_ldlinux_len) { 49976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not write ldlinux.sys"); 50076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 50176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 50276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 50376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* If desired, fix the MBR */ 50476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.install_mbr || opt.activate_partition) { 50576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct storage_device_number sdn; 50676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (GetStorageDeviceNumberByHandle(d_handle, &sdn)) { 50776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!FixMBR(sdn.DeviceNumber, sdn.PartitionNumber, opt.install_mbr, opt.activate_partition)) { 50876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 50976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Did not successfully update the MBR; continuing...\n"); 51076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 51276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, 51376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "Could not find device number for updating MBR; continuing...\n"); 51476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 51676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 51776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Close file */ 51876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CloseHandle(f_handle); 51976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Move the file to the desired location */ 52176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.directory) 52276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman move_file(ldlinux_name, "ldlinux.sys"); 52376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 52476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f_handle = CreateFile(ldlinuxc32_name, GENERIC_READ | GENERIC_WRITE, 52576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_SHARE_READ | FILE_SHARE_WRITE, 52676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NULL, CREATE_ALWAYS, 52776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | 52876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_HIDDEN, NULL); 52976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f_handle == INVALID_HANDLE_VALUE) { 53176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Unable to create ldlinux.c32"); 53276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 53376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 53476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 53576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Write ldlinux.c32 file */ 53676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!WriteFile(f_handle, (const char _force *)syslinux_ldlinuxc32, 53776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_ldlinuxc32_len, &bytes_written, NULL) || 53876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bytes_written != syslinux_ldlinuxc32_len) { 53976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not write ldlinux.c32"); 54076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 54176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 54276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Now flush the media */ 54476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!FlushFileBuffers(f_handle)) { 54576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("FlushFileBuffers failed"); 54676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 54776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 54876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 54976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CloseHandle(f_handle); 55076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Move the file to the desired location */ 55276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.directory) 55376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman move_file(ldlinuxc32_name, "ldlinux.c32"); 55476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Make the syslinux boot sector */ 55676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman syslinux_make_bootsect(sectbuf, fs_type); 55776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 55876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Write the syslinux boot sector into the boot sector */ 55976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (opt.bootsecfile) { 56076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman f_handle = CreateFile(opt.bootsecfile, GENERIC_READ | GENERIC_WRITE, 56176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_SHARE_READ | FILE_SHARE_WRITE, 56276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman NULL, CREATE_ALWAYS, 56376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman FILE_ATTRIBUTE_ARCHIVE, NULL); 56476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (f_handle == INVALID_HANDLE_VALUE) { 56576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Unable to create bootsector file"); 56676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 56776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 56876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!WriteFile(f_handle, sectbuf, SECTOR_SIZE, &bytes_written, NULL)) { 56976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman error("Could not write boot sector file"); 57076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 57176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 57276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CloseHandle(f_handle); 57376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } else { 57476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman SetFilePointer(d_handle, 0, NULL, FILE_BEGIN); 57576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman WriteFile(d_handle, sectbuf, SECTOR_SIZE, &bytes_written, NULL); 57676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 57776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 57876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (bytes_written != SECTOR_SIZE) { 57976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman fprintf(stderr, "Could not write the whole boot sector\n"); 58076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman exit(1); 58176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 58276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Close file */ 58476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman CloseHandle(d_handle); 58576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 58676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Done! */ 58776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 58876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 589