📄 pgpmemlocknt.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
pgpMemLockNT.c - PGPmemlock kernel mode device driver for locking memory
$Id: pgpMemLockNT.c,v 1.3 2002/08/06 20:11:20 dallen Exp $
____________________________________________________________________________*/
#include "ntddk.h"
#include "stdarg.h"
#include "PGPsdkDriver.h"
#include "pgpMemLockNT.h"
#include "pgpMisc.h"
// ______________________________________________________
//
// internal memory allocation routines
static VOID
sHeapBlockInit (
IN PPGPMEMLOCKBLOCK pmlb)
{
ULONG i = 0;
PPGPMEMLOCKITEM pmli = NULL;
pmlb->pblockNext = NULL;
pmli = &(pmlb->item[0]);
for (i=1; i<NUMITEMSPERBLOCK; i++)
{
pmli->pitemNext = &(pmlb->item[i]);
pmli = pmli->pitemNext;
}
pmli->pitemNext = NULL;
}
static ULONG
sHeapInit (
IN PPGPMEMLOCK ppml)
{
ULONG i = 0;
PPGPMEMLOCKITEM pmli = NULL;
ppml->pblockHeap = pgpDriverSecureAlloc (sizeof(PGPMEMLOCKBLOCK));
if (ppml->pblockHeap)
{
sHeapBlockInit (ppml->pblockHeap);
ppml->pitemFreeList = &(ppml->pblockHeap->item[0]);
return TRUE;
}
else
return FALSE;
}
static VOID
sHeapDestroy (
IN PPGPMEMLOCK ppml)
{
PPGPMEMLOCKBLOCK pmlb = NULL;
PPGPMEMLOCKBLOCK pmlbNext = NULL;
pmlb = ppml->pblockHeap;
while (pmlb)
{
pmlbNext = pmlb->pblockNext;
pgpDriverSecureFree (pmlb);
pmlb = pmlbNext;
}
ppml->pblockHeap = NULL;
ppml->pitemFreeList = NULL;
}
static PPGPMEMLOCKITEM
sAllocateItem (
IN PPGPMEMLOCK ppml)
{
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKBLOCK pmlbNew = NULL;
// there is an item available
if (ppml->pitemFreeList)
{
// remove item from free list
pmli = ppml->pitemFreeList;
ppml->pitemFreeList = ppml->pitemFreeList->pitemNext;
return pmli;
}
// free list is empty, allocate more memory
pmlbNew = pgpDriverSecureAlloc (sizeof(PGPMEMLOCKBLOCK));
if (pmlbNew)
{
// insert block into linked list of blocks
pmlbNew->pblockNext = ppml->pblockHeap;
ppml->pblockHeap = pmlbNew;
// link new items into a list
sHeapBlockInit (pmlbNew);
// first item will be returned to caller
pmli = &(pmlbNew->item[0]);
// add rest of new items to free list
ppml->pitemFreeList = &(pmlbNew->item[1]);
return pmli;
}
// couldn't get an item
return NULL;
}
static VOID
sFreeItem (
IN PPGPMEMLOCK ppml,
IN PPGPMEMLOCKITEM pmli)
{
// add item to list of free items
pmli->pitemNext = ppml->pitemFreeList;
ppml->pitemFreeList = pmli;
}
// ______________________________________________________
//
// wipe the specified memory block
static VOID
sWipeBlock (
IN ULONG ulPage,
IN ULONG ulNumPages)
{
PVOID pmem;
ULONG ulBytes;
pmem = (PVOID)(ulPage << WIN32PAGESIZE);
ulBytes = ulNumPages << WIN32PAGESIZE;
memset (pmem, 0, ulBytes);
}
// ______________________________________________________
//
// add the specified memory block to list of blocks
static ULONG
sAddBlockToList (
IN PPGPMEMLOCK ppml,
IN PFILE_OBJECT pfo,
IN PVOID pCriticalSection,
IN ULONG ulPage,
IN ULONG ulNumPages,
IN PMDL pmdl)
{
PPGPMEMLOCKITEM pmli = NULL;
PEPROCESS peProcess = NULL;
ULONG bReturn = FALSE;
peProcess = PsGetCurrentProcess ();
pgpDriverEnterCriticalSection (pCriticalSection, MUTEX);
// allocate new item
pmli = sAllocateItem (ppml);
if (pmli)
{
// insert block information into item
pmli->peProcess = peProcess;
pmli->pfo = pfo;
pmli->ulPage = ulPage;
pmli->ulNumPages = ulNumPages;
pmli->pmdl = pmdl;
// insert item into list
pmli->pitemNext = ppml->pitemLockedList;
ppml->pitemLockedList = pmli;
bReturn = TRUE;
}
pgpDriverLeaveCriticalSection (pCriticalSection, MUTEX);
return bReturn;
}
// ______________________________________________________
//
// remove the specified memory page(s) from list of
// locked blocks and unlock the memory
static ULONG
sUnlockPage (
IN PPGPMEMLOCK ppml,
IN PFILE_OBJECT pfo,
IN PVOID pCriticalSection,
IN ULONG ulPage,
IN ULONG ulNumPages,
IN ULONG bUnlock)
{
PMDL pmdl = NULL;
PEPROCESS peProcess = NULL;
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKITEM pitemPrev = NULL;
ULONG bReturn = FALSE;
peProcess = PsGetCurrentProcess ();
pgpDriverEnterCriticalSection (pCriticalSection, MUTEX);
// search list for specified block
pitemPrev = NULL;
pmli = ppml->pitemLockedList;
while (pmli)
{
if ((pmli->peProcess == peProcess) &&
(pmli->pfo == pfo))
{
if ((pmli->ulPage == ulPage) &&
(pmli->ulNumPages == ulNumPages))
{
if (pitemPrev)
{
pitemPrev->pitemNext = pmli->pitemNext;
}
else
{
ppml->pitemLockedList = pmli->pitemNext;
}
pmdl = pmli->pmdl;
sFreeItem (ppml, pmli);
bReturn = TRUE;
break;
}
}
pitemPrev = pmli;
pmli = pmli->pitemNext;
}
pgpDriverLeaveCriticalSection (pCriticalSection, MUTEX);
// unlock pages and discard MDL
if (bUnlock && pmdl)
{
sWipeBlock (ulPage, ulNumPages);
MmUnlockPages (pmdl);
IoFreeMdl (pmdl);
}
return bReturn;
}
// ______________________________________________________
//
// lock the pages in the specified virtual address range
static ULONG
sLockTheMemory(
IN PPGPMEMLOCK ppml,
IN PPGPMEMLOCKSTRUCT ppmls,
IN PFILE_OBJECT pfo,
IN PVOID pCriticalSection)
{
PMDL pmdl = NULL;
ULONG ulPage = 0;
ULONG ulNumPages = 0;
PGPdbgVerbosePrint (("PGPutil: sLockTheMemory.\n"));
// assume no error
ppmls->ulError = kPGPUDError_NoErr;
// allocate and initialize a Memory Descriptor List
pmdl = IoAllocateMdl(ppmls->pMem, ppmls->ulNumBytes, FALSE, FALSE, NULL);
if (pmdl == NULL)
{
PGPdbgPrint (("PGPutil: Err: IoAllocateMdl failed.\n"));
ppmls->ulError = kPGPUDError_MemAllocError;
goto done;
}
// calculate page numbers
ulPage = ((ULONG)(ppmls->pMem)) >> WIN32PAGESIZE;
ulNumPages = (((ppmls->ulNumBytes)-1) >> WIN32PAGESIZE ) +1;
PGPdbgVerbosePrint (("PGPutil: locking page(s) %x - %x.\n",
ulPage, ulPage+ulNumPages-1));
// add this block to the array of locked blocks
if (!sAddBlockToList (ppml, pfo, pCriticalSection, ulPage, ulNumPages, pmdl))
{
// we couldn't allocate a new list item
PGPdbgPrint (("PGPutil: Err: sAddBlockToList failed.\n"));
ppmls->ulError = kPGPUDError_LockListError;
// free the mdl we allocated,
IoFreeMdl(pmdl);
goto done;
}
// try to lock down the client's area
__try {
MmProbeAndLockPages (pmdl, UserMode, IoModifyAccess);
} __except(EXCEPTION_EXECUTE_HANDLER) {
// client must have passed a bad address, or it exceeded its quota
PGPdbgPrint (("PGPutil: Err: MmProbeAndLockPages failed.\n"));
ppmls->ulError = kPGPUDError_MemLockError;
// remove block from array and free the MDL we allocated,
sUnlockPage (ppml, pfo, pCriticalSection, ulPage, ulNumPages, FALSE);
IoFreeMdl (pmdl);
goto done;
}
return TRUE;
done:
return FALSE;
}
// ______________________________________________________
//
// unlock the pages in the specified virtual address range
static ULONG
sUnlockTheMemory(
IN PPGPMEMLOCK ppml,
IN PPGPMEMLOCKSTRUCT ppmls,
IN PFILE_OBJECT pfo,
IN PVOID pCriticalSection)
{
ULONG ulPage = 0;
ULONG ulNumPages = 0;
PGPdbgVerbosePrint (("PGPutil: sUnlockTheMemory.\n"));
// assume no error
ppmls->ulError = kPGPUDError_NoErr;
// calculate page numbers
ulPage = ((ULONG)(ppmls->pMem)) >> WIN32PAGESIZE;
ulNumPages = (((ppmls->ulNumBytes)-1) >> WIN32PAGESIZE ) +1;
PGPdbgVerbosePrint (("PGPutil: unlocking page(s) %x - %x.\n",
ulPage, ulPage+ulNumPages-1));
// unlock the pages
if (!sUnlockPage (ppml, pfo, pCriticalSection, ulPage, ulNumPages, TRUE))
{
// we couldn't unlock the memory
PGPdbgPrint (("PGPutil: Err: sUnlockPage failed.\n"));
ppmls->ulError = kPGPUDError_MemUnlockError;
return FALSE;
}
return TRUE;
}
// ______________________________________________________
//
// process the DeviceIOControl message from the attached application
VOID
pgpMemlockProcessOperation (
IN PPGPMEMLOCK ppml,
IN PPGPMEMLOCKSTRUCT ppmls,
IN PFILE_OBJECT pfo,
IN ULONG ulStatusFlags,
IN PVOID pCriticalSection)
{
if (!(ulStatusFlags & kPGPUDFlag_MemlockInitialized))
{
ppmls->ulError = kPGPUDError_DriverUninitialized;
return;
}
switch (ppmls->ulOperation) {
case kPGPUDOperation_LockMemory :
if (sLockTheMemory (ppml, ppmls, pfo, pCriticalSection))
PGPdbgVerbosePrint (("PGPutil: memory successfully locked.\n"));
else
PGPdbgPrint (("PGPutil: Err: memory lock failed.\n"));
break;
case kPGPUDOperation_UnlockMemory:
if (sUnlockTheMemory (ppml, ppmls, pfo, pCriticalSection))
PGPdbgVerbosePrint (("PGPutil: memory successfully unlocked.\n"));
else
PGPdbgPrint (("PGPutil: Err: memory unlock failed.\n"));
break;
default :
ppmls->ulError = kPGPUDError_UndefinedOperation;
break;
}
}
// ______________________________________________________
//
// initialize the memlock routines
ULONG
pgpMemlockInit (
IN PPGPMEMLOCK ppml)
{
ppml->pitemLockedList = NULL;
return sHeapInit (ppml);
}
// ______________________________________________________
//
// remove all of this handle's memory blocks from
// list of blocks and unlock the memory
VOID
pgpMemlockCleanupHandle (
IN PPGPMEMLOCK ppml,
IN PFILE_OBJECT pfo,
IN PVOID pCriticalSection)
{
PEPROCESS peProcess = NULL;
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKITEM pitemNext = NULL;
PPGPMEMLOCKITEM pitemPrev = NULL;
peProcess = PsGetCurrentProcess ();
// first wipe any blocks belonging to this handle
pmli = ppml->pitemLockedList;
while (pmli)
{
if ((pmli->peProcess == peProcess) &&
(pmli->pfo == pfo))
{
sWipeBlock (pmli->ulPage, pmli->ulNumPages);
}
pmli = pmli->pitemNext;
}
pgpDriverEnterCriticalSection (pCriticalSection, MUTEX);
// search list for items belonging to this handle
// and unlock/free them
pitemPrev = NULL;
pmli = ppml->pitemLockedList;
while (pmli)
{
if ((pmli->peProcess == peProcess) &&
(pmli->pfo == pfo))
{
if (pitemPrev)
{
pitemPrev->pitemNext = pmli->pitemNext;
}
else
{
ppml->pitemLockedList = pmli->pitemNext;
}
pitemNext = pmli->pitemNext;
MmUnlockPages (pmli->pmdl);
IoFreeMdl (pmli->pmdl);
sFreeItem (ppml, pmli);
pmli = pitemNext;
}
else
{
pitemPrev = pmli;
pmli = pmli->pitemNext;
}
}
pgpDriverLeaveCriticalSection (pCriticalSection, MUTEX);
}
// ______________________________________________________
//
// remove all locked memory blocks from
// list of blocks and unlock the memory
VOID
pgpMemlockCleanup (
IN PPGPMEMLOCK ppml,
IN PVOID pCriticalSection)
{
PPGPMEMLOCKITEM pmli = NULL;
PPGPMEMLOCKITEM pitemNext = NULL;
// first wipe all blocks
pmli = ppml->pitemLockedList;
while (pmli)
{
sWipeBlock (pmli->ulPage, pmli->ulNumPages);
pmli = pmli->pitemNext;
}
pgpDriverEnterCriticalSection (pCriticalSection, MUTEX);
// now unlock blocks and destroy list
pmli = ppml->pitemLockedList;
while (pmli)
{
pitemNext = pmli->pitemNext;
MmUnlockPages (pmli->pmdl);
IoFreeMdl (pmli->pmdl);
sFreeItem (ppml, pmli);
pmli = pitemNext;
}
ppml->pitemLockedList = NULL;
pgpDriverLeaveCriticalSection (pCriticalSection, MUTEX);
sHeapDestroy (ppml);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -