|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
rtnotify.c
Abstract:
NT level registry test program, basic non-error paths.
Wait for notification.
This program tests waiting for notification on a change to a registry node. It can wait synchronously, for an event, for for an Apc. It can use any filter.
Only the first letter of option control are significant.
rtnotify <keyname> {key|tree|event|Apc|hold|name|write|security|prop|*}
key = key only [default] (last of these two wins) tree = subtree
event = wait on an event (overrides hold) Apc = use an Apc (overrides hold) hold = be synchronous [default] (overrides event and Apc)
name = watch for create/delete of children write = last set change security = acl change prop = any attr == security change * = all
Example:
rtflush \REGISTRY\MACHINE\TEST\bigkey
Author:
Bryan Willman (bryanwi) 10-Jan-92
Revision History:
--*/
#include "cmp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORK_SIZE 1024
void main(); void processargs();
ULONG CallCount = 0L;
VOID ApcTest( PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock );
UNICODE_STRING KeyName; WCHAR workbuffer[WORK_SIZE]; BOOLEAN WatchTree; BOOLEAN UseEvent; BOOLEAN UseApc; BOOLEAN ApcSeen; BOOLEAN Hold; BOOLEAN Filter; IO_STATUS_BLOCK RtIoStatusBlock;
void main( int argc, char *argv[] ) { NTSTATUS status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE BaseHandle; HANDLE EventHandle; PIO_APC_ROUTINE ApcRoutine;
//
// Process args
//
KeyName.MaximumLength = WORK_SIZE; KeyName.Length = 0L; KeyName.Buffer = &(workbuffer[0]);
processargs(argc, argv);
//
// Set up and open KeyPath
//
printf("rtnotify: starting\n");
InitializeObjectAttributes( &ObjectAttributes, &KeyName, 0, (HANDLE)NULL, NULL ); ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
status = NtOpenKey( &BaseHandle, KEY_NOTIFY, &ObjectAttributes ); if (!NT_SUCCESS(status)) { printf("rtnotify: t0: %08lx\n", status); exit(1); }
EventHandle = (HANDLE)NULL; if (UseEvent == TRUE) { status = NtCreateEvent( &EventHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, NULL, NotificationEvent, FALSE ); if (!NT_SUCCESS(status)) { printf("rtnotify: t1: %08lx\n", status); exit(1); } }
ApcRoutine = NULL; if (UseApc) { ApcRoutine = ApcTest; }
printf("rtnotify:\n"); printf("\tUseEvent = %08lx\n", UseEvent); printf("\tApcRoutine = %08lx\n", ApcRoutine); printf("\tHold = %08lx\n", Hold); printf("\tFilter = %08lx\n", Filter); printf("\tWatchTree = %08lx\n", WatchTree);
while (TRUE) { ApcSeen = FALSE; printf("\nCallCount = %dt\n", CallCount); CallCount++; status = NtNotifyChangeKey( BaseHandle, EventHandle, ApcRoutine, (PVOID)1992, // arbitrary context value
&RtIoStatusBlock, Filter, WatchTree, NULL, 0, ! Hold );
exit(0);
if ( ! NT_SUCCESS(status)) { printf("rtnotify: t2: %08lx\n", status); exit(1); }
if (Hold) { printf("rtnotify: Synchronous Status = %08lx\n", RtIoStatusBlock.Status); }
if (UseEvent) { status = NtWaitForSingleObject( EventHandle, TRUE, NULL ); if (!NT_SUCCESS(status)) { printf("rtnotify: t3: status = %08lx\n", status); exit(1); } printf("rtnotify: Event Status = %08lx\n", RtIoStatusBlock.Status); }
if (UseApc) { while ((volatile)ApcSeen == FALSE) { NtTestAlert(); } } }
NtClose(BaseHandle); exit(0); }
VOID ApcTest( PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock ) { ApcSeen = TRUE;
if (ApcContext != (PVOID)1992) { printf("rtnotify: Apc: Apccontext is wrong %08lx\n", ApcContext); exit(1); } if (IoStatusBlock != &RtIoStatusBlock) { printf("rtnotify: Apc: IoStatusBlock is wrong %08ln", IoStatusBlock); exit(1); }
printf("rtnotify: Apc status = %08lx\n", IoStatusBlock->Status); return; }
void processargs( int argc, char *argv[] ) { ANSI_STRING temp; ULONG i;
if (argc < 2) { goto Usage; }
//
// name
//
RtlInitAnsiString( &temp, argv[1] );
RtlAnsiStringToUnicodeString( &KeyName, &temp, FALSE );
WatchTree = FALSE; UseEvent = FALSE; UseApc = FALSE; Hold = TRUE; Filter = 0;
//
// switches
//
for (i = 2; i < (ULONG)argc; i++) { switch (*argv[i]) {
case 'a': // Apc
case 'A': Hold = FALSE; UseApc = TRUE; break;
case 'e': // event
case 'E': Hold = FALSE; UseEvent = TRUE; break;
case 'h': // hold
case 'H': UseApc = FALSE; UseEvent = FALSE; Hold = TRUE; break;
case 'k': // key only
case 'K': WatchTree = FALSE; break;
case 'n': case 'N': Filter |= REG_NOTIFY_CHANGE_NAME; break;
case 'p': case 'P': Filter |= REG_NOTIFY_CHANGE_ATTRIBUTES; break;
case 's': case 'S': Filter |= REG_NOTIFY_CHANGE_SECURITY; break;
case 't': // subtree
case 'T': WatchTree = TRUE; break;
case 'w': case 'W': Filter |= REG_NOTIFY_CHANGE_LAST_SET; break;
case '*': Filter = REG_LEGAL_CHANGE_FILTER; break;
default: goto Usage; break; } } if (Filter == 0) { Filter = REG_LEGAL_CHANGE_FILTER; } return;
Usage: printf("Usage: %s <KeyPath> {key|tree|event|Apc|sync|name|write|security|attribute|*}\n", argv[0]); exit(1); }
|