/ntoskrnl/ex/event.c

https://bitbucket.org/arty/arty-newcc-reactos · C · 543 lines · 377 code · 54 blank · 112 comment · 27 complexity · abe83ec775933e886b67e5ff47cba441 MD5 · raw file

  1. /*
  2. * COPYRIGHT: See COPYING in the top level directory
  3. * PROJECT: ReactOS Kernel
  4. * FILE: ntoskrnl/ex/event.c
  5. * PURPOSE: Event support
  6. * PROGRAMMERS: Alex Ionescu(alex@relsoft.net)
  7. * Thomas Weidenmueller
  8. */
  9. /* INCLUDES *****************************************************************/
  10. #include <ntoskrnl.h>
  11. #define NDEBUG
  12. #include <debug.h>
  13. #if defined (ALLOC_PRAGMA)
  14. #pragma alloc_text(INIT, ExpInitializeEventImplementation)
  15. #endif
  16. /* GLOBALS *******************************************************************/
  17. POBJECT_TYPE _ExEventObjectType = NULL;
  18. GENERIC_MAPPING ExpEventMapping =
  19. {
  20. STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
  21. STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
  22. STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
  23. EVENT_ALL_ACCESS};
  24. static const INFORMATION_CLASS_INFO ExEventInfoClass[] =
  25. {
  26. /* EventBasicInformation */
  27. ICI_SQ_SAME( sizeof(EVENT_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
  28. };
  29. /* FUNCTIONS *****************************************************************/
  30. VOID
  31. INIT_FUNCTION
  32. NTAPI
  33. ExpInitializeEventImplementation(VOID)
  34. {
  35. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  36. UNICODE_STRING Name;
  37. DPRINT("Creating Event Object Type\n");
  38. /* Create the Event Object Type */
  39. RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
  40. RtlInitUnicodeString(&Name, L"Event");
  41. ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
  42. ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT);
  43. ObjectTypeInitializer.GenericMapping = ExpEventMapping;
  44. ObjectTypeInitializer.PoolType = NonPagedPool;
  45. ObjectTypeInitializer.ValidAccessMask = EVENT_ALL_ACCESS;
  46. ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExEventObjectType);
  47. }
  48. /*
  49. * @implemented
  50. */
  51. NTSTATUS
  52. NTAPI
  53. NtClearEvent(IN HANDLE EventHandle)
  54. {
  55. PKEVENT Event;
  56. NTSTATUS Status;
  57. PAGED_CODE();
  58. /* Reference the Object */
  59. Status = ObReferenceObjectByHandle(EventHandle,
  60. EVENT_MODIFY_STATE,
  61. ExEventObjectType,
  62. ExGetPreviousMode(),
  63. (PVOID*)&Event,
  64. NULL);
  65. /* Check for Success */
  66. if(NT_SUCCESS(Status))
  67. {
  68. /* Clear the Event and Dereference */
  69. KeClearEvent(Event);
  70. ObDereferenceObject(Event);
  71. }
  72. /* Return Status */
  73. return Status;
  74. }
  75. /*
  76. * @implemented
  77. */
  78. NTSTATUS
  79. NTAPI
  80. NtCreateEvent(OUT PHANDLE EventHandle,
  81. IN ACCESS_MASK DesiredAccess,
  82. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  83. IN EVENT_TYPE EventType,
  84. IN BOOLEAN InitialState)
  85. {
  86. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  87. PKEVENT Event;
  88. HANDLE hEvent;
  89. NTSTATUS Status;
  90. PAGED_CODE();
  91. DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n",
  92. EventHandle, DesiredAccess, ObjectAttributes);
  93. /* Check if we were called from user-mode */
  94. if (PreviousMode != KernelMode)
  95. {
  96. /* Enter SEH Block */
  97. _SEH2_TRY
  98. {
  99. /* Check handle pointer */
  100. ProbeForWriteHandle(EventHandle);
  101. }
  102. _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  103. {
  104. /* Return the exception code */
  105. _SEH2_YIELD(return _SEH2_GetExceptionCode());
  106. }
  107. _SEH2_END;
  108. }
  109. /* Create the Object */
  110. Status = ObCreateObject(PreviousMode,
  111. ExEventObjectType,
  112. ObjectAttributes,
  113. PreviousMode,
  114. NULL,
  115. sizeof(KEVENT),
  116. 0,
  117. 0,
  118. (PVOID*)&Event);
  119. /* Check for Success */
  120. if(NT_SUCCESS(Status))
  121. {
  122. /* Initalize the Event */
  123. KeInitializeEvent(Event,
  124. EventType,
  125. InitialState);
  126. /* Insert it */
  127. Status = ObInsertObject((PVOID)Event,
  128. NULL,
  129. DesiredAccess,
  130. 0,
  131. NULL,
  132. &hEvent);
  133. /* Check for success */
  134. if(NT_SUCCESS(Status))
  135. {
  136. /* Enter SEH for return */
  137. _SEH2_TRY
  138. {
  139. /* Return the handle to the caller */
  140. *EventHandle = hEvent;
  141. }
  142. _SEH2_EXCEPT(ExSystemExceptionFilter())
  143. {
  144. /* Get the exception code */
  145. Status = _SEH2_GetExceptionCode();
  146. }
  147. _SEH2_END;
  148. }
  149. }
  150. /* Return Status */
  151. return Status;
  152. }
  153. /*
  154. * @implemented
  155. */
  156. NTSTATUS
  157. NTAPI
  158. NtOpenEvent(OUT PHANDLE EventHandle,
  159. IN ACCESS_MASK DesiredAccess,
  160. IN POBJECT_ATTRIBUTES ObjectAttributes)
  161. {
  162. HANDLE hEvent;
  163. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  164. NTSTATUS Status;
  165. PAGED_CODE();
  166. DPRINT("NtOpenEvent(0x%p, 0x%x, 0x%p)\n",
  167. EventHandle, DesiredAccess, ObjectAttributes);
  168. /* Check if we were called from user-mode */
  169. if (PreviousMode != KernelMode)
  170. {
  171. /* Enter SEH Block */
  172. _SEH2_TRY
  173. {
  174. /* Check handle pointer */
  175. ProbeForWriteHandle(EventHandle);
  176. }
  177. _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  178. {
  179. /* Return the exception code */
  180. _SEH2_YIELD(return _SEH2_GetExceptionCode());
  181. }
  182. _SEH2_END;
  183. }
  184. /* Open the Object */
  185. Status = ObOpenObjectByName(ObjectAttributes,
  186. ExEventObjectType,
  187. PreviousMode,
  188. NULL,
  189. DesiredAccess,
  190. NULL,
  191. &hEvent);
  192. /* Check for success */
  193. if (NT_SUCCESS(Status))
  194. {
  195. /* Enter SEH for return */
  196. _SEH2_TRY
  197. {
  198. /* Return the handle to the caller */
  199. *EventHandle = hEvent;
  200. }
  201. _SEH2_EXCEPT(ExSystemExceptionFilter())
  202. {
  203. /* Get the exception code */
  204. Status = _SEH2_GetExceptionCode();
  205. }
  206. _SEH2_END;
  207. }
  208. /* Return status */
  209. return Status;
  210. }
  211. /*
  212. * @implemented
  213. */
  214. NTSTATUS
  215. NTAPI
  216. NtPulseEvent(IN HANDLE EventHandle,
  217. OUT PLONG PreviousState OPTIONAL)
  218. {
  219. PKEVENT Event;
  220. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  221. NTSTATUS Status;
  222. PAGED_CODE();
  223. DPRINT("NtPulseEvent(EventHandle 0%x PreviousState 0%x)\n",
  224. EventHandle, PreviousState);
  225. /* Check if we were called from user-mode */
  226. if((PreviousState) && (PreviousMode != KernelMode))
  227. {
  228. /* Entry SEH Block */
  229. _SEH2_TRY
  230. {
  231. /* Make sure the state pointer is valid */
  232. ProbeForWriteLong(PreviousState);
  233. }
  234. _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  235. {
  236. /* Return the exception code */
  237. _SEH2_YIELD(return _SEH2_GetExceptionCode());
  238. }
  239. _SEH2_END;
  240. }
  241. /* Open the Object */
  242. Status = ObReferenceObjectByHandle(EventHandle,
  243. EVENT_MODIFY_STATE,
  244. ExEventObjectType,
  245. PreviousMode,
  246. (PVOID*)&Event,
  247. NULL);
  248. /* Check for success */
  249. if(NT_SUCCESS(Status))
  250. {
  251. /* Pulse the Event */
  252. LONG Prev = KePulseEvent(Event, EVENT_INCREMENT, FALSE);
  253. ObDereferenceObject(Event);
  254. /* Check if caller wants the old state back */
  255. if(PreviousState)
  256. {
  257. /* Entry SEH Block for return */
  258. _SEH2_TRY
  259. {
  260. /* Return previous state */
  261. *PreviousState = Prev;
  262. }
  263. _SEH2_EXCEPT(ExSystemExceptionFilter())
  264. {
  265. /* Get the exception code */
  266. Status = _SEH2_GetExceptionCode();
  267. }
  268. _SEH2_END;
  269. }
  270. }
  271. /* Return Status */
  272. return Status;
  273. }
  274. /*
  275. * @implemented
  276. */
  277. NTSTATUS
  278. NTAPI
  279. NtQueryEvent(IN HANDLE EventHandle,
  280. IN EVENT_INFORMATION_CLASS EventInformationClass,
  281. OUT PVOID EventInformation,
  282. IN ULONG EventInformationLength,
  283. OUT PULONG ReturnLength OPTIONAL)
  284. {
  285. PKEVENT Event;
  286. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  287. NTSTATUS Status;
  288. PEVENT_BASIC_INFORMATION BasicInfo =
  289. (PEVENT_BASIC_INFORMATION)EventInformation;
  290. PAGED_CODE();
  291. DPRINT("NtQueryEvent(0x%p, 0x%x)\n", EventHandle, EventInformationClass);
  292. /* Check buffers and class validity */
  293. Status = DefaultQueryInfoBufferCheck(EventInformationClass,
  294. ExEventInfoClass,
  295. sizeof(ExEventInfoClass) /
  296. sizeof(ExEventInfoClass[0]),
  297. EventInformation,
  298. EventInformationLength,
  299. ReturnLength,
  300. NULL,
  301. PreviousMode);
  302. if(!NT_SUCCESS(Status))
  303. {
  304. /* Invalid buffers */
  305. DPRINT("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
  306. return Status;
  307. }
  308. /* Get the Object */
  309. Status = ObReferenceObjectByHandle(EventHandle,
  310. EVENT_QUERY_STATE,
  311. ExEventObjectType,
  312. PreviousMode,
  313. (PVOID*)&Event,
  314. NULL);
  315. /* Check for success */
  316. if(NT_SUCCESS(Status))
  317. {
  318. /* Entry SEH Block */
  319. _SEH2_TRY
  320. {
  321. /* Return Event Type and State */
  322. BasicInfo->EventType = Event->Header.Type;
  323. BasicInfo->EventState = KeReadStateEvent(Event);
  324. /* Return length */
  325. if(ReturnLength) *ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
  326. }
  327. _SEH2_EXCEPT(ExSystemExceptionFilter())
  328. {
  329. /* Get the exception code */
  330. Status = _SEH2_GetExceptionCode();
  331. }
  332. _SEH2_END;
  333. /* Dereference the Object */
  334. ObDereferenceObject(Event);
  335. }
  336. /* Return status */
  337. return Status;
  338. }
  339. /*
  340. * @implemented
  341. */
  342. NTSTATUS
  343. NTAPI
  344. NtResetEvent(IN HANDLE EventHandle,
  345. OUT PLONG PreviousState OPTIONAL)
  346. {
  347. PKEVENT Event;
  348. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  349. NTSTATUS Status;
  350. PAGED_CODE();
  351. DPRINT("NtResetEvent(EventHandle 0%x PreviousState 0%x)\n",
  352. EventHandle, PreviousState);
  353. /* Check if we were called from user-mode */
  354. if ((PreviousState) && (PreviousMode != KernelMode))
  355. {
  356. /* Entry SEH Block */
  357. _SEH2_TRY
  358. {
  359. /* Make sure the state pointer is valid */
  360. ProbeForWriteLong(PreviousState);
  361. }
  362. _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  363. {
  364. /* Return the exception code */
  365. _SEH2_YIELD(return _SEH2_GetExceptionCode());
  366. }
  367. _SEH2_END;
  368. }
  369. /* Open the Object */
  370. Status = ObReferenceObjectByHandle(EventHandle,
  371. EVENT_MODIFY_STATE,
  372. ExEventObjectType,
  373. PreviousMode,
  374. (PVOID*)&Event,
  375. NULL);
  376. /* Check for success */
  377. if(NT_SUCCESS(Status))
  378. {
  379. /* Reset the Event */
  380. LONG Prev = KeResetEvent(Event);
  381. ObDereferenceObject(Event);
  382. /* Check if caller wants the old state back */
  383. if(PreviousState)
  384. {
  385. /* Entry SEH Block for return */
  386. _SEH2_TRY
  387. {
  388. /* Return previous state */
  389. *PreviousState = Prev;
  390. }
  391. _SEH2_EXCEPT(ExSystemExceptionFilter())
  392. {
  393. /* Get the exception code */
  394. Status = _SEH2_GetExceptionCode();
  395. }
  396. _SEH2_END;
  397. }
  398. }
  399. /* Return Status */
  400. return Status;
  401. }
  402. /*
  403. * @implemented
  404. */
  405. NTSTATUS
  406. NTAPI
  407. NtSetEvent(IN HANDLE EventHandle,
  408. OUT PLONG PreviousState OPTIONAL)
  409. {
  410. PKEVENT Event;
  411. KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
  412. NTSTATUS Status;
  413. PAGED_CODE();
  414. DPRINT("NtSetEvent(EventHandle 0%x PreviousState 0%x)\n",
  415. EventHandle, PreviousState);
  416. /* Check if we were called from user-mode */
  417. if ((PreviousState) && (PreviousMode != KernelMode))
  418. {
  419. /* Entry SEH Block */
  420. _SEH2_TRY
  421. {
  422. /* Make sure the state pointer is valid */
  423. ProbeForWriteLong(PreviousState);
  424. }
  425. _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
  426. {
  427. /* Return the exception code */
  428. _SEH2_YIELD(return _SEH2_GetExceptionCode());
  429. }
  430. _SEH2_END;
  431. }
  432. /* Open the Object */
  433. Status = ObReferenceObjectByHandle(EventHandle,
  434. EVENT_MODIFY_STATE,
  435. ExEventObjectType,
  436. PreviousMode,
  437. (PVOID*)&Event,
  438. NULL);
  439. if (NT_SUCCESS(Status))
  440. {
  441. /* Set the Event */
  442. LONG Prev = KeSetEvent(Event, EVENT_INCREMENT, FALSE);
  443. ObDereferenceObject(Event);
  444. /* Check if caller wants the old state back */
  445. if (PreviousState)
  446. {
  447. /* Entry SEH Block for return */
  448. _SEH2_TRY
  449. {
  450. /* Return previous state */
  451. *PreviousState = Prev;
  452. }
  453. _SEH2_EXCEPT(ExSystemExceptionFilter())
  454. {
  455. Status = _SEH2_GetExceptionCode();
  456. }
  457. _SEH2_END;
  458. }
  459. }
  460. /* Return Status */
  461. return Status;
  462. }
  463. /*
  464. * @implemented
  465. */
  466. NTSTATUS
  467. NTAPI
  468. NtSetEventBoostPriority(IN HANDLE EventHandle)
  469. {
  470. PKEVENT Event;
  471. NTSTATUS Status;
  472. PAGED_CODE();
  473. /* Open the Object */
  474. Status = ObReferenceObjectByHandle(EventHandle,
  475. EVENT_MODIFY_STATE,
  476. ExEventObjectType,
  477. ExGetPreviousMode(),
  478. (PVOID*)&Event,
  479. NULL);
  480. if (NT_SUCCESS(Status))
  481. {
  482. /* Set the Event */
  483. KeSetEventBoostPriority(Event, NULL);
  484. ObDereferenceObject(Event);
  485. }
  486. /* Return Status */
  487. return Status;
  488. }
  489. /* EOF */