VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxMMR/tsmfhook.cpp@ 51287

Last change on this file since 51287 was 46593, checked in by vboxsync, 12 years ago

updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.9 KB
Line 
1/* $Id: tsmfhook.cpp 46593 2013-06-17 14:32:51Z vboxsync $ */
2/** @file
3 * VBoxMMR - Multimedia Redirection
4 */
5
6/*
7 * Copyright (C) 2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "stdafx.h"
19#include "tsmfhook.h"
20#include "tsmf.h"
21#include "logging.h"
22
23#include <DbgHelp.h>
24
25#include <stdio.h>
26#include <mfidl.h>
27#include <WtsApi32.h>
28
29#include <iprt/thread.h>
30#include <VBox/VBoxGuestLib.h>
31#include <VBox/VBoxGuest.h>
32#include <VBox/HostServices/VBoxHostChannel.h>
33
34#define CODECAVE_SIZE 0x64
35
36/* Generic byte code for API calls redirection.
37 * It corresponds to the following set of instructions:
38 * push ebp
39 * mov ebp, esp
40 * pop ebp
41 * mov eax, 0DEADBEEFh
42 * jmp eax
43 */
44static const char g_szCodeCave[] = "\x55\x8B\xEC\x5D\xB8\xEF\xBE\xAD\xDE\xFF\xE0";
45
46const WCHAR *g_pwszMMRFlags = L"VBoxMMR";
47
48const WCHAR *g_pwszMMRAdditions =
49 L"SOFTWARE\\Oracle\\VirtualBox Guest Additions";
50
51const char *g_pszVRDETSMF = "/vrde/tsmf";
52
53const DWORD g_dwMMRCodeCavingEnabled = 0x00000002;
54
55BOOL g_bMMRCodeCavingIsEnabled = TRUE;
56
57BOOL MMRCodeCavingIsEnabled()
58{
59 LONG lResult;
60 HKEY hKey;
61 DWORD dwType = 0;
62 DWORD dwValue = 0;
63 DWORD dwSize = sizeof(dwValue);
64
65 BOOL fEnabled = TRUE;
66
67 lResult = RegOpenKeyExW(
68 HKEY_LOCAL_MACHINE, g_pwszMMRAdditions, 0, KEY_QUERY_VALUE, &hKey);
69
70 if (lResult == ERROR_SUCCESS)
71 {
72 lResult = RegQueryValueExW(
73 hKey, g_pwszMMRFlags, NULL, &dwType, (BYTE *) &dwValue, &dwSize);
74
75 RegCloseKey(hKey);
76
77 if (lResult == ERROR_SUCCESS &&
78 dwSize == sizeof(dwValue) &&
79 dwType == REG_DWORD)
80 {
81 fEnabled = g_dwMMRCodeCavingEnabled & dwValue;
82 VBoxMMRHookLog("VBoxMMR: Registry setting: %d\n", dwValue);
83 }
84 }
85
86 return fEnabled;
87}
88
89/* Events, which are specific for the tsmf channel. */
90#define VBOX_TSMF_HCH_CREATE_ACCEPTED (VBOX_HOST_CHANNEL_EVENT_USER + 0)
91#define VBOX_TSMF_HCH_CREATE_DECLINED (VBOX_HOST_CHANNEL_EVENT_USER + 1)
92#define VBOX_TSMF_HCH_DISCONNECTED (VBOX_HOST_CHANNEL_EVENT_USER + 2)
93
94RTTHREAD hDetachMonitor = NIL_RTTHREAD;
95uint32_t nUserData = 1;
96
97HANDLE ghVBoxDriver = NULL;
98
99using std::map;
100using std::list;
101using std::queue;
102
103extern bool isWMP;
104
105CRITICAL_SECTION CreateLock;
106HANDLE hCreateEvent;
107uint32_t g_nCreateResult = VBOX_TSMF_HCH_CREATE_DECLINED;
108
109TRACEHANDLE g_hTraceSession = NULL;
110
111struct HookEntry
112{
113 LPCSTR DllName;
114 LPCSTR FunctionName;
115 PVOID HookFuncAddr;
116 PVOID *OrigFuncAddrPtr;
117 PVOID *MMRFuncAddrPtr;
118};
119
120
121struct HostChannelCtx
122{
123 RTTHREAD thread;
124 bool fShutdown;
125 uint32_t u32HGCMClientId;
126 uint8_t au8EventData[4];
127};
128
129HostChannelCtx g_HostChannelCtx = {0};
130
131struct ReadReq
132{
133 PBYTE Buffer;
134 LPOVERLAPPED_COMPLETION_ROUTINE Func;
135 LPOVERLAPPED lpOverlapped;
136 HANDLE hThread;
137 DWORD cbRead;
138 DWORD ErrorCode;
139};
140
141
142VOID CALLBACK APCProc(ULONG_PTR dwParam)
143{
144 ReadReq *pReq = (ReadReq *) dwParam;
145
146 if (NULL != g_hTraceSession)
147 {
148 /* Size FieldTypeFlags */
149 TraceEventData Event; // = { { sizeof(Event), (USHORT) 0, }, h };
150
151 ZeroMemory(&Event, sizeof(Event));
152 Event.Header.Size = sizeof(Event.Header) + sizeof(Event.ReadEnd);
153 Event.Header.Class.Type = EVENT_TRACE_TYPE_DC_END;
154 Event.Header.Class.Version = 0;
155 Event.Header.Class.Level = TRACE_LEVEL_INFORMATION;
156 Event.Header.Flags = WNODE_FLAG_TRACED_GUID;
157 Event.Header.Guid = ChannelReadCategoryId;
158 Event.ReadEnd.ErrorCode = pReq->ErrorCode;
159
160 if (0 == pReq->ErrorCode)
161 {
162 DWORD cbToTrace = min(((PCHANNEL_PDU_HEADER) pReq->Buffer)->length, sizeof(Event.ReadEnd.Data));
163 CopyMemory(Event.ReadEnd.Data, pReq->Buffer, cbToTrace);
164 }
165 else
166 Event.Header.Size -= sizeof(Event.ReadEnd.Data);
167
168
169 TraceEvent(g_hTraceSession, &Event.Header);
170 }
171
172 pReq->Func(pReq->ErrorCode, pReq->cbRead, pReq->lpOverlapped);
173 CloseHandle(pReq->hThread);
174 delete pReq;
175}
176
177class VBOX_RDP_CHANNEL
178{
179 static list<HANDLE> ChannelList;
180 static map<DWORD, HANDLE> ChannelMap;
181
182 DWORD m_Id;
183 CRITICAL_SECTION m_Lock;
184 queue<PBYTE> m_BufferList;
185 queue<ReadReq *> m_ReqList;
186
187 // we need to ignore the first write operation(s), as they are handled by VRDP for us
188 // we probably don't want this in the final solution.
189 DWORD m_nWriteOps;
190
191protected:
192
193 void DoCompleteRead(PBYTE pBuffer, ReadReq *pReq)
194 {
195 uint32_t u32DataSize = *((uint32_t *) pBuffer);
196
197 // FIXME : we really want the VBox RDP server to preserve these for us
198 PCHANNEL_PDU_HEADER pPduHdr = (PCHANNEL_PDU_HEADER) pReq->Buffer;
199
200 pPduHdr->length = u32DataSize;
201 pPduHdr->flags = CHANNEL_FLAG_ONLY;
202
203 CopyMemory(++pPduHdr, pBuffer + sizeof(u32DataSize), u32DataSize);
204
205 pReq->cbRead = u32DataSize + sizeof(CHANNEL_PDU_HEADER);
206 pReq->ErrorCode = ERROR_SUCCESS;
207
208 delete [] pBuffer;
209
210 QueueUserAPC(APCProc, pReq->hThread, (ULONG_PTR) pReq);
211 }
212
213public:
214 VBOX_RDP_CHANNEL(DWORD Id) : m_Id(Id), m_nWriteOps(0)
215 {
216 ChannelList.push_back(this);
217 ChannelMap[Id] = this;
218
219 InitializeCriticalSection(&m_Lock);
220 };
221
222 ~VBOX_RDP_CHANNEL()
223 {
224 DeleteCriticalSection(&m_Lock);
225
226 ChannelMap.erase(m_Id);
227 ChannelList.remove(this);
228
229 while (!m_ReqList.empty())
230 {
231 ReadReq *req = m_ReqList.front();
232
233 req->cbRead = 0;
234 req->ErrorCode = ERROR_BROKEN_PIPE;
235
236 QueueUserAPC(APCProc, req->hThread, (ULONG_PTR) req);
237
238 m_ReqList.pop();
239 }
240 }
241
242
243 void PushRequest(PBYTE Buffer, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionFunc)
244 {
245 ReadReq *req = new ReadReq;
246
247 req->Buffer = Buffer;
248 req->Func = lpCompletionFunc;
249 req->lpOverlapped = lpOverlapped;
250
251 // the pseudo handle returned by GetCurrentTHread() can not be used with QueueUserAPC()
252 BOOL b = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
253 GetCurrentProcess(), &req->hThread,
254 THREAD_SET_CONTEXT, FALSE, 0);
255
256 EnterCriticalSection(&m_Lock);
257
258 if (!m_BufferList.empty())
259 {
260 PBYTE pBuffer = m_BufferList.front();
261 DoCompleteRead(pBuffer, req);
262 m_BufferList.pop();
263 }
264 else
265 {
266 m_ReqList.push(req);
267 }
268
269 LeaveCriticalSection(&m_Lock);
270 }
271
272 void PushBuffer(PBYTE pBuffer)
273 {
274 EnterCriticalSection(&m_Lock);
275
276 if (!m_ReqList.empty())
277 {
278 ReadReq *req = m_ReqList.front();
279 DoCompleteRead(pBuffer, req);
280
281 m_ReqList.pop();
282 }
283 else
284 {
285 m_BufferList.push(pBuffer);
286 }
287
288 LeaveCriticalSection(&m_Lock);
289 }
290
291 static bool IsInstance(HANDLE hObject)
292 {
293 for (list<HANDLE>::iterator iter = ChannelList.begin(); iter != ChannelList.end(); ++iter)
294 {
295 if (hObject == *iter)
296 return true;
297 }
298
299 return false;
300 }
301
302 static uint32_t ChannelCount()
303 {
304 return ChannelList.size();
305 }
306
307 DWORD GetId() { return m_Id; }
308
309 static VBOX_RDP_CHANNEL * GetFromId(DWORD Id)
310 {
311 map<DWORD, HANDLE>::iterator iter = ChannelMap.find(Id);
312 if (iter != ChannelMap.end())
313 return (VBOX_RDP_CHANNEL *) iter->second;
314
315 return NULL;
316 }
317
318#ifdef TRACE
319
320 void RequestWritten(const DWORD *pSharedHdr)
321 {
322 // avoid filling up the map too much
323 if (pSharedHdr[2] != 0x100 && pSharedHdr[2] != 0x101 && pSharedHdr[2] != 0x106 && pSharedHdr[2] != 0x107 && pSharedHdr[2] != 0x108)
324 return;
325
326 LARGE_INTEGER li;
327 li.HighPart = (pSharedHdr[0] & 0x3FFFFFFF);
328 li.LowPart = pSharedHdr[1];
329
330 m_ServerReqMap[li.QuadPart] = pSharedHdr[2];
331 }
332
333#endif
334};
335
336list<HANDLE> VBOX_RDP_CHANNEL::ChannelList;
337map<DWORD, HANDLE> VBOX_RDP_CHANNEL::ChannelMap;
338
339const IMAGE_IMPORT_DESCRIPTOR * GetImportDescriptor(HMODULE hMod)
340{
341 const PBYTE pBaseAddr = (PBYTE) hMod;
342
343 const IMAGE_DOS_HEADER *pDosHdr = (IMAGE_DOS_HEADER *) pBaseAddr;
344 const size_t nOptHdrOffset = pDosHdr->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER);
345
346 const IMAGE_OPTIONAL_HEADER *pOptHdr = (IMAGE_OPTIONAL_HEADER *) (pBaseAddr + nOptHdrOffset);
347 const size_t nImportDescOffset = pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
348
349 return (IMAGE_IMPORT_DESCRIPTOR *) (pBaseAddr + nImportDescOffset);
350}
351
352DWORD ReadLoadedImage(LPCVOID pBaseAddr)
353{
354 DWORD nCCAddress = 0;
355 PIMAGE_SECTION_HEADER pTextSectionHdr = 0;
356
357 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)pBaseAddr;
358
359 PIMAGE_NT_HEADERS32 pNtFileHdr = (PIMAGE_NT_HEADERS32)((DWORD)pBaseAddr + pDosHdr->e_lfanew);
360
361 DWORD nNumberOfSections = pNtFileHdr->FileHeader.NumberOfSections;
362
363 PIMAGE_SECTION_HEADER pSectionsHdr = (PIMAGE_SECTION_HEADER)((DWORD)pBaseAddr + pDosHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS32));
364
365
366 for (DWORD i = 0; i < nNumberOfSections; i++)
367 {
368 PIMAGE_SECTION_HEADER pSectionHdr = &pSectionsHdr[i];
369
370 if (!_stricmp((char*)pSectionHdr->Name, ".text"))
371 {
372 pTextSectionHdr = pSectionHdr;
373 break;
374 }
375 }
376
377 if(0 != pTextSectionHdr)
378 {
379 nCCAddress = (DWORD)pBaseAddr + pTextSectionHdr->VirtualAddress + pTextSectionHdr->SizeOfRawData;
380 }
381
382 return nCCAddress;
383}
384
385
386bool ReplaceStubAddr(BYTE* pBuffer,DWORD nBufferSize,DWORD nOld,DWORD nNew)
387{
388 if ( 0 != nNew )
389 {
390 for (DWORD i = 0; i < nBufferSize - sizeof(DWORD); i++)
391 {
392 if (*(PDWORD)(pBuffer + i) == nOld)
393 {
394 memcpy(pBuffer + i, &nNew, sizeof(DWORD));
395 return true;
396 }
397 }
398 }
399
400 return false;
401}
402
403void InstallHook(IMAGE_THUNK_DATA *pIATEntry, HookEntry pEntry,const PBYTE pBaseAddr)
404{
405 SIZE_T cbWritten;
406 static map<DWORD, DWORD> CCAddrHistoryMap;
407
408 PVOID pfnHook = pEntry.HookFuncAddr;
409 PVOID *ppfnOrig = pEntry.OrigFuncAddrPtr;
410 PVOID *ppfnMMR = pEntry.MMRFuncAddrPtr;
411 LPCSTR FunctionName = pEntry.FunctionName;
412
413 unsigned int nCCOffSet = sizeof(g_szCodeCave);
414
415 if (NULL == *ppfnOrig)
416 {
417 WriteProcessMemory(GetCurrentProcess(), ppfnOrig, &pIATEntry->u1.Function, 4, &cbWritten);
418 }
419
420 if(g_bMMRCodeCavingIsEnabled)
421 {
422 DWORD nCodeCaveAddr = ReadLoadedImage(pBaseAddr);
423
424 if (!nCodeCaveAddr)
425 {
426 /* If fails perform the hooking without code caving */
427 VBoxMMRHookLog("VBoxMMR: Retrieving code cave location had failed\n");
428 WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &pfnHook, 4, (SIZE_T *) &cbWritten);
429 return;
430 }
431
432 nCodeCaveAddr = nCodeCaveAddr - CODECAVE_SIZE;
433
434 BYTE pByteCodeBuffer[CODECAVE_SIZE] = {0};
435
436 memcpy(pByteCodeBuffer, g_szCodeCave, CODECAVE_SIZE);
437
438 map<DWORD, DWORD>::iterator iter = CCAddrHistoryMap.find(nCodeCaveAddr);
439 if (iter != CCAddrHistoryMap.end())
440 {
441 nCodeCaveAddr += CCAddrHistoryMap[nCodeCaveAddr] ;
442 iter->second += nCCOffSet;
443
444 }else{
445
446 CCAddrHistoryMap[nCodeCaveAddr] = nCCOffSet;
447 }
448
449 bool bResult = ReplaceStubAddr( pByteCodeBuffer,
450 CODECAVE_SIZE,
451 0xDEADBEEF,
452 (DWORD)ppfnMMR);
453
454 if (!bResult)
455 {
456 /* If fails perform the hooking without code caving */
457 VBoxMMRHookLog("VBoxMMR: Replacing code cave stub address failed\n");
458 WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &pfnHook, 4, (SIZE_T *) &cbWritten);
459 return ;
460 }
461
462 bResult = WriteProcessMemory( GetCurrentProcess(),
463 (LPVOID)nCodeCaveAddr,
464 pByteCodeBuffer,
465 sizeof(g_szCodeCave),
466 0 );
467
468 if (!bResult)
469 {
470 /* If fails perform the hooking without code caving*/
471 VBoxMMRHookLog("VBoxMMR: Writing byte code to the text section failed\n");
472 WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &pfnHook, 4, (SIZE_T *) &cbWritten);
473 return;
474 }
475
476 bResult = WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &nCodeCaveAddr, 4, &cbWritten);
477
478 if (!bResult)
479 {
480 VBoxMMRHookLog("VBoXMMR: Patching the IAT failed\n");
481 WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &pfnHook, 4, (SIZE_T *) &cbWritten);
482 return;
483 }
484 }else
485 {
486 WriteProcessMemory(GetCurrentProcess(), &pIATEntry->u1.Function, &pfnHook, 4, (SIZE_T *) &cbWritten);
487 }
488}
489
490void InstallHooks(const IMAGE_IMPORT_DESCRIPTOR *pDescriptor, const PBYTE pBaseAddr, HookEntry *pEntries)
491{
492 DWORD nCodeCaveOffSet= 0;
493 while(pDescriptor->FirstThunk)
494 {
495 LPCSTR pszDllName = (LPCSTR) (pBaseAddr + pDescriptor->Name);
496
497 const IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*) (pBaseAddr + pDescriptor->OriginalFirstThunk);
498 IMAGE_THUNK_DATA *pIATEntry = (IMAGE_THUNK_DATA *)(pBaseAddr + pDescriptor->FirstThunk);
499 LPCSTR pszModuleName = (LPCSTR) (pBaseAddr + pDescriptor->Name);
500
501 while (pThunk->u1.Function)
502 {
503 for (int nIndex = 0; NULL != pEntries[nIndex].DllName; ++nIndex)
504 {
505 if (0 == _stricmp(pszDllName, pEntries[nIndex].DllName))
506 {
507 if (0 == (pThunk->u1.AddressOfData & IMAGE_ORDINAL_FLAG))
508 {
509 IMAGE_IMPORT_BY_NAME *pImport = (IMAGE_IMPORT_BY_NAME *) (pBaseAddr + pThunk->u1.AddressOfData);
510
511 if (0 == strcmp((LPCSTR) pImport->Name, pEntries[nIndex].FunctionName))
512 {
513 VBoxMMRHookLog("VBoxMMR: Install Hook for dll %s function %s \n",
514 pEntries[nIndex].DllName, pEntries[nIndex].FunctionName);
515
516 InstallHook(pIATEntry,
517 pEntries[nIndex],
518 pBaseAddr);
519 }
520 }
521 }
522 }
523 ++pThunk; ++pIATEntry;
524 }
525 ++pDescriptor;
526 }
527}
528
529int StartMonitor(RTTHREAD *hMonitor, PFNRTTHREAD pMonitorFn,
530 void *pData, size_t cbStack, RTTHREADTYPE enmType,
531 uint32_t flags, const char *pszName)
532{
533 int rc;
534
535 rc = RTThreadCreate(hMonitor, pMonitorFn, pData,
536 cbStack, enmType, flags, pszName);
537
538 if (RT_FAILURE(rc))
539 {
540 VBoxMMRHookLog("VBoxMMR: Error starting monitor %s: %d\n", pszName, rc);
541 }
542
543 return rc;
544}
545
546int StopMonitor(RTTHREAD *hMonitor, const char* pszName)
547{
548 int rc;
549
550 if (*hMonitor != NIL_RTTHREAD)
551 {
552 rc = RTThreadUserSignal(*hMonitor);
553
554 if (RT_SUCCESS(rc))
555 {
556 // rc = RTThreadWait(*hMonitor, RT_INDEFINITE_WAIT, NULL);
557
558 if (RT_FAILURE(rc))
559 {
560 VBoxMMRHookLog("VBoxMMR: Error waiting for monitor %s to stop: %d\n", pszName, rc);
561 }
562 }
563 else
564 {
565 VBoxMMRHookLog("VBoxMMR: Error sending stop signal to monitor %s: %d\n", pszName, rc);
566 }
567
568 *hMonitor = NIL_RTTHREAD;
569 }
570
571
572 return rc;
573}
574
575DECLCALLBACK(int)
576MonitorDetach(RTTHREAD hThreadSelf, void *pvUser)
577{
578 VBoxGuestFilterMaskInfo maskInfo;
579 DWORD cbReturned;
580 bool bPrevious = FALSE;
581 bool bCurrent = bPrevious;
582
583 maskInfo.u32OrMask = VMMDEV_EVENT_VRDP;
584 maskInfo.u32NotMask = 0;
585
586 VBoxMMRHookLog("VBoxMMR: MonitorDetach starting\n");
587
588 if (DeviceIoControl (ghVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
589 {
590 VBoxMMRHookLog("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask - or) succeeded\n");
591 }
592 else
593 {
594 VBoxMMRHookLog("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask) failed\n");
595 return 0;
596 }
597
598 for(;;)
599 {
600 /* Call the host to get VRDP status and the experience level. */
601 VMMDevVRDPChangeRequest vrdpChangeRequest = {0};
602
603 vrdpChangeRequest.header.size = sizeof(VMMDevVRDPChangeRequest);
604 vrdpChangeRequest.header.version = VMMDEV_REQUEST_HEADER_VERSION;
605 vrdpChangeRequest.header.requestType = VMMDevReq_GetVRDPChangeRequest;
606 vrdpChangeRequest.u8VRDPActive = 0;
607 vrdpChangeRequest.u32VRDPExperienceLevel = 0;
608
609 if (DeviceIoControl (ghVBoxDriver,
610 VBOXGUEST_IOCTL_VMMREQUEST(sizeof(VMMDevVRDPChangeRequest)),
611 &vrdpChangeRequest,
612 sizeof(VMMDevVRDPChangeRequest),
613 &vrdpChangeRequest,
614 sizeof(VMMDevVRDPChangeRequest),
615 &cbReturned, NULL))
616 {
617 bCurrent = ( vrdpChangeRequest.u8VRDPActive == 1) ? TRUE : FALSE;
618
619 if (bCurrent != bPrevious)
620 {
621 VBoxMMRHookLog(
622 "VBoxMMR: VRDP active status changed: %d\n",
623 vrdpChangeRequest.u8VRDPActive);
624
625 if (bCurrent == FALSE &&
626 VBOX_RDP_CHANNEL::ChannelCount() > 0)
627 {
628 VBoxMMRHookLog("VBoxMMR: exiting ...\n");
629 ExitProcess(0);
630 break;
631 }
632 }
633
634 bPrevious = bCurrent;
635 }
636 else
637 {
638 VBoxMMRHookLog("VBoxMMR: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n");
639
640 }
641
642 if (RTThreadUserWait(hThreadSelf, 1000) == VINF_SUCCESS)
643 {
644 VBoxMMRHookLog("VBoxMMR: detach monitor received stop signal\n");
645 break;
646 }
647 }
648
649 VBoxMMRHookLog("VBoxMMR: MonitorDetach stopping\n");
650
651 return VINF_SUCCESS;
652}
653
654/*
655 * WTSQuerySessionInformationW
656 */
657
658BOOL (WINAPI * g_pfnWTSQuerySessionInformation)(HANDLE, DWORD, WTS_INFO_CLASS, LPWSTR *, DWORD *) = NULL;
659BOOL WINAPI MMRWTSQuerySessionInformation(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR *ppBuffer, DWORD *pBytesReturned)
660{
661 BOOL b = g_pfnWTSQuerySessionInformation(hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned);
662
663 if (WTSIsRemoteSession == WTSInfoClass)
664 {
665 PBYTE pb = (PBYTE) *ppBuffer;
666 *pb = 1;
667 return b;
668 }
669 else if (WTSClientProtocolType == WTSInfoClass)
670 {
671 PUSHORT pus = (PUSHORT) *ppBuffer;
672 *pus = 2;
673 return b;
674 }
675
676 return b;
677}
678
679BOOL WINAPI LocalWTSQuerySessionInformation(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPWSTR *ppBuffer, DWORD *pBytesReturned)
680{
681 return MMRWTSQuerySessionInformation( hServer, SessionId, WTSInfoClass, ppBuffer, pBytesReturned);
682}
683
684
685/*
686 * WriteFile
687 */
688
689BOOL (WINAPI *g_pfnWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED) = NULL;
690
691BOOL WINAPI MMRWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
692{
693 BOOL b = TRUE;
694
695 if (NULL != g_hTraceSession)
696 {
697 /* Size FieldTypeFlags */
698 TraceEventData Event; // = { { sizeof(Event), (USHORT) 0, }, h };
699
700 ZeroMemory(&Event, sizeof(Event));
701 Event.Header.Size = sizeof(Event.Header) + sizeof(Event.WriteStart);
702 Event.Header.Class.Type = EVENT_TRACE_TYPE_DC_START;
703 Event.Header.Class.Version = 0;
704 Event.Header.Class.Level = TRACE_LEVEL_INFORMATION;
705 Event.Header.Flags = WNODE_FLAG_TRACED_GUID;
706 Event.Header.Guid = ChannelWriteCategoryId;
707 Event.WriteStart.Channel = hFile;
708
709 DWORD cbToTrace = min(nNumberOfBytesToWrite, sizeof(Event.WriteStart.Data));
710 CopyMemory(Event.WriteStart.Data, lpBuffer, cbToTrace);
711
712 TraceEvent(g_hTraceSession, &Event.Header);
713 }
714
715
716 if (VBOX_RDP_CHANNEL::IsInstance(hFile))
717 {
718 VBOX_RDP_CHANNEL *pChannel = (VBOX_RDP_CHANNEL *) hFile;
719
720 *lpNumberOfBytesWritten = 0;
721
722 int rc = VbglR3HostChannelSend(
723 pChannel->GetId(), g_HostChannelCtx.u32HGCMClientId,
724 (void *) lpBuffer, nNumberOfBytesToWrite);
725
726 if (RT_SUCCESS(rc))
727 {
728 *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
729 }
730
731 VBoxMMRHookLog(
732 "VBoxMMR: TSMF send, channel: %d, sent: %d, result: %d\n",
733 pChannel->GetId(), *lpNumberOfBytesWritten, rc);
734 }
735 else
736 {
737 b = g_pfnWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
738 }
739
740 return b;
741}
742
743BOOL WINAPI LocalWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
744{
745 return MMRWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
746}
747
748/*
749/*
750 * ReadFileEx
751 */
752
753
754BOOL (WINAPI *g_pfnReadFileEx)(HANDLE, LPVOID, DWORD, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE) = 0;
755
756BOOL WINAPI MMRReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
757{
758 BOOL br = TRUE;
759
760 if (NULL != g_hTraceSession)
761 {
762 /* Size FieldTypeFlags */
763 TraceEventData Event; // = { { sizeof(Event), (USHORT) 0, }, h };
764
765 ZeroMemory(&Event, sizeof(Event));
766 Event.Header.Size = sizeof(Event.Header) + sizeof(Event.ReadStart);
767 Event.Header.Class.Type = EVENT_TRACE_TYPE_DC_START;
768 Event.Header.Class.Version = 0;
769 Event.Header.Class.Level = TRACE_LEVEL_INFORMATION;
770 Event.Header.Flags = WNODE_FLAG_TRACED_GUID;
771 Event.Header.Guid = ChannelReadCategoryId;
772 Event.ReadStart.Channel = hFile;
773
774 TraceEvent(g_hTraceSession, &Event.Header);
775 }
776
777 if (VBOX_RDP_CHANNEL::IsInstance(hFile))
778 {
779 VBOX_RDP_CHANNEL *pChannel = (VBOX_RDP_CHANNEL *) hFile;
780 pChannel->PushRequest((PBYTE) lpBuffer, lpOverlapped, lpCompletionRoutine);
781 }
782 else
783 {
784 br = g_pfnReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
785 }
786
787 return br;
788}
789
790BOOL WINAPI LocalReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
791{
792 return MMRReadFileEx(hFile, lpBuffer, nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine);
793}
794
795
796/*
797 * CloseHandle
798 */
799
800BOOL (WINAPI * g_pfnCloseHandle)(HANDLE) = NULL;
801
802BOOL WINAPI MMRCloseHandle(HANDLE hObject)
803{
804 if (NULL != g_hTraceSession)
805 {
806 /* Size FieldTypeFlags */
807 TraceEventData Event; // = { { sizeof(Event), (USHORT) 0, }, h };
808
809 ZeroMemory(&Event, sizeof(Event));
810 Event.Header.Size = sizeof(Event.Header) + sizeof(Event.Close);
811 Event.Header.Class.Type = EVENT_TRACE_TYPE_DC_START;
812 Event.Header.Class.Version = 0;
813 Event.Header.Class.Level = TRACE_LEVEL_INFORMATION;
814 Event.Header.Flags = WNODE_FLAG_TRACED_GUID;
815 Event.Header.Guid = ChannelCloseCategoryId;
816 Event.Close.Channel = hObject;
817
818 TraceEvent(g_hTraceSession, &Event.Header);
819 }
820
821 if (VBOX_RDP_CHANNEL::IsInstance(hObject))
822 {
823 VBOX_RDP_CHANNEL *pChannel = (VBOX_RDP_CHANNEL *) hObject;
824
825 VbglR3HostChannelDetach(
826 pChannel->GetId(), g_HostChannelCtx.u32HGCMClientId);
827
828 delete pChannel;
829
830 return TRUE;
831 }
832
833 return g_pfnCloseHandle(hObject);
834}
835
836BOOL WINAPI LocalCloseHandle(HANDLE hObject)
837{
838 return MMRCloseHandle(hObject);
839}
840
841/*
842 * CancelIo
843 */
844
845BOOL (WINAPI * g_pfnCancelIo)(HANDLE) = 0;
846
847BOOL WINAPI MMRCancelIo(HANDLE hFile)
848{
849 if (VBOX_RDP_CHANNEL::IsInstance(hFile))
850 {
851 // FIXME
852 return TRUE;
853 }
854
855 return g_pfnCancelIo(hFile);
856}
857
858BOOL WINAPI LocalCancelIo(HANDLE hFile)
859{
860 return MMRCancelIo(hFile);
861}
862
863
864/*
865 * WinStationIsSessionRemoteable
866 */
867
868BOOL (WINAPI *g_pfnWinStationIsSessionRemoteable)(HANDLE, DWORD, PVOID) = NULL;
869
870BOOL WINAPI MMRWinStationIsSessionRemoteable(HANDLE hServer, DWORD hSession, PVOID c)
871{
872 BOOL b = g_pfnWinStationIsSessionRemoteable(hServer, hSession, c);
873
874 PBYTE pb = (PBYTE) c;
875
876 VBoxMMRHookLog("VBoxMMR: LocalWinStationIsSessionRemoteable() = %d -> 1\n", (int) *pb);
877
878 *pb = 1;
879
880 return b;
881}
882
883BOOL WINAPI LocalWinStationIsSessionRemoteable(HANDLE hServer, DWORD hSession, PVOID c)
884{
885 return MMRWinStationIsSessionRemoteable(hServer, hSession, c);
886}
887
888/*
889 * WinStationVirtualOpenEx
890 */
891
892HANDLE (WINAPI *g_pfnWinStationVirtualOpenEx)(HANDLE, DWORD, LPSTR, DWORD) = NULL;
893
894HANDLE WINAPI MMRWinStationVirtualOpenEx(HANDLE hServer, DWORD hSession, LPSTR pVirtualName, DWORD flags)
895{
896 // assert(WTS_CURRENT_SERVER == hServer)
897 // assert(WTS_CURRENT_SESSION == hSession)
898
899 HANDLE h = g_pfnWinStationVirtualOpenEx(hServer, hSession, pVirtualName, flags);
900
901 if (NULL == h && 0 != g_HostChannelCtx.u32HGCMClientId)
902 {
903 uint32_t u32ChannelHandle = 0;
904 uint32_t u32Flags = 0x00; /* Not used currently. */
905
906 EnterCriticalSection(&CreateLock);
907
908 g_nCreateResult = VBOX_TSMF_HCH_CREATE_DECLINED;
909
910 int rc = VbglR3HostChannelAttach(
911 &u32ChannelHandle, g_HostChannelCtx.u32HGCMClientId, "/vrde/tsmf", u32Flags);
912
913 if (RT_SUCCESS(rc))
914 {
915 WaitForSingleObject(hCreateEvent, 5000);
916
917 if (g_nCreateResult == VBOX_TSMF_HCH_CREATE_ACCEPTED)
918 {
919 h = new VBOX_RDP_CHANNEL(u32ChannelHandle);
920
921 if (hDetachMonitor == NIL_RTTHREAD)
922 {
923 StartMonitor(&hDetachMonitor, MonitorDetach,
924 &nUserData, 0, RTTHREADTYPE_INFREQUENT_POLLER,
925 RTTHREADFLAGS_WAITABLE, "mmrpoll");
926 }
927 }
928 else
929 {
930 VBoxMMRHookLog("VBoxMMR: Unable to open channel: %d\n", g_nCreateResult);
931 }
932 }
933 else
934 {
935 VBoxMMRHookLog("VBoxMMR: Error attaching channel: %d\n", rc);
936 }
937
938 LeaveCriticalSection(&CreateLock);
939 }
940
941 if (NULL != g_hTraceSession)
942 {
943 /* Size FieldTypeFlags */
944 TraceEventData Event; // = { { sizeof(Event), (USHORT) 0, }, h };
945
946 ZeroMemory(&Event, sizeof(Event));
947 Event.Header.Size = sizeof(Event.Header) + sizeof(Event.Open);
948 Event.Header.Class.Type = EVENT_TRACE_TYPE_DC_END;
949 Event.Header.Class.Version = 0;
950 Event.Header.Class.Level = TRACE_LEVEL_INFORMATION;
951 Event.Header.Flags = WNODE_FLAG_TRACED_GUID;
952 Event.Header.Guid = ChannelOpenCategoryId;
953 Event.Open.Channel = h;
954
955 TraceEvent(g_hTraceSession, &Event.Header);
956 }
957
958 return h;
959}
960
961HANDLE WINAPI LocalWinStationVirtualOpenEx(HANDLE hServer, DWORD hSession, LPSTR pVirtualName, DWORD flags)
962{
963 return MMRWinStationVirtualOpenEx(hServer, hSession, pVirtualName, flags);
964}
965
966/*
967 * GetSystemMetrics
968 */
969
970int (WINAPI *g_pfnGetSystemMetrics)(int) = NULL;
971
972
973int WINAPI MMRGetSystemMetrics(int nIndex)
974{
975 const char *format = (nIndex < 100) ? "VBoxMMR: GetSystemMetrics(%d)\n" : "VBoxMMR: GetSystemMetrics(0x%x)\n";
976
977 VBoxMMRHookLog(format, nIndex);
978
979 if (0x1000 == nIndex)
980 return 1;
981
982 return g_pfnGetSystemMetrics(nIndex);
983}
984
985int WINAPI LocalGetSystemMetrics(int nIndex)
986{
987 return MMRGetSystemMetrics(nIndex);
988}
989
990HookEntry g_TSMFHooks[] =
991{
992 { "winsta.dll", "WinStationIsSessionRemoteable", LocalWinStationIsSessionRemoteable, (PVOID *) &g_pfnWinStationIsSessionRemoteable, (PVOID *) &MMRWinStationIsSessionRemoteable },
993 { "winsta.dll", "WinStationVirtualOpenEx", LocalWinStationVirtualOpenEx, (PVOID *) &g_pfnWinStationVirtualOpenEx, (PVOID *) &MMRWinStationVirtualOpenEx },
994 { "user32.dll", "GetSystemMetrics", LocalGetSystemMetrics, (PVOID *) &g_pfnGetSystemMetrics, (PVOID *) &MMRGetSystemMetrics},
995 { "kernel32.dll", "ReadFileEx", LocalReadFileEx, (PVOID *) &g_pfnReadFileEx, (PVOID *) &MMRReadFileEx },
996 { "kernel32.dll", "WriteFile", LocalWriteFile, (PVOID *) &g_pfnWriteFile,(PVOID *) &MMRWriteFile },
997 { "kernel32.dll", "CloseHandle", LocalCloseHandle, (PVOID *) &g_pfnCloseHandle,(PVOID *) &MMRCloseHandle },
998 { "kernel32.dll", "CancelIo", LocalCancelIo, (PVOID *) &g_pfnCancelIo, (PVOID *) &MMRCancelIo },
999 { "wtsapi32.dll", "WTSQuerySessionInformationW", LocalWTSQuerySessionInformation, (PVOID *) &g_pfnWTSQuerySessionInformation, (PVOID *) &MMRWTSQuerySessionInformation },
1000 { NULL, NULL, NULL, NULL, NULL }
1001};
1002
1003/*
1004 * MFCreateRemoteDesktopPlugin
1005 */
1006
1007HRESULT (STDAPICALLTYPE *g_pfnMFCreateRemoteDesktopPlugin)(IMFRemoteDesktopPlugin **ppPlugin) = NULL;
1008
1009STDAPI MMRMFCreateRemoteDesktopPlugin(IMFRemoteDesktopPlugin **ppPlugin)
1010{
1011 HRESULT hr = g_pfnMFCreateRemoteDesktopPlugin(ppPlugin);
1012
1013 VBoxMMRHookLog("VBoxMMR: LocalMFCreateRemoteDesktopPlugin: *ppPlugin = %p, result: %x\n", *ppPlugin, hr);
1014
1015 static bool IsTSMFHooked = false;
1016 if (!IsTSMFHooked)
1017 {
1018 HMODULE hModule = GetModuleHandleA("tsmf");
1019
1020 if (hModule)
1021 {
1022 VBoxMMRHookLog("VBoxMMR: Installing hooks for tsmf.dll\n");
1023 const IMAGE_IMPORT_DESCRIPTOR *pDescriptor = GetImportDescriptor(hModule);
1024 InstallHooks(pDescriptor, (PBYTE) hModule, g_TSMFHooks);
1025 IsTSMFHooked = true;
1026 }
1027 }
1028
1029 return hr;
1030}
1031
1032STDAPI LocalMFCreateRemoteDesktopPlugin(IMFRemoteDesktopPlugin **ppPlugin)
1033{
1034 return MMRMFCreateRemoteDesktopPlugin(ppPlugin);
1035}
1036
1037/*
1038 * GetProcAddress
1039 */
1040
1041FARPROC (WINAPI *g_pfnGetProcAddress)(HMODULE, LPCSTR) = NULL;
1042FARPROC WINAPI LocalGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
1043FARPROC WINAPI MMRGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
1044
1045HookEntry g_MFHooks[] =
1046{
1047 { "kernel32.dll", "GetProcAddress", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress,(PVOID *) &MMRGetProcAddress },
1048 { NULL, NULL, NULL, NULL, NULL }
1049};
1050
1051HookEntry g_WinMMHooks[] =
1052{
1053 { "user32.dll", "GetSystemMetrics", LocalGetSystemMetrics, (PVOID *) &g_pfnGetSystemMetrics,(PVOID *) &MMRGetSystemMetrics},
1054 { "kernel32.dll", "GetProcAddress", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress,(PVOID *) &MMRGetProcAddress },
1055 { NULL, NULL, NULL, NULL, NULL }
1056};
1057
1058HookEntry g_DShowHooks[] =
1059{
1060 { "user32.dll", "GetSystemMetrics", LocalGetSystemMetrics, (PVOID *) &g_pfnGetSystemMetrics,(PVOID *) &MMRGetSystemMetrics },
1061 { "kernel32.dll", "GetProcAddress", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress,(PVOID *) &MMRGetProcAddress },
1062 { NULL, NULL, NULL, NULL, NULL }
1063};
1064
1065
1066FARPROC WINAPI MMRGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
1067{
1068 FARPROC ret = g_pfnGetProcAddress(hModule, lpProcName);
1069
1070 static bool IsMFHooked = false;
1071 if (!IsMFHooked)
1072 {
1073 CHAR szBuf[512];
1074 GetModuleFileNameA(hModule, szBuf, sizeof(szBuf));
1075 PCHAR pc = strrchr(szBuf, '\\');
1076 if (0 == _stricmp(pc + 1, "mf.dll"))
1077 {
1078 VBoxMMRHookLog("VBoxMMR: Installing hooks for mf.dll\n");
1079 const IMAGE_IMPORT_DESCRIPTOR *pDescriptor = GetImportDescriptor(hModule);
1080 InstallHooks(pDescriptor, (PBYTE) hModule, g_MFHooks);
1081 IsMFHooked = true;
1082 }
1083 }
1084
1085 static bool IsWinMMHooked = false;
1086 if (!IsWinMMHooked)
1087 {
1088 CHAR szBuf[512];
1089 GetModuleFileNameA(hModule, szBuf, sizeof(szBuf));
1090 PCHAR pc = strrchr(szBuf, '\\');
1091 if (0 == _stricmp(pc + 1, "winmm.dll"))
1092 {
1093 VBoxMMRHookLog("VBoxMMR: Installing hooks for winmm.dll\n");
1094 const IMAGE_IMPORT_DESCRIPTOR *pDescriptor = GetImportDescriptor(hModule);
1095 InstallHooks(pDescriptor, (PBYTE) hModule, g_WinMMHooks);
1096 IsWinMMHooked = true;
1097 }
1098 }
1099
1100 // if an ordinal, all but the lower word must be 0
1101 // FIXME: should be pointer size
1102 if (0 == ((DWORD) lpProcName & ~0xFFFF))
1103 {
1104 CHAR szDllName[512];
1105 if (FALSE == GetModuleFileNameA(hModule, szDllName, sizeof(szDllName)))
1106 szDllName[0] = '\0';
1107
1108 VBoxMMRHookLog("VBoxMMR: GetProcAddress: %u (%s)\n", (DWORD) lpProcName, szDllName);
1109 }
1110 else
1111 {
1112 if (0 == strncmp(lpProcName, "WTS", 3) || 0 == strncmp(lpProcName, "MF", 2) || 0 == strncmp(lpProcName, "GetTS", 5))
1113 VBoxMMRHookLog("VBoxMMR: GetProcAddress: %s\n", lpProcName);
1114
1115 if (0 == strcmp(lpProcName, "MFCreateRemoteDesktopPlugin"))
1116 {
1117 g_pfnMFCreateRemoteDesktopPlugin = (HRESULT (STDAPICALLTYPE *)(IMFRemoteDesktopPlugin **ppPlugin)) ret;
1118 ret = (FARPROC) LocalMFCreateRemoteDesktopPlugin;
1119
1120 CHAR szDllName[512];
1121
1122 if (FALSE == GetModuleFileNameA(hModule, szDllName, sizeof(szDllName)))
1123 {
1124 szDllName[0] = '\0';
1125 }
1126 }
1127 else if (0 == strcmp(lpProcName, "WTSQuerySessionInformationW"))
1128 {
1129 g_pfnWTSQuerySessionInformation = (BOOL (__stdcall *)(HANDLE,DWORD,WTS_INFO_CLASS,LPWSTR *,DWORD *)) ret;
1130 ret = (FARPROC) LocalWTSQuerySessionInformation;
1131
1132 CHAR szDllName[512];
1133
1134 if (FALSE == GetModuleFileNameA(hModule, szDllName, sizeof(szDllName)))
1135 {
1136 szDllName[0] = '\0';
1137 }
1138 }
1139 }
1140
1141 return ret;
1142}
1143
1144FARPROC WINAPI LocalGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
1145{
1146 return MMRGetProcAddress(hModule, lpProcName);
1147}
1148
1149HookEntry g_WMPHooks[] =
1150{
1151 { "user32.dll", "GetSystemMetrics", LocalGetSystemMetrics, (PVOID *) &g_pfnGetSystemMetrics, (PVOID *)&MMRGetSystemMetrics },
1152 { "kernel32.dll", "GetProcAddress", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress, (PVOID *)&MMRGetProcAddress },
1153 { "mf.dll", "MFCreateRemoteDesktopPlugin", LocalMFCreateRemoteDesktopPlugin, (PVOID *) &g_pfnMFCreateRemoteDesktopPlugin, (PVOID *) &MMRMFCreateRemoteDesktopPlugin },
1154 { "wtsapi32.dll", "WTSQuerySessionInformationW", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress,(PVOID *) &MMRGetProcAddress },
1155 { NULL, NULL, NULL, NULL, NULL }
1156};
1157
1158/*
1159 * Note that McAffee hooks into GetProcAddress as well (HIPIS0e011b5.dll), so there is no point
1160 * in patching "GetProcAddress" of ole32.dll
1161 */
1162
1163static TRACEHANDLE g_hTraceRegistration = NULL;
1164
1165static ULONG WINAPI ControlCallback(WMIDPREQUESTCODE RequestCode, PVOID Context, ULONG *Reserved, PVOID pBuffer)
1166{
1167 UNREFERENCED_PARAMETER(Context);
1168 UNREFERENCED_PARAMETER(Reserved);
1169
1170 ULONG status = ERROR_SUCCESS;
1171 TRACEHANDLE hTraceSession = GetTraceLoggerHandle(pBuffer);
1172
1173 switch(RequestCode)
1174 {
1175 case WMI_ENABLE_EVENTS: // Enable the provider
1176 if (NULL == g_hTraceSession)
1177 g_hTraceSession = hTraceSession;
1178 break;
1179 case WMI_DISABLE_EVENTS: // Disable the provider
1180 // igonore disable requests from other sessions
1181 if (hTraceSession == g_hTraceSession)
1182 g_hTraceSession = NULL;
1183 break;
1184 default:
1185 status = ERROR_INVALID_PARAMETER;
1186 break;
1187 }
1188
1189 return status;
1190}
1191
1192
1193static int VBoxMMROpenBaseDriver(void)
1194{
1195 /* Open VBox guest driver. */
1196 DWORD dwErr = ERROR_SUCCESS;
1197 ghVBoxDriver = CreateFile(TEXT(VBOXGUEST_DEVICE_NAME),
1198 GENERIC_READ | GENERIC_WRITE,
1199 FILE_SHARE_READ | FILE_SHARE_WRITE,
1200 NULL,
1201 OPEN_EXISTING,
1202 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
1203 NULL);
1204
1205 if (INVALID_HANDLE_VALUE == ghVBoxDriver )
1206 {
1207 dwErr = GetLastError();
1208 VBoxMMRHookLog("VBoxMMR: Could not open VirtualBox Guest Additions driver! Please install / start it first! Error = %08X\n", dwErr);
1209 }
1210 return RTErrConvertFromWin32(dwErr);
1211}
1212
1213static void VBoxMMRCloseBaseDriver(void)
1214{
1215 if (ghVBoxDriver)
1216 {
1217 CloseHandle(ghVBoxDriver);
1218 ghVBoxDriver = NULL;
1219 }
1220}
1221
1222void
1223ReadTSMF(uint32_t u32ChannelHandle, uint32_t u32HGCMClientId, uint32_t u32SizeAvailable)
1224{
1225 uint32_t u32SizeReceived = 0;
1226 uint32_t u32SizeRemaining = 0;
1227
1228 PBYTE pBuffer = (PBYTE) malloc(u32SizeAvailable + sizeof(u32SizeAvailable));
1229 CopyMemory(pBuffer, &u32SizeAvailable, sizeof(u32SizeAvailable));
1230
1231 int rc = VbglR3HostChannelRecv(u32ChannelHandle,
1232 u32HGCMClientId,
1233 pBuffer + sizeof(u32SizeAvailable),
1234 u32SizeAvailable,
1235 &u32SizeReceived,
1236 &u32SizeRemaining);
1237
1238 VBoxMMRHookLog(
1239 "VBoxMMR: TSMF recv, channel: %d, available: %d, received %d, remaining %d, result: %d\n",
1240 u32ChannelHandle, u32SizeAvailable, u32SizeReceived, u32SizeRemaining, rc);
1241
1242 VBOX_RDP_CHANNEL *pChannel =
1243 VBOX_RDP_CHANNEL::GetFromId(u32ChannelHandle);
1244
1245 if (RT_SUCCESS(rc) && pChannel && u32SizeReceived != 0)
1246 {
1247 DWORD *pPtr = (DWORD *) (pBuffer + sizeof(u32SizeAvailable));
1248
1249 if (0x01 != pPtr[2] && 0x02 != pPtr[2] &&
1250 0x80000000 != pPtr[0] && 0x40000001 != pPtr[0])
1251 {
1252 VBoxMMRHookLog(
1253 "VBoxMMR: Unknown TSMF Data: %X %X %X\n",
1254 pPtr[0], pPtr[1], pPtr[2]);
1255 }
1256
1257 pChannel->PushBuffer(pBuffer);
1258 }
1259 else
1260 {
1261 delete [] pBuffer;
1262 }
1263}
1264
1265DECLCALLBACK(int)
1266MonitorTSMFChannel(RTTHREAD hThreadSelf, void *pvUser)
1267{
1268 HostChannelCtx *pCtx = (HostChannelCtx *) pvUser;
1269
1270 VBoxMMRHookLog("VBoxMMR: MonitorTSMFChannel starting\n");
1271
1272 while (!pCtx->fShutdown)
1273 {
1274 uint32_t u32ChannelHandle = 0;
1275 uint32_t u32EventId = 0;
1276 uint32_t u32SizeReturned = 0;
1277 void *pvParm = &pCtx->au8EventData[0];
1278 uint32_t cbParm = sizeof(pCtx->au8EventData);
1279
1280 int rc = VbglR3HostChannelEventWait(
1281 &u32ChannelHandle, pCtx->u32HGCMClientId,
1282 &u32EventId, pvParm, cbParm, &u32SizeReturned);
1283
1284 if (RT_SUCCESS(rc))
1285 {
1286 switch(u32EventId)
1287 {
1288 case VBOX_TSMF_HCH_CREATE_ACCEPTED:
1289 {
1290 VBoxMMRHookLog("VBoxMMR: VBOX_TSMF_HCH_CREATE_ACCEPTED: channel: %d\n", u32ChannelHandle);
1291 g_nCreateResult = u32EventId;
1292 SetEvent(hCreateEvent);
1293 } break;
1294
1295 case VBOX_TSMF_HCH_CREATE_DECLINED:
1296 {
1297 VBoxMMRHookLog("VBoxMMR: VBOX_TSMF_HCH_CREATE_DECLINED: channel: %d\n", u32ChannelHandle);
1298 g_nCreateResult = u32EventId;
1299 SetEvent(hCreateEvent);
1300 } break;
1301
1302 case VBOX_TSMF_HCH_DISCONNECTED:
1303 {
1304 VBoxMMRHookLog("VBoxMMR: VBOX_TSMF_HCH_DISCONNECTED: channel: %d\n", u32ChannelHandle);
1305 } break;
1306
1307 case VBOX_HOST_CHANNEL_EVENT_CANCELLED:
1308 {
1309 VBoxMMRHookLog("VBoxMMR: VBOX_HOST_CHANNEL_EVENT_CANCELLED\n");
1310 } break;
1311
1312 case VBOX_HOST_CHANNEL_EVENT_UNREGISTERED:
1313 {
1314 VBoxMMRHookLog("VBoxMMR: VBOX_HOST_CHANNEL_EVENT_UNREGISTERED\n");
1315 } break;
1316
1317 case VBOX_HOST_CHANNEL_EVENT_RECV:
1318 {
1319 VBOXHOSTCHANNELEVENTRECV *p =
1320 (VBOXHOSTCHANNELEVENTRECV *)pvParm;
1321
1322 if (p->u32SizeAvailable > 0)
1323 {
1324 ReadTSMF(u32ChannelHandle, pCtx->u32HGCMClientId, p->u32SizeAvailable);
1325 }
1326 else
1327 {
1328 VBoxMMRHookLog("VBoxMMR: TSMF recv, channel: %d, available: 0\n", u32ChannelHandle);
1329 }
1330 } break;
1331
1332 default:
1333 {
1334 VBoxMMRHookLog("VBoxMMR: unknown event id %d\n", u32EventId);
1335 } break;
1336 }
1337 }
1338 }
1339
1340 VBoxMMRHookLog("VBoxMMR: MonitorTSMFChannel stopping\n");
1341
1342 return VINF_SUCCESS;
1343}
1344
1345void InstallHooksForSystemModule(const char *pszName, HookEntry hooks[])
1346{
1347 /* Construct the full path to the given module and load it. */
1348 char szPath[MAX_PATH];
1349 UINT cchPath = GetSystemDirectoryA(szPath, MAX_PATH);
1350 size_t cbName = strlen(pszName) + 1;
1351 if (cchPath + 1 + cbName <= sizeof(szPath))
1352 {
1353 szPath[cchPath] = '\\';
1354 memcpy(&szPath[cchPath + 1], pszName, cbName);
1355
1356 HMODULE hMod = LoadLibraryA(szPath);
1357 if (hMod != NULL)
1358 {
1359 VBoxMMRHookLog("VBoxMMR: Hooking %s -> %x \n", pszName, hMod);
1360 const IMAGE_IMPORT_DESCRIPTOR *pDescriptor = GetImportDescriptor(hMod);
1361 InstallHooks(pDescriptor, (PBYTE) hMod, hooks);
1362 }
1363 else
1364 VBoxMMRHookLog("VBoxMMR: Error hooking %s -> not found (last error %u)\n", pszName, GetLastError());
1365 }
1366 else
1367 VBoxMMRHookLog("VBoxMMR: Error hooking %s -> not found\n", pszName);
1368}
1369
1370TSMFHOOK_API LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
1371{
1372 static bool bInit = false;
1373
1374 if (isWMP && !bInit)
1375 {
1376 bInit = true;
1377
1378 g_bMMRCodeCavingIsEnabled = MMRCodeCavingIsEnabled();
1379
1380 VBoxMMRHookLog("VBoxMMR: WMP APIs Hooking started ...\n");
1381
1382 HMODULE hMod = GetModuleHandleA("wmp");
1383 if (hMod != NULL)
1384 {
1385 VBoxMMRHookLog("VBoxMMR: Hooking wmp -> %x \n",hMod);
1386 const IMAGE_IMPORT_DESCRIPTOR *pDescriptor = GetImportDescriptor(hMod);
1387 InstallHooks(pDescriptor, (PBYTE) hMod, g_WMPHooks);
1388 }
1389 else
1390 {
1391 VBoxMMRHookLog("VBoxMMR: Error hooking wmp -> not found\n");
1392 }
1393
1394 InstallHooksForSystemModule("winmm.dll", g_WinMMHooks);
1395 InstallHooksForSystemModule("tsmf.dll", g_TSMFHooks);
1396 InstallHooksForSystemModule("DSHOWRDPFILTER.dll", g_TSMFHooks);
1397 InstallHooksForSystemModule("MSMPEG2VDEC.dll", g_DShowHooks);
1398 InstallHooksForSystemModule("MFDS.dll", g_DShowHooks);
1399 InstallHooksForSystemModule("mf.dll", g_MFHooks);
1400
1401 ULONG ret = RegisterTraceGuids(
1402 ControlCallback, NULL, &ProviderId, 0,
1403 NULL, NULL, NULL, &g_hTraceRegistration);
1404
1405 if (ERROR_SUCCESS != ret)
1406 {
1407 VBoxMMRHookLog("VBoxMMR: RegisterTraceGuids failed with error code: %u\n", GetLastError());
1408 }
1409
1410 bool bInRDPSession = (1 == GetSystemMetrics(0x1000));
1411
1412 if (!bInRDPSession)
1413 {
1414 uint32_t u32HGCMClientId = 0;
1415
1416 int rc = VbglR3HostChannelInit(&u32HGCMClientId);
1417
1418 if (RT_SUCCESS(rc))
1419 {
1420 uint32_t u32Size = 0;
1421
1422 rc = VbglR3HostChannelQuery(g_pszVRDETSMF, u32HGCMClientId,
1423 VBOX_HOST_CHANNEL_CTRL_EXISTS, NULL, 0, NULL, 0, &u32Size);
1424
1425 if (RT_SUCCESS(rc))
1426 {
1427 hCreateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1428 InitializeCriticalSection(&CreateLock);
1429
1430 g_HostChannelCtx.thread = NIL_RTTHREAD;
1431 g_HostChannelCtx.u32HGCMClientId = u32HGCMClientId;
1432
1433 StartMonitor(
1434 &g_HostChannelCtx.thread, MonitorTSMFChannel,
1435 &g_HostChannelCtx, 64*_1K,
1436 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
1437 "tsmfio");
1438
1439 VBoxMMROpenBaseDriver();
1440 }
1441 else
1442 {
1443 VBoxMMRHookLog(
1444 "VBoxMMR: TSMF HGCM unavailable: hgcmid: %d, rc: %d\n",
1445 u32HGCMClientId, rc);
1446
1447 VbglR3HostChannelTerm(u32HGCMClientId);
1448 }
1449 }
1450 else
1451 {
1452 VBoxMMRHookLog("VBoxMMR: Error connecting to HGCM: %d\n", rc);
1453 }
1454 }
1455 }
1456
1457 return CallNextHookEx(NULL /*ignored */, nCode, wParam, lParam);
1458}
1459
1460void Shutdown()
1461{
1462 if (isWMP)
1463 {
1464 VBoxMMRHookLog("VBoxMMR: Shutdown\n");
1465
1466 StopMonitor(&hDetachMonitor, "mmrpoll");
1467 VBoxMMRCloseBaseDriver();
1468
1469 if (g_HostChannelCtx.u32HGCMClientId != 0)
1470 {
1471 g_HostChannelCtx.fShutdown = true;
1472 VbglR3HostChannelEventCancel(0, g_HostChannelCtx.u32HGCMClientId);
1473 StopMonitor(&g_HostChannelCtx.thread, "tsmfio");
1474 VbglR3HostChannelTerm(g_HostChannelCtx.u32HGCMClientId);
1475 }
1476
1477 if (hCreateEvent)
1478 {
1479 CloseHandle(hCreateEvent);
1480 DeleteCriticalSection(&CreateLock);
1481 }
1482
1483 if (g_hTraceRegistration)
1484 UnregisterTraceGuids(g_hTraceRegistration);
1485 }
1486}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette