From f75a9fc7cbdbd3cd0a2bfa715cd307fabeed86c5 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 27 Nov 2011 02:09:45 +0000 Subject: [PATCH] [boot] added MS-DOS file extraction from diskcopy.dll * diskcopy.dll contains a resource ('BINFILE') that is a 1.4MB floppy image of a bootable MS-DOS disk (FAT12) * we can extract these files and use them for bootable USB --- .msvc/rufus_2010.vcxproj | 2 + .msvc/rufus_2010.vcxproj.filters | 6 ++ .msvc/rufus_sources | 1 + Makefile | 2 +- msdos.c | 145 +++++++++++++++++++++++++++++++ msdos.h | 50 +++++++++++ 6 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 msdos.c create mode 100644 msdos.h diff --git a/.msvc/rufus_2010.vcxproj b/.msvc/rufus_2010.vcxproj index e571395f..25bfc3f9 100644 --- a/.msvc/rufus_2010.vcxproj +++ b/.msvc/rufus_2010.vcxproj @@ -143,11 +143,13 @@ + + diff --git a/.msvc/rufus_2010.vcxproj.filters b/.msvc/rufus_2010.vcxproj.filters index 0c416acc..dc7c559d 100644 --- a/.msvc/rufus_2010.vcxproj.filters +++ b/.msvc/rufus_2010.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + @@ -35,6 +38,9 @@ Header Files + + Header Files + diff --git a/.msvc/rufus_sources b/.msvc/rufus_sources index e7e6cd33..d167a9cb 100644 --- a/.msvc/rufus_sources +++ b/.msvc/rufus_sources @@ -25,4 +25,5 @@ SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest SOURCES=rufus.c \ stdlg.c \ + msdos.c \ rufus.rc diff --git a/Makefile b/Makefile index 18a7d11b..2fc73edf 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ STRIP = strip CFLAGS = -std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration -Wno-pointer-sign -Wshadow -O2 -Wl,--subsystem,windows -DWINVER=0x501 -D_WIN32_IE=0x501 LIBS = -lsetupapi -lole32 -lgdi32 -RUFUS_SRC = rufus.c stdlg.c +RUFUS_SRC = rufus.c stdlg.c msdos.c .PHONY: all clean diff --git a/msdos.c b/msdos.c new file mode 100644 index 00000000..9c6ce37e --- /dev/null +++ b/msdos.c @@ -0,0 +1,145 @@ +/* + * Rufus: The Resourceful USB Formatting Utility + * MS-DOS boot file extraction, from the FAT12 floppy image in diskcopy.dll + * Copyright (c) 2011 Pete Batard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include + +#include "rufus.h" +#include "msdos.h" + +static BYTE* DiskImage; +static size_t DiskImageSize; + +/* Extract the file identified by FAT RootDir index 'entry' to 'path' */ +static BOOL ExtractFAT(int entry, const char* path) +{ + FILE* fd; + char filename[MAX_PATH]; + size_t i, pos; + size_t filestart; + size_t filesize; + size_t FATFile = FAT12_ROOTDIR_OFFSET + entry*FAT12_ROOTDIR_ENTRY_SIZE; + + if ((path == NULL) || ((safe_strlen(path) + 14) > sizeof(filename))) { + uprintf("invalid path supplied for MS-DOS FAT extraction\n"); + return FALSE; + } + strcpy(filename, path); + pos = strlen(path); + filename[pos++] = '\\'; + + for(i=0; i<8; i++) { + if (DiskImage[FATFile + i] == ' ') + break; + filename[pos++] = DiskImage[FATFile + i]; + } + filename[pos++] = '.'; + for (i=8; i<11; i++) { + if (DiskImage[FATFile + i] == ' ') + break; + filename[pos++] = DiskImage[FATFile + i]; + } + filename[pos] = 0; + GET_ULONG_LE(filesize, DiskImage, FATFile + FAT12_ROOTDIR_FILESIZE); + GET_USHORT_LE(filestart, DiskImage, FATFile + FAT12_ROOTDIR_FIRSTCLUSTER); + filestart += FAT12_CLUSTER_OFFSET; + filestart *= FAT12_CLUSTER_SIZE; + if ((filestart + filesize) > DiskImageSize) { + uprintf("FAT File %s would be out of bounds\n", filename); + return FALSE; + } + + fd = fopen(filename, "wb"); + if (fd == NULL) { + uprintf("Unable to create file '%s'.\n", filename); + return FALSE; + } + + if (fwrite(&DiskImage[filestart], 1, filesize, fd) != filesize) { + uprintf("Couldn't write file '%s'.\n", filename); + fclose(fd); + return FALSE; + } + fclose(fd); + + uprintf("Succesfully wrote '%s' (%d bytes)\n", filename, filesize); + + // TODO: MSDOS.SYS and IO.SYS should have 'rahs' attributes + return TRUE; +} + +/* Extract the MS-DOS files contained in the FAT12 1.4MB floppy + image included as resource "BINFILE" in diskcopy.dll */ +BOOL ExtractMSDOS(const char* path) +{ + char dllname[MAX_PATH] = "C:\\Windows\\System32"; + int i, j; + HMODULE hDLL; + HRSRC hDiskImage; + + // TODO: optionally extract some more, including "deleted" entries + char* extractlist[] = {"MSDOS SYS", "COMMAND COM", "IO SYS"}; + + GetSystemDirectoryA(dllname, sizeof(dllname)); + safe_strcat(dllname, sizeof(dllname), "\\diskcopy.dll"); + hDLL = LoadLibraryA(dllname); + if (hDLL == NULL) { + uprintf("Unable to open %s: %s\n", dllname, WindowsErrorString()); + return FALSE; + } + hDiskImage = FindResourceA(hDLL, MAKEINTRESOURCEA(1), "BINFILE"); + if (hDiskImage == NULL) { + uprintf("Unable to locate disk image in %s: %s\n", dllname, WindowsErrorString()); + FreeLibrary(hDLL); + return FALSE; + } + DiskImage = (BYTE*)LockResource(LoadResource(hDLL, hDiskImage)); + if (DiskImage == NULL) { + uprintf("Unable to access disk image in %s: %s\n", dllname, WindowsErrorString()); + FreeLibrary(hDLL); + return FALSE; + } + DiskImageSize = (size_t)SizeofResource(hDLL, hDiskImage); + // Sanity check + if (DiskImageSize < 700*1024) { + uprintf("MS-DOS disk image is too small (%d bytes)\n", dllname, DiskImageSize); + FreeLibrary(hDLL); + return FALSE; + } + + for (i=0; i + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* http://www.c-jump.com/CIS24/Slides/FAT/lecture.html */ +#define FAT12_ROOTDIR_OFFSET 0x2600 +#define FAT12_ROOTDIR_ENTRY_SIZE 0x20 +#define FAT12_ROOTDIR_NB_ENTRIES 0xE0 +#define FAT12_ROOTDIR_FIRSTCLUSTER 0x1A // No need for high word on a 1.44 MB media +#define FAT12_ROOTDIR_FILESIZE 0x1C +#define FAT12_DELETED_ENTRY 0xE5 + +/* Ideally, we'd read those from the FAT Boot Sector, but we have + a pretty good idea of what they are for a 1.44 MB floppy image */ +#define FAT12_CLUSTER_SIZE 0x200 // = sector size +#define FAT12_DATA_START 0x4200 +#define FAT12_CLUSTER_OFFSET ((FAT12_DATA_START/FAT12_CLUSTER_SIZE)-2) // First cluster in data area is #2 + +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (ULONG) (b)[(i) ] ) \ + | ( (ULONG) (b)[(i) + 1] << 8 ) \ + | ( (ULONG) (b)[(i) + 2] << 16 ) \ + | ( (ULONG) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef GET_USHORT_LE +#define GET_USHORT_LE(n,b,i) \ +{ \ + (n) = ( (USHORT) (b)[(i) ] ) \ + | ( (USHORT) (b)[(i) + 1] << 8 ); \ +} +#endif