Author: fireball Date: Sat Jul 18 14:35:59 2009 New Revision: 42041
URL: http://svn.reactos.org/svn/reactos?rev=42041&view=rev Log: - Implement proper "wine server" invocations support, including variable data requests (both to and from the server). - Add global synch, so that our server deals only with one caller at a time.
Modified: branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c
Modified: branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c [iso-8859-1] Sat Jul 18 14:35:59 2009 @@ -20,33 +20,166 @@ #define NDEBUG #include <debug.h>
+ERESOURCE UserLock; + +PVOID RequestData; +ULONG ReplySize; +PVOID ReplyData; + /* PRIVATE FUNCTIONS *********************************************************/ + +VOID UserEnterExclusive(VOID) +{ + /* Acquire user resource exclusively */ + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&UserLock, TRUE); +} + +VOID UserLeave(VOID) +{ + /* Release user resource */ + ExReleaseResourceLite(&UserLock); + KeLeaveCriticalRegion(); +} + +#if 0 +VOID UserCleanup(VOID) +{ + ExDeleteResourceLite(&UserLock); +} +#endif + +VOID UserInitialize(VOID) +{ + NTSTATUS Status; + + /* Initialize user access resource */ + Status = ExInitializeResourceLite(&UserLock); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failure initializing USER resource!\n"); + } +}
UINT APIENTRY wine_server_call(void *req_ptr) { struct __server_request_info *reqinfo = req_ptr; - //struct type##_request * const req = &__req.u.req.type##_request; - //const struct type##_reply * const reply = &__req.u.reply.type##_reply; - union generic_reply reply; enum request req = reqinfo->u.req.request_header.req; + UCHAR i; + ULONG DataWritten=0;
DPRINT("WineServer call of type 0x%x\n", req);
+ /* Zero reply's memory area */ memset( &reply, 0, sizeof(reply) );
- //if (debug_level) trace_request(); + /* Acquire lock */ + UserEnterExclusive();
+ /* Clear error status */ + set_error(0); + + if (reqinfo->data_count > 1) + { + /* We need to make a contiguous data block from those */ + DataWritten = 0; + for (i=0; i<reqinfo->data_count; i++) + { + DataWritten += reqinfo->data[i].size; + } + + /* Allocate memory for it */ + RequestData = ExAllocatePool(PagedPool, DataWritten); + + /* Place them */ + DataWritten = 0; + for (i=0; i<reqinfo->data_count; i++) + { + RtlCopyMemory(((UCHAR *)RequestData + DataWritten), + reqinfo->data[i].ptr, + reqinfo->data[i].size); + + /* Advance to the next data block */ + DataWritten += reqinfo->data[i].size; + } + } + else + { + RequestData = (PVOID)reqinfo->data[0].ptr; + } + + ReplySize = 0; + ReplyData = NULL; + + /* Perform the request */ if (req < REQ_NB_REQUESTS) + { + /* Call request handler */ req_handlers[req]( req_ptr, &reply ); + } else + { DPRINT1("WineServer call of type 0x%x is not implemented!\n", req); + }
- //reply.reply_header.error = current->error; - //reply.reply_header.reply_size = current->reply_size; - //if (debug_level) trace_reply( req, &reply ); + /* Free the request data area if needed */ + if (reqinfo->data_count > 1) ExFreePool(RequestData);
- return 0; + /* Copy back the reply data if any */ + if (ReplySize) + { + /* Copy it */ + RtlCopyMemory(reqinfo->reply_data, ReplyData, ReplySize); + + /* Free temp storage */ + ExFreePool(ReplyData); + } + + /* Set reply's error flag and size */ + reply.reply_header.error = get_error(); + reply.reply_header.reply_size = ReplySize; + + /* Copy reply back */ + memcpy (&reqinfo->u.reply, &reply, sizeof(reply)); + + /* Release lock */ + UserLeave(); + + //if (reply.reply_header.error) + // DPRINT1("returning error 0x%08X\n", reply.reply_header.error); + + //if (reply.reply_header.error == 0x103 || + // reply.reply_header.error == STATUS_ACCESS_DENIED) DbgBreakPoint(); + + return reply.reply_header.error; } + +/* allocate the reply data */ +void *set_reply_data_size( void *req, data_size_t size ) +{ + ASSERT( size <= get_reply_max_size(req) ); + + /* Allocate storage for reply data */ + if (size && !(ReplyData = ExAllocatePool( PagedPool, size ))) size = 0; + + /* Set reply size */ + ReplySize = size; + + /* Return a pointer to allocated storage */ + return ReplyData; +} + +/* set the reply data pointer directly (will be freed by request code) */ +void set_reply_data_ptr( void *req, void *data, data_size_t size ) +{ + ASSERT( size < get_reply_max_size(req)); + + /* Just save them */ + ReplySize = size; + ReplyData = data; +} +