notlstnr.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 815 行 · 第 1/2 页

CPP
815
字号
/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

/* notlstnr.cpp : Defines the entry point for the DLL application.
*                  Handle all the interaction with Services.exe and
*                  with the netwotk. Uses class S4JProxy to interact
*                  with sync4j engine.
*/

#include "stdafx.h"
#include "notlstnr.h"
#include "Notify.h"
#include <stdio.h>
#include <service.h>
#include <iptypes.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Pmpolicy.h>

#include "http/GPRSConnection.h"
#include "s4jproxy.h"
#include "worker.h"
#include "notify/checknet.h"
#include "notify/s4n_service.h"
#include "notify/addresschange.h"
#include "notify/util.h"
#include "pim/SettingFunctions.h"
#include "base/startcmd.h"
#include "base/util/utils.h"
#include "processUtils.h"
#include "localizationUtils.h"
#include "pim/ClientSettings.h"

#include "CTPConfig.h"
#include "CTPManager.h"
#include "CTPMessage.h"  

#define NOTLSTNR_LOG_NAME       "notlstnr.txt"
#define NOTLSTNR_LOG_PATH       ""
#define NOTLSTNR_LOG_TITLE      "Funambol Windows Mobile Notification-Listener Log"
#define NOTLSTNR_MAX_SIZE       100000      // 100k


extern HWND cp_hWnd;

// Service state
static DWORD g_dwServiceState = SERVICE_STATE_UNINITIALIZED;
// Global critical section
static CRITICAL_SECTION g_cs;

//static
DWORD addressChangeHandler(void);
static DWORD acceptConnection(SOCKET sock);

int getPushTypeFromRegistry();


HANDLE moduleHandle = 0;


///////////////////////////////////////////////////////////////////
// Notification Listener: Dll entry
///////////////////////////////////////////////////////////////////
/**
* Dll entry point.
*/
extern "C" BOOL WINAPI DllMain(HANDLE hInstDll, DWORD fdwReason,
        LPVOID lpvReserved) {

    LogLevel l;

    switch (fdwReason) {
        case DLL_PROCESS_ATTACH:
            g_dwServiceState = SERVICE_STATE_UNINITIALIZED;
            InitializeCriticalSection (&g_cs);
            // This DLL does not require thread attatch/deatch
            DisableThreadLibraryCalls((HMODULE)hInstDll);
            
            // Init LOG:
            //Log(1, NOTLSTNR_LOG_PATH, NOTLSTNR_LOG_NAME);
            LOG.setLogPath(NOTLSTNR_LOG_PATH);
            LOG.setLogName(NOTLSTNR_LOG_NAME);
            LOG.reset(NOTLSTNR_LOG_TITLE);
            l = getLOGLevel();
            LOG.setLevel(l);

            LOG.info("Process attach.");
            moduleHandle = hInstDll;
            break;

        case DLL_PROCESS_DETACH:
            DeleteCriticalSection (&g_cs);
            LOG.info("Process detach.");
            moduleHandle = 0;
            break;
    }
    return TRUE;
}


///////////////////////////////////////////////////////////////////
// Notification Listener: service callbaks
///////////////////////////////////////////////////////////////////
/**
* Service callback: not implemented.
*/
APIEXPORT BOOL S4N_Open(
        DWORD dwData,
        DWORD dwAccess,
        DWORD dwShareMode
        ) {
    LOG.debug("Open - dwData: %lx, dwAccess: %lx, dwShareMode: %lx",
              dwData, dwAccess, dwShareMode);

    return TRUE;
}

/**
* Service callback: not implemented.
*/
APIEXPORT BOOL S4N_Close( DWORD dwData) {
    LOG.debug("Close - dwData: %lx", dwData);
    return TRUE;
}

/**
* Service callback: close the socket and exit.
*/
APIEXPORT BOOL S4N_Deinit( DWORD dwData) {
    LOG.debug("Deinit - dwData: %lx", dwData);

    //MessageBox (NULL, TEXT("DeInit"), TEXT("Test"), MB_SETFOREGROUND | MB_OK);
    
    // Stop child threads of STP.
    stopWorker();

    // Stop CTP process: try to send the BYE message and 
    // then close the socket connection.
    LOG.info("Stopping push service");
    CTPManager* ctpManager = CTPManager::getInstance();
    ctpManager->stopCTP();
    stopCheckInternetConnectionWorker(0);

    // Stop CP process (will send a WM_CLOSE msg).
    stopClientPush();

    // Must release the localization DLL if we used it
    if (localizationUtils::isInstantiated()) {
        localizationUtils* language = getLocalizationUtils();
        if (language) {
            delete language;
        }
    }

    // Remove unattended mode
    PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);

    return TRUE;
}

/**
* Service callback: init the service and return the listen port.
*/
APIEXPORT DWORD S4N_Init( DWORD dwData) {
    EnterCriticalSection (&g_cs);
    LogLevel l = getLOGLevel();
    LOG.setLevel(l);

    LOG.debug("S4N_Init");

    if (g_dwServiceState != SERVICE_STATE_UNINITIALIZED) {
        // Someone is trying to load multiple times
        LOG.error("S4ND: ERROR: service already initialized on S4N_Init() call");
        LeaveCriticalSection (&g_cs);
        return 0;
    }

    g_dwServiceState = SERVICE_STATE_STARTING_UP;
    LOG.info("S4ND: S4N_Init success - service is in starting up state");

    // Try to connect to Internet (in a thread).
    starCheckInternetConnectionWorker();

    // Starts the Client-push, in a separate process.
    startClientPush();

    LeaveCriticalSection (&g_cs);
    return getListenerPort();
}

/**
* Service callback: main method containing the service.exe events.
* On IOCTL_SERVICE_REFRESH and IOCTL_SERVICE_NOTIFY_ADDR_CHANGE events, it is invoked
* a new ip address change notification to the server.
* On IOCTL_SERVICE_CONNECTION event it is opened a socket connection listening
* for the server messages
*/
APIEXPORT BOOL S4N_IOControl(
        DWORD dwData,
        DWORD dwCode,
        PBYTE pBufIn,
        DWORD dwLenIn,
        PBYTE pBufOut,
        DWORD dwLenOut,
        PDWORD pdwActualOut
        )
{
    DWORD dwError = ERROR_INVALID_PARAMETER;

    //LOG.debug("IOControl - dwCode: %lx", dwCode);
    EnterCriticalSection (&g_cs);

    switch(dwCode){
        // Control code sent to start a service.  (services start FIN0:)
        case IOCTL_SERVICE_START:
            if (g_dwServiceState != SERVICE_STATE_OFF) {
                LOG.error("S4ND: ERROR: IOCTL_SERVICE_START fails because service is not off. State=<%d>", g_dwServiceState);
                dwError = ERROR_SERVICE_ALREADY_RUNNING;
            }
            else {
                // Notification listener must work in unattended mode
                PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

                LOG.debug("S4ND: State changed to ON");
                g_dwServiceState = SERVICE_STATE_ON;
                dwError = ERROR_SUCCESS;
            }
            break;

        // Control code sent to refresh a service. (services refresh FIN0:)
        case IOCTL_SERVICE_REFRESH:

            if (g_dwServiceState != SERVICE_STATE_ON) {
                LOG.error("S4ND:ERROR:IOCTL_SERVICE_REFRESH fails because service is not on. State=<%d>", g_dwServiceState);
                dwError = ERROR_SERVICE_NOT_ACTIVE;
            }
            else {
                LOG.debug("S4ND: Stop on a refresh");
                g_dwServiceState = SERVICE_STATE_SHUTTING_DOWN;
                stopWorker();
                //Sleep(1000);  no: we don't want to spend time here...
                // Shut the service down, re-read configuration
                // TODO: close connections? Abort sync?
                // (if we have any) and then restart.
                LOG.debug("S4ND: Restarting on refresh");
                g_dwServiceState = SERVICE_STATE_ON;
                dwError = ERROR_SUCCESS;
                addressChangeHandler();
            }
            break;

        // Control code sent to stop a service.  (services stop S4N0:)
        case IOCTL_SERVICE_STOP:
            // No longer accept new network connections.
            // Close existing connections
            if (g_dwServiceState != SERVICE_STATE_ON) {
                LOG.error("S4ND:ERROR:IOCTL_SERVICE_STOP fails.  Service state is not on. Current State=<%d>", g_dwServiceState);
                dwError = ERROR_SERVICE_NOT_ACTIVE;
            }
            else {
                LOG.debug("S4ND: Service stopping");
                stopWorker();
                g_dwServiceState = SERVICE_STATE_OFF;
                dwError = ERROR_SUCCESS;
            }
            break;

        // An application (possibly services.exe itself) is
        // querying for the service's running state.
        case IOCTL_SERVICE_STATUS:
            // No need for critical section since this is an atomic read.
            __try {
                if (pBufOut && dwLenOut == sizeof(DWORD)) {
                    *(DWORD *)pBufOut = g_dwServiceState;
                    if (pdwActualOut)
                        *pdwActualOut = sizeof(DWORD);
                    dwError = ERROR_SUCCESS;
                }
            }
            __except (EXCEPTION_EXECUTE_HANDLER) {
                LOG.error("S4ND: ERROR Invalid pointer on IOCTL_SERVICE_STATUS");
                dwError = ERROR_INVALID_PARAMETER;
            }
            break;
        // Services.exe has completed super-service init for this service.
        // Incoming super-service connections can come in at anytime now.
        case IOCTL_SERVICE_STARTED:
            if (g_dwServiceState != SERVICE_STATE_STARTING_UP) {
                LOG.error("S4ND:ERROR:IOCTL_SERVICE_STARTED failed because state != starting up. State=<%d>", g_dwServiceState);
                dwError = ERROR_SERVICE_ALREADY_RUNNING;
            }
            else {
                LOG.debug("S4ND: IOCTL_SERVICE_STARTED changed state to SERVICE_STATE_ON");
                g_dwServiceState = SERVICE_STATE_ON;
                dwError = ERROR_SUCCESS;
            }
            addressChangeHandler();
            break;

        // IP address changed: notify the server
        case IOCTL_SERVICE_NOTIFY_ADDR_CHANGE:
            dwError = addressChangeHandler();
            break;

        // A new connection request
        case IOCTL_SERVICE_CONNECTION:
            LOG.debug("S4ND: IOCTL_SERVICE_CONNECTION");
            if (dwLenIn != sizeof(SOCKET)) {
                dwError = ERROR_INVALID_PARAMETER;
            }
            else {
                SOCKET sock;

                __try {
                    sock = * ((SOCKET*)pBufIn);
                }
                __except (EXCEPTION_EXECUTE_HANDLER) {
                    dwError = ERROR_INVALID_PARAMETER;
                    break;
                }
                // Call new connection handler
                dwError = acceptConnection(sock);
            }
            break;
        default:
            //LOG.debug("IOControl - dwCode: %lx", dwCode);
            return TRUE;
    }

    if (dwError != ERROR_SUCCESS)
        SetLastError(dwError);

    LeaveCriticalSection(&g_cs);

    return (dwError==ERROR_SUCCESS);
}

/**
* Service callback: not implemented.
*/
APIEXPORT DWORD S4N_Read(
        DWORD dwData,
        LPVOID pBuf,
        DWORD dwLen
        ) {
    LOG.debug("Read - dwData: %lx", dwData);
    return 0;
}

/**
* Service callback: not implemented.
*/
APIEXPORT DWORD S4N_Write(
        DWORD dwData,
        LPVOID pInBuf,
        DWORD dwInLen
        ) {
    LOG.debug("Write - dwData: %lx", dwData);
    return 0;
}


/**
* Service callback: not implemented.
*/
APIEXPORT DWORD S4N_Seek(
        DWORD dwData,
        long pos,
        DWORD type
        ) {
    LOG.debug("Seek - dwData: %lx", dwData);
    return 0;
}



⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?