Example #1
0
//----------------------------------------------------------------------
//
// RegmonMapServiceTable
//
// If we are running on Whistler then we have
// to double map the system service table to get around the 
// fact that the system service table is write-protected on systems
// with > 128MB memory. Since there's no harm in always double mapping,
// we always do it, regardless of whether or not we are on Whistler.
//
//----------------------------------------------------------------------
PVOID *
RegmonMapServiceTable(
    SERVICE_HOOK_DESCRIPTOR **HookDescriptors
    )
{
    //
    // Allocate an array to store original function addresses in. This
    // makes us play well with other hookers.
    //
    *HookDescriptors = (SERVICE_HOOK_DESCRIPTOR *) ExAllocatePool( NonPagedPool,
                          KeServiceDescriptorTable->Limit * sizeof(SERVICE_HOOK_DESCRIPTOR));
    if( !*HookDescriptors ) {

        return NULL;
    }
    memset( *HookDescriptors, 0, 
            KeServiceDescriptorTable->Limit * sizeof(SERVICE_HOOK_DESCRIPTOR));

    //
    // Build an MDL that describes the system service table function 
    // pointers array.
    //
    KdPrint(("Reglib: KeServiceDescriptorTable: %I64x Pointers: %I64x Limit: %d\n",
              KeServiceDescriptorTable, KeServiceDescriptorTable->ServicePointers,
              KeServiceDescriptorTable->Limit ));
    KeServiceTableMdl = MmCreateMdl( NULL, KeServiceDescriptorTable->ServicePointers, 
                                     KeServiceDescriptorTable->Limit * sizeof(PVOID));
    if( !KeServiceTableMdl ) {

        return NULL;
    }

    //
    // Fill in the physical pages and then double-map the description. Note
    // that MmMapLockedPages is obsolete as of Win2K and has been replaced
    // with MmMapLockedPagesSpecifyCache. However, we use the same driver
    // on all NT platforms, so we use it anyway.
    //
    MmBuildMdlForNonPagedPool( KeServiceTableMdl );
    KeServiceTableMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
#if defined(_M_IA64)
    return MmMapLockedPagesSpecifyCache( KeServiceTableMdl, KernelMode, 
                                         MmCached, NULL, FALSE, NormalPagePriority );
#else
    return MmMapLockedPages( KeServiceTableMdl, KernelMode );
#endif
}
Example #2
0
NTSTATUS initMDL()
{  
   // map memory into our domain
   g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, 
                               KeServiceDescriptorTable.NumberOfServices*4);
   if(!g_pmdlSystemCall)
      return STATUS_UNSUCCESSFUL;

   MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

   // change MDL permissions
   g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
   MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
   
   MDLinit = TRUE;

   return STATUS_SUCCESS;
}
/**
*  设置钩子函数
*
*/
NTSTATUS  sstHook_OpenProcess()
{
    if(m_MDL == NULL)
	{
		m_MDL = MmCreateMdl(NULL,KeServiceDescriptorTable->ServiceTableBase,KeServiceDescriptorTable->NumberOfService*4);

		if(!m_MDL)
			return STATUS_UNSUCCESSFUL;

		MmBuildMdlForNonPagedPool(m_MDL);
		m_MDL->MdlFlags = m_MDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
		m_Mapped = (PVOID *)MmMapLockedPages(m_MDL, KernelMode);
		HOOK_SYSCALL(ZwOpenProcess,MyNtOpenProcess,pOriNtOpenProcess);
		g_openProcessId = (ULONG)SYSTEMSERVICE(ZwOpenProcess);

		return STATUS_SUCCESS;
	}

	UpdateService(SYSCALL_INDEX(ZwOpenProcess),(PVOID)MyNtOpenProcess);
	return STATUS_SUCCESS;
}
Example #4
0
//----------------------------------------------------------------------
//
// RegmonMapMem
//
// Double maps memory for writing.
//
//----------------------------------------------------------------------
PVOID 
RegmonMapMem( 
    PVOID Pointer, 
    ULONG Length, 
    PMDL *MapMdl 
    )
{
    *MapMdl = MmCreateMdl( NULL, Pointer, Length );
    if( !(*MapMdl)) {

        return NULL;
    }

    MmBuildMdlForNonPagedPool( *MapMdl );
    (*MapMdl)->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
#if defined(_M_IA64)
    return MmMapLockedPagesSpecifyCache( *MapMdl, KernelMode, 
                                         MmCached, NULL, FALSE, NormalPagePriority );
#else
    return MmMapLockedPages( *MapMdl, KernelMode );
#endif
}
Example #5
0
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath)
{
   DriverObject->DriverUnload  = OnUnload;

   DbgPrint("Driver cargado");
   ZwOpenProcessIni =(TypZwOpenProc)(SYSTEMSERVICE(ZwOpenProcess));

   //Creamos la MDL para deshabilitar la protección de memoria
   g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
   if(!g_pmdlSystemCall)
      return STATUS_UNSUCCESSFUL;

   MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

   g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

   MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);


   DbgPrint("Hookeando...");
   HOOK_SYSCALL( ZwOpenProcess, NewZwOpenProcess, ZwOpenProcessIni );

   return STATUS_SUCCESS;
}
Example #6
0
NTSTATUS
AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    LARGE_INTEGER cacheSizeBytes;
    AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    OBJECT_ATTRIBUTES   stObjectAttribs;
    IO_STATUS_BLOCK stIoStatus;
    UNICODE_STRING uniServiceName;

    __Enter
    {

        //
        // First this is to load the library
        //

        RtlInitUnicodeString( &uniServiceName,
                              AFS_REDIR_LIBRARY_SERVICE_ENTRY);

        ntStatus = AFSLoadLibrary( 0,
                                   &uniServiceName);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n",
                          ntStatus);

            try_return( ntStatus);
        }

        //
        // Save off the cache file information
        //

        pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize;

        pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount;

        pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength;

        cacheSizeBytes = RedirInitInfo->ExtentCount;
        cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize;

        AFSDumpFileLocation.Length = 0;

        AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR));

        AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
                                                                        AFSDumpFileLocation.MaximumLength,
                                                                        AFS_GENERIC_MEMORY_23_TAG);

        if( AFSDumpFileLocation.Buffer == NULL)
        {

            AFSDbgLogMsg( AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n");

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlCopyMemory( AFSDumpFileLocation.Buffer,
                       L"\\??\\",
                       4 * sizeof( WCHAR));

        AFSDumpFileLocation.Length = 4 * sizeof( WCHAR);

        RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)],
                       (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset),
                       RedirInitInfo->DumpFileLocationLength);

        AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength;

        //
        // Be sure the shutdown flag is not set
        //

        ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);

        //
        // Set up the Throttles.
        //
        // Max IO is 10% of the cache, or the value in the registry,
        // with a minimum of 5Mb (and a maximum of 50% cache size)
        //
        if( AFSMaxDirectIo)
        {
            //
            // collect what the user
            //
            pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo;
            pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024);

        }
        else
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
        }

        if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204))
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204;

        }

        //
        // For small cache configurations ...
        //

        if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2)
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart  = cacheSizeBytes.QuadPart / 2;
        }

        //
        // Maximum Dirty is 50% of the cache, or the value in the
        // registry.  No minimum, maximum of 90% of cache size.
        //
        if (AFSMaxDirtyFile)
        {

            pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile;
            pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024);

        }
        else
        {

            pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2;

        }

        cacheSizeBytes.QuadPart *= 9;
        cacheSizeBytes.QuadPart  = cacheSizeBytes.QuadPart / 10;

        if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart)
        {
            pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart;
        }

        //
        // Store off any flags for the file system
        //

        if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES))
        {

            //
            // Hide files which begin with .
            //

            SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES);
        }

        if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
            RedirInitInfo->MemoryCacheLength.QuadPart != 0)
        {

            ntStatus = STATUS_INSUFFICIENT_RESOURCES;

#ifdef AMD64
            pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
                                                          (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
                                                          RedirInitInfo->MemoryCacheLength.QuadPart);
#else
            pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
                                                          (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
                                                          RedirInitInfo->MemoryCacheLength.LowPart);
#endif

            if( pDevExt->Specific.RDR.CacheMdl != NULL)
            {

                __try
                {

                    MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
                                         KernelMode,
                                         IoModifyAccess);

                    pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
                                                                                           NormalPagePriority);
                }
                __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
                {
                    IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
                    pDevExt->Specific.RDR.CacheMdl = NULL;
                }

                if( pDevExt->Specific.RDR.CacheMdl != NULL)
                {
                    pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
                    ntStatus = STATUS_SUCCESS;
                }

            }
        }
Example #7
0
NTSTATUS
MiCcPrepareReadInfo (
    IN PMI_READ_INFO MiReadInfo
    )

/*++

Routine Description:

    This routine constructs MDLs that describe the pages in the argument
    read-list. The caller will then issue the I/O on return.

Arguments:

    MiReadInfo - Supplies a pointer to the read-list.

Return Value:

    Various NTSTATUS codes.

Environment:

    Kernel mode, PASSIVE_LEVEL.

--*/

{
    UINT64 PteOffset;
    NTSTATUS Status;
    PMMPTE ProtoPte;
    PMMPTE LastProto;
    PMMPTE *ProtoPteArray;
    PCONTROL_AREA ControlArea;
    PSUBSECTION Subsection;
    PMMINPAGE_SUPPORT InPageSupport;
    PMDL Mdl;
    PMDL IoMdl;
    PMDL ApiMdl;
    ULONG i;
    PFN_NUMBER NumberOfPages;

    ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);

    NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (MiReadInfo->FileOffset.LowPart, MiReadInfo->LengthInBytes);

    //
    // Translate the section object into the relevant control area.
    //

    ControlArea = (PCONTROL_AREA)MiReadInfo->FileObject->SectionObjectPointer->DataSectionObject;

    //
    // If the section is backed by a ROM, then there's no need to prefetch
    // anything as it would waste RAM.
    //

    if (ControlArea->u.Flags.Rom == 1) {
        return STATUS_NOT_SUPPORTED;
    }

    //
    // Initialize the internal Mi readlist.
    //

    MiReadInfo->ControlArea = ControlArea;

    //
    // Allocate and initialize an inpage support block for this run.
    //

    InPageSupport = MiGetInPageSupportBlock (MM_NOIRQL, &Status);
    
    if (InPageSupport == NULL) {
        ASSERT (!NT_SUCCESS (Status));
        return Status;
    }
    
    MiReadInfo->InPageSupport = InPageSupport;

    //
    // Allocate and initialize an MDL to return to our caller.  The actual
    // frame numbers are filled in when all the pages are reference counted.
    //

    ApiMdl = MmCreateMdl (NULL, NULL, NumberOfPages << PAGE_SHIFT);

    if (ApiMdl == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    ApiMdl->MdlFlags |= MDL_PAGES_LOCKED;

    MiReadInfo->ApiMdl = ApiMdl;

    //
    // Allocate and initialize an MDL to use for the actual transfer (if any).
    //

    IoMdl = MmCreateMdl (NULL, NULL, NumberOfPages << PAGE_SHIFT);

    if (IoMdl == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MiReadInfo->IoMdl = IoMdl;
    Mdl = IoMdl;

    //
    // Make sure the section is really prefetchable - physical and
    // pagefile-backed sections are not.
    //

    if ((ControlArea->u.Flags.PhysicalMemory) ||
        (ControlArea->u.Flags.Image == 1) ||
        (ControlArea->FilePointer == NULL)) {

        return STATUS_INVALID_PARAMETER_1;
    }

    //
    // Start the read at the proper file offset.
    //

    InPageSupport->ReadOffset = MiReadInfo->FileOffset;
    ASSERT (BYTE_OFFSET (InPageSupport->ReadOffset.LowPart) == 0);
    InPageSupport->FilePointer = MiReadInfo->FileObject;

    //
    // Stash a pointer to the start of the prototype PTE array (the values
    // in the array are not contiguous as they may cross subsections)
    // in the inpage block so we can walk it quickly later when the pages
    // are put into transition.
    //

    ProtoPteArray = (PMMPTE *)(Mdl + 1);

    InPageSupport->BasePte = (PMMPTE) ProtoPteArray;

    //
    // Data (but not image) reads use the whole page and the filesystems
    // zero fill any remainder beyond valid data length so we don't
    // bother to handle this here.  It is important to specify the
    // entire page where possible so the filesystem won't post this
    // which will hurt perf.  LWFIX: must use CcZero to make this true.
    //

    ASSERT (((ULONG_PTR)Mdl & (sizeof(QUAD) - 1)) == 0);
    InPageSupport->u1.e1.PrefetchMdlHighBits = ((ULONG_PTR)Mdl >> 3);

    //
    // Initialize the prototype PTE pointers.
    //

    ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 0);

    if (ControlArea->u.Flags.Rom == 0) {
        Subsection = (PSUBSECTION)(ControlArea + 1);
    }
    else {
        Subsection = (PSUBSECTION)((PLARGE_CONTROL_AREA)ControlArea + 1);
    }

#if DBG
    if (MiCcDebug & MI_CC_FORCE_PREFETCH) {
        MiRemoveUserPages ();
    }
#endif

    //
    // Calculate the first prototype PTE address.
    //

    PteOffset = (UINT64)(MiReadInfo->FileOffset.QuadPart >> PAGE_SHIFT);

    //
    // Make sure the PTEs are not in the extended part of the segment.
    //

    while (TRUE) {
            
        //
        // A memory barrier is needed to read the subsection chains
        // in order to ensure the writes to the actual individual
        // subsection data structure fields are visible in correct
        // order.  This avoids the need to acquire any stronger
        // synchronization (ie: PFN lock), thus yielding better
        // performance and pageability.
        //

        KeMemoryBarrier ();

        if (PteOffset < (UINT64) Subsection->PtesInSubsection) {
            break;
        }

        PteOffset -= Subsection->PtesInSubsection;
        Subsection = Subsection->NextSubsection;
    }

    Status = MiAddViewsForSectionWithPfn ((PMSUBSECTION) Subsection,
                                          Subsection->PtesInSubsection);

    if (!NT_SUCCESS (Status)) {
        return Status;
    }

    MiReadInfo->FirstReferencedSubsection = Subsection;
    MiReadInfo->LastReferencedSubsection = Subsection;

    ProtoPte = &Subsection->SubsectionBase[PteOffset];
    LastProto = &Subsection->SubsectionBase[Subsection->PtesInSubsection];

    for (i = 0; i < NumberOfPages; i += 1) {

        //
        // Calculate which PTE maps the given logical block offset.
        //
        // Always look forwards (as an optimization) in the subsection chain.
        //
        // A quick check is made first to avoid recalculations and loops where
        // possible.
        //
    
        if (ProtoPte >= LastProto) {

            //
            // Handle extended subsections.  Increment the view count for
            // every subsection spanned by this request, creating prototype
            // PTEs if needed.
            //

            ASSERT (i != 0);

            Subsection = Subsection->NextSubsection;

            Status = MiAddViewsForSectionWithPfn ((PMSUBSECTION) Subsection,
                                                  Subsection->PtesInSubsection);

            if (!NT_SUCCESS (Status)) {
                return Status;
            }

            MiReadInfo->LastReferencedSubsection = Subsection;

            ProtoPte = Subsection->SubsectionBase;

            LastProto = &Subsection->SubsectionBase[Subsection->PtesInSubsection];
        }

        *ProtoPteArray = ProtoPte;
        ProtoPteArray += 1;

        ProtoPte += 1;
    }

    return STATUS_SUCCESS;
}
Example #8
0
NTSTATUS
AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
{

    NTSTATUS ntStatus = STATUS_SUCCESS;
    LARGE_INTEGER cacheSizeBytes;
    AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
    OBJECT_ATTRIBUTES   stObjectAttribs;
    IO_STATUS_BLOCK stIoStatus;
    UNICODE_STRING uniServiceName;

    __Enter
    {

        //
        // First this is to load the library
        //

        RtlInitUnicodeString( &uniServiceName,
                              AFS_REDIR_LIBRARY_SERVICE_ENTRY);

        ntStatus = AFSLoadLibrary( 0,
                                   &uniServiceName);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n",
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // Save off the cache file information
        //

        pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize;

        pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount;

        pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength;

        cacheSizeBytes = RedirInitInfo->ExtentCount;
        cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize;

        AFSDumpFileLocation.Length = 0;

        AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR));

        AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
                                                                        AFSDumpFileLocation.MaximumLength,
                                                                        AFS_GENERIC_MEMORY_23_TAG);

        if( AFSDumpFileLocation.Buffer == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"));

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlCopyMemory( AFSDumpFileLocation.Buffer,
                       L"\\??\\",
                       4 * sizeof( WCHAR));

        AFSDumpFileLocation.Length = 4 * sizeof( WCHAR);

        RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)],
                       (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset),
                       RedirInitInfo->DumpFileLocationLength);

        AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength;

        //
        // Be sure the shutdown flag is not set
        //

        ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);

        //
        // Set up the Throttles.
        //
        // Max IO is 10% of the cache, or the value in the registry,
        // with a minimum of 5Mb (and a maximum of 50% cache size)
        //
        if( AFSMaxDirectIo)
        {
            //
            // collect what the user
            //
            pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo;
            pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024);

        }
        else
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
        }

        if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204))
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204;

        }

        //
        // For small cache configurations ...
        //

        if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2)
        {

            pDevExt->Specific.RDR.MaxIo.QuadPart  = cacheSizeBytes.QuadPart / 2;
        }

        //
        // Maximum Dirty is 50% of the cache, or the value in the
        // registry.  No minimum, maximum of 90% of cache size.
        //
        if (AFSMaxDirtyFile)
        {

            pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile;
            pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024);

        }
        else
        {

            pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2;

        }

        cacheSizeBytes.QuadPart *= 9;
        cacheSizeBytes.QuadPart  = cacheSizeBytes.QuadPart / 10;

        if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart)
        {
            pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart;
        }

        //
        // Store off any flags for the file system
        //

        if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES))
        {

            //
            // Hide files which begin with .
            //

            SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES);
        }

        if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES))
        {

            //
            // Hide files which begin with .
            //

            SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES);
        }

        //
	// Global Reparse Point Policy
	//

	pDevExt->Specific.RDR.ReparsePointPolicy = RedirInitInfo->GlobalReparsePointPolicy;

	//
        // Are we performing direct to service IO?
        //

        if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO))
        {

            //
            // Send IO requests directly to service
            //

            SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO);
        }
        else
        {

            if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
                RedirInitInfo->MemoryCacheLength.QuadPart != 0)
            {

                ntStatus = STATUS_INSUFFICIENT_RESOURCES;

#ifdef AMD64
                pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
                                                              (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
                                                              RedirInitInfo->MemoryCacheLength.QuadPart);
#else
                pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
                                                              (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
                                                              RedirInitInfo->MemoryCacheLength.LowPart);
#endif

                if( pDevExt->Specific.RDR.CacheMdl != NULL)
                {

                    __try
                    {

                        MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
                                             KernelMode,
                                             IoModifyAccess);

                        pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
                                                                                               NormalPagePriority);
                    }
                    __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
                    {

                        AFSDumpTraceFilesFnc();

                        IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
                        pDevExt->Specific.RDR.CacheMdl = NULL;
                    }

                    if( pDevExt->Specific.RDR.CacheMdl != NULL)
                    {
                        pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
                        ntStatus = STATUS_SUCCESS;
                    }

                }
            }

            if( !NT_SUCCESS( ntStatus) &&
                RedirInitInfo->CacheFileNameLength == 0)
            {

                AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                              AFS_TRACE_LEVEL_ERROR,
                              "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
                              ntStatus));

                try_return( ntStatus);
            }

            if( pDevExt->Specific.RDR.CacheMdl == NULL)
            {

                if( RedirInitInfo->CacheFileNameLength == 0)
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSInitializeRedirector CacheMdl == NULL\n"));

                    try_return( ntStatus = STATUS_INVALID_PARAMETER);
                }

                //
                // Go open the cache file
                //

                pDevExt->Specific.RDR.CacheFile.Length = 0;
                pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));

                pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
                                                                                            pDevExt->Specific.RDR.CacheFile.MaximumLength,
                                                                                            AFS_GENERIC_MEMORY_24_TAG);

                if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n"));

                    try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
                }

                RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
                               L"\\??\\",
                               4 * sizeof( WCHAR));

                pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);

                RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
                               RedirInitInfo->CacheFileName,
                               RedirInitInfo->CacheFileNameLength);

                pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;

                InitializeObjectAttributes( &stObjectAttribs,
                                            &pDevExt->Specific.RDR.CacheFile,
                                            OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                                            NULL,
                                            NULL);

                ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
                                       GENERIC_READ | GENERIC_WRITE,
                                       &stObjectAttribs,
                                       &stIoStatus,
                                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                                       FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
                                  ntStatus));

                    try_return( ntStatus);
                }

                //
                // Map to the fileobject
                //

                ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
                                                      SYNCHRONIZE,
                                                      NULL,
                                                      KernelMode,
                                                      (void **)&pDevExt->Specific.RDR.CacheFileObject,
                                                      NULL);

                if( !NT_SUCCESS( ntStatus))
                {

                    AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
                                  AFS_TRACE_LEVEL_ERROR,
                                  "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
                                  ntStatus));

                    try_return( ntStatus);
                }
            }
        }
/*
 * DriverEntry initializes the driver and is the first routine called by the
 * system after the driver is loaded. DriverEntry specifies the other entry
 * points in the function driver, such as EvtDevice and DriverUnload.
 *
 * @param DriverObject - represents the instance of the function driver that is loaded
 *   into memory. DriverEntry must initialize members of DriverObject before it
 *   returns to the caller. DriverObject is allocated by the system before the
 *   driver is loaded, and it is released by the system after the system unloads
 *   the function driver from memory.
 * @param RegistryPath - represents the driver specific path in the Registry.
 *   The function driver can use the path to store driver related data between
 *   reboots. The path does not store hardware instance specific data.
 *
 * @return STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise
 */
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT pDriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    // Local variables
    NTSTATUS          status;
	PDEVICE_EXTENSION devExt;
	PDEVICE_OBJECT    devObj;
	UNICODE_STRING    devName;
	UNICODE_STRING    linkName;
	int               counter;

	DbgPrint("%s - version %s", NAME, VERSION);
	DbgPrint("Built %s %s\n", __DATE__, __TIME__);

	// Set the basic dispatch routines for all IRPs handled
	for (counter = 0; counter < IRP_MJ_MAXIMUM_FUNCTION; counter++)
	{
		pDriverObject->MajorFunction[counter] = OutboundDispatchPassDown;
	}

	// Set a specific dispatch routine for read requests
	pDriverObject->MajorFunction[IRP_MJ_READ] = OutboundDispatchRead;

	// Hook the keyboard stack
	status = OutboundHookKeyboard(pDriverObject);
	if (!NT_SUCCESS(status))
		DbgPrint("Error hooking the keyboard.\n");
	else
		DbgPrint("Successfully hooked the keyboard.\n");

	// Save old system call locations
	OldZwWriteFile = (ZWWRITEFILE)(SYSTEMSERVICE(ZwWriteFile));
	OldZwCreateFile = (ZWCREATEFILE)(SYSTEMSERVICE(ZwCreateFile));

	//***Begin HideProcessHookMDL SSDT hook code***

	// Map the memory into our domain so we can change the permissions on the MDL.
	g_pmdlSystemCall = MmCreateMdl(NULL,
								KeServiceDescriptorTable.ServiceTableBase,
								KeServiceDescriptorTable.NumberOfServices * 4);
    if(!g_pmdlSystemCall)
	{
	    DbgPrint("Failed mapping memory...");
		return STATUS_UNSUCCESSFUL;
	}

	MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

	// Change the flags of the MDL
	g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); //TODO: use MmMapLockedPagesSpecifyCache instead, MmMapLockedPages is obselete according to OACR

	// Hook the system call
	_asm{cli}
	HOOK_SYSCALL(ZwWriteFile, NewZwWriteFile, OldZwWriteFile);
	HOOK_SYSCALL(ZwCreateFile, NewZwCreateFile, OldZwCreateFile);
	_asm{sti}

	//***End HideProcessHookMDL SSDT hook code***

	// Set the driver unload routine
	pDriverObject->DriverUnload = Unload;

	return STATUS_SUCCESS;
} // DriverEntry