| /* |
| * Process synchronisation |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <time.h> |
| #include "debugtools.h" |
| |
| #include "winerror.h" |
| #include "server.h" |
| #include "ntddk.h" |
| #include "ntdll_misc.h" |
| |
| DEFAULT_DEBUG_CHANNEL(ntdll); |
| |
| /* copy a key name into the request buffer */ |
| static inline NTSTATUS copy_nameU( LPWSTR Dest, const OBJECT_ATTRIBUTES *attr ) |
| { |
| if (attr && attr->ObjectName && attr->ObjectName->Buffer) |
| { |
| if ((attr->ObjectName->Length) > MAX_PATH) return STATUS_BUFFER_OVERFLOW; |
| lstrcpyW( Dest, attr->ObjectName->Buffer ); |
| } |
| else Dest[0] = 0; |
| return STATUS_SUCCESS; |
| } |
| |
| /* |
| * Semaphores |
| */ |
| |
| /****************************************************************************** |
| * NtCreateSemaphore |
| */ |
| NTSTATUS WINAPI NtCreateSemaphore( |
| OUT PHANDLE SemaphoreHandle, |
| IN ACCESS_MASK DesiredAccess, |
| IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, |
| IN ULONG InitialCount, |
| IN ULONG MaximumCount) |
| { |
| struct create_semaphore_request *req = get_req_buffer(); |
| NTSTATUS ret; |
| |
| if ((MaximumCount <= 0) || (InitialCount < 0) || (InitialCount > MaximumCount)) |
| return STATUS_INVALID_PARAMETER; |
| |
| *SemaphoreHandle = 0; |
| req->initial = InitialCount; |
| req->max = MaximumCount; |
| req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT); |
| if (!(ret = copy_nameU( req->name, ObjectAttributes )) && |
| !(ret = server_call_noerr( REQ_CREATE_SEMAPHORE ))) *SemaphoreHandle = req->handle; |
| return ret; |
| } |
| |
| /****************************************************************************** |
| * NtOpenSemaphore |
| */ |
| NTSTATUS WINAPI NtOpenSemaphore( |
| OUT PHANDLE SemaphoreHandle, |
| IN ACCESS_MASK DesiredAcces, |
| IN POBJECT_ATTRIBUTES ObjectAttributes) |
| { |
| struct open_semaphore_request *req = get_req_buffer(); |
| NTSTATUS ret; |
| |
| *SemaphoreHandle = 0; |
| req->access = DesiredAcces; |
| req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT); |
| if (!(ret = copy_nameU( req->name, ObjectAttributes )) && |
| !(ret = server_call_noerr( REQ_OPEN_SEMAPHORE ))) *SemaphoreHandle = req->handle; |
| return ret; |
| } |
| |
| /****************************************************************************** |
| * NtQuerySemaphore |
| */ |
| NTSTATUS WINAPI NtQuerySemaphore( |
| HANDLE SemaphoreHandle, |
| PVOID SemaphoreInformationClass, |
| OUT PVOID SemaphoreInformation, |
| ULONG Length, |
| PULONG ReturnLength) |
| { |
| FIXME("(0x%08x,%p,%p,0x%08lx,%p) stub!\n", |
| SemaphoreHandle, SemaphoreInformationClass, SemaphoreInformation, Length, ReturnLength); |
| return STATUS_SUCCESS; |
| } |
| /****************************************************************************** |
| * NtReleaseSemaphore |
| */ |
| NTSTATUS WINAPI NtReleaseSemaphore( |
| IN HANDLE SemaphoreHandle, |
| IN ULONG ReleaseCount, |
| IN PULONG PreviousCount) |
| { |
| struct release_semaphore_request *req = get_req_buffer(); |
| NTSTATUS ret; |
| |
| if (ReleaseCount < 0) return STATUS_INVALID_PARAMETER; |
| |
| req->handle = SemaphoreHandle; |
| req->count = ReleaseCount; |
| if (!(ret = server_call_noerr( REQ_RELEASE_SEMAPHORE ))) |
| { |
| if (PreviousCount) *PreviousCount = req->prev_count; |
| } |
| return ret; |
| } |
| |
| /* |
| * Events |
| */ |
| |
| /************************************************************************** |
| * NtCreateEvent |
| */ |
| NTSTATUS WINAPI NtCreateEvent( |
| OUT PHANDLE EventHandle, |
| IN ACCESS_MASK DesiredAccess, |
| IN POBJECT_ATTRIBUTES ObjectAttributes, |
| IN BOOLEAN ManualReset, |
| IN BOOLEAN InitialState) |
| { |
| struct create_event_request *req = get_req_buffer(); |
| NTSTATUS ret; |
| |
| *EventHandle = 0; |
| req->manual_reset = ManualReset; |
| req->initial_state = InitialState; |
| req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT); |
| if (!(ret = copy_nameU( req->name, ObjectAttributes )) && |
| !(ret = server_call_noerr( REQ_CREATE_EVENT ))) *EventHandle = req->handle; |
| return ret; |
| } |
| |
| /****************************************************************************** |
| * NtOpenEvent |
| */ |
| NTSTATUS WINAPI NtOpenEvent( |
| OUT PHANDLE EventHandle, |
| IN ACCESS_MASK DesiredAccess, |
| IN POBJECT_ATTRIBUTES ObjectAttributes) |
| { |
| struct open_event_request *req = get_req_buffer(); |
| NTSTATUS ret; |
| |
| *EventHandle = 0; |
| req->access = DesiredAccess; |
| req->inherit = ObjectAttributes && (ObjectAttributes->Attributes & OBJ_INHERIT); |
| if (!(ret = copy_nameU( req->name, ObjectAttributes )) && |
| !(ret = server_call_noerr( REQ_OPEN_EVENT ))) *EventHandle = req->handle; |
| return ret; |
| } |
| |
| |
| /****************************************************************************** |
| * NtSetEvent |
| */ |
| NTSTATUS WINAPI NtSetEvent( |
| IN HANDLE EventHandle, |
| PULONG NumberOfThreadsReleased) |
| { |
| struct event_op_request *req = get_req_buffer(); |
| FIXME("(0x%08x,%p)\n", EventHandle, NumberOfThreadsReleased); |
| req->handle = EventHandle; |
| req->op = SET_EVENT; |
| return server_call_noerr( REQ_EVENT_OP ); |
| } |
| |
| /****************************************************************************** |
| * NtResetEvent |
| */ |
| NTSTATUS WINAPI NtResetEvent( |
| IN HANDLE EventHandle, |
| PULONG NumberOfThreadsReleased) |
| { |
| struct event_op_request *req = get_req_buffer(); |
| FIXME("(0x%08x,%p)\n", EventHandle, NumberOfThreadsReleased); |
| req->handle = EventHandle; |
| req->op = RESET_EVENT; |
| return server_call_noerr( REQ_EVENT_OP ); |
| } |
| |
| /****************************************************************************** |
| * NtClearEvent |
| * |
| * FIXME |
| * same as NtResetEvent ??? |
| */ |
| NTSTATUS WINAPI NtClearEvent ( |
| IN HANDLE EventHandle) |
| { |
| return NtResetEvent( EventHandle, NULL ); |
| } |
| |
| /****************************************************************************** |
| * NtPulseEvent |
| * |
| * FIXME |
| * PulseCount |
| */ |
| NTSTATUS WINAPI NtPulseEvent( |
| IN HANDLE EventHandle, |
| IN PULONG PulseCount) |
| { |
| struct event_op_request *req = get_req_buffer(); |
| FIXME("(0x%08x,%p)\n", EventHandle, PulseCount); |
| req->handle = EventHandle; |
| req->op = PULSE_EVENT; |
| return server_call_noerr( REQ_EVENT_OP ); |
| } |
| |
| /****************************************************************************** |
| * NtQueryEvent |
| */ |
| NTSTATUS WINAPI NtQueryEvent ( |
| IN HANDLE EventHandle, |
| IN UINT EventInformationClass, |
| OUT PVOID EventInformation, |
| IN ULONG EventInformationLength, |
| OUT PULONG ReturnLength) |
| { |
| FIXME("(0x%08x)\n", EventHandle); |
| return STATUS_SUCCESS; |
| } |