windows-nt/Source/XPSP1/NT/inetsrv/iis/setup/util/install/start.cpp
2020-09-26 16:20:57 +08:00

491 lines
15 KiB
C++

//----------------------------------------------
//
// program to use setupapi.dll to install the DefaultInstall section of a install.inf file
//
//----------------------------------------------
#include <tchar.h>
#include <windows.h>
#include <winbase.h>
#include <shlobj.h>
#include <io.h>
#include <stdio.h>
#include <setupapi.h>
#include "resource.h"
#include "advpub.h"
#define MAX_BUFFER 1024
typedef struct _QUEUECONTEXT {
HWND OwnerWindow;
DWORD MainThreadId;
HWND ProgressDialog;
HWND ProgressBar;
BOOL Cancelled;
PTSTR CurrentSourceName;
BOOL ScreenReader;
BOOL MessageBoxUp;
WPARAM PendingUiType;
PVOID PendingUiParameters;
UINT CancelReturnCode;
BOOL DialogKilled;
//
// If the SetupInitDefaultQueueCallbackEx is used, the caller can
// specify an alternate handler for progress. This is useful to
// get the default behavior for disk prompting, error handling, etc,
// but to provide a gas gauge embedded, say, in a wizard page.
//
// The alternate window is sent ProgressMsg once when the copy queue
// is started (wParam = 0. lParam = number of files to copy).
// It is then also sent once per file copied (wParam = 1. lParam = 0).
//
// NOTE: a silent installation (i.e., no progress UI) can be accomplished
// by specifying an AlternateProgressWindow handle of INVALID_HANDLE_VALUE.
//
HWND AlternateProgressWindow;
UINT ProgressMsg;
UINT NoToAllMask;
HANDLE UiThreadHandle;
#ifdef NOCANCEL_SUPPORT
BOOL AllowCancel;
#endif
} QUEUECONTEXT, *PQUEUECONTEXT;
/* ************************ prototypes ***************************** */
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
void MakePath(LPSTR lpPath);
void AddPath(LPSTR szPath, LPCSTR szName );
void MyMessageBox(int WhichString_ID, char g_szFilepath[] = '\0');
BOOL GetThisModulePath( LPSTR lpPath, int size );
int InstallDefaultInfSection(void);
int InstallDefaultInfSection2(void);
HRESULT MyRunSetupCommand(HWND hwnd, LPCSTR lpszInfFile, LPCSTR lpszSection);
/* ************************* globals ******************************* */
HINSTANCE g_hInstance = NULL;
HINSTANCE g_hPrevInstance = NULL;
LPSTR g_lpCmdLine = NULL;
int g_nCmdShow = 0;
/* **************************************************************** */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wcl;
char szWinName[255];
g_hInstance = hInstance;
g_hPrevInstance = hPrevInstance;
g_lpCmdLine = lpCmdLine;
g_nCmdShow = nCmdShow;
LoadString( g_hInstance, IDS_TITLE, szWinName, _MAX_PATH );
// define windows class
wcl.hInstance = hInstance;
wcl.lpszClassName = szWinName;
wcl.lpfnWndProc = WindowFunc;
wcl.style = 0;
wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
wcl.lpszMenuName = NULL;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
// register the window class.
if (!RegisterClass (&wcl)) return 0;
hwnd = CreateWindow(szWinName, NULL, WS_DISABLED | WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, 10, 10, HWND_DESKTOP, NULL, hInstance , NULL);
if (NULL != hwnd)
{
// display the window
ShowWindow(hwnd, nCmdShow);
// Install the inf section
InstallDefaultInfSection();
// Call PostQuit Message
PostQuitMessage(0);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//***************************************************************************
//*
//* purpose: you know what
//*
//***************************************************************************
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
break;
case WM_PAINT:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam, lParam);
}
return 0;
}
//***************************************************************************
//*
//* purpose: TRUE if the file is opened, FALSE if the file does not exists.
//*
//***************************************************************************
int CheckIfFileExists(char * szFileName)
{
char svTemp1[_MAX_PATH];
char *pdest;
strcpy(svTemp1, szFileName);
// cut off the trailing \ if need to
pdest = svTemp1;
if (*(pdest + (strlen(pdest) - 1)) == '\\')
{*(strrchr(svTemp1, '\\')) = '\0';}
if ((_access(svTemp1,0)) != -1)
{return TRUE;}
else
{return FALSE;}
}
//***************************************************************************
//*
//* purpose: display message that we were unable to runthe exe
//*
//***************************************************************************
void MyMessageBox(int WhichString_ID, char g_szFilepath[])
{
TCHAR TempString[_MAX_PATH];
TCHAR TempString1[_MAX_PATH];
TCHAR TempString2[_MAX_PATH];
if(!LoadString(g_hInstance,IDS_ERROR,TempString1,sizeof(TempString1))) {*TempString1 = TEXT('\0');}
if(!LoadString(g_hInstance,WhichString_ID,TempString2,sizeof(TempString2))) {*TempString2 = TEXT('\0');}
strcpy(TempString, "Error");
sprintf(TempString, TempString2, g_szFilepath);
MessageBox(NULL, TempString, TempString1, MB_OK | MB_ICONSTOP);
return;
}
int InstallDefaultInfSection2(void)
{
HWND Window = NULL;
BOOL bError = TRUE; // assume failure.
char szPath[_MAX_PATH];
char szINFFilename_Full[_MAX_PATH];
char szSectionName[_MAX_PATH];
char szINFFilename[_MAX_PATH];
if(!LoadString(NULL,IDS_SECTION_NAME,szSectionName,sizeof(szSectionName)))
{strcpy(szSectionName, "DefaultInstall");}
if(!LoadString(NULL,IDS_INF_FILENAME,szINFFilename,sizeof(szINFFilename)))
{strcpy(szINFFilename, "install.inf");}
// Get the path to setup.exe and strip off filename so we only have the path
GetModuleFileName((HINSTANCE) Window, szPath, _MAX_PATH);
*(strrchr(szPath, '\\') + 1) = '\0';
strcpy(szINFFilename_Full, szPath);
strcat(szINFFilename_Full, szINFFilename);
// Check if the file exists
if (CheckIfFileExists(szINFFilename_Full) == FALSE)
{
MyMessageBox(IDS_UNABLE_TO_FIND, szINFFilename_Full);
}
else
{
MyRunSetupCommand(NULL, szINFFilename_Full, szSectionName);
}
return TRUE;
}
//-------------------------------------------------------------------
// purpose: install default inf section from install.inf file
//-------------------------------------------------------------------
int InstallDefaultInfSection(void)
{
HWND Window = NULL;
PTSTR SourcePath = NULL;
HINF InfHandle = INVALID_HANDLE_VALUE;
HSPFILEQ FileQueue = INVALID_HANDLE_VALUE;
PQUEUECONTEXT QueueContext = NULL;
BOOL bReturn = FALSE;
BOOL bError = TRUE; // assume failure.
TCHAR ActualSection[1000];
DWORD ActualSectionLength;
char szSectionName[_MAX_PATH];
char szINFFilename[_MAX_PATH];
if(!LoadString(NULL,IDS_SECTION_NAME,szSectionName,sizeof(szSectionName)))
{strcpy(szSectionName, "DefaultInstall");}
if(!LoadString(NULL,IDS_INF_FILENAME,szINFFilename,sizeof(szINFFilename)))
{strcpy(szINFFilename, "install.inf");}
__try {
// Get the path to setup.exe and strip off filename so we only have the path
char szPath[_MAX_PATH];
char szINFFilename_Full[_MAX_PATH];
GetModuleFileName((HINSTANCE) Window, szPath, _MAX_PATH);
*(strrchr(szPath, '\\') + 1) = '\0';
strcpy(szINFFilename_Full, szPath);
strcat(szINFFilename_Full, szINFFilename);
SourcePath = szPath;
*(strrchr(SourcePath, '\\') ) = '\0';
// Check if the file exists
if (CheckIfFileExists(szINFFilename_Full) == FALSE)
{
MyMessageBox(IDS_UNABLE_TO_FIND, szINFFilename_Full);
goto c0;
}
//
// Load the inf file and get the handle
//
InfHandle = SetupOpenInfFile(szINFFilename_Full, NULL, INF_STYLE_WIN4, NULL);
if(InfHandle == INVALID_HANDLE_VALUE) {goto c1;}
//
// See if there is an nt-specific section
//
SetupDiGetActualSectionToInstall(InfHandle,szSectionName,ActualSection,sizeof(ActualSection),&ActualSectionLength,NULL);
//
// Create a setup file queue and initialize the default queue callback.
//
FileQueue = SetupOpenFileQueue();
if(FileQueue == INVALID_HANDLE_VALUE) {goto c1;}
//QueueContext = SetupInitDefaultQueueCallback(Window);
//if(!QueueContext) {goto c1;}
QueueContext = (PQUEUECONTEXT) SetupInitDefaultQueueCallbackEx(Window,NULL,0,0,0);
if(!QueueContext) {goto c1;}
QueueContext->PendingUiType = IDF_CHECKFIRST;
//
// Enqueue file operations for the section passed on the cmd line.
//
//SourcePath = NULL;
bReturn = SetupInstallFilesFromInfSection(InfHandle,NULL,FileQueue,ActualSection,SourcePath,SP_COPY_NEWER);
if(!bReturn) {goto c1;}
//
// Commit file queue.
//
if(!SetupCommitFileQueue(Window, FileQueue, SetupDefaultQueueCallback, QueueContext)) {goto c1;}
//
// Perform non-file operations for the section passed on the cmd line.
//
bReturn = SetupInstallFromInfSection(Window,InfHandle,ActualSection,SPINST_ALL & ~SPINST_FILES,NULL,NULL,0,NULL,NULL,NULL,NULL);
if(!bReturn) {goto c1;}
//
// Refresh the desktop.
//
SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_FLUSHNOWAIT,0,0);
//
// If we get to here, then this routine has been successful.
//
bError = FALSE;
c1:
//
// If the bError was because the user cancelled, then we don't want to consider
// that as an bError (i.e., we don't want to give an bError popup later).
//
if(bError && (GetLastError() == ERROR_CANCELLED)) {bError = FALSE;}
if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);QueueContext = NULL;}
if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);FileQueue = INVALID_HANDLE_VALUE;}
if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);InfHandle = INVALID_HANDLE_VALUE;}
c0: ;
} __except(EXCEPTION_EXECUTE_HANDLER)
{
if(QueueContext) {SetupTermDefaultQueueCallback(QueueContext);}
if(FileQueue != INVALID_HANDLE_VALUE) {SetupCloseFileQueue(FileQueue);}
if(InfHandle != INVALID_HANDLE_VALUE) {SetupCloseInfFile(InfHandle);}
}
//
// If the bError was because the user cancelled, then we don't want to consider
// that as an bError (i.e., we don't want to give an bError popup later).
//
if(bError && (GetLastError() == ERROR_CANCELLED)) {bError = FALSE;}
// Display installation failed message
if(bError) {MyMessageBox(IDS_INF_FAILED);}
return bError;
}
//***************************************************************************
//*
//* purpose: pass a particular section (from the .inf file) to the "RunSetupCommand" function
//* in advpack.dll. depends upon if user wants to download another cpu/os
//* than is own.
//*
//***************************************************************************
HRESULT MyRunSetupCommand(HWND hwnd, LPCSTR lpszInfFile, LPCSTR lpszSection)
{
DWORD dwFlags;
RUNSETUPCOMMAND fpRunSetupCommand;
HRESULT hr = E_FAIL;
char szTemp[MAX_BUFFER];
HINSTANCE g_hAdvpack = NULL;
char g_szSourceDir[MAX_PATH] = "";
char szTmp[MAX_PATH];
HRESULT g_hr = E_FAIL;
BOOL bOleInited = FALSE ;
if (SUCCEEDED(g_hr = CoInitialize(NULL)))
{
bOleInited = TRUE ;
GetThisModulePath(g_szSourceDir, sizeof(g_szSourceDir));
lstrcpy(szTmp, g_szSourceDir);
AddPath(szTmp, "advpack.dll");
lstrcpy(szTmp, "advpack.dll");
g_hAdvpack = LoadLibrary( szTmp );
if ( g_hAdvpack != NULL )
{
lstrcpy(szTemp, lpszSection);
//dwFlags |= (RSC_FLAG_INF | RSC_FLAG_NGCONV);
dwFlags = (RSC_FLAG_INF | RSC_FLAG_NGCONV);
if (fpRunSetupCommand = (RUNSETUPCOMMAND)GetProcAddress(g_hAdvpack, achRUNSETUPCOMMANDFUNCTION))
{
hr = fpRunSetupCommand(hwnd, lpszInfFile, szTemp, g_szSourceDir, NULL, NULL, dwFlags, NULL);
if (hr == S_OK){MessageBox(NULL, "", "Everything OK, no reboot needed.", MB_OK | MB_ICONSTOP);}
if (hr == S_ASYNCHRONOUS){MessageBox(NULL, "", "Please wait on phEXE.", MB_OK | MB_ICONSTOP);}
if (hr == ERROR_SUCCESS_REBOOT_REQUIRED){MessageBox(NULL, "", "Reboot required.", MB_OK | MB_ICONSTOP);}
if (hr == E_INVALIDARG){MessageBox(NULL, "", "E_INVALIDARG", MB_OK | MB_ICONSTOP);}
if (hr == E_UNEXPECTED){MessageBox(NULL, "", "E_UNEXPECTED", MB_OK | MB_ICONSTOP);}
}
}
else
{
MyMessageBox(IDS_UNABLE_TO_FIND, szTmp);
}
}
if (bOleInited) CoUninitialize();
return hr;
}
//***************************************************************************
//*
//* purpose: getmodulefilename and return only the path
//*
//***************************************************************************
BOOL GetThisModulePath( LPSTR lpPath, int size )
{
*lpPath = '\0';
if ( GetModuleFileName( g_hInstance, lpPath, size ) )
{
MakePath(lpPath);
return TRUE;
}
return FALSE;
}
//***************************************************************************
//*
//* purpose:
//*
//***************************************************************************
void AddPath(LPSTR szPath, LPCSTR szName )
{
LPSTR szTmp;
// Find end of the string
szTmp = szPath + lstrlen(szPath);
// If no trailing backslash then add one
if ( szTmp > szPath && *(CharPrev( szPath, szTmp )) != '\\' )
*(szTmp++) = '\\';
// Add new name to existing path string
while ( *szName == ' ' ) szName++;
lstrcpy( szTmp, szName );
}
//***************************************************************************
//*
//* purpose:
//*
//***************************************************************************
void MakePath(LPSTR lpPath)
{
LPSTR lpTmp;
lpTmp = CharPrev( lpPath, lpPath+lstrlen(lpPath));
// chop filename off
while ( (lpTmp > lpPath) && *lpTmp && (*lpTmp != '\\') )
lpTmp = CharPrev( lpPath, lpTmp );
if ( *CharPrev( lpPath, lpTmp ) != ':' )
*lpTmp = '\0';
else
*CharNext( lpTmp ) = '\0';
return;
}