aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShao Miller <sha0.miller@gmail.com>2012-11-08 20:19:06 -0500
committerShao Miller <sha0.miller@gmail.com>2012-11-09 16:01:03 -0500
commitb66e388c936ec2b13d512f6d418a5f9ebc1efafb (patch)
tree1c4f71f0608dc261ed427f3bb60e010c3fdb9cf1
parent7307d60063ee4303da4de45f9d984fdc8df92146 (diff)
downloadsyslinux-mdiskchk_win.tar.gz
syslinux-mdiskchk_win.tar.xz
syslinux-mdiskchk_win.zip
win: Add mdiskchk and pmem drivermdiskchk_win
The win/mdiskchk/ directory produces two components: - mdiskchk.exe - pmem.sys mdiskchk.exe will be the Windows counterpart for the DOS version mdiskchk.com. The purpose is to be able to scan low memory for instances of Syslinux' MEMDISK and report these instances' parameters to a user or batch file. Under Windows, we will use the pmem.sys driver to scan physical memory. If the driver is not installed, we will install it. Work-in-progress-by: Shao Miller <sha0.miller@gmail.com>
-rw-r--r--memdisk/compiler.h3
-rw-r--r--win/mdiskchk/BUILDING.txt20
-rw-r--r--win/mdiskchk/dirs4
-rw-r--r--win/mdiskchk/exe/mdiskchk.c317
-rw-r--r--win/mdiskchk/exe/mdiskchk.rc23
-rw-r--r--win/mdiskchk/exe/sources8
-rw-r--r--win/mdiskchk/exe/winstuff.c583
-rw-r--r--win/mdiskchk/inc/common.h57
-rw-r--r--win/mdiskchk/inc/pmem.h46
-rw-r--r--win/mdiskchk/inc/stdint.h7
-rw-r--r--win/mdiskchk/mdiskchk.dev205
-rw-r--r--win/mdiskchk/sys/pmem.c370
-rw-r--r--win/mdiskchk/sys/pmem.def7
-rw-r--r--win/mdiskchk/sys/pmem.rc21
-rw-r--r--win/mdiskchk/sys/sources9
-rw-r--r--win32/mdiskchk/exe/Makefile48
-rw-r--r--win32/mdiskchk/sys/Makefile63
-rw-r--r--win64/mdiskchk/exe/Makefile48
-rw-r--r--win64/mdiskchk/sys/Makefile63
19 files changed, 1902 insertions, 0 deletions
diff --git a/memdisk/compiler.h b/memdisk/compiler.h
index d1b03e06..a1bdb2bb 100644
--- a/memdisk/compiler.h
+++ b/memdisk/compiler.h
@@ -2,6 +2,9 @@
#ifdef __WATCOMC__
# define MEMDISK_PACKED_PREFIX _Packed
# define MEMDISK_PACKED_POSTFIX
+#elif defined(_MSC_VER)
+# define MEMDISK_PACKED_PREFIX
+# define MEMDISK_PACKED_POSTFIX
#else
/* Assume GNU C for now */
# define MEMDISK_PACKED_PREFIX
diff --git a/win/mdiskchk/BUILDING.txt b/win/mdiskchk/BUILDING.txt
new file mode 100644
index 00000000..d03dbccf
--- /dev/null
+++ b/win/mdiskchk/BUILDING.txt
@@ -0,0 +1,20 @@
+November 8th, 2012 - Shao Miller
+
+With Windows and its DDK:
+
+1. Open a build environment, such as with:
+ Start -> Programs -> Windows Driver Kits -> WDK 6001.18001 ->
+ Build Environments -> Windows 2000 ->
+ Launch Windows 2000 x86 Free Build Environment
+
+2. cd /d X:\path\without\spaces\syslinux\win\mdiskchk
+ Where X: is the appropriate drive letter
+
+3. Issue the 'build' command
+
+With Linux and MinGW:
+
+1. cd /path/to/syslinux/winZZ/mdiskchk
+ Where ZZ is 32 or 64
+
+2. Issue the 'make' command
diff --git a/win/mdiskchk/dirs b/win/mdiskchk/dirs
new file mode 100644
index 00000000..b41f9a3f
--- /dev/null
+++ b/win/mdiskchk/dirs
@@ -0,0 +1,4 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For DDK 'build'
+
+DIRS=sys exe
diff --git a/win/mdiskchk/exe/mdiskchk.c b/win/mdiskchk/exe/mdiskchk.c
new file mode 100644
index 00000000..95feec30
--- /dev/null
+++ b/win/mdiskchk/exe/mdiskchk.c
@@ -0,0 +1,317 @@
+/* ------------------------------------------------------------------------- *\
+ *
+ * Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
+ * Portions copyright 2010-2012 Shao Miller
+ *
+ * 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.
+ *
+\* ------------------------------------------------------------------------- */
+
+/*
+ * mdiskchk.c
+ *
+ * Windows program to check for the existence of MEMDISK instances
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+/* Object types */
+struct memdiskinfo;
+
+/* Functions types */
+typedef void f_output(const int, const struct memdiskinfo * const);
+typedef void f_action(void);
+
+/* Functions declarations */
+extern void *MK_FP(uint16_t seg, uint16_t off);
+extern void release_lowmem(void);
+extern int fetch_lowmem(void);
+
+static const char *bootloadername(uint8_t id);
+static f_output normal_output;
+static f_output batch_output;
+static f_action do_nothing;
+static f_action show_usage;
+static f_action show_mbfts;
+static f_action show_safe_hooks;
+
+/* Pull in MEMDISK common structures */
+#ifdef _MSC_VER
+# pragma pack(1)
+#endif
+#include "../../../memdisk/mstructs.h"
+#ifdef _MSC_VER
+# pragma pack()
+#endif
+
+/* Struct/union definitions */
+struct memdiskinfo {
+ struct mdi mdi;
+
+ /* We add our own fields at the end */
+ int cylinders;
+ int heads;
+ int sectors;
+};
+
+/* Objects */
+
+/* We do not output batch file output by default. We show MEMDISK info */
+static f_output *show_memdisk = normal_output;
+
+/* Functions definitions */
+
+/* Program entry-point. Returns the number of MEMDISK instances found */
+int __cdecl main(int argc, char **argv)
+{
+ int found = 0;
+
+ /* Default behaviour */
+ f_action *usage = do_nothing,
+ *safe_hooks = do_nothing,
+ *mbfts = do_nothing;
+
+ /* For each argument */
+ while (--argc) {
+ /* Argument should begin with one of these chars */
+ if ((*argv[argc] != '/') && (*argv[argc] != '-')) {
+ /* It doesn't. Print usage soon */
+ usage = show_usage;
+ break;
+ }
+ argv[argc]++;
+
+ /* Next char might be '-' as in "--safe-hooks" */
+ if (*argv[argc] == '-')
+ argv[argc]++;
+
+ switch (*argv[argc]) {
+ case 'S':
+ case 's':
+ safe_hooks = show_safe_hooks;
+ if (fetch_lowmem() != EXIT_SUCCESS)
+ return 0;
+ break;
+ case 'M':
+ case 'm':
+ mbfts = show_mbfts;
+ if (fetch_lowmem() != EXIT_SUCCESS)
+ return 0;
+ break;
+ case 'B':
+ case 'b':
+ show_memdisk = batch_output;
+ break;
+ default:
+ usage = show_usage;
+ } /* switch */
+ } /* while */
+
+ safe_hooks();
+ mbfts();
+ usage();
+
+ release_lowmem();
+ return found;
+}
+
+static const char *bootloadername(uint8_t id)
+{
+ static const struct {
+ uint8_t id, mask;
+ const char *name;
+ } *lp, list[] = {
+ {0x00, 0xf0, "LILO"},
+ {0x10, 0xf0, "LOADLIN"},
+ {0x31, 0xff, "SYSLINUX"},
+ {0x32, 0xff, "PXELINUX"},
+ {0x33, 0xff, "ISOLINUX"},
+ {0x34, 0xff, "EXTLINUX"},
+ {0x30, 0xf0, "SYSLINUX family"},
+ {0x40, 0xf0, "Etherboot"},
+ {0x50, 0xf0, "ELILO"},
+ {0x70, 0xf0, "GrUB"},
+ {0x80, 0xf0, "U-Boot"},
+ {0xA0, 0xf0, "Gujin"},
+ {0xB0, 0xf0, "Qemu"},
+ {0x00, 0x00, "unknown"}
+ };
+
+ for (lp = list;; lp++) {
+ if (((id ^ lp->id) & lp->mask) == 0)
+ return lp->name;
+ }
+}
+
+/* Show MEMDISK information for the passed structure */
+static void normal_output(const int d, const struct memdiskinfo * const m)
+{
+ if (m == NULL)
+ return;
+ printf("Drive %02X is MEMDISK %u.%02u:\n"
+ "\tAddress = 0x%08lx, len = %lu sectors, chs = %u/%u/%u,\n"
+ "\tloader = 0x%02x (%s),\n"
+ "\tcmdline = %s\n",
+ d, m->mdi.version_major, m->mdi.version_minor,
+ m->mdi.diskbuf, m->mdi.disksize, m->cylinders, m->heads, m->sectors,
+ m->mdi.bootloaderid, bootloadername(m->mdi.bootloaderid),
+ (const char *)MK_FP(m->mdi.cmdline.seg_off.segment,
+ m->mdi.cmdline.seg_off.offset));
+}
+
+/* Yield CMD.EXE SET command(s) as output for each MEMDISK kernel argument */
+static void batch_output(const int d, const struct memdiskinfo * const m)
+{
+ (void)d;
+ if (m != NULL) {
+ char buf[256], *bc;
+ const char *c =
+ MK_FP(m->mdi.cmdline.seg_off.segment,
+ m->mdi.cmdline.seg_off.offset);
+ const char *have_equals, is_set[] = "=1";
+
+ while (*c != '\0') {
+ /* Skip whitespace */
+ while (isspace(*c))
+ c++;
+ if (*c == '\0')
+ /* Trailing whitespace. That's enough processing */
+ break;
+ /*
+ * Walk the kernel arguments while filling the buffer,
+ * looking for space or NUL or checking for a full buffer
+ */
+ bc = buf;
+ have_equals = is_set;
+ while ((*c != '\0') && !isspace(*c) &&
+ (bc < &buf[sizeof buf - 1])) {
+ /* Check if the param is "x=y" */
+ if (*c == '=')
+ /* "=1" not needed */
+ have_equals = &is_set[sizeof is_set - 1];
+ *bc = *c;
+ c++;
+ bc++;
+ }
+ /* Found the end of the parameter and optional value sequence */
+ *bc = '\0';
+ printf("set %s%s\n", buf, have_equals);
+ }
+ }
+}
+
+static void do_nothing(void)
+{
+ return;
+}
+
+static void show_usage(void)
+{
+ printf("\nUsage: mdiskchk [--safe-hooks] [--mbfts] [--batch-output]\n"
+ "\n"
+ "Action: --safe-hooks . . Will scan INT 13h \"safe hook\" chain\n"
+ " --mbfts . . . . Will scan memory for MEMDISK mBFTs\n"
+ " --batch-output . Will output SET command output based\n"
+ " on MEMDISK kernel arguments\n");
+}
+
+/* Search memory for mBFTs and report them via the output method */
+static void show_mbfts(void)
+{
+ const uint16_t * const free_base_mem =
+ MK_FP(0x0040, 0x0013);
+ uint16_t seg;
+ uint8_t chksum;
+ uint32_t i;
+ const struct mBFT *mbft;
+ struct memdiskinfo m;
+ struct patch_area *patch_area;
+
+ for (seg = *free_base_mem / 16; seg < 0x9FFF; seg++) {
+ mbft = MK_FP(seg, 0);
+ /* Check for signature */
+ if (mbft->acpi.signature[0] != 'm' ||
+ mbft->acpi.signature[1] != 'B' ||
+ mbft->acpi.signature[2] != 'F' ||
+ mbft->acpi.signature[3] != 'T')
+ continue;
+ if (mbft->acpi.length != sizeof *mbft)
+ continue;
+ /* Check sum */
+ chksum = 0;
+ for (i = 0; i < sizeof *mbft; i++)
+ chksum += ((const uint8_t *)mbft)[i];
+ if (chksum)
+ continue;
+ /* Copy the MDI from the mBFT */
+ memcpy(&m, &mbft->mdi, sizeof mbft->mdi);
+ /*
+ * Adjust C/H/S since we actually know
+ * it directly for any MEMDISK with an mBFT
+ */
+ patch_area = (struct patch_area *)&mbft->mdi;
+ m.cylinders = patch_area->cylinders;
+ m.heads = patch_area->heads;
+ m.sectors = patch_area->sectors;
+ show_memdisk(patch_area->driveno, &m);
+ }
+}
+
+/*
+ * Walk the "safe hook" chain as far as possible
+ * and report MEMDISKs that we find via the output method
+ */
+static void show_safe_hooks(void)
+{
+ const real_addr_t * const int13 =
+ MK_FP(0x0000, 0x0013 * sizeof *int13);
+ const struct safe_hook *hook =
+ MK_FP(int13->seg_off.segment, int13->seg_off.offset);
+
+ while ((hook->signature[0] == '$') &&
+ (hook->signature[1] == 'I') &&
+ (hook->signature[2] == 'N') &&
+ (hook->signature[3] == 'T') &&
+ (hook->signature[4] == '1') &&
+ (hook->signature[5] == '3') &&
+ (hook->signature[6] == 'S') &&
+ (hook->signature[7] == 'F')) {
+ /* Found a valid "safe hook" */
+ if ((hook->vendor[0] == 'M') &&
+ (hook->vendor[1] == 'E') &&
+ (hook->vendor[2] == 'M') &&
+ (hook->vendor[3] == 'D') &&
+ (hook->vendor[4] == 'I') &&
+ (hook->vendor[5] == 'S') &&
+ (hook->vendor[6] == 'K')) {
+ /* Found a valid MEMDISK "safe hook". It will have an mBFT */
+ const struct mBFT *mbft;
+ struct memdiskinfo m;
+ struct patch_area *patch_area;
+
+ /* Copy the MDI from the mBFT. Offset is a misnomer here */
+ mbft = MK_FP((uint16_t)(hook->mbft >> 4), 0); /* Always aligned */
+ memcpy(&m, &mbft->mdi, sizeof mbft->mdi);
+ /*
+ * Adjust C/H/S since we actually know
+ * it directly for any MEMDISK with an mBFT
+ */
+ patch_area = (struct patch_area *)&mbft->mdi;
+ m.cylinders = patch_area->cylinders;
+ m.heads = patch_area->heads;
+ m.sectors = patch_area->sectors;
+ show_memdisk(patch_area->driveno, &m);
+ } /* if */
+ /* Step to the next hook in the "safe hook" chain */
+ hook = MK_FP(hook->old_hook.seg_off.segment,
+ hook->old_hook.seg_off.offset);
+ } /* while */
+}
diff --git a/win/mdiskchk/exe/mdiskchk.rc b/win/mdiskchk/exe/mdiskchk.rc
new file mode 100644
index 00000000..79500c1d
--- /dev/null
+++ b/win/mdiskchk/exe/mdiskchk.rc
@@ -0,0 +1,23 @@
+1 VERSIONINFO
+FILEVERSION 0,0,0,1
+PRODUCTVERSION 0,0,0,1
+FILEOS 0x40004
+FILETYPE 0x3 {
+ BLOCK "StringFileInfo" {
+ BLOCK "000004B0" {
+ VALUE "CompanyName", "Shao Miller"
+ VALUE "FileDescription", "MDiskChk Utility"
+ VALUE "FileVersion", "0.0.0.1 (June-13-2012)"
+ VALUE "InternalName", "MDiskChk Utility"
+ VALUE "LegalCopyright", " 2012 Shao Miller, All rights reserved, Licensed under GPL."
+ VALUE "OriginalFilename", "mdiskchk.exe"
+ VALUE "ProductName", "MDiskChk Utility"
+ VALUE "ProductVersion", "0.0.0.1"
+ }
+ }
+ BLOCK "VarFileInfo" {
+ VALUE "Translation", 0x0000, 0x04B0
+ }
+ }
+
+1 RCDATA "PMem.Sys"
diff --git a/win/mdiskchk/exe/sources b/win/mdiskchk/exe/sources
new file mode 100644
index 00000000..55924fc4
--- /dev/null
+++ b/win/mdiskchk/exe/sources
@@ -0,0 +1,8 @@
+TARGETNAME=mdiskchk
+INCLUDES=..\inc
+TARGETTYPE=PROGRAM
+UMTYPE=console
+UMENTRY=main
+USE_MSVCRT=1
+TARGETPATH=obj
+SOURCES=mdiskchk.c winstuff.c mdiskchk.rc
diff --git a/win/mdiskchk/exe/winstuff.c b/win/mdiskchk/exe/winstuff.c
new file mode 100644
index 00000000..50ee03ab
--- /dev/null
+++ b/win/mdiskchk/exe/winstuff.c
@@ -0,0 +1,583 @@
+/* ------------------------------------------------------------------------- *\
+ *
+ * Copyright 2010-2012 Shao Miller
+ *
+ * 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.
+ *
+\* ------------------------------------------------------------------------- */
+
+/****
+ * @file
+ *
+ * Fetch low memory using the PMem driver
+ */
+
+#include <windows.h>
+#include <winioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+
+#include "common.h"
+#include "pmem.h"
+
+/*** Macros */
+#undef TextMode_
+#define TextMode_ L
+
+#define CvMdcKibibyte 1024
+#define CvMdcMebibyte (1024 * CvMdcKibibyte)
+
+/*** Object types */
+
+/*** Function types */
+
+/*** Function declarations */
+static INT MdcShowLastError(void);
+static UCHAR * MdcEmbeddedDriver(DWORD * Size);
+static INT MdcCopyDriver(void);
+static INT MdcModeInstall(void);
+static INT MdcModeRemove(void);
+static INT MdcModeStart(void);
+static INT MdcModeStop(void);
+static INT MdcGetDeviceHandle(void);
+
+/*** Struct/union definitions */
+
+/*** Object definitions */
+static WCHAR MdcDriverFilename[] =
+ L"C:\\Windows\\System32\\Drivers\\" PmemDriverName L".Sys";
+
+/* The PMem driver's device */
+static HANDLE MdcDeviceHandle = INVALID_HANDLE_VALUE;
+
+/* Low memory */
+static UCHAR * MdcLowMemory;
+
+/*** Function definitions */
+
+VOID * MK_FP(UINT16 seg, UINT16 off) {
+ /* Note that there's no assertion of MdcLowMemory */
+ return MdcLowMemory + (((UINT32) seg) << 4) + off;
+ }
+
+VOID release_lowmem(void) {
+ /* Release the low memory copy */
+ if (MdcLowMemory) {
+ free(MdcLowMemory);
+ MdcLowMemory = NULL;
+ }
+
+ return;
+ }
+
+INT fetch_lowmem(void) {
+ INT rc;
+ BOOL ok;
+ DWORD bytes_read;
+
+ /* Already done? */
+ if (MdcLowMemory)
+ return EXIT_SUCCESS;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Allocate for a copy of low memory (1 MiB) */
+ MdcLowMemory = malloc(CvMdcMebibyte);
+ if (!MdcLowMemory) {
+ fprintf(stderr, "Couldn't allocate copy of low memory!\n");
+ goto err_low_mem;
+ }
+
+ if (MdcGetDeviceHandle() != EXIT_SUCCESS)
+ goto err_dev_handle;
+
+ ok = ReadFile(
+ MdcDeviceHandle,
+ MdcLowMemory,
+ CvMdcMebibyte,
+ &bytes_read,
+ NULL
+ );
+ if (!ok || bytes_read != CvMdcMebibyte) {
+ fprintf(stderr, "Couldn't copy low memory!\n");
+ goto err_read;
+ }
+
+ rc = EXIT_SUCCESS;
+
+ err_read:
+
+ CloseHandle(MdcDeviceHandle);
+ MdcDeviceHandle = INVALID_HANDLE_VALUE;
+
+ /* Stop the driver */
+ MdcModeStop();
+
+ /* Remove the driver */
+ MdcModeRemove();
+
+ err_dev_handle:
+
+ if (rc != EXIT_SUCCESS)
+ release_lowmem();
+ err_low_mem:
+
+ return rc;
+ }
+
+/* Display the last-set error code */
+static INT MdcShowLastError(void) {
+ DWORD err_code;
+ CHAR * buf = NULL;
+
+ err_code = GetLastError();
+ FormatMessageW(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ err_code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR) &buf,
+ 0,
+ NULL
+ );
+ if (buf) {
+ fprintf(stderr, "GetLastError():\n %s", buf);
+ LocalFree(buf);
+ }
+ return err_code;
+ }
+
+static UCHAR * MdcEmbeddedDriver(DWORD * size) {
+ HRSRC res_info;
+ HGLOBAL res_handle;
+ UCHAR * driver;
+
+ /* Assume failure */
+ driver = NULL;
+
+ /*
+ * Get a handle to the resource information
+ * block for the embedded driver
+ */
+ res_info = FindResource(
+ /* Current module */
+ NULL,
+ /* The resource ID */
+ MAKEINTRESOURCE(1),
+ /* The resource type */
+ RT_RCDATA
+ );
+ if (!res_info) {
+ fprintf(stderr, "Couldn't find embedded driver!\n");
+ MdcShowLastError();
+ goto err_res_info;
+ }
+
+ /* Get a handle to the embedded driver resource */
+ res_handle = LoadResource(NULL, res_info);
+ if (!res_handle) {
+ fprintf(stderr, "Couldn't load embedded driver!\n");
+ MdcShowLastError();
+ goto err_res_handle;
+ }
+
+ /* Get a pointer to the embedded driver resource */
+ driver = LockResource(res_handle);
+ if (!driver) {
+ fprintf(stderr, "Couldn't use embedded driver!\n");
+ MdcShowLastError();
+ goto err_driver;
+ }
+
+ /* Fetch the size */
+ *size = SizeofResource(NULL, res_info);
+
+ /* Success */
+
+ err_driver:
+
+ err_res_handle:
+
+ err_res_info:
+
+ return driver;
+ }
+
+static INT MdcCopyDriver(void) {
+ INT rc;
+ HANDLE driver_file;
+ UCHAR * driver;
+ DWORD size;
+ BOOL ok;
+ DWORD bytes_written;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Try to create the driver file */
+ driver_file = CreateFileW(
+ MdcDriverFilename,
+ GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ NULL,
+ CREATE_ALWAYS,
+ 0,
+ NULL
+ );
+ if (driver_file == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Couldn't open driver file for writing!\n");
+ MdcShowLastError();
+ goto err_driver_file;
+ }
+
+ /* Get a pointer to the embedded driver resource */
+ driver = MdcEmbeddedDriver(&size);
+ if (!driver)
+ goto err_driver;
+
+ /* Write the file */
+ ok = WriteFile(driver_file, driver, size, &bytes_written, NULL);
+ if (!ok) {
+ fprintf(stderr, "Couldn't write driver file!\n");
+ MdcShowLastError();
+ goto err_write;
+ }
+
+ /* Success */
+ rc = EXIT_SUCCESS;
+
+ err_write:
+
+ CloseHandle(driver_file);
+ err_driver_file:
+
+ err_driver:
+
+ return rc;
+ }
+
+static INT MdcModeInstall(void) {
+ INT rc;
+ SC_HANDLE scm;
+ SC_HANDLE svc;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Write the driver file */
+ rc = MdcCopyDriver();
+ if (rc != EXIT_SUCCESS) {
+ goto err_copy_driver;
+ }
+
+ /* Get a handle to the Service Control Manager */
+ scm = OpenSCManagerW(
+ NULL,
+ NULL,
+ SC_MANAGER_CREATE_SERVICE
+ );
+ if (!scm) {
+ fprintf(stderr, "Couldn't connect to service control manager!\n");
+ MdcShowLastError();
+ goto err_scm;
+ }
+
+ /* Register the driver with the service control manager */
+ svc = CreateServiceW(
+ /* Service Control Manager handle */
+ scm,
+ /* Name */
+ PmemDriverName,
+ /* Display name */
+ PmemDriverName,
+ /* Access */
+ SERVICE_ALL_ACCESS,
+ /* Type */
+ SERVICE_KERNEL_DRIVER,
+ /* Start type */
+ SERVICE_DEMAND_START,
+ /* Error control */
+ SERVICE_ERROR_NORMAL,
+ /* Binary path */
+ MdcDriverFilename,
+ /* Load order group: None */
+ NULL,
+ /* Load order group tag: Don't care */
+ NULL,
+ /* Dependencies: None */
+ NULL,
+ /* Account name: SYSTEM */
+ NULL,
+ /* Account password: Not specified for SYSTEM */
+ NULL
+ );
+ if (!svc) {
+ fprintf(stderr, "Couldn't install driver!\n");
+ MdcShowLastError();
+ goto err_svc;
+ }
+
+ /* Success */
+ fprintf(stderr, "Driver installed\n");
+ rc = EXIT_SUCCESS;
+
+ CloseServiceHandle(svc);
+ err_svc:
+
+ CloseServiceHandle(scm);
+ err_scm:
+
+ err_copy_driver:
+
+ return rc;
+ }
+
+static INT MdcModeRemove(void) {
+ INT rc;
+ SC_HANDLE scm;
+ SC_HANDLE svc;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Get a handle to the Service Control Manager */
+ scm = OpenSCManagerW(
+ NULL,
+ NULL,
+ SC_MANAGER_CREATE_SERVICE
+ );
+ if (!scm) {
+ fprintf(stderr, "Couldn't connect to service control manager!\n");
+ MdcShowLastError();
+ goto err_scm;
+ }
+
+ /* Open the driver service for removal */
+ svc = OpenServiceW(
+ /* Service Control Manager handle */
+ scm,
+ /* Name */
+ PmemDriverName,
+ /* Access */
+ DELETE
+ );
+ if (!svc) {
+ fprintf(stderr, "Couldn't open driver service for removal!\n");
+ MdcShowLastError();
+ goto err_svc;
+ }
+
+ /* De-register the driver service with the service control manager */
+ if (!DeleteService(svc)) {
+ fprintf(stderr, "Couldn't remove driver!\n");
+ MdcShowLastError();
+ goto err_delete_svc;
+ }
+
+ if (!DeleteFileW(MdcDriverFilename)) {
+ fprintf(stderr, "Couldn't delete driver!\n");
+ MdcShowLastError();
+ goto err_delete_file;
+ }
+
+ /* Success */
+ fprintf(stderr, "Driver removed\n");
+ rc = EXIT_SUCCESS;
+
+ err_delete_file:
+
+ err_delete_svc:
+
+ CloseServiceHandle(svc);
+ err_svc:
+
+ CloseServiceHandle(scm);
+ err_scm:
+
+ return rc;
+ }
+
+static INT MdcModeStart(void) {
+ INT rc;
+ SC_HANDLE scm;
+ SC_HANDLE svc;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Get a handle to the Service Control Manager */
+ scm = OpenSCManagerW(
+ NULL,
+ NULL,
+ SC_MANAGER_CREATE_SERVICE
+ );
+ if (!scm) {
+ fprintf(stderr, "Couldn't connect to service control manager!\n");
+ MdcShowLastError();
+ goto err_scm;
+ }
+
+ /* Open the driver service for starting */
+ svc = OpenServiceW(
+ /* Service Control Manager handle */
+ scm,
+ /* Name */
+ PmemDriverName,
+ /* Access */
+ SERVICE_START
+ );
+ if (!svc) {
+ /* Try to install the service */
+ rc = MdcModeInstall();
+ if (rc == EXIT_FAILURE)
+ goto inner_err_svc;
+
+ /* Try again */
+ svc = OpenServiceW(
+ /* Service Control Manager handle */
+ scm,
+ /* Name */
+ PmemDriverName,
+ /* Access */
+ SERVICE_START
+ );
+ if (!svc) {
+ inner_err_svc:
+ fprintf(stderr, "Couldn't open driver service for starting!\n");
+ MdcShowLastError();
+ goto err_svc;
+ }
+ }
+
+ /* Send start signal */
+ if (!StartService(svc, 0, NULL)) {
+ fprintf(stderr, "Couldn't start driver!\n");
+ MdcShowLastError();
+ goto err_start;
+ }
+
+ /* Success */
+ fprintf(stderr, "Driver start signal sent\n");
+ rc = EXIT_SUCCESS;
+
+ err_start:
+
+ CloseServiceHandle(svc);
+ err_svc:
+
+ CloseServiceHandle(scm);
+ err_scm:
+
+ return rc;
+ }
+
+static INT MdcModeStop(void) {
+ INT rc;
+ SC_HANDLE scm;
+ SC_HANDLE svc;
+ SERVICE_STATUS status;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Get a handle to the Service Control Manager */
+ scm = OpenSCManagerW(
+ NULL,
+ NULL,
+ SC_MANAGER_CREATE_SERVICE
+ );
+ if (!scm) {
+ fprintf(stderr, "Couldn't connect to service control manager!\n");
+ MdcShowLastError();
+ goto err_scm;
+ }
+
+ /* Open the driver service for stopping */
+ svc = OpenServiceW(
+ /* Service Control Manager handle */
+ scm,
+ /* Name */
+ PmemDriverName,
+ /* Access */
+ SERVICE_STOP
+ );
+ if (!svc) {
+ fprintf(stderr, "Couldn't open driver service for stopping!\n");
+ MdcShowLastError();
+ goto err_svc;
+ }
+
+ /* Send stop signal */
+ if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
+ fprintf(stderr, "Couldn't start driver!\n");
+ MdcShowLastError();
+ goto err_stop;
+ }
+
+ /* Success */
+ fprintf(stderr, "Driver stop signal sent\n");
+ rc = EXIT_SUCCESS;
+
+ err_stop:
+
+ CloseServiceHandle(svc);
+ err_svc:
+
+ CloseServiceHandle(scm);
+ err_scm:
+
+ return rc;
+ }
+
+static INT MdcGetDeviceHandle(void) {
+ INT rc;
+
+ /* Assume failure */
+ rc = EXIT_FAILURE;
+
+ /* Try to open a handle to the PMem driver's device */
+ MdcDeviceHandle = CreateFileW(
+ PmemFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+ if (MdcDeviceHandle == INVALID_HANDLE_VALUE) {
+ /* Try to start the service */
+ rc = MdcModeStart();
+ if (rc != EXIT_SUCCESS)
+ goto err_dev_handle;
+
+ /* Try again */
+ MdcDeviceHandle = CreateFileW(
+ PmemFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL
+ );
+ if (MdcDeviceHandle == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Unable to open device!\n");
+ rc = MdcShowLastError();
+ goto err_dev_handle;
+ }
+ }
+
+ /* Success */
+ rc = EXIT_SUCCESS;
+
+ err_dev_handle:
+
+ return rc;
+ }
diff --git a/win/mdiskchk/inc/common.h b/win/mdiskchk/inc/common.h
new file mode 100644
index 00000000..715b748c
--- /dev/null
+++ b/win/mdiskchk/inc/common.h
@@ -0,0 +1,57 @@
+/* ------------------------------------------------------------------------- *\
+ *
+ * Copyright (C) 2012, Shao Miller <sha0.miller@gmail.com>.
+ *
+ * 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_COMMON_H_
+
+/****
+ * @file
+ *
+ * Commonly-used stuff
+ */
+
+/*** Macros */
+#define M_COMMON_H_
+
+/* Handy for arrays */
+#define Countof(array) (sizeof (array) / sizeof *(array))
+
+/* Unused parameters */
+#define Unused_(param) (void)(param)
+
+/* char versus wide char */
+#ifndef TextMode_
+# define TextMode_
+#endif
+#define Text___(text_mode, text) text_mode ## text
+#define Text__(text_mode, text) Text___(text_mode, text)
+#define Text_(text) Text__(TextMode_, text)
+
+/* I forget why this is here; copied and pasted from my Unfilter driver */
+#ifndef INVALID_HANDLE_VALUE
+# define INVALID_HANDLE_VALUE NULL
+#endif
+
+/* IN and OUT specifiers might or might not be present */
+#ifndef IN
+# define IN
+#endif
+#ifndef OUT
+# define OUT
+#endif
+
+/* Driver dispatch-type macros */
+#if 0
+# define DriverDispatchType_(type) __drv_dispatchType(type)
+#else
+# define DriverDispatchType_(type)
+#endif
+
+#endif /* M_COMMON_H_ */
diff --git a/win/mdiskchk/inc/pmem.h b/win/mdiskchk/inc/pmem.h
new file mode 100644
index 00000000..62105819
--- /dev/null
+++ b/win/mdiskchk/inc/pmem.h
@@ -0,0 +1,46 @@
+/* ------------------------------------------------------------------------- *\
+ *
+ * Copyright (C) 2010-2012, Shao Miller <sha0.miller@gmail.com>.
+ *
+ * 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_PMEM_H_
+
+/****
+ * @file
+ *
+ * Provide file-access to physical memory
+ */
+
+/*** Macros */
+#define M_PMEM_H_
+
+/* The driver name */
+#define PmemDriverName Text_("Pmem")
+
+/* Our device object's names */
+#define PmemDeviceName Text_("\\Device\\") PmemDriverName
+#define PmemDosDeviceName Text_("\\DosDevices\\") PmemDriverName
+#define PmemFileName Text_("\\\\.\\") PmemDriverName
+
+/* Device IO controls */
+#define CvPmemIoctlBase 0x8000
+
+/* Perform a scan */
+#define CvPmemIoctlFoo CTL_CODE( \
+ CvPmemIoctlBase, \
+ 0x800, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS | FILE_WRITE_ACCESS \
+ )
+
+/*** Object types */
+
+/*** Struct/union definitions */
+
+#endif /* M_PMEM_H_ */
diff --git a/win/mdiskchk/inc/stdint.h b/win/mdiskchk/inc/stdint.h
new file mode 100644
index 00000000..314eb937
--- /dev/null
+++ b/win/mdiskchk/inc/stdint.h
@@ -0,0 +1,7 @@
+#ifndef M_STDINT_H_
+#define M_STDINT_H_
+typedef unsigned long long uint64_t;
+typedef unsigned long uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+#endif /* M_STDINT_H_ */
diff --git a/win/mdiskchk/mdiskchk.dev b/win/mdiskchk/mdiskchk.dev
new file mode 100644
index 00000000..0a869930
--- /dev/null
+++ b/win/mdiskchk/mdiskchk.dev
@@ -0,0 +1,205 @@
+[Project]
+FileName=mdiskchk.dev
+Name=MDiskChk
+UnitCount=11
+PchHead=-1
+PchSource=-1
+Ver=3
+IsCpp=1
+ProfilesCount=2
+ProfileIndex=0
+Folders=exe,inc,sys
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNrOnRebuild=0
+AutoIncBuildNrOnCompile=0
+
+[Profile1]
+ProfileName=Mingw gcc 3.4.5
+Type=1
+ObjFiles=
+Includes=
+Libs=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=
+PreprocDefines=
+CompilerSettings=0000000000000000000000
+Icon=
+ExeOutput=Output\MingW
+ObjectOutput=Objects\MingW
+OverrideOutput=0
+OverrideOutputName=mdiskchk.exe
+HostApplication=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerType=0
+
+[Profile2]
+ProfileName=MS VC++ 2005
+Type=1
+ObjFiles=
+Includes=
+Libs=
+ResourceIncludes=
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=
+PreprocDefines=
+CompilerSettings=000000000000010000000000000000000000
+Icon=
+ExeOutput=Output\MSVC++2005
+ObjectOutput=Objects\MSVC++2005
+OverrideOutput=0
+OverrideOutputName=
+HostApplication=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=1
+CompilerType=1
+
+[Unit5]
+FileName=sys\pmem.c
+CompileCpp=1
+Folder=sys
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit1]
+FileName=sys\sources
+Folder=sys
+Compile=0
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=exe\sources
+Folder=exe
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=0
+
+[Unit4]
+FileName=exe\mdiskchk.rc
+Folder=exe
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=sys\pmem.def
+CompileCpp=1
+Folder=sys
+Compile=0
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=sys\pmem.rc
+Folder=sys
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit8]
+FileName=inc\pmem.h
+Folder=inc
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=1
+
+[Unit9]
+FileName=inc\common.h
+CompileCpp=1
+Folder=inc
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=dirs
+CompileCpp=1
+Folder=
+Compile=0
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=exe\winstuff.c
+Folder=exe
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=1
+
+[Unit13]
+FileName=sys\Makefile.hpa
+
+[Unit12]
+FileName=exe\winstuff.c
+Folder=exe
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+CompileCpp=1
+
+[Unit2]
+FileName=exe\mdiskchk.c
+CompileCpp=0
+Folder=exe
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/win/mdiskchk/sys/pmem.c b/win/mdiskchk/sys/pmem.c
new file mode 100644
index 00000000..a7fe820a
--- /dev/null
+++ b/win/mdiskchk/sys/pmem.c
@@ -0,0 +1,370 @@
+/* ------------------------------------------------------------------------- *\
+ *
+ * Copyright (C) 2010-2012, Shao Miller <sha0.miller@gmail.com>.
+ *
+ * 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.
+ *
+\* ------------------------------------------------------------------------- */
+
+/****
+ * @file
+ *
+ * Provide file-access to physical memory
+ */
+
+#include <ntddk.h>
+
+#include "common.h"
+#include "pmem.h"
+
+/*** Macros */
+#undef TextMode_
+#define TextMode_ L
+
+/*** Constants */
+
+/*** Object types */
+
+/*** Function declarations */
+DRIVER_INITIALIZE DriverEntry;
+static DRIVER_DISPATCH PmemIrpNotSupported;
+static
+ DriverDispatchType_(IRP_MJ_CREATE)
+ DriverDispatchType_(IRP_MJ_CLOSE)
+ DRIVER_DISPATCH
+ PmemIrpCreateClose;
+static
+ DriverDispatchType_(IRP_MJ_READ)
+ DRIVER_DISPATCH
+ PmemIrpRead;
+static
+ DriverDispatchType_(IRP_MJ_QUERY_INFORMATION)
+ DriverDispatchType_(IRP_MJ_SET_INFORMATION)
+ DRIVER_DISPATCH
+ PmemIrpQuerySetInformation;
+static
+ DriverDispatchType_(IRP_MJ_DEVICE_CONTROL)
+ DRIVER_DISPATCH
+ PmemIrpDeviceControl;
+static
+ DriverDispatchType_(IRP_MJ_CLEANUP)
+ DRIVER_DISPATCH
+ PmemIrpCleanup;
+static DRIVER_UNLOAD PmemUnload;
+
+/*** Struct/union definitions */
+
+/*** Object definitions */
+
+/* Our device object's names */
+static UNICODE_STRING PmemDeviceNameUnicodeString;
+static UNICODE_STRING PmemDosDeviceNameUnicodeString;
+
+/* Our driver and device objects */
+static DRIVER_OBJECT * PmemDriverObject;
+static DEVICE_OBJECT * PmemDeviceObject;
+
+/* Our open handle count */
+static volatile LONG PmemHandleCount;
+
+/* Current position in physical memory */
+static PHYSICAL_ADDRESS PmemPosition;
+
+/*** Function definitions */
+
+/* The driver entry-point */
+NTSTATUS NTAPI DriverEntry(
+ IN DRIVER_OBJECT * drv_obj,
+ IN UNICODE_STRING * reg_path
+ ) {
+ UCHAR i;
+ NTSTATUS status;
+
+ Unused_(reg_path);
+
+ /* Initialize our device object's names */
+ RtlInitUnicodeString(&PmemDeviceNameUnicodeString, PmemDeviceName);
+ RtlInitUnicodeString(&PmemDosDeviceNameUnicodeString, PmemDosDeviceName);
+
+ /* Set driver entry-points */
+ ASSERT(drv_obj);
+ PmemDriverObject = drv_obj;
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
+ drv_obj->MajorFunction[i] = PmemIrpNotSupported;
+
+ drv_obj->MajorFunction[IRP_MJ_CREATE] = PmemIrpCreateClose;
+ drv_obj->MajorFunction[IRP_MJ_CLOSE] = PmemIrpCreateClose;
+ drv_obj->MajorFunction[IRP_MJ_READ] = PmemIrpRead;
+ drv_obj->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
+ PmemIrpQuerySetInformation;
+ drv_obj->MajorFunction[IRP_MJ_SET_INFORMATION] =
+ PmemIrpQuerySetInformation;
+ drv_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PmemIrpDeviceControl;
+ drv_obj->MajorFunction[IRP_MJ_CLEANUP] = PmemIrpCleanup;
+
+ drv_obj->DriverUnload = PmemUnload;
+ /*
+ * Since we're not a PnP driver, we don't set
+ * PmemDriverObject->DriverExtension->AddDevice
+ */
+
+ /* Create our device */
+ status = IoCreateDevice(
+ PmemDriverObject,
+ 0,
+ &PmemDeviceNameUnicodeString,
+ FILE_DEVICE_CONTROLLER,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &PmemDeviceObject
+ );
+ if (!NT_SUCCESS(status))
+ goto err_dev_obj;
+
+ /* This driver is not intended to be high-performance */
+ PmemDeviceObject->Flags |= DO_BUFFERED_IO;
+
+ /* Establish the symbolic link */
+ status = IoCreateSymbolicLink(
+ &PmemDosDeviceNameUnicodeString,
+ &PmemDeviceNameUnicodeString
+ );
+ if (!NT_SUCCESS(status))
+ goto err_symlink;
+
+ return STATUS_SUCCESS;
+
+ /* Delete the symbolic link */
+ IoDeleteSymbolicLink(&PmemDosDeviceNameUnicodeString);
+ err_symlink:
+
+ /* Destroy our device */
+ IoDeleteDevice(PmemDeviceObject);
+ err_dev_obj:
+
+ return status;
+ }
+
+/* When the driver unloads */
+static VOID NTAPI PmemUnload(IN DRIVER_OBJECT * drv_obj) {
+ Unused_(drv_obj);
+
+ /* Delete the symbolic link */
+ IoDeleteSymbolicLink(&PmemDosDeviceNameUnicodeString);
+
+ /* We shouldn't have any open handles */
+ ASSERT(!PmemHandleCount);
+
+ /* Destroy our device */
+ ASSERT(PmemDeviceObject);
+ IoDeleteDevice(PmemDeviceObject);
+
+ return;
+ }
+
+/* When we don't support an IRP */
+static NTSTATUS NTAPI PmemIrpNotSupported(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ Unused_(dev_obj);
+
+ ASSERT(irp);
+ irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_NOT_SUPPORTED;
+ }
+
+/* When our device is opened or closed */
+static NTSTATUS NTAPI PmemIrpCreateClose(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ IO_STACK_LOCATION * io_stack_loc;
+ LONG handle_count;
+
+ Unused_(dev_obj);
+
+ ASSERT(irp);
+ io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+ ASSERT(io_stack_loc);
+ if (io_stack_loc->MajorFunction == IRP_MJ_CREATE) {
+ /* We only allow a single open handle */
+ handle_count = InterlockedIncrement(&PmemHandleCount);
+ if (handle_count > 1) {
+ InterlockedDecrement(&PmemHandleCount);
+ irp->IoStatus.Status = STATUS_TOO_MANY_OPENED_FILES;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_TOO_MANY_OPENED_FILES;
+ }
+
+ /* Reset the current physical memory position */
+ PmemPosition.QuadPart = 0;
+ } else {
+ /* With IRP_MJ_CLOSE, we will drop our single handle */
+ handle_count = InterlockedDecrement(&PmemHandleCount);
+ }
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
+
+static NTSTATUS NTAPI PmemIrpRead(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ IO_STACK_LOCATION * io_stack_loc;
+ LARGE_INTEGER offset;
+ ULONG size;
+ unsigned char * phys_mem;
+ NTSTATUS status;
+
+ Unused_(dev_obj);
+
+ ASSERT(irp);
+ io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+ ASSERT(io_stack_loc);
+ offset = io_stack_loc->Parameters.Read.ByteOffset;
+ if (offset.QuadPart)
+ PmemPosition.QuadPart = offset.QuadPart;
+ size = io_stack_loc->Parameters.Read.Length;
+
+ /* Map the physical memory */
+ phys_mem = MmMapIoSpace(
+ PmemPosition,
+ size,
+ MmNonCached
+ );
+ if (!phys_mem) {
+ /* Treat this as an I/O error */
+ size = 0;
+ status = STATUS_NONEXISTENT_SECTOR;
+ goto err_map;
+ }
+
+ ASSERT(irp->AssociatedIrp.SystemBuffer);
+ RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, phys_mem, size);
+ PmemPosition.QuadPart += size;
+ status = STATUS_SUCCESS;
+
+ /* Unmap the memory */
+ MmUnmapIoSpace(phys_mem, size);
+ err_map:
+
+ irp->IoStatus.Information = size;
+ irp->IoStatus.Status = status;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return status;
+ }
+
+static NTSTATUS NTAPI PmemIrpQuerySetInformation(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ IO_STACK_LOCATION * io_stack_loc;
+ FILE_INFORMATION_CLASS file_info_class;
+ FILE_POSITION_INFORMATION * file_pos_info;
+ FILE_BASIC_INFORMATION * file_basic_info;
+ NTSTATUS status;
+
+ Unused_(dev_obj);
+
+ ASSERT(irp);
+ io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+ ASSERT(io_stack_loc);
+ if (io_stack_loc->MajorFunction == IRP_MJ_QUERY_INFORMATION) {
+ file_info_class =
+ io_stack_loc->Parameters.QueryFile.FileInformationClass;
+ } else {
+ file_info_class =
+ io_stack_loc->Parameters.SetFile.FileInformationClass;
+ }
+ switch (file_info_class) {
+ case FilePositionInformation:
+ if (
+ io_stack_loc->Parameters.QueryFile.Length <
+ sizeof *file_pos_info
+ ) {
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ file_pos_info = irp->AssociatedIrp.SystemBuffer;
+ ASSERT(file_pos_info);
+ RtlZeroMemory(file_pos_info, sizeof *file_pos_info);
+ if (io_stack_loc->MajorFunction == IRP_MJ_QUERY_INFORMATION)
+ file_pos_info->CurrentByteOffset.QuadPart = PmemPosition.QuadPart;
+ else
+ PmemPosition.QuadPart = file_pos_info->CurrentByteOffset.QuadPart;
+ irp->IoStatus.Information = sizeof *file_pos_info;
+ status = STATUS_SUCCESS;
+ break;
+
+ case FileBasicInformation:
+ if (
+ io_stack_loc->Parameters.QueryFile.Length <
+ sizeof *file_basic_info
+ ) {
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ file_basic_info = irp->AssociatedIrp.SystemBuffer;
+ ASSERT(file_basic_info);
+ RtlZeroMemory(file_basic_info, sizeof *file_basic_info);
+ irp->IoStatus.Information = sizeof *file_basic_info;
+ status = STATUS_SUCCESS;
+ break;
+
+ default:
+ status = STATUS_NOT_SUPPORTED;
+ }
+ irp->IoStatus.Status = status;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return status;
+ }
+
+/* Handle a device control */
+static NTSTATUS NTAPI PmemIrpDeviceControl(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ IO_STACK_LOCATION * io_stack_loc;
+ NTSTATUS status;
+
+ Unused_(dev_obj);
+
+ /* Check the type of IOCTL */
+ ASSERT(irp);
+ io_stack_loc = IoGetCurrentIrpStackLocation(irp);
+ switch (io_stack_loc->Parameters.DeviceIoControl.IoControlCode) {
+ /* Maybe later */
+ case CvPmemIoctlFoo:
+
+ /* Otherwise, we don't support this IOCTL */
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ /* Complete the IRP and return the status */
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = status;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return status;
+ }
+
+static NTSTATUS NTAPI PmemIrpCleanup(
+ IN DEVICE_OBJECT * dev_obj,
+ IN IRP * irp
+ ) {
+ Unused_(dev_obj);
+ ASSERT(irp);
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+ }
diff --git a/win/mdiskchk/sys/pmem.def b/win/mdiskchk/sys/pmem.def
new file mode 100644
index 00000000..62d7bb0f
--- /dev/null
+++ b/win/mdiskchk/sys/pmem.def
@@ -0,0 +1,7 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For DDK 'build'
+
+NAME PMEM.SYS
+
+EXPORTS
+ DriverEntry
diff --git a/win/mdiskchk/sys/pmem.rc b/win/mdiskchk/sys/pmem.rc
new file mode 100644
index 00000000..d28c46cd
--- /dev/null
+++ b/win/mdiskchk/sys/pmem.rc
@@ -0,0 +1,21 @@
+1 VERSIONINFO
+FILEVERSION 0,0,0,1
+PRODUCTVERSION 0,0,0,1
+FILEOS 0x40004
+FILETYPE 0x3 {
+ BLOCK "StringFileInfo" {
+ BLOCK "000004B0" {
+ VALUE "CompanyName", "Shao Miller"
+ VALUE "FileDescription", "PMem Driver"
+ VALUE "FileVersion", "0.0.0.1 (June-13-2012)"
+ VALUE "InternalName", "PMem Driver"
+ VALUE "LegalCopyright", " 2012 Shao Miller, All rights reserved, Licensed under GPL."
+ VALUE "OriginalFilename", "pmem.sys"
+ VALUE "ProductName", "PMem Driver"
+ VALUE "ProductVersion", "0.0.0.1"
+ }
+ }
+ BLOCK "VarFileInfo" {
+ VALUE "Translation", 0x0000, 0x04B0
+ }
+ }
diff --git a/win/mdiskchk/sys/sources b/win/mdiskchk/sys/sources
new file mode 100644
index 00000000..20682327
--- /dev/null
+++ b/win/mdiskchk/sys/sources
@@ -0,0 +1,9 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For DDK 'build'
+
+TARGETNAME=pmem
+INCLUDES=..\inc
+TARGETTYPE=DRIVER
+TARGETPATH=obj
+SOURCES=pmem.c pmem.rc
+DLLDEF=pmem.def
diff --git a/win32/mdiskchk/exe/Makefile b/win32/mdiskchk/exe/Makefile
new file mode 100644
index 00000000..cb892c79
--- /dev/null
+++ b/win32/mdiskchk/exe/Makefile
@@ -0,0 +1,48 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For 'make'
+
+# hpa's helper for finding MinGW
+WINPREFIX := $(shell ../../find-mingw32.sh gcc)
+
+WININC := /usr/i686-w64-mingw32/sys-root/mingw/include
+WINLIB := /usr/i686-w64-mingw32/sys-root/mingw/lib
+
+# Programs
+CC := $(WINPREFIX)gcc
+WINDRES := $(WINPREFIX)windres
+LINK := $(WINPREFIX)ld
+DLLTOOL := $(WINPREFIX)dlltool
+RM := rm -f
+
+# Inclusions and libraries
+INCS := -I$(WININC) -I../../../win/mdiskchk/inc
+LIBS := -L$(WINLIB)
+
+DEFINES :=
+CWARN := -Wall -Wextra
+
+# Flags
+CFLAGS := $(INCS) $(DEFINES) $(CWARN) \
+ -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+LFLAGS := -Os -s
+
+# Files
+COBJS := mdiskchk.o winstuff.o
+ROBJS := mdiskchk.res
+LOBJS := mdiskchk.res mdiskchk.o winstuff.o
+BIN := mdiskchk.exe
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(COBJS) $(ROBJS) PMem.Sys
+
+$(BIN): $(COBJS) $(ROBJS)
+ $(CC) $(CFLAGS) $(LFLAGS) -o $(BIN) $(LOBJS)
+
+%.o: ../../../win/mdiskchk/exe/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.res: ../../../win/mdiskchk/exe/%.rc
+ cp ../sys/pmem.sys PMem.Sys
+ $(WINDRES) -O COFF $< $@
diff --git a/win32/mdiskchk/sys/Makefile b/win32/mdiskchk/sys/Makefile
new file mode 100644
index 00000000..d73967b9
--- /dev/null
+++ b/win32/mdiskchk/sys/Makefile
@@ -0,0 +1,63 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For 'make'
+
+# hpa's helper for finding MinGW
+WINPREFIX := $(shell ../../find-mingw32.sh gcc)
+
+WININC := /usr/i686-w64-mingw32/sys-root/mingw/include
+WINLIB := /usr/i686-w64-mingw32/sys-root/mingw/lib
+
+# Programs
+CC := $(WINPREFIX)gcc
+WINDRES := $(WINPREFIX)windres
+LINK := $(WINPREFIX)ld
+DLLTOOL := $(WINPREFIX)dlltool
+RM := rm -f
+
+# Inclusions and libraries
+INCS := -I$(WININC) -I$(WININC)/ddk -I../../../win/mdiskchk/inc
+LIBS := -L$(WINLIB)
+
+DEFINES := -DNO_INTERLOCKED_INTRINSICS
+CWARN := -Wall -Wextra
+
+# Flags
+CFLAGS := $(INCS) $(DEFINES) $(CWARN) \
+ -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+LFLAGS1 := $(LIBS) -s -nostartfiles -nostdlib --entry _DriverEntry@8
+LFLAGS2 := $(LIBS) \
+ --subsystem native \
+ --entry _DriverEntry@8 \
+ --image-base 0x10000 \
+ --file-alignment 0x1000 \
+ --stack 0x40000 \
+ --section-alignment 0x1000
+
+# Files
+COBJS := pmem.o
+ROBJS := pmem.res
+BASES := pmem.base
+EXPS := pmem.exp
+LOBJS := pmem.res pmem.o -lntoskrnl
+BIN := pmem.sys
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(EXPS) $(BASES) $(COBJS) $(ROBJS)
+
+$(BIN): $(COBJS) $(ROBJS) $(EXPS)
+ $(LINK) $(LFLAGS2) -o $(BIN) $(EXPS) $(LOBJS)
+
+%.o: ../../../win/mdiskchk/sys/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.res: ../../../win/mdiskchk/sys/%.rc
+ $(WINDRES) -O COFF $< $@
+
+%.base: $(COBJS) $(ROBJS)
+ $(LINK) $(LFLAGS1) --base-file $@ -o $(BIN).tmp $(LOBJS)
+ $(RM) $(BIN).tmp
+
+%.exp: $(BASES)
+ $(DLLTOOL) --dllname $(BIN) --base-file $(BASES) --output-exp $@
diff --git a/win64/mdiskchk/exe/Makefile b/win64/mdiskchk/exe/Makefile
new file mode 100644
index 00000000..5b5ee4a4
--- /dev/null
+++ b/win64/mdiskchk/exe/Makefile
@@ -0,0 +1,48 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For 'make'
+
+# hpa's helper for finding MinGW
+WINPREFIX := $(shell ../../find-mingw64.sh gcc)
+
+WININC := /usr/x86_64-w64-mingw32/sys-root/mingw/include
+WINLIB := /usr/x86_64-w64-mingw32/sys-root/mingw/lib
+
+# Programs
+CC := $(WINPREFIX)gcc
+WINDRES := $(WINPREFIX)windres
+LINK := $(WINPREFIX)ld
+DLLTOOL := $(WINPREFIX)dlltool
+RM := rm -f
+
+# Inclusions and libraries
+INCS := -I$(WININC) -I../../../win/mdiskchk/inc
+LIBS := -L$(WINLIB)
+
+DEFINES :=
+CWARN := -Wall -Wextra
+
+# Flags
+CFLAGS := $(INCS) $(DEFINES) $(CWARN) \
+ -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+LFLAGS := -Os -s
+
+# Files
+COBJS := mdiskchk.o winstuff.o
+ROBJS := mdiskchk.res
+LOBJS := mdiskchk.res mdiskchk.o winstuff.o
+BIN := mdiskchk.exe
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(COBJS) $(ROBJS) PMem.Sys
+
+$(BIN): $(COBJS) $(ROBJS)
+ $(CC) $(CFLAGS) $(LFLAGS) -o $(BIN) $(LOBJS)
+
+%.o: ../../../win/mdiskchk/exe/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.res: ../../../win/mdiskchk/exe/%.rc
+ cp ../sys/pmem.sys PMem.Sys
+ $(WINDRES) -O COFF $< $@
diff --git a/win64/mdiskchk/sys/Makefile b/win64/mdiskchk/sys/Makefile
new file mode 100644
index 00000000..7829772f
--- /dev/null
+++ b/win64/mdiskchk/sys/Makefile
@@ -0,0 +1,63 @@
+# 2012, Shao Miller <sha0.miller@gmail.com>.
+# For 'make'
+
+# hpa's helper for finding MinGW
+WINPREFIX := $(shell ../../find-mingw64.sh gcc)
+
+WININC := /usr/x86_64-w64-mingw32/sys-root/mingw/include
+WINLIB := /usr/x86_64-w64-mingw32/sys-root/mingw/lib
+
+# Programs
+CC := $(WINPREFIX)gcc
+WINDRES := $(WINPREFIX)windres
+LINK := $(WINPREFIX)ld
+DLLTOOL := $(WINPREFIX)dlltool
+RM := rm -f
+
+# Inclusions and libraries
+INCS := -I$(WININC) -I$(WININC)/ddk -I../../../win/mdiskchk/inc
+LIBS := -L$(WINLIB)
+
+DEFINES := -DNO_INTERLOCKED_INTRINSICS
+CWARN := -Wall -Wextra
+
+# Flags
+CFLAGS := $(INCS) $(DEFINES) $(CWARN) \
+ -Wno-sign-compare -Os -fomit-frame-pointer -D_FILE_OFFSET_BITS=64
+LFLAGS1 := $(LIBS) -s -nostartfiles -nostdlib --entry DriverEntry
+LFLAGS2 := $(LIBS) \
+ --subsystem native \
+ --entry DriverEntry \
+ --image-base 0x10000 \
+ --file-alignment 0x1000 \
+ --stack 0x40000 \
+ --section-alignment 0x1000
+
+# Files
+COBJS := pmem.o
+ROBJS := pmem.res
+BASES := pmem.base
+EXPS := pmem.exp
+LOBJS := pmem.res pmem.o -lntoskrnl
+BIN := pmem.sys
+
+all: $(BIN)
+
+clean:
+ $(RM) $(BIN) $(EXPS) $(BASES) $(COBJS) $(ROBJS)
+
+$(BIN): $(COBJS) $(ROBJS) $(EXPS)
+ $(LINK) $(LFLAGS2) -o $(BIN) $(EXPS) $(LOBJS)
+
+%.o: ../../../win/mdiskchk/sys/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+%.res: ../../../win/mdiskchk/sys/%.rc
+ $(WINDRES) -O COFF $< $@
+
+%.base: $(COBJS) $(ROBJS)
+ $(LINK) $(LFLAGS1) --base-file $@ -o $(BIN).tmp $(LOBJS)
+ $(RM) $(BIN).tmp
+
+%.exp: $(BASES)
+ $(DLLTOOL) --dllname $(BIN) --base-file $(BASES) --output-exp $@