Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. rtnotify.c
  5. Abstract:
  6. NT level registry test program, basic non-error paths.
  7. Wait for notification.
  8. This program tests waiting for notification on a change to
  9. a registry node. It can wait synchronously, for an event,
  10. for for an Apc. It can use any filter.
  11. Only the first letter of option control are significant.
  12. rtnotify <keyname> {key|tree|event|Apc|hold|name|write|security|prop|*}
  13. key = key only [default] (last of these two wins)
  14. tree = subtree
  15. event = wait on an event (overrides hold)
  16. Apc = use an Apc (overrides hold)
  17. hold = be synchronous [default] (overrides event and Apc)
  18. name = watch for create/delete of children
  19. write = last set change
  20. security = acl change
  21. prop = any attr == security change
  22. * = all
  23. Example:
  24. rtflush \REGISTRY\MACHINE\TEST\bigkey
  25. Author:
  26. Bryan Willman (bryanwi) 10-Jan-92
  27. Revision History:
  28. --*/
  29. #include "cmp.h"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #define WORK_SIZE 1024
  34. void main();
  35. void processargs();
  36. ULONG CallCount = 0L;
  37. VOID
  38. ApcTest(
  39. PVOID ApcContext,
  40. PIO_STATUS_BLOCK IoStatusBlock
  41. );
  42. UNICODE_STRING KeyName;
  43. WCHAR workbuffer[WORK_SIZE];
  44. BOOLEAN WatchTree;
  45. BOOLEAN UseEvent;
  46. BOOLEAN UseApc;
  47. BOOLEAN ApcSeen;
  48. BOOLEAN Hold;
  49. BOOLEAN Filter;
  50. IO_STATUS_BLOCK RtIoStatusBlock;
  51. void
  52. main(
  53. int argc,
  54. char *argv[]
  55. )
  56. {
  57. NTSTATUS status;
  58. OBJECT_ATTRIBUTES ObjectAttributes;
  59. HANDLE BaseHandle;
  60. HANDLE EventHandle;
  61. PIO_APC_ROUTINE ApcRoutine;
  62. //
  63. // Process args
  64. //
  65. KeyName.MaximumLength = WORK_SIZE;
  66. KeyName.Length = 0L;
  67. KeyName.Buffer = &(workbuffer[0]);
  68. processargs(argc, argv);
  69. //
  70. // Set up and open KeyPath
  71. //
  72. printf("rtnotify: starting\n");
  73. InitializeObjectAttributes(
  74. &ObjectAttributes,
  75. &KeyName,
  76. 0,
  77. (HANDLE)NULL,
  78. NULL
  79. );
  80. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  81. status = NtOpenKey(
  82. &BaseHandle,
  83. KEY_NOTIFY,
  84. &ObjectAttributes
  85. );
  86. if (!NT_SUCCESS(status)) {
  87. printf("rtnotify: t0: %08lx\n", status);
  88. exit(1);
  89. }
  90. EventHandle = (HANDLE)NULL;
  91. if (UseEvent == TRUE) {
  92. status = NtCreateEvent(
  93. &EventHandle,
  94. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  95. NULL,
  96. NotificationEvent,
  97. FALSE
  98. );
  99. if (!NT_SUCCESS(status)) {
  100. printf("rtnotify: t1: %08lx\n", status);
  101. exit(1);
  102. }
  103. }
  104. ApcRoutine = NULL;
  105. if (UseApc) {
  106. ApcRoutine = ApcTest;
  107. }
  108. printf("rtnotify:\n");
  109. printf("\tUseEvent = %08lx\n", UseEvent);
  110. printf("\tApcRoutine = %08lx\n", ApcRoutine);
  111. printf("\tHold = %08lx\n", Hold);
  112. printf("\tFilter = %08lx\n", Filter);
  113. printf("\tWatchTree = %08lx\n", WatchTree);
  114. while (TRUE) {
  115. ApcSeen = FALSE;
  116. printf("\nCallCount = %dt\n", CallCount);
  117. CallCount++;
  118. status = NtNotifyChangeKey(
  119. BaseHandle,
  120. EventHandle,
  121. ApcRoutine,
  122. (PVOID)1992, // arbitrary context value
  123. &RtIoStatusBlock,
  124. Filter,
  125. WatchTree,
  126. NULL,
  127. 0,
  128. ! Hold
  129. );
  130. exit(0);
  131. if ( ! NT_SUCCESS(status)) {
  132. printf("rtnotify: t2: %08lx\n", status);
  133. exit(1);
  134. }
  135. if (Hold) {
  136. printf("rtnotify: Synchronous Status = %08lx\n", RtIoStatusBlock.Status);
  137. }
  138. if (UseEvent) {
  139. status = NtWaitForSingleObject(
  140. EventHandle,
  141. TRUE,
  142. NULL
  143. );
  144. if (!NT_SUCCESS(status)) {
  145. printf("rtnotify: t3: status = %08lx\n", status);
  146. exit(1);
  147. }
  148. printf("rtnotify: Event Status = %08lx\n", RtIoStatusBlock.Status);
  149. }
  150. if (UseApc) {
  151. while ((volatile)ApcSeen == FALSE) {
  152. NtTestAlert();
  153. }
  154. }
  155. }
  156. NtClose(BaseHandle);
  157. exit(0);
  158. }
  159. VOID
  160. ApcTest(
  161. PVOID ApcContext,
  162. PIO_STATUS_BLOCK IoStatusBlock
  163. )
  164. {
  165. ApcSeen = TRUE;
  166. if (ApcContext != (PVOID)1992) {
  167. printf("rtnotify: Apc: Apccontext is wrong %08lx\n", ApcContext);
  168. exit(1);
  169. }
  170. if (IoStatusBlock != &RtIoStatusBlock) {
  171. printf("rtnotify: Apc: IoStatusBlock is wrong %08ln", IoStatusBlock);
  172. exit(1);
  173. }
  174. printf("rtnotify: Apc status = %08lx\n", IoStatusBlock->Status);
  175. return;
  176. }
  177. void
  178. processargs(
  179. int argc,
  180. char *argv[]
  181. )
  182. {
  183. ANSI_STRING temp;
  184. ULONG i;
  185. if (argc < 2) {
  186. goto Usage;
  187. }
  188. //
  189. // name
  190. //
  191. RtlInitAnsiString(
  192. &temp,
  193. argv[1]
  194. );
  195. RtlAnsiStringToUnicodeString(
  196. &KeyName,
  197. &temp,
  198. FALSE
  199. );
  200. WatchTree = FALSE;
  201. UseEvent = FALSE;
  202. UseApc = FALSE;
  203. Hold = TRUE;
  204. Filter = 0;
  205. //
  206. // switches
  207. //
  208. for (i = 2; i < (ULONG)argc; i++) {
  209. switch (*argv[i]) {
  210. case 'a': // Apc
  211. case 'A':
  212. Hold = FALSE;
  213. UseApc = TRUE;
  214. break;
  215. case 'e': // event
  216. case 'E':
  217. Hold = FALSE;
  218. UseEvent = TRUE;
  219. break;
  220. case 'h': // hold
  221. case 'H':
  222. UseApc = FALSE;
  223. UseEvent = FALSE;
  224. Hold = TRUE;
  225. break;
  226. case 'k': // key only
  227. case 'K':
  228. WatchTree = FALSE;
  229. break;
  230. case 'n':
  231. case 'N':
  232. Filter |= REG_NOTIFY_CHANGE_NAME;
  233. break;
  234. case 'p':
  235. case 'P':
  236. Filter |= REG_NOTIFY_CHANGE_ATTRIBUTES;
  237. break;
  238. case 's':
  239. case 'S':
  240. Filter |= REG_NOTIFY_CHANGE_SECURITY;
  241. break;
  242. case 't': // subtree
  243. case 'T':
  244. WatchTree = TRUE;
  245. break;
  246. case 'w':
  247. case 'W':
  248. Filter |= REG_NOTIFY_CHANGE_LAST_SET;
  249. break;
  250. case '*':
  251. Filter = REG_LEGAL_CHANGE_FILTER;
  252. break;
  253. default:
  254. goto Usage;
  255. break;
  256. }
  257. }
  258. if (Filter == 0) {
  259. Filter = REG_LEGAL_CHANGE_FILTER;
  260. }
  261. return;
  262. Usage:
  263. printf("Usage: %s <KeyPath> {key|tree|event|Apc|sync|name|write|security|attribute|*}\n",
  264. argv[0]);
  265. exit(1);
  266. }
  267.