diff options
| author | Dave Wilson <[email protected]> | 2015-04-29 09:48:49 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-04-29 10:47:29 -0700 |
| commit | d40232638faaab19de557e70a3ee938da7a35295 (patch) | |
| tree | 14e61c973745949af186b7940e3a53d25322f5de /storage/ramdisk/src | |
| parent | 02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff) | |
samples update for //build
Diffstat (limited to 'storage/ramdisk/src')
| -rw-r--r-- | storage/ramdisk/src/WdfRamdisk.vcxproj | 160 | ||||
| -rw-r--r-- | storage/ramdisk/src/WdfRamdisk.vcxproj.Filters | 42 | ||||
| -rw-r--r-- | storage/ramdisk/src/forward_progress.c | 347 | ||||
| -rw-r--r-- | storage/ramdisk/src/forward_progress.h | 52 | ||||
| -rw-r--r-- | storage/ramdisk/src/ramdisk.c | 898 | ||||
| -rw-r--r-- | storage/ramdisk/src/ramdisk.h | 196 | ||||
| -rw-r--r-- | storage/ramdisk/src/ramdisk.inx | 102 | ||||
| -rw-r--r-- | storage/ramdisk/src/ramdisk.rc | 11 |
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" |
