VBoxGuestInstallHelper.cpp revision 9b26f96bcfeda631b89494cf2f5c31529f2e1419
af062818b47340eef15700d2f0211576ba3506eevboxsync/* $Id$ */
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @file
af062818b47340eef15700d2f0211576ba3506eevboxsync * VBoxGuestInstallHelper - Various helper routines for Windows guest installer.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2010 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#include <windows.h>
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include <stdlib.h>
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync#include <Strsafe.h>
4b9d6701570cb98fd36e209314239d104ec584d3vboxsync#include "exdll.h"
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync/* Required structures/defines of VBoxTray. */
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include "../../VBoxTray/VBoxTrayMsg.h"
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncHINSTANCE g_hInstance;
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsyncHWND g_hwndParent;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#define VBOXINSTALLHELPER_EXPORT extern "C" void __declspec(dllexport)
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/**
af062818b47340eef15700d2f0211576ba3506eevboxsync * Pops (gets) a value from the internal NSIS stack.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Since the supplied popstring() method easily can cause buffer
af062818b47340eef15700d2f0211576ba3506eevboxsync * overflows, use VBoxPopString() instead!
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * @return HRESULT
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param pszDest Pointer to pre-allocated string to store result.
af062818b47340eef15700d2f0211576ba3506eevboxsync * @param cchDest Size (in characters) of pre-allocated string.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic HRESULT VBoxPopString(TCHAR *pszDest, size_t cchDest)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync HRESULT hr = S_OK;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!g_stacktop || !*g_stacktop)
af062818b47340eef15700d2f0211576ba3506eevboxsync hr = ERROR_EMPTY;
af062818b47340eef15700d2f0211576ba3506eevboxsync else
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync stack_t *pStack = (*g_stacktop);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pStack)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync hr = StringCchCopy(pszDest, cchDest, pStack->text);
if (SUCCEEDED(hr))
{
*g_stacktop = pStack->next;
GlobalFree((HGLOBAL)pStack);
}
}
}
return hr;
}
static HRESULT VBoxPopULong(ULONG *pulValue)
{
HRESULT hr = S_OK;
if (!g_stacktop || !*g_stacktop)
hr = ERROR_EMPTY;
else
{
stack_t *pStack = (*g_stacktop);
if (pStack)
{
*pulValue = strtoul(pStack->text, NULL, 10 /* Base */);
*g_stacktop = pStack->next;
GlobalFree((HGLOBAL)pStack);
}
}
return hr;
}
HANDLE VBoIPCConnect()
{
HANDLE hPipe = NULL;
while (1)
{
hPipe = CreateFile(VBOXTRAY_PIPE_IPC, /* Pipe name. */
GENERIC_READ | /* Read and write access. */
GENERIC_WRITE,
0, /* No sharing. */
NULL, /* Default security attributes. */
OPEN_EXISTING, /* Opens existing pipe. */
0, /* Default attributes. */
NULL); /* No template file. */
/* Break if the pipe handle is valid. */
if (hPipe != INVALID_HANDLE_VALUE)
break;
/* Exit if an error other than ERROR_PIPE_BUSY occurs. */
if (GetLastError() != ERROR_PIPE_BUSY)
return NULL;
/* All pipe instances are busy, so wait for 20 seconds. */
if (!WaitNamedPipe(VBOXTRAY_PIPE_IPC, 20000))
return NULL;
}
/* The pipe connected; change to message-read mode. */
DWORD dwMode = PIPE_READMODE_MESSAGE;
BOOL fSuccess = SetNamedPipeHandleState(hPipe, /* Pipe handle. */
&dwMode, /* New pipe mode. */
NULL, /* Don't set maximum bytes. */
NULL); /* Don't set maximum time. */
if (!fSuccess)
return NULL;
return hPipe;
}
void VBoxIPCDisconnect(HANDLE hPipe)
{
CloseHandle(hPipe);
}
HRESULT VBoxIPCWriteMessage(HANDLE hPipe, BYTE *pMessage, DWORD cbMessage)
{
HRESULT hr = S_OK;
DWORD cbWritten = 0;
if (!WriteFile(hPipe, pMessage, cbMessage - cbWritten, &cbWritten, 0))
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
/**
* Shows a balloon message using VBoxTray's notification area in the
* Windows task bar.
*
* @param hwndParent Window handle of parent.
* @param string_size Size of variable string.
* @param variables The actual variable string.
* @param stacktop Pointer to a pointer to the current stack.
*/
VBOXINSTALLHELPER_EXPORT VBoxTrayShowBallonMsg(HWND hwndParent, int string_size,
TCHAR *variables, stack_t **stacktop)
{
EXDLL_INIT();
VBOXTRAYIPCHEADER hdr;
hdr.ulMsg = VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG;
VBOXTRAYIPCMSG_SHOWBALLOONMSG msg;
HRESULT hr = VBoxPopString(msg.szBody, sizeof(msg.szBody) / sizeof(TCHAR));
if (SUCCEEDED(hr))
hr = VBoxPopString(msg.szTitle, sizeof(msg.szTitle) / sizeof(TCHAR));
if (SUCCEEDED(hr))
hr = VBoxPopULong(&msg.ulType);
if (SUCCEEDED(hr))
hr = VBoxPopULong(&msg.ulShowMS);
if (SUCCEEDED(hr))
{
msg.ulFlags = 0;
HANDLE hPipe = VBoIPCConnect();
if (hPipe)
{
hr = VBoxIPCWriteMessage(hPipe, (BYTE*)&hdr, sizeof(VBOXTRAYIPCHEADER));
if (SUCCEEDED(hr))
hr = VBoxIPCWriteMessage(hPipe, (BYTE*)&msg, sizeof(VBOXTRAYIPCMSG_SHOWBALLOONMSG));
VBoxIPCDisconnect(hPipe);
}
}
/* Push simple return value on stack. */
SUCCEEDED(hr) ? pushstring("0") : pushstring("1");
}
BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID lpReserved)
{
g_hInstance = (HINSTANCE)hInst;
return TRUE;
}