Changeset 37226 in vbox for trunk/src/VBox/Additions/WINNT
- Timestamp:
- May 26, 2011 5:06:02 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Mouse/NT5/VBoxMFInternal.cpp
r37225 r37226 38 38 VBOXGDC Gdc; 39 39 KSPIN_LOCK SyncLock; 40 KEVENT TerminateEvent;41 KEVENT MouseEvent;42 PKTHREAD pThread;43 40 volatile PVBOXMOUSE_DEVEXT pCurrentDevExt; 44 41 LIST_ENTRY DevExtList; 45 volatile boolfIsNewProtEnabled;42 BOOLEAN fIsNewProtEnabled; 46 43 MOUSE_INPUT_DATA LastReportedData; 47 44 } VBoxGlobalContext; … … 119 116 } 120 117 121 /* overwrites the previously set one, can be NULL to clear the event */ 122 NTSTATUS VBoxGdcSetMouseNotifyEvent(PKEVENT pEvent) 123 { 124 if (!VBoxGdcIsInitialized()) 125 { 126 WARN(("Guest Device Communication not initialized")); 127 return STATUS_UNSUCCESSFUL; 128 } 129 130 NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_EVENT, pEvent, sizeof (pEvent)); 118 static DECLCALLBACK(void) vboxNewProtMouseEventCb(void *pvContext) 119 { 120 PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt); 121 if (pDevExt) 122 { 123 #define VBOXMOUSE_POLLERTAG 'PMBV' 124 NTSTATUS Status = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt); 125 if (NT_SUCCESS(Status)) 126 { 127 ULONG InputDataConsumed = 0; 128 VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed); 129 IoReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt); 130 } 131 else 132 { 133 WARN(("IoAcquireRemoveLock failed, Status (0x%x)", Status)); 134 } 135 } 136 else 137 { 138 WARN(("no current pDevExt specified")); 139 } 140 } 141 142 static BOOLEAN vboxNewProtIsEnabled() 143 { 144 return g_ctx.fIsNewProtEnabled; 145 } 146 147 static NTSTATUS vboxNewProtRegisterMouseEventCb(BOOLEAN fRegister) 148 { 149 VBoxGuestMouseSetNotifyCallback CbInfo = {}; 150 CbInfo.pfnNotify = fRegister ? vboxNewProtMouseEventCb : NULL; 151 152 NTSTATUS Status = vboxGdcSubmit(VBOXGUEST_IOCTL_INTERNAL_SET_MOUSE_NOTIFY_CALLBACK, &CbInfo, sizeof (CbInfo)); 131 153 if (!NT_SUCCESS(Status)) 132 154 { … … 136 158 } 137 159 138 /**139 * helper function used for system thread creation140 */141 static NTSTATUS vboxCreateSystemThread(PKTHREAD *ppThread, PKSTART_ROUTINE pfnStartRoutine, PVOID pvStartContext)142 {143 OBJECT_ATTRIBUTES ObjectAttributes;144 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);145 146 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);147 148 HANDLE hThread;149 NTSTATUS Status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &ObjectAttributes, NULL, NULL, (PKSTART_ROUTINE)pfnStartRoutine, pvStartContext);150 Assert(Status == STATUS_SUCCESS);151 if (Status == STATUS_SUCCESS)152 {153 Status = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)ppThread, NULL);154 Assert(Status == STATUS_SUCCESS);155 ZwClose(hThread);156 if (Status == STATUS_SUCCESS)157 {158 return STATUS_SUCCESS;159 }160 161 /* @todo: how would we fail in this case ?*/162 }163 return Status;164 }165 166 static VOID vboxMouseEventPollerThread(PVOID pvContext)167 {168 PKEVENT apEvents[] = {&g_ctx.MouseEvent, &g_ctx.TerminateEvent};169 NTSTATUS Status;170 while (1)171 {172 Status = KeWaitForMultipleObjects(RT_ELEMENTS(apEvents), (PVOID*)apEvents,173 WaitAny, Executive, KernelMode, FALSE /* BOOLEAN Alertable */,174 NULL /* PLARGE_INTEGER Timeout */,175 NULL /* PKWAIT_BLOCK WaitBlockArray */176 );177 Assert(NT_SUCCESS(Status));178 179 if (Status != STATUS_WAIT_0)180 {181 /* terminate event */182 Assert(Status == STATUS_WAIT_1);183 break;184 }185 186 ULONG InputDataConsumed = 0;187 PVBOXMOUSE_DEVEXT pDevExt = (PVBOXMOUSE_DEVEXT)ASMAtomicUoReadPtr((void * volatile *)&g_ctx.pCurrentDevExt);188 if (pDevExt)189 {190 #define VBOXMOUSE_POLLERTAG 'PMBV'191 Status = IoAcquireRemoveLock(&pDevExt->RemoveLock, pDevExt);192 if (NT_SUCCESS(Status))193 {194 VBoxDrvNotifyServiceCB(pDevExt, &g_ctx.LastReportedData, &g_ctx.LastReportedData + 1, &InputDataConsumed);195 IoReleaseRemoveLock(&pDevExt->RemoveLock, pDevExt);196 }197 else198 {199 WARN(("IoAcquireRemoveLock failed, Status (0x%x)", Status));200 }201 }202 else203 {204 WARN(("no current pDevExt specified"));205 }206 }207 208 PsTerminateSystemThread(STATUS_SUCCESS);209 }210 211 static BOOLEAN vboxNewProtIsInitialized()212 {213 return !!g_ctx.pThread;214 }215 216 static BOOLEAN vboxNewProtIsStarted()217 {218 return (BOOLEAN)ASMAtomicReadBool(&g_ctx.fIsNewProtEnabled);219 }220 160 221 161 NTSTATUS VBoxNewProtInit() … … 225 165 { 226 166 KeInitializeSpinLock(&g_ctx.SyncLock); 227 KeInitializeEvent(&g_ctx.TerminateEvent, NotificationEvent, FALSE);228 KeInitializeEvent(&g_ctx.MouseEvent, SynchronizationEvent, FALSE);229 167 InitializeListHead(&g_ctx.DevExtList); 230 168 /* we assume the new prot data in g_ctx is zero-initialized (see g_ctx definition) */ 231 169 232 Status = vbox CreateSystemThread(&g_ctx.pThread, vboxMouseEventPollerThread, NULL);170 Status = vboxNewProtRegisterMouseEventCb(TRUE); 233 171 if (NT_SUCCESS(Status)) 234 172 { 173 g_ctx.fIsNewProtEnabled = TRUE; 235 174 return STATUS_SUCCESS; 236 175 } 237 g_ctx.pThread = NULL;176 VBoxGdcTerm(); 238 177 } 239 178 … … 244 183 { 245 184 Assert(IsListEmpty(&g_ctx.DevExtList)); 246 Assert(!vboxNewProtIsStarted()); 247 if (!vboxNewProtIsInitialized()) 185 if (!vboxNewProtIsEnabled()) 186 { 187 WARN(("New Protocol is disabled")); 248 188 return STATUS_SUCCESS; 249 250 KeSetEvent(&g_ctx.TerminateEvent, 0, FALSE); 251 NTSTATUS Status = KeWaitForSingleObject(g_ctx.pThread, Executive, KernelMode, FALSE, NULL); 189 } 190 191 g_ctx.fIsNewProtEnabled = FALSE; 192 193 NTSTATUS Status = vboxNewProtRegisterMouseEventCb(FALSE); 252 194 if (!NT_SUCCESS(Status)) 253 195 { … … 256 198 } 257 199 258 ObDereferenceObject(g_ctx.pThread); 259 g_ctx.pThread = NULL; 260 261 return Status; 200 VBoxGdcTerm(); 201 202 return STATUS_SUCCESS; 262 203 } 263 204 264 205 static NTSTATUS vboxNewProtDeviceAdded(PVBOXMOUSE_DEVEXT pDevExt) 265 206 { 266 if (!vboxNewProtIsInitialized()) 207 if (!vboxNewProtIsEnabled()) 208 { 209 WARN(("New Protocol is disabled")); 267 210 return STATUS_UNSUCCESSFUL; 211 } 268 212 269 213 NTSTATUS Status = STATUS_SUCCESS; 270 214 KIRQL Irql; 271 BOOLEAN fDoEventRegister = FALSE;272 215 KeAcquireSpinLock(&g_ctx.SyncLock, &Irql); 273 216 InsertHeadList(&g_ctx.DevExtList, &pDevExt->ListEntry); … … 277 220 /* ensure the object is not deleted while it is being used by a poller thread */ 278 221 ObReferenceObject(pDevExt->pdoSelf); 279 fDoEventRegister = TRUE;280 222 } 281 223 KeReleaseSpinLock(&g_ctx.SyncLock, Irql); 282 224 283 if (fDoEventRegister)284 {285 /* to ensure we do not concur with vboxNewProtDeviceRemoved cleaning the event,286 * do it in a loop until the cauuent state of fIsNewProtEnabled is false,287 * setting one and the same event multiple times will not hutr */288 do289 {290 Status = VBoxGdcSetMouseNotifyEvent(&g_ctx.MouseEvent);291 if (!NT_SUCCESS(Status))292 {293 WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));294 break;295 }296 } while (ASMAtomicCmpXchgBool(&g_ctx.fIsNewProtEnabled, true, false));297 298 if (NT_SUCCESS(Status))299 {300 /* signal the event to ensure we did not miss anything */301 KeSetEvent(&g_ctx.MouseEvent, 0, FALSE);302 Status = STATUS_SUCCESS;303 }304 }305 #ifdef DEBUG_misha306 else307 {308 Assert(g_ctx.fIsNewProtEnabled);309 }310 #endif311 312 225 return Status; 313 226 } … … 317 230 static NTSTATUS vboxNewProtDeviceRemoved(PVBOXMOUSE_DEVEXT pDevExt) 318 231 { 319 if (!vboxNewProtIsInitialized()) 232 if (!vboxNewProtIsEnabled()) 233 { 234 WARN(("New Protocol is disabled")); 320 235 return STATUS_UNSUCCESSFUL; 236 } 321 237 322 238 KIRQL Irql; 323 239 NTSTATUS Status = STATUS_SUCCESS; 324 BOOLEAN fDoEventUnregister = FALSE;325 240 KeAcquireSpinLock(&g_ctx.SyncLock, &Irql); 326 241 RemoveEntryList(&pDevExt->ListEntry); … … 339 254 } 340 255 341 fDoEventUnregister = IsListEmpty(&g_ctx.DevExtList);342 256 KeReleaseSpinLock(&g_ctx.SyncLock, Irql); 343 344 if (fDoEventUnregister)345 {346 if (vboxNewProtIsStarted())347 {348 Status = VBoxGdcSetMouseNotifyEvent(NULL);349 if (!NT_SUCCESS(Status))350 {351 WARN(("VBoxGdcSetMouseNotifyEvent failed, Status (0x%x)", Status));352 }353 354 ASMAtomicWriteBool(&g_ctx.fIsNewProtEnabled, false);355 }356 }357 257 358 258 return Status; … … 380 280 pData->LastY = pDevExt->pSCReq->pointerYPos; 381 281 pData->Flags = MOUSE_MOVE_ABSOLUTE; 382 if (vboxNewProtIs Started())282 if (vboxNewProtIsEnabled()) 383 283 pData->Flags |= MOUSE_VIRTUAL_DESKTOP; 384 284 pData++; … … 545 445 { 546 446 req->mouseFeatures = VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 547 if (vboxNewProtIs Started())447 if (vboxNewProtIsEnabled()) 548 448 req->mouseFeatures |= VMMDEV_MOUSE_NEW_PROTOCOL; 549 449
Note:
See TracChangeset
for help on using the changeset viewer.