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 | */
|
---|
44 | static const char g_szCodeCave[] = "\x55\x8B\xEC\x5D\xB8\xEF\xBE\xAD\xDE\xFF\xE0";
|
---|
45 |
|
---|
46 | const WCHAR *g_pwszMMRFlags = L"VBoxMMR";
|
---|
47 |
|
---|
48 | const WCHAR *g_pwszMMRAdditions =
|
---|
49 | L"SOFTWARE\\Oracle\\VirtualBox Guest Additions";
|
---|
50 |
|
---|
51 | const char *g_pszVRDETSMF = "/vrde/tsmf";
|
---|
52 |
|
---|
53 | const DWORD g_dwMMRCodeCavingEnabled = 0x00000002;
|
---|
54 |
|
---|
55 | BOOL g_bMMRCodeCavingIsEnabled = TRUE;
|
---|
56 |
|
---|
57 | BOOL 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 |
|
---|
94 | RTTHREAD hDetachMonitor = NIL_RTTHREAD;
|
---|
95 | uint32_t nUserData = 1;
|
---|
96 |
|
---|
97 | HANDLE ghVBoxDriver = NULL;
|
---|
98 |
|
---|
99 | using std::map;
|
---|
100 | using std::list;
|
---|
101 | using std::queue;
|
---|
102 |
|
---|
103 | extern bool isWMP;
|
---|
104 |
|
---|
105 | CRITICAL_SECTION CreateLock;
|
---|
106 | HANDLE hCreateEvent;
|
---|
107 | uint32_t g_nCreateResult = VBOX_TSMF_HCH_CREATE_DECLINED;
|
---|
108 |
|
---|
109 | TRACEHANDLE g_hTraceSession = NULL;
|
---|
110 |
|
---|
111 | struct HookEntry
|
---|
112 | {
|
---|
113 | LPCSTR DllName;
|
---|
114 | LPCSTR FunctionName;
|
---|
115 | PVOID HookFuncAddr;
|
---|
116 | PVOID *OrigFuncAddrPtr;
|
---|
117 | PVOID *MMRFuncAddrPtr;
|
---|
118 | };
|
---|
119 |
|
---|
120 |
|
---|
121 | struct HostChannelCtx
|
---|
122 | {
|
---|
123 | RTTHREAD thread;
|
---|
124 | bool fShutdown;
|
---|
125 | uint32_t u32HGCMClientId;
|
---|
126 | uint8_t au8EventData[4];
|
---|
127 | };
|
---|
128 |
|
---|
129 | HostChannelCtx g_HostChannelCtx = {0};
|
---|
130 |
|
---|
131 | struct 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 |
|
---|
142 | VOID 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 |
|
---|
177 | class 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 |
|
---|
191 | protected:
|
---|
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 |
|
---|
213 | public:
|
---|
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 |
|
---|
336 | list<HANDLE> VBOX_RDP_CHANNEL::ChannelList;
|
---|
337 | map<DWORD, HANDLE> VBOX_RDP_CHANNEL::ChannelMap;
|
---|
338 |
|
---|
339 | const 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 |
|
---|
352 | DWORD 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 |
|
---|
386 | bool 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 |
|
---|
403 | void 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 |
|
---|
490 | void 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 |
|
---|
529 | int 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 |
|
---|
546 | int 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 |
|
---|
575 | DECLCALLBACK(int)
|
---|
576 | MonitorDetach(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 |
|
---|
658 | BOOL (WINAPI * g_pfnWTSQuerySessionInformation)(HANDLE, DWORD, WTS_INFO_CLASS, LPWSTR *, DWORD *) = NULL;
|
---|
659 | BOOL 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 |
|
---|
679 | BOOL 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 |
|
---|
689 | BOOL (WINAPI *g_pfnWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED) = NULL;
|
---|
690 |
|
---|
691 | BOOL 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 |
|
---|
743 | BOOL 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 |
|
---|
754 | BOOL (WINAPI *g_pfnReadFileEx)(HANDLE, LPVOID, DWORD, LPOVERLAPPED, LPOVERLAPPED_COMPLETION_ROUTINE) = 0;
|
---|
755 |
|
---|
756 | BOOL 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 |
|
---|
790 | BOOL 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 |
|
---|
800 | BOOL (WINAPI * g_pfnCloseHandle)(HANDLE) = NULL;
|
---|
801 |
|
---|
802 | BOOL 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 |
|
---|
836 | BOOL WINAPI LocalCloseHandle(HANDLE hObject)
|
---|
837 | {
|
---|
838 | return MMRCloseHandle(hObject);
|
---|
839 | }
|
---|
840 |
|
---|
841 | /*
|
---|
842 | * CancelIo
|
---|
843 | */
|
---|
844 |
|
---|
845 | BOOL (WINAPI * g_pfnCancelIo)(HANDLE) = 0;
|
---|
846 |
|
---|
847 | BOOL 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 |
|
---|
858 | BOOL WINAPI LocalCancelIo(HANDLE hFile)
|
---|
859 | {
|
---|
860 | return MMRCancelIo(hFile);
|
---|
861 | }
|
---|
862 |
|
---|
863 |
|
---|
864 | /*
|
---|
865 | * WinStationIsSessionRemoteable
|
---|
866 | */
|
---|
867 |
|
---|
868 | BOOL (WINAPI *g_pfnWinStationIsSessionRemoteable)(HANDLE, DWORD, PVOID) = NULL;
|
---|
869 |
|
---|
870 | BOOL 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 |
|
---|
883 | BOOL WINAPI LocalWinStationIsSessionRemoteable(HANDLE hServer, DWORD hSession, PVOID c)
|
---|
884 | {
|
---|
885 | return MMRWinStationIsSessionRemoteable(hServer, hSession, c);
|
---|
886 | }
|
---|
887 |
|
---|
888 | /*
|
---|
889 | * WinStationVirtualOpenEx
|
---|
890 | */
|
---|
891 |
|
---|
892 | HANDLE (WINAPI *g_pfnWinStationVirtualOpenEx)(HANDLE, DWORD, LPSTR, DWORD) = NULL;
|
---|
893 |
|
---|
894 | HANDLE 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 |
|
---|
961 | HANDLE 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 |
|
---|
970 | int (WINAPI *g_pfnGetSystemMetrics)(int) = NULL;
|
---|
971 |
|
---|
972 |
|
---|
973 | int 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 |
|
---|
985 | int WINAPI LocalGetSystemMetrics(int nIndex)
|
---|
986 | {
|
---|
987 | return MMRGetSystemMetrics(nIndex);
|
---|
988 | }
|
---|
989 |
|
---|
990 | HookEntry 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 |
|
---|
1007 | HRESULT (STDAPICALLTYPE *g_pfnMFCreateRemoteDesktopPlugin)(IMFRemoteDesktopPlugin **ppPlugin) = NULL;
|
---|
1008 |
|
---|
1009 | STDAPI 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 |
|
---|
1032 | STDAPI LocalMFCreateRemoteDesktopPlugin(IMFRemoteDesktopPlugin **ppPlugin)
|
---|
1033 | {
|
---|
1034 | return MMRMFCreateRemoteDesktopPlugin(ppPlugin);
|
---|
1035 | }
|
---|
1036 |
|
---|
1037 | /*
|
---|
1038 | * GetProcAddress
|
---|
1039 | */
|
---|
1040 |
|
---|
1041 | FARPROC (WINAPI *g_pfnGetProcAddress)(HMODULE, LPCSTR) = NULL;
|
---|
1042 | FARPROC WINAPI LocalGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
|
---|
1043 | FARPROC WINAPI MMRGetProcAddress(HMODULE hModule, LPCSTR lpProcName);
|
---|
1044 |
|
---|
1045 | HookEntry g_MFHooks[] =
|
---|
1046 | {
|
---|
1047 | { "kernel32.dll", "GetProcAddress", LocalGetProcAddress, (PVOID *) &g_pfnGetProcAddress,(PVOID *) &MMRGetProcAddress },
|
---|
1048 | { NULL, NULL, NULL, NULL, NULL }
|
---|
1049 | };
|
---|
1050 |
|
---|
1051 | HookEntry 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 |
|
---|
1058 | HookEntry 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 |
|
---|
1066 | FARPROC 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 |
|
---|
1144 | FARPROC WINAPI LocalGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
|
---|
1145 | {
|
---|
1146 | return MMRGetProcAddress(hModule, lpProcName);
|
---|
1147 | }
|
---|
1148 |
|
---|
1149 | HookEntry 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 |
|
---|
1163 | static TRACEHANDLE g_hTraceRegistration = NULL;
|
---|
1164 |
|
---|
1165 | static 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 |
|
---|
1193 | static 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 |
|
---|
1213 | static void VBoxMMRCloseBaseDriver(void)
|
---|
1214 | {
|
---|
1215 | if (ghVBoxDriver)
|
---|
1216 | {
|
---|
1217 | CloseHandle(ghVBoxDriver);
|
---|
1218 | ghVBoxDriver = NULL;
|
---|
1219 | }
|
---|
1220 | }
|
---|
1221 |
|
---|
1222 | void
|
---|
1223 | ReadTSMF(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 |
|
---|
1265 | DECLCALLBACK(int)
|
---|
1266 | MonitorTSMFChannel(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 |
|
---|
1345 | void 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 |
|
---|
1370 | TSMFHOOK_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 |
|
---|
1460 | void 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 | }
|
---|