Back to index

lightning-sunbird  0.9+nobinonly
Defines | Functions | Variables
ipcConnectionWin.cpp File Reference
#include <windows.h>
#include "prprf.h"
#include "prmon.h"
#include "prthread.h"
#include "plevent.h"
#include "nsIServiceManager.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsAutoLock.h"
#include "ipcConfig.h"
#include "ipcLog.h"
#include "ipcConnection.h"
#include "ipcm.h"

Go to the source code of this file.

Defines

#define IPC_WM_SENDMSG   (WM_USER + 0x1)
#define IPC_WM_CALLBACK   (WM_USER + 0x2)
#define IPC_WM_SHUTDOWN   (WM_USER + 0x3)

Functions

static LRESULT CALLBACK ipcThreadWindowProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static void ipcThreadFunc (void *arg)
static PRStatus ipcThreadInit ()
static PRStatus ipcThreadShutdown ()
nsresult IPC_Disconnect ()
 IPC_Disconnect.
nsresult IPC_Connect (const char *daemonPath)
 IPC_Connect.
nsresult IPC_SendMsg (ipcMessage *msg)
 IPC_SendMsg.
nsresult IPC_DoCallback (ipcCallbackFunc func, void *arg)
 IPC_DoCallback.

Variables

static nsresult ipcThreadStatus = NS_OK
static PRThreadipcThread = NULL
static PRMonitoripcMonitor = NULL
static HWND ipcDaemonHwnd = NULL
static HWND ipcLocalHwnd = NULL
static PRBool ipcShutdown = PR_FALSE

Define Documentation

#define IPC_WM_CALLBACK   (WM_USER + 0x2)

Definition at line 70 of file ipcConnectionWin.cpp.

#define IPC_WM_SENDMSG   (WM_USER + 0x1)

Definition at line 69 of file ipcConnectionWin.cpp.

#define IPC_WM_SHUTDOWN   (WM_USER + 0x3)

Definition at line 71 of file ipcConnectionWin.cpp.


Function Documentation

nsresult IPC_Connect ( const char *  daemonPath)

IPC_Connect.

This function causes a connection to the IPC daemon to be established. If a connection already exists, then this function will be ignored.

Parameters:
daemonPathSpecifies the path to the IPC daemon executable.

NOTE: This function must be called on the main thread.

Definition at line 266 of file ipcConnectionWin.cpp.

{
    LOG(("IPC_Connect\n"));

    NS_ENSURE_TRUE(ipcDaemonHwnd == NULL, NS_ERROR_ALREADY_INITIALIZED);
    nsresult rv;

    ipcDaemonHwnd = FindWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME);
    if (!ipcDaemonHwnd) {
        LOG(("  daemon does not appear to be running\n"));
        //
        // daemon does not exist; spawn daemon...
        //
        rv = IPC_SpawnDaemon(daemonPath);
        if (NS_FAILED(rv))
            return rv;

        ipcDaemonHwnd = FindWindow(IPC_WINDOW_CLASS, IPC_WINDOW_NAME);
        if (!ipcDaemonHwnd)
            return NS_ERROR_FAILURE;
    }

    // 
    // delay creation of the message thread until we know the daemon exists.
    //
    if (!ipcThread && ipcThreadInit() != PR_SUCCESS) {
        ipcDaemonHwnd = NULL;
        return NS_ERROR_FAILURE;
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

IPC_Disconnect.

This function causes a connection to the IPC daemon to be closed. Any unsent messages (IPC_SendMsg puts messages on a queue) will be sent to the IPC daemon before the connection is closed.

NOTE: This function must be called on the main thread.

Definition at line 248 of file ipcConnectionWin.cpp.

{
    LOG(("IPC_Disconnect\n"));

    //XXX mHaveConnection = PR_FALSE;
    
    if (!ipcDaemonHwnd)
        return NS_ERROR_NOT_INITIALIZED;

    if (ipcThread)
        ipcThreadShutdown();

    // clear our reference to the daemon's HWND.
    ipcDaemonHwnd = NULL;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

IPC_DoCallback.

This function executes a callback function on the same background thread that calls IPC_OnConnectionEnd and IPC_OnMessageAvailable.

If this function succeeds, then the caller is guaranteed that |func| will be called. This guarantee is important because it allows the caller to free any memory associated with |arg| once |func| has been called.

NOTE: This function may be called on any thread.

Definition at line 319 of file ipcConnectionWin.cpp.

{
    LOG(("IPC_DoCallback\n"));

    if (ipcShutdown) {
        LOG(("unable to send message b/c message thread is shutdown\n"));
        return NS_ERROR_FAILURE;
    }
    if (!PostMessage(ipcLocalHwnd, IPC_WM_CALLBACK, (WPARAM) func, (LPARAM) arg)) {
        LOG(("  PostMessage failed w/ error = %u\n", GetLastError()));
        return NS_ERROR_FAILURE;
    }
    return NS_OK;
}

Here is the caller graph for this function:

IPC_SendMsg.

This function sends a message to the IPC daemon. Typically, the message is put on a queue, to be delivered asynchronously to the IPC daemon. The ipcMessage object will be deleted when IPC_SendMsg is done with it. The caller must not touch |msg| after passing it to IPC_SendMsg.

IPC_SendMsg cannot be called before IPC_Connect or after IPC_Disconnect.

NOTE: This function may be called on any thread.

Definition at line 300 of file ipcConnectionWin.cpp.

{
    LOG(("IPC_SendMsg\n"));

    if (ipcShutdown) {
        LOG(("unable to send message b/c message thread is shutdown\n"));
        goto loser;
    }
    if (!PostMessage(ipcLocalHwnd, IPC_WM_SENDMSG, 0, (LPARAM) msg)) {
        LOG(("  PostMessage failed w/ error = %u\n", GetLastError()));
        goto loser;
    }
    return NS_OK;
loser:
    delete msg;
    return NS_ERROR_FAILURE;
}

Here is the caller graph for this function:

static void ipcThreadFunc ( void arg) [static]

Definition at line 143 of file ipcConnectionWin.cpp.

{
    LOG(("entering message thread\n"));

    DWORD pid = GetCurrentProcessId();

    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.lpfnWndProc = ipcThreadWindowProc;
    wc.lpszClassName = IPC_CLIENT_WINDOW_CLASS;
    RegisterClass(&wc);

    char wName[sizeof(IPC_CLIENT_WINDOW_NAME_PREFIX) + 20];
    PR_snprintf(wName, sizeof(wName), "%s%u", IPC_CLIENT_WINDOW_NAME_PREFIX, pid);

    ipcLocalHwnd = CreateWindow(IPC_CLIENT_WINDOW_CLASS, wName,
                                0, 0, 0, 10, 10, NULL, NULL, NULL, NULL);

    {
        nsAutoMonitor mon(ipcMonitor);
        if (!ipcLocalHwnd)
            ipcThreadStatus = NS_ERROR_FAILURE;
        mon.Notify();
    }

    if (ipcLocalHwnd) {
        MSG msg;
        while (GetMessage(&msg, ipcLocalHwnd, 0, 0))
            DispatchMessage(&msg);

        ipcShutdown = PR_TRUE; // assuming atomic memory write

        DestroyWindow(ipcLocalHwnd);
        ipcLocalHwnd = NULL;
    }

    LOG(("exiting message thread\n"));
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus ipcThreadInit ( ) [static]

Definition at line 184 of file ipcConnectionWin.cpp.

{
    if (ipcThread)
        return PR_FAILURE;

    ipcShutdown = PR_FALSE;

    ipcMonitor = PR_NewMonitor();
    if (!ipcMonitor)
        return PR_FAILURE;

    // spawn message thread
    ipcThread = PR_CreateThread(PR_USER_THREAD, ipcThreadFunc, NULL,
                                PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
                                PR_JOINABLE_THREAD, 0);
    if (!ipcThread) {
        NS_WARNING("thread creation failed");
        PR_DestroyMonitor(ipcMonitor);
        ipcMonitor = NULL;
        return PR_FAILURE;
    }

    // wait for hidden window to be created
    {
        nsAutoMonitor mon(ipcMonitor);
        while (!ipcLocalHwnd && NS_SUCCEEDED(ipcThreadStatus))
            mon.Wait();
    }

    if (NS_FAILED(ipcThreadStatus)) {
        NS_WARNING("message thread failed");
        return PR_FAILURE;
    }

    return PR_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRStatus ipcThreadShutdown ( ) [static]

Definition at line 222 of file ipcConnectionWin.cpp.

{
    if (PR_AtomicSet(&ipcShutdown, PR_TRUE) == PR_FALSE) {
        LOG(("posting IPC_WM_SHUTDOWN message\n"));
        PostMessage(ipcLocalHwnd, IPC_WM_SHUTDOWN, 0, 0);
    }

    LOG(("joining w/ message thread...\n"));
    PR_JoinThread(ipcThread);
    ipcThread = NULL;

    //
    // ok, now the message thread is dead
    //

    PR_DestroyMonitor(ipcMonitor);
    ipcMonitor = NULL;

    return PR_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static LRESULT CALLBACK ipcThreadWindowProc ( HWND  hWnd,
UINT  uMsg,
WPARAM  wParam,
LPARAM  lParam 
) [static]

Definition at line 85 of file ipcConnectionWin.cpp.

{
    LOG(("got message [msg=%x wparam=%x lparam=%x]\n", uMsg, wParam, lParam));

    if (uMsg == WM_COPYDATA) {
        COPYDATASTRUCT *cd = (COPYDATASTRUCT *) lParam;
        if (cd && cd->lpData) {
            ipcMessage *msg = new ipcMessage();
            PRUint32 bytesRead;
            PRBool complete;
            PRStatus rv = msg->ReadFrom((const char *) cd->lpData, cd->cbData,
                                        &bytesRead, &complete);
            if (rv == PR_SUCCESS && complete)
                IPC_OnMessageAvailable(msg); // takes ownership of msg
            else {
                LOG(("  unable to deliver message [complete=%u]\n", complete));
                delete msg;
            }
        }
        return TRUE;
    }

    if (uMsg == IPC_WM_SENDMSG) {
        ipcMessage *msg = (ipcMessage *) lParam;
        if (msg) {
            LOG(("  sending message...\n"));
            COPYDATASTRUCT cd;
            cd.dwData = GetCurrentProcessId();
            cd.cbData = (DWORD) msg->MsgLen();
            cd.lpData = (PVOID) msg->MsgBuf();
            SendMessageA(ipcDaemonHwnd, WM_COPYDATA, (WPARAM) hWnd, (LPARAM) &cd);
            LOG(("  done.\n"));
            delete msg;
        }
        return 0;
    }

    if (uMsg == IPC_WM_CALLBACK) {
        ipcCallbackFunc func = (ipcCallbackFunc) wParam;
        void *arg = (void *) lParam;
        (func)(arg);
        return 0;
    }

    if (uMsg == IPC_WM_SHUTDOWN) {
        IPC_OnConnectionEnd(NS_OK);
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

HWND ipcDaemonHwnd = NULL [static]

Definition at line 76 of file ipcConnectionWin.cpp.

HWND ipcLocalHwnd = NULL [static]

Definition at line 77 of file ipcConnectionWin.cpp.

PRMonitor* ipcMonitor = NULL [static]

Definition at line 75 of file ipcConnectionWin.cpp.

Definition at line 78 of file ipcConnectionWin.cpp.

PRThread* ipcThread = NULL [static]

Definition at line 74 of file ipcConnectionWin.cpp.

Definition at line 73 of file ipcConnectionWin.cpp.