size_t Diagnosis::whoUseMe(std::vector<std::string>& appList, std::string const& oneFilePath) { DWORD dwSession = 0; WCHAR szSessionKey[CCH_RM_SESSION_KEY + 1] = { 0 }; UINT nProcInfoNeeded = 0; UINT nProcInfo = 0; RM_PROCESS_INFO* pRgpi = NULL; DWORD dwReason; DWORD dwError = 0; wchar_t* pwcs = NULL; char* pApp = NULL; try { dwError = RmStartSession(&dwSession, 0, szSessionKey); if (dwError != ERROR_SUCCESS) { throw std::runtime_error("fail to start restart manager."); } // convert char string to wchar string pwcs = new wchar_t[oneFilePath.size() + 1](); MultiByteToWideChar(CP_ACP, 0, oneFilePath.c_str(), oneFilePath.size(), pwcs, oneFilePath.size() + 1); LPCWSTR supervisedFiles[] = {pwcs}; dwError = RmRegisterResources(dwSession, 1, supervisedFiles, 0, NULL, 0, NULL); if (dwError != ERROR_SUCCESS) { std::string msg("fail to register resources. system error code: "); msg += std::to_string(dwError) + ", refer to: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373663(v=vs.85).aspx"; throw std::runtime_error(msg); } // first try to get process list max 5 nProcInfo = 5; pRgpi = new RM_PROCESS_INFO[nProcInfo]; dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, pRgpi, &dwReason); // there are more than 5 process using the file, then get them all if (dwError == ERROR_MORE_DATA) { // get list of all the process info delete[] pRgpi; nProcInfo = nProcInfoNeeded; pRgpi = new RM_PROCESS_INFO[nProcInfo]; dwError = RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, pRgpi, &dwReason); } if (dwError != ERROR_SUCCESS) { std::string msg("fail to get process list. system error code: "); msg += std::to_string(dwError) + ", refer to: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx"; throw std::runtime_error(msg); } getProcName(appList, nProcInfo, pRgpi); RmEndSession(dwSession); } catch (std::exception const& e) { std::cerr << e.what() << std::endl; RmEndSession(dwSession); } delete[] pRgpi; delete[] pwcs; delete[] pApp; return nProcInfoNeeded; }
int _cdecl wmain() { DWORD dwErrCode = ERROR_SUCCESS; DWORD dwSessionHandle = 0xFFFFFFFF; // Invalid handle value // // CCH_RM_SESSION_KEY: Character count of the // Text-Encoded session key,defined in RestartManager.h // WCHAR sessKey[CCH_RM_SESSION_KEY+1]; // Number of calc files to be registered. DWORD dwFiles = 2; // // NOTE:We register two calc executable files. // The second one is for the redirection of 32 bit calc on // 64 bit machines. Even if you are using a 32 bit machine, // you don't need to comment out the second line. // LPCWSTR rgsFiles[] = {L"C:\\Windows\\System32\\calc.exe", L"C:\\Windows\\SysWow64\\calc.exe"}; UINT nRetry = 0; UINT nAffectedApps = 0; UINT nProcInfoNeeded = 0; RM_REBOOT_REASON dwRebootReasons = RmRebootReasonNone; RM_PROCESS_INFO *rgAffectedApps = NULL; // // Start a Restart Manager Session // dwErrCode = RmStartSession(&dwSessionHandle, 0, sessKey); if (ERROR_SUCCESS != dwErrCode) { goto RM_CLEANUP; } // // Register items with Restart Manager // // NOTE: we only register two calc executable files //in this sample. You can register files, processes // (in the form of process ID), and services (in the // form of service short names) with Restart Manager. // dwErrCode = RmRegisterResources(dwSessionHandle, dwFiles, rgsFiles, // Files 0, NULL, // Processes 0, NULL); // Services if (ERROR_SUCCESS != dwErrCode) { goto RM_CLEANUP; } // // Obtain the list of affected applications/services. // // NOTE: Restart Manager returns the results into the // buffer allocated by the caller. The first call to // RmGetList() will return the size of the buffer // (i.e. nProcInfoNeeded) the caller needs to allocate. // The caller then needs to allocate the buffer // (i.e. rgAffectedApps) and make another RmGetList() // call to ask Restart Manager to write the results // into the buffer. However, since Restart Manager // refreshes the list every time RmGetList()is called, // it is possible that the size returned by the first // RmGetList()call is not sufficient to hold the results // discovered by the second RmGetList() call. Therefore, // it is recommended that the caller follows the // following practice to handle this race condition: // // Use a loop to call RmGetList() in case the buffer // allocated according to the size returned in previous // call is not enough. // // In this example, we use a do-while loop trying to make // 3 RmGetList() calls (including the first attempt to get // buffer size) and if we still cannot succeed, we give up. // do { dwErrCode = RmGetList(dwSessionHandle, &nProcInfoNeeded, &nAffectedApps, rgAffectedApps, (LPDWORD) &dwRebootReasons); if (ERROR_SUCCESS == dwErrCode) { // // RmGetList() succeeded // break; } if (ERROR_MORE_DATA != dwErrCode) { // // RmGetList() failed, with errors // other than ERROR_MORE_DATA // goto RM_CLEANUP; } // // RmGetList() is asking for more data // nAffectedApps = nProcInfoNeeded; if (NULL != rgAffectedApps) { delete []rgAffectedApps; rgAffectedApps = NULL; } rgAffectedApps = new RM_PROCESS_INFO[nAffectedApps]; } while ((ERROR_MORE_DATA == dwErrCode) && (nRetry ++ < 3)); if (ERROR_SUCCESS != dwErrCode) { goto RM_CLEANUP; } if (RmRebootReasonNone != dwRebootReasons) { // // Restart Manager cannot mitigate a reboot. // We goes to the clean up. The caller may want // to add additional code to handle this scenario. // goto RM_CLEANUP; } // // Now rgAffectedApps contains the affected applications // and services. The number of applications and services // returned is nAffectedApps. The result of RmGetList can // be interpreted by the user to determine subsequent // action (e.g. ask user's permission to shutdown). // // CALLER CODE GOES HERE... // // Shut down all running instances of affected // applications and services. // dwErrCode = RmShutdown(dwSessionHandle, 0, NULL); if (ERROR_SUCCESS != dwErrCode) { goto RM_CLEANUP; } // // An installer can now replace or update // the calc executable file. // // CALLER CODE GOES HERE... // // Restart applications and services, after the // files have been replaced or updated. // dwErrCode = RmRestart(dwSessionHandle, 0, NULL); if (ERROR_SUCCESS != dwErrCode) { goto RM_CLEANUP; } RM_CLEANUP: if (NULL != rgAffectedApps) { delete [] rgAffectedApps; rgAffectedApps = NULL; } if (0xFFFFFFFF != dwSessionHandle) { // // Clean up the Restart Manager session. // RmEndSession(dwSessionHandle); dwSessionHandle = 0xFFFFFFFF; } return 0; }