Пример #1
0
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;
}