windows-nt/Source/XPSP1/NT/shell/osshell/control/drivers/remove.c
2020-09-26 16:20:57 +08:00

516 lines
14 KiB
C

/* REMOVE.C
**
** Copyright (C) Microsoft, 1990, All Rights Reserved.
**
** Multimedia Control Panel Applet for removing
** device drivers. See the ispec doc DRIVERS.DOC for more information.
**
** History:
**
** Thu Oct 17 1991 -by- Sanjaya
** Created. Originally part of drivers.c
*/
#include <windows.h>
#include <mmsystem.h>
#include <winsvc.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <cpl.h>
#include <cphelp.h>
#include "drivers.h"
#include "sulib.h"
BOOL SetValidAlias (PSTR, PSTR);
#ifdef DOBOOT
BOOL FindBootDriver (char *);
PSTR strstri (PSTR, PSTR);
#endif // DOBOOT
/*
* RemoveService(szFile)
*
* Remove the service corresponding to the file szFile
*
* returns TRUE if successful, FALSE otherwise
*/
BOOL RemoveService(LPSTR szFile)
{
SC_HANDLE SCManagerHandle;
SC_HANDLE ServiceHandle;
char ServiceName[MAX_PATH];
BOOL Status = FALSE;
/*
* Extract the service name from the file name
*/
{
char drive[MAX_PATH], directory[MAX_PATH], ext[MAX_PATH];
_splitpath(szFile, drive, directory, ServiceName, ext);
}
/*
* First try and obtain a handle to the service controller
*/
SCManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (SCManagerHandle == NULL) {
char szMesg[MAXSTR];
char szMesg2[MAXSTR];
LoadString(myInstance, IDS_INSUFFICIENT_PRIVILEGE, szMesg, sizeof(szMesg));
wsprintf(szMesg2, szMesg, szFile);
MessageBox(hMesgBoxParent, szMesg2, szRemove, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
return FALSE;
}
ServiceHandle = OpenService(SCManagerHandle,
ServiceName,
SERVICE_ALL_ACCESS);
if (ServiceHandle != NULL) {
SERVICE_STATUS ServiceStatus;
SC_LOCK ServicesDatabaseLock;
/*
* Stop the service if possible.
*/
ControlService(ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus);
/*
* Delete the service.
* We aren't detecting if we can just carry on.
*/
/*
* 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)) {
}
Status = DeleteService(ServiceHandle);
UnlockServiceDatabase(ServicesDatabaseLock);
CloseServiceHandle(ServiceHandle);
} else {
/*
* It's possible there was no services entry so the driver
* wasn't really installed after all.
*/
LONG Error = GetLastError();
if (Error == ERROR_FILE_NOT_FOUND ||
Error == ERROR_PATH_NOT_FOUND ||
Error == ERROR_SERVICE_DOES_NOT_EXIST) {
Status = TRUE;
}
}
CloseServiceHandle(SCManagerHandle);
return Status;
}
/*
** PostRemove()
**
** Mark an installed driver for removal later AND remove the driver's entry
** in SYSTEM.INI to avoid conflicts when we add or remove later.
*/
LONG PostRemove(HWND hWnd, PIDRIVER pIDriver, BOOL bLookAtRelated,
int iIndexMain)
{
char *keystr;
char allkeystr[MAXSTR];
char szfile[MAX_PATH];
HANDLE hDriver;
LONG Status = DRVCNF_CANCEL;
PSTR pstr;
GetPrivateProfileString(pIDriver->szSection,
pIDriver->szAlias,
pIDriver->szFile,
pIDriver->szFile,
MAX_PATH,
szSysIni);
/*
* Remove parameters from file name
*/
for ( pstr=pIDriver->szFile; *pstr && (*pstr!=COMMA) &&
(*pstr!=SPACE); pstr++ )
;
*pstr = '\0';
if (bLookAtRelated && (!bRelated || pIDriver->bRelated))
strcpy(szRestartDrv, pIDriver->szDesc);
/*
* If it's a kernel driver remove it from the config registry
* and services controller
*/
if (pIDriver->KernelDriver) {
Status = RemoveService(pIDriver->szFile) ? DRVCNF_RESTART : DRVCNF_CANCEL;
if (Status == DRVCNF_CANCEL) {
return DRVCNF_CANCEL;
}
} else {
hDriver = OpenDriver(pIDriver->wszAlias, pIDriver->wszSection, 0L);
if (hDriver)
{
/*
* Removal can fail so don't mark as deleted in this case
*/
Status = SendDriverMessage(hDriver, DRV_REMOVE, 0L, 0L);
CloseDriver(hDriver, 0L, 0L);
if (Status == DRVCNF_CANCEL) {
return DRVCNF_CANCEL;
}
}
}
SendMessage(hWnd, LB_DELETESTRING, iIndexMain, 0L);
if (bLookAtRelated)
{
char allkeystr[MAXSTR];
if (GetPrivateProfileString(szRelatedDesc, pIDriver->szAlias,
allkeystr, allkeystr, sizeof(allkeystr), szControlIni))
{
int i, iIndex;
BOOL bFound;
PIDRIVER pIDriver;
char szTemp[MAXSTR];
for (i = 1; infParseField(allkeystr, i, szTemp);i++)
{
bFound = FALSE;
iIndex = (int)SendMessage(hWnd, LB_GETCOUNT, 0, 0L);
while ( iIndex-- > 0 && !bFound)
if ( (int)(pIDriver = (PIDRIVER)SendMessage(hWnd, LB_GETITEMDATA, iIndex, 0L)) != LB_ERR) {
if (!FileNameCmp(pIDriver->szFile, szTemp))
{
if (PostRemove(hWnd, pIDriver, FALSE, iIndex)
== DRVCNF_RESTART) {
Status = DRVCNF_RESTART;
}
bFound = TRUE;
}
}
}
}
}
// Remove the driver entry from SYSTEM.INI so you don't
// conflict with other drivers.
GetPrivateProfileString(pIDriver->szSection, NULL, NULL,
allkeystr, sizeof(allkeystr), szSysIni);
keystr = allkeystr;
while (strlen(keystr) > 0)
{
GetPrivateProfileString(pIDriver->szSection, keystr, NULL, szfile, sizeof(szfile), szSysIni);
if (!FileNameCmp(pIDriver->szFile, szfile))
RemoveDriverEntry(keystr, pIDriver->szFile, pIDriver->szSection, bLookAtRelated);
keystr = &keystr[strlen(keystr) + 1];
}
return Status;
}
void RemoveDriverEntry (PSTR szKey, PSTR szFile, PSTR szSection, BOOL bLookAtRelated)
{
/*
* Remove entry for loading driver
*/
WritePrivateProfileString(szSection, szKey, NULL, szSysIni);
/*
* Delete entry for parameters for this driver
*/
WriteProfileString(szFile, szKey, NULL);
/*
* Remove entry which says this is a user driver (as opposed to
* a pre-installed one).
*/
WritePrivateProfileString(szUserDrivers, szKey, NULL, szControlIni);
/*
* Remove description
*/
WritePrivateProfileString(szDriversDesc, szFile, NULL, szControlIni);
/*
* Remove links to related drivers
*/
WritePrivateProfileString(szRelatedDesc, szKey, NULL, szControlIni);
#ifdef DOBOOT
FindBootDriver(szKey);
#endif // DOBOOT
if (bLookAtRelated)
SetValidAlias(szKey, szSection);
}
/*
* SetValidAlias()
*
* Check to see if the alias removed would create a hole in the device
* numbering scheme. If so switch the last device number with the deleted one.
*/
BOOL SetValidAlias(PSTR pstrType, PSTR pstrSection)
{
char *keystr;
static char allkeystr[MAXSTR];
static char szExKey[MAXSTR], szExFile[MAXSTR], szExDesc[MAXSTR];
BOOL bfound = FALSE, bExchange = FALSE;
int val, maxval = 0, typelen, len;
/*
* Getting length of alias
*/
len = typelen = strlen(pstrType);
// If the last char on the type is a number don't consider it
if (pstrType[typelen -1] > '0' && pstrType[typelen - 1] <= '9')
typelen--;
// Get all the aliases in the drivers section
GetPrivateProfileString(pstrSection, NULL, NULL, allkeystr,
sizeof(allkeystr), szSysIni);
keystr = allkeystr;
while (*keystr != TEXT('\0'))
{
// Compare the root of the aliases
if (!_strnicmp(keystr, pstrType, typelen) && ((keystr[typelen] <= '9' && keystr[typelen] > '0') || keystr[typelen] == TEXT('\0')))
{
//We found a common alias
bfound = TRUE;
val = atoi(&keystr[typelen]);
if (val > maxval)
{
maxval = val;
strcpy(szExKey, keystr);
}
}
//Pointer to next alias
keystr = &keystr[strlen(keystr) + 1];
}
//If we found one
if (bfound)
{
if (len == typelen)
bExchange = TRUE;
else
if (atoi(&pstrType[typelen]) < maxval)
bExchange = TRUE;
// We need to exchange it with the one we found
if (bExchange)
{
//Exchanging the one in the drivers section in system.ini
GetPrivateProfileString(pstrSection, szExKey, NULL, szExFile,
sizeof(szExFile), szSysIni);
WritePrivateProfileString(pstrSection, szExKey, NULL, szSysIni);
WritePrivateProfileString(pstrSection, pstrType, szExFile, szSysIni);
#ifdef TRASHDRIVERDESC
//Exchanging the one in the drivers description section of control.ini
GetPrivateProfileString(szDriversDesc, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
WritePrivateProfileString(szDriversDesc, szExKey, NULL, szControlIni);
WritePrivateProfileString(szDriversDesc, pstrType, szExDesc, szControlIni);
#endif
//If any related drivers were present under old alias switch them
GetPrivateProfileString(szRelatedDesc, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
if (strlen(szExDesc))
{
WritePrivateProfileString(szRelatedDesc, szExKey, NULL, szControlIni);
WritePrivateProfileString(szRelatedDesc, pstrType, szExDesc, szControlIni);
}
//If user installed driver under old alias switch them
GetPrivateProfileString(szUserDrivers, szExKey, NULL, szExDesc, sizeof(szExFile), szControlIni);
if (strlen(szExDesc))
{
WritePrivateProfileString(szUserDrivers, szExKey, NULL, szControlIni);
WritePrivateProfileString(szUserDrivers, pstrType, szExDesc, szControlIni);
}
#ifdef DOBOOT
if (FindBootDriver(szExKey))
{
static char szTemp[MAXSTR];
GetPrivateProfileString(szBoot, szDrivers, szTemp, szTemp,
sizeof(szTemp), szSysIni);
strcat(szTemp, " ");
strcat(szTemp, pstrType);
WritePrivateProfileString(szBoot, szDrivers, szTemp, szSysIni);
}
#endif // DOBOOT
}
}
return(bExchange);
}
#if 0 // Dead code !
/*
* IsOnlyInstance()
*
* Check to see if this is the only occurance of an open driver, so we can
* tell if a DRV_INSTALL message has been sent to the driver yet OR
* if it is the last instance of the driver so we can send a
* DRV_REMOVE message.
*/
BOOL IsOnlyInstance( HWND hwndLB, PIDRIVER pIDriver )
{
int iEntries;
PIDRIVER pIDTest;
if (pIDriver == NULL)
return FALSE;
/*
* Check Installed ListBox
*/
if ((iEntries = (int)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L)) == LB_ERR)
iEntries = 0;
else
while (iEntries-- > 0)
{
pIDTest = (PIDRIVER)SendMessage(hwndLB,
LB_GETITEMDATA,
iEntries,
0L);
if (pIDTest == NULL)
continue;
if (pIDriver == pIDTest)
continue;
if (FileNameCmp(pIDTest->szFile,pIDriver->szFile) == 0)
{
return FALSE;
}
}
return TRUE;
}
#endif
int FileNameCmp(char far *pch1, char far *pch2)
{
LPSTR pchEOS;
while (*pch1 == ' ') pch1++; // eat spaces
while (*pch2 == ' ') pch2++; // eat spaces
for (pchEOS = pch1; *pchEOS && *pchEOS != ' '; pchEOS++);
return _strnicmp(pch1, pch2, pchEOS - pch1);
}
#ifdef DOBOOT
PSTR strstri(PSTR pszStr, PSTR pszKey)
{
while (pszStr)
if (!_strnicmp(pszStr, pszKey, lstrlen(pszKey)))
return(pszStr);
else
pszStr++;
return(NULL);
}
/*
* FindBootDriver()
* Checks to see if the driver alias is on the drivers line of the
* boot section. If so the alias is removed from the line.
*/
BOOL FindBootDriver(char *szKey)
{
char *ptr;
int wKeyLen = (int)strlen(szKey);
char *endkey;
static char szDriverline[MAXSTR];
GetPrivateProfileString("boot", "drivers", szDriverline, szDriverline,
MAX_PATH, szSysIni);
ptr = strstri(szDriverline, szKey);
if (ptr)
{
if ((((ptr != szDriverline) && (*(ptr - 1) == ' ' )) ||
(ptr == szDriverline)) &&
(*(ptr + wKeyLen) == ' ' || *(ptr + wKeyLen) == NULL))
{
endkey = ptr + wKeyLen;
while (*endkey)
*ptr++ = *endkey++;
*ptr = NULL;
WritePrivateProfileString("boot", "drivers", szDriverline,
szSysIni);
return(TRUE);
}
}
return(FALSE);
}
#endif // DOBOOT