284 lines
7.8 KiB
C
284 lines
7.8 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
UsnTest.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This is the main module for the UsnJournal test.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Tom Miller 14-Jan-1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "UsnTest.h"
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <time.h>
|
|||
|
#include <windows.h>
|
|||
|
|
|||
|
//
|
|||
|
// Current delay is 10 seconds
|
|||
|
//
|
|||
|
|
|||
|
#define DELAY_TIME ((LONGLONG)(-100000000))
|
|||
|
|
|||
|
void
|
|||
|
UsnTest(
|
|||
|
IN PCHAR DrivePath,
|
|||
|
IN ULONG Async
|
|||
|
);
|
|||
|
|
|||
|
CHAR *
|
|||
|
FileTimeToString(
|
|||
|
FILETIME *pft
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
__cdecl main( argc, argv )
|
|||
|
int argc;
|
|||
|
char *argv[];
|
|||
|
{
|
|||
|
char *p;
|
|||
|
int i;
|
|||
|
char c;
|
|||
|
char DrivePath[ 4 ];
|
|||
|
ULONG Async = FALSE;
|
|||
|
|
|||
|
if ( argc > 1 ) {
|
|||
|
if (argc > 2) {
|
|||
|
Async = TRUE;
|
|||
|
}
|
|||
|
while (--argc) {
|
|||
|
p = *++argv;
|
|||
|
if ( isalpha(*p) ) {
|
|||
|
sprintf( DrivePath, "%c:", *p );
|
|||
|
UsnTest( DrivePath, Async );
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
printf( "UsnTest <DriveLetter> [A](for asyncmode)" );
|
|||
|
}
|
|||
|
|
|||
|
return( 0 );
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
UsnTest(
|
|||
|
IN PCHAR DrivePath,
|
|||
|
IN ULONG Async
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
UCHAR VolumePath[16];
|
|||
|
HANDLE VolumeHandle;
|
|||
|
HANDLE Event;
|
|||
|
DWORD ReturnedByteCount;
|
|||
|
CREATE_USN_JOURNAL_DATA CreateUsnJournalData = {0x800000, 0x100000};
|
|||
|
READ_USN_JOURNAL_DATA ReadUsnJournalData = {0, MAXULONG, 0, DELAY_TIME, 1};
|
|||
|
ULONGLONG Buffer[1024];
|
|||
|
PUSN_RECORD UsnRecord;
|
|||
|
NTSTATUS Status;
|
|||
|
IO_STATUS_BLOCK Iosb;
|
|||
|
|
|||
|
//
|
|||
|
// Create the event.
|
|||
|
//
|
|||
|
|
|||
|
Status = NtCreateEvent( &Event, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
printf( "NtCreateEvent failed with %08lx\n", Status );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get a volume handle.
|
|||
|
//
|
|||
|
|
|||
|
_strupr( DrivePath );
|
|||
|
sprintf( VolumePath, "\\\\.\\%s", DrivePath );
|
|||
|
VolumeHandle = CreateFile( VolumePath,
|
|||
|
GENERIC_READ | GENERIC_WRITE,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
(Async ? FILE_FLAG_OVERLAPPED : 0),
|
|||
|
NULL );
|
|||
|
|
|||
|
if (VolumeHandle == INVALID_HANDLE_VALUE ) {
|
|||
|
fprintf( stderr, "UsnTest: Unable to open %s volume (%u)\n", &VolumePath, GetLastError() );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create the Usn Journal if it does not exist.
|
|||
|
//
|
|||
|
|
|||
|
printf( "Creating UsnJournal on %s\n", DrivePath );
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status = NtFsControlFile( VolumeHandle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&Iosb,
|
|||
|
FSCTL_CREATE_USN_JOURNAL,
|
|||
|
&CreateUsnJournalData,
|
|||
|
sizeof(CreateUsnJournalData),
|
|||
|
NULL,
|
|||
|
0 ))) {
|
|||
|
|
|||
|
printf( "Create Usn Journal failed (%08lx)\n", Status );
|
|||
|
return;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
while (TRUE) {
|
|||
|
|
|||
|
Status = NtFsControlFile( VolumeHandle,
|
|||
|
Async ? Event : NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&Iosb,
|
|||
|
FSCTL_READ_USN_JOURNAL,
|
|||
|
&ReadUsnJournalData,
|
|||
|
sizeof(ReadUsnJournalData),
|
|||
|
&Buffer,
|
|||
|
sizeof(Buffer) );
|
|||
|
|
|||
|
if (Status == STATUS_PENDING) {
|
|||
|
NtWaitForSingleObject( Event, TRUE, NULL );
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
Status = Iosb.Status;
|
|||
|
}
|
|||
|
|
|||
|
if (Status == STATUS_KEY_DELETED) {
|
|||
|
printf( "\n\nUsn %08lx, %08lx has been deleted, seeking to new journal start\n\n\n",
|
|||
|
(ULONG)ReadUsnJournalData.StartUsn,
|
|||
|
(ULONG)(ReadUsnJournalData.StartUsn >> 32) );
|
|||
|
ReadUsnJournalData.StartUsn = 0;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
printf( "Read Usn Journal failed (%08lx)\n", Status );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ReturnedByteCount = Iosb.Information;
|
|||
|
if (ReturnedByteCount != 0) {
|
|||
|
|
|||
|
UsnRecord = (PUSN_RECORD)((PCHAR)&Buffer + sizeof(USN));
|
|||
|
ReturnedByteCount -= sizeof(USN);
|
|||
|
ReadUsnJournalData.StartUsn = *(USN *)&Buffer;
|
|||
|
printf( "Next Usn will be: %08lx, %08lx\n",
|
|||
|
(ULONG)ReadUsnJournalData.StartUsn,
|
|||
|
(ULONG)(ReadUsnJournalData.StartUsn >> 32) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
while (ReturnedByteCount != 0) {
|
|||
|
|
|||
|
printf( "Usn: %08lx, %08lx, RecordLength: %lx, FileRef: %08lx, %08lx, ParentRef: %08lx, %08lx\n",
|
|||
|
(ULONG)UsnRecord->Usn,
|
|||
|
(ULONG)(UsnRecord->Usn >> 32),
|
|||
|
UsnRecord->RecordLength,
|
|||
|
(ULONG)UsnRecord->FileReferenceNumber,
|
|||
|
(ULONG)(UsnRecord->FileReferenceNumber >> 32),
|
|||
|
(ULONG)UsnRecord->ParentFileReferenceNumber,
|
|||
|
(ULONG)(UsnRecord->ParentFileReferenceNumber >> 32) );
|
|||
|
printf( " Reason: %08lx, SecurityId: %08lx, TimeStamp: %s\n FileName: %S\n",
|
|||
|
UsnRecord->Reason,
|
|||
|
UsnRecord->SecurityId,
|
|||
|
FileTimeToString((FILETIME *)&UsnRecord->TimeStamp),
|
|||
|
&UsnRecord->FileName );
|
|||
|
|
|||
|
if (UsnRecord->RecordLength <= ReturnedByteCount) {
|
|||
|
ReturnedByteCount -= UsnRecord->RecordLength;
|
|||
|
UsnRecord = (PUSN_RECORD)((PCHAR)UsnRecord + UsnRecord->RecordLength);
|
|||
|
} else {
|
|||
|
printf( "********Bogus ReturnedByteCount: %08lx\n", UsnRecord->RecordLength );
|
|||
|
ReturnedByteCount = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Show the end of the request.
|
|||
|
//
|
|||
|
|
|||
|
printf( "\n" );
|
|||
|
|
|||
|
//
|
|||
|
// Keep growing the data we will wait for, just to try some different cases.
|
|||
|
// Basically this converges quickly to always waiting for a full buffer, or
|
|||
|
// else the timeout.
|
|||
|
//
|
|||
|
|
|||
|
if (ReadUsnJournalData.BytesToWaitFor < sizeof(Buffer)) {
|
|||
|
if (!Async || (ReadUsnJournalData.BytesToWaitFor < 512)) {
|
|||
|
ReadUsnJournalData.BytesToWaitFor << 2;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle( VolumeHandle );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
char *Days[] =
|
|||
|
{
|
|||
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
|||
|
};
|
|||
|
|
|||
|
char *Months[] =
|
|||
|
{
|
|||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|||
|
};
|
|||
|
|
|||
|
CHAR *
|
|||
|
FileTimeToString(FILETIME *FileTime)
|
|||
|
{
|
|||
|
FILETIME LocalFileTime;
|
|||
|
SYSTEMTIME SystemTime;
|
|||
|
static char Buffer[32];
|
|||
|
|
|||
|
Buffer[0] = '\0';
|
|||
|
if (FileTime->dwHighDateTime != 0 || FileTime->dwLowDateTime != 0)
|
|||
|
{
|
|||
|
if (!FileTimeToLocalFileTime(FileTime, &LocalFileTime) ||
|
|||
|
!FileTimeToSystemTime(&LocalFileTime, &SystemTime))
|
|||
|
{
|
|||
|
return("Time???");
|
|||
|
}
|
|||
|
sprintf(
|
|||
|
Buffer,
|
|||
|
"%s %s %2d, %4d %02d:%02d:%02d",
|
|||
|
Days[SystemTime.wDayOfWeek],
|
|||
|
Months[SystemTime.wMonth - 1],
|
|||
|
SystemTime.wDay,
|
|||
|
SystemTime.wYear,
|
|||
|
SystemTime.wHour,
|
|||
|
SystemTime.wMinute,
|
|||
|
SystemTime.wSecond);
|
|||
|
}
|
|||
|
return(Buffer);
|
|||
|
}
|
|||
|
|