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.

709 lines
16 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. eventpr.c
  5. Abstract:
  6. This module implements the executive event pair object. Functions
  7. are provided to create, open, waitlow, waithi, setlow, sethi,
  8. sethiwaitlo, setlowaithi.
  9. Author:
  10. Mark Lucovsky (markl) 18-Oct-1990
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. --*/
  15. #include "exp.h"
  16. //
  17. // Define performance counters.
  18. //
  19. ULONG EvPrSetHigh = 0;
  20. ULONG EvPrSetLow = 0;
  21. //
  22. // Address of event pair object type descriptor.
  23. //
  24. POBJECT_TYPE ExEventPairObjectType;
  25. //
  26. // Structure that describes the mapping of generic access rights to object
  27. // specific access rights for event pair objects.
  28. //
  29. #ifdef ALLOC_DATA_PRAGMA
  30. #pragma const_seg("INITCONST")
  31. #endif
  32. const GENERIC_MAPPING ExpEventPairMapping = {
  33. STANDARD_RIGHTS_READ |
  34. SYNCHRONIZE,
  35. STANDARD_RIGHTS_WRITE |
  36. SYNCHRONIZE,
  37. STANDARD_RIGHTS_EXECUTE |
  38. SYNCHRONIZE,
  39. EVENT_PAIR_ALL_ACCESS
  40. };
  41. #ifdef ALLOC_DATA_PRAGMA
  42. #pragma const_seg()
  43. #endif
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text(INIT, ExpEventPairInitialization)
  46. #pragma alloc_text(PAGE, NtCreateEventPair)
  47. #pragma alloc_text(PAGE, NtOpenEventPair)
  48. #pragma alloc_text(PAGE, NtWaitLowEventPair)
  49. #pragma alloc_text(PAGE, NtWaitHighEventPair)
  50. #pragma alloc_text(PAGE, NtSetLowWaitHighEventPair)
  51. #pragma alloc_text(PAGE, NtSetHighWaitLowEventPair)
  52. #pragma alloc_text(PAGE, NtSetHighEventPair)
  53. #pragma alloc_text(PAGE, NtSetLowEventPair)
  54. #endif
  55. BOOLEAN
  56. ExpEventPairInitialization (
  57. )
  58. /*++
  59. Routine Description:
  60. This function creates the event pair object type descriptor at system
  61. initialization and stores the address of the object type descriptor
  62. in global storage.
  63. Arguments:
  64. None.
  65. Return Value:
  66. A value of TRUE is returned if the event pair object type descriptor is
  67. successfully initialized. Otherwise a value of FALSE is returned.
  68. --*/
  69. {
  70. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  71. NTSTATUS Status;
  72. UNICODE_STRING TypeName;
  73. //
  74. // Initialize string descriptor.
  75. //
  76. RtlInitUnicodeString(&TypeName, L"EventPair");
  77. //
  78. // Create event object type descriptor.
  79. //
  80. RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
  81. ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
  82. ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
  83. ObjectTypeInitializer.GenericMapping = ExpEventPairMapping;
  84. ObjectTypeInitializer.PoolType = NonPagedPool;
  85. ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EEVENT_PAIR);
  86. ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS;
  87. ObjectTypeInitializer.UseDefaultObject = TRUE;
  88. Status = ObCreateObjectType(&TypeName,
  89. &ObjectTypeInitializer,
  90. (PSECURITY_DESCRIPTOR)NULL,
  91. &ExEventPairObjectType);
  92. //
  93. // If the event pair object type descriptor was successfully created, then
  94. // return a value of TRUE. Otherwise return a value of FALSE.
  95. //
  96. return (BOOLEAN)(NT_SUCCESS(Status));
  97. }
  98. NTSTATUS
  99. NtCreateEventPair (
  100. OUT PHANDLE EventPairHandle,
  101. IN ACCESS_MASK DesiredAccess,
  102. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
  103. )
  104. /*++
  105. Routine Description:
  106. This function creates an event pair object, sets it initial state,
  107. and opens a handle to the object with the specified desired access.
  108. Arguments:
  109. EventPairHandle - Supplies a pointer to a variable that will receive the
  110. event pair object handle.
  111. DesiredAccess - Supplies the desired types of access for the event
  112. pair object.
  113. ObjectAttributes - Supplies a pointer to an object attributes
  114. structure.
  115. Return Value:
  116. NTSTATUS.
  117. --*/
  118. {
  119. PEEVENT_PAIR EventPair;
  120. HANDLE Handle;
  121. KPROCESSOR_MODE PreviousMode;
  122. NTSTATUS Status;
  123. //
  124. // Establish an exception handler, probe the output handle address, and
  125. // attempt to create an event object. If the probe fails, then return the
  126. // exception code as the service status. Otherwise return the status value
  127. // returned by the object insertion routine.
  128. //
  129. //
  130. // Get previous processor mode and probe output handle address if
  131. // necessary.
  132. //
  133. PreviousMode = KeGetPreviousMode();
  134. if (PreviousMode != KernelMode) {
  135. try {
  136. ProbeForWriteHandle(EventPairHandle);
  137. } except (ExSystemExceptionFilter()) {
  138. return GetExceptionCode();
  139. }
  140. }
  141. //
  142. // Allocate event object.
  143. //
  144. Status = ObCreateObject(PreviousMode,
  145. ExEventPairObjectType,
  146. ObjectAttributes,
  147. PreviousMode,
  148. NULL,
  149. sizeof(EEVENT_PAIR),
  150. 0,
  151. 0,
  152. (PVOID *)&EventPair);
  153. //
  154. // If the event pair object was successfully allocated, then
  155. // initialize the event pair object and attempt to insert the
  156. // event pair object in the current process' handle table.
  157. //
  158. if (NT_SUCCESS(Status)) {
  159. KeInitializeEventPair(&EventPair->KernelEventPair);
  160. Status = ObInsertObject((PVOID)EventPair,
  161. NULL,
  162. DesiredAccess,
  163. 0,
  164. (PVOID *)NULL,
  165. &Handle);
  166. //
  167. // If the event pair object was successfully inserted in the
  168. // current process' handle table, then attempt to write the
  169. // event pair object handle value. If the write attempt
  170. // fails, then do not report an error. When the caller
  171. // attempts to access the handle value, an access violation
  172. // will occur.
  173. if (NT_SUCCESS(Status)) {
  174. if (PreviousMode != KernelMode) {
  175. try {
  176. *EventPairHandle = Handle;
  177. } except(ExSystemExceptionFilter()) {
  178. NOTHING;
  179. }
  180. }
  181. else {
  182. *EventPairHandle = Handle;
  183. }
  184. }
  185. }
  186. //
  187. // Return service status.
  188. //
  189. return Status;
  190. }
  191. NTSTATUS
  192. NtOpenEventPair(
  193. OUT PHANDLE EventPairHandle,
  194. IN ACCESS_MASK DesiredAccess,
  195. IN POBJECT_ATTRIBUTES ObjectAttributes
  196. )
  197. /*++
  198. Routine Description:
  199. This function opens a handle to an event pair object with the specified
  200. desired access.
  201. Arguments:
  202. EventPairHandle - Supplies a pointer to a variable that will receive
  203. the event pair object handle.
  204. DesiredAccess - Supplies the desired types of access for the event
  205. pair object.
  206. ObjectAttributes - Supplies a pointer to an object attributes structure.
  207. Return Value:
  208. NTSTATUS.
  209. --*/
  210. {
  211. HANDLE Handle;
  212. KPROCESSOR_MODE PreviousMode;
  213. NTSTATUS Status;
  214. //
  215. // Establish an exception handler, probe the output handle address, and
  216. // attempt to open the event object. If the probe fails, then return the
  217. // exception code as the service status. Otherwise return the status value
  218. // returned by the object open routine.
  219. //
  220. //
  221. // Get previous processor mode and probe output handle address
  222. // if necessary.
  223. //
  224. PreviousMode = KeGetPreviousMode();
  225. if (PreviousMode != KernelMode) {
  226. try {
  227. ProbeForWriteHandle(EventPairHandle);
  228. } except (ExSystemExceptionFilter()) {
  229. return GetExceptionCode();
  230. }
  231. }
  232. //
  233. // Open handle to the event pair object with the specified
  234. // desired access.
  235. //
  236. Status = ObOpenObjectByName(ObjectAttributes,
  237. ExEventPairObjectType,
  238. PreviousMode,
  239. NULL,
  240. DesiredAccess,
  241. NULL,
  242. &Handle);
  243. //
  244. // If the open was successful, then attempt to write the event
  245. // pair object handle value. If the write attempt fails, then do
  246. // not report an error. When the caller attempts to access the
  247. // handle value, an access violation will occur.
  248. //
  249. if (NT_SUCCESS(Status)) {
  250. if (PreviousMode != KernelMode) {
  251. try {
  252. *EventPairHandle = Handle;
  253. } except(ExSystemExceptionFilter()) {
  254. NOTHING;
  255. }
  256. }
  257. else {
  258. *EventPairHandle = Handle;
  259. }
  260. }
  261. //
  262. // Return service status.
  263. //
  264. return Status;
  265. }
  266. NTSTATUS
  267. NtWaitLowEventPair(
  268. IN HANDLE EventPairHandle
  269. )
  270. /*++
  271. Routine Description:
  272. This function waits on the low event of an event pair object.
  273. Arguments:
  274. EventPairHandle - Supplies a handle to an event pair object.
  275. Return Value:
  276. NTSTATUS.
  277. --*/
  278. {
  279. PEEVENT_PAIR EventPair;
  280. KPROCESSOR_MODE PreviousMode;
  281. NTSTATUS Status;
  282. //
  283. // Reference event pair object by handle.
  284. //
  285. PreviousMode = KeGetPreviousMode();
  286. Status = ObReferenceObjectByHandle(EventPairHandle,
  287. SYNCHRONIZE,
  288. ExEventPairObjectType,
  289. PreviousMode,
  290. (PVOID *)&EventPair,
  291. NULL);
  292. //
  293. // If the reference was successful, then wait on the Low event
  294. // of the event pair.
  295. //
  296. if (NT_SUCCESS(Status)) {
  297. Status = KeWaitForLowEventPair(&EventPair->KernelEventPair,
  298. PreviousMode,
  299. FALSE,
  300. NULL);
  301. ObDereferenceObject(EventPair);
  302. }
  303. //
  304. // Return service status.
  305. //
  306. return Status;
  307. }
  308. NTSTATUS
  309. NtWaitHighEventPair(
  310. IN HANDLE EventPairHandle
  311. )
  312. /*++
  313. Routine Description:
  314. This function waits on the high event of an event pair object.
  315. Arguments:
  316. EventPairHandle - Supplies a handle to an event pair object.
  317. Return Value:
  318. NTSTATUS.
  319. --*/
  320. {
  321. PEEVENT_PAIR EventPair;
  322. KPROCESSOR_MODE PreviousMode;
  323. NTSTATUS Status;
  324. //
  325. // Reference event pair object by handle.
  326. //
  327. PreviousMode = KeGetPreviousMode();
  328. Status = ObReferenceObjectByHandle(EventPairHandle,
  329. SYNCHRONIZE,
  330. ExEventPairObjectType,
  331. PreviousMode,
  332. (PVOID *)&EventPair,
  333. NULL);
  334. //
  335. // If the reference was successful, then wait on the Low event
  336. // of the event pair.
  337. //
  338. if (NT_SUCCESS(Status)) {
  339. Status = KeWaitForHighEventPair(&EventPair->KernelEventPair,
  340. PreviousMode,
  341. FALSE,
  342. NULL);
  343. ObDereferenceObject(EventPair);
  344. }
  345. //
  346. // Return service status.
  347. //
  348. return Status;
  349. }
  350. NTSTATUS
  351. NtSetLowWaitHighEventPair(
  352. IN HANDLE EventPairHandle
  353. )
  354. /*++
  355. Routine Description:
  356. This function sets the low event of an event pair and then
  357. waits on the high event of an event pair object.
  358. Arguments:
  359. EventPairHandle - Supplies a handle to an event pair object.
  360. Return Value:
  361. NTSTATUS.
  362. --*/
  363. {
  364. PEEVENT_PAIR EventPair;
  365. KPROCESSOR_MODE PreviousMode;
  366. NTSTATUS Status;
  367. //
  368. // Reference event pair object by handle.
  369. //
  370. PreviousMode = KeGetPreviousMode();
  371. Status = ObReferenceObjectByHandle(EventPairHandle,
  372. SYNCHRONIZE,
  373. ExEventPairObjectType,
  374. PreviousMode,
  375. (PVOID *)&EventPair,
  376. NULL);
  377. //
  378. // If the reference was successful, then wait on the Low event
  379. // of the event pair.
  380. //
  381. if (NT_SUCCESS(Status)) {
  382. EvPrSetLow += 1;
  383. Status = KeSetLowWaitHighEventPair(&EventPair->KernelEventPair,
  384. PreviousMode);
  385. ObDereferenceObject(EventPair);
  386. }
  387. //
  388. // Return service status.
  389. //
  390. return Status;
  391. }
  392. NTSTATUS
  393. NtSetHighWaitLowEventPair(
  394. IN HANDLE EventPairHandle
  395. )
  396. /*++
  397. Routine Description:
  398. This function sets the high event of an event pair and then
  399. waits on the low event of an event pair object.
  400. Arguments:
  401. EventPairHandle - Supplies a handle to an event pair object.
  402. Return Value:
  403. NTSTATUS.
  404. --*/
  405. {
  406. PEEVENT_PAIR EventPair;
  407. KPROCESSOR_MODE PreviousMode;
  408. NTSTATUS Status;
  409. //
  410. // Reference event pair object by handle.
  411. //
  412. PreviousMode = KeGetPreviousMode();
  413. Status = ObReferenceObjectByHandle(EventPairHandle,
  414. SYNCHRONIZE,
  415. ExEventPairObjectType,
  416. PreviousMode,
  417. (PVOID *)&EventPair,
  418. NULL);
  419. //
  420. // If the reference was successful, then wait on the Low event
  421. // of the event pair.
  422. //
  423. if (NT_SUCCESS(Status)) {
  424. EvPrSetHigh += 1;
  425. Status = KeSetHighWaitLowEventPair(&EventPair->KernelEventPair,
  426. PreviousMode);
  427. ObDereferenceObject(EventPair);
  428. }
  429. //
  430. // Return service status.
  431. //
  432. return Status;
  433. }
  434. NTSTATUS
  435. NtSetLowEventPair(
  436. IN HANDLE EventPairHandle
  437. )
  438. /*++
  439. Routine Description:
  440. This function sets the low event of an event pair object.
  441. Arguments:
  442. EventPairHandle - Supplies a handle to an event pair object.
  443. Return Value:
  444. NTSTATUS.
  445. --*/
  446. {
  447. PEEVENT_PAIR EventPair;
  448. KPROCESSOR_MODE PreviousMode;
  449. NTSTATUS Status;
  450. //
  451. // Reference event pair object by handle.
  452. //
  453. PreviousMode = KeGetPreviousMode();
  454. Status = ObReferenceObjectByHandle(EventPairHandle,
  455. SYNCHRONIZE,
  456. ExEventPairObjectType,
  457. PreviousMode,
  458. (PVOID *)&EventPair,
  459. NULL);
  460. //
  461. // If the reference was successful, then wait on the Low event
  462. // of the event pair.
  463. //
  464. if (NT_SUCCESS(Status)) {
  465. EvPrSetLow += 1;
  466. KeSetLowEventPair(&EventPair->KernelEventPair,
  467. EVENT_PAIR_INCREMENT,FALSE);
  468. ObDereferenceObject(EventPair);
  469. }
  470. //
  471. // Return service status.
  472. //
  473. return Status;
  474. }
  475. NTSTATUS
  476. NtSetHighEventPair(
  477. IN HANDLE EventPairHandle
  478. )
  479. /*++
  480. Routine Description:
  481. This function sets the high event of an event pair object.
  482. Arguments:
  483. EventPairHandle - Supplies a handle to an event pair object.
  484. Return Value:
  485. NTSTATUS.
  486. --*/
  487. {
  488. PEEVENT_PAIR EventPair;
  489. KPROCESSOR_MODE PreviousMode;
  490. NTSTATUS Status;
  491. //
  492. // Reference event pair object by handle.
  493. //
  494. PreviousMode = KeGetPreviousMode();
  495. Status = ObReferenceObjectByHandle(EventPairHandle,
  496. SYNCHRONIZE,
  497. ExEventPairObjectType,
  498. PreviousMode,
  499. (PVOID *)&EventPair,
  500. NULL);
  501. //
  502. // If the reference was successful, then wait on the Low event
  503. // of the event pair.
  504. //
  505. if (NT_SUCCESS(Status)) {
  506. EvPrSetHigh += 1;
  507. KeSetHighEventPair(&EventPair->KernelEventPair,
  508. EVENT_PAIR_INCREMENT,FALSE);
  509. ObDereferenceObject(EventPair);
  510. }
  511. //
  512. // Return service status.
  513. //
  514. return Status;
  515. }