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
25 #include "wine/port.h"
30 #ifdef HAVE_SYS_TIME_H
31 # include <sys/time.h>
36 #ifdef HAVE_SYS_POLL_H
37 # include <sys/poll.h>
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
55 #define WIN32_NO_STATUS
58 #include "wine/server.h"
59 #include "wine/debug.h"
60 #include "ntdll_misc.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
64 HANDLE keyed_event
= NULL
;
66 /* creates a struct security_descriptor and contained information in one contiguous piece of memory */
67 NTSTATUS
NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd
, struct security_descriptor
**server_sd
,
68 data_size_t
*server_sd_len
)
73 BOOLEAN owner_present
, group_present
, dacl_present
, sacl_present
;
82 return STATUS_SUCCESS
;
85 len
= sizeof(struct security_descriptor
);
87 status
= RtlGetOwnerSecurityDescriptor(nt_sd
, &owner
, &owner_present
);
88 if (status
!= STATUS_SUCCESS
) return status
;
89 status
= RtlGetGroupSecurityDescriptor(nt_sd
, &group
, &group_present
);
90 if (status
!= STATUS_SUCCESS
) return status
;
91 status
= RtlGetSaclSecurityDescriptor(nt_sd
, &sacl_present
, &sacl
, &defaulted
);
92 if (status
!= STATUS_SUCCESS
) return status
;
93 status
= RtlGetDaclSecurityDescriptor(nt_sd
, &dacl_present
, &dacl
, &defaulted
);
94 if (status
!= STATUS_SUCCESS
) return status
;
97 len
+= RtlLengthSid(owner
);
99 len
+= RtlLengthSid(group
);
100 if (sacl_present
&& sacl
)
101 len
+= sacl
->AclSize
;
102 if (dacl_present
&& dacl
)
103 len
+= dacl
->AclSize
;
105 /* fix alignment for the Unicode name that follows the structure */
106 len
= (len
+ sizeof(WCHAR
) - 1) & ~(sizeof(WCHAR
) - 1);
107 *server_sd
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
108 if (!*server_sd
) return STATUS_NO_MEMORY
;
110 (*server_sd
)->control
= ((SECURITY_DESCRIPTOR
*)nt_sd
)->Control
& ~SE_SELF_RELATIVE
;
111 (*server_sd
)->owner_len
= owner_present
? RtlLengthSid(owner
) : 0;
112 (*server_sd
)->group_len
= group_present
? RtlLengthSid(group
) : 0;
113 (*server_sd
)->sacl_len
= (sacl_present
&& sacl
) ? sacl
->AclSize
: 0;
114 (*server_sd
)->dacl_len
= (dacl_present
&& dacl
) ? dacl
->AclSize
: 0;
116 ptr
= (unsigned char *)(*server_sd
+ 1);
117 memcpy(ptr
, owner
, (*server_sd
)->owner_len
);
118 ptr
+= (*server_sd
)->owner_len
;
119 memcpy(ptr
, group
, (*server_sd
)->group_len
);
120 ptr
+= (*server_sd
)->group_len
;
121 memcpy(ptr
, sacl
, (*server_sd
)->sacl_len
);
122 ptr
+= (*server_sd
)->sacl_len
;
123 memcpy(ptr
, dacl
, (*server_sd
)->dacl_len
);
125 *server_sd_len
= len
;
127 return STATUS_SUCCESS
;
130 /* frees a struct security_descriptor allocated by NTDLL_create_struct_sd */
131 void NTDLL_free_struct_sd(struct security_descriptor
*server_sd
)
133 RtlFreeHeap(GetProcessHeap(), 0, server_sd
);
140 /******************************************************************************
141 * NtCreateSemaphore (NTDLL.@)
143 NTSTATUS WINAPI
NtCreateSemaphore( OUT PHANDLE SemaphoreHandle
,
144 IN ACCESS_MASK access
,
145 IN
const OBJECT_ATTRIBUTES
*attr OPTIONAL
,
146 IN LONG InitialCount
,
147 IN LONG MaximumCount
)
149 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
151 struct object_attributes objattr
;
152 struct security_descriptor
*sd
= NULL
;
154 if (MaximumCount
<= 0 || InitialCount
< 0 || InitialCount
> MaximumCount
)
155 return STATUS_INVALID_PARAMETER
;
156 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
158 objattr
.rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
160 objattr
.name_len
= len
;
163 ret
= NTDLL_create_struct_sd( attr
->SecurityDescriptor
, &sd
, &objattr
.sd_len
);
164 if (ret
!= STATUS_SUCCESS
) return ret
;
167 SERVER_START_REQ( create_semaphore
)
169 req
->access
= access
;
170 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
171 req
->initial
= InitialCount
;
172 req
->max
= MaximumCount
;
173 wine_server_add_data( req
, &objattr
, sizeof(objattr
) );
174 if (objattr
.sd_len
) wine_server_add_data( req
, sd
, objattr
.sd_len
);
175 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
176 ret
= wine_server_call( req
);
177 *SemaphoreHandle
= wine_server_ptr_handle( reply
->handle
);
181 NTDLL_free_struct_sd( sd
);
186 /******************************************************************************
187 * NtOpenSemaphore (NTDLL.@)
189 NTSTATUS WINAPI
NtOpenSemaphore( OUT PHANDLE SemaphoreHandle
,
190 IN ACCESS_MASK access
,
191 IN
const OBJECT_ATTRIBUTES
*attr
)
193 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
196 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
198 SERVER_START_REQ( open_semaphore
)
200 req
->access
= access
;
201 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
202 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
203 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
204 ret
= wine_server_call( req
);
205 *SemaphoreHandle
= wine_server_ptr_handle( reply
->handle
);
211 /******************************************************************************
212 * NtQuerySemaphore (NTDLL.@)
214 NTSTATUS WINAPI
NtQuerySemaphore(
215 HANDLE SemaphoreHandle
,
216 SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass
,
217 PVOID SemaphoreInformation
,
221 FIXME("(%p,%d,%p,0x%08x,%p) stub!\n",
222 SemaphoreHandle
, SemaphoreInformationClass
, SemaphoreInformation
, Length
, ReturnLength
);
223 return STATUS_SUCCESS
;
226 /******************************************************************************
227 * NtReleaseSemaphore (NTDLL.@)
229 NTSTATUS WINAPI
NtReleaseSemaphore( HANDLE handle
, ULONG count
, PULONG previous
)
232 SERVER_START_REQ( release_semaphore
)
234 req
->handle
= wine_server_obj_handle( handle
);
236 if (!(ret
= wine_server_call( req
)))
238 if (previous
) *previous
= reply
->prev_count
;
249 /**************************************************************************
250 * NtCreateEvent (NTDLL.@)
251 * ZwCreateEvent (NTDLL.@)
253 NTSTATUS WINAPI
NtCreateEvent( PHANDLE EventHandle
, ACCESS_MASK DesiredAccess
,
254 const OBJECT_ATTRIBUTES
*attr
, EVENT_TYPE type
, BOOLEAN InitialState
)
256 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
258 struct security_descriptor
*sd
= NULL
;
259 struct object_attributes objattr
;
261 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
263 objattr
.rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
265 objattr
.name_len
= len
;
268 ret
= NTDLL_create_struct_sd( attr
->SecurityDescriptor
, &sd
, &objattr
.sd_len
);
269 if (ret
!= STATUS_SUCCESS
) return ret
;
272 SERVER_START_REQ( create_event
)
274 req
->access
= DesiredAccess
;
275 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
276 req
->manual_reset
= (type
== NotificationEvent
);
277 req
->initial_state
= InitialState
;
278 wine_server_add_data( req
, &objattr
, sizeof(objattr
) );
279 if (objattr
.sd_len
) wine_server_add_data( req
, sd
, objattr
.sd_len
);
280 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
281 ret
= wine_server_call( req
);
282 *EventHandle
= wine_server_ptr_handle( reply
->handle
);
286 NTDLL_free_struct_sd( sd
);
291 /******************************************************************************
292 * NtOpenEvent (NTDLL.@)
293 * ZwOpenEvent (NTDLL.@)
295 NTSTATUS WINAPI
NtOpenEvent(
296 OUT PHANDLE EventHandle
,
297 IN ACCESS_MASK DesiredAccess
,
298 IN
const OBJECT_ATTRIBUTES
*attr
)
300 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
303 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
305 SERVER_START_REQ( open_event
)
307 req
->access
= DesiredAccess
;
308 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
309 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
310 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
311 ret
= wine_server_call( req
);
312 *EventHandle
= wine_server_ptr_handle( reply
->handle
);
319 /******************************************************************************
320 * NtSetEvent (NTDLL.@)
321 * ZwSetEvent (NTDLL.@)
323 NTSTATUS WINAPI
NtSetEvent( HANDLE handle
, PULONG NumberOfThreadsReleased
)
327 /* FIXME: set NumberOfThreadsReleased */
329 SERVER_START_REQ( event_op
)
331 req
->handle
= wine_server_obj_handle( handle
);
333 ret
= wine_server_call( req
);
339 /******************************************************************************
340 * NtResetEvent (NTDLL.@)
342 NTSTATUS WINAPI
NtResetEvent( HANDLE handle
, PULONG NumberOfThreadsReleased
)
346 /* resetting an event can't release any thread... */
347 if (NumberOfThreadsReleased
) *NumberOfThreadsReleased
= 0;
349 SERVER_START_REQ( event_op
)
351 req
->handle
= wine_server_obj_handle( handle
);
352 req
->op
= RESET_EVENT
;
353 ret
= wine_server_call( req
);
359 /******************************************************************************
360 * NtClearEvent (NTDLL.@)
363 * same as NtResetEvent ???
365 NTSTATUS WINAPI
NtClearEvent ( HANDLE handle
)
367 return NtResetEvent( handle
, NULL
);
370 /******************************************************************************
371 * NtPulseEvent (NTDLL.@)
376 NTSTATUS WINAPI
NtPulseEvent( HANDLE handle
, PULONG PulseCount
)
381 FIXME("(%p,%d)\n", handle
, *PulseCount
);
383 SERVER_START_REQ( event_op
)
385 req
->handle
= wine_server_obj_handle( handle
);
386 req
->op
= PULSE_EVENT
;
387 ret
= wine_server_call( req
);
393 /******************************************************************************
394 * NtQueryEvent (NTDLL.@)
396 NTSTATUS WINAPI
NtQueryEvent( HANDLE handle
, EVENT_INFORMATION_CLASS
class,
397 void *info
, ULONG len
, ULONG
*ret_len
)
400 EVENT_BASIC_INFORMATION
*out
= info
;
402 if (class != EventBasicInformation
)
404 FIXME("(%p, %d, %d) Unknown class\n",
406 return STATUS_INVALID_INFO_CLASS
;
409 if (len
!= sizeof(EVENT_BASIC_INFORMATION
)) return STATUS_INFO_LENGTH_MISMATCH
;
411 SERVER_START_REQ( query_event
)
413 req
->handle
= wine_server_obj_handle( handle
);
414 if (!(ret
= wine_server_call( req
)))
416 out
->EventType
= reply
->manual_reset
? NotificationEvent
: SynchronizationEvent
;
417 out
->EventState
= reply
->state
;
418 if (ret_len
) *ret_len
= sizeof(EVENT_BASIC_INFORMATION
);
427 * Mutants (known as Mutexes in Kernel32)
430 /******************************************************************************
431 * NtCreateMutant [NTDLL.@]
432 * ZwCreateMutant [NTDLL.@]
434 NTSTATUS WINAPI
NtCreateMutant(OUT HANDLE
* MutantHandle
,
435 IN ACCESS_MASK access
,
436 IN
const OBJECT_ATTRIBUTES
* attr OPTIONAL
,
437 IN BOOLEAN InitialOwner
)
440 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
441 struct security_descriptor
*sd
= NULL
;
442 struct object_attributes objattr
;
444 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
446 objattr
.rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
448 objattr
.name_len
= len
;
451 status
= NTDLL_create_struct_sd( attr
->SecurityDescriptor
, &sd
, &objattr
.sd_len
);
452 if (status
!= STATUS_SUCCESS
) return status
;
455 SERVER_START_REQ( create_mutex
)
457 req
->access
= access
;
458 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
459 req
->owned
= InitialOwner
;
460 wine_server_add_data( req
, &objattr
, sizeof(objattr
) );
461 if (objattr
.sd_len
) wine_server_add_data( req
, sd
, objattr
.sd_len
);
462 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
463 status
= wine_server_call( req
);
464 *MutantHandle
= wine_server_ptr_handle( reply
->handle
);
468 NTDLL_free_struct_sd( sd
);
473 /**************************************************************************
474 * NtOpenMutant [NTDLL.@]
475 * ZwOpenMutant [NTDLL.@]
477 NTSTATUS WINAPI
NtOpenMutant(OUT HANDLE
* MutantHandle
,
478 IN ACCESS_MASK access
,
479 IN
const OBJECT_ATTRIBUTES
* attr
)
482 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
484 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
486 SERVER_START_REQ( open_mutex
)
488 req
->access
= access
;
489 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
490 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
491 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
492 status
= wine_server_call( req
);
493 *MutantHandle
= wine_server_ptr_handle( reply
->handle
);
499 /**************************************************************************
500 * NtReleaseMutant [NTDLL.@]
501 * ZwReleaseMutant [NTDLL.@]
503 NTSTATUS WINAPI
NtReleaseMutant( IN HANDLE handle
, OUT PLONG prev_count OPTIONAL
)
507 SERVER_START_REQ( release_mutex
)
509 req
->handle
= wine_server_obj_handle( handle
);
510 status
= wine_server_call( req
);
511 if (prev_count
) *prev_count
= reply
->prev_count
;
517 /******************************************************************
518 * NtQueryMutant [NTDLL.@]
519 * ZwQueryMutant [NTDLL.@]
521 NTSTATUS WINAPI
NtQueryMutant(IN HANDLE handle
,
522 IN MUTANT_INFORMATION_CLASS MutantInformationClass
,
523 OUT PVOID MutantInformation
,
524 IN ULONG MutantInformationLength
,
525 OUT PULONG ResultLength OPTIONAL
)
527 FIXME("(%p %u %p %u %p): stub!\n",
528 handle
, MutantInformationClass
, MutantInformation
, MutantInformationLength
, ResultLength
);
529 return STATUS_NOT_IMPLEMENTED
;
536 /******************************************************************************
537 * NtCreateJobObject [NTDLL.@]
538 * ZwCreateJobObject [NTDLL.@]
540 NTSTATUS WINAPI
NtCreateJobObject( PHANDLE handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
542 FIXME( "stub: %p %x %s\n", handle
, access
, attr
? debugstr_us(attr
->ObjectName
) : "" );
543 *handle
= (HANDLE
)0xdead;
544 return STATUS_SUCCESS
;
547 /******************************************************************************
548 * NtOpenJobObject [NTDLL.@]
549 * ZwOpenJobObject [NTDLL.@]
551 NTSTATUS WINAPI
NtOpenJobObject( PHANDLE handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
553 FIXME( "stub: %p %x %s\n", handle
, access
, attr
? debugstr_us(attr
->ObjectName
) : "" );
554 return STATUS_NOT_IMPLEMENTED
;
557 /******************************************************************************
558 * NtTerminateJobObject [NTDLL.@]
559 * ZwTerminateJobObject [NTDLL.@]
561 NTSTATUS WINAPI
NtTerminateJobObject( HANDLE handle
, NTSTATUS status
)
563 FIXME( "stub: %p %x\n", handle
, status
);
564 return STATUS_SUCCESS
;
567 /******************************************************************************
568 * NtQueryInformationJobObject [NTDLL.@]
569 * ZwQueryInformationJobObject [NTDLL.@]
571 NTSTATUS WINAPI
NtQueryInformationJobObject( HANDLE handle
, JOBOBJECTINFOCLASS
class, PVOID info
,
572 ULONG len
, PULONG ret_len
)
574 FIXME( "stub: %p %u %p %u %p\n", handle
, class, info
, len
, ret_len
);
575 return STATUS_NOT_IMPLEMENTED
;
578 /******************************************************************************
579 * NtSetInformationJobObject [NTDLL.@]
580 * ZwSetInformationJobObject [NTDLL.@]
582 NTSTATUS WINAPI
NtSetInformationJobObject( HANDLE handle
, JOBOBJECTINFOCLASS
class, PVOID info
, ULONG len
)
584 FIXME( "stub: %p %u %p %u\n", handle
, class, info
, len
);
585 return STATUS_SUCCESS
;
588 /******************************************************************************
589 * NtIsProcessInJob [NTDLL.@]
590 * ZwIsProcessInJob [NTDLL.@]
592 NTSTATUS WINAPI
NtIsProcessInJob( HANDLE process
, HANDLE job
)
594 FIXME( "stub: %p %p\n", process
, job
);
595 return STATUS_PROCESS_NOT_IN_JOB
;
598 /******************************************************************************
599 * NtAssignProcessToJobObject [NTDLL.@]
600 * ZwAssignProcessToJobObject [NTDLL.@]
602 NTSTATUS WINAPI
NtAssignProcessToJobObject( HANDLE job
, HANDLE process
)
604 FIXME( "stub: %p %p\n", job
, process
);
605 return STATUS_SUCCESS
;
612 /**************************************************************************
613 * NtCreateTimer [NTDLL.@]
614 * ZwCreateTimer [NTDLL.@]
616 NTSTATUS WINAPI
NtCreateTimer(OUT HANDLE
*handle
,
617 IN ACCESS_MASK access
,
618 IN
const OBJECT_ATTRIBUTES
*attr OPTIONAL
,
619 IN TIMER_TYPE timer_type
)
621 DWORD len
= (attr
&& attr
->ObjectName
) ? attr
->ObjectName
->Length
: 0;
624 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
626 if (timer_type
!= NotificationTimer
&& timer_type
!= SynchronizationTimer
)
627 return STATUS_INVALID_PARAMETER
;
629 SERVER_START_REQ( create_timer
)
631 req
->access
= access
;
632 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
633 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
634 req
->manual
= (timer_type
== NotificationTimer
) ? TRUE
: FALSE
;
635 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
636 status
= wine_server_call( req
);
637 *handle
= wine_server_ptr_handle( reply
->handle
);
644 /**************************************************************************
645 * NtOpenTimer [NTDLL.@]
646 * ZwOpenTimer [NTDLL.@]
648 NTSTATUS WINAPI
NtOpenTimer(OUT PHANDLE handle
,
649 IN ACCESS_MASK access
,
650 IN
const OBJECT_ATTRIBUTES
* attr
)
652 DWORD len
= (attr
&& attr
->ObjectName
) ? attr
->ObjectName
->Length
: 0;
655 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
657 SERVER_START_REQ( open_timer
)
659 req
->access
= access
;
660 req
->attributes
= (attr
) ? attr
->Attributes
: 0;
661 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
662 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
663 status
= wine_server_call( req
);
664 *handle
= wine_server_ptr_handle( reply
->handle
);
670 /**************************************************************************
671 * NtSetTimer [NTDLL.@]
672 * ZwSetTimer [NTDLL.@]
674 NTSTATUS WINAPI
NtSetTimer(IN HANDLE handle
,
675 IN
const LARGE_INTEGER
* when
,
676 IN PTIMER_APC_ROUTINE callback
,
677 IN PVOID callback_arg
,
679 IN ULONG period OPTIONAL
,
680 OUT PBOOLEAN state OPTIONAL
)
682 NTSTATUS status
= STATUS_SUCCESS
;
684 TRACE("(%p,%p,%p,%p,%08x,0x%08x,%p) stub\n",
685 handle
, when
, callback
, callback_arg
, resume
, period
, state
);
687 SERVER_START_REQ( set_timer
)
689 req
->handle
= wine_server_obj_handle( handle
);
690 req
->period
= period
;
691 req
->expire
= when
->QuadPart
;
692 req
->callback
= wine_server_client_ptr( callback
);
693 req
->arg
= wine_server_client_ptr( callback_arg
);
694 status
= wine_server_call( req
);
695 if (state
) *state
= reply
->signaled
;
699 /* set error but can still succeed */
700 if (resume
&& status
== STATUS_SUCCESS
) return STATUS_TIMER_RESUME_IGNORED
;
704 /**************************************************************************
705 * NtCancelTimer [NTDLL.@]
706 * ZwCancelTimer [NTDLL.@]
708 NTSTATUS WINAPI
NtCancelTimer(IN HANDLE handle
, OUT BOOLEAN
* state
)
712 SERVER_START_REQ( cancel_timer
)
714 req
->handle
= wine_server_obj_handle( handle
);
715 status
= wine_server_call( req
);
716 if (state
) *state
= reply
->signaled
;
722 /******************************************************************************
723 * NtQueryTimer (NTDLL.@)
725 * Retrieves information about a timer.
728 * TimerHandle [I] The timer to retrieve information about.
729 * TimerInformationClass [I] The type of information to retrieve.
730 * TimerInformation [O] Pointer to buffer to store information in.
731 * Length [I] The length of the buffer pointed to by TimerInformation.
732 * ReturnLength [O] Optional. The size of buffer actually used.
735 * Success: STATUS_SUCCESS
736 * Failure: STATUS_INFO_LENGTH_MISMATCH, if Length doesn't match the required data
737 * size for the class specified.
738 * STATUS_INVALID_INFO_CLASS, if an invalid TimerInformationClass was specified.
739 * STATUS_ACCESS_DENIED, if TimerHandle does not have TIMER_QUERY_STATE access
742 NTSTATUS WINAPI
NtQueryTimer(
744 TIMER_INFORMATION_CLASS TimerInformationClass
,
745 PVOID TimerInformation
,
749 TIMER_BASIC_INFORMATION
* basic_info
= TimerInformation
;
753 TRACE("(%p,%d,%p,0x%08x,%p)\n", TimerHandle
, TimerInformationClass
,
754 TimerInformation
, Length
, ReturnLength
);
756 switch (TimerInformationClass
)
758 case TimerBasicInformation
:
759 if (Length
< sizeof(TIMER_BASIC_INFORMATION
))
760 return STATUS_INFO_LENGTH_MISMATCH
;
762 SERVER_START_REQ(get_timer_info
)
764 req
->handle
= wine_server_obj_handle( TimerHandle
);
765 status
= wine_server_call(req
);
767 /* convert server time to absolute NTDLL time */
768 basic_info
->RemainingTime
.QuadPart
= reply
->when
;
769 basic_info
->TimerState
= reply
->signaled
;
773 /* convert from absolute into relative time */
774 NtQuerySystemTime(&now
);
775 if (now
.QuadPart
> basic_info
->RemainingTime
.QuadPart
)
776 basic_info
->RemainingTime
.QuadPart
= 0;
778 basic_info
->RemainingTime
.QuadPart
-= now
.QuadPart
;
780 if (ReturnLength
) *ReturnLength
= sizeof(TIMER_BASIC_INFORMATION
);
785 FIXME("Unhandled class %d\n", TimerInformationClass
);
786 return STATUS_INVALID_INFO_CLASS
;
790 /******************************************************************************
791 * NtQueryTimerResolution [NTDLL.@]
793 NTSTATUS WINAPI
NtQueryTimerResolution(OUT ULONG
* min_resolution
,
794 OUT ULONG
* max_resolution
,
795 OUT ULONG
* current_resolution
)
797 FIXME("(%p,%p,%p), stub!\n",
798 min_resolution
, max_resolution
, current_resolution
);
800 return STATUS_NOT_IMPLEMENTED
;
803 /******************************************************************************
804 * NtSetTimerResolution [NTDLL.@]
806 NTSTATUS WINAPI
NtSetTimerResolution(IN ULONG resolution
,
807 IN BOOLEAN set_resolution
,
808 OUT ULONG
* current_resolution
)
810 FIXME("(%u,%u,%p), stub!\n",
811 resolution
, set_resolution
, current_resolution
);
813 return STATUS_NOT_IMPLEMENTED
;
818 /* wait operations */
820 /******************************************************************
821 * NtWaitForMultipleObjects (NTDLL.@)
823 NTSTATUS WINAPI
NtWaitForMultipleObjects( DWORD count
, const HANDLE
*handles
,
824 BOOLEAN wait_all
, BOOLEAN alertable
,
825 const LARGE_INTEGER
*timeout
)
827 select_op_t select_op
;
828 UINT i
, flags
= SELECT_INTERRUPTIBLE
;
830 if (!count
|| count
> MAXIMUM_WAIT_OBJECTS
) return STATUS_INVALID_PARAMETER_1
;
832 if (alertable
) flags
|= SELECT_ALERTABLE
;
833 select_op
.wait
.op
= wait_all
? SELECT_WAIT_ALL
: SELECT_WAIT
;
834 for (i
= 0; i
< count
; i
++) select_op
.wait
.handles
[i
] = wine_server_obj_handle( handles
[i
] );
835 return server_select( &select_op
, offsetof( select_op_t
, wait
.handles
[count
] ), flags
, timeout
);
839 /******************************************************************
840 * NtWaitForSingleObject (NTDLL.@)
842 NTSTATUS WINAPI
NtWaitForSingleObject(HANDLE handle
, BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
844 return NtWaitForMultipleObjects( 1, &handle
, FALSE
, alertable
, timeout
);
848 /******************************************************************
849 * NtSignalAndWaitForSingleObject (NTDLL.@)
851 NTSTATUS WINAPI
NtSignalAndWaitForSingleObject( HANDLE hSignalObject
, HANDLE hWaitObject
,
852 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
854 select_op_t select_op
;
855 UINT flags
= SELECT_INTERRUPTIBLE
;
857 if (!hSignalObject
) return STATUS_INVALID_HANDLE
;
859 if (alertable
) flags
|= SELECT_ALERTABLE
;
860 select_op
.signal_and_wait
.op
= SELECT_SIGNAL_AND_WAIT
;
861 select_op
.signal_and_wait
.wait
= wine_server_obj_handle( hWaitObject
);
862 select_op
.signal_and_wait
.signal
= wine_server_obj_handle( hSignalObject
);
863 return server_select( &select_op
, sizeof(select_op
.signal_and_wait
), flags
, timeout
);
867 /******************************************************************
868 * NtYieldExecution (NTDLL.@)
870 NTSTATUS WINAPI
NtYieldExecution(void)
872 #ifdef HAVE_SCHED_YIELD
874 return STATUS_SUCCESS
;
876 return STATUS_NO_YIELD_PERFORMED
;
881 /******************************************************************
882 * NtDelayExecution (NTDLL.@)
884 NTSTATUS WINAPI
NtDelayExecution( BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
886 /* if alertable, we need to query the server */
888 return server_select( NULL
, 0, SELECT_INTERRUPTIBLE
| SELECT_ALERTABLE
, timeout
);
890 if (!timeout
|| timeout
->QuadPart
== TIMEOUT_INFINITE
) /* sleep forever */
892 for (;;) select( 0, NULL
, NULL
, NULL
, NULL
);
897 timeout_t when
, diff
;
899 if ((when
= timeout
->QuadPart
) < 0)
901 NtQuerySystemTime( &now
);
902 when
= now
.QuadPart
- when
;
905 /* Note that we yield after establishing the desired timeout */
907 if (!when
) return STATUS_SUCCESS
;
912 NtQuerySystemTime( &now
);
913 diff
= (when
- now
.QuadPart
+ 9) / 10;
914 if (diff
<= 0) break;
915 tv
.tv_sec
= diff
/ 1000000;
916 tv
.tv_usec
= diff
% 1000000;
917 if (select( 0, NULL
, NULL
, NULL
, &tv
) != -1) break;
920 return STATUS_SUCCESS
;
924 /******************************************************************************
925 * NtCreateKeyedEvent (NTDLL.@)
927 NTSTATUS WINAPI
NtCreateKeyedEvent( HANDLE
*handle
, ACCESS_MASK access
,
928 const OBJECT_ATTRIBUTES
*attr
, ULONG flags
)
930 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
932 struct security_descriptor
*sd
= NULL
;
933 struct object_attributes objattr
;
935 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
937 objattr
.rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
939 objattr
.name_len
= len
;
942 ret
= NTDLL_create_struct_sd( attr
->SecurityDescriptor
, &sd
, &objattr
.sd_len
);
943 if (ret
!= STATUS_SUCCESS
) return ret
;
946 SERVER_START_REQ( create_keyed_event
)
948 req
->access
= access
;
949 req
->attributes
= attr
? attr
->Attributes
: 0;
950 wine_server_add_data( req
, &objattr
, sizeof(objattr
) );
951 if (objattr
.sd_len
) wine_server_add_data( req
, sd
, objattr
.sd_len
);
952 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
953 ret
= wine_server_call( req
);
954 *handle
= wine_server_ptr_handle( reply
->handle
);
958 NTDLL_free_struct_sd( sd
);
962 /******************************************************************************
963 * NtOpenKeyedEvent (NTDLL.@)
965 NTSTATUS WINAPI
NtOpenKeyedEvent( HANDLE
*handle
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
967 DWORD len
= attr
&& attr
->ObjectName
? attr
->ObjectName
->Length
: 0;
970 if (len
>= MAX_PATH
* sizeof(WCHAR
)) return STATUS_NAME_TOO_LONG
;
972 SERVER_START_REQ( open_keyed_event
)
974 req
->access
= access
;
975 req
->attributes
= attr
? attr
->Attributes
: 0;
976 req
->rootdir
= wine_server_obj_handle( attr
? attr
->RootDirectory
: 0 );
977 if (len
) wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
978 ret
= wine_server_call( req
);
979 *handle
= wine_server_ptr_handle( reply
->handle
);
985 /******************************************************************************
986 * NtWaitForKeyedEvent (NTDLL.@)
988 NTSTATUS WINAPI
NtWaitForKeyedEvent( HANDLE handle
, const void *key
,
989 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
991 select_op_t select_op
;
992 UINT flags
= SELECT_INTERRUPTIBLE
;
994 if ((ULONG_PTR
)key
& 1) return STATUS_INVALID_PARAMETER_1
;
995 if (alertable
) flags
|= SELECT_ALERTABLE
;
996 select_op
.keyed_event
.op
= SELECT_KEYED_EVENT_WAIT
;
997 select_op
.keyed_event
.handle
= wine_server_obj_handle( handle
);
998 select_op
.keyed_event
.key
= wine_server_client_ptr( key
);
999 return server_select( &select_op
, sizeof(select_op
.keyed_event
), flags
, timeout
);
1002 /******************************************************************************
1003 * NtReleaseKeyedEvent (NTDLL.@)
1005 NTSTATUS WINAPI
NtReleaseKeyedEvent( HANDLE handle
, const void *key
,
1006 BOOLEAN alertable
, const LARGE_INTEGER
*timeout
)
1008 select_op_t select_op
;
1009 UINT flags
= SELECT_INTERRUPTIBLE
;
1011 if ((ULONG_PTR
)key
& 1) return STATUS_INVALID_PARAMETER_1
;
1012 if (alertable
) flags
|= SELECT_ALERTABLE
;
1013 select_op
.keyed_event
.op
= SELECT_KEYED_EVENT_RELEASE
;
1014 select_op
.keyed_event
.handle
= wine_server_obj_handle( handle
);
1015 select_op
.keyed_event
.key
= wine_server_client_ptr( key
);
1016 return server_select( &select_op
, sizeof(select_op
.keyed_event
), flags
, timeout
);
1019 /******************************************************************
1020 * NtCreateIoCompletion (NTDLL.@)
1021 * ZwCreateIoCompletion (NTDLL.@)
1023 * Creates I/O completion object.
1026 * CompletionPort [O] created completion object handle will be placed there
1027 * DesiredAccess [I] desired access to a handle (combination of IO_COMPLETION_*)
1028 * ObjectAttributes [I] completion object attributes
1029 * NumberOfConcurrentThreads [I] desired number of concurrent active worker threads
1032 NTSTATUS WINAPI
NtCreateIoCompletion( PHANDLE CompletionPort
, ACCESS_MASK DesiredAccess
,
1033 POBJECT_ATTRIBUTES ObjectAttributes
, ULONG NumberOfConcurrentThreads
)
1037 TRACE("(%p, %x, %p, %d)\n", CompletionPort
, DesiredAccess
,
1038 ObjectAttributes
, NumberOfConcurrentThreads
);
1040 if (!CompletionPort
)
1041 return STATUS_INVALID_PARAMETER
;
1043 SERVER_START_REQ( create_completion
)
1045 req
->access
= DesiredAccess
;
1046 req
->attributes
= ObjectAttributes
? ObjectAttributes
->Attributes
: 0;
1047 req
->rootdir
= wine_server_obj_handle( ObjectAttributes
? ObjectAttributes
->RootDirectory
: 0 );
1048 req
->concurrent
= NumberOfConcurrentThreads
;
1049 if (ObjectAttributes
&& ObjectAttributes
->ObjectName
)
1050 wine_server_add_data( req
, ObjectAttributes
->ObjectName
->Buffer
,
1051 ObjectAttributes
->ObjectName
->Length
);
1052 if (!(status
= wine_server_call( req
)))
1053 *CompletionPort
= wine_server_ptr_handle( reply
->handle
);
1059 /******************************************************************
1060 * NtSetIoCompletion (NTDLL.@)
1061 * ZwSetIoCompletion (NTDLL.@)
1063 * Inserts completion message into queue
1066 * CompletionPort [I] HANDLE to completion object
1067 * CompletionKey [I] completion key
1068 * CompletionValue [I] completion value (usually pointer to OVERLAPPED)
1069 * Status [I] operation status
1070 * NumberOfBytesTransferred [I] number of bytes transferred
1072 NTSTATUS WINAPI
NtSetIoCompletion( HANDLE CompletionPort
, ULONG_PTR CompletionKey
,
1073 ULONG_PTR CompletionValue
, NTSTATUS Status
,
1074 SIZE_T NumberOfBytesTransferred
)
1078 TRACE("(%p, %lx, %lx, %x, %lx)\n", CompletionPort
, CompletionKey
,
1079 CompletionValue
, Status
, NumberOfBytesTransferred
);
1081 SERVER_START_REQ( add_completion
)
1083 req
->handle
= wine_server_obj_handle( CompletionPort
);
1084 req
->ckey
= CompletionKey
;
1085 req
->cvalue
= CompletionValue
;
1086 req
->status
= Status
;
1087 req
->information
= NumberOfBytesTransferred
;
1088 status
= wine_server_call( req
);
1094 /******************************************************************
1095 * NtRemoveIoCompletion (NTDLL.@)
1096 * ZwRemoveIoCompletion (NTDLL.@)
1098 * (Wait for and) retrieve first completion message from completion object's queue
1101 * CompletionPort [I] HANDLE to I/O completion object
1102 * CompletionKey [O] completion key
1103 * CompletionValue [O] Completion value given in NtSetIoCompletion or in async operation
1104 * iosb [O] IO_STATUS_BLOCK of completed asynchronous operation
1105 * WaitTime [I] optional wait time in NTDLL format
1108 NTSTATUS WINAPI
NtRemoveIoCompletion( HANDLE CompletionPort
, PULONG_PTR CompletionKey
,
1109 PULONG_PTR CompletionValue
, PIO_STATUS_BLOCK iosb
,
1110 PLARGE_INTEGER WaitTime
)
1114 TRACE("(%p, %p, %p, %p, %p)\n", CompletionPort
, CompletionKey
,
1115 CompletionValue
, iosb
, WaitTime
);
1119 SERVER_START_REQ( remove_completion
)
1121 req
->handle
= wine_server_obj_handle( CompletionPort
);
1122 if (!(status
= wine_server_call( req
)))
1124 *CompletionKey
= reply
->ckey
;
1125 *CompletionValue
= reply
->cvalue
;
1126 iosb
->Information
= reply
->information
;
1127 iosb
->u
.Status
= reply
->status
;
1131 if (status
!= STATUS_PENDING
) break;
1133 status
= NtWaitForSingleObject( CompletionPort
, FALSE
, WaitTime
);
1134 if (status
!= WAIT_OBJECT_0
) break;
1139 /******************************************************************
1140 * NtOpenIoCompletion (NTDLL.@)
1141 * ZwOpenIoCompletion (NTDLL.@)
1143 * Opens I/O completion object
1146 * CompletionPort [O] completion object handle will be placed there
1147 * DesiredAccess [I] desired access to a handle (combination of IO_COMPLETION_*)
1148 * ObjectAttributes [I] completion object name
1151 NTSTATUS WINAPI
NtOpenIoCompletion( PHANDLE CompletionPort
, ACCESS_MASK DesiredAccess
,
1152 POBJECT_ATTRIBUTES ObjectAttributes
)
1156 TRACE("(%p, 0x%x, %p)\n", CompletionPort
, DesiredAccess
, ObjectAttributes
);
1158 if (!CompletionPort
|| !ObjectAttributes
|| !ObjectAttributes
->ObjectName
)
1159 return STATUS_INVALID_PARAMETER
;
1161 SERVER_START_REQ( open_completion
)
1163 req
->access
= DesiredAccess
;
1164 req
->rootdir
= wine_server_obj_handle( ObjectAttributes
->RootDirectory
);
1165 wine_server_add_data( req
, ObjectAttributes
->ObjectName
->Buffer
,
1166 ObjectAttributes
->ObjectName
->Length
);
1167 if (!(status
= wine_server_call( req
)))
1168 *CompletionPort
= wine_server_ptr_handle( reply
->handle
);
1174 /******************************************************************
1175 * NtQueryIoCompletion (NTDLL.@)
1176 * ZwQueryIoCompletion (NTDLL.@)
1178 * Requests information about given I/O completion object
1181 * CompletionPort [I] HANDLE to completion port to request
1182 * InformationClass [I] information class
1183 * CompletionInformation [O] user-provided buffer for data
1184 * BufferLength [I] buffer length
1185 * RequiredLength [O] required buffer length
1188 NTSTATUS WINAPI
NtQueryIoCompletion( HANDLE CompletionPort
, IO_COMPLETION_INFORMATION_CLASS InformationClass
,
1189 PVOID CompletionInformation
, ULONG BufferLength
, PULONG RequiredLength
)
1193 TRACE("(%p, %d, %p, 0x%x, %p)\n", CompletionPort
, InformationClass
, CompletionInformation
,
1194 BufferLength
, RequiredLength
);
1196 if (!CompletionInformation
) return STATUS_INVALID_PARAMETER
;
1197 switch( InformationClass
)
1199 case IoCompletionBasicInformation
:
1201 ULONG
*info
= CompletionInformation
;
1203 if (RequiredLength
) *RequiredLength
= sizeof(*info
);
1204 if (BufferLength
!= sizeof(*info
))
1205 status
= STATUS_INFO_LENGTH_MISMATCH
;
1208 SERVER_START_REQ( query_completion
)
1210 req
->handle
= wine_server_obj_handle( CompletionPort
);
1211 if (!(status
= wine_server_call( req
)))
1212 *info
= reply
->depth
;
1219 status
= STATUS_INVALID_PARAMETER
;
1225 NTSTATUS
NTDLL_AddCompletion( HANDLE hFile
, ULONG_PTR CompletionValue
,
1226 NTSTATUS CompletionStatus
, ULONG Information
)
1230 SERVER_START_REQ( add_fd_completion
)
1232 req
->handle
= wine_server_obj_handle( hFile
);
1233 req
->cvalue
= CompletionValue
;
1234 req
->status
= CompletionStatus
;
1235 req
->information
= Information
;
1236 status
= wine_server_call( req
);
1242 /******************************************************************
1243 * RtlRunOnceInitialize (NTDLL.@)
1245 void WINAPI
RtlRunOnceInitialize( RTL_RUN_ONCE
*once
)
1250 /******************************************************************
1251 * RtlRunOnceBeginInitialize (NTDLL.@)
1253 DWORD WINAPI
RtlRunOnceBeginInitialize( RTL_RUN_ONCE
*once
, ULONG flags
, void **context
)
1255 if (flags
& RTL_RUN_ONCE_CHECK_ONLY
)
1257 ULONG_PTR val
= (ULONG_PTR
)once
->Ptr
;
1259 if (flags
& RTL_RUN_ONCE_ASYNC
) return STATUS_INVALID_PARAMETER
;
1260 if ((val
& 3) != 2) return STATUS_UNSUCCESSFUL
;
1261 if (context
) *context
= (void *)(val
& ~3);
1262 return STATUS_SUCCESS
;
1267 ULONG_PTR next
, val
= (ULONG_PTR
)once
->Ptr
;
1271 case 0: /* first time */
1272 if (!interlocked_cmpxchg_ptr( &once
->Ptr
,
1273 (flags
& RTL_RUN_ONCE_ASYNC
) ? (void *)3 : (void *)1, 0 ))
1274 return STATUS_PENDING
;
1277 case 1: /* in progress, wait */
1278 if (flags
& RTL_RUN_ONCE_ASYNC
) return STATUS_INVALID_PARAMETER
;
1280 if (interlocked_cmpxchg_ptr( &once
->Ptr
, (void *)((ULONG_PTR
)&next
| 1),
1281 (void *)val
) == (void *)val
)
1282 NtWaitForKeyedEvent( keyed_event
, &next
, FALSE
, NULL
);
1286 if (context
) *context
= (void *)(val
& ~3);
1287 return STATUS_SUCCESS
;
1289 case 3: /* in progress, async */
1290 if (!(flags
& RTL_RUN_ONCE_ASYNC
)) return STATUS_INVALID_PARAMETER
;
1291 return STATUS_PENDING
;
1296 /******************************************************************
1297 * RtlRunOnceComplete (NTDLL.@)
1299 DWORD WINAPI
RtlRunOnceComplete( RTL_RUN_ONCE
*once
, ULONG flags
, void *context
)
1301 if ((ULONG_PTR
)context
& 3) return STATUS_INVALID_PARAMETER
;
1303 if (flags
& RTL_RUN_ONCE_INIT_FAILED
)
1305 if (context
) return STATUS_INVALID_PARAMETER
;
1306 if (flags
& RTL_RUN_ONCE_ASYNC
) return STATUS_INVALID_PARAMETER
;
1308 else context
= (void *)((ULONG_PTR
)context
| 2);
1312 ULONG_PTR val
= (ULONG_PTR
)once
->Ptr
;
1316 case 1: /* in progress */
1317 if (interlocked_cmpxchg_ptr( &once
->Ptr
, context
, (void *)val
) != (void *)val
) break;
1321 ULONG_PTR next
= *(ULONG_PTR
*)val
;
1322 NtReleaseKeyedEvent( keyed_event
, (void *)val
, FALSE
, NULL
);
1325 return STATUS_SUCCESS
;
1327 case 3: /* in progress, async */
1328 if (!(flags
& RTL_RUN_ONCE_ASYNC
)) return STATUS_INVALID_PARAMETER
;
1329 if (interlocked_cmpxchg_ptr( &once
->Ptr
, context
, (void *)val
) != (void *)val
) break;
1330 return STATUS_SUCCESS
;
1333 return STATUS_UNSUCCESSFUL
;
1338 /******************************************************************
1339 * RtlRunOnceExecuteOnce (NTDLL.@)
1341 DWORD WINAPI
RtlRunOnceExecuteOnce( RTL_RUN_ONCE
*once
, PRTL_RUN_ONCE_INIT_FN func
,
1342 void *param
, void **context
)
1344 DWORD ret
= RtlRunOnceBeginInitialize( once
, 0, context
);
1346 if (ret
!= STATUS_PENDING
) return ret
;
1348 if (!func( once
, param
, context
))
1350 RtlRunOnceComplete( once
, RTL_RUN_ONCE_INIT_FAILED
, NULL
);
1351 return STATUS_UNSUCCESSFUL
;
1354 return RtlRunOnceComplete( once
, 0, context
? *context
: NULL
);
1357 /***********************************************************************
1358 * RtlInitializeSRWLock (NTDLL.@)
1360 void WINAPI
RtlInitializeSRWLock( RTL_SRWLOCK
*lock
)
1365 /***********************************************************************
1366 * RtlAcquireSRWLockExclusive (NTDLL.@)
1368 void WINAPI
RtlAcquireSRWLockExclusive( RTL_SRWLOCK
*lock
)
1370 FIXME( "%p stub\n", lock
);
1373 /***********************************************************************
1374 * RtlAcquireSRWLockShared (NTDLL.@)
1376 void WINAPI
RtlAcquireSRWLockShared( RTL_SRWLOCK
*lock
)
1378 FIXME( "%p stub\n", lock
);
1381 /***********************************************************************
1382 * RtlReleaseSRWLockExclusive (NTDLL.@)
1384 void WINAPI
RtlReleaseSRWLockExclusive( RTL_SRWLOCK
*lock
)
1386 FIXME( "%p stub\n", lock
);
1389 /***********************************************************************
1390 * RtlReleaseSRWLockShared (NTDLL.@)
1392 void WINAPI
RtlReleaseSRWLockShared( RTL_SRWLOCK
*lock
)
1394 FIXME( "%p stub\n", lock
);