[VIDEOPRT/WIN32K]: Synchronize and share PEVENT/ENG_EVENT/VIDEO_PORT_EVENT implementation, as these objects are actually the same (and VideoPrt Event* APIs can be used on GRE Event Objects). Use ENG_EVENT structure from ntddvdeo.h instead of re-creating our own. Drivers using these interfaces will no longer explode.

[VIDEOPRT]: Add parameter checks to DeleteEvent and WaitForSingleObject.
[VIDEOPRT]: Fix WaitForSingleObject. It was waiting on the Object paramter itself -- which is the VideoPrt/ENG Event, not a real object, we have to wait on ->pKEvent instead.
[VIDEOPRT]: Fix WaitForSingleObject round two, it was returning the NT_STATUS, while VideoPrt should return VP_STATUS/Win32 error codes.
[WIN32K]: Allocate/free GRE events directly from pool, instead of using Eng APIs. Use documented tag for GRE Events (Dfsm), found in pooltag.txt
[WIN32K]: Implement EngMapEvent and EngUnmapEvent.


svn path=/trunk/; revision=50256
This commit is contained in:
Sir Richard 2011-01-01 18:15:25 +00:00
parent 05721dae3e
commit 3062a63e47
4 changed files with 186 additions and 137 deletions

View file

@ -1,120 +1,140 @@
/* /*
* VideoPort driver * PROJECT: ReactOS Video Port Driver
* * LICENSE: BSD - See COPYING.ARM in the top level directory
* Copyright (C) 2002, 2003, 2004 ReactOS Team * FILE: drivers/video/videoprt/event.c
* * PURPOSE: Event Support Routines
* This library is free software; you can redistribute it and/or * PROGRAMMERS: ReactOS Portable Systems Group
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/ */
/* INCLUDES *******************************************************************/
#include "videoprt.h" #include "videoprt.h"
#include "../../subsystems/win32/win32k/include/engevent.h"
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
/* /*
* @implemented * @implemented
*/ */
VP_STATUS
VP_STATUS NTAPI NTAPI
VideoPortCreateEvent( VideoPortCreateEvent(IN PVOID HwDeviceExtension,
IN PVOID HwDeviceExtension, IN ULONG EventFlag,
IN ULONG EventFlag, IN PVOID Unused,
IN PVOID Unused, OUT PEVENT *Event)
OUT PEVENT *Event)
{ {
PVIDEO_PORT_EVENT VpEvent; VP_STATUS Result = NO_ERROR;
EVENT_TYPE Type = SynchronizationEvent; PVIDEO_PORT_EVENT EngEvent;
/* Allocate storage for the event structure */ /* Allocate memory for the event structure */
VpEvent = ExAllocatePoolWithTag( EngEvent = ExAllocatePoolWithTag(NonPagedPool,
NonPagedPool, sizeof(VIDEO_PORT_EVENT) + sizeof(KEVENT),
sizeof(VIDEO_PORT_EVENT), TAG_VIDEO_PORT);
TAG_VIDEO_PORT); if (EngEvent)
{
/* Set KEVENT pointer */
EngEvent->pKEvent = EngEvent + 1;
/* Initialize the kernel event */
KeInitializeEvent(EngEvent->pKEvent,
(EventFlag & EVENT_TYPE_MASK) ?
NotificationEvent : SynchronizationEvent,
EventFlag & INITIAL_EVENT_STATE_MASK);
/* Fail if not enough memory */ /* Pass pointer to our structure to the caller */
if (!VpEvent) return ERROR_NOT_ENOUGH_MEMORY; *Event = (PEVENT)EngEvent;
DPRINT("VideoPortCreateEvent() created %p\n", EngEvent);
}
else
{
/* Out of memory */
DPRINT("VideoPortCreateEvent() failed\n");
Result = ERROR_NOT_ENOUGH_MEMORY;
}
/* Initialize the event structure */ /* Return result */
RtlZeroMemory(VpEvent, sizeof(VIDEO_PORT_EVENT)); return Result;
VpEvent->pKEvent = &VpEvent->Event;
/* Determine the event type */
if (EventFlag & NOTIFICATION_EVENT)
Type = NotificationEvent;
/* Initialize kernel event */
KeInitializeEvent(VpEvent->pKEvent, Type, EventFlag & INITIAL_EVENT_SIGNALED);
/* Indicate success */
return NO_ERROR;
} }
/* /*
* @implemented * @implemented
*/ */
VP_STATUS
VP_STATUS NTAPI NTAPI
VideoPortDeleteEvent( VideoPortDeleteEvent(IN PVOID HwDeviceExtension,
IN PVOID HwDeviceExtension, IN PEVENT Event)
IN PEVENT Event)
{ {
/* Free storage */ /* Handle error cases */
ExFreePool(Event); if (!Event) return ERROR_INVALID_PARAMETER;
if (Event->fFlags & ENG_EVENT_USERMAPPED) return ERROR_INVALID_PARAMETER;
if (!Event->pKEvent) return ERROR_INVALID_PARAMETER;
/* Indicate success */ /* Free storage */
return NO_ERROR; ExFreePool(Event);
/* Indicate success */
return NO_ERROR;
} }
/* /*
* @implemented * @implemented
*/ */
LONG
LONG NTAPI NTAPI
VideoPortSetEvent( VideoPortSetEvent(IN PVOID HwDeviceExtension,
IN PVOID HwDeviceExtension, IN PEVENT Event)
IN PEVENT Event)
{ {
return KeSetEvent(Event->pKEvent, IO_NO_INCREMENT, FALSE); return KeSetEvent(Event->pKEvent, IO_NO_INCREMENT, FALSE);
} }
/* /*
* @implemented * @implemented
*/ */
VOID
VOID NTAPI NTAPI
VideoPortClearEvent( VideoPortClearEvent(IN PVOID HwDeviceExtension,
IN PVOID HwDeviceExtension, IN PEVENT Event)
IN PEVENT Event)
{ {
KeClearEvent(Event->pKEvent); KeClearEvent(Event->pKEvent);
} }
/* /*
* @implemented * @implemented
*/ */
VP_STATUS
VP_STATUS NTAPI NTAPI
VideoPortWaitForSingleObject( VideoPortWaitForSingleObject(IN PVOID HwDeviceExtension,
IN PVOID HwDeviceExtension, IN PVOID Event,
IN PVOID Object, IN PLARGE_INTEGER Timeout OPTIONAL)
IN PLARGE_INTEGER Timeout OPTIONAL)
{ {
return KeWaitForSingleObject( PVIDEO_PORT_EVENT EngEvent = Event;
Object, NTSTATUS Status;
Executive,
KernelMode, /* Handle error cases */
FALSE, if (!EngEvent) return ERROR_INVALID_PARAMETER;
Timeout); if (!EngEvent->pKEvent) return ERROR_INVALID_PARAMETER;
if (EngEvent->fFlags & ENG_EVENT_USERMAPPED) return ERROR_INVALID_PARAMETER;
/* Do the actual wait */
Status = KeWaitForSingleObject(EngEvent->pKEvent,
Executive,
KernelMode,
FALSE,
Timeout);
if (Status == STATUS_TIMEOUT)
{
/* Convert to wait timeout, otherwise NT_SUCCESS would return NO_ERROR */
return WAIT_TIMEOUT;
}
else if (NT_SUCCESS(Status))
{
/* All other success codes are Win32 success */
return NO_ERROR;
}
/* Otherwise, return default Win32 failure */
return ERROR_INVALID_PARAMETER;
} }
/* EOF */

View file

@ -107,11 +107,7 @@ typedef struct _VIDEO_PORT_DEVICE_EXTENSTION
typedef struct _VIDEO_PORT_EVENT typedef struct _VIDEO_PORT_EVENT
{ {
/* Public part */
ENG_EVENT; ENG_EVENT;
/* Private part */
KEVENT Event;
} VIDEO_PORT_EVENT, *PVIDEO_PORT_EVENT; } VIDEO_PORT_EVENT, *PVIDEO_PORT_EVENT;
/* agp.c */ /* agp.c */

View file

@ -1,54 +1,59 @@
/* /*
* PROJECT: ReactOS Win32K * PROJECT: ReactOS Win32K
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: subsystems/win32/win32k/eng/engevent.c * FILE: subsystems/win32/win32k/eng/engevent.c
* PURPOSE: Event Support Routines * PURPOSE: Event Support Routines
* PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org> * PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
* ReactOS Portable Systems Group
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES *******************************************************************/
#include <win32k.h> #include <win32k.h>
#include <ntddvdeo.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#define TAG_ENG ' gnE' /* Dfsm - <unknown> - Eng event allocation (ENG_KEVENTALLOC,ENG_ALLOC) in ntgdi\gre */
#define TAG_GRE_EVENT 'msfD'
/* PUBLIC FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
BOOL BOOL
APIENTRY APIENTRY
EngCreateEvent(OUT PEVENT* Event) EngCreateEvent(OUT PEVENT* Event)
{ {
BOOLEAN Result = TRUE;
PENG_EVENT EngEvent; PENG_EVENT EngEvent;
/* Allocate memory for the event structure */ /* Allocate memory for the event structure */
EngEvent = EngAllocMem(FL_NONPAGED_MEMORY | FL_ZERO_MEMORY, EngEvent = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ENG_EVENT), sizeof(ENG_EVENT) + sizeof(KEVENT),
TAG_ENG); TAG_GRE_EVENT);
if (EngEvent)
/* Check if we are out of memory */
if (!EngEvent)
{ {
/* We are, fail */ /* Set KEVENT pointer */
return FALSE; EngEvent->fFlags = 0;
EngEvent->pKEvent = EngEvent + 1;
/* Initialize the kernel event */
KeInitializeEvent(EngEvent->pKEvent,
SynchronizationEvent,
FALSE);
/* Pass pointer to our structure to the caller */
*Event = EngEvent;
DPRINT("EngCreateEvent() created %p\n", EngEvent);
}
else
{
/* Out of memory */
DPRINT("EngCreateEvent() failed\n");
Result = FALSE;
} }
/* Set KEVENT pointer */ /* Return result */
EngEvent->pKEvent = &EngEvent->KEvent; return Result;
/* Initialize the kernel event */
KeInitializeEvent(EngEvent->pKEvent,
SynchronizationEvent,
FALSE);
/* Pass pointer to our structure to the caller */
*Event = EngEvent;
DPRINT("EngCreateEvent() created %p\n", EngEvent);
/* Return success */
return TRUE;
} }
BOOL BOOL
@ -66,7 +71,7 @@ EngDeleteEvent(IN PEVENT Event)
} }
/* Free the allocated memory */ /* Free the allocated memory */
EngFreeMem(Event); ExFreePool(Event);
/* Return success */ /* Return success */
return TRUE; return TRUE;
@ -106,18 +111,57 @@ EngMapEvent(IN HDEV hDev,
IN PVOID Reserved2, IN PVOID Reserved2,
IN PVOID Reserved3) IN PVOID Reserved3)
{ {
DPRINT("EngMapEvent(%x %x %p %p %p)\n", hDev, hUserObject, Reserved1, Reserved2, Reserved3); PENG_EVENT EngEvent;
UNIMPLEMENTED; NTSTATUS Status;
return NULL;
/* Allocate memory for the event structure */
EngEvent = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ENG_EVENT),
TAG_GRE_EVENT);
if (!EngEvent) return NULL;
/* Zero it out */
EngEvent->fFlags = 0;
EngEvent->pKEvent = NULL;
/* Create a handle, and have Ob fill out the pKEvent field */
Status = ObReferenceObjectByHandle(EngEvent,
EVENT_ALL_ACCESS,
ExEventObjectType,
UserMode,
&EngEvent->pKEvent,
NULL);
if (NT_SUCCESS(Status))
{
/* Pulse the event and set that it's mapped by user */
KePulseEvent(EngEvent->pKEvent, EVENT_INCREMENT, FALSE);
EngEvent->fFlags |= ENG_EVENT_USERMAPPED;
}
else
{
/* Free the allocation */
ExFreePool(EngEvent);
EngEvent = NULL;
}
/* Support legacy interface */
if (Reserved1) *(PVOID*)Reserved1 = EngEvent;
return EngEvent;
} }
BOOL BOOL
APIENTRY APIENTRY
EngUnmapEvent(IN PEVENT Event) EngUnmapEvent(IN PEVENT Event)
{ {
DPRINT("EngUnmapEvent(%p)\n", Event); /* Must be a usermapped event */
UNIMPLEMENTED; if (!(Event->fFlags & ENG_EVENT_USERMAPPED)) return FALSE;
return FALSE;
/* Dereference the object, destroying it */
ObDereferenceObject(Event->pKEvent);
/* Free the Eng object */
ExFreePool(Event);
return TRUE;
} }
BOOL BOOL
@ -126,7 +170,6 @@ EngWaitForSingleObject(IN PEVENT Event,
IN PLARGE_INTEGER TimeOut) IN PLARGE_INTEGER TimeOut)
{ {
NTSTATUS Status; NTSTATUS Status;
DPRINT("EngWaitForSingleObject(%p %I64d)\n", Event, TimeOut->QuadPart); DPRINT("EngWaitForSingleObject(%p %I64d)\n", Event, TimeOut->QuadPart);
/* Validate parameters */ /* Validate parameters */
@ -148,12 +191,7 @@ EngWaitForSingleObject(IN PEVENT Event,
TimeOut); TimeOut);
/* Check if there is a failure or a timeout */ /* Check if there is a failure or a timeout */
if (!NT_SUCCESS(Status)) return NT_SUCCESS(Status);
{
/* Return failure */
return FALSE;
}
/* Return success */
return TRUE;
} }
/* EOF */

View file

@ -1,13 +1,8 @@
#pragma once #pragma once
#define ENG_EVENT_USERMAPPED 1 //
// Flags for the fFlags field of ENG_EVENT
//
#define ENG_EVENT_USERMAPPED 0x01
typedef struct _ENG_EVENT /* EOF */
{
/* Public part */
PVOID pKEvent;
ULONG fFlags;
/* Private part */
KEVENT KEvent;
} ENG_EVENT, *PENG_EVENT;