Windows2000/private/ntos/config/test/rtnotify.c
2020-09-30 17:12:32 +02:00

319 lines
6.5 KiB
C

/*++
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);
}