[syslinux:master] win: Add further NTFS support to Windows installers

syslinux-bot for Shao Miller shao.miller at yrdsb.edu.on.ca
Sat Dec 17 21:19:29 PST 2011


Commit-ID:  966e23ecf875a0863636e6c5403b0c3ebaa3bdde
Gitweb:     http://www.syslinux.org/commit/966e23ecf875a0863636e6c5403b0c3ebaa3bdde
Author:     Shao Miller <shao.miller at yrdsb.edu.on.ca>
AuthorDate: Sun, 14 Aug 2011 19:41:24 -0400
Committer:  Paulo Alcantara <pcacjr at gmail.com>
CommitDate: Sun, 11 Sep 2011 04:09:59 +0000

win: Add further NTFS support to Windows installers

We have a way of building a map of the LDLINUX.SYS sectors
on an NTFS filesystem, now.

Signed-off-by: Paulo Alcantara <pcacjr at gmail.com>
Signed-off-by: Shao Miller <shao.miller at yrdsb.edu.on.ca>

---
 win/ntfssect.c                |  355 +++++++++++++++++++++++++++++++++++++++++
 win/ntfssect.h                |  152 ++++++++++++++++++
 win/ntfstest.c                |  163 +++++++++++++++++++
 win/ntfstest.rc               |   26 +++
 win/syslinux.c                |   35 ++++
 win32/Makefile                |    2 +-
 win32/{ => ntfstest}/Makefile |   43 ++----
 win64/Makefile                |    2 +-
 win64/{ => ntfstest}/Makefile |   44 ++----
 9 files changed, 761 insertions(+), 61 deletions(-)

diff --git a/win/ntfssect.c b/win/ntfssect.c
new file mode 100644
index 0000000..8c2bcca
--- /dev/null
+++ b/win/ntfssect.c
@@ -0,0 +1,355 @@
+/* -------------------------------------------------------------------------- *
+ *
+ *   Copyright 2011 Shao Miller - All Rights Reserved
+ *
+ *   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, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+/****
+ * ntfssect.c
+ *
+ * Fetch NTFS file cluster & sector information via Windows
+ *
+ * With special thanks to Mark Roddy for his article:
+ *   http://www.wd-3.com/archive/luserland.htm
+ */
+
+#include <windows.h>
+#include <winioctl.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "ntfssect.h"
+
+/*** Macros */
+#define M_ERR(msg) (NtfsSectLastErrorMessage = (msg))
+
+/*** Function declarations */
+static DWORD NtfsSectGetVolumeHandle(
+    CHAR * VolumeName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  );
+static DWORD NtfsSectGetVolumePartitionLba(S_NTFSSECT_VOLINFO * VolumeInfo);
+
+/*** Objects */
+CHAR * NtfsSectLastErrorMessage;
+
+/*** Function definitions */
+DWORD M_NTFSSECT_API NtfsSectGetFileVcnExtent(
+    HANDLE File,
+    LARGE_INTEGER * Vcn,
+    S_NTFSSECT_EXTENT * Extent
+  ) {
+    BOOL bad, ok;
+    DWORD output_size, rc;
+    STARTING_VCN_INPUT_BUFFER input;
+    RETRIEVAL_POINTERS_BUFFER output;
+
+    bad = (
+        File == INVALID_HANDLE_VALUE ||
+        !Vcn ||
+        Vcn->QuadPart < 0 ||
+        !Extent
+      );
+    if (bad)
+      return ERROR_INVALID_PARAMETER;
+
+    input.StartingVcn = *Vcn;
+    ok = DeviceIoControl(
+        File,
+        FSCTL_GET_RETRIEVAL_POINTERS,
+        &input,
+        sizeof input,
+        &output,
+        sizeof output,
+        &output_size,
+        NULL
+      );
+    rc = GetLastError();
+    switch (rc) {
+        case NO_ERROR:
+        case ERROR_MORE_DATA:
+          Extent->FirstVcn = output.StartingVcn;
+          Extent->NextVcn = output.Extents[0].NextVcn;
+          Extent->FirstLcn = output.Extents[0].Lcn;
+          return ERROR_SUCCESS;
+
+        case ERROR_HANDLE_EOF:
+          break;
+
+        default:
+          M_ERR("NtfsSectGetFileVcnExtent(): Unknown status!");
+      }
+
+    return rc;
+  }
+
+/* Internal use only */
+static DWORD NtfsSectGetVolumeHandle(
+    CHAR * VolumeName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  ) {
+    #define M_VOL_PREFIX "\\\\.\\"
+    CHAR volname[sizeof M_VOL_PREFIX - 1 + MAX_PATH + 1] = M_VOL_PREFIX;
+    CHAR * const volname_short = volname + sizeof M_VOL_PREFIX - 1;
+    CHAR * c;
+    DWORD rc;
+
+    /* Prefix "\\.\" onto the passed volume name */
+    strcpy(volname + sizeof M_VOL_PREFIX - 1, VolumeName);
+
+    /* Find the last non-null character */
+    for (c = volname_short; *c; ++c)
+      ;
+
+    /* Remove trailing back-slash */
+    if (c[-1] == '\\')
+      c[-1] = 0;
+
+    /* Open the volume */
+    VolumeInfo->Handle = CreateFile(
+        volname,
+        GENERIC_READ,
+        FILE_SHARE_READ | FILE_SHARE_WRITE,
+        NULL,
+        OPEN_EXISTING,
+        0,
+        NULL
+      );
+    rc = GetLastError();
+    if (VolumeInfo->Handle == INVALID_HANDLE_VALUE) {
+        M_ERR("Unable to open volume handle!");
+        goto err_handle;
+      }
+
+    return ERROR_SUCCESS;
+
+    CloseHandle(VolumeInfo->Handle);
+    err_handle:
+
+    return rc;
+  }
+
+DWORD M_NTFSSECT_API NtfsSectGetVolumeInfo(
+    CHAR * VolumeName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  ) {
+    S_NTFSSECT_XPFUNCS xp_funcs;
+    DWORD rc, free_clusts, total_clusts;
+    BOOL ok;
+
+    if (!VolumeName || !VolumeInfo)
+      return ERROR_INVALID_PARAMETER;
+
+    rc = NtfsSectGetVolumeHandle(VolumeName, VolumeInfo);
+    if (rc != ERROR_SUCCESS)
+      goto err_handle;
+
+    rc = NtfsSectLoadXpFuncs(&xp_funcs);
+    if (rc != ERROR_SUCCESS)
+      goto err_xp_funcs;
+
+    ok = xp_funcs.GetDiskFreeSpace(
+        VolumeName,
+        &VolumeInfo->SectorsPerCluster,
+        &VolumeInfo->BytesPerSector,
+        &free_clusts,
+        &total_clusts
+      );
+    rc = GetLastError();
+    if (!ok) {
+        M_ERR("GetDiskFreeSpace() failed!");
+        goto err_freespace;
+      }
+
+    rc = NtfsSectGetVolumePartitionLba(VolumeInfo);
+    if (rc != ERROR_SUCCESS)
+      goto err_lba;
+
+    VolumeInfo->Size = sizeof *VolumeInfo;
+    rc = ERROR_SUCCESS;
+
+    err_lba:
+
+    err_freespace:
+
+    NtfsSectUnloadXpFuncs(&xp_funcs);
+    err_xp_funcs:
+
+    if (rc != ERROR_SUCCESS) {
+        CloseHandle(VolumeInfo->Handle);
+        VolumeInfo->Handle = INVALID_HANDLE_VALUE;
+      }
+    err_handle:
+
+    return rc;
+  }
+
+DWORD M_NTFSSECT_API NtfsSectGetVolumeInfoFromFileName(
+    CHAR * FileName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  ) {
+    S_NTFSSECT_XPFUNCS xp_funcs;
+    DWORD rc;
+    CHAR volname[MAX_PATH + 1];
+    BOOL ok;
+
+    if (!FileName || !VolumeInfo)
+      return ERROR_INVALID_PARAMETER;
+
+    rc = NtfsSectLoadXpFuncs(&xp_funcs);
+    if (rc != ERROR_SUCCESS) {
+        goto err_xp_funcs;
+      }
+
+    ok = xp_funcs.GetVolumePathName(
+        FileName,
+        volname,
+        sizeof volname
+      );
+    rc = GetLastError();
+    if (!ok) {
+        M_ERR("GetVolumePathName() failed!");
+        goto err_volname;
+      }
+
+    rc = NtfsSectGetVolumeInfo(volname, VolumeInfo);
+
+    err_volname:
+
+    NtfsSectUnloadXpFuncs(&xp_funcs);
+    err_xp_funcs:
+
+    return rc;
+  }
+
+/* Internal use only */
+static DWORD NtfsSectGetVolumePartitionLba(S_NTFSSECT_VOLINFO * VolumeInfo) {
+    BOOL ok;
+    VOLUME_DISK_EXTENTS vol_disk_extents;
+    DWORD output_size, rc;
+
+    ok = DeviceIoControl(
+        VolumeInfo->Handle,
+        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+        NULL,
+        0,
+        &vol_disk_extents,
+        sizeof vol_disk_extents,
+        &output_size,
+        NULL
+      );
+    rc = GetLastError();
+    if (!ok) {
+        M_ERR("Couldn't fetch volume disk extent(s)!");
+        goto err_vol_disk_extents;
+      }
+
+    if (vol_disk_extents.NumberOfDiskExtents != 1) {
+        M_ERR("Unsupported number of volume disk extents!");
+        goto err_num_of_extents;
+      }
+
+    VolumeInfo->PartitionLba.QuadPart = (
+        vol_disk_extents.Extents[0].StartingOffset.QuadPart /
+        VolumeInfo->BytesPerSector
+      );
+
+    return ERROR_SUCCESS;
+
+    err_num_of_extents:
+
+    err_vol_disk_extents:
+
+    return rc;
+  }
+
+DWORD M_NTFSSECT_API NtfsSectLcnToLba(
+    const S_NTFSSECT_VOLINFO * VolumeInfo,
+    const LARGE_INTEGER * Lcn,
+    LARGE_INTEGER * Lba
+  ) {
+    BOOL bad;
+    bad = (
+        !VolumeInfo ||
+        !VolumeInfo->BytesPerSector ||
+        !VolumeInfo->SectorsPerCluster ||
+        !Lcn ||
+        Lcn->QuadPart < 0 ||
+        !Lba
+      );
+    if (bad)
+      return ERROR_INVALID_PARAMETER;
+
+    Lba->QuadPart = (
+        VolumeInfo->PartitionLba.QuadPart +
+        Lcn->QuadPart *
+        VolumeInfo->SectorsPerCluster
+      );
+    return ERROR_SUCCESS;
+  }
+
+DWORD M_NTFSSECT_API NtfsSectLoadXpFuncs(S_NTFSSECT_XPFUNCS * XpFuncs) {
+    DWORD rc;
+
+    if (!XpFuncs)
+      return ERROR_INVALID_PARAMETER;
+
+    XpFuncs->Size = sizeof *XpFuncs;
+
+    XpFuncs->Kernel32 = LoadLibrary("kernel32.dll");
+    rc = GetLastError();
+    if (!XpFuncs->Kernel32) {
+        M_ERR("KERNEL32.DLL not found!");
+        goto err;
+      }
+
+    XpFuncs->GetVolumePathName = (F_KERNEL32_GETVOLUMEPATHNAME *) (
+        GetProcAddress(
+            XpFuncs->Kernel32,
+            "GetVolumePathNameA"
+          )
+      );
+    rc = GetLastError();
+    if (!XpFuncs->GetVolumePathName) {
+        M_ERR("GetVolumePathName() not found in KERNEL32.DLL!");
+        goto err;
+      }
+
+    XpFuncs->GetDiskFreeSpace = (F_KERNEL32_GETDISKFREESPACE *) (
+        GetProcAddress(
+            XpFuncs->Kernel32,
+            "GetDiskFreeSpaceA"
+          )
+      );
+    rc = GetLastError();
+    if (!XpFuncs->GetDiskFreeSpace) {
+        M_ERR("GetDiskFreeSpace() not found in KERNEL32.DLL!");
+        goto err;
+      }
+
+    return ERROR_SUCCESS;
+
+    err:
+    NtfsSectUnloadXpFuncs(XpFuncs);
+    return rc;
+  }
+
+VOID M_NTFSSECT_API NtfsSectUnloadXpFuncs(S_NTFSSECT_XPFUNCS * XpFuncs) {
+    if (!XpFuncs)
+      return;
+
+    XpFuncs->GetDiskFreeSpace = NULL;
+    XpFuncs->GetVolumePathName = NULL;
+    if (XpFuncs->Kernel32)
+      FreeLibrary(XpFuncs->Kernel32);
+    XpFuncs->Kernel32 = NULL;
+    XpFuncs->Size = 0;
+    return;
+  }
+
diff --git a/win/ntfssect.h b/win/ntfssect.h
new file mode 100644
index 0000000..246c26d
--- /dev/null
+++ b/win/ntfssect.h
@@ -0,0 +1,152 @@
+/* -------------------------------------------------------------------------- *
+ *
+ *   Copyright 2011 Shao Miller - All Rights Reserved
+ *
+ *   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, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+#ifndef M_NTFSSECT_H_
+
+/****
+ * ntfssect.h
+ *
+ * Fetch NTFS file cluster & sector information via Windows
+ *
+ * With special thanks to Mark Roddy for his article:
+ *   http://www.wd-3.com/archive/luserland.htm
+ */
+
+/*** Macros */
+#define M_NTFSSECT_H_
+#define M_NTFSSECT_API
+
+/*** Object types */
+
+/* An "extent;" a contiguous range of file data */
+typedef struct S_NTFSSECT_EXTENT_ S_NTFSSECT_EXTENT;
+
+/* Volume info relevant to file cluster & sector info */
+typedef struct S_NTFSSECT_VOLINFO_ S_NTFSSECT_VOLINFO;
+
+/* Stores function pointers to some Windows functions */
+typedef struct S_NTFSSECT_XPFUNCS_ S_NTFSSECT_XPFUNCS;
+
+/*** Function types */
+
+/* The function type for Kernel32.dll's GetDiskFreeSpace() */
+typedef BOOL WINAPI F_KERNEL32_GETDISKFREESPACE(
+    LPCTSTR,
+    LPDWORD,
+    LPDWORD,
+    LPDWORD,
+    LPDWORD
+  );
+
+/* The function type for Kernel32.dll's GetVolumePathName() */
+typedef BOOL WINAPI F_KERNEL32_GETVOLUMEPATHNAME(LPCTSTR, LPCTSTR, DWORD);
+
+/*** Function declarations */
+
+/**
+ * Fetch the extent containing a particular VCN
+ *
+ * @v File
+ * @v Vcn
+ * @v Extent
+ * @ret DWORD
+ */
+DWORD M_NTFSSECT_API NtfsSectGetFileVcnExtent(
+    HANDLE File,
+    LARGE_INTEGER * Vcn,
+    S_NTFSSECT_EXTENT * Extent
+  );
+
+/**
+ * Populate a volume info object
+ *
+ * @v VolumeName
+ * @v VolumeInfo
+ * @ret DWORD
+ */
+DWORD M_NTFSSECT_API NtfsSectGetVolumeInfo(
+    CHAR * VolumeName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  );
+
+/**
+ * Populate a volume info object
+ *
+ * @v FileName
+ * @v VolumeInfo
+ * @ret DWORD
+ */
+DWORD M_NTFSSECT_API NtfsSectGetVolumeInfoFromFileName(
+    CHAR * FileName,
+    S_NTFSSECT_VOLINFO * VolumeInfo
+  );
+
+/**
+ * Convert a volume LCN to an absolute disk LBA
+ *
+ * @v VolumeInfo
+ * @v Lcn
+ * @v Lba
+ * @ret DWORD
+ */
+DWORD M_NTFSSECT_API NtfsSectLcnToLba(
+    const S_NTFSSECT_VOLINFO * VolumeInfo,
+    const LARGE_INTEGER * Lcn,
+    LARGE_INTEGER * Lba
+  );
+
+/**
+ * Load some helper XP functions
+ *
+ * @v XpFuncs
+ * @ret DWORD
+ */
+DWORD M_NTFSSECT_API NtfsSectLoadXpFuncs(S_NTFSSECT_XPFUNCS * XpFuncs);
+
+/**
+ * Unload some helper XP functions
+ *
+ * @v XpFuncs
+ * @ret DWORD
+ */
+VOID M_NTFSSECT_API NtfsSectUnloadXpFuncs(S_NTFSSECT_XPFUNCS * XpFuncs);
+
+/*** Object declarations */
+
+/**
+ * The last error message set by one of our functions.
+ * Obviously not per-thread
+ */
+extern CHAR * NtfsSectLastErrorMessage;
+
+/*** Struct/union definitions */
+struct S_NTFSSECT_EXTENT_ {
+    LARGE_INTEGER FirstVcn;
+    LARGE_INTEGER NextVcn;
+    LARGE_INTEGER FirstLcn;
+  };
+
+struct S_NTFSSECT_VOLINFO_ {
+    DWORD Size;
+    HANDLE Handle;
+    DWORD BytesPerSector;
+    DWORD SectorsPerCluster;
+    LARGE_INTEGER PartitionLba;
+  };
+
+struct S_NTFSSECT_XPFUNCS_ {
+    DWORD Size;
+    HMODULE Kernel32;
+    F_KERNEL32_GETVOLUMEPATHNAME * GetVolumePathName;
+    F_KERNEL32_GETDISKFREESPACE * GetDiskFreeSpace;
+  };
+
+#endif /* M_NTFSSECT_H_ */
diff --git a/win/ntfstest.c b/win/ntfstest.c
new file mode 100644
index 0000000..1fc2718
--- /dev/null
+++ b/win/ntfstest.c
@@ -0,0 +1,163 @@
+/* -------------------------------------------------------------------------- *
+ *
+ *   Copyright 2011 Shao Miller - All Rights Reserved
+ *
+ *   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, Inc., 53 Temple Place Ste 330,
+ *   Boston MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ------------------------------------------------------------------------- */
+
+/****
+ * ntfstest.c
+ *
+ * (C) Shao Miller, 2011
+ *
+ * Tests ntfssect.c functions
+ *
+ * With special thanks to Mark Roddy for his article:
+ *   http://www.wd-3.com/archive/luserland.htm
+ */
+#include <windows.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ntfssect.h"
+
+/*** Object types */
+
+/*** Function declarations */
+static void show_usage(void);
+static void show_last_err(void);
+static void show_err(DWORD);
+
+/*** Struct/union definitions */
+
+/*** Function definitions */
+
+/** Program entry-point */
+int main(int argc, char ** argv) {
+    int rc;
+    DWORD err;
+    S_NTFSSECT_VOLINFO vol_info;
+    HANDLE file;
+    LARGE_INTEGER vcn, lba;
+    S_NTFSSECT_EXTENT extent;
+    LONGLONG len;
+    BOOL ok;
+
+    if (argc != 2) {
+        rc = EXIT_FAILURE;
+        show_usage();
+        goto err_args;
+      }
+
+    /* Get volume info */
+    err = NtfsSectGetVolumeInfoFromFileName(argv[1], &vol_info);
+    if (err != ERROR_SUCCESS) {
+        show_err(err);
+        goto err_vol_info;
+      }
+    printf(
+        "Volume has %d bytes per sector, %d sectors per cluster\n",
+        vol_info.BytesPerSector,
+        vol_info.SectorsPerCluster
+      );
+
+    /* Open the file for reading */
+    file = CreateFile(
+        argv[1],
+        GENERIC_READ,
+        FILE_SHARE_READ,
+        NULL,
+        OPEN_EXISTING,
+        0,
+        NULL
+      );
+    if (file == INVALID_HANDLE_VALUE) {
+        rc = EXIT_FAILURE;
+        show_last_err();
+        goto err_file;
+      }
+
+    /* For each extent */
+    for (
+        vcn.QuadPart = 0;
+        NtfsSectGetFileVcnExtent(file, &vcn, &extent) == ERROR_SUCCESS;
+        vcn = extent.NextVcn
+      ) {
+        len = extent.NextVcn.QuadPart - extent.FirstVcn.QuadPart;
+        printf("Extent @ VCN #%lld,", extent.FirstVcn.QuadPart);
+        printf(" %lld clusters long:\n", len);
+        printf("  VCN #%lld -", extent.FirstVcn.QuadPart);
+        printf(" #%lld\n", extent.FirstVcn.QuadPart + len - 1);
+        printf("  LCN #%lld -", extent.FirstLcn.QuadPart);
+        printf(" #%lld\n", extent.FirstLcn.QuadPart + len - 1);
+        err = NtfsSectLcnToLba(
+            &vol_info,
+            &extent.FirstLcn,
+            &lba
+          );
+        if (err == ERROR_SUCCESS) {
+            printf("  LBA #%lld -", lba.QuadPart);
+            printf(
+                " #%lld\n",
+                lba.QuadPart + len * vol_info.SectorsPerCluster
+              );
+          }
+        continue;
+      }
+
+    rc = EXIT_SUCCESS;
+
+    CloseHandle(file);
+    err_file:
+
+    CloseHandle(vol_info.Handle);
+    err_vol_info:
+
+    err_args:
+
+    return rc;
+  }
+
+/** Display usage */
+static void show_usage(void) {
+    static const char usage_text[] = "\
+  File sector info . . . . . . . . . . . . . . . . . . . . Shao Miller, 2011\n\
+\n\
+  Usage: NTFSTEST.EXE <filename>\n\
+\n\
+  Attempts to dump cluster and sector info for <filename>.\n";
+
+    printf(usage_text);
+    return;
+  }
+
+static void show_last_err(void) {
+    show_err(GetLastError());
+    return;
+  }
+
+/** Display an error */
+static void show_err(DWORD err_code) {
+    void * buf;
+
+    FormatMessage(
+        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+        NULL,
+        err_code,
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+        (LPTSTR) &buf,
+        0,
+        NULL
+      );
+    fprintf(stderr, "Error: %s\n", buf);
+    LocalFree(buf);
+    return;
+  }
+
diff --git a/win/ntfstest.rc b/win/ntfstest.rc
new file mode 100644
index 0000000..462d21f
--- /dev/null
+++ b/win/ntfstest.rc
@@ -0,0 +1,26 @@
+
+1 VERSIONINFO
+FILEVERSION 0,0,0,1
+PRODUCTVERSION 0,0,0,1
+FILEOS 0x40004
+FILETYPE 0x1
+  {
+    BLOCK "StringFileInfo"
+      {
+        BLOCK "040904B0"
+          {
+            VALUE "CompanyName", "Shao Miller"
+            VALUE "FileDescription", "NTFS File Sector Info"
+            VALUE "FileVersion", "0.0.0.1 (Aug-12-2011)"
+            VALUE "InternalName", "NTFSTest"
+            VALUE "LegalCopyright", "© 2011 Shao Miller. All rights reserved."
+            VALUE "OriginalFilename", "NTFSTEST.EXE"
+            VALUE "ProductName", "Utilities"
+            VALUE "ProductVersion", "0.0.0.1"
+          }
+      }
+  }
+
+#if 0
+1 ICON "ntfstest.ico"
+#endif
diff --git a/win/syslinux.c b/win/syslinux.c
index 4e4435e..13f25b6 100644
--- a/win/syslinux.c
+++ b/win/syslinux.c
@@ -27,6 +27,8 @@
 #include "setadv.h"
 #include "sysexits.h"
 #include "syslxopt.h"
+#include "syslxfs.h"
+#include "ntfssect.h"
 
 #ifdef __GNUC__
 # define noreturn void __attribute__((noreturn))
@@ -382,6 +384,38 @@ int main(int argc, char *argv[])
     ldlinux_sectors = (syslinux_ldlinux_len + 2 * ADV_SIZE + SECTOR_SIZE - 1)
 	>> SECTOR_SHIFT;
     sectors = calloc(ldlinux_sectors, sizeof *sectors);
+    if (fs_type == NTFS) {
+	DWORD err;
+	S_NTFSSECT_VOLINFO vol_info;
+	LARGE_INTEGER vcn, lba, len;
+	S_NTFSSECT_EXTENT extent;
+
+	err = NtfsSectGetVolumeInfo(drive_name + 4, &vol_info);
+	if (err != ERROR_SUCCESS) {
+	    error("Could not fetch NTFS volume info");
+	    exit(1);
+	}
+	secp = sectors;
+	nsectors = 0;
+	for (vcn.QuadPart = 0;
+	     NtfsSectGetFileVcnExtent(f_handle, &vcn, &extent) == ERROR_SUCCESS;
+	     vcn = extent.NextVcn) {
+	    err = NtfsSectLcnToLba(&vol_info, &extent.FirstLcn, &lba);
+	    if (err != ERROR_SUCCESS) {
+		error("Could not translate LDLINUX.SYS LCN to disk LBA");
+		exit(1);
+	    }
+	    lba.QuadPart -= vol_info.PartitionLba.QuadPart;
+	    len.QuadPart = ((extent.NextVcn.QuadPart -
+			     extent.FirstVcn.QuadPart) *
+			    vol_info.SectorsPerCluster);
+	    while (len.QuadPart--) {
+		*secp++ = lba.QuadPart++;
+		nsectors++;
+	    }
+	}
+	goto map_done;
+    }
     fs = libfat_open(libfat_readfile, (intptr_t) d_handle);
     ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
     secp = sectors;
@@ -393,6 +427,7 @@ int main(int argc, char *argv[])
 	s = libfat_nextsector(fs, s);
     }
     libfat_close(fs);
+map_done:
 
     /*
      * Patch ldlinux.sys and the boot sector
diff --git a/win32/Makefile b/win32/Makefile
index cdb18f2..f960998 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -47,7 +47,7 @@ WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
 
 .SUFFIXES: .c .obj .lib .exe .i .s .S
 
-SRCS     = ../win/syslinux.c
+SRCS     = ../win/syslinux.c ../win/ntfssect.c
 OBJS     = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
 LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/syslxmod.c \
diff --git a/win32/Makefile b/win32/ntfstest/Makefile
similarity index 68%
copy from win32/Makefile
copy to win32/ntfstest/Makefile
index cdb18f2..00e89cf 100644
--- a/win32/Makefile
+++ b/win32/ntfstest/Makefile
@@ -12,7 +12,7 @@
 ## -----------------------------------------------------------------------
 
 #
-# Makefile for SYSLINUX Win32
+# Makefile for Win32 NTFS file cluster test
 #
 # This is separated out mostly so we can have a different set of Makefile
 # variables.
@@ -29,42 +29,32 @@ else
 ifeq ($(findstring MINGW32,$(OSTYPE)),MINGW32)
 WINPREFIX  :=
 else
-WINPREFIX  := $(shell ./find-mingw32.sh gcc)
+WINPREFIX  := $(shell ../find-mingw32.sh gcc)
 endif
 WINCFLAGS  := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
 	      -D_FILE_OFFSET_BITS=64
 WINLDFLAGS := -Os -s
 endif
-WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
-	     -I../libinstaller/getopt
+WINCFLAGS += -I. -I../../win
 
 WINCC      := $(WINPREFIX)gcc
 WINAR	   := $(WINPREFIX)ar
 WINRANLIB  := $(WINPREFIX)ranlib
+WINDRES    := $(WINPREFIX)windres
 
 WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
-	-o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
+	-o hello.exe ../../win/hello.c >/dev/null 2>&1 ; echo $$?)
 
-.SUFFIXES: .c .obj .lib .exe .i .s .S
+.SUFFIXES: .c .obj .lib .exe .i .s .S .rc .res
 
-SRCS     = ../win/syslinux.c
+SRCS     = ../../win/ntfstest.c ../../win/ntfssect.c 
+RCS      = ../../win/ntfstest.rc 
 OBJS     = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
-LIBSRC   = ../libinstaller/fs.c \
-	   ../libinstaller/syslxmod.c \
-	   ../libinstaller/syslxopt.c \
-	   ../libinstaller/setadv.c \
-	   ../libinstaller/getopt/getopt_long.c \
-	   ../libinstaller/bootsect_bin.c \
-	   ../libinstaller/ldlinux_bin.c \
-	   ../libinstaller/mbr_bin.c \
-	   $(wildcard ../libfat/*.c)
-LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
+RESS     = $(patsubst %.rc,%.res,$(notdir $(RCS)))
 
-LIB	 = syslinux.lib
+VPATH = .:../../win
 
-VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
-
-TARGETS = syslinux.exe
+TARGETS = ntfstest.exe
 
 ifeq ($(WINCC_IS_GOOD),0)
 all: $(TARGETS)
@@ -81,14 +71,7 @@ clean: tidy
 spotless: clean
 	-rm -f *~ $(TARGETS)
 
-installer:
-
-$(LIB): $(LIBOBJS)
-	rm -f $@
-	$(WINAR) cq $@ $^
-	$(WINRANLIB) $@
-
-syslinux.exe: $(OBJS) $(LIB)
+ntfstest.exe: $(OBJS) $(RESS)
 	$(WINCC) $(WINLDFLAGS) -o $@ $^
 
 
@@ -98,5 +81,7 @@ syslinux.exe: $(OBJS) $(LIB)
 	$(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -E -o $@ $<
 %.s: %.c
 	$(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -S -o $@ $<
+%.res: %.rc
+	$(WINDRES) -O COFF $< $@
 
 -include .*.d *.tmp
diff --git a/win64/Makefile b/win64/Makefile
index 6853fb2..fe60793 100644
--- a/win64/Makefile
+++ b/win64/Makefile
@@ -37,7 +37,7 @@ WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
 
 .SUFFIXES: .c .obj .lib .exe .i .s .S
 
-SRCS     = ../win/syslinux.c
+SRCS     = ../win/syslinux.c ../win/ntfssect.c
 OBJS     = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
 LIBSRC   = ../libinstaller/fs.c \
 	   ../libinstaller/syslxmod.c \
diff --git a/win64/Makefile b/win64/ntfstest/Makefile
similarity index 64%
copy from win64/Makefile
copy to win64/ntfstest/Makefile
index 6853fb2..5b975be 100644
--- a/win64/Makefile
+++ b/win64/ntfstest/Makefile
@@ -12,7 +12,7 @@
 ## -----------------------------------------------------------------------
 
 #
-# Makefile for SYSLINUX Win64
+# Makefile for Win64 NTFS file cluster test
 #
 # This is separated out mostly so we can have a different set of Makefile
 # variables.
@@ -20,41 +20,30 @@
 
 OSTYPE   = $(shell uname -msr)
 # Don't know how to do a native compile here...
-WINPREFIX  := $(shell ./find-mingw64.sh gcc)
+WINPREFIX  := $(shell ../find-mingw64.sh gcc)
 WINCFLAGS  := $(GCCWARN) -Wno-sign-compare -Os -fomit-frame-pointer \
 	      -D_FILE_OFFSET_BITS=64
 WINLDFLAGS := -Os -s
-
-WINCFLAGS += -I. -I../win -I.. -I../libfat -I../libinstaller \
-	     -I../libinstaller/getopt
+WINCFLAGS += -I. -I../../win
 
 WINCC      := $(WINPREFIX)gcc
 WINAR	   := $(WINPREFIX)ar
 WINRANLIB  := $(WINPREFIX)ranlib
+WINDRES    := $(WINPREFIX)windres
 
 WINCC_IS_GOOD := $(shell $(WINCC) $(WINCFLAGS) $(WINLDFLAGS) \
-	-o hello.exe ../win/hello.c >/dev/null 2>&1 ; echo $$?)
+	-o hello.exe ../../win/hello.c >/dev/null 2>&1 ; echo $$?)
 
-.SUFFIXES: .c .obj .lib .exe .i .s .S
+.SUFFIXES: .c .obj .lib .exe .i .s .S .rc .res
 
-SRCS     = ../win/syslinux.c
+SRCS     = ../../win/ntfstest.c ../../win/ntfssect.c
+RCS      = ../../win/ntfstest.rc
 OBJS     = $(patsubst %.c,%.obj,$(notdir $(SRCS)))
-LIBSRC   = ../libinstaller/fs.c \
-	   ../libinstaller/syslxmod.c \
-	   ../libinstaller/syslxopt.c \
-	   ../libinstaller/setadv.c \
-	   ../libinstaller/getopt/getopt_long.c \
-	   ../libinstaller/bootsect_bin.c \
-	   ../libinstaller/ldlinux_bin.c \
-	   ../libinstaller/mbr_bin.c \
-	   $(wildcard ../libfat/*.c)
-LIBOBJS  = $(patsubst %.c,%.obj,$(notdir $(LIBSRC)))
-
-LIB	 = syslinux.lib
+RESS     = $(patsubst %.rc,%.res,$(notdir $(RCS)))
 
-VPATH = .:../win:../libfat:../libinstaller:../libinstaller/getopt
+VPATH = .:../../win
 
-TARGETS = syslinux64.exe
+TARGETS = ntfstest64.exe
 
 ifeq ($(WINCC_IS_GOOD),0)
 all: $(TARGETS)
@@ -71,14 +60,7 @@ clean: tidy
 spotless: clean
 	-rm -f *~ $(TARGETS)
 
-installer:
-
-$(LIB): $(LIBOBJS)
-	rm -f $@
-	$(WINAR) cq $@ $^
-	$(WINRANLIB) $@
-
-syslinux64.exe: $(OBJS) $(LIB)
+ntfstest64.exe: $(OBJS) $(RESS)
 	$(WINCC) $(WINLDFLAGS) -o $@ $^
 
 
@@ -88,5 +70,7 @@ syslinux64.exe: $(OBJS) $(LIB)
 	$(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -E -o $@ $<
 %.s: %.c
 	$(WINCC) $(UMAKEDEPS) $(WINCFLAGS) -S -o $@ $<
+%.res: %.rc
+	$(WINDRES) -O COFF $< $@
 
 -include .*.d *.tmp


More information about the Syslinux-commits mailing list