402 lines
15 KiB
C
402 lines
15 KiB
C
|
//-----------------------------------------------------------------------------
|
||
|
// File: DInstall.c
|
||
|
//
|
||
|
// Desc: Example code showing how to use DirectXSetup.
|
||
|
//
|
||
|
// This file contains code that will handle all messages sent to the
|
||
|
// DirectXSetupCallbackFunction, with the filtering level set at what the
|
||
|
// user wants. This way you can test to see which messages you want to
|
||
|
// handle automatically or pass on to the user.
|
||
|
//
|
||
|
// Call Tree:
|
||
|
// DirectXInstallWndProc SEE WINCODE.C
|
||
|
// DirectXInstall Set up the callback and handle return codes
|
||
|
// GetReply SEE WINCODE.C
|
||
|
// DirectXGetVersion Display the results of DirectXSetupGetVersion()
|
||
|
// DirectXSetupCallbackFunction Called from DirectXSetup
|
||
|
// GetReply SEE WINCODE.C
|
||
|
// SetButtons SEE WINCODE.C
|
||
|
// ShowButton SEE WINCODE.C
|
||
|
//
|
||
|
// Copyright (c) 1998 Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <dsetup.h>
|
||
|
#include "resource.h"
|
||
|
#include "dinstall.h"
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Externs for global variables
|
||
|
//-----------------------------------------------------------------------------
|
||
|
extern DWORD g_fStatus; // filter setting for messages from DirectXSetup
|
||
|
extern HINSTANCE g_hInstance; // global instance handle
|
||
|
extern HWND g_hDlg; // window handle to dialog proc
|
||
|
extern char g_szAppTitle[256]; // application title
|
||
|
extern int g_wReply; // global value for dialog return
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: GetReply(DWORD )
|
||
|
// Desc: Waits for the user to click on a button on our simulated message box
|
||
|
// See DlgProc for the code that sets g_wReply
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int
|
||
|
GetReply(DWORD dwMsgType)
|
||
|
{
|
||
|
WORD wDefaultButton = 0;
|
||
|
|
||
|
// Wait until DlgProc() lets us know that the user clicked on a button
|
||
|
while (g_wReply == -1)
|
||
|
{
|
||
|
MSG msg;
|
||
|
|
||
|
// Forward my messages...
|
||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||
|
{
|
||
|
if (msg.message == WM_QUIT ||
|
||
|
msg.message == WM_CLOSE ||
|
||
|
msg.message == WM_SYSCOMMAND ||
|
||
|
msg.message == WM_DESTROY)
|
||
|
{
|
||
|
// Put the message back on the queue and get out of here.
|
||
|
PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||
|
break;
|
||
|
}
|
||
|
if (!IsDialogMessage(msg.hwnd, &msg))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return the proper ID value for the button the user clicked on
|
||
|
// This code simulates what MessageBox() would return
|
||
|
switch (dwMsgType & 0x0000000F)
|
||
|
{
|
||
|
case MB_OKCANCEL:
|
||
|
wDefaultButton = (g_wReply == IDBUT1) ? IDOK : IDCANCEL;
|
||
|
break;
|
||
|
case MB_OK:
|
||
|
wDefaultButton = IDOK;
|
||
|
break;
|
||
|
case MB_RETRYCANCEL:
|
||
|
wDefaultButton = (g_wReply == IDBUT1) ? IDRETRY : IDCANCEL;
|
||
|
break;
|
||
|
case MB_ABORTRETRYIGNORE:
|
||
|
if (g_wReply == IDBUT1)
|
||
|
wDefaultButton = IDABORT;
|
||
|
else if (g_wReply == IDBUT2)
|
||
|
wDefaultButton = IDRETRY;
|
||
|
else
|
||
|
wDefaultButton = IDIGNORE;
|
||
|
break;
|
||
|
case MB_YESNOCANCEL:
|
||
|
if (g_wReply == IDBUT1)
|
||
|
wDefaultButton = IDYES;
|
||
|
else if (g_wReply == IDBUT2)
|
||
|
wDefaultButton = IDNO;
|
||
|
else
|
||
|
wDefaultButton = IDCANCEL;
|
||
|
break;
|
||
|
case MB_YESNO:
|
||
|
wDefaultButton = (g_wReply == IDBUT1) ? IDYES : IDNO;
|
||
|
break;
|
||
|
default:
|
||
|
wDefaultButton = IDOK;
|
||
|
}
|
||
|
g_wReply = -1;
|
||
|
return wDefaultButton;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: DirectXSetupCallbackFunction(DWORD , DWORD , LPSTR , LPSTR , void *)
|
||
|
// Desc: Handle each reason for why the callback was called, filtering each
|
||
|
// message by what the current state of g_fStatus is.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
DWORD WINAPI
|
||
|
DirectXSetupCallbackFunction(DWORD dwReason, DWORD dwMsgType, LPSTR szMessage, LPSTR
|
||
|
szName, void *pInfo)
|
||
|
{
|
||
|
if (szMessage == NULL && szName == NULL)
|
||
|
return IDOK;
|
||
|
SetButtons(g_hDlg, -1);
|
||
|
if (g_fStatus == SHOW_ALL)
|
||
|
{
|
||
|
//---------------------------------------------------------------------
|
||
|
// Show all messages from DirectSetup
|
||
|
//---------------------------------------------------------------------
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), szMessage);
|
||
|
// When dwMsgType is equal to zero we can display status information but
|
||
|
// should not wait for input from the user.
|
||
|
if (dwMsgType == 0)
|
||
|
{
|
||
|
Sleep(1000);
|
||
|
return IDOK;
|
||
|
}
|
||
|
else
|
||
|
SetButtons(g_hDlg, dwMsgType);
|
||
|
}
|
||
|
else if (g_fStatus == SHOW_UPGRADES)
|
||
|
{
|
||
|
//---------------------------------------------------------------------
|
||
|
// Show only upgrade messages
|
||
|
//---------------------------------------------------------------------
|
||
|
switch (dwReason)
|
||
|
{
|
||
|
case DSETUP_CB_MSG_SETUP_INIT_FAILED:
|
||
|
case DSETUP_CB_MSG_INTERNAL_ERROR:
|
||
|
case DSETUP_CB_MSG_OUTOFDISKSPACE:
|
||
|
case DSETUP_CB_MSG_FILECOPYERROR:
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), szMessage);
|
||
|
SetButtons(g_hDlg, dwMsgType);
|
||
|
break;
|
||
|
case DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE:
|
||
|
{
|
||
|
// pInfo points to a structure containing flags that summarize
|
||
|
// the DirectXSetup functions recommendation on how the upgrade
|
||
|
// of DirectX components and drivers should be preformed
|
||
|
DWORD dwUpgrade = ((DSETUP_CB_UPGRADEINFO *) pInfo)->UpgradeFlags
|
||
|
& DSETUP_CB_UPGRADE_TYPE_MASK;
|
||
|
switch (dwUpgrade)
|
||
|
{
|
||
|
case DSETUP_CB_UPGRADE_FORCE:
|
||
|
case DSETUP_CB_UPGRADE_KEEP:
|
||
|
case DSETUP_CB_UPGRADE_SAFE:
|
||
|
case DSETUP_CB_UPGRADE_UNKNOWN:
|
||
|
{
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), szMessage);
|
||
|
SetButtons(g_hDlg, dwMsgType);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
return IDOK;
|
||
|
}
|
||
|
}
|
||
|
else if (g_fStatus == SHOW_PROBLEMS)
|
||
|
{
|
||
|
//---------------------------------------------------------------------
|
||
|
// Show only problem messages
|
||
|
//---------------------------------------------------------------------
|
||
|
switch (dwReason)
|
||
|
{
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_UNKNOWNOS:
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_NT:
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_BETA:
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_NOTWIN32:
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_WRONGLANGUAGE:
|
||
|
case DSETUP_CB_MSG_CANTINSTALL_WRONGPLATFORM:
|
||
|
case DSETUP_CB_MSG_PREINSTALL_NT:
|
||
|
case DSETUP_CB_MSG_NOTPREINSTALLEDONNT:
|
||
|
case DSETUP_CB_MSG_SETUP_INIT_FAILED:
|
||
|
case DSETUP_CB_MSG_INTERNAL_ERROR:
|
||
|
case DSETUP_CB_MSG_OUTOFDISKSPACE:
|
||
|
case DSETUP_CB_MSG_FILECOPYERROR:
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), szMessage);
|
||
|
SetButtons(g_hDlg, dwMsgType);
|
||
|
break;
|
||
|
case DSETUP_CB_MSG_CHECK_DRIVER_UPGRADE:
|
||
|
{
|
||
|
DWORD dwUpgrade = ((DSETUP_CB_UPGRADEINFO *) pInfo)->UpgradeFlags
|
||
|
& DSETUP_CB_UPGRADE_TYPE_MASK;
|
||
|
switch (dwUpgrade)
|
||
|
{
|
||
|
case DSETUP_CB_UPGRADE_FORCE:
|
||
|
case (DSETUP_CB_UPGRADE_SAFE & DSETUP_CB_UPGRADE_HASWARNINGS):
|
||
|
case DSETUP_CB_UPGRADE_UNKNOWN:
|
||
|
{
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), szMessage);
|
||
|
SetButtons(g_hDlg, dwMsgType);
|
||
|
break;
|
||
|
}
|
||
|
case DSETUP_CB_UPGRADE_KEEP:
|
||
|
return IDOK;
|
||
|
case DSETUP_CB_UPGRADE_SAFE:
|
||
|
switch (dwMsgType & 0x0000000F)
|
||
|
{
|
||
|
case MB_YESNO:
|
||
|
case MB_YESNOCANCEL:
|
||
|
return IDYES;
|
||
|
case MB_OKCANCEL:
|
||
|
case MB_OK:
|
||
|
default:
|
||
|
return IDOK;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
return IDOK;
|
||
|
}
|
||
|
}
|
||
|
else if (g_fStatus == SHOW_NONE)
|
||
|
{
|
||
|
//---------------------------------------------------------------------
|
||
|
// Don't show any messages
|
||
|
//---------------------------------------------------------------------
|
||
|
return IDOK;
|
||
|
}
|
||
|
return GetReply(dwMsgType);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: DirectXGetVersion(void )
|
||
|
// Desc: Shows the results of a call to DirectXSetupGetVersion()
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void
|
||
|
DirectXGetVersion(void )
|
||
|
{
|
||
|
INT iret;
|
||
|
DWORD dwVersion;
|
||
|
DWORD dwRevision;
|
||
|
char szBuf[128];
|
||
|
|
||
|
iret = DirectXSetupGetVersion(&dwVersion, &dwRevision);
|
||
|
sprintf(szBuf, "Version 0x%08lX\nRevision %ld", dwVersion, dwRevision);
|
||
|
// Use HIWORD(dwVersion); to get the DirectX major version
|
||
|
// Use LOWORD(dwVersion); to get the DirectX minor version
|
||
|
// For example:
|
||
|
// dwVersion ==
|
||
|
// DirectX 1: 0x00040001
|
||
|
// DirectX 2: 0x00040002
|
||
|
// DirectX 3: 0x00040003
|
||
|
// DirectX 5: 0x00040005
|
||
|
// DirectX 6: 0x00040006
|
||
|
MessageBox(NULL, szBuf, "Results:", MB_OK | MB_ICONINFORMATION);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: DirectXInstall(HWND )
|
||
|
// Desc: Set up the callback function for DirectXSetup and handle the return
|
||
|
// results. This function starts a modeless version of MessageBox() so
|
||
|
// that the user can see the progress of the DirectX installation.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
DirectXInstall(HWND hWnd)
|
||
|
{
|
||
|
char szSource[_MAX_PATH];
|
||
|
char string[256];
|
||
|
int retc;
|
||
|
|
||
|
// The DSETUP DLLs should be at the current path, along with the DirectX
|
||
|
// redist directory so that it can be found and set up. Otherwise, change
|
||
|
// the code below to reflect the real path.
|
||
|
GetCurrentDirectory(_MAX_PATH, szSource);
|
||
|
|
||
|
// If the user wants any messages, bring up the simulated MessageBox
|
||
|
// dialog
|
||
|
if (g_fStatus != SHOW_NONE)
|
||
|
{
|
||
|
// Create a modeless dialog box so we can show messages that don't
|
||
|
// need user input
|
||
|
g_hDlg = CreateDialog(g_hInstance, "INSTDX", hWnd, (DLGPROC) DlgProc);
|
||
|
if (g_hDlg == NULL)
|
||
|
{
|
||
|
char buf[200];
|
||
|
|
||
|
LoadString(g_hInstance, STR_NODIALOG, buf, 200);
|
||
|
MessageBox(hWnd, string, g_szAppTitle, MB_ICONSTOP | MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT1), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT2), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT3), SW_HIDE);
|
||
|
ShowWindow(g_hDlg, SW_NORMAL);
|
||
|
}
|
||
|
|
||
|
// Set the callback function up before calling DirectXSetup
|
||
|
DirectXSetupSetCallback((DSETUP_CALLBACK) DirectXSetupCallbackFunction);
|
||
|
if (g_fStatus != SHOW_NONE)
|
||
|
{
|
||
|
LoadString(g_hInstance, STR_STARTSETUP, string, 256);
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), string);
|
||
|
SetButtons(g_hDlg, -1);
|
||
|
Sleep(1000);
|
||
|
}
|
||
|
|
||
|
// INSTALL DIRECTX
|
||
|
|
||
|
retc = DirectXSetup(hWnd, szSource, DSETUP_DIRECTX);// | DSETUP_TESTINSTALL);
|
||
|
|
||
|
// If the user didn't want any message, we now need to bring up the dialog
|
||
|
// to reflect the return message from DirectXSetup
|
||
|
if (g_fStatus == SHOW_NONE)
|
||
|
{
|
||
|
g_hDlg = CreateDialog(g_hInstance, "INSTDX", hWnd, (DLGPROC) DlgProc);
|
||
|
if (g_hDlg == NULL)
|
||
|
{
|
||
|
char buf[200];
|
||
|
|
||
|
LoadString(g_hInstance, STR_NODIALOG, buf, 200);
|
||
|
MessageBox(hWnd, string, g_szAppTitle, MB_ICONSTOP | MB_OK);
|
||
|
return FALSE;
|
||
|
}
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT1), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT2), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(g_hDlg, IDBUT3), SW_HIDE);
|
||
|
ShowWindow(g_hDlg, SW_NORMAL);
|
||
|
}
|
||
|
|
||
|
switch (retc)
|
||
|
{
|
||
|
// Since our MessageBox dialog is still up, display the results in it
|
||
|
case DSETUPERR_SUCCESS_RESTART:
|
||
|
LoadString(g_hInstance, STR_RESTART, string, 256);
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), string);
|
||
|
SetButtons(g_hDlg, -1);
|
||
|
SetButtons(g_hDlg, MB_YESNO);
|
||
|
if (GetReply(MB_YESNO) == IDYES)
|
||
|
{
|
||
|
// Restart Windows
|
||
|
ExitWindowsEx(EWX_REBOOT, 0);
|
||
|
}
|
||
|
break;
|
||
|
case DSETUPERR_SUCCESS:
|
||
|
LoadString(g_hInstance, STR_SUCCESS, string, 256);
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), string);
|
||
|
SetButtons(g_hDlg, -1);
|
||
|
SetButtons(g_hDlg, MB_OK);
|
||
|
GetReply(MB_OK);
|
||
|
break;
|
||
|
case DSETUPERR_BADWINDOWSVERSION:
|
||
|
case DSETUPERR_SOURCEFILENOTFOUND:
|
||
|
case DSETUPERR_BADSOURCESIZE:
|
||
|
case DSETUPERR_BADSOURCETIME:
|
||
|
case DSETUPERR_NOCOPY:
|
||
|
case DSETUPERR_OUTOFDISKSPACE:
|
||
|
case DSETUPERR_CANTFINDINF:
|
||
|
case DSETUPERR_CANTFINDDIR:
|
||
|
case DSETUPERR_INTERNAL:
|
||
|
case DSETUPERR_NTWITHNO3D:
|
||
|
case DSETUPERR_UNKNOWNOS:
|
||
|
case DSETUPERR_USERHITCANCEL:
|
||
|
case DSETUPERR_NOTPREINSTALLEDONNT:
|
||
|
LoadString(g_hInstance, STR_ERRORRETURN + (retc * -1) - 1, string, 256);
|
||
|
SetWindowText(GetDlgItem(g_hDlg, ID_MYMESSAGE), string);
|
||
|
SetButtons(g_hDlg, -1);
|
||
|
SetButtons(g_hDlg, MB_OK);
|
||
|
GetReply(MB_OK);
|
||
|
break;
|
||
|
}
|
||
|
DestroyWindow(g_hDlg);
|
||
|
g_hDlg = NULL;
|
||
|
SendMessage(hWnd, WM_COMMAND, IDEXIT, 0);
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|