VirtualBox

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

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

*,IPRT: Redid the ring-3 init to always convert the arguments to UTF-8.

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