VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp@ 35380

Last change on this file since 35380 was 34080, checked in by vboxsync, 14 years ago

VBoxTray: Hacking for IPC over named pipes support.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1/** @file
2 * VBoxTray - Guest Additions Tray Application
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include "VBoxTray.h"
22#include "VBoxTrayMsg.h"
23#include "VBoxHelpers.h"
24#include "VBoxSeamless.h"
25#include "VBoxClipboard.h"
26#include "VBoxDisplay.h"
27#include "VBoxRestore.h"
28#include "VBoxVRDP.h"
29#include "VBoxHostVersion.h"
30#include "VBoxSharedFolders.h"
31#include "VBoxIPC.h"
32#include <VBoxHook.h>
33#include "resource.h"
34#include <malloc.h>
35#include <VBoxGuestInternal.h>
36
37#include <sddl.h>
38
39#include <iprt/buildconfig.h>
40
41
42/*******************************************************************************
43* Global Variables *
44*******************************************************************************/
45HANDLE gVBoxDriver;
46HANDLE gStopSem;
47HANDLE ghSeamlessNotifyEvent = 0;
48SERVICE_STATUS gVBoxServiceStatus;
49SERVICE_STATUS_HANDLE gVBoxServiceStatusHandle;
50HINSTANCE gInstance;
51HWND gToolWindow;
52NOTIFYICONDATA gNotifyIconData;
53DWORD gMajorVersion;
54
55/* Global message handler prototypes. */
56int vboxTrayGlMsgTaskbarCreated(WPARAM lParam, LPARAM wParam);
57int vboxTrayGlMsgShowBalloonMsg(WPARAM lParam, LPARAM wParam);
58
59/* Prototypes */
60int vboxTrayCreateTrayIcon(void);
61VOID DisplayChangeThread(void *dummy);
62LRESULT CALLBACK VBoxToolWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
63
64
65/* The service table. */
66static VBOXSERVICEINFO vboxServiceTable[] =
67{
68 {
69 "Display",
70 VBoxDisplayInit,
71 VBoxDisplayThread,
72 VBoxDisplayDestroy
73 },
74 {
75 "Shared Clipboard",
76 VBoxClipboardInit,
77 VBoxClipboardThread,
78 VBoxClipboardDestroy
79 },
80 {
81 "Seamless Windows",
82 VBoxSeamlessInit,
83 VBoxSeamlessThread,
84 VBoxSeamlessDestroy
85 },
86#ifdef VBOX_WITH_VRDP_SESSION_HANDLING
87 {
88 "Restore",
89 VBoxRestoreInit,
90 VBoxRestoreThread,
91 VBoxRestoreDestroy
92 },
93#endif
94 {
95 "VRDP",
96 VBoxVRDPInit,
97 VBoxVRDPThread,
98 VBoxVRDPDestroy
99 },
100 {
101 "IPC",
102 VBoxIPCInit,
103 VBoxIPCThread,
104 VBoxIPCDestroy
105 },
106 {
107 NULL
108 }
109};
110
111/* The global message table. */
112static VBOXGLOBALMESSAGE s_vboxGlobalMessageTable[] =
113{
114 /* Windows specific stuff. */
115 {
116 "TaskbarCreated",
117 vboxTrayGlMsgTaskbarCreated
118 },
119
120 /* VBoxTray specific stuff. */
121 /** @todo Add new messages here! */
122
123 {
124 NULL
125 }
126};
127
128/**
129 * Gets called whenever the Windows main taskbar
130 * get (re-)created. Nice to install our tray icon.
131 *
132 * @return IPRT status code.
133 * @param wParam
134 * @param lParam
135 */
136static int vboxTrayGlMsgTaskbarCreated(WPARAM wParam, LPARAM lParam)
137{
138 return vboxTrayCreateTrayIcon();
139}
140
141static int vboxTrayCreateTrayIcon(void)
142{
143 HICON hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_VIRTUALBOX));
144 if (hIcon == NULL)
145 {
146 DWORD dwErr = GetLastError();
147 Log(("VBoxTray: Could not load tray icon, error %08X\n", dwErr));
148 return RTErrConvertFromWin32(dwErr);
149 }
150
151 /* Prepare the system tray icon. */
152 RT_ZERO(gNotifyIconData);
153 gNotifyIconData.cbSize = NOTIFYICONDATA_V1_SIZE; // sizeof(NOTIFYICONDATA);
154 gNotifyIconData.hWnd = gToolWindow;
155 gNotifyIconData.uID = ID_TRAYICON;
156 gNotifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
157 gNotifyIconData.uCallbackMessage = WM_VBOXTRAY_TRAY_ICON;
158 gNotifyIconData.hIcon = hIcon;
159
160 sprintf(gNotifyIconData.szTip, "%s Guest Additions %d.%d.%dr%d",
161 VBOX_PRODUCT, VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
162
163 int rc = VINF_SUCCESS;
164 if (!Shell_NotifyIcon(NIM_ADD, &gNotifyIconData))
165 {
166 DWORD dwErr = GetLastError();
167 Log(("VBoxTray: Could not create tray icon, error = %08X\n", dwErr));
168 rc = RTErrConvertFromWin32(dwErr);
169 RT_ZERO(gNotifyIconData);
170 }
171
172 if (hIcon)
173 DestroyIcon(hIcon);
174 return rc;
175}
176
177static void vboxTrayRemoveTrayIcon()
178{
179 if (gNotifyIconData.cbSize > 0)
180 {
181 /* Remove the system tray icon and refresh system tray. */
182 Shell_NotifyIcon(NIM_DELETE, &gNotifyIconData);
183 HWND hTrayWnd = FindWindow("Shell_TrayWnd", NULL); /* We assume we only have one tray atm. */
184 if (hTrayWnd)
185 {
186 HWND hTrayNotifyWnd = FindWindowEx(hTrayWnd, 0, "TrayNotifyWnd", NULL);
187 if (hTrayNotifyWnd)
188 SendMessage(hTrayNotifyWnd, WM_PAINT, 0, NULL);
189 }
190 RT_ZERO(gNotifyIconData);
191 }
192}
193
194static int vboxTrayStartServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
195{
196 Log(("VBoxTray: Starting services ...\n"));
197
198 pEnv->hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
199
200 if (!pEnv->hStopEvent)
201 {
202 /* Could not create event. */
203 return VERR_NOT_SUPPORTED;
204 }
205
206 while (pTable->pszName)
207 {
208 Log(("VBoxTray: Starting %s ...\n", pTable->pszName));
209
210 int rc = VINF_SUCCESS;
211
212 bool fStartThread = false;
213
214 pTable->hThread = (HANDLE)0;
215 pTable->pInstance = NULL;
216 pTable->fStarted = false;
217
218 if (pTable->pfnInit)
219 rc = pTable->pfnInit (pEnv, &pTable->pInstance, &fStartThread);
220
221 if (RT_FAILURE(rc))
222 {
223 Log(("VBoxTray: Failed to initialize rc = %Rrc\n", rc));
224 }
225 else
226 {
227 if (pTable->pfnThread && fStartThread)
228 {
229 unsigned threadid;
230 pTable->hThread = (HANDLE)_beginthreadex(NULL, /* security */
231 0, /* stacksize */
232 pTable->pfnThread,
233 pTable->pInstance,
234 0, /* initflag */
235 &threadid);
236
237 if (pTable->hThread == (HANDLE)(0))
238 rc = VERR_NOT_SUPPORTED;
239 }
240
241 if (RT_SUCCESS(rc))
242 pTable->fStarted = true;
243 else
244 {
245 Log(("VBoxTray: Failed to start the thread\n"));
246 if (pTable->pfnDestroy)
247 pTable->pfnDestroy(pEnv, pTable->pInstance);
248 }
249 }
250
251 /* Advance to next table element. */
252 pTable++;
253 }
254
255 return VINF_SUCCESS;
256}
257
258static void vboxTrayStopServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
259{
260 if (!pEnv->hStopEvent)
261 return;
262
263 /* Signal to all threads. */
264 SetEvent(pEnv->hStopEvent);
265
266 while (pTable->pszName)
267 {
268 if (pTable->fStarted)
269 {
270 if (pTable->pfnThread)
271 {
272 /* There is a thread, wait for termination. */
273 WaitForSingleObject(pTable->hThread, INFINITE);
274
275 CloseHandle(pTable->hThread);
276 pTable->hThread = 0;
277 }
278
279 if (pTable->pfnDestroy)
280 pTable->pfnDestroy (pEnv, pTable->pInstance);
281 pTable->fStarted = false;
282 }
283
284 /* Advance to next table element. */
285 pTable++;
286 }
287
288 CloseHandle(pEnv->hStopEvent);
289}
290
291int vboxTrayRegisterGlobalMessages(PVBOXGLOBALMESSAGE pTable)
292{
293 int rc = VINF_SUCCESS;
294 if (pTable == NULL) /* No table to register? Skip. */
295 return rc;
296 while ( pTable->pszName
297 && RT_SUCCESS(rc))
298 {
299 /* Register global accessible window messages. */
300 pTable->uMsgID = RegisterWindowMessage(TEXT(pTable->pszName));
301 if (!pTable->uMsgID)
302 {
303 DWORD dwErr = GetLastError();
304 Log(("VBoxTray: Registering global message \"%s\" failed, error = %08X\n", dwErr));
305 rc = RTErrConvertFromWin32(dwErr);
306 }
307
308 /* Advance to next table element. */
309 pTable++;
310 }
311 return rc;
312}
313
314bool vboxTrayHandleGlobalMessages(PVBOXGLOBALMESSAGE pTable, UINT uMsg,
315 WPARAM wParam, LPARAM lParam)
316{
317 if (pTable == NULL)
318 return false;
319 while (pTable->pszName)
320 {
321 if (pTable->uMsgID == uMsg)
322 {
323 if (pTable->pfnHandler)
324 pTable->pfnHandler(wParam, lParam);
325 return true;
326 }
327
328 /* Advance to next table element. */
329 pTable++;
330 }
331 return false;
332}
333
334void WINAPI VBoxServiceStart(void)
335{
336 Log(("VBoxTray: Entering service main function\n"));
337
338 VBOXSERVICEENV svcEnv;
339 DWORD dwErr = NO_ERROR;
340
341 /* Open VBox guest driver. */
342 gVBoxDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
343 GENERIC_READ | GENERIC_WRITE,
344 FILE_SHARE_READ | FILE_SHARE_WRITE,
345 NULL,
346 OPEN_EXISTING,
347 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
348 NULL);
349 if (gVBoxDriver == INVALID_HANDLE_VALUE)
350 {
351 dwErr = GetLastError();
352 LogRel(("VBoxTray: Could not open VirtualBox Guest Additions driver! Please install / start it first! Error = %08X\n", dwErr));
353 }
354
355 if (dwErr == NO_ERROR)
356 {
357 /* Create a custom window class. */
358 WNDCLASS windowClass = {0};
359 windowClass.style = CS_NOCLOSE;
360 windowClass.lpfnWndProc = (WNDPROC)VBoxToolWndProc;
361 windowClass.hInstance = gInstance;
362 windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
363 windowClass.lpszClassName = "VBoxTrayToolWndClass";
364 if (!RegisterClass(&windowClass))
365 {
366 dwErr = GetLastError();
367 Log(("VBoxTray: Registering invisible tool window failed, error = %08X\n", dwErr));
368 }
369 }
370
371 if (dwErr == NO_ERROR)
372 {
373 /* Create our (invisible) tool window. */
374 /* Note: The window name ("VBoxTrayToolWnd") and class ("VBoxTrayToolWndClass") is
375 * needed for posting globally registered messages to VBoxTray and must not be
376 * changed! Otherwise things get broken! */
377 gToolWindow = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
378 "VBoxTrayToolWndClass", "VBoxTrayToolWnd",
379 WS_POPUPWINDOW,
380 -200, -200, 100, 100, NULL, NULL, gInstance, NULL);
381 if (!gToolWindow)
382 {
383 dwErr = GetLastError();
384 Log(("VBoxTray: Creating invisible tool window failed, error = %08X\n", dwErr));
385 }
386 else
387 {
388 hlpReloadCursor();
389 }
390 }
391
392 Log(("VBoxTray: Window Handle = %p, Status = %p\n", gToolWindow, dwErr));
393
394 OSVERSIONINFO info;
395 gMajorVersion = 5; /* default XP */
396 info.dwOSVersionInfoSize = sizeof(info);
397 if (GetVersionEx(&info))
398 {
399 Log(("VBoxTray: Windows version %ld.%ld\n", info.dwMajorVersion, info.dwMinorVersion));
400 gMajorVersion = info.dwMajorVersion;
401 }
402
403 if (dwErr == NO_ERROR)
404 {
405 gStopSem = CreateEvent(NULL, TRUE, FALSE, NULL);
406 if (gStopSem == NULL)
407 {
408 Log(("VBoxTray: CreateEvent for stopping VBoxTray failed, error = %08X\n", GetLastError()));
409 return;
410 }
411
412 /* We need to setup a security descriptor to allow other processes modify access to the seamless notification event semaphore */
413 SECURITY_ATTRIBUTES SecAttr;
414 char secDesc[SECURITY_DESCRIPTOR_MIN_LENGTH];
415 BOOL ret;
416
417 SecAttr.nLength = sizeof(SecAttr);
418 SecAttr.bInheritHandle = FALSE;
419 SecAttr.lpSecurityDescriptor = &secDesc;
420 InitializeSecurityDescriptor(SecAttr.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
421 ret = SetSecurityDescriptorDacl(SecAttr.lpSecurityDescriptor, TRUE, 0, FALSE);
422 if (!ret)
423 Log(("VBoxTray: SetSecurityDescriptorDacl failed with error = %08X\n", GetLastError()));
424
425 /* For Vista and up we need to change the integrity of the security descriptor too */
426 if (gMajorVersion >= 6)
427 {
428 HMODULE hModule;
429
430 BOOL (WINAPI * pfnConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR StringSecurityDescriptor, DWORD StringSDRevision, PSECURITY_DESCRIPTOR *SecurityDescriptor, PULONG SecurityDescriptorSize);
431
432 hModule = LoadLibrary("ADVAPI32.DLL");
433 if (hModule)
434 {
435 PSECURITY_DESCRIPTOR pSD;
436 PACL pSacl = NULL;
437 BOOL fSaclPresent = FALSE;
438 BOOL fSaclDefaulted = FALSE;
439
440 *(uintptr_t *)&pfnConvertStringSecurityDescriptorToSecurityDescriptorA = (uintptr_t)GetProcAddress(hModule, "ConvertStringSecurityDescriptorToSecurityDescriptorA");
441
442 Log(("VBoxTray: pfnConvertStringSecurityDescriptorToSecurityDescriptorA = %x\n", pfnConvertStringSecurityDescriptorToSecurityDescriptorA));
443 if (pfnConvertStringSecurityDescriptorToSecurityDescriptorA)
444 {
445 ret = pfnConvertStringSecurityDescriptorToSecurityDescriptorA("S:(ML;;NW;;;LW)", /* this means "low integrity" */
446 SDDL_REVISION_1, &pSD, NULL);
447 if (!ret)
448 Log(("VBoxTray: ConvertStringSecurityDescriptorToSecurityDescriptorA failed with error = %08X\n", GetLastError()));
449
450 ret = GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted);
451 if (!ret)
452 Log(("VBoxTray: GetSecurityDescriptorSacl failed with error = %08X\n", GetLastError()));
453
454 ret = SetSecurityDescriptorSacl(SecAttr.lpSecurityDescriptor, TRUE, pSacl, FALSE);
455 if (!ret)
456 Log(("VBoxTray: SetSecurityDescriptorSacl failed with error = %08X\n", GetLastError()));
457 }
458 }
459 }
460
461 if (gMajorVersion >= 5) /* Only for W2K and up ... */
462 {
463 ghSeamlessNotifyEvent = CreateEvent(&SecAttr, FALSE, FALSE, VBOXHOOK_GLOBAL_EVENT_NAME);
464 if (ghSeamlessNotifyEvent == NULL)
465 {
466 Log(("VBoxTray: CreateEvent for Seamless failed, error = %08X\n", GetLastError()));
467 return;
468 }
469 }
470 }
471
472 /*
473 * Start services listed in the vboxServiceTable.
474 */
475 svcEnv.hInstance = gInstance;
476 svcEnv.hDriver = gVBoxDriver;
477
478 /* initializes disp-if to default (XPDM) mode */
479 dwErr = VBoxDispIfInit(&svcEnv.dispIf);
480#ifdef VBOX_WITH_WDDM
481 /*
482 * For now the display mode will be adjusted to WDDM mode if needed
483 * on display service initialization when it detects the display driver type.
484 */
485#endif
486
487 if (dwErr == NO_ERROR)
488 {
489 int rc = vboxTrayStartServices(&svcEnv, vboxServiceTable);
490 if (RT_FAILURE (rc))
491 {
492 dwErr = ERROR_GEN_FAILURE;
493 }
494 }
495
496 /* terminate service if something went wrong */
497 if (dwErr != NO_ERROR)
498 {
499 vboxTrayStopServices(&svcEnv, vboxServiceTable);
500 return;
501 }
502
503 int rc = vboxTrayCreateTrayIcon();
504 if ( RT_SUCCESS(rc)
505 && gMajorVersion >= 5) /* Only for W2K and up ... */
506 {
507 /* We're ready to create the tooltip balloon. */
508 /* Check in 10 seconds (@todo make seconds configurable) ... */
509 SetTimer(gToolWindow,
510 TIMERID_VBOXTRAY_CHECK_HOSTVERSION,
511 10 * 1000, /* 10 seconds */
512 NULL /* No timerproc */);
513 }
514
515 /* Do the Shared Folders auto-mounting stuff. */
516 VBoxSharedFoldersAutoMount();
517
518 /* Boost thread priority to make sure we wake up early for seamless window notifications (not sure if it actually makes any difference though) */
519 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
520
521 /*
522 * Main execution loop
523 * Wait for the stop semaphore to be posted or a window event to arrive
524 */
525
526 DWORD dwEventCount = 2;
527 HANDLE hWaitEvent[2] = {gStopSem, ghSeamlessNotifyEvent};
528
529 if (0 == ghSeamlessNotifyEvent) /* If seamless mode is not active / supported, reduce event array count */
530 dwEventCount = 1;
531
532 Log(("VBoxTray: Number of events to wait in main loop: %ld\n", dwEventCount));
533 while (true)
534 {
535 DWORD waitResult = MsgWaitForMultipleObjectsEx(dwEventCount, hWaitEvent, 500, QS_ALLINPUT, 0);
536 waitResult = waitResult - WAIT_OBJECT_0;
537
538 /* Only enable for message debugging, lots of traffic! */
539 //Log(("VBoxTray: Wait result = %ld\n", waitResult));
540
541 if (waitResult == 0)
542 {
543 Log(("VBoxTray: Event 'Exit' triggered\n"));
544 /* exit */
545 break;
546 }
547 else if ( (waitResult == 1)
548 && (ghSeamlessNotifyEvent!=0)) /* Only jump in, if seamless is active! */
549 {
550 Log(("VBoxTray: Event 'Seamless' triggered\n"));
551
552 /* seamless window notification */
553 VBoxSeamlessCheckWindows();
554 }
555 else
556 {
557 /* timeout or a window message, handle it */
558 MSG msg;
559 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
560 {
561 Log(("VBoxTray: msg %p\n", msg.message));
562 if (msg.message == WM_QUIT)
563 {
564 Log(("VBoxTray: WM_QUIT!\n"));
565 SetEvent(gStopSem);
566 continue;
567 }
568 TranslateMessage(&msg);
569 DispatchMessage(&msg);
570 }
571 }
572 }
573
574 Log(("VBoxTray: Returned from main loop, exiting ...\n"));
575
576 vboxTrayRemoveTrayIcon();
577
578 Log(("VBoxTray: Waiting for display change thread ...\n"));
579
580 vboxTrayStopServices(&svcEnv, vboxServiceTable);
581
582 Log(("VBoxTray: Destroying tool window ...\n"));
583
584 /* Destroy the tool window. */
585 DestroyWindow(gToolWindow);
586
587 UnregisterClass("VBoxTrayToolWndClass", gInstance);
588
589 CloseHandle(gVBoxDriver);
590 CloseHandle(gStopSem);
591 CloseHandle(ghSeamlessNotifyEvent);
592
593 Log(("VBoxTray: Leaving service main function\n"));
594
595 return;
596}
597
598
599/**
600 * Main function
601 */
602int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
603{
604 /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */
605 HANDLE hMutexAppRunning = CreateMutex(NULL, FALSE, "VBoxTray");
606 if ( hMutexAppRunning != NULL
607 && GetLastError() == ERROR_ALREADY_EXISTS)
608 {
609 /* Close the mutex for this application instance. */
610 CloseHandle (hMutexAppRunning);
611 hMutexAppRunning = NULL;
612 return 0;
613 }
614
615 int rc = RTR3Init();
616 if (RT_FAILURE(rc))
617 return rc;
618
619 rc = VbglR3Init();
620 if (RT_FAILURE(rc))
621 return rc;
622
623 LogRel(("VBoxTray: %s r%s started\n", RTBldCfgVersion(), RTBldCfgRevisionStr()));
624
625 gInstance = hInstance;
626 VBoxServiceStart();
627
628 LogRel(("VBoxTray: Ended\n"));
629
630 /* Release instance mutex. */
631 if (hMutexAppRunning != NULL)
632 {
633 CloseHandle(hMutexAppRunning);
634 hMutexAppRunning = NULL;
635 }
636
637 VbglR3Term();
638 return 0;
639}
640
641/**
642 * Window procedure for our tool window
643 */
644LRESULT CALLBACK VBoxToolWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
645{
646 switch (uMsg)
647 {
648 case WM_CREATE:
649 {
650 Log(("VBoxTray: Tool window created\n"));
651
652 int rc = vboxTrayRegisterGlobalMessages(&s_vboxGlobalMessageTable[0]);
653 if (RT_FAILURE(rc))
654 Log(("VBoxTray: Error registering global window messages, rc=%Rrc\n", rc));
655 return 0;
656 }
657
658 case WM_CLOSE:
659 return 0;
660
661 case WM_DESTROY:
662 Log(("VBoxTray: Tool window destroyed\n"));
663 KillTimer(gToolWindow, TIMERID_VBOXTRAY_CHECK_HOSTVERSION);
664 return 0;
665
666 case WM_TIMER:
667 switch (wParam)
668 {
669 case TIMERID_VBOXTRAY_CHECK_HOSTVERSION:
670 if (RT_SUCCESS(VBoxCheckHostVersion()))
671 {
672 /* After successful run we don't need to check again. */
673 KillTimer(gToolWindow, TIMERID_VBOXTRAY_CHECK_HOSTVERSION);
674 }
675 return 0;
676
677 default:
678 break;
679 }
680 break; /* Make sure other timers get processed the usual way! */
681
682 case WM_VBOXTRAY_TRAY_ICON:
683 switch (lParam)
684 {
685 case WM_LBUTTONDBLCLK:
686 break;
687
688 case WM_RBUTTONDOWN:
689 break;
690 }
691 return 0;
692
693 case WM_VBOX_INSTALL_SEAMLESS_HOOK:
694 VBoxSeamlessInstallHook();
695 return 0;
696
697 case WM_VBOX_REMOVE_SEAMLESS_HOOK:
698 VBoxSeamlessRemoveHook();
699 return 0;
700
701 case WM_VBOX_SEAMLESS_UPDATE:
702 VBoxSeamlessCheckWindows();
703 return 0;
704
705 case WM_VBOXTRAY_VM_RESTORED:
706 VBoxRestoreSession();
707 return 0;
708
709 case WM_VBOXTRAY_VRDP_CHECK:
710 VBoxRestoreCheckVRDP();
711 return 0;
712
713 default:
714
715 /* Handle all globally registered window messages. */
716 if (vboxTrayHandleGlobalMessages(&s_vboxGlobalMessageTable[0], uMsg,
717 wParam, lParam))
718 {
719 return 0; /* We handled the message. @todo Add return value!*/
720 }
721 break; /* We did not handle the message, dispatch to DefWndProc. */
722 }
723
724 /* Only if message was *not* handled by our switch above, dispatch
725 * to DefWindowProc. */
726 return DefWindowProc(hWnd, uMsg, wParam, lParam);
727}
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