WindowsXP-SP1/enduser/netmeeting/ui/conf/setupdd.cpp
2020-09-30 16:53:49 +02:00

375 lines
9.0 KiB
C++

/*
* SETUPDD.CPP
*
* The code to install the NM display driver for Windows NT. This was
* a standalone application launched by Setup that we are now importing
* into NM itself.
*
* Author:
* dannygl, 05 Apr 97
*/
#include "precomp.h"
#include "conf.h"
#include "confwnd.h"
#include "resource.h"
#include "setupdd.h"
// String to identify the DLL and function that we need to call to install
// the display driver on SP3.
const TCHAR g_pcszDisplayCPLName[] = TEXT("DESK.CPL");
const CHAR g_pcszInstallDriverAPIName[] = "InstallGraphicsDriver";
const WCHAR g_pcwszDefaultModelName[] = L"Microsoft NetMeeting graphics driver";
const WCHAR g_pcwszDefaultINFName[] = L"MNMDD.INF";
// Maxmimum size of the model name string
const int NAME_BUFFER_SIZE = 128;
// Prototype for the function installed by the Display CPL
typedef DWORD (*PFNINSTALLGRAPHICSDRIVER)(
HWND hwnd,
LPCWSTR pszSourceDirectory,
LPCWSTR pszModel,
LPCWSTR pszInf
);
/*
* GetInstallDisplayDriverEntryPoint
*
* This function loads the DLL containing the display driver installation
* code and retrieves the entry point for the installation function. It
* is used by the below functions as a utility function.
*
* It returns TRUE if it is able to load the library and get the entry point,
* FALSE if either operation fails. It is returns TRUE, it also returns the
* DLL module handle and the function address.
*/
BOOL
GetInstallDisplayDriverEntryPoint(
HMODULE *phInstallDDDll,
PFNINSTALLGRAPHICSDRIVER *ppfnInstallDDFunction)
{
HMODULE hDll;
PFNINSTALLGRAPHICSDRIVER pfn = NULL;
ASSERT(NULL != phInstallDDDll
&& NULL != ppfnInstallDDFunction);
hDll = LoadLibrary(g_pcszDisplayCPLName);
if (NULL != hDll)
{
pfn = (PFNINSTALLGRAPHICSDRIVER)
GetProcAddress(hDll,
g_pcszInstallDriverAPIName);
}
// If the entry point exists, we pass it and the DLL handle back to
// the caller. Otherwise, we unload the DLL immediately.
if (NULL != pfn)
{
*phInstallDDDll = hDll;
*ppfnInstallDDFunction = pfn;
return TRUE;
}
else
{
if (NULL != hDll)
{
FreeLibrary(hDll);
}
return FALSE;
}
}
/*
* CanInstallNTDisplayDriver
*
* This function determines whether the entry point for installing the
* NT display driver is availalble (i.e. NT 4.0 SP3 or later).
*/
BOOL
CanInstallNTDisplayDriver(void)
{
static BOOL fComputed = FALSE;
static BOOL fRet = FALSE;
ASSERT(::IsWindowsNT());
// We verify that the major version number is exactly 4 and either
// the minor version number is greater than 0 or the service pack
// number (which is stored in the high byte of the low word of the
// CSD version) is 3 or greater.
if (! fComputed)
{
LPOSVERSIONINFO lposvi = GetVersionInfo();
if (4 == lposvi->dwMajorVersion)
{
if (0 == lposvi->dwMinorVersion)
{
RegEntry re(NT_WINDOWS_SYSTEM_INFO_KEY, HKEY_LOCAL_MACHINE, FALSE);
DWORD dwCSDVersion =
re.GetNumber(REGVAL_NT_CSD_VERSION, 0);
if (3 <= HIBYTE(LOWORD(dwCSDVersion)))
{
// This is NT 4.0, SP 3 or later
fRet = TRUE;
}
}
else
{
// We assume that any future version of Windows NT 4.x (x > 0)
// will support this.
fRet = TRUE;
}
}
fComputed = TRUE;
}
ASSERT(fComputed);
return fRet;
}
/*
* OnEnableAppSharing
*
* Invoked when the "Enable Application Sharing" menu item is selected.
*
* This function determines whether the entry point for installing the
* NT display driver is available. If so, it prompts the user to confirm
* this operation, proceeds with the installation, and then prompts the
* user to restart the computer.
*
* If not, it presents a text dialog with information about how to get
* the necessary NT Service Pack(s).
*/
void
OnEnableAppSharing(
HWND hWnd)
{
ASSERT(::IsWindowsNT());
USES_CONVERSION;
if (::CanInstallNTDisplayDriver())
{
// Confirm the installation with the user
if (IDYES == ::ConfMsgBox(
hWnd,
(LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_CONFIRM,
MB_YESNO | MB_ICONQUESTION))
{
BOOL fDriverInstallSucceeded = FALSE;
HMODULE hDisplayCPL = NULL;
PFNINSTALLGRAPHICSDRIVER pfnInstallGraphicsDriver;
TCHAR pszSourcePath[MAX_PATH];
LPWSTR pwszSourcePath = NULL;
LPWSTR pwszSourcePathEnd;
WCHAR pwszModelNameBuffer[NAME_BUFFER_SIZE];
LPCWSTR pcwszModelName;
WCHAR pwszINFNameBuffer[MAX_PATH];
LPCWSTR pcwszINFName;
// Get the entry point for display driver installation
if (! ::GetInstallDisplayDriverEntryPoint(
&hDisplayCPL,
&pfnInstallGraphicsDriver))
{
ERROR_OUT(("GetInstallDisplayDriverEntryPoint() fails"));
goto OEAS_AbortInstall;
}
// The driver files are located in the NM directory.
if (! ::GetInstallDirectory(pszSourcePath))
{
ERROR_OUT(("GetInstallDirectory() fails"));
goto OEAS_AbortInstall;
}
// Convert the install directory to Unicode, if necessary
pwszSourcePath = T2W(pszSourcePath);
if (NULL == pwszSourcePath)
{
ERROR_OUT(("AnsiToUnicode() fails"));
goto OEAS_AbortInstall;
}
// Strip the trailing backslash that GetInstallDirectory appends
pwszSourcePathEnd = pwszSourcePath + lstrlenW(pwszSourcePath);
// Handle X:\, just to be safe
if (pwszSourcePathEnd - pwszSourcePath > 3)
{
ASSERT(L'\\' == *(pwszSourcePathEnd - 1));
*--pwszSourcePathEnd = L'\0';
}
// Read the model name string from the resource file
if (0 < ::LoadStringW(GetInstanceHandle(),
IDS_NMDD_DISPLAYNAME,
pwszModelNameBuffer,
CCHMAX(pwszModelNameBuffer)))
{
pcwszModelName = pwszModelNameBuffer;
}
else
{
ERROR_OUT(("LoadStringW() fails, err=%lu", GetLastError()));
pcwszModelName = g_pcwszDefaultModelName;
}
// Read the INF name string from the resource file
if (0 < ::LoadStringW(GetInstanceHandle(),
IDS_NMDD_INFNAME,
pwszINFNameBuffer,
CCHMAX(pwszINFNameBuffer)))
{
pcwszINFName = pwszINFNameBuffer;
}
else
{
ERROR_OUT(("LoadStringW() fails, err=%lu", GetLastError()));
pcwszINFName = g_pcwszDefaultINFName;
}
// Now we're set to call the actual installation function
DWORD dwErr;
dwErr = (*pfnInstallGraphicsDriver)(hWnd,
pwszSourcePath,
pcwszModelName,
pcwszINFName);
if (dwErr)
{
WARNING_OUT(("InstallGraphicsDriver() fails, err=%lu", dwErr));
}
if (ERROR_SUCCESS == dwErr)
{
fDriverInstallSucceeded = TRUE;
g_fNTDisplayDriverEnabled = TRUE;
}
OEAS_AbortInstall:
// If we failed to install the driver, we report an error.
// If we succeeded, we prompt the user to restart the system.
if (! fDriverInstallSucceeded)
{
::ConfMsgBox(
hWnd,
(LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_FAILURE,
MB_OK | MB_ICONERROR);
}
else if (IDYES == ::ConfMsgBox(
hWnd,
(LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_COMPLETE,
MB_YESNO | MB_ICONQUESTION))
{
// Initiate a system restart. This involves getting the
// necessary privileges first.
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL fRet;
// Get the current process token handle so we can get shutdown
// privilege.
fRet = OpenProcessToken(
GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken);
// Get the LUID for shutdown privilege.
if (fRet)
{
fRet = LookupPrivilegeValue(
NULL,
SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
}
else
{
hToken = NULL;
WARNING_OUT(("OpenProcessToken() fails (error %lu)", GetLastError()));
}
// Get shutdown privilege for this process.
if (fRet)
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
fRet = AdjustTokenPrivileges(
hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES) NULL,
0);
// Special-case scenario where call succeeds but not all
// privileges were set.
if (fRet && ERROR_SUCCESS != GetLastError())
{
fRet = FALSE;
}
}
else
{
WARNING_OUT(("LookupPrivilegeValue() fails (error %lu)", GetLastError()));
}
if (! fRet)
{
WARNING_OUT(("AdjustTokenPrivileges() fails (error %lu)", GetLastError()));
}
if (NULL != hToken)
{
CloseHandle(hToken);
}
if (! ::ExitWindowsEx(EWX_REBOOT, 0))
{
WARNING_OUT(("ExitWindowsEx() fails (error %lu)", GetLastError()));
}
}
if (NULL != hDisplayCPL)
{
FreeLibrary(hDisplayCPL);
}
}
}
else
{
// Tell the user how to get the SP
::ConfMsgBox(
hWnd,
(LPCTSTR) IDS_ENABLEAPPSHARING_NEEDNTSP);
}
return;
}