Thread: Processcreate events?

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    2

    Processcreate events?

    Hello,
    Unfortionally I was unable to find any information on the internet, so that's why I would like to ask it here.
    Is there a function in c++ (ms visual studio 2005) wich warns/calls a function when a new process is created?

    I need to check if a program starts during the time that files are being updated, so the program can stop updating to prevent errors. Any help would be welcome.

    -executed

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    C++ has no concept of processes, which are OS-specific. I'd ask in the Windows Programming forum.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    If you need the program to not run when something else external is happening, then have the external updating program create some sort of sentinel (a temp file, named mutex, semaphore) that the second program can check on startup and if it finds it, stops executing.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm 99.9% sure that there's no such thing in Windows. You could, in theory, scan the process list, but that would be prone to errors.

    If it's your own application and updater, then you could of course have a protocol, but if you have an updater that works together with some other application, there's no simple way to solve it. You could write a wrapper application (that is, really, replace the application's .exe with your own stub application that starts the real application, after syncing with the updater).

    You could prevent the application from starting by opening it in read-only mode with no sharing - but that will stop the application from starting, rather than signaling to you when the application is being used. Likewise, you can stop the application from opening files you are accessing by opening the files you update with no sharing allowed, but again, it won't let you know the app has started, but rather prevent it from opening the file.

    Edit: I should put the "there's no such thing" a bit differently, there is PsSetCreateProcessNotifyRoutine - but that's not available to user-mode code, only driver code can call that. So theoretically, if it's important enough, you could write a small driver that you connect your user-mode code to, and you read a message from whenever a process is created. But writing driver code is never easy, even if this one probably ends up being quite small.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    May 2008
    Posts
    2
    The problem is that when the update process is updating, it must stop updating as soon as the main program starts.
    I was thinking maybe there is a function to do something like virus-scanners do to see when a process is being started they scan.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    http://cboard.cprogramming.com/showthread.php?t=100412

    Here is a complete WMI example of monitoring process creation, put together from the discussion in that thread:
    Code:
    #define _WIN32_DCOM
    
    #include <iostream>
    using namespace std;
    
    #include <comdef.h>
    #include <Wbemidl.h>
    
    #pragma comment(lib, "wbemuuid.lib")
    
    class EventSink : public IWbemObjectSink
    {
        LONG m_lRef;
        bool bDone;
    
    public:
        EventSink() { m_lRef = 0; }
       ~EventSink() { bDone = true; }
    
        virtual ULONG STDMETHODCALLTYPE AddRef();
        virtual ULONG STDMETHODCALLTYPE Release();
        virtual HRESULT STDMETHODCALLTYPE QueryInterface(
                REFIID riid, void** ppv
                );
    
        virtual HRESULT STDMETHODCALLTYPE Indicate( 
                LONG lObjectCount,
                IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
                );
            
        virtual HRESULT STDMETHODCALLTYPE SetStatus( 
                /* [in] */ LONG lFlags,
                /* [in] */ HRESULT hResult,
                /* [in] */ BSTR strParam,
                /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
                );
    };
    
    ULONG EventSink::AddRef()
    {
        return InterlockedIncrement(&m_lRef);
    }
    
    ULONG EventSink::Release()
    {
        LONG lRef = InterlockedDecrement(&m_lRef);
        if(lRef == 0)
            delete this;
        return lRef;
    }
    
    HRESULT EventSink::QueryInterface(REFIID riid, void** ppv)
    {
        if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
        {
            *ppv = (IWbemObjectSink *) this;
            AddRef();
            return WBEM_S_NO_ERROR;
        }
        else return E_NOINTERFACE;
    }
    
    #include <comutil.h>
    _COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
    
    HRESULT EventSink::Indicate(long lObjectCount, IWbemClassObject **apObjArray)
    {
        HRESULT hres = S_OK;
    
        for (int i = 0; i < lObjectCount; i++)
        {
            cout << "Event occurred" << endl;
            IWbemClassObject *pObj = apObjArray[i];
    
            HRESULT hres;
            VARIANT vInst_;
            hres = pObj->Get(L"TargetInstance", 0, &vInst_, 0, 0);
            if (FAILED(hres))
            {
                cout << "Failed to get TargetInstance: " << hres << endl;
                continue;
            }//if
    
            try
            {
                _variant_t vInst;
                vInst.Attach(vInst_); // use C++ class to manage VARIANT
    
                IWbemClassObjectPtr pWin32ProcessObj(vInst);
    
                VARIANT vVar;
                hres = pWin32ProcessObj->Get(L"ExecutablePath", 0, &vVar, 0, 0);
                if (FAILED(hres))
                {
                    cout << "Failed to get ExecutablePath: " << hres << endl;
                }//if
                else
                {
                    _variant_t vExecPath;
                    vExecPath.Attach(vVar);
    
                    wcout << L"ExecPath: " << (const wchar_t*)((_bstr_t)vExecPath) << endl;
                }//else
            }//try
            catch(_com_error &err)
            {
                cout << "caught _com_error: " << err.Error() << endl;
            }//catch
        }//for
    
        return WBEM_S_NO_ERROR;
    }//Indicate
    
    HRESULT EventSink::SetStatus(
                /* [in] */ LONG lFlags,
                /* [in] */ HRESULT hResult,
                /* [in] */ BSTR strParam,
                /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
            )
    {
        if(lFlags == WBEM_STATUS_COMPLETE)
        {
            printf("Call complete. hResult = 0x&#37;X\n", hResult);
        }
        else if(lFlags == WBEM_STATUS_PROGRESS)
        {
            printf("Call in progress.\n");
        }
    
        return WBEM_S_NO_ERROR;
    }    // end of EventSink.cpp
    
    
    int main(int iArgCnt, char ** argv)
    {
        HRESULT hres;
    
        // Step 1: --------------------------------------------------
        // Initialize COM. ------------------------------------------
        hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
        if (FAILED(hres))
        {
            cout << "Failed to initialize COM library. Error code = 0x" 
                 << hex << hres << endl;
            return 1;                  // Program has failed.
        }
    
        // Step 2: --------------------------------------------------
        // Set general COM security levels --------------------------
        // Note: If you are using Windows 2000, you need to specify -
        // the default authentication credentials for a user by using
        // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
        // parameter of CoInitializeSecurity ------------------------
        hres =  CoInitializeSecurity(
            NULL, 
            -1,                          // COM negotiates service
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
            NULL,                        // Authentication info
            EOAC_NONE,                   // Additional capabilities 
            NULL                         // Reserved
            );
    
        if (FAILED(hres))
        {
            cout << "Failed to initialize security. Error code = 0x" 
                 << hex << hres << endl;
            CoUninitialize();
            return 1;                      // Program has failed.
        }
        
        // Step 3: ---------------------------------------------------
        // Obtain the initial locator to WMI -------------------------
        IWbemLocator *pLoc = NULL;
    
        hres = CoCreateInstance(
            CLSID_WbemLocator,             
            0, 
            CLSCTX_INPROC_SERVER, 
            IID_IWbemLocator, (LPVOID *) &pLoc);
     
        if (FAILED(hres))
        {
            cout << "Failed to create IWbemLocator object. "
                 << "Err code = 0x"
                 << hex << hres << endl;
            CoUninitialize();
            return 1;                 // Program has failed.
        }
    
        // Step 4: ---------------------------------------------------
        // Connect to WMI through the IWbemLocator::ConnectServer method
        IWbemServices *pSvc = NULL;
        
        // Connect to the local root\cimv2 namespace
        // and obtain pointer pSvc to make IWbemServices calls.
        hres = pLoc->ConnectServer(
            _bstr_t(L"ROOT\\CIMV2"), 
            NULL,
            NULL, 
            0, 
            NULL, 
            0, 
            0, 
            &pSvc
        );
            
        if (FAILED(hres))
        {
            cout << "Could not connect. Error code = 0x" 
                 << hex << hres << endl;
            pLoc->Release();     
            CoUninitialize();
            return 1;                // Program has failed.
        }
    
        cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
    
        // Step 5: --------------------------------------------------
        // Set security levels on the proxy -------------------------
        hres = CoSetProxyBlanket(
            pSvc,                        // Indicates the proxy to set
            RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx 
            RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx 
            NULL,                        // Server principal name 
            RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
            RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
            NULL,                        // client identity
            EOAC_NONE                    // proxy capabilities 
        );
    
        if (FAILED(hres))
        {
            cout << "Could not set proxy blanket. Error code = 0x" 
                 << hex << hres << endl;
            pSvc->Release();
            pLoc->Release();     
            CoUninitialize();
            return 1;               // Program has failed.
        }
    
        // Step 6: -------------------------------------------------
        // Receive event notifications -----------------------------
    
        // Use an unsecured apartment for security
        IUnsecuredApartment* pUnsecApp = NULL;
    
        hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL, 
            CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment, 
            (void**)&pUnsecApp);
     
        EventSink* pSink = new EventSink;
        pSink->AddRef();
    
        IUnknown* pStubUnk = NULL; 
        pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
    
        IWbemObjectSink* pStubSink = NULL;
        pStubUnk->QueryInterface(IID_IWbemObjectSink,
            (void **) &pStubSink);
    
        // The ExecNotificationQueryAsync method will call
        // The EventQuery::Indicate method when an event occurs
        hres = pSvc->ExecNotificationQueryAsync(
            _bstr_t("WQL"), 
            _bstr_t("SELECT * " 
                    "FROM __InstanceCreationEvent WITHIN 1 "
                    "WHERE TargetInstance ISA 'Win32_Process'"), 
            WBEM_FLAG_SEND_STATUS, 
            NULL, 
            pStubSink);
    
        // Check for errors.
        if (FAILED(hres))
        {
            printf("ExecNotificationQueryAsync failed "
                   "with = 0x%X\n", hres);
            pSvc->Release();
            pLoc->Release();
            pUnsecApp->Release();
            pStubUnk->Release();
            pSink->Release();
            pStubSink->Release();
            CoUninitialize();
            return 1;
        }
    
        // Wait for some event to occur 
        // now would the time to start some apps
        Sleep(10000);
             
        hres = pSvc->CancelAsyncCall(pStubSink);
    
        // Cleanup
        // ========
        pSvc->Release();
        pLoc->Release();
        pUnsecApp->Release();
        pStubUnk->Release();
        pSink->Release();
        pStubSink->Release();
        CoUninitialize();
    
        return 0;
    }
    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sending events with JScript?
    By IcyDeath in forum Networking/Device Communication
    Replies: 1
    Last Post: 12-28-2004, 06:15 PM
  2. Loading cursors on events
    By cfrost in forum C++ Programming
    Replies: 1
    Last Post: 05-13-2004, 09:07 PM
  3. seismic events program
    By santaclaus in forum C Programming
    Replies: 16
    Last Post: 11-23-2003, 03:23 PM
  4. ATL: fireing events from a Instanced object
    By CHECCO in forum C++ Programming
    Replies: 2
    Last Post: 09-03-2002, 07:05 AM
  5. Windows events
    By Unregistered in forum Windows Programming
    Replies: 1
    Last Post: 12-22-2001, 01:44 PM