Index: bootcd/isolinux/syslinux-6.03/win/ntfssect.c
===================================================================
--- bootcd/isolinux/syslinux-6.03/win/ntfssect.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
+++ bootcd/isolinux/syslinux-6.03/win/ntfssect.c	(revision e16e8f2a41938d263af54a9fd6b4020d6c0d69fa)
@@ -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;
+  }
+
