2 * Process synchronisation
4 * Copyright 1996, 1997, 1998 Marcus Meissner
5 * Copyright 1997, 1999 Alexandre Julliard
6 * Copyright 1999, 2000 Juergen Schmied
7 * Copyright 2003 Eric Pouech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/port.h"
35 #ifdef HAVE_SYS_SYSCALL_H
36 #include <sys/syscall.h>
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
44 #ifdef HAVE_SYS_POLL_H
45 # include <sys/poll.h>
60 #define WIN32_NO_STATUS
61 #define NONAMELESSUNION
64 #include "wine/server.h"
65 #include "wine/debug.h"
66 #include "unix_private.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(sync
);
71 HANDLE keyed_event
= 0;
74 /* create a struct security_descriptor and contained information in one contiguous piece of memory */
75 static NTSTATUS
alloc_object_attributes( const OBJECT_ATTRIBUTES
*attr
, struct object_attributes
**ret
,
76 data_size_t
*ret_len
)
78 unsigned int len
= sizeof(**ret
);
79 PSID owner
= NULL
, group
= NULL
;
81 BOOLEAN dacl_present
, sacl_present
, defaulted
;
82 PSECURITY_DESCRIPTOR sd
;
88 if (!attr
) return STATUS_SUCCESS
;
90 if (attr
->Length
!= sizeof(*attr
)) return STATUS_INVALID_PARAMETER
;
92 if ((sd
= attr
->SecurityDescriptor
))
94 len
+= sizeof(struct security_descriptor
);
96 if ((status
= RtlGetOwnerSecurityDescriptor( sd
, &owner
, &defaulted
))) return status
;
97 if ((status
= RtlGetGroupSecurityDescriptor( sd
, &group
, &defaulted
))) return status
;
98 if ((status
= RtlGetSaclSecurityDescriptor( sd
, &sacl_present
, &sacl
, &defaulted
))) return status
;
99 if ((status
= RtlGetDaclSecurityDescriptor( sd
, &dacl_present
, &dacl
, &defaulted
))) return status
;
100 if (owner
) len
+= RtlLengthSid( owner
);
101 if (group
) len
+= RtlLengthSid( group
);
102 if (sacl_present
&& sacl
) len
+= sacl
->AclSize
;
103 if (dacl_present
&& dacl
) len
+= dacl
->AclSize
;
105 /* fix alignment for the Unicode name that follows the structure */
106 len
= (len
+ sizeof(WCHAR
) - 1) & ~(sizeof(WCHAR
) - 1);
109 if (attr
->ObjectName
)
111 if (attr
->ObjectName
->Length
& (sizeof(WCHAR
) - 1)) return STATUS_OBJECT_NAME_INVALID
;
112 len
+= attr
->ObjectName
->Length
;
114 else if (attr
->RootDirectory
) return STATUS_OBJECT_NAME_INVALID
;
116 len
= (len
+ 3) & ~3; /* DWORD-align the entire structure */
118 *ret
= RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
119 if (!*ret
) return STATUS_NO_MEMORY
;
121 (*ret
)->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
122 (*ret
)->attributes
= attr
->Attributes
;
124 if (attr
->SecurityDescriptor
)
126 struct security_descriptor
*descr
= (struct security_descriptor
*)(*ret
+ 1);
127 unsigned char *ptr
= (unsigned char *)(descr
+ 1);
129 descr
->control
= ((SECURITY_DESCRIPTOR
*)sd
)->Control
& ~SE_SELF_RELATIVE
;
130 if (owner
) descr
->owner_len
= RtlLengthSid( owner
);
131 if (group
) descr
->group_len
= RtlLengthSid( group
);
132 if (sacl_present
&& sacl
) descr
->sacl_len
= sacl
->AclSize
;
133 if (dacl_present
&& dacl
) descr
->dacl_len
= dacl
->AclSize
;
135 memcpy( ptr
, owner
, descr
->owner_len
);
136 ptr
+= descr
->owner_len
;
137 memcpy( ptr
, group
, descr
->group_len
);
138 ptr
+= descr
->group_len
;
139 memcpy( ptr
, sacl
, descr
->sacl_len
);
140 ptr
+= descr
->sacl_len
;
141 memcpy( ptr
, dacl
, descr
->dacl_len
);
142 (*ret
)->sd_len
= (sizeof(*descr
) + descr
->owner_len
+ descr
->group_len
+ descr
->sacl_len
+
143 descr
->dacl_len
+ sizeof(WCHAR
) - 1) & ~(sizeof(WCHAR
) - 1);
146 if (attr
->ObjectName
)
148 unsigned char *ptr
= (unsigned char *)(*ret
+ 1) + (*ret
)->sd_len
;
149 (*ret
)->name_len
= attr
->ObjectName
->Length
;
150 memcpy( ptr
, attr
->ObjectName
->Buffer
, (*ret
)->name_len
);
154 return STATUS_SUCCESS
;
158 static NTSTATUS
validate_open_object_attributes( const OBJECT_ATTRIBUTES
*attr
)
160 if (!attr
|| attr
->Length
!= sizeof(*attr
)) return STATUS_INVALID_PARAMETER
;
162 if (attr
->ObjectName
)
164 if (attr
->ObjectName
->Length
& (sizeof(WCHAR
) - 1)) return STATUS_OBJECT_NAME_INVALID
;
166 else if (attr
->RootDirectory
) return STATUS_OBJECT_NAME_INVALID
;
168 return STATUS_SUCCESS
;
172 /******************************************************************************
173 * NtCreateSemaphore (NTDLL.@)
175 NTSTATUS WINAPI
NtCreateSemaphore( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
176 LONG initial
, LONG max
)
180 struct object_attributes
*objattr
;
182 if (max
<= 0 || initial
< 0 || initial
> max
) return STATUS_INVALID_PARAMETER
;
183 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
185 SERVER_START_REQ( create_semaphore
)
187 req
->access
= access
;
188 req
->initial
= initial
;
190 wine_server_add_data( req
, objattr
, len
);
191 ret
= wine_server_call( req
);
192 *handle
= wine_server_ptr_handle( reply
->handle
);
196 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
201 /******************************************************************************
202 * NtOpenSemaphore (NTDLL.@)
204 NTSTATUS WINAPI
NtOpenSemaphore( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
208 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
210 SERVER_START_REQ( open_semaphore
)
212 req
->access
= access
;
213 req
->attributes
= attr
->Attributes
;
214 req
->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
215 if (attr
->ObjectName
)
216 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
217 ret
= wine_server_call( req
);
218 *handle
= wine_server_ptr_handle( reply
->handle
);
225 /******************************************************************************
226 * NtQuerySemaphore (NTDLL.@)
228 NTSTATUS WINAPI
NtQuerySemaphore( HANDLE handle
, SEMAPHORE_INFORMATION_CLASS
class,
229 void *info
, ULONG len
, ULONG
*ret_len
)
232 SEMAPHORE_BASIC_INFORMATION
*out
= info
;
234 TRACE("(%p, %u, %p, %u, %p)\n", handle
, class, info
, len
, ret_len
);
236 if (class != SemaphoreBasicInformation
)
238 FIXME("(%p,%d,%u) Unknown class\n", handle
, class, len
);
239 return STATUS_INVALID_INFO_CLASS
;
242 if (len
!= sizeof(SEMAPHORE_BASIC_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
244 SERVER_START_REQ( query_semaphore
)
246 req
->handle
= wine_server_obj_handle( handle
);
247 if (!(ret
= wine_server_call( req
)))
249 out
->CurrentCount
= reply
->current
;
250 out
->MaximumCount
= reply
->max
;
251 if (ret_len
) *ret_len
= sizeof(SEMAPHORE_BASIC_INFORMATION
);
259 /******************************************************************************
260 * NtReleaseSemaphore (NTDLL.@)
262 NTSTATUS WINAPI
NtReleaseSemaphore( HANDLE handle
, ULONG count
, ULONG
*previous
)
266 SERVER_START_REQ( release_semaphore
)
268 req
->handle
= wine_server_obj_handle( handle
);
270 if (!(ret
= wine_server_call( req
)))
272 if (previous
) *previous
= reply
->prev_count
;
280 /**************************************************************************
281 * NtCreateEvent (NTDLL.@)
283 NTSTATUS WINAPI
NtCreateEvent( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
284 EVENT_TYPE type
, BOOLEAN state
)
288 struct object_attributes
*objattr
;
290 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
292 SERVER_START_REQ( create_event
)
294 req
->access
= access
;
295 req
->manual_reset
= (type
== NotificationEvent
);
296 req
->initial_state
= state
;
297 wine_server_add_data( req
, objattr
, len
);
298 ret
= wine_server_call( req
);
299 *handle
= wine_server_ptr_handle( reply
->handle
);
303 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
308 /******************************************************************************
309 * NtOpenEvent (NTDLL.@)
311 NTSTATUS WINAPI
NtOpenEvent( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
315 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
317 SERVER_START_REQ( open_event
)
319 req
->access
= access
;
320 req
->attributes
= attr
->Attributes
;
321 req
->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
322 if (attr
->ObjectName
)
323 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
324 ret
= wine_server_call( req
);
325 *handle
= wine_server_ptr_handle( reply
->handle
);
332 /******************************************************************************
333 * NtSetEvent (NTDLL.@)
335 NTSTATUS WINAPI
NtSetEvent( HANDLE handle
, LONG
*prev_state
)
339 SERVER_START_REQ( event_op
)
341 req
->handle
= wine_server_obj_handle( handle
);
343 ret
= wine_server_call( req
);
344 if (!ret
&& prev_state
) *prev_state
= reply
->state
;
351 /******************************************************************************
352 * NtResetEvent (NTDLL.@)
354 NTSTATUS WINAPI
NtResetEvent( HANDLE handle
, LONG
*prev_state
)
358 SERVER_START_REQ( event_op
)
360 req
->handle
= wine_server_obj_handle( handle
);
361 req
->op
= RESET_EVENT
;
362 ret
= wine_server_call( req
);
363 if (!ret
&& prev_state
) *prev_state
= reply
->state
;
370 /******************************************************************************
371 * NtClearEvent (NTDLL.@)
373 NTSTATUS WINAPI
NtClearEvent( HANDLE handle
)
375 /* FIXME: same as NtResetEvent ??? */
376 return NtResetEvent( handle
, NULL
);
380 /******************************************************************************
381 * NtPulseEvent (NTDLL.@)
383 NTSTATUS WINAPI
NtPulseEvent( HANDLE handle
, LONG
*prev_state
)
387 SERVER_START_REQ( event_op
)
389 req
->handle
= wine_server_obj_handle( handle
);
390 req
->op
= PULSE_EVENT
;
391 ret
= wine_server_call( req
);
392 if (!ret
&& prev_state
) *prev_state
= reply
->state
;
399 /******************************************************************************
400 * NtQueryEvent (NTDLL.@)
402 NTSTATUS WINAPI
NtQueryEvent( HANDLE handle
, EVENT_INFORMATION_CLASS
class,
403 void *info
, ULONG len
, ULONG
*ret_len
)
406 EVENT_BASIC_INFORMATION
*out
= info
;
408 TRACE("(%p, %u, %p, %u, %p)\n", handle
, class, info
, len
, ret_len
);
410 if (class != EventBasicInformation
)
412 FIXME("(%p, %d, %d) Unknown class\n",
414 return STATUS_INVALID_INFO_CLASS
;
417 if (len
!= sizeof(EVENT_BASIC_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
419 SERVER_START_REQ( query_event
)
421 req
->handle
= wine_server_obj_handle( handle
);
422 if (!(ret
= wine_server_call( req
)))
424 out
->EventType
= reply
->manual_reset
? NotificationEvent
: SynchronizationEvent
;
425 out
->EventState
= reply
->state
;
426 if (ret_len
) *ret_len
= sizeof(EVENT_BASIC_INFORMATION
);
434 /******************************************************************************
435 * NtCreateMutant (NTDLL.@)
437 NTSTATUS WINAPI
NtCreateMutant( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
442 struct object_attributes
*objattr
;
444 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
446 SERVER_START_REQ( create_mutex
)
448 req
->access
= access
;
450 wine_server_add_data( req
, objattr
, len
);
451 ret
= wine_server_call( req
);
452 *handle
= wine_server_ptr_handle( reply
->handle
);
456 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
461 /**************************************************************************
462 * NtOpenMutant (NTDLL.@)
464 NTSTATUS WINAPI
NtOpenMutant( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
468 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
470 SERVER_START_REQ( open_mutex
)
472 req
->access
= access
;
473 req
->attributes
= attr
->Attributes
;
474 req
->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
475 if (attr
->ObjectName
)
476 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
477 ret
= wine_server_call( req
);
478 *handle
= wine_server_ptr_handle( reply
->handle
);
485 /**************************************************************************
486 * NtReleaseMutant (NTDLL.@)
488 NTSTATUS WINAPI
NtReleaseMutant( HANDLE handle
, LONG
*prev_count
)
492 SERVER_START_REQ( release_mutex
)
494 req
->handle
= wine_server_obj_handle( handle
);
495 ret
= wine_server_call( req
);
496 if (prev_count
) *prev_count
= 1 - reply
->prev_count
;
503 /******************************************************************
504 * NtQueryMutant (NTDLL.@)
506 NTSTATUS WINAPI
NtQueryMutant( HANDLE handle
, MUTANT_INFORMATION_CLASS
class,
507 void *info
, ULONG len
, ULONG
*ret_len
)
510 MUTANT_BASIC_INFORMATION
*out
= info
;
512 TRACE("(%p, %u, %p, %u, %p)\n", handle
, class, info
, len
, ret_len
);
514 if (class != MutantBasicInformation
)
516 FIXME( "(%p, %d, %d) Unknown class\n", handle
, class, len
);
517 return STATUS_INVALID_INFO_CLASS
;
520 if (len
!= sizeof(MUTANT_BASIC_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
522 SERVER_START_REQ( query_mutex
)
524 req
->handle
= wine_server_obj_handle( handle
);
525 if (!(ret
= wine_server_call( req
)))
527 out
->CurrentCount
= 1 - reply
->count
;
528 out
->OwnedByCaller
= reply
->owned
;
529 out
->AbandonedState
= reply
->abandoned
;
530 if (ret_len
) *ret_len
= sizeof(MUTANT_BASIC_INFORMATION
);
538 /**************************************************************************
539 * NtCreateTimer (NTDLL.@)
541 NTSTATUS WINAPI
NtCreateTimer( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
546 struct object_attributes
*objattr
;
548 if (type
!= NotificationTimer
&& type
!= SynchronizationTimer
) return STATUS_INVALID_PARAMETER
;
550 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
552 SERVER_START_REQ( create_timer
)
554 req
->access
= access
;
555 req
->manual
= (type
== NotificationTimer
);
556 wine_server_add_data( req
, objattr
, len
);
557 ret
= wine_server_call( req
);
558 *handle
= wine_server_ptr_handle( reply
->handle
);
562 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
568 /**************************************************************************
569 * NtOpenTimer (NTDLL.@)
571 NTSTATUS WINAPI
NtOpenTimer( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
575 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
577 SERVER_START_REQ( open_timer
)
579 req
->access
= access
;
580 req
->attributes
= attr
->Attributes
;
581 req
->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
582 if (attr
->ObjectName
)
583 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
584 ret
= wine_server_call( req
);
585 *handle
= wine_server_ptr_handle( reply
->handle
);
592 /**************************************************************************
593 * NtSetTimer (NTDLL.@)
595 NTSTATUS WINAPI
NtSetTimer( HANDLE handle
, const LARGE_INTEGER
*when
, PTIMER_APC_ROUTINE callback
,
596 void *arg
, BOOLEAN resume
, ULONG period
, BOOLEAN
*state
)
598 NTSTATUS ret
= STATUS_SUCCESS
;
600 TRACE( "(%p,%p,%p,%p,%08x,0x%08x,%p)\n", handle
, when
, callback
, arg
, resume
, period
, state
);
602 SERVER_START_REQ( set_timer
)
604 req
->handle
= wine_server_obj_handle( handle
);
605 req
->period
= period
;
606 req
->expire
= when
->QuadPart
;
607 req
->callback
= wine_server_client_ptr( callback
);
608 req
->arg
= wine_server_client_ptr( arg
);
609 ret
= wine_server_call( req
);
610 if (state
) *state
= reply
->signaled
;
614 /* set error but can still succeed */
615 if (resume
&& ret
== STATUS_SUCCESS
) return STATUS_TIMER_RESUME_IGNORED
;
620 /**************************************************************************
621 * NtCancelTimer (NTDLL.@)
623 NTSTATUS WINAPI
NtCancelTimer( HANDLE handle
, BOOLEAN
*state
)
627 SERVER_START_REQ( cancel_timer
)
629 req
->handle
= wine_server_obj_handle( handle
);
630 ret
= wine_server_call( req
);
631 if (state
) *state
= reply
->signaled
;
638 /******************************************************************************
639 * NtQueryTimer (NTDLL.@)
641 NTSTATUS WINAPI
NtQueryTimer( HANDLE handle
, TIMER_INFORMATION_CLASS
class,
642 void *info
, ULONG len
, ULONG
*ret_len
)
644 TIMER_BASIC_INFORMATION
*basic_info
= info
;
648 TRACE( "(%p,%d,%p,0x%08x,%p)\n", handle
, class, info
, len
, ret_len
);
652 case TimerBasicInformation
:
653 if (len
< sizeof(TIMER_BASIC_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
655 SERVER_START_REQ( get_timer_info
)
657 req
->handle
= wine_server_obj_handle( handle
);
658 ret
= wine_server_call(req
);
659 /* convert server time to absolute NTDLL time */
660 basic_info
->RemainingTime
.QuadPart
= reply
->when
;
661 basic_info
->TimerState
= reply
->signaled
;
665 /* convert into relative time */
666 if (basic_info
->RemainingTime
.QuadPart
> 0) NtQuerySystemTime( &now
);
669 RtlQueryPerformanceCounter( &now
);
670 basic_info
->RemainingTime
.QuadPart
= -basic_info
->RemainingTime
.QuadPart
;
673 if (now
.QuadPart
> basic_info
->RemainingTime
.QuadPart
)
674 basic_info
->RemainingTime
.QuadPart
= 0;
676 basic_info
->RemainingTime
.QuadPart
-= now
.QuadPart
;
678 if (ret_len
) *ret_len
= sizeof(TIMER_BASIC_INFORMATION
);
682 FIXME( "Unhandled class %d\n", class );
683 return STATUS_INVALID_INFO_CLASS
;
687 /******************************************************************
688 * NtWaitForMultipleObjects (NTDLL.@)
690 NTSTATUS WINAPI
NtWaitForMultipleObjects( DWORD count
, const HANDLE
*handles
, BOOLEAN wait_any
,
691 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
693 select_op_t select_op
;
694 UINT i
, flags
= SELECT_INTERRUPTIBLE
;
696 if (!count
|| count
> MAXIMUM_WAIT_OBJECTS
) return STATUS_INVALID_PARAMETER_1
;
698 if (alertable
) flags
|= SELECT_ALERTABLE
;
699 select_op
.wait
.op
= wait_any
? SELECT_WAIT
: SELECT_WAIT_ALL
;
700 for (i
= 0; i
< count
; i
++) select_op
.wait
.handles
[i
] = wine_server_obj_handle( handles
[i
] );
701 return server_wait( &select_op
, offsetof( select_op_t
, wait
.handles
[count
] ), flags
, timeout
);
705 /******************************************************************
706 * NtWaitForSingleObject (NTDLL.@)
708 NTSTATUS WINAPI
NtWaitForSingleObject( HANDLE handle
, BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
710 return NtWaitForMultipleObjects( 1, &handle
, FALSE
, alertable
, timeout
);
714 /******************************************************************
715 * NtSignalAndWaitForSingleObject (NTDLL.@)
717 NTSTATUS WINAPI
NtSignalAndWaitForSingleObject( HANDLE signal
, HANDLE wait
,
718 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
720 select_op_t select_op
;
721 UINT flags
= SELECT_INTERRUPTIBLE
;
723 if (!signal
) return STATUS_INVALID_HANDLE
;
725 if (alertable
) flags
|= SELECT_ALERTABLE
;
726 select_op
.signal_and_wait
.op
= SELECT_SIGNAL_AND_WAIT
;
727 select_op
.signal_and_wait
.wait
= wine_server_obj_handle( wait
);
728 select_op
.signal_and_wait
.signal
= wine_server_obj_handle( signal
);
729 return server_wait( &select_op
, sizeof(select_op
.signal_and_wait
), flags
, timeout
);
733 /******************************************************************
734 * NtYieldExecution (NTDLL.@)
736 NTSTATUS WINAPI
NtYieldExecution(void)
738 #ifdef HAVE_SCHED_YIELD
740 return STATUS_SUCCESS
;
742 return STATUS_NO_YIELD_PERFORMED
;
747 /******************************************************************
748 * NtDelayExecution (NTDLL.@)
750 NTSTATUS WINAPI
NtDelayExecution( BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
752 /* if alertable, we need to query the server */
753 if (alertable
) return server_wait( NULL
, 0, SELECT_INTERRUPTIBLE
| SELECT_ALERTABLE
, timeout
);
755 if (!timeout
|| timeout
->QuadPart
== TIMEOUT_INFINITE
) /* sleep forever */
757 for (;;) select( 0, NULL
, NULL
, NULL
, NULL
);
762 timeout_t when
, diff
;
764 if ((when
= timeout
->QuadPart
) < 0)
766 NtQuerySystemTime( &now
);
767 when
= now
.QuadPart
- when
;
770 /* Note that we yield after establishing the desired timeout */
772 if (!when
) return STATUS_SUCCESS
;
777 NtQuerySystemTime( &now
);
778 diff
= (when
- now
.QuadPart
+ 9) / 10;
779 if (diff
<= 0) break;
780 tv
.tv_sec
= diff
/ 1000000;
781 tv
.tv_usec
= diff
% 1000000;
782 if (select( 0, NULL
, NULL
, NULL
, &tv
) != -1) break;
785 return STATUS_SUCCESS
;
789 /******************************************************************************
790 * NtCreateKeyedEvent (NTDLL.@)
792 NTSTATUS WINAPI
NtCreateKeyedEvent( HANDLE
*handle
, ACCESS_MASK access
,
793 const OBJECT_ATTRIBUTES
*attr
, ULONG flags
)
797 struct object_attributes
*objattr
;
799 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
801 SERVER_START_REQ( create_keyed_event
)
803 req
->access
= access
;
804 wine_server_add_data( req
, objattr
, len
);
805 ret
= wine_server_call( req
);
806 *handle
= wine_server_ptr_handle( reply
->handle
);
810 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
815 /******************************************************************************
816 * NtOpenKeyedEvent (NTDLL.@)
818 NTSTATUS WINAPI
NtOpenKeyedEvent( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
822 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
824 SERVER_START_REQ( open_keyed_event
)
826 req
->access
= access
;
827 req
->attributes
= attr
->Attributes
;
828 req
->rootdir
= wine_server_obj_handle( attr
->RootDirectory
);
829 if (attr
->ObjectName
)
830 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
831 ret
= wine_server_call( req
);
832 *handle
= wine_server_ptr_handle( reply
->handle
);
838 /******************************************************************************
839 * NtWaitForKeyedEvent (NTDLL.@)
841 NTSTATUS WINAPI
NtWaitForKeyedEvent( HANDLE handle
, const void *key
,
842 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
844 select_op_t select_op
;
845 UINT flags
= SELECT_INTERRUPTIBLE
;
847 if (!handle
) handle
= keyed_event
;
848 if ((ULONG_PTR
)key
& 1) return STATUS_INVALID_PARAMETER_1
;
849 if (alertable
) flags
|= SELECT_ALERTABLE
;
850 select_op
.keyed_event
.op
= SELECT_KEYED_EVENT_WAIT
;
851 select_op
.keyed_event
.handle
= wine_server_obj_handle( handle
);
852 select_op
.keyed_event
.key
= wine_server_client_ptr( key
);
853 return server_wait( &select_op
, sizeof(select_op
.keyed_event
), flags
, timeout
);
857 /******************************************************************************
858 * NtReleaseKeyedEvent (NTDLL.@)
860 NTSTATUS WINAPI
NtReleaseKeyedEvent( HANDLE handle
, const void *key
,
861 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
863 select_op_t select_op
;
864 UINT flags
= SELECT_INTERRUPTIBLE
;
866 if (!handle
) handle
= keyed_event
;
867 if ((ULONG_PTR
)key
& 1) return STATUS_INVALID_PARAMETER_1
;
868 if (alertable
) flags
|= SELECT_ALERTABLE
;
869 select_op
.keyed_event
.op
= SELECT_KEYED_EVENT_RELEASE
;
870 select_op
.keyed_event
.handle
= wine_server_obj_handle( handle
);
871 select_op
.keyed_event
.key
= wine_server_client_ptr( key
);
872 return server_wait( &select_op
, sizeof(select_op
.keyed_event
), flags
, timeout
);