Changeset 37221 in vbox for trunk/src/VBox/Additions/WINNT/Mouse
- Timestamp:
- May 26, 2011 10:33:21 AM (14 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/Mouse
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMF.h
r37163 r37221 56 56 VMMDevReqMouseStatus *pSCReq; /* Preallocated request to use in pfnServiceCB */ 57 57 58 IO_REMOVE_LOCK RemoveLock; 58 59 } VBOXMOUSE_DEVEXT, *PVBOXMOUSE_DEVEXT; 59 60 … … 76 77 VOID VBoxDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt); 77 78 79 VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG InputDataConsumed); 80 78 81 #endif /*VBOXMF_H*/ -
trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFDriver.cpp
r37163 r37221 20 20 #include <VBox/VBoxGuestLib.h> 21 21 #include <iprt/initterm.h> 22 #include <iprt/assert.h> 22 23 23 24 #ifdef ALLOC_PRAGMA … … 63 64 } 64 65 66 #define VBOXUSB_RLTAG 'LRBV' 67 65 68 NTSTATUS VBoxDrvAddDevice(IN PDRIVER_OBJECT Driver, IN PDEVICE_OBJECT PDO) 66 69 { … … 82 85 RtlZeroMemory(pDevExt, sizeof(VBOXMOUSE_DEVEXT)); 83 86 87 IoInitializeRemoveLock(&pDevExt->RemoveLock, VBOXUSB_RLTAG, 1, 100); 88 89 rc = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt); 90 if (!NT_SUCCESS(rc)) 91 { 92 WARN(("IoAcquireRemoveLock failed with %#x", rc)); 93 IoDeleteDevice(pDO); 94 return rc; 95 } 96 84 97 pDOParent = IoAttachDeviceToDeviceStack(pDO, PDO); 85 98 if (!pDOParent) 86 99 { 100 IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, pDevExt); 101 87 102 WARN(("IoAttachDeviceToDeviceStack failed")); 88 103 IoDeleteDevice(pDO); … … 105 120 NTSTATUS VBoxIrpPassthrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 106 121 { 107 PIO_STACK_LOCATION pStack; 108 PVBOXMOUSE_DEVEXT pDevExt; 109 LOGF_ENTER(); 110 111 pStack = IoGetCurrentIrpStackLocation(Irp); 122 PVBOXMOUSE_DEVEXT pDevExt; 123 LOGF_ENTER(); 124 112 125 pDevExt = (PVBOXMOUSE_DEVEXT) DeviceObject->DeviceExtension; 113 126 … … 127 140 pDevExt = (PVBOXMOUSE_DEVEXT) DeviceObject->DeviceExtension; 128 141 129 if (pDevExt->pSCReq) 130 { 131 int rc = VbglGRPerform(&pDevExt->pSCReq->header); 132 133 if (RT_SUCCESS(rc)) 134 { 135 if (pDevExt->pSCReq->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE) 136 { 137 PMOUSE_INPUT_DATA pData = InputDataStart; 138 while (pData<InputDataEnd) 139 { 140 pData->LastX = pDevExt->pSCReq->pointerXPos; 141 pData->LastY = pDevExt->pSCReq->pointerYPos; 142 pData->Flags = MOUSE_MOVE_ABSOLUTE; 143 pData++; 144 } 145 } 146 } 147 else 148 { 149 WARN(("VbglGRPerform failed with rc=%#x", rc)); 150 } 151 } 152 153 /* Call original callback */ 154 pDevExt->OriginalConnectData.pfnServiceCB(pDevExt->OriginalConnectData.pDO, 155 InputDataStart, InputDataEnd, InputDataConsumed); 142 VBoxDrvNotifyServiceCB(pDevExt, InputDataStart, InputDataEnd, InputDataConsumed); 156 143 157 144 LOGF_LEAVE(); … … 219 206 { 220 207 LOGF(("IRP_MN_REMOVE_DEVICE")); 208 209 IoReleaseRemoveLockAndWait(&pDevExt->RemoveLock, pDevExt); 210 221 211 VBoxDeviceRemoved(pDevExt); 222 212 -
trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp
r37163 r37221 19 19 #include "VBoxMF.h" 20 20 #include <VBox/VBoxGuestLib.h> 21 #include <VBox/VBoxGuest.h> 22 #include <iprt/assert.h> 23 #include <iprt/asm.h> 24 25 typedef struct VBOXGDC 26 { 27 PDEVICE_OBJECT pDo; 28 PFILE_OBJECT pFo; 29 } VBOXGDC, *PVBOXGDC; 21 30 22 31 typedef struct _VBoxGlobalContext … … 27 36 volatile LONG fHostInformed; 28 37 volatile LONG fHostMouseFound; 38 VBOXGDC Gdc; 39 KSPIN_LOCK SyncLock; 40 KEVENT TerminateEvent; 41 KEVENT MouseEvent; 42 PKTHREAD pThread; 43 volatile PVBOXMOUSE_DEVEXT pCurrentDevExt; 44 LIST_ENTRY DevExtList; 45 MOUSE_INPUT_DATA LastReportedData; 29 46 } VBoxGlobalContext; 30 47 31 static VBoxGlobalContext g_ctx = {0, FALSE, FALSE, FALSE, FALSE}; 48 static VBoxGlobalContext g_ctx = {}; 49 50 NTSTATUS VBoxGdcInit() 51 { 52 UNICODE_STRING UniName; 53 RtlInitUnicodeString(&UniName, VBOXGUEST_DEVICE_NAME_NT); 54 NTSTATUS Status = IoGetDeviceObjectPointer(&UniName, FILE_ALL_ACCESS, &g_ctx.Gdc.pFo, &g_ctx.Gdc.pDo); 55 if (!NT_SUCCESS(Status)) 56 { 57 WARN(("IoGetDeviceObjectPointer failed Status(0x%x)", Status)); 58 memset(&g_ctx.Gdc, 0, sizeof (g_ctx.Gdc)); 59 } 60 return Status; 61 } 62 63 BOOLEAN VBoxGdcIsInitialized() 64 { 65 return !!g_ctx.Gdc.pDo; 66 } 67 68 NTSTATUS VBoxGdcTerm() 69 { 70 if (!g_ctx.Gdc.pFo) 71 return STATUS_SUCCESS; 72 /* this will dereference device object as well */ 73 ObDereferenceObject(g_ctx.Gdc.pFo); 74 return STATUS_SUCCESS; 75 } 76 77 static NTSTATUS vboxGdcSubmitAsync(ULONG uCtl, PVOID pvBuffer, SIZE_T cbBuffer, PKEVENT pEvent, PIO_STATUS_BLOCK pIoStatus) 78 { 79 NTSTATUS Status; 80 PIRP pIrp; 81 KIRQL Irql = KeGetCurrentIrql(); 82 Assert(Irql == PASSIVE_LEVEL); 83 84 pIrp = IoBuildDeviceIoControlRequest(uCtl, g_ctx.Gdc.pDo, NULL, 0, NULL, 0, TRUE, pEvent, pIoStatus); 85 if (!pIrp) 86 { 87 WARN(("IoBuildDeviceIoControlRequest failed!!\n")); 88 pIoStatus->Status = STATUS_INSUFFICIENT_RESOURCES; 89 pIoStatus->Information = 0; 90 return STATUS_INSUFFICIENT_RESOURCES; 91 } 92 93 PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp); 94 pSl->Parameters.Others.Argument1 = (PVOID)pvBuffer; 95 pSl->Parameters.Others.Argument2 = (PVOID)cbBuffer; 96 Status = IoCallDriver(g_ctx.Gdc.pDo, pIrp); 97 98 return Status; 99 } 100 101 static NTSTATUS vboxGdcSubmit(ULONG uCtl, PVOID pvBuffer, SIZE_T cbBuffer) 102 { 103 IO_STATUS_BLOCK IoStatus = {0}; 104 KEVENT Event; 105 NTSTATUS Status; 106 107 KeInitializeEvent(&Event, NotificationEvent, FALSE); 108 109 Status = vboxGdcSubmitAsync(uCtl, pvBuffer, cbBuffer, &Event, &IoStatus); 110 if (Status == STATUS_PENDING) 111 { 112 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 113 Status = IoStatus.Status; 114 } 115 116 return Status; 117 } 118 119 /* overwrites the previously set one, can be NULL to clear the event */ 120 NTSTATUS VBoxGdcSetMouseNotifyEvent(PKEVENT pEvent) 121 { 122 if (!VBoxGdcIsInitialized()) 123 { 124 WARN(("Guest Device Communication not initialized")); 125 return STATUS_UNSUCCESSFUL; 126 } 127 128 NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_EVENT, pEvent, sizeof (pEvent)); 129 if (!NT_SUCCESS(Status)) 130 { 131 WARN(("vboxGdcSubmit failed Status(0x%x)", Status)); 132 } 133 return Status; 134 } 135 136 /** 137 * helper function used for system thread creation 138 */ 139 static NTSTATUS vboxCreateSystemThread(PKTHREAD *ppThread, PKSTART_ROUTINE pfnStartRoutine, PVOID pvStartContext) 140 { 141 OBJECT_ATTRIBUTES ObjectAttributes; 142 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL); 143 144 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); 145 146 HANDLE hThread; 147 NTSTATUS Status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)pfnStartRoutine, pvStartContext); 148 Assert(Status == STATUS_SUCCESS); 149 if (Status == STATUS_SUCCESS) 150 { 151 Status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)ppThread, NULL); 152 Assert(Status == STATUS_SUCCESS); 153 ZwClose(hThread); 154 if (Status == STATUS_SUCCESS) 155 { 156 return STATUS_SUCCESS; 157 } 158 159 /* @todo: how would we fail in this case ?*/ 160 } 161 return Status; 162 } 163 164 static VOID vboxMouseEventPollerThread(PVOID pvContext) 165 { 166 PKEVENT apEvents[] = {&g_ctx.MouseEvent, &g_ctx.TerminateEvent}; 167 NTSTATUS Status; 168 while (1) 169 { 170 Status = KeWaitForMultipleObjects(RT_ELEMENTS(apEvents), (PVOID*)apEvents, 171 WaitAny, Executive, KernelMode, FALSE /* BOOLEAN Alertable */, 172 NULL /* PLARGE_INTEGER Timeout */, 173 NULL /* PKWAIT_BLOCK WaitBlockArray */ 174 ); 175 Assert(NT_SUCCESS(Status)); 176 177 if (Status != STATUS_WAIT_0) 178 { 179 /* terminate event */ 180 Assert(Status == STATUS_WAIT_1); 181 break; 182 } 183 184 ULONG InputDataConsumed = 0; 185 PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt); 186 if (pDevExt) 187 { 188 #define VBOXMOUSE_POLLERTAG 'PMBV' 189 Status = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt); 190 if (NT_SUCCESS(Status)) 191 { 192 VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed); 193 IoReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt); 194 } 195 else 196 { 197 WARN(("IoAcquireRemoveLock failed, Status (0x%x)", Status)); 198 } 199 } 200 else 201 { 202 WARN(("no current pDevExt specified")); 203 } 204 } 205 206 PsTerminateSystemThread(STATUS_SUCCESS); 207 } 208 209 static NTSTATUS vboxNewProtInit(PVBOXMOUSE_DEVEXT pCurrentDevExt) 210 { 211 NTSTATUS Status = VBoxGdcInit(); 212 if (NT_SUCCESS(Status)) 213 { 214 KeInitializeSpinLock(&g_ctx.SyncLock); 215 KeInitializeEvent(&g_ctx.TerminateEvent, NotificationEvent, FALSE); 216 KeInitializeEvent(&g_ctx.MouseEvent, SynchronizationEvent, FALSE); 217 218 Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent); 219 if (NT_SUCCESS(Status)) 220 { 221 Status = vboxCreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL); 222 if (NT_SUCCESS(Status)) 223 { 224 g_ctx.pCurrentDevExt = pCurrentDevExt; 225 return STATUS_SUCCESS; 226 } 227 g_ctx.pThread = NULL; 228 NTSTATUS tmpStatus = VBoxGdcSetMouseNotifyEvent(NULL); 229 Assert(NT_SUCCESS(tmpStatus)); 230 } 231 } 232 233 return Status; 234 } 235 236 static BOOLEAN vboxNewProtIsSupported() 237 { 238 return !!g_ctx.pThread; 239 } 240 241 static NTSTATUS vboxNewProtTerm() 242 { 243 KeSetEvent(&g_ctx.TerminateEvent, 0, FALSE); 244 NTSTATUS Status = KeWaitForSingleObject(g_ctx.pThread, Executive, KernelMode, FALSE, NULL); 245 if (!NT_SUCCESS(Status)) 246 { 247 WARN(("KeWaitForSingleObject failed, Status (0x%x)", Status)); 248 return Status; 249 } 250 251 Status = VBoxGdcSetMouseNotifyEvent(NULL); 252 if (!NT_SUCCESS(Status)) 253 { 254 WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status)); 255 return Status; 256 } 257 258 ObDereferenceObject(g_ctx.pThread); 259 g_ctx.pThread = NULL; 260 261 return Status; 262 } 263 264 static NTSTATUS vboxNewProtSetCurrentDevExt(PVBOXMOUSE_DEVEXT pCurrentDevExt) 265 { 266 ASMAtomicWritePtrVoid((void * volatile *)&g_ctx.pCurrentDevExt, pCurrentDevExt); 267 return STATUS_SUCCESS; 268 } 269 270 VOID VBoxDrvNotifyServiceCB(PVBOXMOUSE_DEVEXT pDevExt, PMOUSE_INPUT_DATA InputDataStart, PMOUSE_INPUT_DATA InputDataEnd, PULONG InputDataConsumed) 271 { 272 KIRQL Irql; 273 /* we need to avoid concurrency between the poller thread and our ServiceCB. 274 * this is perhaps not the best way of doing things, but the most easiest to avoid concurrency 275 * and to ensure the pfnServiceCB is invoked at DISPATCH_LEVEL */ 276 KeAcquireSpinLock(&g_ctx.SyncLock, &Irql); 277 if (pDevExt->pSCReq) 278 { 279 int rc = VbglGRPerform(&pDevExt->pSCReq->header); 280 281 if (RT_SUCCESS(rc)) 282 { 283 if (pDevExt->pSCReq->mouseFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE) 284 { 285 PMOUSE_INPUT_DATA pData = InputDataStart; 286 while (pData<InputDataEnd) 287 { 288 pData->LastX = pDevExt->pSCReq->pointerXPos; 289 pData->LastY = pDevExt->pSCReq->pointerYPos; 290 pData->Flags = MOUSE_MOVE_ABSOLUTE; 291 if (vboxNewProtIsSupported()) 292 pData->Flags |= MOUSE_VIRTUAL_DESKTOP; 293 pData++; 294 } 295 296 /* get the last data & cache it */ 297 --pData; 298 g_ctx.LastReportedData.UnitId = pData->UnitId; 299 } 300 } 301 else 302 { 303 WARN(("VbglGRPerform failed with rc=%#x", rc)); 304 } 305 } 306 307 /* Call original callback */ 308 pDevExt->OriginalConnectData.pfnServiceCB(pDevExt->OriginalConnectData.pDO, 309 InputDataStart, InputDataEnd, InputDataConsumed); 310 KeReleaseSpinLock(&g_ctx.SyncLock, Irql); 311 } 32 312 33 313 static BOOLEAN vboxIsVBGLInited(void) … … 73 353 WARN(("VBGL init failed with rc=%#x", rc)); 74 354 } 355 356 vboxNewProtInit(pDevExt); 75 357 } 76 358 } … … 172 454 { 173 455 req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 456 if (vboxNewProtIsSupported()) 457 req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL; 458 174 459 req->pointerXPos = 0; 175 460 req->pointerYPos = 0; … … 260 545 if (callCnt == 0) 261 546 { 547 vboxNewProtTerm(); 548 262 549 if (vboxIsVBGLInited()) 263 550 { -
trunk/src/VBox/Additions/WINNT/Mouse/common/VBoxMouseLog.h
r37163 r37221 19 19 #ifndef VBOXMOUSELOG_H 20 20 #define VBOXMOUSELOG_H 21 22 #ifdef DEBUG_misha 23 #include <iprt/assert.h> 24 #endif 21 25 22 26 #define VBOX_MOUSE_LOG_NAME "VBoxMouse" … … 44 48 } while (0) 45 49 50 #ifdef DEBUG_misha 51 # define BREAK_WARN() AssertFailed() 52 #else 53 # define BREAK_WARN() do {} while(0) 54 #endif 55 46 56 #define WARN(_a) \ 47 57 do \ … … 50 60 Log(_a); \ 51 61 Log((VBOX_MOUSE_LOG_SUFFIX_FMT VBOX_MOUSE_LOG_SUFFIX_PARMS)); \ 62 BREAK_WARN(); \ 52 63 } while (0) 53 64
Note:
See TracChangeset
for help on using the changeset viewer.