Leaked source code of windows server 2003
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.

1934 lines
53 KiB

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