|
|
//----------------------------------------------
//
// 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; }
|