VirtualBox

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

Last change on this file since 34079 was 34025, checked in by vboxsync, 14 years ago

VBoxTray: Implemented global message registration/handling mechanism, added a global message for sending external messages to the systray balloon, refactoring, some bugfixes.

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