VirtualBox

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

Last change on this file since 40498 was 40498, checked in by vboxsync, 13 years ago

VBoxTray: monitor the guest properties

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