📄 uninstall.cpp
字号:
BOOL res = MessageBox(NULL, szText, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION) == IDOK ? TRUE : FALSE; return res;}/* * CUninstaller::GetNextItem - Parses the next item out of the log */BOOLCUninstaller::GetNextItem(SInstItem*& pItem){ char szLine[READ_SIZE]; pItem = NULL; if(!fgets(szLine, READ_SIZE, m_fpLog) || feof(m_fpLog)) { return FALSE; } char* szName; // Trim whitespace for(szName = szLine; *szName != '\0' && isspace(*szName); szName++); if(*szName == '#') { // Comment. Get next line. return GetNextItem(pItem); } // Get the item name. char* szNameEnd = strchr(szName, ':'); if(szNameEnd < szName) { // No item name. Try the next line return GetNextItem(pItem); } // Find beginning of value. char* szValue; for(szValue = szNameEnd + 1; *szValue != '\0' && isspace(*szValue); szValue++); UINT uNameLen = szNameEnd - szName; UINT uValLen = strlen(szValue); if(uNameLen == 0 || uValLen == 0) { // Missing name or value. Go on to the next line return GetNextItem(pItem); } // Trim trailing whitespace for(;isspace(szValue[uValLen-1]);uValLen--); pItem = new SInstItem; if(!pItem) { // No memory!! return FALSE; } pItem->szName = new char[uNameLen + 1]; pItem->szValue = new char[uValLen + 1]; if(!pItem->szName || !pItem->szValue) { // no memory! HX_DELETE(pItem); return FALSE; } // Copy the name and value strncpy(pItem->szName, szName, uNameLen); pItem->szName[uNameLen] = '\0'; strncpy(pItem->szValue, szValue, uValLen); pItem->szValue[uValLen] = '\0'; return TRUE;}/* * CUninstaller::RemoveServices - looks for all service items and stops * and removes them. */voidCUninstaller::RemoveServices(){ fseek(m_fpLog, 0, SEEK_SET); SInstItem* pItem; while(GetNextItem(pItem)) { if(stricmp(pItem->szName, UNINST_SERVICE) == 0) { UpdateDlgText(STR_DEL_SERVICE); RemoveService(pItem->szValue); m_ulItems++; SetProgress((UINT16) (((double)m_ulItems / (double)m_ulTotalItems) * 100)); } delete pItem; }}/* * CUninstaller::RemoveAll - Removes everything that has not yet * been handled - files, reg entries, directories */voidCUninstaller::RemoveAll(){ fseek(m_fpLog, 0, SEEK_SET); // Traverse the log. SInstItem* pItem; GetNextItem(pItem); while(pItem) { m_ulItems++; SetProgress((UINT16) (((double) m_ulItems / (double) m_ulTotalItems) * 100)); pItem = HandleItem(pItem); } // Close the log file and delete it fclose(m_fpLog); m_fpLog = 0; UpdateDlgText(STR_DEL_FILE); RemoveInstallFile(m_szLog); // Try to change to the system directory, so we can // delete '.' char szSysDir[MAX_PATH+1]; UINT uLen = GetSystemDirectory(szSysDir, MAX_PATH); if(uLen && uLen <= MAX_PATH) { chdir(szSysDir); } // Now remove all the directories and reg keys char* szVal; while(szVal = m_Dirs.Pop()) { RemoveInstDirectory(szVal); m_ulItems++; SetProgress((UINT16) (((double) m_ulItems / (double) m_ulTotalItems) * 100)); delete[] szVal; } while(szVal = m_RegKeys.Pop()) { RemoveRegTree(szVal, FALSE); m_ulItems++; SetProgress((UINT16) (((double) m_ulItems / (double) m_ulTotalItems) * 100)); delete[] szVal; } SetProgress(100);}/* * CUninstaller::HandleItem - removes or otherwise handles pItem */SInstItem*CUninstaller::HandleItem(SInstItem* pItem){ SInstItem* pNextItem = NULL; if(stricmp(pItem->szName, UNINST_FILE) == 0) { // delete the file UpdateDlgText(STR_DEL_FILE); RemoveInstallFile(pItem->szValue); } else if(stricmp(pItem->szName, UNINST_MULTIFILE) == 0) { // delete the files UpdateDlgText(STR_DEL_FILE); RemoveMultipleFiles(pItem->szValue); } else if(stricmp(pItem->szName, UNINST_SHFILE) == 0) { // deref and delete if appropriate UpdateDlgText(STR_DEL_FILE); RemoveSharedFile(pItem->szValue); } else if(stricmp(pItem->szName, UNINST_DIRECTORY) == 0) { // Queue for deletion char* szDir = new char[MAX_PATH+1]; strncpy(szDir, pItem->szValue, MAX_PATH); szDir[MAX_PATH] = '\0'; if(!m_Dirs.Find(szDir)) { m_Dirs.Push(szDir); } } else if(stricmp(pItem->szName, UNINST_REGKEY) == 0) { // Remove values and key if empty UpdateDlgText(STR_DEL_REG); pNextItem = RemoveRegKeyVals(pItem->szValue); } else if (stricmp(pItem->szName, UNINST_REGTREE) == 0) { // Remove the entire tree! UpdateDlgText(STR_DEL_REG); RemoveRegTree(pItem->szValue, TRUE); } delete pItem; if(!pNextItem) { GetNextItem(pNextItem); } return pNextItem;}/* * CUninstaller::RemoveInstallFile - Removes szFile */voidCUninstaller::RemoveInstallFile(const char* szFile){ // Check if the file exists and try to remove it struct stat info; if(stat(szFile, &info) != 0 || DeleteFile(szFile)) { return; } // If it exists and we can't delete it, then check if it's this exe char szPath[MAX_PATH+1]; UINT32 ulLen = GetShortPathName(szFile, szPath, MAX_PATH+1); if(ulLen && ulLen <= MAX_PATH && stricmp(szPath, m_szUninstPath) == 0) { // Move it to a temp file. char szTempDir[MAX_PATH+1]; ulLen = GetTempPath(MAX_PATH+1, szTempDir); if(ulLen && ulLen <= MAX_PATH && GetTempFileName(szTempDir, "hxsetup", 0, szPath)) { DeleteFile(szPath); if(MoveFile(szFile, szPath)) { // Mark the temp file for removal on reboot ReplaceOnReboot(szPath, NULL); } } }}/* * CUninstaller::RemoveMultipleFiles - Removes files matching the * wildcard description */void CUninstaller::RemoveMultipleFiles(const char* szFileDescriptor){ WIN32_FIND_DATA fd; HANDLE hFind = FindFirstFile(szFileDescriptor, &fd); if(hFind == INVALID_HANDLE_VALUE) { // No matching file return; } char* szDirEnd = strrchr(szFileDescriptor, OS_SEPARATOR_CHAR); if(szDirEnd <= szFileDescriptor) { FindClose(hFind); return; } char szFullPath[MAX_PATH+1]; char* pFileName; UINT uLen = min(szDirEnd-szFileDescriptor, MAX_PATH - 1); UINT uFNameSize = MAX_PATH - uLen - 1; strncpy(szFullPath, szFileDescriptor, uLen+1); pFileName = &szFullPath[uLen+1]; // Delete all files do { // Don't delete "." or ".." if(strcmp(fd.cFileName, ".") != 0 && strcmp(fd.cFileName, "..") != 0 && !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { strncpy(pFileName, fd.cFileName, uFNameSize); pFileName[uFNameSize] = '\0'; RemoveInstallFile(szFullPath); } } while(FindNextFile(hFind, &fd)); FindClose(hFind);}/* * CUninstaller::RemoveSharedFile - decrements the ref count, and * removes the file and ref count if appropriate, of szFileName. */voidCUninstaller::RemoveSharedFile(const char* szFileName){ HKEY hKey; DWORD dwType; DWORD dwSize; DWORD dwRefCount = 0; // Open the key if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_SHARED_FILES_KEY, 0, KEY_EXECUTE | KEY_SET_VALUE, &hKey) != ERROR_SUCCESS) { // Can't access shared files key! Just leave the file alone. return; } // Get the value dwSize = sizeof(DWORD); if(RegQueryValueEx(hKey, szFileName, NULL, &dwType, (LPBYTE)&dwRefCount, &dwSize) != ERROR_SUCCESS) { // If we couldn't find a ref count, leave the file and set to 1 dwRefCount = 2; } if(dwRefCount > 1) { // decrement the ref count dwRefCount--; RegSetValueEx(hKey, szFileName, 0, REG_DWORD, (LPBYTE)&dwRefCount, sizeof(DWORD)); } else { // no more refs. delete the file and ref count. RegDeleteValue(hKey, szFileName); RemoveInstallFile(szFileName); } RegCloseKey(hKey);}/* * CUninstaller::RemoveService - Stops the service if it is running * and deletes it. */voidCUninstaller::RemoveService(const char* szServiceName){ SC_HANDLE schManager; SC_HANDLE schService; // Open service control manager schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if(!schManager) { return; } // Open the service entry schService = OpenService(schManager, szServiceName, SERVICE_STOP | DELETE); if(schService != NULL) { SERVICE_STATUS ss; // Stop the service ControlService(schService, SERVICE_CONTROL_STOP, &ss); // Wait for it to stop DWORD dwWaitInterval; DWORD dwWaitTime = 0; while (QueryServiceStatus(schService, &ss) && ss.dwCurrentState == SERVICE_STOP_PENDING && dwWaitTime < ss.dwWaitHint) { // 1/10 wait hint, min 1 sec, max 10 sec dwWaitInterval = ss.dwWaitHint < 10000 ? 1000 : (ss.dwWaitHint > 100000 ? 10000 : ss.dwWaitHint / 10); Sleep(dwWaitInterval); dwWaitTime += dwWaitInterval; } } else { // Try to just open for deleting if we failed for stop and delete schService = OpenService(schManager, szServiceName, DELETE); } if(schService != NULL) { // Delete the service DeleteService(schService); CloseServiceHandle(schService); } CloseServiceHandle(schManager);}/* * CUninstaller::RemoveRegKeyVals - Removes all values associated with a key. * Returns the next install item to be processed. */SInstItem*CUninstaller::RemoveRegKeyVals(char* szFullKey){ HKEY hkeyRoot; char* szKey = GetRootKey(szFullKey, hkeyRoot); // Parse the root key (e.g. HKEY_CLASSES_ROOT) if(!szKey) { return NULL; } HKEY hkey; // Open the key if(RegOpenKeyEx(hkeyRoot, szKey, 0, KEY_READ | KEY_SET_VALUE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -