예제 #1
0
//----------------------------------------------------------------------
//
// RegmonFreeHashEntry
//
// When we see a file close, we can free the string we had associated
// with the fileobject being closed since we know it won't be used
// again.
//
//----------------------------------------------------------------------
VOID 
RegmonFreeHashEntry( 
    HKEY hkey 
    )
{
    PHASH_ENTRY		hashEntry, prevEntry;

    Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );

    //
    // Look-up the entry.
    //
    hashEntry = HashTable[ HASHOBJECT( hkey ) ];
    prevEntry = NULL;

    while( hashEntry && hashEntry->hkey != hkey ) {

        prevEntry = hashEntry;
        hashEntry = hashEntry->Next;
    }
  
    //  
    // If we fall of the hash list without finding what we're looking
    // for, just return.
    //
    if( !hashEntry ) {

        Signal_Semaphore( HashMutex );
        return;
    }

    //
    // Got it! Remove it from the list
    //
    if( prevEntry ) {

        prevEntry->Next = hashEntry->Next;

    } else {

        HashTable[ HASHOBJECT( hkey )] = hashEntry->Next;
    }

    //
    // Free the memory associated with it
    //
    HeapFree( hashEntry, 0 );
    Signal_Semaphore( HashMutex );
}
void 
PGPdiskSemaphore::Signal()
{
	pgpAssert(NULL!=(int)(mSemHandle));

	Signal_Semaphore(mSemHandle);
}
예제 #3
0
//----------------------------------------------------------------------
//
// RegmonLogHash
//
// Logs the key and associated fullpath in the hash table.
//
//----------------------------------------------------------------------
VOID 
RegmonLogHash( 
    HKEY hkey, 
    PCHAR fullname 
    )
{
    PHASH_ENTRY     newEntry;

    Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );

    //
    // Find or allocate an entry to use
    //
    newEntry = HeapAllocate( sizeof(HASH_ENTRY) + strlen(fullname)+1, 0 );

    //
    // Initialize the new entry.
    //
    if( newEntry ) {

        newEntry->hkey = hkey;
        newEntry->Next = HashTable[ HASHOBJECT(hkey) ];
        HashTable[ HASHOBJECT(hkey) ] = newEntry;	
        strcpy( newEntry->FullName, fullname );
    }
    Signal_Semaphore( HashMutex );
}
예제 #4
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL	EnableWriteProtect()
{
	Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
	g_bEnableProtect = TRUE;
	Signal_Semaphore(g_hSemSyncIO);
	return TRUE;
}
예제 #5
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL MoveGroup(DWORD dwSStart,DWORD dwSize,DWORD dwTStart)
{
//	DWORD		k,i,j;
	BOOL		bResult;
	DWORD		dwPages;
	PVOID		pBuf = NULL;

	dwPages	= (dwSize+7)/8;
	pBuf	= (PVOID)_PageAllocate(dwPages,PG_SYS,NULL,0,0,0,NULL,PAGEFIXED);

	Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
	if(pBuf)
	{
		bResult = SecureReadWriteSector(READ_OPERATION,dwSStart,dwSize,pBuf,g_pMoverData);
		if(bResult)
		{
			bResult = SecureReadWriteSector(WRITE_OPERATION,dwTStart,dwSize,pBuf,g_pMoverData);
		}
	}
	Signal_Semaphore(g_hSemSyncIO);

	if(pBuf)
	{
		g_dwRePointer = dwSStart + dwSize;
		_PageFree(pBuf,0);
	}
	return bResult;
}
예제 #6
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL SetGroupTable(DWORD dwStartSec,DWORD dwRecNum)
{
	BOOL				bResult = FALSE;
	PRM_SEC_GROUP		pGroupBuff,pGroup;
	PRM_SEC_GROUP_TABLE pDataRegion;

//	PTCB			hThread = NULL;
//	DWORD		    dwOldPri;

//    hThread	 = Get_Cur_Thread_Handle();
//    dwOldPri = Get_Cur_Thread_Priority(hThread);

	Out_Debug_String("BLOCKMOVER: Set group table\n\r");
	pDataRegion = (PRM_SEC_GROUP_TABLE)YG_List_Allocate(g_pDataRegionLRUList);
	if(pDataRegion)
	{
		pGroupBuff	  = (PRM_SEC_GROUP)_PageAllocate(SEC_GROUP_BUFFER_SIZE/SECTORS_PER_PAGE,PG_SYS,NULL,0,0,0,NULL,PAGEFIXED);
		if(pGroupBuff)
		{
//			if(dwOldPri < 12)
//			{
//				Set_Cur_Thread_Priority(hThread,12);
//			}
			 Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
			 bResult = SecureReadWriteSector(READ_OPERATION,dwStartSec, SEC_GROUP_BUFFER_SIZE,
									pGroupBuff,g_pMoverData);
			 Signal_Semaphore(g_hSemSyncIO);
//			if(dwOldPri < 12)
//			{
//				Set_Cur_Thread_Priority(hThread,dwOldPri);
//			}
		}
		
		memset(pDataRegion,0,sizeof(RM_SEC_GROUP_TABLE));
		pDataRegion->dwStartSec = dwStartSec;
		pDataRegion->dwRecNum   = dwRecNum;
		pDataRegion->pGroupsBuff= pGroupBuff;
		pDataRegion->dwDataRegionStart = pGroupBuff->dwSStartSec;
		pGroup = (PRM_SEC_GROUP)(pGroupBuff+dwRecNum-1);
		pDataRegion->dwDataRegionEnd = pGroup->dwSStartSec + pGroup->dwLength;

		if(g_dwNumDataRegionLoaded >= MAX_DATA_REGION_LOADED && !bResult)
		{
			_PageFree(pGroupBuff,0);
			pDataRegion->pGroupsBuff = NULL;
		}
		if(g_pDataRegionListTail)
			g_pDataRegionListTail->pNext = pDataRegion;
						
		g_pDataRegionListTail = pDataRegion;
		if(g_pDataRegionListHead == NULL)
			g_pDataRegionListHead = pDataRegion;

		if(pDataRegion->pGroupsBuff)
			YG_List_Attach_Tail(g_pDataRegionLRUList,pDataRegion);
		g_dwNumDataRegionLoaded ++;
	}
	return bResult;
}
예제 #7
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL    ReadSectors(DWORD dwStartSec,DWORD dwSecs,PVOID pBuffer)
{
	BOOL		bResult = FALSE;

    Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);

	bResult = SecureReadWriteSector(READ_OPERATION,dwStartSec,dwSecs,pBuffer,g_pMoverData);

    Signal_Semaphore(g_hSemSyncIO);
	return bResult;
}
예제 #8
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL	SetWriteResult(BOOL bSys,DWORD dwStartSec,DWORD dwSize)
{
	Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
	if(!bSys && g_dwMovedRecNum)
	{
		g_MovingGroup.dwMovedSize += dwSize;
	}
	if(g_bReLocate && bSys) 
		g_dwRePointer = dwStartSec + dwSize;
	Signal_Semaphore(g_hSemSyncIO);		
	return TRUE;
}
예제 #9
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
BOOL	SetMoingGroupCur(BOOL bFront,DWORD dwSStart,DWORD dwTStart,DWORD dwSize,DWORD dwRecNum)
{
	Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
	g_MovingGroup.bFront		= bFront;
	g_MovingGroup.dwSStart		= dwSStart;
	g_MovingGroup.dwTStart		= dwTStart;
	g_MovingGroup.dwSize		= dwSize;
	g_MovingGroup.dwMovedSize	= 0;
	g_dwMovedRecNum				= dwRecNum;
	g_pMoverData->bWorking		= TRUE;
	Signal_Semaphore(g_hSemSyncIO);
	return TRUE;
}
예제 #10
0
//----------------------------------------------------------------------
//
// ApplyFilters
//
// If the name matches the exclusion mask, we do not log it. Else if
// it doesn't match the inclusion mask we do not log it. 
//
//----------------------------------------------------------------------
BOOLEAN
ApplyFilters( 
    PCHAR fullname 
    )
{
    ULONG    i;

    //   
    // If it matches the exclusion string, do not log it
    //
    Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
    for( i = 0; i < NumExcludeFilters; i++ ) {

        if( MatchWithPattern( ExcludeFilters[i], fullname ) ) {

            Signal_Semaphore( FilterMutex );
            return FALSE;
        }
    }
 
    //
    // If it matches an include filter then log it
    //
    for( i = 0; i < NumIncludeFilters; i++ ) {

        if( MatchWithPattern( IncludeFilters[i], fullname )) {

            Signal_Semaphore( FilterMutex );
            return TRUE;
        }
    }

    //
    // It didn't match any include filters so don't log
    //
    Signal_Semaphore( FilterMutex );
    return FALSE;
}
예제 #11
0
파일: Blkmover.c 프로젝트: xfxf123444/japan
NTSTATUS	PostScript(BOOL bReboot)
#endif
{
    PBYTE	pSector;
    DWORD	dwHashIndex;
    DWORD	dwSectorNum;
    PBYTE	pSectors;
    BOOL	bSucc;
    BOOL	bRetVal = TRUE;
    int 	nTotalSectors;
    int 	n;

#ifdef WIN_9X
    if (bReboot)
      Reboot();
    Wait_Semaphore(g_hSemSyncIO,BLOCK_THREAD_IDLE);
    EnableOrDisable(FALSE);
    if (g_hSemInternalReq)
		Destroy_Semaphore(g_hSemInternalReq);
#else
    if (g_MoverCache.pCache)
		ExFreePool(g_MoverCache.pCache);
	
	if(g_pMoverData)
	{
		ExFreePool(g_pMoverData);
		g_pMoverData = NULL;
	}
	if(g_pSharkData)
	{
		ExFreePool(g_pSharkData);
		g_pSharkData	= NULL;
	}
	if(g_partitionInfo)
	{
		ExFreePool(g_partitionInfo);
		g_partitionInfo = NULL;
	}
	g_bBlkMovSucc	 = FALSE;
	g_bPartitionSet  = FALSE;
#endif

#ifdef WIN_9X
    Signal_Semaphore(g_hSemSyncIO);
    return  bRetVal;
#else
	return STATUS_SUCCESS;
#endif
}   //	PostScript
예제 #12
0
//----------------------------------------------------------------------
//
// RegmonUpdateFilters
//
// Takes a new filter specification and updates the filter
// arrays with them.
//
//----------------------------------------------------------------------
VOID 
RegmonUpdateFilters(
    VOID
    )
{
    //
    // Free old filters (if any)
    //
    Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );

    RegmonFreeFilters();

    //
    // Create new filter arrays
    //
    MakeFilterArray( FilterDef.includefilter,
                     IncludeFilters, &NumIncludeFilters );
    MakeFilterArray( FilterDef.excludefilter,
                     ExcludeFilters, &NumExcludeFilters );
    Signal_Semaphore( FilterMutex );
}
예제 #13
0
DWORD SBBSExec::OnW32DeviceIoControl(PIOCTLPARAMS pIOCTL)
{
	DWORD	rd;
	DWORD	wr;
	DWORD	avail;
	vm_t*	vm;

//	DBTRACEd(0,"SBBSEXEC ioctl"
		//,pIOCTL->dioc_IOCtlCode);

	switch(pIOCTL->dioc_IOCtlCode) {
		case DIOC_OPEN:
			DBTRACEd(0,"IOCTL: OPEN",Get_System_Time());
			break;

		case DIOC_CLOSEHANDLE:
			DBTRACEd(0,"IOCTL: CLOSE",Get_System_Time());
			break;

		case SBBSEXEC_IOCTL_START:
			DBTRACEd(0,"IOCTL: START",Get_System_Time());
			DBTRACEx(0,"Current Thread Handle",Get_Cur_Thread_Handle());
			if(start.event) {
				DBTRACE(0,"Exec already started!");
				return(SBBSEXEC_ERROR_INUSE);
			}
			if (pIOCTL->dioc_InBuf==NULL 
				|| pIOCTL->dioc_cbInBuf!=sizeof(start)) {
				return(SBBSEXEC_ERROR_INBUF);
			}
			start=*(sbbsexec_start_t*)pIOCTL->dioc_InBuf;
			break;

		case SBBSEXEC_IOCTL_COMPLETE:
			DBTRACEd(0,"IOCTL: COMPLETE",Get_System_Time());
			if(start.event || new_vm==NULL) {
				DBTRACE(0,"!VM never created");
				start.event=0;
				return(SBBSEXEC_ERROR_INUSE);
			}
			if(pIOCTL->dioc_OutBuf==NULL
				|| pIOCTL->dioc_cbOutBuf<sizeof(VMHANDLE)) {
				DBTRACE(0,"!Invalid OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}
			*(VMHANDLE*)pIOCTL->dioc_OutBuf=new_vm->handle;
			DBTRACEx(0,"CREATED VM HANDLE", new_vm->handle);
			new_vm=NULL;

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = sizeof(VMHANDLE);
			break;
		case SBBSEXEC_IOCTL_READ:

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			if (pIOCTL->dioc_OutBuf==NULL || pIOCTL->dioc_cbOutBuf==0) {
				DBTRACE(0,"!INVALID OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			rd = RingBufFull(&vm->out);

			if(rd>pIOCTL->dioc_cbOutBuf) {
				DBTRACEdd(0,"Reducing read size"
                	,rd, pIOCTL->dioc_cbOutBuf);
				rd=pIOCTL->dioc_cbOutBuf;
			}

			RingBufRead(&vm->out, (BYTE*)pIOCTL->dioc_OutBuf, rd);

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = rd;

            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);

            if(rd>1) {
            	DBTRACEd(1,"IOCTL_READ bytes", rd);
            }
			break;

		case SBBSEXEC_IOCTL_WRITE:

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf<sizeof(VMHANDLE)+1) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			if (pIOCTL->dioc_OutBuf==NULL
				|| pIOCTL->dioc_cbOutBuf!=sizeof(DWORD)) {
				DBTRACE(0,"!INVALID OUTBUF");
				return(SBBSEXEC_ERROR_OUTBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			wr = pIOCTL->dioc_cbInBuf-sizeof(VMHANDLE);

			avail = RingBufFree(&vm->in);

			if(wr>avail) {
				DBTRACEdd(0,"Reducing write size", wr, avail);
				wr=avail;
			}

			RingBufWrite(&vm->in, (BYTE*)pIOCTL->dioc_InBuf+sizeof(VMHANDLE), wr);

			*(DWORD *)pIOCTL->dioc_OutBuf = wr;

			if(pIOCTL->dioc_bytesret!=NULL)
				*pIOCTL->dioc_bytesret = sizeof(DWORD);

            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);

			// Wake up the VDM (improves keyboard response - dramatically!)
			Wake_Up_VM(vm->handle);
			break;

		case SBBSEXEC_IOCTL_DISCONNECT:
			DBTRACEd(0,"IOCTL: DISCONNECT",Get_System_Time());

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			vm->online=false;

            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);
            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);
			break;

		case SBBSEXEC_IOCTL_STOP:
			DBTRACEd(0,"IOCTL: STOP",Get_System_Time());

			if (pIOCTL->dioc_InBuf==NULL
				|| pIOCTL->dioc_cbInBuf!=sizeof(VMHANDLE)) {
				DBTRACE(0,"!INVALID INBUF");
				return(SBBSEXEC_ERROR_INBUF);
			}

			vm = find_vm(*(VMHANDLE*)pIOCTL->dioc_InBuf);
			if(vm==NULL) {
				DBTRACE(0,"!NO VM LIST");
				return(SBBSEXEC_ERROR_INDATA);
			}

			DBTRACEx(0,"CLOSING VM HANDLE", vm->handle);
			vm->handle=NULL;	// Mark as available
			RingBufDispose(&vm->in);
			RingBufDispose(&vm->out);
            if(vm->input_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->input_sem);
            if(vm->output_sem!=NULL) // Wake up int14 handler
            	Signal_Semaphore(vm->output_sem);

			vm->input_sem=NULL;
			vm->output_sem=NULL;

			break;

		default:
			DBTRACEdx(0,"!UNKNOWN IOCTL"
				,pIOCTL->dioc_IOCtlCode,pIOCTL->dioc_IOCtlCode);
			return(SBBSEXEC_ERROR_IOCTL);

	}
	return (0);	// DEVIOCTL_NOERROR);
}
예제 #14
0
//----------------------------------------------------------------------
//
// GetFullName
//
// Returns the full pathname of a key, if we can obtain one, else
// returns a handle.
//
//----------------------------------------------------------------------
VOID 
GetFullName( 
    HKEY hKey, 
    PCHAR lpszSubKey, 
    PCHAR lpszValue, 
    PCHAR fullname 
    )
{
    PHASH_ENTRY		hashEntry;
    CHAR                tmpkey[16];

    //
    // See if we find the key in the hash table
    //
    fullname[0] = 0;
    Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );

    hashEntry = HashTable[ HASHOBJECT( hKey ) ];
    while( hashEntry && hashEntry->hkey != hKey ) {

        hashEntry = hashEntry->Next;
    }

    Signal_Semaphore( HashMutex );

    if( hashEntry ) {

        strcpy( fullname, hashEntry->FullName );

    } else {

        //
        // Okay, make a name
        //
        switch( hKey ) {

        case HKEY_CLASSES_ROOT:
            strcat(fullname, "HKCR");
            break;

        case HKEY_CURRENT_USER:
            strcat(fullname, "HKCU");
            break;

        case HKEY_LOCAL_MACHINE:
            strcat(fullname, "HKLM");
            break;

        case HKEY_USERS:
            strcat(fullname, "HKU");
            break;

        case HKEY_CURRENT_CONFIG:
            strcat(fullname, "HKCC");
            break;

        case HKEY_DYN_DATA:
            strcat(fullname, "HKDD");
            break;

        default:

            //
            // We will only get here if key was created before we loaded
            //
            sprintf( tmpkey, "0x%X", hKey );					
            strcat(fullname, tmpkey );
            break;
        }
    }

    //
    // Append subkey and value, if they are there
    //
    if( lpszSubKey ) {

        if( lpszSubKey[0] ) {

            strcat( fullname, "\\" );
            strcat( fullname, lpszSubKey );
        }
    }

    if( lpszValue ) {

        if( lpszValue[0] ) {

            strcat( fullname, "\\" );
            strcat( fullname, lpszValue );
        }
    }
}
예제 #15
0
//----------------------------------------------------------------------
//
// LogRecord
//
// Add a new string to Log, if it fits.
//
//----------------------------------------------------------------------
VOID 
LogRecord( 
    const char * format, 
    ... 
    )
{	
    PENTRY		Entry;
    ULONG		len;
    va_list		arg_ptr;
    static CHAR text[MAXPATHLEN];
    DWORD       timehi;
    DWORD       time, date;

    //
    // If no filtering is desired, don't bother
    //
    if( !FilterOn ) {
 
        return;
    }

    //
    // Lock the output buffer.
    //
    Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );

    //
    // Vsprintf to determine length of the buffer
    //
    _asm cld;
    va_start( arg_ptr, format );
    len = vsprintf( text, format, arg_ptr );
    va_end( arg_ptr );

    //
    // Only log it if it passes the filtes
    //
    if( ApplyFilters( text )) {

        //
        // If the current output buffer is near capacity, move to a new
        // output buffer
        //
        if( (ULONG) (Log->Len + len + sizeof(ENTRY) +1) >= LOGBUFSIZE ) {
	
            RegmonNewLog();
        }

        //
        // Extract the sequence number and Log it
        //
        dprintf("%s\n", text );
        Entry = (void *)(Log->Data+Log->Len);
        _asm cld;
        memcpy( Entry->text, text, len+1 );
        Entry->time.u.HighPart = IFSMgr_Get_DOSTime( &Entry->time.u.LowPart );

        //
        // We calculate milliseconds to get around a bug in 
        // IFSMgr_Get_DOSTime 
        //
        time = VTD_Get_Date_And_Time( &date );
        Entry->time.u.LowPart = time - ((Entry->time.u.HighPart >> 11)& 0x1F)*60*60*1000 - 
            ((Entry->time.u.HighPart >> 5) & 0x3F)*60*1000 - 
            ((Entry->time.u.HighPart & 0x1F)*2000);

        VTD_Get_Real_Time( &Entry->perftime.u.HighPart, &Entry->perftime.u.LowPart );
        Entry->seq = Sequence++;
        Entry->perftime.u.HighPart -= StartTime.u.HighPart;
        Entry->perftime.u.LowPart  -= StartTime.u.LowPart;

        //
        // Log the length of the string, plus 1 for the terminating
        // NULL  
        //   
        Log->Len += (Entry->text - (PCHAR) Entry) + len + 1;
    }

    //
    // Release the output buffer lock
    //
    Signal_Semaphore( LogMutex );
}
예제 #16
0
//----------------------------------------------------------------------
//
// OnW32Deviceiocontrol
//
// Interface with the GUI.
//
//----------------------------------------------------------------------
DWORD 
OnW32Deviceiocontrol(
    PIOCTLPARAMS p
    )
{
    PLOG_BUF        old;
    static BOOLEAN  connected = FALSE;

    switch( p->dioc_IOCtlCode ) {

    case 0:
        return 0;

    case IOCTL_REGMON_ZEROSTATS:
  
        Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );
        while ( Log->Next )  {
 
            //
            // Release the next entry.
            //
            old = Log->Next;
            Log->Next = old->Next;
            Signal_Semaphore( LogMutex );
            PageFree( old->Handle, 0 );
            Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );
            NumLog--;
        }
        Log->Len = 0;
        Sequence = 0;
        VTD_Get_Real_Time( &StartTime.u.HighPart, &StartTime.u.LowPart );
        
        Signal_Semaphore( LogMutex );
        return 0;

    case IOCTL_REGMON_GETSTATS:
  
        //
        // Copy buffer into user space.
        Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );
        if ( LOGBUFSIZE > p->dioc_cbOutBuf ) {

            //
            // Buffer is too small. Return error.
            //
            Signal_Semaphore( LogMutex );

            return 1;

        } else if ( Log->Len  ||  Log->Next ) {

            //
            // Switch to a new buffer.
            //
            RegmonNewLog();

            //
            // Fetch the oldest buffer to give to caller.
            //
            old = RegmonOldestLog();
            Signal_Semaphore( LogMutex );

            //
            // Copy it into the caller's buffer.
            //
            memcpy( p->dioc_OutBuf, old->Data, old->Len );

            //
            // Return length of copied info.
            //
            *p->dioc_bytesret = old->Len;

            //   
            // Deallocate the buffer.
            //
            PageFree( old->Handle, 0 );
            NumLog--;

        } else {

            //
            // There is no unread data.
            //
            Signal_Semaphore( LogMutex );
            *p->dioc_bytesret = 0;
        }
        return 0;

    case IOCTL_REGMON_UNHOOK:

        FilterOn = FALSE;
        return 0;

    case IOCTL_REGMON_HOOK:

        FilterOn = TRUE;
        return 0;

    case IOCTL_REGMON_SETFILTER:

        FilterDef = * (PFILTER) p->dioc_InBuf;
        RegmonUpdateFilters();
        return 0;
    }
    return 0;
}