//---------------------------------------------- // // program to use setupapi.dll to install the DefaultInstall section of a install.inf file // //---------------------------------------------- #include #include #include #include #include #include #include #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; }