|
|
/*************************************************************************
* * INSTALL.C * * Copyright (C) Microsoft, 1991, All Rights Reserved. * * History: * * Thu Oct 17 1991 -by- Sanjaya * Created. Culled out of drivers.c * *************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <mmddk.h>
#include <winsvc.h>
#include <memory.h>
#include <string.h>
#include <cpl.h>
#include <cphelp.h>
#include <stdlib.h>
#include "drivers.h"
#include "sulib.h"
BOOL GetValidAlias (HWND, PSTR, PSTR); BOOL SelectInstalled (HWND, PIDRIVER, LPSTR); void InitDrvConfigInfo (LPDRVCONFIGINFO, PIDRIVER ); BOOL InstallDrivers (HWND, HWND, PSTR); void RemoveAlreadyInstalled (PSTR, PSTR); void CheckIniDrivers (PSTR, PSTR); void RemoveDriverParams (LPSTR, LPSTR);
/**************************************************************************
* * InstallDrivers() * * Install a driver and set of driver types. * * Parameters : * hwnd - Window handle of the main drivers.cpl windows * hwndAvail - Handle of the 'available drivers' dialog window * pstrKey - Key name of the inf section item we are installing * * This routine calls itself recursively to install related drivers * (as listed in the .inf file). * **************************************************************************/
BOOL InstallDrivers(HWND hWnd, HWND hWndAvail, PSTR pstrKey) { IDRIVER IDTemplate; // temporary for installing, removing, etc.
PIDRIVER pIDriver=NULL; int n,iIndex; HWND hWndI; char szTypes[MAXSTR]; char szType[MAXSTR]; char szParams[MAXSTR];
szTypes[0] = '\0';
hMesgBoxParent = hWndAvail;
/*
* mmAddNewDriver needs a buffer for all types we've actually installed * User critical errors will pop up a task modal */
IDTemplate.bRelated = FALSE; IDTemplate.szRemove[0] = TEXT('\0');
/*
* Do the copying and extract the list of types (WAVE, MIDI, ...) * and the other driver data */
if (!mmAddNewDriver(pstrKey, szTypes, &IDTemplate)) return FALSE;
szTypes[lstrlen(szTypes)-1] = '\0'; // Remove space left at end
RemoveAlreadyInstalled(IDTemplate.szFile, IDTemplate.szSection);
/*
* At this point we assume the drivers were actually copied. * Now we need to add them to the installed list. * For each driver type we create an IDRIVER and add to the listbox */
hWndI = GetDlgItem(hWnd, LB_INSTALLED);
for (n = 1; infParseField(szTypes, n, szType); n++) { /*
* Find a valid alias for this device (eg Wave2). This is * used as the key in the [MCI] or [drivers] section. */
if (GetValidAlias(hWndI, szType, IDTemplate.szSection) == FALSE) { /*
* Exceeded the maximum, tell the user */
PSTR pstrMessage; char szApp[MAXSTR]; char szMessage[MAXSTR];
LoadString(myInstance, IDS_CONFIGURE_DRIVER, szApp, sizeof(szApp));
LoadString(myInstance, IDS_TOO_MANY_DRIVERS, szMessage, sizeof(szMessage));
if (NULL != (pstrMessage = (PSTR)LocalAlloc(LPTR, sizeof(szMessage) + lstrlen(szType)))) { wsprintf(pstrMessage, szMessage, (LPSTR)szType);
MessageBox(hWndAvail, pstrMessage, szApp, MB_OK | MB_ICONEXCLAMATION|MB_TASKMODAL);
LocalFree((HANDLE)pstrMessage); } continue; }
if ( (pIDriver = (PIDRIVER)LocalAlloc(LPTR, sizeof(IDRIVER))) != NULL) { /*
* Copy all fields */
memcpy(pIDriver, &IDTemplate, sizeof(IDRIVER)); strncpy(pIDriver->szAlias, szType, sizeof(pIDriver->szAlias)); pIDriver->szAlias[sizeof(pIDriver->szAlias) - 1] = '\0'; mbstowcs(pIDriver->wszAlias, pIDriver->szAlias, MAX_PATH);
/*
* Want only one instance of each driver to show up in the list * of installed drivers. Thus for the remaining drivers just * place an entry in the drivers section of system.ini */
if ( n > 1) {
if (strlen(szParams) != 0 && !pIDriver->KernelDriver) { /*
* Write their parameters to a section bearing their * file name with an alias reflecting their alias */
WriteProfileString(pIDriver->szFile, pIDriver->szAlias, szParams); }
WritePrivateProfileString(pIDriver->szSection, pIDriver->szAlias, pIDriver->szFile, szSysIni); } else {
/*
* Add the driver description to our listbox */
iIndex = (int)SendMessage(hWndI, LB_ADDSTRING, 0, (LONG)pIDriver->szDesc);
if (iIndex >= LB_OKAY) {
/*
* Our PIDRIVER data is our listbox item */
SendMessage(hWndI, LB_SETITEMDATA, iIndex, (LONG)pIDriver);
/*
* Reduce to just the driver name */
RemoveDriverParams(pIDriver->szFile, szParams);
mbstowcs(pIDriver->wszFile, pIDriver->szFile, MAX_PATH);
if (strlen(szParams) != 0 && !pIDriver->KernelDriver) { /*
* Write their parameters to a section bearing their * file name with an alias reflecting their alias */
WriteProfileString(pIDriver->szFile, pIDriver->szAlias, szParams); }
WritePrivateProfileString(pIDriver->szSection, pIDriver->szAlias, pIDriver->szFile, szSysIni);
/*
* Call the driver to see if it can be configured * and configure it if it can be */
if (!SelectInstalled(hWndAvail, pIDriver, szParams)) {
/*
* Error talking to driver */
WritePrivateProfileString(pIDriver->szSection, pIDriver->szAlias, NULL, szSysIni);
WriteProfileString(pIDriver->szFile, pIDriver->szAlias, NULL);
SendMessage(hWndI, LB_DELETESTRING, iIndex, 0L); return FALSE; }
/*
* for displaying the driver desc. in the restart mesg */
if (!bRelated || pIDriver->bRelated) { strcpy(szRestartDrv, pIDriver->szDesc); }
/*
* We need to write out the driver description to the * control.ini section [Userinstallable.drivers] * so we can differentiate between user and system drivers * * This is tested by the function UserInstalled when * the user tries to remove a driver and merely * affects which message the user gets when being * asked to confirm removal (non user-installed drivers * are described as being necessary to the system). */
WritePrivateProfileString(szUserDrivers, pIDriver->szAlias, pIDriver->szFile, szControlIni);
/*
* Update [related.desc] section of control.ini : * * ALIAS=driver name list * * When the driver whose alias is ALIAS is removed * the drivers in the name list will also be removed. * These were the drivers in the related drivers list * when the driver is installed. */
WritePrivateProfileString(szRelatedDesc, pIDriver->szAlias, pIDriver->szRemove, szControlIni);
/*
* Cache the description string in control.ini in the * drivers description section. * * The key is the driver file name + extension. */
WritePrivateProfileString(szDriversDesc, pIDriver->szFile, pIDriver->szDesc, szControlIni);
#ifdef DOBOOT // We don't do the boot section on NT
if (bInstallBootLine) { szTemp[MAXSTR];
GetPrivateProfileString(szBoot, szDrivers, szTemp, szTemp, sizeof(szTemp), szSysIni); strcat(szTemp, " "); strcat(szTemp, pIDriver->szAlias); WritePrivateProfileString(szBoot, szDrivers, szTemp, szSysIni); bInstallBootLine = FALSE; } #endif // DOBOOT
} else { /*
* Problem getting an alias or adding a driver to the listbox */
LocalFree((HANDLE)pIDriver); pIDriver = NULL; return FALSE; //ERROR
} } } else return FALSE; //ERROR
}
/*
* If no types were added then fail */
if (pIDriver == NULL) { return FALSE; }
/*
* If there are related drivers listed in the .inf section to install * then install them now by calling ourselves. Use IDTemplate which * is where mmAddNewDriver put the data. */
if (IDTemplate.bRelated == TRUE) {
int i; char szTemp[MAXSTR];
/*
* Tell file copying to abort rather than put up errors */
bCopyingRelated = TRUE;
for (i = 1; infParseField(IDTemplate.szRelated, i, szTemp);i++) {
InstallDrivers(hWnd, hWndAvail, szTemp); } } return TRUE; }
/************************************************************************
* * SelectInstalled() * * Check if the driver can be configured and configure it if it can be. * * hwnd - Our window - parent for driver to make its config window * pIDriver - info about the driver * params - the drivers parameters from the .inf file. * * Returns FALSE if an error occurred, otherwise TRUE * ************************************************************************/
BOOL SelectInstalled(HWND hwnd, PIDRIVER pIDriver, LPSTR pszParams) { DRVCONFIGINFO DrvConfigInfo; HANDLE hDriver; BOOL Success = FALSE; DWORD dwTagId;
wsStartWait();
/*
* If it's a kernel driver call the services controller to * install the driver */
if (pIDriver->KernelDriver) {
SC_HANDLE SCManagerHandle; SC_HANDLE ServiceHandle; char ServiceName[MAX_PATH]; char BinaryPath[MAX_PATH];
/*
* These drivers are not configurable */
pIDriver->fQueryable = 0;
/*
* The services controller will create the registry node to * which we can add the device parameters value */
strcpy(BinaryPath, "\\SystemRoot\\system32\\drivers\\"); strcat(BinaryPath, pIDriver->szFile);
/*
* First try and obtain a handle to the service controller */
SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (SCManagerHandle != NULL) {
SC_LOCK ServicesDatabaseLock;
/*
* Lock the service controller database to avoid deadlocks * we have to loop because we can't wait */
for (ServicesDatabaseLock = NULL; (ServicesDatabaseLock = LockServiceDatabase(SCManagerHandle)) == NULL; Sleep(100)) { }
{ char drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH]; _splitpath(pIDriver->szFile, drive, directory, ServiceName, ext); }
ServiceHandle = CreateService(SCManagerHandle, ServiceName, NULL, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, BinaryPath, "Base", &dwTagId, "\0", NULL, NULL);
UnlockServiceDatabase(ServicesDatabaseLock);
if (ServiceHandle != NULL) { /*
* Try to write the parameters to the registry if there * are any */
if (strlen(pszParams)) {
HKEY ParmsKey; char RegPath[MAX_PATH]; strcpy(RegPath, "\\SYSTEM\\CurrentControlSet\\Services\\"); strcat(RegPath, ServiceName); strcat(RegPath, "\\Parameters");
Success = RegCreateKey(HKEY_LOCAL_MACHINE, RegPath, &ParmsKey) == ERROR_SUCCESS && RegSetValue(ParmsKey, "", REG_SZ, pszParams, strlen(pszParams)) == ERROR_SUCCESS && RegCloseKey(ParmsKey) == ERROR_SUCCESS; } else { Success = TRUE; }
/*
* Service created so try and start it */
if (Success) { /*
* We tell them to restart just in case */
bRestart = TRUE;
/*
* Load the kernel driver by starting the service. * If this is successful it should be safe to let * the system load the driver at system start so * we change the start type. */
Success = StartService(ServiceHandle, 0, NULL) && ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, SERVICE_SYSTEM_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (!Success) { char szMesg[MAXSTR]; char szMesg2[MAXSTR]; char szTitle[50];
/*
* Uninstall driver if we couldn't load it */
for (ServicesDatabaseLock = NULL; (ServicesDatabaseLock = LockServiceDatabase(SCManagerHandle)) == NULL; Sleep(100)) { }
DeleteService(ServiceHandle);
UnlockServiceDatabase(ServicesDatabaseLock);
/*
* Tell the user there was a configuration error * (our best guess). */
LoadString(myInstance, IDS_DRIVER_CONFIG_ERROR, szMesg, sizeof(szMesg)); LoadString(myInstance, IDS_CONFIGURE_DRIVER, szTitle, sizeof(szTitle)); wsprintf(szMesg2, szMesg, FileName(pIDriver->szFile)); MessageBox(hMesgBoxParent, szMesg2, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); } }
CloseServiceHandle(ServiceHandle); }
CloseServiceHandle(SCManagerHandle); } } else {
/*
* Put up a message if the driver can't be loaded or doesn't * respond favourably to the DRV_INSTALL message. */
BOOL bPutUpMessage;
bPutUpMessage = FALSE;
/*
* See if we can open the driver */
hDriver = OpenDriver(pIDriver->wszFile, NULL, 0L);
if (hDriver) { Success = TRUE;
InitDrvConfigInfo(&DrvConfigInfo, pIDriver);
/*
* See if activating the driver will require restarting the * system. * * Also check the driver wants to install (it may not * have the right privilege level). */
switch (SendDriverMessage(hDriver, DRV_INSTALL, 0L, (LONG)(LPDRVCONFIGINFO)&DrvConfigInfo))
{
case DRVCNF_RESTART:
bRestart = TRUE; break;
case DRVCNF_CANCEL:
/*
* The driver did not want to install */
bPutUpMessage = TRUE; Success = FALSE; break;
}
/*
* Remember whether the driver is configurable */
pIDriver->fQueryable = (int)SendDriverMessage(hDriver, DRV_QUERYCONFIGURE, 0L, 0L);
/*
* If the driver is configurable then configure it. * Configuring the driver may result in a need to restart * the system. The user may also cancel install. */
if (pIDriver->fQueryable) {
switch (SendDriverMessage( hDriver, DRV_CONFIGURE, (LONG)hwnd, (LONG)(LPDRVCONFIGINFO)&DrvConfigInfo)) {
case DRVCNF_RESTART: bRestart = TRUE; break;
case DRVCNF_CANCEL:
/*
* Don't put up the error box if the user cancelled */
Success = FALSE; break; } } CloseDriver(hDriver, 0L, 0L); } else { bPutUpMessage = TRUE; Success = FALSE; }
if (bPutUpMessage) {
/*
* If dealing with the driver resulted in error then put * up a message */
OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile); } } wsEndWait(); return Success; }
/***********************************************************************
* * InitDrvConfigInfo() * * Initialize Driver Configuration Information. * ***********************************************************************/
void InitDrvConfigInfo( LPDRVCONFIGINFO lpDrvConfigInfo, PIDRIVER pIDriver ) { lpDrvConfigInfo->dwDCISize = sizeof(DRVCONFIGINFO); lpDrvConfigInfo->lpszDCISectionName = pIDriver->wszSection; lpDrvConfigInfo->lpszDCIAliasName = pIDriver->wszAlias; }
/***********************************************************************
* * GetValidAlias() * * hwnd - Window handle - not used * pstrType - Input - the type * Output - New alias for that type * * pstrSection - The system.ini section we're dealing with * * Create a valid alias name for a type. Searches the system.ini file * in the drivers section for aliases of the type already defined and * returns a new alias (eg WAVE1). * ***********************************************************************/
BOOL GetValidAlias(HWND hwnd, PSTR pstrType, PSTR pstrSection) { #define MAXDRVTYPES 10
char *keystr; char allkeystr[MAXSTR]; BOOL found = FALSE; int val, maxval = 0, typelen;
typelen = strlen(pstrType); GetPrivateProfileString(pstrSection, NULL, NULL, allkeystr, sizeof(allkeystr), szSysIni); keystr = allkeystr;
/*
* See if we have driver if this type already installed by searching * our the [drivers] section. */
while (*keystr != '\0') { if (!_strnicmp(keystr, pstrType, typelen) && ((keystr[typelen] > '0' && keystr[typelen] <= '9') || keystr[typelen] == TEXT('\0') )) { found = TRUE; val = atoi(&keystr[typelen]); if (val > maxval) maxval = val; } keystr = &keystr[strlen(keystr) + 1]; }
if (found) { if (maxval == MAXDRVTYPES) return FALSE; // too many of my type!
pstrType[typelen] = (char)(maxval + '1'); pstrType[typelen+1] = '\0'; }
return TRUE; }
/*******************************************************************
* * IsConfigurable * * Find if a driver supports configuration * *******************************************************************/
BOOL IsConfigurable(PIDRIVER pIDriver, HWND hwnd) { HANDLE hDriver;
wsStartWait();
/*
* have we ever checked if this driver is queryable? */
if ( pIDriver->fQueryable == -1 ) {
/*
* Check it's not a kernel driver */
if (pIDriver->KernelDriver) { pIDriver->fQueryable = 0; } else {
/*
* Open the driver and ask it if it is configurable */
hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
if (hDriver) { pIDriver->fQueryable = (int)SendDriverMessage(hDriver, DRV_QUERYCONFIGURE, 0L, 0L);
CloseDriver(hDriver, 0L, 0L); } else { pIDriver->fQueryable = 0; OpenDriverError(hwnd, pIDriver->szDesc, pIDriver->szFile); wsEndWait(); return(FALSE); } } } wsEndWait(); return((BOOL)pIDriver->fQueryable); }
/******************************************************************
* * Find any driver with the same name currently installed and * remove it * * szFile - File name of driver * szSection - system.ini section ([MCI] or [drivers]). * ******************************************************************/
void RemoveAlreadyInstalled(PSTR szFile, PSTR szSection) { int iIndex; PIDRIVER pIDriver;
iIndex = (int)SendMessage(hlistbox, LB_GETCOUNT, 0, 0L);
while ( iIndex-- > 0) {
pIDriver = (PIDRIVER)SendMessage(hlistbox, LB_GETITEMDATA, iIndex, 0L);
if ( (int)pIDriver != LB_ERR) {
if (!FileNameCmp(pIDriver->szFile, szFile)) { PostRemove(hlistbox, pIDriver, FALSE, iIndex); return; } } }
CheckIniDrivers(szFile, szSection); }
/******************************************************************
* * Remove system.ini file entries for our driver * * szFile - driver file name * szSection - [drivers] or [MCI] * ******************************************************************/
void CheckIniDrivers(PSTR szFile, PSTR szSection) { char allkeystr[MAXSTR * 2]; char szRemovefile[20]; char *keystr;
GetPrivateProfileString(szSection, NULL, NULL, allkeystr, sizeof(allkeystr), szSysIni);
keystr = allkeystr; while (strlen(keystr) > 0) {
GetPrivateProfileString(szSection, keystr, NULL, szRemovefile, sizeof(szRemovefile), szSysIni);
if (!FileNameCmp(szFile, szRemovefile)) RemoveDriverEntry(keystr, szFile, szSection, FALSE);
keystr = &keystr[strlen(keystr) + 1]; } }
/******************************************************************
* * RemoveDriverParams * * Remove anything after the next token * ******************************************************************/
void RemoveDriverParams(LPSTR szFile, LPSTR Params) { for(;*szFile == ' '; szFile++); for(;*szFile != ' ' && *szFile != '\0'; szFile++); if (*szFile == ' ') { *szFile = '\0'; for (;*++szFile == ' ';); strcpy(Params, szFile); } else { *Params = '\0'; } }
|