diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index af1dba92c40..b05bd1988a6 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -211,16 +211,33 @@ NTSTATUS WINAPI NtOpenSemaphore( OUT PHANDLE SemaphoreHandle, /****************************************************************************** * NtQuerySemaphore (NTDLL.@) */ -NTSTATUS WINAPI NtQuerySemaphore( - HANDLE SemaphoreHandle, - SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass, - PVOID SemaphoreInformation, - ULONG Length, - PULONG ReturnLength) +NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS class, + void *info, ULONG len, ULONG *ret_len ) { - FIXME("(%p,%d,%p,0x%08x,%p) stub!\n", - SemaphoreHandle, SemaphoreInformationClass, SemaphoreInformation, Length, ReturnLength); - return STATUS_SUCCESS; + NTSTATUS ret; + SEMAPHORE_BASIC_INFORMATION *out = info; + + if (class != SemaphoreBasicInformation) + { + FIXME("(%p,%d,%u) Unknown class\n", handle, class, len); + return STATUS_INVALID_INFO_CLASS; + } + + if (len != sizeof(SEMAPHORE_BASIC_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; + + SERVER_START_REQ( query_semaphore ) + { + req->handle = wine_server_obj_handle( handle ); + if (!(ret = wine_server_call( req ))) + { + out->CurrentCount = reply->current; + out->MaximumCount = reply->max; + if (ret_len) *ret_len = sizeof(SEMAPHORE_BASIC_INFORMATION); + } + } + SERVER_END_REQ; + + return ret; } /****************************************************************************** diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index f936a882ec4..0d69ad31de5 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1280,6 +1280,17 @@ struct release_semaphore_reply char __pad_12[4]; }; +struct query_semaphore_request +{ + struct request_header __header; + obj_handle_t handle; +}; +struct query_semaphore_reply +{ + struct reply_header __header; + unsigned int current; + unsigned int max; +}; struct open_semaphore_request @@ -5108,6 +5119,7 @@ enum request REQ_open_mutex, REQ_create_semaphore, REQ_release_semaphore, + REQ_query_semaphore, REQ_open_semaphore, REQ_create_file, REQ_open_file_object, @@ -5369,6 +5381,7 @@ union generic_request struct open_mutex_request open_mutex_request; struct create_semaphore_request create_semaphore_request; struct release_semaphore_request release_semaphore_request; + struct query_semaphore_request query_semaphore_request; struct open_semaphore_request open_semaphore_request; struct create_file_request create_file_request; struct open_file_object_request open_file_object_request; @@ -5628,6 +5641,7 @@ union generic_reply struct open_mutex_reply open_mutex_reply; struct create_semaphore_reply create_semaphore_reply; struct release_semaphore_reply release_semaphore_reply; + struct query_semaphore_reply query_semaphore_reply; struct open_semaphore_reply open_semaphore_reply; struct create_file_reply create_file_reply; struct open_file_object_reply open_file_object_reply; @@ -5848,6 +5862,6 @@ union generic_reply struct set_suspend_context_reply set_suspend_context_reply; }; -#define SERVER_PROTOCOL_VERSION 453 +#define SERVER_PROTOCOL_VERSION 454 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winnt.h b/include/winnt.h index f1751a5b5bc..f55f2feddce 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -4512,6 +4512,7 @@ typedef enum tagSID_NAME_USE { #define EVENT_MODIFY_STATE 0x0002 #define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) +#define SEMAPHORE_QUERY_STATE 0x0001 #define SEMAPHORE_MODIFY_STATE 0x0002 #define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3) diff --git a/server/protocol.def b/server/protocol.def index 8c5f953511e..fec5e755997 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1072,6 +1072,12 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; unsigned int prev_count; /* previous semaphore count */ @END +@REQ(query_semaphore) + obj_handle_t handle; /* handle to the semaphore */ +@REPLY + unsigned int current; /* current count */ + unsigned int max; /* maximum count */ +@END /* Open a semaphore */ @REQ(open_semaphore) diff --git a/server/request.h b/server/request.h index 3730f7b5f7c..8e35b0d07a3 100644 --- a/server/request.h +++ b/server/request.h @@ -142,6 +142,7 @@ DECL_HANDLER(release_mutex); DECL_HANDLER(open_mutex); DECL_HANDLER(create_semaphore); DECL_HANDLER(release_semaphore); +DECL_HANDLER(query_semaphore); DECL_HANDLER(open_semaphore); DECL_HANDLER(create_file); DECL_HANDLER(open_file_object); @@ -402,6 +403,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_open_mutex, (req_handler)req_create_semaphore, (req_handler)req_release_semaphore, + (req_handler)req_query_semaphore, (req_handler)req_open_semaphore, (req_handler)req_create_file, (req_handler)req_open_file_object, @@ -888,6 +890,11 @@ C_ASSERT( FIELD_OFFSET(struct release_semaphore_request, count) == 16 ); C_ASSERT( sizeof(struct release_semaphore_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct release_semaphore_reply, prev_count) == 8 ); C_ASSERT( sizeof(struct release_semaphore_reply) == 16 ); +C_ASSERT( FIELD_OFFSET(struct query_semaphore_request, handle) == 12 ); +C_ASSERT( sizeof(struct query_semaphore_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct query_semaphore_reply, current) == 8 ); +C_ASSERT( FIELD_OFFSET(struct query_semaphore_reply, max) == 12 ); +C_ASSERT( sizeof(struct query_semaphore_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct open_semaphore_request, access) == 12 ); C_ASSERT( FIELD_OFFSET(struct open_semaphore_request, attributes) == 16 ); C_ASSERT( FIELD_OFFSET(struct open_semaphore_request, rootdir) == 20 ); diff --git a/server/semaphore.c b/server/semaphore.c index 109eb9aeed9..bdc35fe49d4 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -237,3 +237,17 @@ DECL_HANDLER(release_semaphore) release_object( sem ); } } + +/* query details about the semaphore */ +DECL_HANDLER(query_semaphore) +{ + struct semaphore *sem; + + if ((sem = (struct semaphore *)get_handle_obj( current->process, req->handle, + SEMAPHORE_QUERY_STATE, &semaphore_ops ))) + { + reply->current = sem->count; + reply->max = sem->max; + release_object( sem ); + } +} diff --git a/server/trace.c b/server/trace.c index 7fe5c4fb701..b7924943899 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1543,6 +1543,17 @@ static void dump_release_semaphore_reply( const struct release_semaphore_reply * fprintf( stderr, " prev_count=%08x", req->prev_count ); } +static void dump_query_semaphore_request( const struct query_semaphore_request *req ) +{ + fprintf( stderr, " handle=%04x", req->handle ); +} + +static void dump_query_semaphore_reply( const struct query_semaphore_reply *req ) +{ + fprintf( stderr, " current=%08x", req->current ); + fprintf( stderr, ", max=%08x", req->max ); +} + static void dump_open_semaphore_request( const struct open_semaphore_request *req ) { fprintf( stderr, " access=%08x", req->access ); @@ -4121,6 +4132,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_open_mutex_request, (dump_func)dump_create_semaphore_request, (dump_func)dump_release_semaphore_request, + (dump_func)dump_query_semaphore_request, (dump_func)dump_open_semaphore_request, (dump_func)dump_create_file_request, (dump_func)dump_open_file_object_request, @@ -4378,6 +4390,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_open_mutex_reply, (dump_func)dump_create_semaphore_reply, (dump_func)dump_release_semaphore_reply, + (dump_func)dump_query_semaphore_reply, (dump_func)dump_open_semaphore_reply, (dump_func)dump_create_file_reply, (dump_func)dump_open_file_object_reply, @@ -4635,6 +4648,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "open_mutex", "create_semaphore", "release_semaphore", + "query_semaphore", "open_semaphore", "create_file", "open_file_object",