📄 uninstall.cpp
字号:
&hkey) != ERROR_SUCCESS) { return NULL; } // Remove the values associated with this key SInstItem* pItem; SInstItem* pNextItem = NULL; GetNextItem(pItem); // Key default value while(pItem && stricmp(pItem->szName, UNINST_REGVALUE) == 0) { RemoveRegValue(hkey, NULL, pItem->szValue); delete pItem; GetNextItem(pItem); } // Named values while(pItem && stricmp(pItem->szName, UNINST_REGNAME) == 0) { GetNextItem(pNextItem); if(pNextItem && stricmp(pNextItem->szName, UNINST_REGVALUE) == 0) { do { RemoveRegValue(hkey, pItem->szValue, pNextItem->szValue); delete pNextItem; GetNextItem(pNextItem); } while(pNextItem && stricmp(pNextItem->szName, UNINST_REGVALUE) == 0); } else { // If a value was not given, delete regardless of value RegDeleteValue(hkey, pItem->szValue); } delete pItem; pItem = pNextItem; } RegCloseKey(hkey); // Queue it for deletion if(!m_RegKeys.Find(szFullKey)) { char* szNewKey = new char[strlen(szFullKey)+1]; strcpy(szNewKey, szFullKey); m_RegKeys.Push(szNewKey); } return pItem;}/* * CUninstaller::RemoveRegValue - removes the registry value specified * if its value matches the one we wrote */voidCUninstaller::RemoveRegValue(HKEY hkey, const char* szName, const char* szValue){ DWORD dwType; DWORD dwSize = READ_SIZE; BYTE pData[READ_SIZE]; if(RegQueryValueEx(hkey, szName, 0, &dwType, pData, &dwSize) == ERROR_SUCCESS) { // Check if it's the value we wrote // Only bother with string values for now, since that's // all we use. if(dwType == REG_SZ && strcmp(szValue, (char*)pData) == 0) { RegDeleteValue(hkey, szName); } }}/* * CUninstaller::RemoveInstDirectory - removes the directory if it is * empty. If it contains subdirectories, recursively removes them if empty. * Returns TRUE if successfully removed. */BOOLCUninstaller::RemoveInstDirectory(const char* szPath){ // All file removals should have already been handled by now. // Check if it exists struct stat info; if(stat(szPath, &info) != 0) { // Doesn't exist return TRUE; } // Check if the directory is empty WIN32_FIND_DATA fd; char szFileDesc[MAX_PATH+1]; _snprintf(szFileDesc, MAX_PATH, "%s\\*", szPath); szFileDesc[MAX_PATH] = '\0'; HANDLE hFind = FindFirstFile(szFileDesc, &fd); BOOL bEmpty = TRUE; if(hFind != INVALID_HANDLE_VALUE) { do { // Skip "." and ".." if(strcmp(fd.cFileName, ".") != 0 && strcmp(fd.cFileName, "..") != 0) { // Remove empty subdirectories if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { char szSubDir[MAX_PATH]; if(szSubDir) { _snprintf(szSubDir, MAX_PATH, "%s%c%s", szPath, OS_SEPARATOR_CHAR, fd.cFileName); szFileDesc[MAX_PATH] = '\0'; if(RemoveInstDirectory(szSubDir)) { m_Dirs.FindAndRemove(szSubDir); } } } } } while(FindNextFile(hFind, &fd)); FindClose(hFind); } // remove the directory if it is empty return RemoveDirectory(szPath);}/* * CUninstaller::RemoveRegTree - Recursively removes szFullKey and all * subkeys. If bDeleteVals is TRUE, removes values, otherwise removes * keys only if they are empty of values. * Returns FALSE if the key cannot be deleted because there are value left. */BOOLCUninstaller::RemoveRegTree(const char* szFullKey, BOOL bDeleteVals){ HKEY hkeyRoot; // Parse the root key (e.g. HKEY_CLASSES_ROOT) char* szKey = GetRootKey(szFullKey, hkeyRoot); if(!szKey) { return TRUE; } return RemoveRegTree(hkeyRoot, szKey, bDeleteVals);}BOOLCUninstaller::RemoveRegTree(HKEY hkeyRoot, const char* szKey, BOOL bDelVals){ HKEY hkey; // Open the key if(RegOpenKeyEx(hkeyRoot, szKey, 0, KEY_ALL_ACCESS, &hkey) != ERROR_SUCCESS) { return TRUE; } LONG res; DWORD dwNumKeys; DWORD dwNumVals; DWORD dwKeyLen; FILETIME ftWrite; BOOL bEmpty = TRUE; res = RegQueryInfoKey(hkey, NULL, NULL, NULL, &dwNumKeys, &dwKeyLen, NULL, &dwNumVals, NULL, NULL, NULL, NULL); if(res != ERROR_SUCCESS) { RegCloseKey(hkey); return FALSE; } // Are there any values? if(!bDelVals && dwNumVals) { // There are values, so we cannot delete the key bEmpty = FALSE; } // Are there any keys? if(bEmpty && dwNumKeys) { DWORD dwIndex; DWORD dwLen; char** ppKeys = new char*[dwNumKeys]; // Get all the key names for(dwIndex = 0; dwIndex < dwNumKeys; dwIndex++) { ppKeys[dwIndex] = new char[dwKeyLen+1]; ppKeys[dwIndex][0] = '\0'; dwLen = dwKeyLen+1; if(ppKeys[dwIndex]) { RegEnumKeyEx(hkey, dwIndex, ppKeys[dwIndex], &dwLen, NULL, NULL, NULL, &ftWrite); } } // delete them for(dwIndex = 0; dwIndex < dwNumKeys; dwIndex++) { if((!ppKeys[dwIndex] || ppKeys[dwIndex][0] == '\0' || !RemoveRegTree(hkey, ppKeys[dwIndex], bDelVals)) && !bDelVals) { bEmpty = FALSE; } } } RegCloseKey(hkey); // Remove the key if it has no values that we do not want to delete // RegDeleteKey also deletes all of the keys values return bEmpty ? RegDeleteKey(hkeyRoot, szKey) : FALSE;}/* * CUninstaller::GetRootKey - parses the key name and translates to the * proper predefined root key HKEY (e.g. HKEY_CLASSES_ROOT). returns a pointer * to the beginning of the actual key name in szName, or NULL if no * translation could be made. */char*CUninstaller::GetRootKey(const char* szName, HKEY& hkey){ char* szKey = strchr(szName, '\\'); if(szKey <= szName) { return FALSE; } for(int i=0; HKEY_MAP[i].szName != NULL; i++) { if(strnicmp(szName, HKEY_MAP[i].szName, szKey - szName) == 0) { hkey = HKEY_MAP[i].hkey; return szKey + 1; } } return NULL;}/* * CUninstaller::WarnRunning - warns the user to quit the application before * uninstalling it. Reutrns TRUE if they click okay to continue uninstalling. */BOOLCUninstaller::WarnRunning(){ char szText[READ_SIZE + 512]; char szCaption[READ_SIZE + 64]; sprintf(szText, STR_ERR_RUNNING, m_szTitle); sprintf(szCaption, STR_CAPTION, m_szTitle); if(MessageBox(NULL, szText, szCaption, MB_OKCANCEL) != IDOK) { return FALSE; } return TRUE;}/* * CUninstaller::ShowProgress - Displays the progress dialog. * Single threaded, no cancelling or anything. */BOOLCUninstaller::ShowProgress(void){ // Necessary for the progress bar InitCommonControls(); m_hwndDlg = CreateDialog(m_hInstance, MAKEINTRESOURCE(IDD_PROGRESS), 0, ProgressDlgProc); if(!m_hwndDlg) { return FALSE; } // Set the window title char szCaption[READ_SIZE + 512]; sprintf(szCaption, STR_CAPTION, m_szTitle); SetWindowText(m_hwndDlg, szCaption); return TRUE;}/* * CUninstaller::SetProgress - Sets the progress bar to the specified percentage */voidCUninstaller::SetProgress(UINT16 uProgress){ if(uProgress > 100) { uProgress = 100; } // Just check messages here CheckMessages(); // set the progress bar HWND hwndProgress = GetDlgItem(m_hwndDlg, IDC_PROGRESSBAR); if(hwndProgress) { PostMessage(hwndProgress, PBM_SETPOS, uProgress, 0); } char str[256]; sprintf(str, "Progress: %u\n", uProgress); OutputDebugString(str);}/* * CUninstaller::GetNumItems - attempts to determine the number of install * "items" in order to make a lame approximation of progress */voidCUninstaller::GetNumItems(){ // Count the number of lines in each install instance // amd just use the biggest one. Close enough. char szLine[READ_SIZE]; UINT32 ulNumItems = 0; m_ulItems = 0; m_ulTotalItems = 0; while(fgets(szLine, READ_SIZE, m_fpLog) && !feof(m_fpLog)) { // skip any obviously blank lines or comments if(*szLine != '#' || *szLine != '\n' || *szLine != '\0') { // if we find a title item, this is a new installation if(strncmp(szLine, UNINST_TITLE, strlen(UNINST_TITLE)) == 0) { if(ulNumItems > m_ulItems) { m_ulTotalItems = ulNumItems; } ulNumItems = 0; } else { ulNumItems++; } } } if(ulNumItems > m_ulItems) { m_ulTotalItems = ulNumItems; } // plus one for the log file m_ulTotalItems++;}/* * CUninstaller::UpdateDlgText - updates the progress dialog text */voidCUninstaller::UpdateDlgText(const char* szText){ SetDlgItemText(m_hwndDlg, IDC_TEXT, szText);}/* * CUninstaller::CloseProgress - destroys the progress dialog */voidCUninstaller::CloseProgress(){ if(m_hwndDlg) { DestroyWindow(m_hwndDlg); }}/* * CUninstaller::ShowDoneMessage - Pops up a message to say we're done. */voidCUninstaller::ShowDoneMessage(){ char szText[READ_SIZE + 512]; char szCaption[READ_SIZE + 64]; sprintf(szText, STR_DONE_MSG, m_szTitle); sprintf(szCaption, STR_CAPTION, m_szTitle); MessageBox(NULL, szText, szCaption, MB_OK | MB_ICONINFORMATION);}voidCUninstaller::CheckMessages(void){ MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(!m_hwndDlg || !IsDialogMessage(m_hwndDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -