DOINST.C
/******************************************************************************\ * This is a part of the Microsoft Source Code Samples. * Copyright 1995 - 1998 Microsoft Corporation. * All rights reserved. * This source code is only intended as a supplement to * Microsoft Development Tools and/or WinHelp documentation. * See these sources for detailed information regarding the * Microsoft samples programs. \******************************************************************************/ #include <windows.h> // includes basic windows functionality #include <string.h> // includes the string functions #include <shlobj.h> // To update the desktop #include <regstr.h> #include "setupapi.h" // includes the inf setup api #include "instwiz.h" // includes the application-specific information #include "infinst.h" // includes the application-specific information #include "infdesc.h" // includes the specifics of how this // inf is layed out, like the inf names // the HKeys and the DirIds DWORD InstallFinish(BOOL DoRunOnce); // // FUNCTION: BOOL DoInstallation( HWND hWnd, INSTALLINFO * si ) // // PURPOSE: Install components via setupapi.dll. // // COMMENTS: // // The function does inf install operations based // on the content of the INSTALLINFO data. // These steps could be done during the wizard but // this technique allows for installations with user input. // // This routine will take a INSTALLINFO // and do an installation based on those settings // using the setupapi.dll BOOL DoInstallation( HWND hWnd, INSTALLINFO * si ) { HINF hInf; char szSourcePath[MAX_PATH]; char szInfFileName[MAX_PATH]; DWORD dwResult; BOOL bResult = FALSE; // Context for my call back routine MY_INSTALL_DATA MyInstallData; HSPFILEQ FileQueue; // // First we setup the inf to what the wizard collected // note the hInf will maintain the information and let // you build copy list as you go // This sample seperates the wizard from the setapi stuff // just to keep the setupapi stuff in one place // // // The install process overview is: // TASK SETUPAPI // open a specific inf SetupOpenInfFile // call the wizard for input CreateWizard (implemented in instwiz.c) // set the directory ids SetupSetDirectoryId // create a file queue SetupOpenFileQueue // create a queue context SetupInitDefaultQueueCallback // add files to queue SetupInstallFilesFromInfSection // do the copy SetupCommitFileQueue //??? do the registry stuff SetupInstallFromInfSection // close the queue SetupTermDefaultQueueCallback // close the inf SetupCloseFileQueue // // In this sample we assume the inf is in the base of the // base installation source path--it usually is for most installs // GetModuleFileName(NULL, szSourcePath, _MAX_PATH); *(strrchr(szSourcePath, '\\') + 1) = '\0'; // Strip setup.exe off path strcpy(szInfFileName, szSourcePath); strcat(szInfFileName, "product.inf"); // // Get inf handle // must know where the inf is located // SetupOpenInfFile will only look in windows\inf by default // hInf = SetupOpenInfFile ( szInfFileName, // If path,needs full path, else looks in %windir%\inf NULL, // Inf Type, matches Class in [Version] section SetupClass=SAMPLE INF_STYLE_WIN4, // or INF_STYLE_OLDNT NULL // Line where error occurs if inf is has a problem ); if (hInf == INVALID_HANDLE_VALUE) { dwResult = GetLastError(); // // TODO: handle case where inf cannot be opened // by asking the user to locate the inf return FALSE; } // Run the wizard if (CreateWizard(hWnd, si->hInst)) { RuntimeRegistration(si); } else { SetupCloseInfFile(hInf); return FALSE; } // // Special case the uninstall destitation path // this is because we need to get the registry value // for where to delete the files from. // if (IDC_INSTALL_TYPE_UNINSTALL == si->iInstall_Type) { // get path installed to here! // query registry for si->pszDestPath GetRegString (MYPRODUCT_KEY, TEXT("DestinationPath"), si->pszDestPath); } // // Directory ids are set per HINF // // TODO: verify dest path as a valid file name bResult = SetupSetDirectoryId(hInf, // the HINF that will hold these ids (DWORD) DESTINATION_DIR, // the id that matchs one in the inf si->pszDestPath); // the user's string if(!bResult) { dwResult = GetLastError(); // TODO: handle case where we cannot set dirids, should we default or bail? // perhaps write this out to an error log // // Close the inf file and return // SetupCloseInfFile(hInf); return FALSE; } // // Create a Setup file queue and initialize the default Setup // queue callback routine. // FileQueue = SetupOpenFileQueue(); if(!FileQueue || (FileQueue == INVALID_HANDLE_VALUE)) { dwResult = ERROR_NOT_ENOUGH_MEMORY; // // Close the queue and return // SetupCloseInfFile(hInf); return FALSE; } // // This initialize memory for the default call back // This context MUST be used if our private callback routine // wants to callback into the default routine, we do it here with // a global value for the default context // // We want to use the default progress dialog. // We could override this by specifying a window that // will handle the ui in param 2. // By not passing a progress HWND this is the same as // using SetupInitDefaultQueueCallback. // MyInstallData.pDefaultContext = SetupInitDefaultQueueCallbackEx( hWnd, // HWND of owner window NULL, // HWND of alternate progress dialog which receives -- for example // if you wanted to display your progress bar right in the wizard 0, // Message sent to above window indicating a progress message 0, // DWORD Reserved NULL // PVOID Reserved ); if(!(MyInstallData.pDefaultContext)) { dwResult = ERROR_NOT_ENOUGH_MEMORY; // // Close the queue and the inf file and return // SetupCloseFileQueue(FileQueue); SetupCloseInfFile(hInf); return FALSE; } // // Now that we have a FileQueue, a Queue Context, and an HINF // we want to map the DirectoryIds in the INF to the ones // obtained by the user // // Queue file operations and commit the queue. // // // Install each option they have selected // if (IDC_INSTALL_TYPE_UNINSTALL == si->iInstall_Type) { //TODO: allow the user to remove specific components // note you would want to update the wizard to reflect this bResult = SetupInstallFilesFromInfSection( hInf, // HINF that has the directory ids set above NULL, // layout.inf if you have one, this a convient // place to do all of your file to media id mapping FileQueue, // Queue to add files to TEXT("MyProgramUninstall"), // SectionName, szSourcePath, // Path wher