Windows NT 4.0 source code leak
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.

1764 lines
45 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. synch.c
  5. Abstract:
  6. This module implements all Win32 syncronization
  7. objects.
  8. Author:
  9. Mark Lucovsky (markl) 19-Sep-1990
  10. Revision History:
  11. --*/
  12. #include "basedll.h"
  13. //
  14. // Critical Section Services
  15. //
  16. VOID
  17. InitializeCriticalSection(
  18. LPCRITICAL_SECTION lpCriticalSection
  19. )
  20. /*++
  21. Routine Description:
  22. A critical section object is initialized using
  23. Win32InitializeCriticalSection.
  24. Once a critical section object has been initialized threads within a
  25. single process may enter and exit critical sections using the
  26. critical section object. A critical section object may not me moved
  27. or copied. The application must also not modify the insides of the
  28. object, but must treat it as logically opaque.
  29. description-of-function.
  30. Arguments:
  31. lpCriticalSection - Supplies the address of a critical section object
  32. to be initialized. It is the callers resposibility to allocate
  33. the storage used by a critical section object.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. NTSTATUS Status;
  39. Status = RtlInitializeCriticalSection(lpCriticalSection);
  40. if ( !NT_SUCCESS(Status) ){
  41. RtlRaiseStatus(Status);
  42. }
  43. }
  44. //
  45. // Event Services
  46. //
  47. HANDLE
  48. APIENTRY
  49. CreateEventA(
  50. LPSECURITY_ATTRIBUTES lpEventAttributes,
  51. BOOL bManualReset,
  52. BOOL bInitialState,
  53. LPCSTR lpName
  54. )
  55. /*++
  56. Routine Description:
  57. ANSI thunk to CreateEventW
  58. --*/
  59. {
  60. PUNICODE_STRING Unicode;
  61. ANSI_STRING AnsiString;
  62. NTSTATUS Status;
  63. LPCWSTR NameBuffer;
  64. NameBuffer = NULL;
  65. if ( ARGUMENT_PRESENT(lpName) ) {
  66. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  67. RtlInitAnsiString(&AnsiString,lpName);
  68. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  69. if ( !NT_SUCCESS(Status) ) {
  70. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  71. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  72. }
  73. else {
  74. BaseSetLastNTError(Status);
  75. }
  76. return NULL;
  77. }
  78. NameBuffer = (LPCWSTR)Unicode->Buffer;
  79. }
  80. return CreateEventW(
  81. lpEventAttributes,
  82. bManualReset,
  83. bInitialState,
  84. NameBuffer
  85. );
  86. }
  87. HANDLE
  88. APIENTRY
  89. CreateEventW(
  90. LPSECURITY_ATTRIBUTES lpEventAttributes,
  91. BOOL bManualReset,
  92. BOOL bInitialState,
  93. LPCWSTR lpName
  94. )
  95. /*++
  96. Routine Description:
  97. An event object is created and a handle opened for access to the
  98. object with the CreateEvent function.
  99. The CreateEvent function creates an event object with the specified
  100. initial state. If an event is in the Signaled state (TRUE), a wait
  101. operation on the event does not block. If the event is in the Not-
  102. Signaled state (FALSE), a wait operation on the event blocks until
  103. the specified event attains a state of Signaled, or the timeout
  104. value is exceeded.
  105. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
  106. object type specific access flags are valid for event objects:
  107. - EVENT_MODIFY_STATE - Modify state access (set and reset) to
  108. the event is desired.
  109. - SYNCHRONIZE - Synchronization access (wait) to the event is
  110. desired.
  111. - EVENT_ALL_ACCESS - This set of access flags specifies all of
  112. the possible access flags for an event object.
  113. Arguments:
  114. lpEventAttributes - An optional parameter that may be used to
  115. specify the attributes of the new event. If the parameter is
  116. not specified, then the event is created without a security
  117. descriptor, and the resulting handle is not inherited on process
  118. creation.
  119. bManualReset - Supplies a flag which if TRUE specifies that the
  120. event must be manually reset. If the value is FALSE, then after
  121. releasing a single waiter, the system automaticaly resets the
  122. event.
  123. bInitialState - The initial state of the event object, one of TRUE
  124. or FALSE. If the InitialState is specified as TRUE, the event's
  125. current state value is set to one, otherwise it is set to zero.
  126. lpName - Optional unicode name of event
  127. Return Value:
  128. NON-NULL - Returns a handle to the new event. The handle has full
  129. access to the new event and may be used in any API that requires
  130. a handle to an event object.
  131. FALSE/NULL - The operation failed. Extended error status is available
  132. using GetLastError.
  133. --*/
  134. {
  135. NTSTATUS Status;
  136. OBJECT_ATTRIBUTES Obja;
  137. POBJECT_ATTRIBUTES pObja;
  138. HANDLE Handle;
  139. UNICODE_STRING ObjectName;
  140. if ( ARGUMENT_PRESENT(lpName) ) {
  141. RtlInitUnicodeString(&ObjectName,lpName);
  142. pObja = BaseFormatObjectAttributes(&Obja,lpEventAttributes,&ObjectName);
  143. }
  144. else {
  145. pObja = BaseFormatObjectAttributes(&Obja,lpEventAttributes,NULL);
  146. }
  147. Status = NtCreateEvent(
  148. &Handle,
  149. EVENT_ALL_ACCESS,
  150. pObja,
  151. bManualReset ? NotificationEvent : SynchronizationEvent,
  152. (BOOLEAN)bInitialState
  153. );
  154. if ( NT_SUCCESS(Status) ) {
  155. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  156. SetLastError(ERROR_ALREADY_EXISTS);
  157. }
  158. else {
  159. SetLastError(0);
  160. }
  161. return Handle;
  162. }
  163. else {
  164. BaseSetLastNTError(Status);
  165. return NULL;
  166. }
  167. }
  168. HANDLE
  169. APIENTRY
  170. OpenEventA(
  171. DWORD dwDesiredAccess,
  172. BOOL bInheritHandle,
  173. LPCSTR lpName
  174. )
  175. /*++
  176. Routine Description:
  177. ANSI thunk to OpenNamedEventW
  178. --*/
  179. {
  180. PUNICODE_STRING Unicode;
  181. ANSI_STRING AnsiString;
  182. NTSTATUS Status;
  183. if ( ARGUMENT_PRESENT(lpName) ) {
  184. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  185. RtlInitAnsiString(&AnsiString,lpName);
  186. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  187. if ( !NT_SUCCESS(Status) ) {
  188. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  189. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  190. }
  191. else {
  192. BaseSetLastNTError(Status);
  193. }
  194. return NULL;
  195. }
  196. }
  197. else {
  198. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  199. return NULL;
  200. }
  201. return OpenEventW(
  202. dwDesiredAccess,
  203. bInheritHandle,
  204. (LPCWSTR)Unicode->Buffer
  205. );
  206. }
  207. HANDLE
  208. APIENTRY
  209. OpenEventW(
  210. DWORD dwDesiredAccess,
  211. BOOL bInheritHandle,
  212. LPCWSTR lpName
  213. )
  214. {
  215. OBJECT_ATTRIBUTES Obja;
  216. UNICODE_STRING ObjectName;
  217. NTSTATUS Status;
  218. HANDLE Object;
  219. if ( !lpName ) {
  220. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  221. return NULL;
  222. }
  223. RtlInitUnicodeString(&ObjectName,lpName);
  224. InitializeObjectAttributes(
  225. &Obja,
  226. &ObjectName,
  227. (bInheritHandle ? OBJ_INHERIT : 0),
  228. BaseGetNamedObjectDirectory(),
  229. NULL
  230. );
  231. Status = NtOpenEvent(
  232. &Object,
  233. dwDesiredAccess,
  234. &Obja
  235. );
  236. if ( !NT_SUCCESS(Status) ) {
  237. BaseSetLastNTError(Status);
  238. return NULL;
  239. }
  240. return Object;
  241. }
  242. BOOL
  243. SetEvent(
  244. HANDLE hEvent
  245. )
  246. /*++
  247. Routine Description:
  248. An event can be set to the signaled state (TRUE) with the SetEvent
  249. function.
  250. Setting the event causes the event to attain a state of Signaled,
  251. which releases all currently waiting threads (for manual reset
  252. events), or a single waiting thread (for automatic reset events).
  253. Arguments:
  254. hEvent - Supplies an open handle to an event object. The
  255. handle must have EVENT_MODIFY_STATE access to the event.
  256. Return Value:
  257. TRUE - The operation was successful
  258. FALSE/NULL - The operation failed. Extended error status is available
  259. using GetLastError.
  260. --*/
  261. {
  262. NTSTATUS Status;
  263. Status = NtSetEvent(hEvent,NULL);
  264. if ( NT_SUCCESS(Status) ) {
  265. return TRUE;
  266. }
  267. else {
  268. BaseSetLastNTError(Status);
  269. return FALSE;
  270. }
  271. }
  272. BOOL
  273. ResetEvent(
  274. HANDLE hEvent
  275. )
  276. /*++
  277. Routine Description:
  278. The state of an event is set to the Not-Signaled state (FALSE) using
  279. the ClearEvent function.
  280. Once the event attains a state of Not-Signaled, any threads which
  281. wait on the event block, awaiting the event to become Signaled. The
  282. reset event service sets the event count to zero for the state of
  283. the event.
  284. Arguments:
  285. hEvent - Supplies an open handle to an event object. The
  286. handle must have EVENT_MODIFY_STATE access to the event.
  287. Return Value:
  288. TRUE - The operation was successful
  289. FALSE/NULL - The operation failed. Extended error status is available
  290. using GetLastError.
  291. --*/
  292. {
  293. NTSTATUS Status;
  294. Status = NtClearEvent(hEvent);
  295. if ( NT_SUCCESS(Status) ) {
  296. return TRUE;
  297. }
  298. else {
  299. BaseSetLastNTError(Status);
  300. return FALSE;
  301. }
  302. }
  303. BOOL
  304. PulseEvent(
  305. HANDLE hEvent
  306. )
  307. /*++
  308. Routine Description:
  309. An event can be set to the Signaled state and reset to the Not-
  310. Signaled state atomically with the PulseEvent function.
  311. Pulsing the event causes the event to attain a state of Signaled,
  312. release appropriate threads, and then reset the event. When no
  313. waiters are currently waiting on the event, pulsing an event causes
  314. the event to release no threads and end up in the Not-Signaled
  315. state. With waiters waiting on an event, pulsing an event has a
  316. different effect for manual reset events that it does for automatic
  317. reset events. For manual reset events, pulsing releases all waiters
  318. and then leaves the event in the Not-Signaled state. For automatic
  319. reset events, pulsing the event releases a single waiter and then
  320. leaves the event in the Not-Signaled state.
  321. Arguments:
  322. hEvent - Supplies an open handle to an event object. The
  323. handle must have EVENT_MODIFY_STATE access to the event.
  324. Return Value:
  325. TRUE - The operation was successful
  326. FALSE/NULL - The operation failed. Extended error status is available
  327. using GetLastError.
  328. --*/
  329. {
  330. NTSTATUS Status;
  331. Status = NtPulseEvent(hEvent,NULL);
  332. if ( NT_SUCCESS(Status) ) {
  333. return TRUE;
  334. }
  335. else {
  336. BaseSetLastNTError(Status);
  337. return FALSE;
  338. }
  339. }
  340. //
  341. // Semaphore Services
  342. //
  343. HANDLE
  344. APIENTRY
  345. CreateSemaphoreA(
  346. LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  347. LONG lInitialCount,
  348. LONG lMaximumCount,
  349. LPCSTR lpName
  350. )
  351. /*++
  352. Routine Description:
  353. ANSI thunk to CreateSemaphoreW
  354. --*/
  355. {
  356. PUNICODE_STRING Unicode;
  357. ANSI_STRING AnsiString;
  358. NTSTATUS Status;
  359. LPCWSTR NameBuffer;
  360. NameBuffer = NULL;
  361. if ( ARGUMENT_PRESENT(lpName) ) {
  362. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  363. RtlInitAnsiString(&AnsiString,lpName);
  364. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  365. if ( !NT_SUCCESS(Status) ) {
  366. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  367. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  368. }
  369. else {
  370. BaseSetLastNTError(Status);
  371. }
  372. return NULL;
  373. }
  374. NameBuffer = (LPCWSTR)Unicode->Buffer;
  375. }
  376. return CreateSemaphoreW(
  377. lpSemaphoreAttributes,
  378. lInitialCount,
  379. lMaximumCount,
  380. NameBuffer
  381. );
  382. }
  383. HANDLE
  384. APIENTRY
  385. CreateSemaphoreW(
  386. LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  387. LONG lInitialCount,
  388. LONG lMaximumCount,
  389. LPCWSTR lpName
  390. )
  391. /*++
  392. Routine Description:
  393. A semaphore object is created and a handle opened for access to the
  394. object with the CreateSemaphore function.
  395. The CreateSemaphore function causes a semaphore object to be created
  396. which contains the specified initial and maximum counts.
  397. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the
  398. following object type specific access flags are valid for semaphore
  399. objects:
  400. - SEMAPHORE_MODIFY_STATE - Modify state access (release) to the
  401. semaphore is desired.
  402. - SYNCHRONIZE - Synchronization access (wait) to the semaphore
  403. is desired.
  404. - SEMAPHORE_ALL_ACCESS - This set of access flags specifies all
  405. of the possible access flags for a semaphore object.
  406. Arguments:
  407. lpSemaphoreAttributes - An optional parameter that may be used to
  408. specify the attributes of the new semaphore. If the parameter
  409. is not specified, then the semaphore is created without a
  410. security descriptor, , and the resulting handle is not inherited
  411. on process creation.
  412. lInitialCount - The initial count for the semaphore, this value
  413. must be positive and less than or equal to the maximum count.
  414. lMaximumCount - The maximum count for the semaphore, this value
  415. must be greater than zero..
  416. lpName - Supplies an optional unicode name for the object.
  417. Return Value:
  418. NON-NULL - Returns a handle to the new semaphore. The handle has
  419. full access to the new semaphore and may be used in any API that
  420. requires a handle to a semaphore object.
  421. FALSE/NULL - The operation failed. Extended error status is available
  422. using GetLastError.
  423. --*/
  424. {
  425. NTSTATUS Status;
  426. OBJECT_ATTRIBUTES Obja;
  427. POBJECT_ATTRIBUTES pObja;
  428. HANDLE Handle;
  429. UNICODE_STRING ObjectName;
  430. if ( ARGUMENT_PRESENT(lpName) ) {
  431. RtlInitUnicodeString(&ObjectName,lpName);
  432. pObja = BaseFormatObjectAttributes(&Obja,lpSemaphoreAttributes,&ObjectName);
  433. }
  434. else {
  435. pObja = BaseFormatObjectAttributes(&Obja,lpSemaphoreAttributes,NULL);
  436. }
  437. Status = NtCreateSemaphore(
  438. &Handle,
  439. SEMAPHORE_ALL_ACCESS,
  440. pObja,
  441. lInitialCount,
  442. lMaximumCount
  443. );
  444. if ( NT_SUCCESS(Status) ) {
  445. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  446. SetLastError(ERROR_ALREADY_EXISTS);
  447. }
  448. else {
  449. SetLastError(0);
  450. }
  451. return Handle;
  452. }
  453. else {
  454. BaseSetLastNTError(Status);
  455. return NULL;
  456. }
  457. }
  458. HANDLE
  459. APIENTRY
  460. OpenSemaphoreA(
  461. DWORD dwDesiredAccess,
  462. BOOL bInheritHandle,
  463. LPCSTR lpName
  464. )
  465. /*++
  466. Routine Description:
  467. ANSI thunk to OpenSemaphoreW
  468. --*/
  469. {
  470. PUNICODE_STRING Unicode;
  471. ANSI_STRING AnsiString;
  472. NTSTATUS Status;
  473. if ( ARGUMENT_PRESENT(lpName) ) {
  474. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  475. RtlInitAnsiString(&AnsiString,lpName);
  476. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  477. if ( !NT_SUCCESS(Status) ) {
  478. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  479. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  480. }
  481. else {
  482. BaseSetLastNTError(Status);
  483. }
  484. return NULL;
  485. }
  486. }
  487. else {
  488. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  489. return NULL;
  490. }
  491. return OpenSemaphoreW(
  492. dwDesiredAccess,
  493. bInheritHandle,
  494. (LPCWSTR)Unicode->Buffer
  495. );
  496. }
  497. HANDLE
  498. APIENTRY
  499. OpenSemaphoreW(
  500. DWORD dwDesiredAccess,
  501. BOOL bInheritHandle,
  502. LPCWSTR lpName
  503. )
  504. {
  505. OBJECT_ATTRIBUTES Obja;
  506. UNICODE_STRING ObjectName;
  507. NTSTATUS Status;
  508. HANDLE Object;
  509. if ( !lpName ) {
  510. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  511. return NULL;
  512. }
  513. RtlInitUnicodeString(&ObjectName,lpName);
  514. InitializeObjectAttributes(
  515. &Obja,
  516. &ObjectName,
  517. (bInheritHandle ? OBJ_INHERIT : 0),
  518. BaseGetNamedObjectDirectory(),
  519. NULL
  520. );
  521. Status = NtOpenSemaphore(
  522. &Object,
  523. dwDesiredAccess,
  524. &Obja
  525. );
  526. if ( !NT_SUCCESS(Status) ) {
  527. BaseSetLastNTError(Status);
  528. return NULL;
  529. }
  530. return Object;
  531. }
  532. BOOL
  533. ReleaseSemaphore(
  534. HANDLE hSemaphore,
  535. LONG lReleaseCount,
  536. LPLONG lpPreviousCount
  537. )
  538. /*++
  539. Routine Description:
  540. A semaphore object can be released with the ReleaseSemaphore
  541. function.
  542. When the semaphore is released, the current count of the semaphore
  543. is incremented by the ReleaseCount. Any threads that are waiting
  544. for the semaphore are examined to see if the current semaphore value
  545. is sufficient to satisfy their wait.
  546. If the value specified by ReleaseCount would cause the maximum count
  547. for the semaphore to be exceeded, then the count for the semaphore
  548. is not affected and an error status is returned.
  549. Arguments:
  550. hSemaphore - Supplies an open handle to a semaphore object. The
  551. handle must have SEMAPHORE_MODIFY_STATE access to the semaphore.
  552. lReleaseCount - The release count for the semaphore. The count
  553. must be greater than zero and less than the maximum value
  554. specified for the semaphore.
  555. lpPreviousCount - An optional pointer to a variable that receives
  556. the previous count for the semaphore.
  557. Return Value:
  558. TRUE - The operation was successful
  559. FALSE/NULL - The operation failed. Extended error status is available
  560. using GetLastError.
  561. --*/
  562. {
  563. NTSTATUS Status;
  564. Status = NtReleaseSemaphore(hSemaphore,lReleaseCount,lpPreviousCount);
  565. if ( NT_SUCCESS(Status) ) {
  566. return TRUE;
  567. }
  568. else {
  569. BaseSetLastNTError(Status);
  570. return FALSE;
  571. }
  572. }
  573. //
  574. // Mutex Services
  575. //
  576. HANDLE
  577. APIENTRY
  578. CreateMutexA(
  579. LPSECURITY_ATTRIBUTES lpMutexAttributes,
  580. BOOL bInitialOwner,
  581. LPCSTR lpName
  582. )
  583. /*++
  584. Routine Description:
  585. ANSI thunk to CreateMutexW
  586. --*/
  587. {
  588. PUNICODE_STRING Unicode;
  589. ANSI_STRING AnsiString;
  590. NTSTATUS Status;
  591. LPCWSTR NameBuffer;
  592. NameBuffer = NULL;
  593. if ( ARGUMENT_PRESENT(lpName) ) {
  594. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  595. RtlInitAnsiString(&AnsiString,lpName);
  596. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  597. if ( !NT_SUCCESS(Status) ) {
  598. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  599. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  600. }
  601. else {
  602. BaseSetLastNTError(Status);
  603. }
  604. return NULL;
  605. }
  606. NameBuffer = (LPCWSTR)Unicode->Buffer;
  607. }
  608. return CreateMutexW(
  609. lpMutexAttributes,
  610. bInitialOwner,
  611. NameBuffer
  612. );
  613. }
  614. HANDLE
  615. APIENTRY
  616. CreateMutexW(
  617. LPSECURITY_ATTRIBUTES lpMutexAttributes,
  618. BOOL bInitialOwner,
  619. LPCWSTR lpName
  620. )
  621. /*++
  622. Routine Description:
  623. A mutex object can be created and a handle opened for access to the
  624. object with the CreateMutex function.
  625. A new mutex object is created and a handle opened to the object with
  626. ownership as determined by the InitialOwner parameter. The status
  627. of the newly created mutex object is set to not abandoned.
  628. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the
  629. following object type specific access flags are valid for mutex
  630. objects:
  631. - MUTEX_MODIFY_STATE - Modify access to the mutex is desired.
  632. This allows a process to release a mutex.
  633. - SYNCHRONIZE - Synchronization access (wait or release) to the
  634. mutex object is desired.
  635. - MUTEX_ALL_ACCESS - All possible types of access to the mutex
  636. object are desired.
  637. Arguments:
  638. lpMutexAttributes - An optional parameter that may be used to specify
  639. the attributes of the new mutex. If the parameter is not
  640. specified, then the mutex is created without a security
  641. descriptor, and the resulting handle is not inherited on process
  642. creation.
  643. bInitialOwner - A boolean value that determines whether the creator
  644. of the object desires immediate ownership of the mutex object.
  645. lpName - Supplies an optional unicode name for the mutex.
  646. Return Value:
  647. NON-NULL - Returns a handle to the new mutex. The handle has full
  648. access to the new mutex and may be used in any API that
  649. requires a handle to a mutex object.
  650. FALSE/NULL - The operation failed. Extended error status is available
  651. using GetLastError.
  652. --*/
  653. {
  654. NTSTATUS Status;
  655. OBJECT_ATTRIBUTES Obja;
  656. POBJECT_ATTRIBUTES pObja;
  657. HANDLE Handle;
  658. UNICODE_STRING ObjectName;
  659. if ( ARGUMENT_PRESENT(lpName) ) {
  660. RtlInitUnicodeString(&ObjectName,lpName);
  661. pObja = BaseFormatObjectAttributes(&Obja,lpMutexAttributes,&ObjectName);
  662. }
  663. else {
  664. pObja = BaseFormatObjectAttributes(&Obja,lpMutexAttributes,NULL);
  665. }
  666. Status = NtCreateMutant(
  667. &Handle,
  668. MUTANT_ALL_ACCESS,
  669. pObja,
  670. (BOOLEAN)bInitialOwner
  671. );
  672. if ( NT_SUCCESS(Status) ) {
  673. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  674. SetLastError(ERROR_ALREADY_EXISTS);
  675. }
  676. else {
  677. SetLastError(0);
  678. }
  679. return Handle;
  680. }
  681. else {
  682. BaseSetLastNTError(Status);
  683. return NULL;
  684. }
  685. }
  686. HANDLE
  687. APIENTRY
  688. OpenMutexA(
  689. DWORD dwDesiredAccess,
  690. BOOL bInheritHandle,
  691. LPCSTR lpName
  692. )
  693. /*++
  694. Routine Description:
  695. ANSI thunk to OpenMutexW
  696. --*/
  697. {
  698. PUNICODE_STRING Unicode;
  699. ANSI_STRING AnsiString;
  700. NTSTATUS Status;
  701. if ( ARGUMENT_PRESENT(lpName) ) {
  702. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  703. RtlInitAnsiString(&AnsiString,lpName);
  704. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  705. if ( !NT_SUCCESS(Status) ) {
  706. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  707. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  708. }
  709. else {
  710. BaseSetLastNTError(Status);
  711. }
  712. return NULL;
  713. }
  714. }
  715. else {
  716. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  717. return NULL;
  718. }
  719. return OpenMutexW(
  720. dwDesiredAccess,
  721. bInheritHandle,
  722. (LPCWSTR)Unicode->Buffer
  723. );
  724. }
  725. HANDLE
  726. APIENTRY
  727. OpenMutexW(
  728. DWORD dwDesiredAccess,
  729. BOOL bInheritHandle,
  730. LPCWSTR lpName
  731. )
  732. {
  733. OBJECT_ATTRIBUTES Obja;
  734. UNICODE_STRING ObjectName;
  735. NTSTATUS Status;
  736. HANDLE Object;
  737. if ( !lpName ) {
  738. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  739. return NULL;
  740. }
  741. RtlInitUnicodeString(&ObjectName,lpName);
  742. InitializeObjectAttributes(
  743. &Obja,
  744. &ObjectName,
  745. (bInheritHandle ? OBJ_INHERIT : 0),
  746. BaseGetNamedObjectDirectory(),
  747. NULL
  748. );
  749. Status = NtOpenMutant(
  750. &Object,
  751. dwDesiredAccess,
  752. &Obja
  753. );
  754. if ( !NT_SUCCESS(Status) ) {
  755. BaseSetLastNTError(Status);
  756. return NULL;
  757. }
  758. return Object;
  759. }
  760. BOOL
  761. ReleaseMutex(
  762. HANDLE hMutex
  763. )
  764. /*++
  765. Routine Description:
  766. Ownership of a mutex object can be released with the ReleaseMutex
  767. function.
  768. A mutex object can only be released by a thread that currently owns
  769. the mutex object. When the mutex is released, the current count of
  770. the mutex object is incremented by one. If the resultant count is
  771. one, then the mutex object is no longer owned. Any threads that are
  772. waiting for the mutex object are examined to see if their wait can
  773. be satisfied.
  774. Arguments:
  775. hMutex - An open handle to a mutex object. The handle must
  776. have MUTEX_MODIFY_STATE access to the mutex.
  777. Return Value:
  778. TRUE - The operation was successful
  779. FALSE/NULL - The operation failed. Extended error status is available
  780. using GetLastError.
  781. --*/
  782. {
  783. NTSTATUS Status;
  784. Status = NtReleaseMutant(hMutex,NULL);
  785. if ( NT_SUCCESS(Status) ) {
  786. return TRUE;
  787. }
  788. else {
  789. BaseSetLastNTError(Status);
  790. return FALSE;
  791. }
  792. }
  793. //
  794. // Wait Services
  795. //
  796. DWORD
  797. WaitForSingleObject(
  798. HANDLE hHandle,
  799. DWORD dwMilliseconds
  800. )
  801. /*++
  802. Routine Description:
  803. A wait operation on a waitable object is accomplished with the
  804. WaitForSingleObject function.
  805. Waiting on an object checks the current state of the object. If the
  806. current state of the object allows continued execution, any
  807. adjustments to the object state are made (for example, decrementing
  808. the semaphore count for a semaphore object) and the thread continues
  809. execution. If the current state of the object does not allow
  810. continued execution, the thread is placed into the wait state
  811. pending the change of the object's state or time-out.
  812. Arguments:
  813. hHandle - An open handle to a waitable object. The handle must have
  814. SYNCHRONIZE access to the object.
  815. dwMilliseconds - A time-out value that specifies the relative time,
  816. in milliseconds, over which the wait is to be completed. A
  817. timeout value of 0 specified that the wait is to timeout
  818. immediately. This allows an application to test an object to
  819. determine if it is in the signaled state. A timeout value of -1
  820. specifies an infinite timeout period.
  821. Return Value:
  822. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  823. TimeOut conditions.
  824. 0 - indicates the specified object attained a Signaled
  825. state thus completing the wait.
  826. WAIT_ABANDONED - indicates the specified object attained a Signaled
  827. state but was abandoned.
  828. --*/
  829. {
  830. return WaitForSingleObjectEx(hHandle,dwMilliseconds,FALSE);
  831. }
  832. DWORD
  833. APIENTRY
  834. WaitForSingleObjectEx(
  835. HANDLE hHandle,
  836. DWORD dwMilliseconds,
  837. BOOL bAlertable
  838. )
  839. /*++
  840. Routine Description:
  841. A wait operation on a waitable object is accomplished with the
  842. WaitForSingleObjectEx function.
  843. Waiting on an object checks the current state of the object. If the
  844. current state of the object allows continued execution, any
  845. adjustments to the object state are made (for example, decrementing
  846. the semaphore count for a semaphore object) and the thread continues
  847. execution. If the current state of the object does not allow
  848. continued execution, the thread is placed into the wait state
  849. pending the change of the object's state or time-out.
  850. If the bAlertable parameter is FALSE, the only way the wait
  851. terminates is because the specified timeout period expires, or
  852. because the specified object entered the signaled state. If the
  853. bAlertable parameter is TRUE, then the wait can return due to any
  854. one of the above wait termination conditions, or because an I/O
  855. completion callback terminated the wait early (return value of
  856. WAIT_IO_COMPLETION).
  857. Arguments:
  858. hHandle - An open handle to a waitable object. The handle must have
  859. SYNCHRONIZE access to the object.
  860. dwMilliseconds - A time-out value that specifies the relative time,
  861. in milliseconds, over which the wait is to be completed. A
  862. timeout value of 0 specified that the wait is to timeout
  863. immediately. This allows an application to test an object to
  864. determine if it is in the signaled state. A timeout value of
  865. 0xffffffff specifies an infinite timeout period.
  866. bAlertable - Supplies a flag that controls whether or not the
  867. wait may terminate early due to an I/O completion callback.
  868. A value of TRUE allows this API to complete early due to an I/O
  869. completion callback. A value of FALSE will not allow I/O
  870. completion callbacks to terminate this call early.
  871. Return Value:
  872. WAIT_TIME_OUT - Indicates that the wait was terminated due to the
  873. TimeOut conditions.
  874. 0 - indicates the specified object attained a Signaled
  875. state thus completing the wait.
  876. 0xffffffff - The wait terminated due to an error. GetLastError may be
  877. used to get additional error information.
  878. WAIT_ABANDONED - indicates the specified object attained a Signaled
  879. state but was abandoned.
  880. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  881. completion callbacks.
  882. --*/
  883. {
  884. NTSTATUS Status;
  885. LARGE_INTEGER TimeOut;
  886. PLARGE_INTEGER pTimeOut;
  887. PPEB Peb;
  888. Peb = NtCurrentPeb();
  889. switch( (DWORD)hHandle ) {
  890. case STD_INPUT_HANDLE: hHandle = Peb->ProcessParameters->StandardInput;
  891. break;
  892. case STD_OUTPUT_HANDLE: hHandle = Peb->ProcessParameters->StandardOutput;
  893. break;
  894. case STD_ERROR_HANDLE: hHandle = Peb->ProcessParameters->StandardError;
  895. break;
  896. }
  897. if (CONSOLE_HANDLE(hHandle) && VerifyConsoleIoHandle(hHandle)) {
  898. hHandle = GetConsoleInputWaitHandle();
  899. }
  900. pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
  901. rewait:
  902. Status = NtWaitForSingleObject(hHandle,(BOOLEAN)bAlertable,pTimeOut);
  903. if ( !NT_SUCCESS(Status) ) {
  904. BaseSetLastNTError(Status);
  905. Status = (NTSTATUS)0xffffffff;
  906. }
  907. else {
  908. if ( bAlertable && Status == STATUS_ALERTED ) {
  909. goto rewait;
  910. }
  911. }
  912. return (DWORD)Status;
  913. }
  914. DWORD
  915. WINAPI
  916. SignalObjectAndWait(
  917. HANDLE hObjectToSignal,
  918. HANDLE hObjectToWaitOn,
  919. DWORD dwMilliseconds,
  920. BOOL bAlertable
  921. )
  922. {
  923. NTSTATUS Status;
  924. LARGE_INTEGER TimeOut;
  925. PLARGE_INTEGER pTimeOut;
  926. PPEB Peb;
  927. Peb = NtCurrentPeb();
  928. switch( (DWORD)hObjectToWaitOn ) {
  929. case STD_INPUT_HANDLE: hObjectToWaitOn = Peb->ProcessParameters->StandardInput;
  930. break;
  931. case STD_OUTPUT_HANDLE: hObjectToWaitOn = Peb->ProcessParameters->StandardOutput;
  932. break;
  933. case STD_ERROR_HANDLE: hObjectToWaitOn = Peb->ProcessParameters->StandardError;
  934. break;
  935. }
  936. if (CONSOLE_HANDLE(hObjectToWaitOn) && VerifyConsoleIoHandle(hObjectToWaitOn)) {
  937. hObjectToWaitOn = GetConsoleInputWaitHandle();
  938. }
  939. pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
  940. rewait:
  941. Status = NtSignalAndWaitForSingleObject(
  942. hObjectToSignal,
  943. hObjectToWaitOn,
  944. (BOOLEAN)bAlertable,
  945. pTimeOut
  946. );
  947. if ( !NT_SUCCESS(Status) ) {
  948. BaseSetLastNTError(Status);
  949. Status = (NTSTATUS)0xffffffff;
  950. }
  951. else {
  952. if ( bAlertable && Status == STATUS_ALERTED ) {
  953. goto rewait;
  954. }
  955. }
  956. return (DWORD)Status;
  957. }
  958. DWORD
  959. WaitForMultipleObjects(
  960. DWORD nCount,
  961. CONST HANDLE *lpHandles,
  962. BOOL bWaitAll,
  963. DWORD dwMilliseconds
  964. )
  965. /*++
  966. Routine Description:
  967. A wait operation on multiple waitable objects (up to
  968. MAXIMUM_WAIT_OBJECTS) is accomplished with the WaitForMultipleObjects
  969. function.
  970. Arguments:
  971. nCount - A count of the number of objects that are to be waited on.
  972. lpHandles - An array of object handles. Each handle must have
  973. SYNCHRONIZE access to the associated object.
  974. bWaitAll - A flag that supplies the wait type. A value of TRUE
  975. indicates a "wait all". A value of false indicates a "wait
  976. any".
  977. dwMilliseconds - A time-out value that specifies the relative time,
  978. in milliseconds, over which the wait is to be completed. A
  979. timeout value of 0 specified that the wait is to timeout
  980. immediately. This allows an application to test an object to
  981. determine if it is in the signaled state. A timeout value of -1
  982. specifies an infinite timeout period.
  983. Return Value:
  984. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  985. TimeOut conditions.
  986. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  987. object, the object number which satisfied the wait. In the case
  988. of wait for all objects, the value only indicates that the wait
  989. was completed successfully.
  990. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  991. indicates, in the case of wait for any object, the object number
  992. which satisfied the event, and that the object which satisfied
  993. the event was abandoned. In the case of wait for all objects,
  994. the value indicates that the wait was completed successfully and
  995. at least one of the objects was abandoned.
  996. --*/
  997. {
  998. return WaitForMultipleObjectsEx(nCount,lpHandles,bWaitAll,dwMilliseconds,FALSE);
  999. }
  1000. DWORD
  1001. APIENTRY
  1002. WaitForMultipleObjectsEx(
  1003. DWORD nCount,
  1004. CONST HANDLE *lpHandles,
  1005. BOOL bWaitAll,
  1006. DWORD dwMilliseconds,
  1007. BOOL bAlertable
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. A wait operation on multiple waitable objects (up to
  1012. MAXIMUM_WAIT_OBJECTS) is accomplished with the
  1013. WaitForMultipleObjects function.
  1014. This API can be used to wait on any of the specified objects to
  1015. enter the signaled state, or all of the objects to enter the
  1016. signaled state.
  1017. If the bAlertable parameter is FALSE, the only way the wait
  1018. terminates is because the specified timeout period expires, or
  1019. because the specified objects entered the signaled state. If the
  1020. bAlertable parameter is TRUE, then the wait can return due to any one of
  1021. the above wait termination conditions, or because an I/O completion
  1022. callback terminated the wait early (return value of
  1023. WAIT_IO_COMPLETION).
  1024. Arguments:
  1025. nCount - A count of the number of objects that are to be waited on.
  1026. lpHandles - An array of object handles. Each handle must have
  1027. SYNCHRONIZE access to the associated object.
  1028. bWaitAll - A flag that supplies the wait type. A value of TRUE
  1029. indicates a "wait all". A value of false indicates a "wait
  1030. any".
  1031. dwMilliseconds - A time-out value that specifies the relative time,
  1032. in milliseconds, over which the wait is to be completed. A
  1033. timeout value of 0 specified that the wait is to timeout
  1034. immediately. This allows an application to test an object to
  1035. determine if it is in the signaled state. A timeout value of
  1036. 0xffffffff specifies an infinite timeout period.
  1037. bAlertable - Supplies a flag that controls whether or not the
  1038. wait may terminate early due to an I/O completion callback.
  1039. A value of TRUE allows this API to complete early due to an I/O
  1040. completion callback. A value of FALSE will not allow I/O
  1041. completion callbacks to terminate this call early.
  1042. Return Value:
  1043. WAIT_TIME_OUT - indicates that the wait was terminated due to the
  1044. TimeOut conditions.
  1045. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any
  1046. object, the object number which satisfied the wait. In the case
  1047. of wait for all objects, the value only indicates that the wait
  1048. was completed successfully.
  1049. 0xffffffff - The wait terminated due to an error. GetLastError may be
  1050. used to get additional error information.
  1051. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1),
  1052. indicates, in the case of wait for any object, the object number
  1053. which satisfied the event, and that the object which satisfied
  1054. the event was abandoned. In the case of wait for all objects,
  1055. the value indicates that the wait was completed successfully and
  1056. at least one of the objects was abandoned.
  1057. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O
  1058. completion callbacks.
  1059. --*/
  1060. {
  1061. NTSTATUS Status;
  1062. LARGE_INTEGER TimeOut;
  1063. PLARGE_INTEGER pTimeOut;
  1064. DWORD i;
  1065. LPHANDLE HandleArray;
  1066. HANDLE Handles[ 8 ];
  1067. PPEB Peb;
  1068. if (nCount > 8) {
  1069. HandleArray = (LPHANDLE) RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nCount*sizeof(HANDLE));
  1070. if (HandleArray == NULL) {
  1071. BaseSetLastNTError(STATUS_NO_MEMORY);
  1072. return 0xffffffff;
  1073. }
  1074. } else {
  1075. HandleArray = Handles;
  1076. }
  1077. RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE));
  1078. Peb = NtCurrentPeb();
  1079. for (i=0;i<nCount;i++) {
  1080. switch( (DWORD)HandleArray[i] ) {
  1081. case STD_INPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardInput;
  1082. break;
  1083. case STD_OUTPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardOutput;
  1084. break;
  1085. case STD_ERROR_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardError;
  1086. break;
  1087. }
  1088. if (CONSOLE_HANDLE(HandleArray[i]) && VerifyConsoleIoHandle(HandleArray[i])) {
  1089. HandleArray[i] = GetConsoleInputWaitHandle();
  1090. }
  1091. }
  1092. pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
  1093. rewait:
  1094. Status = NtWaitForMultipleObjects(
  1095. (CHAR)nCount,
  1096. HandleArray,
  1097. bWaitAll ? WaitAll : WaitAny,
  1098. (BOOLEAN)bAlertable,
  1099. pTimeOut
  1100. );
  1101. if ( !NT_SUCCESS(Status) ) {
  1102. BaseSetLastNTError(Status);
  1103. Status = (NTSTATUS)0xffffffff;
  1104. }
  1105. else {
  1106. if ( bAlertable && Status == STATUS_ALERTED ) {
  1107. goto rewait;
  1108. }
  1109. }
  1110. if (HandleArray != Handles) {
  1111. RtlFreeHeap(RtlProcessHeap(), 0, HandleArray);
  1112. }
  1113. return (DWORD)Status;
  1114. }
  1115. VOID
  1116. Sleep(
  1117. DWORD dwMilliseconds
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. The execution of the current thread can be delayed for a specified
  1122. interval of time with the Sleep function.
  1123. The Sleep function causes the current thread to enter a
  1124. waiting state until the specified interval of time has passed.
  1125. Arguments:
  1126. dwMilliseconds - A time-out value that specifies the relative time,
  1127. in milliseconds, over which the wait is to be completed. A
  1128. timeout value of 0 specified that the wait is to timeout
  1129. immediately. This allows an application to test an object to
  1130. determine if it is in the signaled state. A timeout value of -1
  1131. specifies an infinite timeout period.
  1132. Return Value:
  1133. None.
  1134. --*/
  1135. {
  1136. SleepEx(dwMilliseconds,FALSE);
  1137. }
  1138. DWORD
  1139. APIENTRY
  1140. SleepEx(
  1141. DWORD dwMilliseconds,
  1142. BOOL bAlertable
  1143. )
  1144. /*++
  1145. Routine Description:
  1146. The execution of the current thread can be delayed for a specified
  1147. interval of time with the SleepEx function.
  1148. The SleepEx function causes the current thread to enter a waiting
  1149. state until the specified interval of time has passed.
  1150. If the bAlertable parameter is FALSE, the only way the SleepEx
  1151. returns is when the specified time interval has passed. If the
  1152. bAlertable parameter is TRUE, then the SleepEx can return due to the
  1153. expiration of the time interval (return value of 0), or because an
  1154. I/O completion callback terminated the SleepEx early (return value
  1155. of WAIT_IO_COMPLETION).
  1156. Arguments:
  1157. dwMilliseconds - A time-out value that specifies the relative time,
  1158. in milliseconds, over which the wait is to be completed. A
  1159. timeout value of 0 specified that the wait is to timeout
  1160. immediately. A timeout value of -1 specifies an infinite
  1161. timeout period.
  1162. bAlertable - Supplies a flag that controls whether or not the
  1163. SleepEx may terminate early due to an I/O completion callback.
  1164. A value of TRUE allows this API to complete early due to an I/O
  1165. completion callback. A value of FALSE will not allow I/O
  1166. completion callbacks to terminate this call early.
  1167. Return Value:
  1168. 0 - The SleepEx terminated due to expiration of the time interval.
  1169. WAIT_IO_COMPLETION - The SleepEx terminated due to one or more I/O
  1170. completion callbacks.
  1171. --*/
  1172. {
  1173. LARGE_INTEGER TimeOut;
  1174. PLARGE_INTEGER pTimeOut;
  1175. NTSTATUS Status;
  1176. pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
  1177. if (pTimeOut == NULL) {
  1178. //
  1179. // If Sleep( -1 ) then delay for the longest possible integer
  1180. // relative to now.
  1181. //
  1182. TimeOut.LowPart = 0x0;
  1183. TimeOut.HighPart = 0x80000000;
  1184. pTimeOut = &TimeOut;
  1185. }
  1186. rewait:
  1187. Status = NtDelayExecution(
  1188. (BOOLEAN)bAlertable,
  1189. pTimeOut
  1190. );
  1191. if ( bAlertable && Status == STATUS_ALERTED ) {
  1192. goto rewait;
  1193. }
  1194. return Status == STATUS_USER_APC ? WAIT_IO_COMPLETION : 0;
  1195. }
  1196. HANDLE
  1197. WINAPI
  1198. CreateWaitableTimerA(
  1199. LPSECURITY_ATTRIBUTES lpTimerAttributes,
  1200. BOOL bManualReset,
  1201. LPCSTR lpTimerName
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. ANSI thunk to CreateWaitableTimerW
  1206. --*/
  1207. {
  1208. PUNICODE_STRING Unicode;
  1209. ANSI_STRING AnsiString;
  1210. NTSTATUS Status;
  1211. LPCWSTR NameBuffer;
  1212. NameBuffer = NULL;
  1213. if ( ARGUMENT_PRESENT(lpTimerName) ) {
  1214. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1215. RtlInitAnsiString(&AnsiString,lpTimerName);
  1216. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1217. if ( !NT_SUCCESS(Status) ) {
  1218. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1219. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  1220. }
  1221. else {
  1222. BaseSetLastNTError(Status);
  1223. }
  1224. return NULL;
  1225. }
  1226. NameBuffer = (LPCWSTR)Unicode->Buffer;
  1227. }
  1228. return CreateWaitableTimerW(
  1229. lpTimerAttributes,
  1230. bManualReset,
  1231. NameBuffer
  1232. );
  1233. }
  1234. HANDLE
  1235. WINAPI
  1236. CreateWaitableTimerW(
  1237. LPSECURITY_ATTRIBUTES lpTimerAttributes,
  1238. BOOL bManualReset,
  1239. LPCWSTR lpTimerName
  1240. )
  1241. {
  1242. NTSTATUS Status;
  1243. OBJECT_ATTRIBUTES Obja;
  1244. POBJECT_ATTRIBUTES pObja;
  1245. HANDLE Handle;
  1246. UNICODE_STRING ObjectName;
  1247. if ( ARGUMENT_PRESENT(lpTimerName) ) {
  1248. RtlInitUnicodeString(&ObjectName,lpTimerName);
  1249. pObja = BaseFormatObjectAttributes(&Obja,lpTimerAttributes,&ObjectName);
  1250. }
  1251. else {
  1252. pObja = BaseFormatObjectAttributes(&Obja,lpTimerAttributes,NULL);
  1253. }
  1254. Status = NtCreateTimer(
  1255. &Handle,
  1256. TIMER_ALL_ACCESS,
  1257. pObja,
  1258. bManualReset ? NotificationTimer : SynchronizationTimer
  1259. );
  1260. if ( NT_SUCCESS(Status) ) {
  1261. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  1262. SetLastError(ERROR_ALREADY_EXISTS);
  1263. }
  1264. else {
  1265. SetLastError(0);
  1266. }
  1267. return Handle;
  1268. }
  1269. else {
  1270. BaseSetLastNTError(Status);
  1271. return NULL;
  1272. }
  1273. }
  1274. HANDLE
  1275. WINAPI
  1276. OpenWaitableTimerA(
  1277. DWORD dwDesiredAccess,
  1278. BOOL bInheritHandle,
  1279. LPCSTR lpTimerName
  1280. )
  1281. {
  1282. PUNICODE_STRING Unicode;
  1283. ANSI_STRING AnsiString;
  1284. NTSTATUS Status;
  1285. if ( ARGUMENT_PRESENT(lpTimerName) ) {
  1286. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1287. RtlInitAnsiString(&AnsiString,lpTimerName);
  1288. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1289. if ( !NT_SUCCESS(Status) ) {
  1290. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1291. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  1292. }
  1293. else {
  1294. BaseSetLastNTError(Status);
  1295. }
  1296. return NULL;
  1297. }
  1298. }
  1299. else {
  1300. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1301. return NULL;
  1302. }
  1303. return OpenWaitableTimerW(
  1304. dwDesiredAccess,
  1305. bInheritHandle,
  1306. (LPCWSTR)Unicode->Buffer
  1307. );
  1308. }
  1309. HANDLE
  1310. WINAPI
  1311. OpenWaitableTimerW(
  1312. DWORD dwDesiredAccess,
  1313. BOOL bInheritHandle,
  1314. LPCWSTR lpTimerName
  1315. )
  1316. {
  1317. OBJECT_ATTRIBUTES Obja;
  1318. UNICODE_STRING ObjectName;
  1319. NTSTATUS Status;
  1320. HANDLE Object;
  1321. if ( !lpTimerName ) {
  1322. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  1323. return NULL;
  1324. }
  1325. RtlInitUnicodeString(&ObjectName,lpTimerName);
  1326. InitializeObjectAttributes(
  1327. &Obja,
  1328. &ObjectName,
  1329. (bInheritHandle ? OBJ_INHERIT : 0),
  1330. BaseGetNamedObjectDirectory(),
  1331. NULL
  1332. );
  1333. Status = NtOpenTimer(
  1334. &Object,
  1335. dwDesiredAccess,
  1336. &Obja
  1337. );
  1338. if ( !NT_SUCCESS(Status) ) {
  1339. BaseSetLastNTError(Status);
  1340. return NULL;
  1341. }
  1342. return Object;
  1343. }
  1344. BOOL
  1345. WINAPI
  1346. SetWaitableTimer(
  1347. HANDLE hTimer,
  1348. const LARGE_INTEGER *lpDueTime,
  1349. LONG lPeriod,
  1350. PTIMERAPCROUTINE pfnCompletionRoutine,
  1351. LPVOID lpArgToCompletionRoutine,
  1352. BOOL fResume
  1353. )
  1354. {
  1355. NTSTATUS Status;
  1356. Status = NtSetTimer(
  1357. hTimer,
  1358. (PLARGE_INTEGER)lpDueTime,
  1359. (PTIMER_APC_ROUTINE)pfnCompletionRoutine,
  1360. lpArgToCompletionRoutine,
  1361. (BOOLEAN) fResume,
  1362. lPeriod,
  1363. NULL
  1364. );
  1365. if ( !NT_SUCCESS(Status) ) {
  1366. BaseSetLastNTError(Status);
  1367. return FALSE;
  1368. }
  1369. else {
  1370. if ( Status == STATUS_TIMER_RESUME_IGNORED ) {
  1371. SetLastError(ERROR_NOT_SUPPORTED);
  1372. }
  1373. else {
  1374. SetLastError(0);
  1375. }
  1376. return TRUE;
  1377. }
  1378. }
  1379. BOOL
  1380. WINAPI
  1381. CancelWaitableTimer(
  1382. HANDLE hTimer
  1383. )
  1384. {
  1385. NTSTATUS Status;
  1386. Status = NtCancelTimer(hTimer,NULL);
  1387. if ( !NT_SUCCESS(Status) ) {
  1388. BaseSetLastNTError(Status);
  1389. return FALSE;
  1390. }
  1391. else {
  1392. return TRUE;
  1393. }
  1394. }