/* 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 #include #include #include #include #include #include #include #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