summaryrefslogtreecommitdiff
path: root/storage/ramdisk/src
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-04-29 09:48:49 -0700
committerDave Wilson <[email protected]>2015-04-29 10:47:29 -0700
commitd40232638faaab19de557e70a3ee938da7a35295 (patch)
tree14e61c973745949af186b7940e3a53d25322f5de /storage/ramdisk/src
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'storage/ramdisk/src')
-rw-r--r--storage/ramdisk/src/WdfRamdisk.vcxproj160
-rw-r--r--storage/ramdisk/src/WdfRamdisk.vcxproj.Filters42
-rw-r--r--storage/ramdisk/src/forward_progress.c347
-rw-r--r--storage/ramdisk/src/forward_progress.h52
-rw-r--r--storage/ramdisk/src/ramdisk.c898
-rw-r--r--storage/ramdisk/src/ramdisk.h196
-rw-r--r--storage/ramdisk/src/ramdisk.inx102
-rw-r--r--storage/ramdisk/src/ramdisk.rc11
8 files changed, 1808 insertions, 0 deletions
diff --git a/storage/ramdisk/src/WdfRamdisk.vcxproj b/storage/ramdisk/src/WdfRamdisk.vcxproj
new file mode 100644
index 00000000..64f70c23
--- /dev/null
+++ b/storage/ramdisk/src/WdfRamdisk.vcxproj
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FAEE8721-3E3F-4338-8E7B-1BE9FC028C15}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{987E33B7-1E8D-4015-A46C-08667083FC5F}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <Inf Include=".\ramdisk.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\ramdisk.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>WdfRamdisk</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>WdfRamdisk</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>WdfRamdisk</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>WdfRamdisk</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="forward_progress.c" />
+ <ClCompile Include="ramdisk.c" />
+ <ResourceCompile Include="ramdisk.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/storage/ramdisk/src/WdfRamdisk.vcxproj.Filters b/storage/ramdisk/src/WdfRamdisk.vcxproj.Filters
new file mode 100644
index 00000000..1e94b2f4
--- /dev/null
+++ b/storage/ramdisk/src/WdfRamdisk.vcxproj.Filters
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{D9F38118-6A63-448F-A1E6-428B134C40FF}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{13BF032A-5FDD-40A6-BA9C-3C48A3EF713E}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{301177B6-FDBA-46E7-BA20-E5AAE5CA0223}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{8D1F3AF6-FD7D-4065-8ADA-FFBF156120D3}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\ramdisk.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\ramdisk.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="forward_progress.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ramdisk.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ramdisk.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/storage/ramdisk/src/forward_progress.c b/storage/ramdisk/src/forward_progress.c
new file mode 100644
index 00000000..a7c29c7a
--- /dev/null
+++ b/storage/ramdisk/src/forward_progress.c
@@ -0,0 +1,347 @@
+
+/*++
+
+Copyright (c) 1990-2000 Microsoft Corporation
+
+Module Name:
+
+ forwardprogress.c
+
+Abstract:
+
+ Show the forward progress feature
+
+
+
+--*/
+
+//
+// NOTE: Forward progress was added in v1.9
+//
+
+#if KMDF_VERSION_MINOR >= 9
+
+#include "ramdisk.h"
+
+VOID
+EvtForwardProgressRequestDestroy(
+ WDFOBJECT Request
+ )
+
+/*++
+
+Routine Description:
+
+ This event is called when the request memory is about to be freed.
+ Reserved requests get deleted only when the queue gets deleted.
+
+
+Arguments:
+
+ Request - Handle to a framework request object.
+
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
+
+ fwdReqContext = GetForwardProgressRequestContext(Request);
+}
+
+VOID
+EvtForwardProgressRequestCleanup(
+ WDFOBJECT Request
+ )
+
+/*++
+
+Routine Description:
+
+ This event is called when the reserved request is about to be deleted.
+ NOTE: In case of reserved request this callback doesn't get called after the
+ I/O is done but only when the request is about to be deleted.
+
+Arguments:
+
+ Request - Handle to a framework request object.
+
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ PFWD_PROGRESS_REQUEST_CONTEXT reqContext;
+
+ reqContext = GetForwardProgressRequestContext(Request);
+
+ //
+ // Cleanup any resources allocated earlier for reserved requests here.
+ //
+}
+
+
+NTSTATUS
+AllocateAdditionalRequestContext(
+ _In_ WDFREQUEST Request
+ )
+
+/*++
+
+Routine Description:
+ Allocate resources used by request.
+ Set the EvtCleanupCallback and EvtDestroyCallback
+ to show the lifetime of a Reserved request.
+
+Arguments:
+
+ Request - Handle to a framework request object.
+
+Return Value:
+
+
+ NTSTATUS
+
+--*/
+{
+ WDF_OBJECT_ATTRIBUTES requestContextAttributes;
+ PFWD_PROGRESS_REQUEST_CONTEXT reqContext;
+ NTSTATUS status;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestContextAttributes,
+ FWD_PROGRESS_REQUEST_CONTEXT);
+ requestContextAttributes.EvtCleanupCallback = EvtForwardProgressRequestCleanup;
+ requestContextAttributes.EvtDestroyCallback = EvtForwardProgressRequestDestroy;
+ status = WdfObjectAllocateContext(Request,
+ &requestContextAttributes,
+ &reqContext);
+
+ return status;
+}
+
+
+WDF_IO_FORWARD_PROGRESS_ACTION
+EvtIoWdmIrpForForwardProgress(
+ _In_ WDFQUEUE Queue,
+ _In_ PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+ A driver's EvtIoWdmIrpForForwardProgress callback function is used for
+ examining an IRP and tell the framework whether to use a reserved
+ request object for the IRP or to fail the I/O request by completing
+ it with an error status value.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+ Irp -
+Return Value:
+
+ WDF_IO_FORWARD_PROGRESS_ACTION
+ WdfIoForwardProgressActionFailRequest is returned it causes
+ the Framework to fail the IRP.
+ WdfIoForwardProgressActionUseReservedRequest is returned it causes
+ the framework to use a reserved request to handle the IRP.
+--*/
+{
+ PIO_STACK_LOCATION irpStack;
+ WDF_IO_FORWARD_PROGRESS_ACTION action;
+
+ UNREFERENCED_PARAMETER(Queue);
+
+ irpStack = IoGetCurrentIrpStackLocation(Irp);
+ switch (irpStack->MajorFunction) {
+ case IRP_MJ_READ:
+ case IRP_MJ_WRITE:
+ case IRP_MJ_DEVICE_CONTROL:
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+
+ //
+ // Use reserved request for reads, writes, IOCTL's
+ //
+ action = WdfIoForwardProgressActionUseReservedRequest;
+ break;
+
+ default:
+ //
+ // Just for demonstration of the available actions fail the
+ // other I/O IRP's
+ //
+ action = WdfIoForwardProgressActionFailRequest;
+ break;
+ }
+
+ return action;
+}
+
+NTSTATUS
+EvtIoAllocateResourcesForReservedRequest(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request
+ )
+
+/*++
+
+Routine Description:
+
+ A driver's EvtIoAllocateResourcesForReservedRequest callback function
+ allocates and stores request-specific resources for request objects that
+ the framework is reserving for low-memory situations.
+
+ NOTE: You can't call WdfRequestGetIoQueue for Reserved requests
+ Use the Queue handle passed in.
+
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+ Request - Handle to a framework request object.
+
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ NTSTATUS status;
+ PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
+
+ UNREFERENCED_PARAMETER(Queue);
+
+ status = STATUS_SUCCESS;
+ ASSERT(WdfRequestIsReserved(Request));
+
+ //
+ // Allocate all resources needed for the request here. If you need to
+ // pre-allocate memory or any other resource do it in this callback and
+ // store it in the context.
+ //
+ status = AllocateAdditionalRequestContext(Request);
+ if (NT_SUCCESS(status)) {
+
+ fwdReqContext = GetForwardProgressRequestContext(Request);
+ }
+
+ return status;
+}
+
+NTSTATUS
+EvtIoAllocateResources(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request
+ )
+
+/*++
+
+Routine Description:
+
+ This event is called for the driver to allocate request
+ resources for immediate use (unlike reserved requests which is for use under
+ low memory).
+ It is called immediately after the framework has received an IRP and created
+ a request object for the IRP.
+
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+ Request - Handle to a framework request object.
+
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ NTSTATUS status;
+ PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
+
+ UNREFERENCED_PARAMETER(Queue);
+ status = STATUS_SUCCESS;
+
+ //
+ // Allocate all resources needed for the request here and store it in the request
+ // context.
+ //
+ fwdReqContext = GetForwardProgressRequestContext(Request);
+
+ return status;
+}
+
+NTSTATUS
+SetForwardProgressOnQueue(
+ _In_ WDFQUEUE Queue
+ )
+
+/*++
+
+Routine Description:
+ Set forward progress on the top level( handles one of the major I/O IRP)
+ queue we created.
+ The default is always a top level queue or if the queue was configured
+ with WdfDeviceConfigureRequestDispatching.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+
+ WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY forwardProgressPolicy;
+ NTSTATUS status;
+
+ //
+ // The policy is configurable by the user. In the code segment below
+ // WdfIoForwardProgressReservedPolicyUseExamine
+ // is demonstrated. If your driver supports paging I/O you should select
+ // WdfIoForwardProgressReservedPolicyPagingIO.
+ // MAX_RESERVED_REQUESTS should be adjusted depending on the number of parallel
+ // requests the driver wants to handle under low memory conditions. It may
+ // require some hit and trial to get the right number.
+ //
+ WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY_EXAMINE_INIT(
+ &forwardProgressPolicy,
+ MAX_RESERVED_REQUESTS,
+ EvtIoWdmIrpForForwardProgress
+ );
+
+ forwardProgressPolicy.EvtIoAllocateResourcesForReservedRequest =
+ EvtIoAllocateResourcesForReservedRequest;
+ forwardProgressPolicy.EvtIoAllocateRequestResources = EvtIoAllocateResources;
+
+ status = WdfIoQueueAssignForwardProgressPolicy(Queue,
+ &forwardProgressPolicy
+ );
+ if (!NT_SUCCESS(status)) {
+ KdPrint(("Error WdfIoQueueAssignForwardProgressPolicy 0x%x\n",status));
+ return status;
+ }
+
+ return status;
+}
+
+#endif
+
diff --git a/storage/ramdisk/src/forward_progress.h b/storage/ramdisk/src/forward_progress.h
new file mode 100644
index 00000000..00bb6aa6
--- /dev/null
+++ b/storage/ramdisk/src/forward_progress.h
@@ -0,0 +1,52 @@
+/*++
+
+Copyright (c) 1990-2000 Microsoft Corporation
+
+Module Name:
+
+ forward_progress.h
+
+Abstract:
+
+ This is the driver object header for forward progress
+
+
+Environment:
+
+ kernel mode only
+
+Revision History:
+
+--*/
+
+#pragma once
+
+//
+// NOTE: Forward progress was added in v1.9
+//
+
+#if KMDF_VERSION_MINOR >= 9
+
+EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtForwardProgressRequestCleanup;
+EVT_WDF_OBJECT_CONTEXT_DESTROY EvtForwardProgressRequestDestroy;
+EVT_WDF_IO_WDM_IRP_FOR_FORWARD_PROGRESS EvtIoWdmIrpForForwardProgress;
+EVT_WDF_IO_ALLOCATE_RESOURCES_FOR_RESERVED_REQUEST EvtIoAllocateResourcesForReservedRequest;
+EVT_WDF_IO_ALLOCATE_REQUEST_RESOURCES EvtIoAllocateResources;
+
+#define MAX_RESERVED_REQUESTS 8
+#define MEMORY_SIZE 0x100
+
+typedef struct _FWD_PROGRESS_REQUEST_CONTEXT {
+ WDFMEMORY Memory;
+} FWD_PROGRESS_REQUEST_CONTEXT, *PFWD_PROGRESS_REQUEST_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FWD_PROGRESS_REQUEST_CONTEXT, GetForwardProgressRequestContext)
+
+
+NTSTATUS
+SetForwardProgressOnQueue(
+ _In_ WDFQUEUE Queue
+ );
+
+#endif
+
diff --git a/storage/ramdisk/src/ramdisk.c b/storage/ramdisk/src/ramdisk.c
new file mode 100644
index 00000000..ce571706
--- /dev/null
+++ b/storage/ramdisk/src/ramdisk.c
@@ -0,0 +1,898 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Ramdisk.c
+
+Abstract:
+
+ This is the Ramdisk sample driver. This version of the driver has been
+ modified to support the driver frameworks. This driver basically creates
+ a nonpaged pool and exposes that as a storage media. User can
+ find the device in the disk manager and format the media to use
+ as FAT or NTFS volume.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#include "ramdisk.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, DriverEntry)
+#pragma alloc_text(PAGE, RamDiskEvtDeviceAdd)
+#pragma alloc_text(PAGE, RamDiskEvtDeviceContextCleanup)
+#pragma alloc_text(PAGE, RamDiskQueryDiskRegParameters)
+#pragma alloc_text(PAGE, RamDiskFormatDisk)
+#endif
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ Installable driver initialization entry point.
+ This entry point is called directly by the I/O system.
+
+Arguments:
+
+ DriverObject - pointer to the driver object
+
+ RegistryPath - pointer to a unicode string representing the path
+ to driver-specific key in the registry
+
+Return Value:
+
+ STATUS_SUCCESS if successful.
+
+--*/
+
+{
+ WDF_DRIVER_CONFIG config;
+
+ KdPrint(("Windows Ramdisk Driver - Driver Framework Edition.\n"));
+
+
+ WDF_DRIVER_CONFIG_INIT( &config, RamDiskEvtDeviceAdd );
+
+ return WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
+}
+
+VOID
+RamDiskEvtIoRead(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ )
+/*++
+
+Routine Description:
+
+ This event is called when the framework receives IRP_MJ_READ request.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+ Request - Handle to a framework request object.
+
+ Length - Length of the data buffer associated with the request.
+ The default property of the queue is to not dispatch
+ zero length read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ WDF_REQUEST_PARAMETERS Parameters;
+ LARGE_INTEGER ByteOffset;
+ WDFMEMORY hMemory;
+
+ _Analysis_assume_(Length > 0);
+
+ WDF_REQUEST_PARAMETERS_INIT(&Parameters);
+ WdfRequestGetParameters(Request, &Parameters);
+
+ ByteOffset.QuadPart = Parameters.Parameters.Read.DeviceOffset;
+
+ if (RamDiskCheckParameters(devExt, ByteOffset, Length)) {
+
+ Status = WdfRequestRetrieveOutputMemory(Request, &hMemory);
+ if(NT_SUCCESS(Status)){
+
+ Status = WdfMemoryCopyFromBuffer(hMemory, // Destination
+ 0, // Offset into the destination
+ devExt->DiskImage + ByteOffset.LowPart, // source
+ Length);
+ }
+ }
+
+ WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length);
+}
+
+VOID
+RamDiskEvtIoWrite(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ )
+
+/*++
+
+Routine Description:
+
+ This event is invoked when the framework receives IRP_MJ_WRITE request.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated with the
+ I/O request.
+
+ Request - Handle to a framework request object.
+
+ Length - Length of the data buffer associated with the request.
+ The default property of the queue is to not dispatch
+ zero length read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+ WDF_REQUEST_PARAMETERS Parameters;
+ LARGE_INTEGER ByteOffset;
+ WDFMEMORY hMemory;
+
+ _Analysis_assume_(Length > 0);
+
+ WDF_REQUEST_PARAMETERS_INIT(&Parameters);
+ WdfRequestGetParameters(Request, &Parameters);
+
+ ByteOffset.QuadPart = Parameters.Parameters.Write.DeviceOffset;
+
+ if (RamDiskCheckParameters(devExt, ByteOffset, Length)) {
+
+ Status = WdfRequestRetrieveInputMemory(Request, &hMemory);
+ if(NT_SUCCESS(Status)){
+
+ Status = WdfMemoryCopyToBuffer(hMemory, // Source
+ 0, // offset in Source memory where the copy has to start
+ devExt->DiskImage + ByteOffset.LowPart, // destination
+ Length);
+ }
+
+ }
+
+ WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length);
+}
+
+VOID
+RamDiskEvtIoDeviceControl(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t OutputBufferLength,
+ IN size_t InputBufferLength,
+ IN ULONG IoControlCode
+ )
+/*++
+
+Routine Description:
+
+ This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
+ requests from the system.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated
+ with the I/O request.
+ Request - Handle to a framework request object.
+
+ OutputBufferLength - length of the request's output buffer,
+ if an output buffer is available.
+ InputBufferLength - length of the request's input buffer,
+ if an input buffer is available.
+
+ IoControlCode - the driver-defined or system-defined I/O control code
+ (IOCTL) that is associated with the request.
+
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+ ULONG_PTR information = 0;
+ size_t bufSize;
+ PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension;
+
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+ UNREFERENCED_PARAMETER(InputBufferLength);
+
+ switch (IoControlCode) {
+ case IOCTL_DISK_GET_PARTITION_INFO: {
+
+ PPARTITION_INFORMATION outputBuffer;
+ PBOOT_SECTOR bootSector = (PBOOT_SECTOR) devExt->DiskImage;
+
+ information = sizeof(PARTITION_INFORMATION);
+
+ Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(PARTITION_INFORMATION), &outputBuffer, &bufSize);
+ if(NT_SUCCESS(Status) ) {
+
+ outputBuffer->PartitionType =
+ (bootSector->bsFileSystemType[4] == '6') ? PARTITION_FAT_16 : PARTITION_FAT_12;
+
+ outputBuffer->BootIndicator = FALSE;
+ outputBuffer->RecognizedPartition = TRUE;
+ outputBuffer->RewritePartition = FALSE;
+ outputBuffer->StartingOffset.QuadPart = 0;
+ outputBuffer->PartitionLength.QuadPart = devExt->DiskRegInfo.DiskSize;
+ outputBuffer->HiddenSectors = (ULONG) (1L);
+ outputBuffer->PartitionNumber = (ULONG) (-1L);
+
+ Status = STATUS_SUCCESS;
+ }
+ }
+ break;
+
+ case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
+
+ PDISK_GEOMETRY outputBuffer;
+
+ //
+ // Return the drive geometry for the ram disk. Note that
+ // we return values which were made up to suit the disk size.
+ //
+ information = sizeof(DISK_GEOMETRY);
+
+ Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(DISK_GEOMETRY), &outputBuffer, &bufSize);
+ if(NT_SUCCESS(Status) &&
+ bufSize >= sizeof(DISK_GEOMETRY)) {
+
+ RtlCopyMemory(outputBuffer, &(devExt->DiskGeometry), sizeof(DISK_GEOMETRY));
+ Status = STATUS_SUCCESS;
+ }
+ }
+ break;
+
+ case IOCTL_DISK_CHECK_VERIFY:
+ case IOCTL_DISK_IS_WRITABLE:
+
+ //
+ // Return status success
+ //
+
+ Status = STATUS_SUCCESS;
+ break;
+ }
+
+ WdfRequestCompleteWithInformation(Request, Status, information);
+}
+
+VOID
+RamDiskEvtDeviceContextCleanup(
+ IN WDFOBJECT Device
+ )
+/*++
+
+Routine Description:
+
+ EvtDeviceContextCleanup event callback cleans up anything done in
+ EvtDeviceAdd, except those things that are automatically cleaned
+ up by the Framework.
+
+ In the case of this sample, everything is automatically handled. In a
+ driver derived from this sample, it's quite likely that this function could
+ be deleted.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+Return Value:
+
+ VOID
+
+--*/
+{
+ PDEVICE_EXTENSION pDeviceExtension = DeviceGetExtension(Device);
+
+ PAGED_CODE();
+
+ if(pDeviceExtension->DiskImage) {
+ ExFreePool(pDeviceExtension->DiskImage);
+ }
+}
+
+NTSTATUS
+RamDiskEvtDeviceAdd(
+ IN WDFDRIVER Driver,
+ IN PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+Routine Description:
+
+ EvtDeviceAdd is called by the framework in response to AddDevice
+ call from the PnP manager. We create and initialize a device object to
+ represent a new instance of the device.
+
+Arguments:
+
+ Driver - Handle to a framework driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ NTSTATUS status;
+ WDFDEVICE device;
+ WDF_OBJECT_ATTRIBUTES queueAttributes;
+ WDF_IO_QUEUE_CONFIG ioQueueConfig;
+ PDEVICE_EXTENSION pDeviceExtension;
+ PQUEUE_EXTENSION pQueueContext = NULL;
+ WDFQUEUE queue;
+ DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME);
+
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ //
+ // Storage drivers have to name their FDOs. Since we are not unique'fying
+ // the device name, we wouldn't be able to install more than one instance
+ // of this ramdisk driver.
+ //
+ status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK);
+ WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
+ WdfDeviceInitSetExclusive(DeviceInit, FALSE);
+
+ //
+ // Since this is a pure software only driver, there is no need to register
+ // any PNP/Power event callbacks. Framework will respond to these
+ // events appropriately.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION);
+ deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup;
+
+ status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ //
+ // Now that the WDF device object has been created, set up any context
+ // that it requires.
+ //
+
+ pDeviceExtension = DeviceGetExtension(device);
+
+ //
+ // Configure a default queue so that requests that are not
+ // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
+ // other queues get dispatched here.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (
+ &ioQueueConfig,
+ WdfIoQueueDispatchSequential
+ );
+
+ ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl;
+ ioQueueConfig.EvtIoRead = RamDiskEvtIoRead;
+ ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION);
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests or
+ // forward them to other drivers. This driver completes the requests
+ // directly in the queue's handlers. If the EvtIoStop callback is not
+ // implemented, the framework waits for all driver-owned requests to be
+ // done before moving in the Dx/sleep states or before removing the
+ // device, which is the correct behavior for this type of driver.
+ // If the requests were taking an indeterminate amount of time to complete,
+ // or if the driver forwarded the requests to a lower driver/another stack,
+ // the queue should have an EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(ioQueueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate( device,
+ &ioQueueConfig,
+ &queueAttributes,
+ &queue );
+ __analysis_assume(ioQueueConfig.EvtIoStop == 0);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ // Context is the Queue handle
+ pQueueContext = QueueGetExtension(queue);
+
+ //
+ // Set the context for our default queue as our device extension.
+ //
+ pQueueContext->DeviceExtension = pDeviceExtension;
+
+#if KMDF_VERSION_MINOR >= 9
+
+ //
+ // Enable forward progress on the queue we just created.
+ // NOTE: If you are planning to use this code without forward progress,
+ // comment out the call to SetForwardProgressOnQueue below.
+ //
+ status = SetForwardProgressOnQueue(queue);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+#endif
+
+ //
+ // Now do any RAM-Disk specific initialization
+ //
+ pDeviceExtension->DiskRegInfo.DriveLetter.Buffer =
+ (PWSTR) &pDeviceExtension->DriveLetterBuffer;
+ pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength =
+ sizeof(pDeviceExtension->DriveLetterBuffer);
+
+ //
+ // Get the disk parameters from the registry
+ //
+ RamDiskQueryDiskRegParameters(
+ WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),
+ &pDeviceExtension->DiskRegInfo
+ );
+
+ //
+ // Allocate memory for the disk image.
+ //
+ pDeviceExtension->DiskImage = ExAllocatePoolWithTag(
+ NonPagedPool,
+ pDeviceExtension->DiskRegInfo.DiskSize,
+ RAMDISK_TAG
+ );
+
+ if (pDeviceExtension->DiskImage) {
+
+ UNICODE_STRING deviceName;
+ UNICODE_STRING win32Name;
+
+ RamDiskFormatDisk(pDeviceExtension);
+
+ status = STATUS_SUCCESS;
+
+ //
+ // Now try to create a symbolic link for the drive letter.
+ //
+ RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME);
+ RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME);
+
+ pDeviceExtension->SymbolicLink.Buffer = (PWSTR)
+ &pDeviceExtension->DosDeviceNameBuffer;
+ pDeviceExtension->SymbolicLink.MaximumLength =
+ sizeof(pDeviceExtension->DosDeviceNameBuffer);
+ pDeviceExtension->SymbolicLink.Length = win32Name.Length;
+
+ RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name);
+ RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,
+ &pDeviceExtension->DiskRegInfo.DriveLetter);
+
+ status = WdfDeviceCreateSymbolicLink(device,
+ &pDeviceExtension->SymbolicLink);
+ }
+
+ return status;
+}
+
+VOID
+RamDiskQueryDiskRegParameters(
+ _In_ PWSTR RegistryPath,
+ _In_ PDISK_INFO DiskRegInfo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from the DriverEntry to get the debug
+ parameters from the registry. If the registry query fails, then
+ default values are used.
+
+Arguments:
+
+ RegistryPath - Points the service path to get the registry parameters
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ RTL_QUERY_REGISTRY_TABLE rtlQueryRegTbl[5 + 1]; // Need 1 for NULL
+ NTSTATUS Status;
+ DISK_INFO defDiskRegInfo;
+
+ PAGED_CODE();
+
+ ASSERT(RegistryPath != NULL);
+
+ // Set the default values
+
+ defDiskRegInfo.DiskSize = DEFAULT_DISK_SIZE;
+ defDiskRegInfo.RootDirEntries = DEFAULT_ROOT_DIR_ENTRIES;
+ defDiskRegInfo.SectorsPerCluster = DEFAULT_SECTORS_PER_CLUSTER;
+
+ RtlInitUnicodeString(&defDiskRegInfo.DriveLetter, DEFAULT_DRIVE_LETTER);
+
+ RtlZeroMemory(rtlQueryRegTbl, sizeof(rtlQueryRegTbl));
+
+ //
+ // Setup the query table
+ //
+
+ rtlQueryRegTbl[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ rtlQueryRegTbl[0].Name = L"Parameters";
+ rtlQueryRegTbl[0].EntryContext = NULL;
+ rtlQueryRegTbl[0].DefaultType = (ULONG_PTR)NULL;
+ rtlQueryRegTbl[0].DefaultData = NULL;
+ rtlQueryRegTbl[0].DefaultLength = (ULONG_PTR)NULL;
+
+ //
+ // Disk paramters
+ //
+
+ rtlQueryRegTbl[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ rtlQueryRegTbl[1].Name = L"DiskSize";
+ rtlQueryRegTbl[1].EntryContext = &DiskRegInfo->DiskSize;
+ rtlQueryRegTbl[1].DefaultType = REG_DWORD;
+ rtlQueryRegTbl[1].DefaultData = &defDiskRegInfo.DiskSize;
+ rtlQueryRegTbl[1].DefaultLength = sizeof(ULONG);
+
+ rtlQueryRegTbl[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ rtlQueryRegTbl[2].Name = L"RootDirEntries";
+ rtlQueryRegTbl[2].EntryContext = &DiskRegInfo->RootDirEntries;
+ rtlQueryRegTbl[2].DefaultType = REG_DWORD;
+ rtlQueryRegTbl[2].DefaultData = &defDiskRegInfo.RootDirEntries;
+ rtlQueryRegTbl[2].DefaultLength = sizeof(ULONG);
+
+ rtlQueryRegTbl[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ rtlQueryRegTbl[3].Name = L"SectorsPerCluster";
+ rtlQueryRegTbl[3].EntryContext = &DiskRegInfo->SectorsPerCluster;
+ rtlQueryRegTbl[3].DefaultType = REG_DWORD;
+ rtlQueryRegTbl[3].DefaultData = &defDiskRegInfo.SectorsPerCluster;
+ rtlQueryRegTbl[3].DefaultLength = sizeof(ULONG);
+
+ rtlQueryRegTbl[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ rtlQueryRegTbl[4].Name = L"DriveLetter";
+ rtlQueryRegTbl[4].EntryContext = &DiskRegInfo->DriveLetter;
+ rtlQueryRegTbl[4].DefaultType = REG_SZ;
+ rtlQueryRegTbl[4].DefaultData = defDiskRegInfo.DriveLetter.Buffer;
+ rtlQueryRegTbl[4].DefaultLength = 0;
+
+
+ Status = RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ RegistryPath,
+ rtlQueryRegTbl,
+ NULL,
+ NULL
+ );
+
+ if (NT_SUCCESS(Status) == FALSE) {
+
+ DiskRegInfo->DiskSize = defDiskRegInfo.DiskSize;
+ DiskRegInfo->RootDirEntries = defDiskRegInfo.RootDirEntries;
+ DiskRegInfo->SectorsPerCluster = defDiskRegInfo.SectorsPerCluster;
+ RtlCopyUnicodeString(&DiskRegInfo->DriveLetter, &defDiskRegInfo.DriveLetter);
+ }
+
+ KdPrint(("DiskSize = 0x%lx\n", DiskRegInfo->DiskSize));
+ KdPrint(("RootDirEntries = 0x%lx\n", DiskRegInfo->RootDirEntries));
+ KdPrint(("SectorsPerCluster = 0x%lx\n", DiskRegInfo->SectorsPerCluster));
+ KdPrint(("DriveLetter = %wZ\n", &(DiskRegInfo->DriveLetter)));
+
+ return;
+}
+
+NTSTATUS
+RamDiskFormatDisk(
+ IN PDEVICE_EXTENSION devExt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine formats the new disk.
+
+
+Arguments:
+
+ DeviceObject - Supplies a pointer to the device object that represents
+ the device whose capacity is to be read.
+
+Return Value:
+
+ status is returned.
+
+--*/
+{
+
+ PBOOT_SECTOR bootSector = (PBOOT_SECTOR) devExt->DiskImage;
+ PUCHAR firstFatSector;
+ ULONG rootDirEntries;
+ ULONG sectorsPerCluster;
+ USHORT fatType; // Type FAT 12 or 16
+ USHORT fatEntries; // Number of cluster entries in FAT
+ USHORT fatSectorCnt; // Number of sectors for FAT
+ PDIR_ENTRY rootDir; // Pointer to first entry in root dir
+
+ PAGED_CODE();
+ ASSERT(sizeof(BOOT_SECTOR) == 512);
+ ASSERT(devExt->DiskImage != NULL);
+
+ RtlZeroMemory(devExt->DiskImage, devExt->DiskRegInfo.DiskSize);
+
+ devExt->DiskGeometry.BytesPerSector = 512;
+ devExt->DiskGeometry.SectorsPerTrack = 32; // Using Ramdisk value
+ devExt->DiskGeometry.TracksPerCylinder = 2; // Using Ramdisk value
+
+ //
+ // Calculate number of cylinders.
+ //
+
+ devExt->DiskGeometry.Cylinders.QuadPart = devExt->DiskRegInfo.DiskSize / 512 / 32 / 2;
+
+ //
+ // Our media type is RAMDISK_MEDIA_TYPE
+ //
+
+ devExt->DiskGeometry.MediaType = RAMDISK_MEDIA_TYPE;
+
+ KdPrint((
+ "Cylinders: %I64d\n TracksPerCylinder: %lu\n SectorsPerTrack: %lu\n BytesPerSector: %lu\n",
+ devExt->DiskGeometry.Cylinders.QuadPart, devExt->DiskGeometry.TracksPerCylinder,
+ devExt->DiskGeometry.SectorsPerTrack, devExt->DiskGeometry.BytesPerSector
+ ));
+
+ rootDirEntries = devExt->DiskRegInfo.RootDirEntries;
+ sectorsPerCluster = devExt->DiskRegInfo.SectorsPerCluster;
+
+ //
+ // Round Root Directory entries up if necessary
+ //
+
+ if (rootDirEntries & (DIR_ENTRIES_PER_SECTOR - 1)) {
+
+ rootDirEntries =
+ (rootDirEntries + (DIR_ENTRIES_PER_SECTOR - 1)) &
+ ~ (DIR_ENTRIES_PER_SECTOR - 1);
+ }
+
+ KdPrint((
+ "Root dir entries: %lu\n Sectors/cluster: %lu\n",
+ rootDirEntries, sectorsPerCluster
+ ));
+
+ //
+ // We need to have the 0xeb and 0x90 since this is one of the
+ // checks the file system recognizer uses
+ //
+
+ bootSector->bsJump[0] = 0xeb;
+ bootSector->bsJump[1] = 0x3c;
+ bootSector->bsJump[2] = 0x90;
+
+ //
+ // Set OemName to "RajuRam "
+ // NOTE: Fill all 8 characters, eg. sizeof(bootSector->bsOemName);
+ //
+ bootSector->bsOemName[0] = 'R';
+ bootSector->bsOemName[1] = 'a';
+ bootSector->bsOemName[2] = 'j';
+ bootSector->bsOemName[3] = 'u';
+ bootSector->bsOemName[4] = 'R';
+ bootSector->bsOemName[5] = 'a';
+ bootSector->bsOemName[6] = 'm';
+ bootSector->bsOemName[7] = ' ';
+
+ bootSector->bsBytesPerSec = (SHORT)devExt->DiskGeometry.BytesPerSector;
+ bootSector->bsResSectors = 1;
+ bootSector->bsFATs = 1;
+ bootSector->bsRootDirEnts = (USHORT)rootDirEntries;
+
+ bootSector->bsSectors = (USHORT)(devExt->DiskRegInfo.DiskSize /
+ devExt->DiskGeometry.BytesPerSector);
+ bootSector->bsMedia = (UCHAR)devExt->DiskGeometry.MediaType;
+ bootSector->bsSecPerClus = (UCHAR)sectorsPerCluster;
+
+ //
+ // Calculate number of sectors required for FAT
+ //
+
+ fatEntries =
+ (bootSector->bsSectors - bootSector->bsResSectors -
+ bootSector->bsRootDirEnts / DIR_ENTRIES_PER_SECTOR) /
+ bootSector->bsSecPerClus + 2;
+
+ //
+ // Choose between 12 and 16 bit FAT based on number of clusters we
+ // need to map
+ //
+
+ if (fatEntries > 4087) {
+ fatType = 16;
+ fatSectorCnt = (fatEntries * 2 + 511) / 512;
+ fatEntries = fatEntries + fatSectorCnt;
+ fatSectorCnt = (fatEntries * 2 + 511) / 512;
+ }
+ else {
+ fatType = 12;
+ fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
+ fatEntries = fatEntries + fatSectorCnt;
+ fatSectorCnt = (((fatEntries * 3 + 1) / 2) + 511) / 512;
+ }
+
+ bootSector->bsFATsecs = fatSectorCnt;
+ bootSector->bsSecPerTrack = (USHORT)devExt->DiskGeometry.SectorsPerTrack;
+ bootSector->bsHeads = (USHORT)devExt->DiskGeometry.TracksPerCylinder;
+ bootSector->bsBootSignature = 0x29;
+ bootSector->bsVolumeID = 0x12345678;
+
+ //
+ // Set Label to "RamDisk "
+ // NOTE: Fill all 11 characters, eg. sizeof(bootSector->bsLabel);
+ //
+ bootSector->bsLabel[0] = 'R';
+ bootSector->bsLabel[1] = 'a';
+ bootSector->bsLabel[2] = 'm';
+ bootSector->bsLabel[3] = 'D';
+ bootSector->bsLabel[4] = 'i';
+ bootSector->bsLabel[5] = 's';
+ bootSector->bsLabel[6] = 'k';
+ bootSector->bsLabel[7] = ' ';
+ bootSector->bsLabel[8] = ' ';
+ bootSector->bsLabel[9] = ' ';
+ bootSector->bsLabel[10] = ' ';
+
+ //
+ // Set FileSystemType to "FAT1? "
+ // NOTE: Fill all 8 characters, eg. sizeof(bootSector->bsFileSystemType);
+ //
+ bootSector->bsFileSystemType[0] = 'F';
+ bootSector->bsFileSystemType[1] = 'A';
+ bootSector->bsFileSystemType[2] = 'T';
+ bootSector->bsFileSystemType[3] = '1';
+ bootSector->bsFileSystemType[4] = '?';
+ bootSector->bsFileSystemType[5] = ' ';
+ bootSector->bsFileSystemType[6] = ' ';
+ bootSector->bsFileSystemType[7] = ' ';
+
+ bootSector->bsFileSystemType[4] = ( fatType == 16 ) ? '6' : '2';
+
+ bootSector->bsSig2[0] = 0x55;
+ bootSector->bsSig2[1] = 0xAA;
+
+ //
+ // The FAT is located immediately following the boot sector.
+ //
+
+ firstFatSector = (PUCHAR)(bootSector + 1);
+ firstFatSector[0] = (UCHAR)devExt->DiskGeometry.MediaType;
+ firstFatSector[1] = 0xFF;
+ firstFatSector[2] = 0xFF;
+
+ if (fatType == 16) {
+ firstFatSector[3] = 0xFF;
+ }
+
+ //
+ // The Root Directory follows the FAT
+ //
+ rootDir = (PDIR_ENTRY)(bootSector + 1 + fatSectorCnt);
+
+ //
+ // Set device name to "MS-RAMDR"
+ // NOTE: Fill all 8 characters, eg. sizeof(rootDir->deName);
+ //
+ rootDir->deName[0] = 'M';
+ rootDir->deName[1] = 'S';
+ rootDir->deName[2] = '-';
+ rootDir->deName[3] = 'R';
+ rootDir->deName[4] = 'A';
+ rootDir->deName[5] = 'M';
+ rootDir->deName[6] = 'D';
+ rootDir->deName[7] = 'R';
+
+ //
+ // Set device extension name to "IVE"
+ // NOTE: Fill all 3 characters, eg. sizeof(rootDir->deExtension);
+ //
+ rootDir->deExtension[0] = 'I';
+ rootDir->deExtension[1] = 'V';
+ rootDir->deExtension[2] = 'E';
+
+ rootDir->deAttributes = DIR_ATTR_VOLUME;
+
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN
+RamDiskCheckParameters(
+ IN PDEVICE_EXTENSION devExt,
+ IN LARGE_INTEGER ByteOffset,
+ IN size_t Length
+ )
+
+{
+ //
+ // Check for invalid parameters. It is an error for the starting offset
+ // + length to go past the end of the buffer, or for the length to
+ // not be a proper multiple of the sector size.
+ //
+ // Others are possible, but we don't check them since we trust the
+ // file system.
+ //
+
+ if( devExt->DiskRegInfo.DiskSize < Length ||
+ ByteOffset.QuadPart < 0 || // QuadPart is signed so check for negative values
+ ((ULONGLONG)ByteOffset.QuadPart > (devExt->DiskRegInfo.DiskSize - Length)) ||
+ (Length & (devExt->DiskGeometry.BytesPerSector - 1))) {
+
+ //
+ // Do not give an I/O boost for parameter errors.
+ //
+
+ KdPrint((
+ "Error invalid parameter\n"
+ "ByteOffset: %I64x\n"
+ "Length: %lu\n",
+ ByteOffset.QuadPart,
+ Length
+ ));
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/storage/ramdisk/src/ramdisk.h b/storage/ramdisk/src/ramdisk.h
new file mode 100644
index 00000000..764e1094
--- /dev/null
+++ b/storage/ramdisk/src/ramdisk.h
@@ -0,0 +1,196 @@
+/*++
+
+Copyright (c) 1990-2003 Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ramdisk.h
+
+Abstract:
+
+ This file includes data declarations for the Ram Disk driver for NT.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+#ifndef _RAMDISK_H_
+#define _RAMDISK_H_
+
+#pragma warning(disable:4201) // nameless struct/union warning
+
+#include <ntddk.h>
+#include <ntdddisk.h>
+
+#pragma warning(default:4201)
+
+#include <wdf.h>
+#define NTSTRSAFE_LIB
+#include <ntstrsafe.h>
+#include "forward_progress.h"
+
+#define NT_DEVICE_NAME L"\\Device\\Ramdisk"
+#define DOS_DEVICE_NAME L"\\DosDevices\\"
+
+#define RAMDISK_TAG 'DmaR' // "RamD"
+#define DOS_DEVNAME_LENGTH (sizeof(DOS_DEVICE_NAME)+sizeof(WCHAR)*10)
+#define DRIVE_LETTER_LENGTH (sizeof(WCHAR)*10)
+
+#define DRIVE_LETTER_BUFFER_SIZE 10
+#define DOS_DEVNAME_BUFFER_SIZE (sizeof(DOS_DEVICE_NAME) / 2) + 10
+
+#define RAMDISK_MEDIA_TYPE 0xF8
+#define DIR_ENTRIES_PER_SECTOR 16
+
+#define DEFAULT_DISK_SIZE (1024*1024) // 1 MB
+#define DEFAULT_ROOT_DIR_ENTRIES 512
+#define DEFAULT_SECTORS_PER_CLUSTER 2
+#define DEFAULT_DRIVE_LETTER L"Z:"
+
+typedef struct _DISK_INFO {
+ ULONG DiskSize; // Ramdisk size in bytes
+ ULONG RootDirEntries; // No. of root directory entries
+ ULONG SectorsPerCluster; // Sectors per cluster
+ UNICODE_STRING DriveLetter; // Drive letter to be used
+} DISK_INFO, *PDISK_INFO;
+
+typedef struct _DEVICE_EXTENSION {
+ PUCHAR DiskImage; // Pointer to beginning of disk image
+ DISK_GEOMETRY DiskGeometry; // Drive parameters built by Ramdisk
+ DISK_INFO DiskRegInfo; // Disk parameters from the registry
+ UNICODE_STRING SymbolicLink; // Dos symbolic name; Drive letter
+ WCHAR DriveLetterBuffer[DRIVE_LETTER_BUFFER_SIZE];
+ WCHAR DosDeviceNameBuffer[DOS_DEVNAME_BUFFER_SIZE];
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, DeviceGetExtension)
+
+typedef struct _QUEUE_EXTENSION {
+ PDEVICE_EXTENSION DeviceExtension;
+} QUEUE_EXTENSION, *PQUEUE_EXTENSION;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_EXTENSION, QueueGetExtension)
+
+#pragma pack(1)
+
+typedef struct _BOOT_SECTOR
+{
+ UCHAR bsJump[3]; // x86 jmp instruction, checked by FS
+ CCHAR bsOemName[8]; // OEM name of formatter
+ USHORT bsBytesPerSec; // Bytes per Sector
+ UCHAR bsSecPerClus; // Sectors per Cluster
+ USHORT bsResSectors; // Reserved Sectors
+ UCHAR bsFATs; // Number of FATs - we always use 1
+ USHORT bsRootDirEnts; // Number of Root Dir Entries
+ USHORT bsSectors; // Number of Sectors
+ UCHAR bsMedia; // Media type - we use RAMDISK_MEDIA_TYPE
+ USHORT bsFATsecs; // Number of FAT sectors
+ USHORT bsSecPerTrack; // Sectors per Track - we use 32
+ USHORT bsHeads; // Number of Heads - we use 2
+ ULONG bsHiddenSecs; // Hidden Sectors - we set to 0
+ ULONG bsHugeSectors; // Number of Sectors if > 32 MB size
+ UCHAR bsDriveNumber; // Drive Number - not used
+ UCHAR bsReserved1; // Reserved
+ UCHAR bsBootSignature; // New Format Boot Signature - 0x29
+ ULONG bsVolumeID; // VolumeID - set to 0x12345678
+ CCHAR bsLabel[11]; // Label - set to RamDisk
+ CCHAR bsFileSystemType[8];// File System Type - FAT12 or FAT16
+ CCHAR bsReserved2[448]; // Reserved
+ UCHAR bsSig2[2]; // Originial Boot Signature - 0x55, 0xAA
+} BOOT_SECTOR, *PBOOT_SECTOR;
+
+typedef struct _DIR_ENTRY
+{
+ UCHAR deName[8]; // File Name
+ UCHAR deExtension[3]; // File Extension
+ UCHAR deAttributes; // File Attributes
+ UCHAR deReserved; // Reserved
+ USHORT deTime; // File Time
+ USHORT deDate; // File Date
+ USHORT deStartCluster; // First Cluster of file
+ ULONG deFileSize; // File Length
+} DIR_ENTRY, *PDIR_ENTRY;
+
+#pragma pack()
+
+//
+// Directory Entry Attributes
+//
+
+#define DIR_ATTR_READONLY 0x01
+#define DIR_ATTR_HIDDEN 0x02
+#define DIR_ATTR_SYSTEM 0x04
+#define DIR_ATTR_VOLUME 0x08
+#define DIR_ATTR_DIRECTORY 0x10
+#define DIR_ATTR_ARCHIVE 0x20
+
+DRIVER_INITIALIZE DriverEntry;
+
+#if KMDF_VERSION_MINOR >= 7
+
+EVT_WDF_DRIVER_DEVICE_ADD RamDiskEvtDeviceAdd;
+EVT_WDF_DEVICE_CONTEXT_CLEANUP RamDiskEvtDeviceContextCleanup;
+EVT_WDF_IO_QUEUE_IO_READ RamDiskEvtIoRead;
+EVT_WDF_IO_QUEUE_IO_WRITE RamDiskEvtIoWrite;
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL RamDiskEvtIoDeviceControl;
+
+#else
+
+NTSTATUS
+RamDiskEvtDeviceAdd(
+ IN WDFDRIVER Driver,
+ IN PWDFDEVICE_INIT DeviceInit
+ );
+
+VOID
+RamDiskEvtDeviceContextCleanup(
+ IN WDFOBJECT Device
+ );
+
+VOID
+RamDiskEvtIoRead(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ );
+
+VOID
+RamDiskEvtIoWrite(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t Length
+ );
+
+VOID
+RamDiskEvtIoDeviceControl(
+ IN WDFQUEUE Queue,
+ IN WDFREQUEST Request,
+ IN size_t OutputBufferLength,
+ IN size_t InputBufferLength,
+ IN ULONG IoControlCode
+ );
+
+#endif
+
+VOID
+RamDiskQueryDiskRegParameters(
+ _In_ PWSTR RegistryPath,
+ _In_ PDISK_INFO DiskRegInfo
+ );
+
+NTSTATUS
+RamDiskFormatDisk(
+ IN PDEVICE_EXTENSION DeviceExtension
+ );
+
+BOOLEAN
+RamDiskCheckParameters(
+ IN PDEVICE_EXTENSION devExt,
+ IN LARGE_INTEGER ByteOffset,
+ IN size_t Length
+ );
+
+#endif // _RAMDISK_H_
+
diff --git a/storage/ramdisk/src/ramdisk.inx b/storage/ramdisk/src/ramdisk.inx
new file mode 100644
index 00000000..40ad4b1b
--- /dev/null
+++ b/storage/ramdisk/src/ramdisk.inx
@@ -0,0 +1,102 @@
+; RAMDISK.INF
+; Windows installation file for installing the Ramdisk driver
+; Copyright (c) Microsoft Corporation All rights Reserved
+;
+; Installation Notes:
+;
+; Using Devcon: Type "devcon install ramdisk.inf Ramdisk" to install
+;
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFT%
+DriverVer=11/14/1999,5.00.2183.1
+CatalogFile=KmdfSamples.cat
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+[ClassInstall32]
+Addreg=SampleClassReg
+
+[SampleClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+
+[DiskCopyfiles]
+WdfRamdisk.sys
+
+[SourceDisksNames]
+1=%InstDisk%,
+
+[SourceDisksFiles]
+WdfRamdisk.sys=1
+
+[Manufacturer]
+%MSFT% = DiskDevice,NT$ARCH$
+
+; For XP and later
+[DiskDevice.NT$ARCH$]
+%DiskDevDesc% = DiskInstall, Ramdisk
+
+[DiskInstall.NT]
+CopyFiles = DiskCopyfiles
+
+[DiskInstall.NT.Services]
+AddService = Ramdisk, %SPSVCINST_ASSOCSERVICE%, DiskServiceInst
+
+[DiskServiceInst]
+ServiceType = %SERVICE_KERNEL_DRIVER%
+StartType = %SERVICE_DEMAND_START%
+ErrorControl = %SERVICE_ERROR_NORMAL%
+DisplayName = %DiskServiceDesc%
+ServiceBinary = %12%\WdfRamdisk.sys
+AddReg = DiskAddReg
+
+[DiskAddReg]
+HKR, "Parameters", "BreakOnEntry", %REG_DWORD%, 0x00000000
+HKR, "Parameters", "DiskSize", %REG_DWORD%, 0x00100000
+HKR, "Parameters", "DriveLetter", %REG_SZ%, "R:"
+HKR, "Parameters", "RootDirEntries", %REG_DWORD%, 0x00000200
+HKR, "Parameters", "SectorsPerCluster", %REG_DWORD%, 0x00000002
+
+
+;-------------- Coinstaller installation
+[DestinationDirs]
+CoInstaller_CopyFiles = 11
+
+[DiskInstall.NT.CoInstallers]
+AddReg=CoInstaller_AddReg
+CopyFiles=CoInstaller_CopyFiles
+
+[CoInstaller_CopyFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
+
+[SourceDisksFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
+
+[CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
+
+[DiskInstall.NT.Wdf]
+KmdfService = Ramdisk, Ramdisk_wdfsect
+[Ramdisk_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+
+[Strings]
+MSFT = "Microsoft"
+ClassName = "Sample Device"
+DiskDevDesc = "WDF Sample RAM disk Driver"
+DiskServiceDesc = "Ramdisk Driver"
+InstDisk = "Ramdisk Install Disk"
+;*******************************************
+;Handy macro substitutions (non-localizable)
+SPSVCINST_ASSOCSERVICE = 0x00000002
+SERVICE_KERNEL_DRIVER = 1
+SERVICE_DEMAND_START = 3
+SERVICE_ERROR_NORMAL = 1
+REG_DWORD = 0x00010001
+REG_SZ = 0x00000000
diff --git a/storage/ramdisk/src/ramdisk.rc b/storage/ramdisk/src/ramdisk.rc
new file mode 100644
index 00000000..1d0ded22
--- /dev/null
+++ b/storage/ramdisk/src/ramdisk.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Driver Frameworks Ramdisk Driver"
+#define VER_INTERNALNAME_STR "ramdisk.sys"
+#define VER_ORIGINALFILENAME_STR "ramdisk.sys"
+
+#include "common.ver"