/*****************************************************************************
 * Copyright (C) Gemalto M2M GmbH
 *****************************************************************************
 * Project: IMC-RIL-Driver
 *****************************************************************************
 * Author : Wireless Modules RD SW A2
 *****************************************************************************
 * $Workfile: Y:/z_ms-d/src/working/Quinn/RilDrv/rilmain.cpp $
 * $Revision: /main/ms-d/40 $
 *     $Date: 2013-04-18 15:51:15 $
 *   $Author: pmackent $
 *****************************************************************************
 * Target:
 *  Microsoft Windows Mobile 5.0
 *****************************************************************************
 * Description:
 *  Gemalto IMC RIL
 *****************************************************************************
 *
 * $Log: Y:/z_ms-d/src/working/Quinn/RilDrv/rilmain.cpp$ 
 * 
 * /main/ms-d/40   2013-04-18 15:51:15   pmackent 
 * Add RIL_GetSignalQuality API for CE7 
 * 
 * /main/ms-d/39   2012-10-30 14:36:08   pmackent 
 * Fix call status problems (voice and data) in CDMA on WinCE6/7 
 * 
 * /main/ms-d/38   2012-07-13 13:04:20   pmackent 
 * Changes for compatibility with Windows CE6/6 
 * 
 * /main/ms-d/37   2012-06-13 10:44:06   pmackent 
 * Added support for CDMA flash
 *
 * /main/ms-d/36   2012-06-08 16:59:32   pmackent
 * Add APIs for CDMA voice privacy
 *
 * /main/ms-d/35   2012-04-26 13:02:31   pmackent
 * Further CDMA specific code
 *
 * /main/ms-d/34   2012-04-18 13:46:27   ctna0256
 * Introducing PVS8
 * Implementing CDMA-SMS
 * Various CDMA enhancements
 *
 * /main/ms-d/33   2011-09-26 13:35:07   ctna0256
 * Comply with CE6 warning level 4
 *
 * /main/ms-d/32   2011-05-30 09:36:17   ctna0256
 * Ignore wrong CREG:0 after CREG:3 (IPIS100073002)
 *
 * /main/ms-d/31   2011-01-20 15:03:58   ctna0256
 * Newly supported RIL-API: RIL_GetAudioDevices()
 *
 * /main/ms-d/30   2010-10-15 11:56:56   ctna0256
 * COLR now supported in PH8
 *
 * /main/ms-d/29   2010-05-07 10:18:39   ctna0256
 * New PPP trace feature needed to find connection problems (IPIS100064425)
 *
 * /main/ms-d/28   2010-03-12 15:01:01   ctna0256
 * Correct hard coded version number.
 * Merge from Microsoft Automotive RIL.
 *
 * /main/ms-d/27   2010-02-03 10:51:18   ctna0256
 * Introduction of WinCE6 support
 *
 * /main/ms-d/26   2010-01-26 09:55:43   ctna0256
 * New API: RIL_GetPositionInfo()
 *
 * /main/ms-d/25   2009-02-18 09:39:54   ctna0256
 * New WM65 API
 *
 * /main/ms-d/24   2008-12-10 15:56:50   ctna0256
 * Set timestamp format with registry key
 *
 * /main/ms-d/23   2008-10-23 11:32:32   ctna0256
 * New trace option (RIL proxy)
 *
 * /main/ms-d/22   2008-10-06 09:25:08   ctna0256
 * Remove support of extended phonebook
 *
 * /main/ms-d/21   2008-09-23 08:50:19   ctna0256
 * Improved handling of writing og extended phonebook entries
 *
 * /main/ms-d/20   2008-09-18 15:24:48   ctna0256
 * Introduction of extended phonebook support in WM6  AKU 1.3
 *
 * /main/ms-d/19   2008-08-22 10:27:24   ctna0256
 * Set Cinterion copyright text
 *
 * /main/ms-d/18   2008-08-21 09:35:20   ctna0256
 * Prepared for new disclaimer handling
 *
 * /main/ms-d/17   2008-07-23 15:17:08   mp49210
 * Additional IOCTL trace
 *
 * /main/ms-d/16   2008-07-09 09:47:21   mp49210
 * New debug traces for IOCTL handling
 *
 * /main/ms-d/15   2008-06-20 11:05:58   mp49210
 * Remove unused SIEMENS_MAGNETO define
 *
 * /main/ms-d/14   2008-05-30 13:32:02   ht37010
 * added debug zone ZONE_PORT
 *
 * /main/ms-d/13   2008-04-16 16:24:26   mp49210
 * Debug zones for RHA traces
 *
 * /main/ms-d/12   2008-04-03 14:41:54   mp49210
 * Introduction of new debug zones
 *
 * /main/ms-d/11   2007-12-11 16:22:19   mp49210
 * Read debug options from registry at attach of rilgsm.dll
 *
 * /main/ms-d/10   2007-11-19 17:43:41   mp49210
 * New WM6 AKU1.0 API
 *
 * /main/ms-d/9   2007-07-13 16:46:05   mp49210
 * New feature RIL_GetCellTowerInfo()
 *
 * /main/ms-d/8   2007-02-26 16:15:36   mp49210
 * New behaviour of CBS, SIM storage and SMS SR
 *
 * /main/ms-d/7   2007-02-21 13:47:58   mp49210
 * Support "RIL_GetAllOperatorsList" on CEPC
 *
 * /main/ms-d/6   2006-12-22 15:06:56   mp49210
 * HC25 doesn't support cell tower info
 *
 * /main/ms-d/5   2006-12-11 16:20:33   mp49210
 * Re-Integration of *#-sequences for GCF approval
 *
 * /main/ms-d/4   2006-11-14 14:40:07   wm36264
 * Disposed unused CRilEventLog
 *
 * /main/ms-d/3   2006-11-14 12:23:47   wm36264
 * Added missing trace init and deinit
 *
 * /main/ms-d/2   2006-11-08 09:35:26   mp49210
 * No COLR in Quinn
 *
 * /main/ms-d/1   2006-10-25 16:51:52   wm36264
 * First transformation from classic RIL
 *
*/

//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008 Gemalto M2M GmbH
// Copyright (C) 2006-2008 Siemens AG
// Copyright (C) 2003 Intrinsyc Europe Ltd.
//
// Version: 1.0
// Date:    dummy
//
//////////////////////////////////////////////////////////////////////////////

/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999  Microsoft Corporation
--*/

#include "precomp.h"
#ifndef RILDRV_CE6
#include <devnotify.h>
#endif
#include "..\..\inc\rilversion.h"
#ifdef RILDRV_CE6
#include <Marshal.hpp>
#endif

//
// Globals
//
CRITICAL_SECTION g_csClosing;
HANDLE g_hCriticalErrorEvent; // = NULL;
static HANDLE g_hDriverPresentEvent; // = NULL;
HANDLE g_hNewDialOrHangupEvent; // = NULL;
DWORD g_dwReadyState;
DWORD g_dwRegStatus;
BOOL g_fRegStatus3detected;
DWORD g_dwGPRSRegStatus;
extern CRITICAL_SECTION g_PPLMNBufferSection;
extern CRITICAL_SECTION g_csPhonebookCmd;
extern CRITICAL_SECTION g_csSCSBInProgress;
#ifdef RIL_LAST_ERROR
DWORD g_dwLastError;            // = 0;
#endif

//Modified for debug
DWORD g_dwDebugZones = 1023;
//DWORD g_dwDebugZones = 0;

//
// Stubs for unsupported RILDrv_ functions
//
#define UNSUPPORTED(n, m) \
HRESULT n m \
{ \
    return E_NOTIMPL; \
}


UNSUPPORTED(RILDrv_SetDTMFMonitoring, (DWORD, BOOL));
UNSUPPORTED(RILDrv_FetchSimToolkitCmd, (DWORD));
UNSUPPORTED(RILDrv_GetCCBSStatus, (DWORD, DWORD));
UNSUPPORTED(RILDrv_ClearCCBSRegistration, (DWORD, DWORD));
UNSUPPORTED(RILDrv_GetSystemTime, (DWORD));
UNSUPPORTED(RILDrv_GetPacketByteCount, (DWORD));
UNSUPPORTED(RILDrv_ResetPacketByteCount, (DWORD));

// These HSCSC and data options are not supported by Cinterion modules.
UNSUPPORTED(RILDrv_GetHSCSDOptions, (DWORD));
UNSUPPORTED(RILDrv_SetHSCSDOptions, (DWORD, RILHSCSDINFO *));
UNSUPPORTED(RILDrv_GetHSCSDCallSettings, (DWORD));

UNSUPPORTED(RILDrv_GetErrorCorrection, (DWORD));
UNSUPPORTED(RILDrv_SetErrorCorrection, (DWORD, RILERRORCORRECTIONINFO *));
#ifdef IOCTL_RIL_DATADORMANT
UNSUPPORTED(RILDrv_DataDormant, (DWORD));
#endif

UNSUPPORTED(RILDrv_SendAKey, (DWORD, LPCSTR));
UNSUPPORTED(RILDrv_SetATLogging, (DWORD, BOOL));
UNSUPPORTED(RILDrv_ATLogFile, (DWORD, LPCTSTR));
UNSUPPORTED(RILDrv_GetATR, (DWORD));
UNSUPPORTED(RILDrv_LogEventToRadio, (DWORD, LPCSTR));

extern RHA_FUNCTION_LIST RHAFunctionList;

HANDLE hInstance;

static BOOL ClearCmdHandle(void* pItem, DWORD dwDummy);

//////////////////////////////////////////////////////////////////////////////

#include "..\..\inc\RilTrace.cpp"

//////////////////////////////////////////////////////////////////////////////

//
// DLL entry point
//
BOOL WINAPI DllMain(HANDLE hinstDll, DWORD dwReason, LPVOID /*lpReserved*/)
{
    hInstance = hinstDll;

    if (DLL_PROCESS_ATTACH == dwReason)
    {
        // Init our possibly used serial port and file trace
        RilTrace(NULL);
        ReadDebugOptions();
    }
    else if (DLL_PROCESS_DETACH == dwReason)
    {
        // Deinit our possibly used serial port and file trace
        RilTrace(NULL);
        ReadDebugOptions();
    }
    return TRUE;
}

#define DRIVERCOOKIE_FROM_RILHANDLE(pDevice)    (DWORD)pDevice;
#define RILHANDLE_FROM_DRIVERCOOKIE(dwData)     (CRilHandle*)dwData;

//
// RIL driver initialization
//
DWORD RIL_Init(DWORD /*dwInfo*/)
{
    CRilHandle* pDevice = NULL;
    DWORD dwRet = 0;

    // Initialize globals
    InitializeCriticalSection(&g_csClosing);
    InitializeCriticalSection(&g_CallInfoSection);
    InitializeCriticalSection(&g_PPLMNBufferSection);
    InitializeCriticalSection(&g_csPhonebookCmd);
    InitializeCriticalSection(&g_csSCSBInProgress);
    g_hCriticalErrorEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!g_hCriticalErrorEvent)
    {
        goto Error;
    }

    g_hDriverPresentEvent = CreateEvent(NULL, TRUE, FALSE, RILDRIVERPRESENT_EVENT);
    if (!g_hDriverPresentEvent)
    {
        goto Error;
    }

    g_hNewDialOrHangupEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!g_hNewDialOrHangupEvent)
    {
        goto Error;
    }

    // Allocate a device handle
    pDevice = new CRilHandle;
    if(RHAFunctionList.pfnRHA_RadioPwrOn == NULL || RHAFunctionList.pfnRHA_RadioPwrOff == NULL || RHAFunctionList.pfnRHA_IsRadioPwrOn == NULL ||
        RHAFunctionList.pfnRHA_ActivateVoicePath == NULL || RHAFunctionList.pfnRHA_DeactivateVoicePath == NULL || RHAFunctionList.pfnRHA_AdjustTxVolume == NULL ||
        RHAFunctionList.pfnRHA_AdjustRxVolume == NULL || RHAFunctionList.pfnRHA_GetRHAVersion == NULL)
    {
        goto Error;
    }
    if (!pDevice || !pDevice->StartInit())
    {
        goto Error;
    }

    dwRet = DRIVERCOOKIE_FROM_RILHANDLE(pDevice);

    // Driver has started successfully, so set
    // the event that says RIL driver is up.
    (void)SetEvent(g_hDriverPresentEvent);

    g_ComManager.Init(pDevice);
    g_PowerManager.Init(pDevice);
    (void)g_GpsHandling.Init(pDevice);

    Error:
    if (!dwRet)
    {
        delete pDevice;
        if (g_hDriverPresentEvent)
        {
            (void)CloseHandle(g_hDriverPresentEvent);
            g_hDriverPresentEvent = NULL;
        }
        if (g_hCriticalErrorEvent)
        {
            (void)CloseHandle(g_hCriticalErrorEvent);
            g_hCriticalErrorEvent = NULL;
        }
        DeleteCriticalSection(&g_CallInfoSection);
        DeleteCriticalSection(&g_PPLMNBufferSection);
        DeleteCriticalSection(&g_csClosing);
        DeleteCriticalSection(&g_csPhonebookCmd);
        DeleteCriticalSection(&g_csSCSBInProgress);
    }

    return dwRet;
}

//
// Driver de-initialization
//
BOOL RIL_Deinit(DWORD dwData)
{
    CRilHandle* pDevice = RILHANDLE_FROM_DRIVERCOOKIE(dwData);
    BOOL fRet = FALSE;

    // Driver is going away. Clear event that
    // says RIL driver is up.
    if (g_hDriverPresentEvent)
    {
        (void)ResetEvent(g_hDriverPresentEvent);
        (void)CloseHandle(g_hDriverPresentEvent);
        g_hDriverPresentEvent = NULL;
    }

    (void)g_GpsHandling.Deinit();
    g_PowerManager.Deinit();
    g_ComManager.Deinit();

    if (!pDevice)
    {
        goto Error;
    }
    delete pDevice;

    if (g_hCriticalErrorEvent)
    {
        (void)CloseHandle(g_hCriticalErrorEvent);
        g_hCriticalErrorEvent = NULL;
    }
    DeleteCriticalSection(&g_CallInfoSection);
    DeleteCriticalSection(&g_PPLMNBufferSection);
    DeleteCriticalSection(&g_csClosing);
    DeleteCriticalSection(&g_csPhonebookCmd);
    DeleteCriticalSection(&g_csSCSBInProgress);
    fRet = TRUE;

    Error:
    return fRet;
}


//
// Open a driver instance
//
DWORD RIL_Open(DWORD dwData, DWORD /*dwAccess*/, DWORD /*dwShareMode*/)
{
    CRilInstanceHandle* pHandle = NULL;
    CRilHandle* pDevice = RILHANDLE_FROM_DRIVERCOOKIE(dwData);
    DWORD dwRet = 0;

    // Wait until the COM port is initialized
    if (!pDevice /* || !pDevice->WaitForInit(MAX_DRIVERINIT_TIME) */ )
    {
        goto Error;
    }

    pHandle = new CRilInstanceHandle;
    if (!pHandle || !pHandle->Init(pDevice))
    {
        goto Error;
    }

    // Insert new handle into the handle list
    if (!pDevice->AddToList(pHandle))
    {
        goto Error;
    }

    dwRet = (DWORD)pHandle;

    Error:
    if (!dwRet)
    {
        delete pHandle;
    }
    return dwRet;
}


//
// Close a driver instance
//
BOOL RIL_Close(DWORD dwOpenData)
{
    CRilInstanceHandle* pHandle = (CRilInstanceHandle*)dwOpenData;

    if (!pHandle)
    {
        return FALSE;
    }

    SYNCBLOCK(g_csClosing);

    // Make sure no commands refer to this handle
    pHandle->GetCmdList()->Enum(ClearCmdHandle, 0);

    // Remove the handle from the handle list
    if (!pHandle->GetDevice()->RemoveFromList(pHandle))
    {
        return FALSE;
    }

    delete pHandle;

    return TRUE;
}



//
// Emulate serial read
//
DWORD RIL_Read(DWORD /*dwOpenData*/, LPVOID /*pBuf*/, DWORD /*len*/)
{
    return 0;
}


//
// Emulate serial write
//
DWORD RIL_Write(DWORD /*dwOpenData*/, LPCVOID /*pBuf*/, DWORD /*len*/)
{
    return 0;
}


//
//
//
DWORD RIL_Seek(DWORD /*dwOpenData*/, long /*pos*/, DWORD /*type*/)
{
    return (DWORD)-1;
}


//
//
//
void RIL_PowerDown(DWORD /*dwData*/)
{
}


//
//
//
void RIL_PowerUp(DWORD /*dwData*/)
{
}


//
// Defines used in the switch below
//
#ifdef RILDRV_CE6
#define CALLDRVAPI_PARAMS(PARAMSTYPE, APICall)              \
    {                                                       \
        PARAMSTYPE##* pParams = (##PARAMSTYPE##*)BufInDuplicate.ptr();    \
        if (BufInDuplicate.ptr() && BufInDuplicate.size() == sizeof(PARAMSTYPE)) {      \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
        ASSERT(BufInDuplicate.ptr() && BufInDuplicate.size() == sizeof(PARAMSTYPE));\
    }

#define CALLDRVAPI_CONSTPARAMS(PARAMSTYPE, APICall)         \
    {                                                       \
        const PARAMSTYPE##* pParams = (##PARAMSTYPE##*)BufInDuplicate.ptr(); \
        if (BufInDuplicate.ptr() && BufInDuplicate.size() == sizeof(PARAMSTYPE)) {      \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
        ASSERT(BufInDuplicate.ptr() && BufInDuplicate.size() == sizeof(PARAMSTYPE));\
    }

#define CALLDRVAPI_VARPARAMS(PARAMSTYPE, APICall)           \
    {                                                       \
        PARAMSTYPE##* pParams = (##PARAMSTYPE##*)BufInDuplicate.ptr();    \
        if (BufInDuplicate.ptr() && (BufInDuplicate.size()  >= sizeof(PARAMSTYPE)) && (pParams->cbSize == BufInDuplicate.size())) {      \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
        ASSERT(BufInDuplicate.ptr() && BufInDuplicate.size() >= sizeof(PARAMSTYPE) && (pParams->cbSize == BufInDuplicate.size()));\
    }

#define CALLDRVAPI_ARRAY(ELEMTYPE, APICall)                 \
    {                                                       \
        ELEMTYPE##* pParams = (##ELEMTYPE##*)BufInDuplicate.ptr();        \
        if (BufInDuplicate.ptr()) {                                       \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
        ASSERT(BufInDuplicate.ptr());\
    }


#define CALLDRVAPI_CONSTARRAY(ELEMTYPE, APICall)            \
    {                                                       \
        const ELEMTYPE##* pParams = (##ELEMTYPE##*)BufInDuplicate.ptr();  \
        if (BufInDuplicate.ptr()) {                                       \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
        ASSERT(BufInDuplicate.ptr());\
    }

#define CALLDRVAPI(APIName)                                 \
    *phr = APIName(dwOpenData);                             \
    dwOutUsed = sizeof(HRESULT);                            \
    fRet = TRUE; \
    ASSERT(NULL == BufInDuplicate.ptr());

#define NULLTERMINATE(ELEMTYPE)                                 \
    {     \
        ELEMTYPE##* pArray = (##ELEMTYPE##*)BufInDuplicate.ptr();  \
        if ( pArray  ) {      \
             pArray[BufInDuplicate.size()/sizeof(*pArray) - 1] = 0;                               \
        }                                                   \
    }
#else
#define CALLDRVAPI_PARAMS(PARAMSTYPE, APICall)              \
    {                                                       \
        PARAMSTYPE##* pParams = (##PARAMSTYPE##*)pBufIn;    \
        if (pBufIn && dwLenIn == sizeof(PARAMSTYPE)) {      \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
    }

#define CALLDRVAPI_VARPARAMS(PARAMSTYPE, APICall)           \
    {                                                       \
        PARAMSTYPE##* pParams = (##PARAMSTYPE##*)pBufIn;    \
        if (pBufIn && dwLenIn >= sizeof(PARAMSTYPE)) {      \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
    }

#define CALLDRVAPI_OPTVARPARAMS(PARAMSTYPE, APICall)        \
    {                                                       \
        PARAMSTYPE##* pParams = (##PARAMSTYPE##*)pBufIn;    \
        if (!pBufIn || dwLenIn >= sizeof(PARAMSTYPE)) {     \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
    }

#define CALLDRVAPI_ARRAY(ELEMTYPE, APICall)                 \
    {                                                       \
        ELEMTYPE##* pParams = (##ELEMTYPE##*)pBufIn;        \
        if (pBufIn) {                                       \
            *phr = APICall;                                 \
            dwOutUsed = sizeof(HRESULT);                    \
            fRet = TRUE;                                    \
        }                                                   \
    }

#define CALLDRVAPI(APIName)                                 \
    *phr = APIName(dwOpenData);                             \
    dwOutUsed = sizeof(HRESULT);                            \
    fRet = TRUE;
#endif

#pragma warning( push )
// Warning disabled to avoid unnecessary ifdef-statement
#pragma warning(disable : 4060)
//
//
//
#ifdef RILDRV_CE6
BOOL RIL_IOControl(DWORD dwOpenData, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, __out_bcount( dwLenOut ) PBYTE pBufOut, DWORD dwLenOut,
                   PDWORD pdwActualOut)
#else
BOOL RIL_IOControl(DWORD dwOpenData, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
                   PDWORD pdwActualOut)
#endif
{
    DWORD dwOutUsed = 0;
    BOOL fRet = FALSE;
#ifdef RILDRV_CE6
    DuplicatedBuffer_t BufInDuplicate;
    DuplicatedBuffer_t BufOutDuplicate;
    DuplicatedBuffer_t BufActualOut;
#endif

    CRilInstanceHandle* pHandle = (CRilInstanceHandle*)dwOpenData;
    if (!pHandle)
    {
        goto Error;
    }

#ifdef RILDRV_CE6
    /* There are quite a few possibilies for in/out coming in to this function:
        RIL API:
            pBufIn = NULL or data
            pBufOut should always be populated and have a size.

        Direct RIL IO control calls:
            The RIl proxy makes other IOCTL calls. They consist of the following possibilities
            pBufIn = NULL or  data
            pBufOut = NULL or data

        Since there are all type of possibilites,  it's up to the  individual IOCTL to confirm the correct information is present.  */
    if ( (pBufIn && !dwLenIn) || \
         (pBufOut && !dwLenOut) || \
         (!pBufIn && dwLenIn) || \
         (!pBufOut && dwLenOut) ||  \
         (pBufOut && !pdwActualOut))
    {
        ASSERT(FALSE);
        goto Error;
    }
    if ( pBufIn )
    {
        if ( FAILED(BufInDuplicate.Allocate(pBufIn, dwLenIn, ARG_I_PTR)))
        {
            goto Error;
        }
    }

    if ( pBufOut)
    {
        if ( FAILED(BufOutDuplicate.Allocate(pBufOut, dwLenOut, ARG_O_PTR)))
        {
            goto Error;
        }
    }

    if ( pdwActualOut )
    {
        if ( FAILED(BufActualOut.Allocate(pdwActualOut, sizeof(DWORD), ARG_O_PTR)))
        {
            goto Error;
        }
    }
#endif

    switch (dwCode)
    {
#ifdef RIL_ENABLE_POWER_HANDLING
#ifdef RILDRV_CE6
        // Power managing interface
    case IOCTL_POWER_CAPABILITIES:
        if (BufOutDuplicate.ptr() && BufActualOut.ptr() && (BufOutDuplicate.size() >= sizeof (POWER_CAPABILITIES))) {
          g_PowerManager.FillPowerCapsStruct((PPOWER_CAPABILITIES)BufOutDuplicate.ptr());
          *((DWORD*)BufActualOut.ptr()) = sizeof(POWER_CAPABILITIES);
          fRet = TRUE;
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
    case IOCTL_POWER_GET:
        if (BufOutDuplicate.ptr() && BufActualOut.ptr() && (BufOutDuplicate.size() >= sizeof (CEDEVICE_POWER_STATE))) {
          *(PCEDEVICE_POWER_STATE)BufOutDuplicate.ptr() = g_PowerManager.GetPowerState();
          *((DWORD*)BufActualOut.ptr()) = sizeof(CEDEVICE_POWER_STATE);
          fRet = TRUE;
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
    case IOCTL_POWER_SET:
        if (BufOutDuplicate.ptr() && BufActualOut.ptr() && (BufOutDuplicate.size() >= sizeof (CEDEVICE_POWER_STATE))) {
          if (SUCCEEDED(RILDrv_SetPowerState(dwOpenData, *(PCEDEVICE_POWER_STATE)BufOutDuplicate.ptr()))) {
            fRet = TRUE;
          }
          *(PCEDEVICE_POWER_STATE)BufOutDuplicate.ptr() = g_PowerManager.GetPowerState();
          *((DWORD*)BufActualOut.ptr()) = sizeof(CEDEVICE_POWER_STATE);
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
        // End of power managing interface
#else
        // Power managing interface
    case IOCTL_POWER_CAPABILITIES:
        if (pBufOut && pdwActualOut && (dwLenOut >= sizeof (POWER_CAPABILITIES))) {
          g_PowerManager.FillPowerCapsStruct((PPOWER_CAPABILITIES)pBufOut);
          *pdwActualOut = sizeof(POWER_CAPABILITIES);
          fRet = TRUE;
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
    case IOCTL_POWER_GET:
        if (pBufOut && pdwActualOut && (dwLenOut >= sizeof (CEDEVICE_POWER_STATE))) {
          *(PCEDEVICE_POWER_STATE)pBufOut = g_PowerManager.GetPowerState();
          *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
          fRet = TRUE;
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
    case IOCTL_POWER_SET:
        if (pBufOut && pdwActualOut && (dwLenOut >= sizeof (CEDEVICE_POWER_STATE))) {
          if (SUCCEEDED(RILDrv_SetPowerState(dwOpenData, *(PCEDEVICE_POWER_STATE)pBufOut))) {
            fRet = TRUE;
          }
          *(PCEDEVICE_POWER_STATE)pBufOut = g_PowerManager.GetPowerState();
          *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
        } else {
          SetLastError(ERROR_INVALID_PARAMETER);
        }
        goto Error;
        // End of power managing interface
#endif
#endif // RIL_ENABLE_POWER_HANDLING

#ifndef RILDRV_CE6
        // Handle the headset IOCTLs
    case IOCTL_CARKIT_ADD_NOTIFY_HWND:
        // Not Supported
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;

    case IOCTL_CARKIT_REMOVE_NOTIFY_HWND:
        // Not Supported
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;

    case IOCTL_HEADSET_ADD_NOTIFY_HWND:
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;

    case IOCTL_HEADSET_REMOVE_NOTIFY_HWND:
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;

    case IOCTL_SPEAKER_ADD_NOTIFY_HWND:
        // Not Supported
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;

    case IOCTL_SPEAKER_REMOVE_NOTIFY_HWND:
        // Not Supported
        SetLastError (ERROR_NOT_SUPPORTED);
        goto Error;
#endif
    }

#ifndef RILDRV_CE6
    if(SUCCEEDED(ValidateAPIPermission(TEXT("RILGSM"), TEXT("IOControl"), VAP_TRUST_CALLER)))  // Perform security check
#endif
    {
		// Only data mode supported on ELS6x
		if(SUPPORTS_ONLY_DATAMODE && ( dwCode == IOCTL_RIL_GETCALLERIDSETTINGS
			 || dwCode == IOCTL_RIL_GETHIDEIDSETTINGS || dwCode == IOCTL_RIL_SETHIDEIDSTATUS
			 || dwCode == IOCTL_RIL_GETDIALEDIDSETTINGS || dwCode == IOCTL_RIL_SETDIALEDIDSTATUS
			 || dwCode == IOCTL_RIL_GETHIDECONNECTEDIDSETTINGS || dwCode == IOCTL_RIL_SETHIDECONNECTEDIDSTATUS
			 || dwCode == IOCTL_RIL_GETCLOSEDGROUPSETTINGS || dwCode == IOCTL_RIL_SETCLOSEDGROUPSETTINGS
			 || dwCode == IOCTL_RIL_GETCALLFORWARDINGSETTINGS || dwCode == IOCTL_RIL_ADDCALLFORWARDING
			 || dwCode == IOCTL_RIL_REMOVECALLFORWARDING || dwCode == IOCTL_RIL_SETCALLFORWARDINGSTATUS
			 || dwCode == IOCTL_RIL_GETCALLWAITINGSETTINGS || dwCode == IOCTL_RIL_SETCALLWAITINGSTATUS
			 || dwCode == IOCTL_RIL_DIAL || dwCode == IOCTL_RIL_ANSWER
			 || dwCode == IOCTL_RIL_HANGUP || dwCode == IOCTL_RIL_MANAGECALLS
			 || dwCode == IOCTL_RIL_TRANSFERCALL || dwCode == IOCTL_RIL_GETBEARERSERVICEOPTIONS
			 || dwCode == IOCTL_RIL_SETBEARERSERVICEOPTIONS || dwCode == IOCTL_RIL_GETRLPOPTIONS
			 || dwCode == IOCTL_RIL_SETRLPOPTIONS || dwCode == IOCTL_RIL_GETCALLBARRINGSTATUS
			 || dwCode == IOCTL_RIL_SETCALLBARRINGSTATUS || dwCode == IOCTL_RIL_CHANGECALLBARRINGPASSWORD
			 || dwCode == IOCTL_RIL_CHANGECALLBARRINGPASSWORDEX || dwCode == IOCTL_RIL_GETCOSTINFO
			 || dwCode == IOCTL_RIL_SETCOSTINFO || dwCode == IOCTL_RIL_SETCALLERIDSTATUS)){
			SetLastError (ERROR_NOT_SUPPORTED);
        	goto Error;
		} 

		//ELS6x don't support Audio
		if(UNSUPPORTS_AUDIO && (dwCode == IOCTL_RIL_SENDDTMF || dwCode == IOCTL_RIL_SETDTMFMONITORING
			|| dwCode == IOCTL_RIL_GETAUDIOGAIN || dwCode == IOCTL_RIL_SETAUDIOGAIN
			|| dwCode == IOCTL_RIL_GETAUDIODEVICES || dwCode == IOCTL_RIL_SETAUDIODEVICES
			|| dwCode == IOCTL_RIL_GETAUDIOMUTING || dwCode == IOCTL_RIL_SETAUDIOMUTING)){
			SetLastError (ERROR_NOT_SUPPORTED);
        	goto Error;
		}

#ifndef RILDRV_CE6
		if(SUPPORTS_ONLY_DATAMODE && (dwCode == IOCTL_RIL_GETLINESTATUS || dwCode == IOCTL_RIL_GETCALLLIST)){
			SetLastError (ERROR_NOT_SUPPORTED);
        	goto Error;
		}
#endif

        switch (dwCode)
        {
        // CPM is ready for us to register with it
        case IOCTL_RIL_REGISTERWITHCPM:
            {
                CRilHandle* pRilDevice = pHandle->GetDevice();
                fRet = pRilDevice->RegisterWithCPM();
            }
            break;

            // This handle will be used for an emergency call - it should be marked as preferred and RIL should be
            //    switched into "emergency mode"
        case IOCTL_RIL_EMERGENCYSTATUS:
            fRet = pHandle->MakePreferred();
            break;

            // Initialize notification delivery
        case IOCTL_RIL_INITNOTIFICATIONS:
#ifdef RILDRV_CE6
            if (BufInDuplicate.ptr() && BufOutDuplicate.ptr())
            {
                fRet = pHandle->CreateNotificationQueue((LPCTSTR)BufInDuplicate.ptr(), (PBYTE)BufOutDuplicate.ptr(), BufOutDuplicate.size(), &dwOutUsed);
            }
#else
            if (pBufIn)
            {
                fRet = pHandle->CreateNotificationQueue((LPCTSTR)pBufIn, pBufOut, dwLenOut, &dwOutUsed);
            }
#endif
            break;

            // Get next RIL notification
        case IOCTL_RIL_GETNEXTNOTIFICATION:
            {
#ifdef RILDRV_CE6
                if ( BufOutDuplicate.ptr() && BufOutDuplicate.size() >= sizeof(RILDRVNOTIFICATION))
                {
                    RILDRVNOTIFICATION* pResult = (RILDRVNOTIFICATION*)BufOutDuplicate.ptr() ;
                    if( SUCCEEDED(RILDrv_GetNextNotification(dwOpenData, pResult)))
                    {
                        dwOutUsed = BufOutDuplicate.size();
                        fRet = TRUE;
                    }
                }
                break;
#else
                RILDRVNOTIFICATION* pResult = (RILDRVNOTIFICATION*)pBufOut;
                if (pBufOut && dwLenOut >= sizeof(RILDRVNOTIFICATION) &&
                    SUCCEEDED(RILDrv_GetNextNotification(dwOpenData, pResult)))
                {

                    dwOutUsed = pResult->cbSize;
                    fRet = TRUE;
                }
                break;
#endif
            }

            // RIL_GetSerialPortStatistics()
        case IOCTL_RIL_GETSERIALPORTSTATISTICS:
            {
#ifdef RILDRV_CE6
                if ((BufOutDuplicate.ptr() && sizeof(RILSERIALPORTSTATS) == BufOutDuplicate.size()))
                {
                    RILSERIALPORTSTATS* pResult = (RILSERIALPORTSTATS*)BufOutDuplicate.ptr();
                    if ( SUCCEEDED(RILDrv_GetSerialPortStatistics(dwOpenData, pResult)))
                    {
                        dwOutUsed = BufOutDuplicate.size();
                        fRet = TRUE;
                    }
                }
                break;
#else
                RILSERIALPORTSTATS* pResult = (RILSERIALPORTSTATS*)pBufOut;
                if (pBufOut && dwLenOut >= sizeof(RILSERIALPORTSTATS) &&
                    SUCCEEDED(RILDrv_GetSerialPortStatistics(dwOpenData, pResult)))
                {

                    dwOutUsed = sizeof(RILSERIALPORTSTATS);
                    fRet = TRUE;
                }
                break;
#endif
            }

            // RIL_GetDriverVersion()
        case IOCTL_RIL_GETDRIVERVERSION:
            {
#ifdef RILDRV_CE6
                if (BufOutDuplicate.ptr() && sizeof(DWORD) == BufOutDuplicate.size())
                {
                    DWORD *pResult = (DWORD *)BufOutDuplicate.ptr();
                    // For now, versioning is going to be done manually on an as needed basis
                    *pResult = (DWORD)RIL_VERSION_NUM;
                    dwOutUsed = BufOutDuplicate.size();
                    fRet = TRUE;
                }
                break;
#else
                if (pBufOut && (dwLenOut >= sizeof(DWORD)))
                {
                    *((PDWORD)pBufOut) = (DWORD)RIL_VERSION_NUM;
                    dwOutUsed = sizeof(DWORD);
                    fRet = TRUE;
                }
                break;
#endif
            }

#ifndef RILDRV_CE6
#if defined(IOCTL_RIL_GETDRIVERVERSIONEX)
        case IOCTL_RIL_GETDRIVERVERSIONEX:
            {
                DEFRILVERSIONEX( RilDriverVersionEx );
                const LPRILVERSIONEX pRilDriverVersionExBuf = (LPRILVERSIONEX)pBufOut;
                if ( !pRilDriverVersionExBuf || (dwLenOut < sizeof(RilDriverVersionEx)) )
                {
                    break;
                }
                fRet = CeSafeCopyMemory( pRilDriverVersionExBuf, &RilDriverVersionEx, sizeof(RilDriverVersionEx) );
                if ( fRet )
                {
                    dwOutUsed = sizeof(RilDriverVersionEx);
                }
                break;
            }
#endif
#endif

#ifdef RIL_LAST_ERROR
        case IOCTL_RIL_GETLASTERROR:
            {
#ifdef RILDRV_CE6
                if (BufInDuplicate.ptr() && sizeof(DWORD) == BufOutDuplicate.size())
                {
                    DWORD *pResult = (DWORD *)BufInDuplicate.ptr();
                    // Give them back the error
                    *pResult = g_dwLastError;
                    dwOutUsed = BufOutDuplicate.size();
                    fRet = TRUE;
                }
                break;
#else
                DWORD *pResult = (DWORD *)pBufOut;
                if (pBufOut && dwLenOut >= sizeof(DWORD))
                {
                    // Give them back the error
                    *pResult = g_dwLastError;
                    dwOutUsed = sizeof(DWORD);
                    fRet = TRUE;
                }
                break;
#endif
            }
            break;
#endif
        case IOCTL_PSL_NOTIFY:
            {
                pHandle->CancelNotifications();
                fRet = TRUE;
                break;
            }

        case IOCTL_RIL_GETSERIALPORTHANDLEFROMCONTEXTID:
            {
#ifdef RILDRV_CE6
                if ( BufInDuplicate.ptr() && sizeof(DWORD) == BufInDuplicate.size() && BufOutDuplicate.ptr() )
                {
                    TCHAR* szPort = g_ComManager.GetPortName(g_ComManager.GetPortFromContextId(*((DWORD*)BufInDuplicate.ptr())));
                    if (szPort)
                    {
                        if ((_tcslen(szPort) + 1) < BufOutDuplicate.size())
                        {
                            (void)_tcscpy((TCHAR*) BufOutDuplicate.ptr(), szPort);
                            dwOutUsed = _tcslen((TCHAR*)BufOutDuplicate.ptr());
                            fRet = TRUE;
                        }
                    }
                }
                TraceIOCTLCallSerialPort(fRet, (PBYTE)BufOutDuplicate.ptr(), dwOutUsed);
                break;
#else
                if (pBufIn && (dwLenIn >= sizeof(DWORD)))
                {
                    TCHAR* szPort = g_ComManager.GetPortName(g_ComManager.GetPortFromContextId(*((DWORD*)pBufIn)));
                    if (szPort)
                    {
                        if ((_tcslen(szPort) + 1) < dwLenOut)
                        {
                            (void)_tcscpy((TCHAR*)pBufOut, szPort);
                            dwOutUsed = _tcslen((TCHAR*)pBufOut);
                            fRet = TRUE;
                        }
                    }
                }
                TraceIOCTLCallSerialPort(fRet, pBufOut, dwOutUsed);
                break;
#endif
            }

        // Other RIL_ APIs
        default:
            {
#ifdef RILDRV_CE6
                HRESULT* phr = (HRESULT*)BufOutDuplicate.ptr() ;
                if (NULL == BufOutDuplicate.ptr()  || BufOutDuplicate.size() != sizeof(HRESULT))
                {
                    goto Error;
                }
                TraceIOCTLCall(dwCode, (PBYTE)BufInDuplicate.ptr(), BufInDuplicate.size());
#else
                HRESULT* phr = (HRESULT*)pBufOut;
                if (!pBufOut || dwLenOut < sizeof(HRESULT))
                {
                    goto Error;
                }
                TraceIOCTLCall(dwCode, pBufIn, dwLenIn);
#endif

                switch (dwCode)
                {
                // RIL_GetSubscriberNumbers()
                case IOCTL_RIL_GETSUBSCRIBERNUMBERS:
                    CALLDRVAPI(RILDrv_GetSubscriberNumbers);
                    break;

                    // RIL_GetOperatorList()
                case IOCTL_RIL_GETOPERATORLIST:
                    CALLDRVAPI(RILDrv_GetOperatorList);
                    break;

                    // RIL_GetPreferredOperatorList()
                case IOCTL_RIL_GETPREFERREDOPERATORLIST:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetPreferredOperatorList(dwOpenData, *pParams));
                    break;

                    // RIL_AddPreferredOperator()
                case IOCTL_RIL_ADDPREFERREDOPERATOR:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(ADDPREFERREDOPERATOR_PARAMS) == BufInDuplicate.size())
                    {
                        LPADDPREFERREDOPERATOR_PARAMS pAPOP = (LPADDPREFERREDOPERATOR_PARAMS)BufInDuplicate.ptr();
                        pAPOP->ronOperatorNames.szLongName[ARRAY_LENGTH(pAPOP->ronOperatorNames.szLongName)-1] = 0;
                        pAPOP->ronOperatorNames.szNumName[ARRAY_LENGTH(pAPOP->ronOperatorNames.szNumName)-1] = 0;
                        pAPOP->ronOperatorNames.szShortName[ARRAY_LENGTH(pAPOP->ronOperatorNames.szShortName)-1] = 0;
                        pAPOP->ronOperatorNames.szCountryCode[ARRAY_LENGTH(pAPOP->ronOperatorNames.szCountryCode)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(ADDPREFERREDOPERATOR_PARAMS, RILDrv_AddPreferredOperator(dwOpenData, \
                                                                                                            pParams->dwIndex, &pParams->ronOperatorNames));
                    break;

                    // RIL_RemovePreferredOperator()
                case IOCTL_RIL_REMOVEPREFERREDOPERATOR:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_RemovePreferredOperator(dwOpenData, *pParams));
                    break;

                    // RIL_GetCurrentOperator()
                case IOCTL_RIL_GETCURRENTOPERATOR:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetCurrentOperator(dwOpenData, *pParams));
                    break;
                    // RIL_GetAllOperatorsList()
                case IOCTL_RIL_GETALLOPERATORSLIST:
                    CALLDRVAPI(RILDrv_GetAllOperatorsList);
                    break;
                    // RIL_RegisterOnNetwork()
                case IOCTL_RIL_REGISTERONNETWORK:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(REGISTERONNETWORK_PARAMS) == BufInDuplicate.size())
                    {
                        LPREGISTERONNETWORK_PARAMS pRONP = (LPREGISTERONNETWORK_PARAMS)BufInDuplicate.ptr();
                        pRONP->ronOperatorNames.szLongName[ARRAY_LENGTH(pRONP->ronOperatorNames.szLongName)-1] = 0;
                        pRONP->ronOperatorNames.szNumName[ARRAY_LENGTH(pRONP->ronOperatorNames.szNumName)-1] = 0;
                        pRONP->ronOperatorNames.szShortName[ARRAY_LENGTH(pRONP->ronOperatorNames.szShortName)-1] = 0;
                        pRONP->ronOperatorNames.szCountryCode[ARRAY_LENGTH(pRONP->ronOperatorNames.szCountryCode)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(REGISTERONNETWORK_PARAMS, RILDrv_RegisterOnNetwork(dwOpenData, pParams->dwMode, \
                                                                                                      &pParams->ronOperatorNames));
                    break;
                case IOCTL_RIL_UNREGISTERFROMNETWORK:
                    CALLDRVAPI(RILDrv_UnregisterFromNetwork);
                    break;

                    // RIL_GetRegistrationStatus()
                case IOCTL_RIL_GETREGISTRATIONSTATUS:
                    CALLDRVAPI(RILDrv_GetRegistrationStatus);
                    break;

                    // RIL_GetCallerIdSettings()
                case IOCTL_RIL_GETCALLERIDSETTINGS:
                    CALLDRVAPI(RILDrv_GetCallerIdSettings);
                    break;

                    // RIL_SetCallerIdStatus()
                case IOCTL_RIL_SETCALLERIDSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetCallerIdStatus(dwOpenData, *pParams));
                    break;

                    // RIL_GetHideIdSettings()
                case IOCTL_RIL_GETHIDEIDSETTINGS:
                    CALLDRVAPI(RILDrv_GetHideIdSettings);
                    break;

                    // RIL_SetHideIdStatus()
                case IOCTL_RIL_SETHIDEIDSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetHideIdStatus(dwOpenData, *pParams));
                    break;

                    // RIL_GetDialedIdSettings()
                case IOCTL_RIL_GETDIALEDIDSETTINGS:
                    CALLDRVAPI(RILDrv_GetDialedIdSettings);
                    break;

                    // RIL_SetDialedIdStatus()
                case IOCTL_RIL_SETDIALEDIDSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetDialedIdStatus(dwOpenData, *pParams));
                    break;

                    // RIL_GetHideConnectedIdSettings()
                case IOCTL_RIL_GETHIDECONNECTEDIDSETTINGS:
                    CALLDRVAPI(RILDrv_GetHideConnectedIdSettings);
                    break;

                    // RIL_SetHideConnectedIdStatus()
                case IOCTL_RIL_SETHIDECONNECTEDIDSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetHideConnectedIdStatus(dwOpenData, *pParams));
                    break;

                    // RIL_GetClosedGroupSettings()
                case IOCTL_RIL_GETCLOSEDGROUPSETTINGS:
                    CALLDRVAPI(RILDrv_GetClosedGroupSettings);
                    break;

                    // RIL_SetClosedGroupSettings()
                case IOCTL_RIL_SETCLOSEDGROUPSETTINGS:
                    CALLDRVAPI_PARAMS(RILCLOSEDGROUPSETTINGS, RILDrv_SetClosedGroupSettings(dwOpenData, pParams));
                    break;

                    // RIL_GetCallForwardingSettings()
                case IOCTL_RIL_GETCALLFORWARDINGSETTINGS:
                    CALLDRVAPI_PARAMS(GETCALLFORWARDING_PARAMS, RILDrv_GetCallForwardingSettings(dwOpenData, pParams->dwReason, pParams->dwInfoClasses));
                    break;

                    // RIL_AddCallForwarding()
                case IOCTL_RIL_ADDCALLFORWARDING:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(ADDCALLFORWARDING_PARAMS) == BufInDuplicate.size())
                    {
                        LPADDCALLFORWARDING_PARAMS pACFP = (LPADDCALLFORWARDING_PARAMS)BufInDuplicate.ptr();
                        pACFP->rcfsSettings.raAddress.wszAddress[ARRAY_LENGTH(pACFP->rcfsSettings.raAddress.wszAddress)-1] = 0;
                        pACFP->rcfsSettings.rsaSubAddress.wszSubAddress[ARRAY_LENGTH(pACFP->rcfsSettings.rsaSubAddress.wszSubAddress)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(ADDCALLFORWARDING_PARAMS, RILDrv_AddCallForwarding(dwOpenData, pParams->dwReason, \
                                                                                                      &pParams->rcfsSettings));
                    break;

                    // RIL_RemoveCallForwarding()
                case IOCTL_RIL_REMOVECALLFORWARDING:
                    CALLDRVAPI_PARAMS(REMOVECALLFORWARDING_PARAMS, RILDrv_RemoveCallForwarding(dwOpenData, \
                                                                                                            pParams->dwReason, pParams->dwInfoClasses));
                    break;

                    // RIL_SetCallForwardingStatus()
                case IOCTL_RIL_SETCALLFORWARDINGSTATUS:
                    CALLDRVAPI_PARAMS(SETCALLFORWARDINGSTATUS_PARAMS, RILDrv_SetCallForwardingStatus(dwOpenData, \
                                                                                                     pParams->dwReason, \
                                                                                                     pParams->dwInfoClasses, \
                                                                                                     pParams->dwStatus));
                    break;

                    // RIL_GetCallWaitingSettings()
                case IOCTL_RIL_GETCALLWAITINGSETTINGS:
                    CALLDRVAPI_PARAMS(GETCALLWAITINGSTATUS_PARAMS, RILDrv_GetCallWaitingSettings(dwOpenData, pParams->dwInfoClasses));
                    break;

                    // RIL_SetCallWaitingStatus()
                case IOCTL_RIL_SETCALLWAITINGSTATUS:
                    CALLDRVAPI_PARAMS(SETCALLWAITINGSTATUS_PARAMS, RILDrv_SetCallWaitingStatus(dwOpenData, \
                                                                                                            pParams->dwInfoClasses, pParams->dwStatus));
                    break;

                    // RIL_SendSupServiceData()
                case IOCTL_RIL_SENDSUPSERVICEDATA:
#ifdef RILDRV_CE6
                    NULLTERMINATE(WCHAR);
                    CALLDRVAPI_CONSTARRAY(BYTE, RILDrv_SendSupServiceData(dwOpenData, pParams, BufInDuplicate.size()));
#else
                    CALLDRVAPI_ARRAY(BYTE, RILDrv_SendSupServiceData(dwOpenData, pParams, dwLenIn));
#endif
                    break;

                    // RIL_CancelSupServiceDataSession()
                case IOCTL_RIL_CANCELSUPSERVICEDATASESSION:
                    CALLDRVAPI(RILDrv_CancelSupServiceDataSession);
                    break;

                    // RIL_GetCurrentAddressId()
                case IOCTL_RIL_GETCURRENTADDRESSID:
                    CALLDRVAPI(RILDrv_GetCurrentAddressId);
                    break;

                    // RIL_SetCurrentAddressId()
                case IOCTL_RIL_SETCURRENTADDRESSID:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetCurrentAddressId(dwOpenData, *pParams));
                    break;

                    // RIL_Dial()
                case IOCTL_RIL_DIAL:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(DIAL_PARAMS) == BufInDuplicate.size())
                    {
                        LPDIAL_PARAMS pDP = (LPDIAL_PARAMS)BufInDuplicate.ptr();
                        pDP->szAddress[ARRAY_LENGTH(pDP->szAddress)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(DIAL_PARAMS, RILDrv_Dial(dwOpenData, pParams->szAddress, pParams->dwType, \
                                                                            pParams->dwOptions));
                    break;

                    // RIL_Asnwer()
                case IOCTL_RIL_ANSWER:
                    CALLDRVAPI(RILDrv_Answer);
                    break;

                    // RIL_Hangup()
                case IOCTL_RIL_HANGUP:
                    CALLDRVAPI(RILDrv_Hangup);
                    break;

                    // RIL_SendDTMF()
                case IOCTL_RIL_SENDDTMF:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(SENDDTMF_PARAMS) == BufInDuplicate.size())
                    {
                        LPSENDDTMF_PARAMS pSDP = (LPSENDDTMF_PARAMS)BufInDuplicate.ptr();
                        pSDP->szDTMF[ARRAY_LENGTH(pSDP->szDTMF)-1] = 0;
                    }
#endif
                    CALLDRVAPI_ARRAY(SENDDTMF_PARAMS, RILDrv_SendDTMF(dwOpenData, pParams->szDTMF, pParams->dwDuration));
                    break;

                    // RIL_SetDTMFMonitoring()
                case IOCTL_RIL_SETDTMFMONITORING:
                    CALLDRVAPI_PARAMS(BOOL, RILDrv_SetDTMFMonitoring(dwOpenData, *pParams));
                    break;

#ifndef RILDRV_CE6
                    // RIL_GetCallList()
                case IOCTL_RIL_GETCALLLIST:
                    CALLDRVAPI(RILDrv_GetCallList);
                    break;
#endif

                    // RIL_ManageCalls()
                case IOCTL_RIL_MANAGECALLS:
                    CALLDRVAPI_PARAMS(MANAGECALLS_PARAMS, RILDrv_ManageCalls(dwOpenData, pParams->dwCommand, pParams->dwID));
                    break;

                    // RIL_TransferCall()
                case IOCTL_RIL_TRANSFERCALL:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(TRANSFERCALL_PARAMS) == BufInDuplicate.size())
                    {
                        LPTRANSFERCALL_PARAMS pTCP = (LPTRANSFERCALL_PARAMS)BufInDuplicate.ptr();
                        pTCP->raAddress.wszAddress[ARRAY_LENGTH(pTCP->raAddress.wszAddress)-1] = 0;
                        pTCP->rsaSubAddress.wszSubAddress[ARRAY_LENGTH(pTCP->rsaSubAddress.wszSubAddress)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(TRANSFERCALL_PARAMS, RILDrv_TransferCall(dwOpenData, &pParams->raAddress, \
                                                                                            (pParams->fSubAddress ? &pParams->rsaSubAddress : NULL)));
                    break;

#ifndef RILDRV_CE6
                    // RIL_GetLineStatus()
                case IOCTL_RIL_GETLINESTATUS:
                    CALLDRVAPI(RILDrv_GetLineStatus);
                    break;
#endif

                    // RIL_GetAudioGain()
                case IOCTL_RIL_GETAUDIOGAIN:
                    CALLDRVAPI(RILDrv_GetAudioGain);
                    break;

                    // RIL_SetAudioGain()
                case IOCTL_RIL_SETAUDIOGAIN:
                    CALLDRVAPI_PARAMS(RILGAININFO, RILDrv_SetAudioGain(dwOpenData, pParams));
                    break;

                    // RIL_GetAudioDevices()
                case IOCTL_RIL_GETAUDIODEVICES:
                    CALLDRVAPI(RILDrv_GetAudioDevices);
                    break;

                    // RIL_SetAudioDevices()
                case IOCTL_RIL_SETAUDIODEVICES:
                    CALLDRVAPI_PARAMS(RILAUDIODEVICEINFO, RILDrv_SetAudioDevices(dwOpenData, pParams));
                    break;

                    // RIL_GetAudioMuting()
                case IOCTL_RIL_GETAUDIOMUTING:
                    CALLDRVAPI(RILDrv_GetAudioMuting);
                    break;

                    // RIL_SetAudioMuting()
                case IOCTL_RIL_SETAUDIOMUTING:
                    CALLDRVAPI_PARAMS(BOOL, RILDrv_SetAudioMuting(dwOpenData, *pParams));
                    break;

                    // RIL_GetHSCSDOptions()
                case IOCTL_RIL_GETHSCSDOPTIONS:
                    CALLDRVAPI(RILDrv_GetHSCSDOptions);
                    break;

                    // RIL_SetHSCSDOptions()
                case IOCTL_RIL_SETHSCSDOPTIONS:
                    CALLDRVAPI_PARAMS(RILHSCSDINFO, RILDrv_SetHSCSDOptions(dwOpenData, pParams));
                    break;

                    // RIL_GetHSCSDCallSettings()
                case IOCTL_RIL_GETHSCSDCALLSETTINGS:
                    CALLDRVAPI(RILDrv_GetHSCSDCallSettings);
                    break;

                    // RIL_GetDataCompression()
                case IOCTL_RIL_GETDATACOMPRESSION:
                    CALLDRVAPI(RILDrv_GetDataCompression);
                    break;

                    // RIL_SetDataCompression()
                case IOCTL_RIL_SETDATACOMPRESSION:
                    CALLDRVAPI_PARAMS(RILDATACOMPINFO, RILDrv_SetDataCompression(dwOpenData, pParams));
                    break;

                    // RIL_GetErrorCorrection()
                case IOCTL_RIL_GETERRORCORRECTION:
                    CALLDRVAPI(RILDrv_GetErrorCorrection);
                    break;

                    // RIL_SetErrorCorrection()
                case IOCTL_RIL_SETERRORCORRECTION:
                    CALLDRVAPI_PARAMS(RILERRORCORRECTIONINFO, RILDrv_SetErrorCorrection(dwOpenData, pParams));
                    break;

                    // RIL_GetBearerServiceOptions()
                case IOCTL_RIL_GETBEARERSERVICEOPTIONS:
                    CALLDRVAPI(RILDrv_GetBearerServiceOptions);
                    break;

                    // RIL_SetBearerServiceOptions()
                case IOCTL_RIL_SETBEARERSERVICEOPTIONS:
                    CALLDRVAPI_PARAMS(RILBEARERSVCINFO, RILDrv_SetBearerServiceOptions(dwOpenData, pParams));
                    break;

                    // RIL_GetRLPOptions()
                case IOCTL_RIL_GETRLPOPTIONS:
                    CALLDRVAPI(RILDrv_GetRLPOptions);
                    break;

                    // RIL_SetRLPOptions()
                case IOCTL_RIL_SETRLPOPTIONS:
                    CALLDRVAPI_PARAMS(RILRLPINFO, RILDrv_SetRLPOptions(dwOpenData, pParams));
                    break;

                    // RIL_GetMsgServiceOptions()
                case IOCTL_RIL_GETMSGSERVICEOPTIONS:
                    CALLDRVAPI(RILDrv_GetMsgServiceOptions);
                    break;

                    // RIL_SetMsgServiceOptions()
                case IOCTL_RIL_SETMSGSERVICEOPTIONS:
                    CALLDRVAPI_PARAMS(RILMSGSERVICEINFO, RILDrv_SetMsgServiceOptions(dwOpenData, pParams));
                    break;

                    // RIL_GetMsgConfig()
                case IOCTL_RIL_GETMSGCONFIG:
                    CALLDRVAPI(RILDrv_GetMsgConfig);
                    break;

                    // RIL_SetMsgConfig()
                case IOCTL_RIL_SETMSGCONFIG:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(RILMSGCONFIG) == BufInDuplicate.size())
                    {
                        LPRILMSGCONFIG pRMC = (LPRILMSGCONFIG)BufInDuplicate.ptr();
                        pRMC->raSvcCtrAddress.wszAddress[ARRAY_LENGTH(pRMC->raSvcCtrAddress.wszAddress)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(RILMSGCONFIG, RILDrv_SetMsgConfig(dwOpenData, pParams));
                    break;

                    // RIL_GetCellBroadcastMsgConfig()
                case IOCTL_RIL_GETCBMSGCONFIG:
                    CALLDRVAPI(RILDrv_GetCellBroadcastMsgConfig);
                    break;

                    // RIL_SetCellBroadcastMsgConfig()
                case IOCTL_RIL_SETCBMSGCONFIG:
#ifdef RILDRV_CE6
                    CALLDRVAPI_VARPARAMS(RILCBMSGCONFIG, RILDrv_SetCellBroadcastMsgConfig(dwOpenData, pParams));
#else
                    CALLDRVAPI_OPTVARPARAMS(RILCBMSGCONFIG, RILDrv_SetCellBroadcastMsgConfig(dwOpenData, pParams));
#endif
                    break;

                    // RIL_ReadMsg()
                case IOCTL_RIL_READMSG:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_ReadMsg(dwOpenData, *pParams));
                    break;

                    // RIL_DeleteMsg()
                case IOCTL_RIL_DELETEMSG:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_DeleteMsg(dwOpenData, *pParams));
                    break;

                    // RIL_WriteMsg()
                case IOCTL_RIL_WRITEMSG:
                    CALLDRVAPI_PARAMS(WRITEMSG_PARAMS, RILDrv_WriteMsg(dwOpenData, &pParams->rmMessage, pParams->dwStatus));
                    break;

                    // RIL_SendMsg()
                case IOCTL_RIL_SENDMSG:
                    CALLDRVAPI_PARAMS(SENDMSG_PARAMS, RILDrv_SendMsg(dwOpenData, &pParams->rmMessage, pParams->dwOptions));
                    break;

                    // RIL_SendStoredMsg()
                case IOCTL_RIL_SENDSTOREDMSG:
                    CALLDRVAPI_PARAMS(SENDSTOREDMSG_PARAMS, RILDrv_SendStoredMsg(dwOpenData, pParams->dwIndex, \
                                                                                              pParams->dwOptions));
                    break;

                    // RIL_SendMsgAcknowledgement()
                case IOCTL_RIL_SENDMSGACKNOWLEDGEMENT:
                    CALLDRVAPI_PARAMS(BOOL, RILDrv_SendMsgAcknowledgement(dwOpenData, *pParams));
                    break;

                    // RIL_GetUserIdentity()
                case IOCTL_RIL_GETUSERIDENTITY:
                    CALLDRVAPI(RILDrv_GetUserIdentity);
                    break;

                    // RIL_GetUserIdentity()
                case IOCTL_RIL_GETPHONELOCKEDSTATE:
                    CALLDRVAPI(RILDrv_GetPhoneLockedState);
                    break;

                    // RIL_UnlockPhone()
                case IOCTL_RIL_UNLOCKPHONE:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(GETLOCKINGSTATUS_PARAMS) == BufInDuplicate.size())
                    {
                        LPGETLOCKINGSTATUS_PARAMS pGLSP = (LPGETLOCKINGSTATUS_PARAMS)BufInDuplicate.ptr();
                        pGLSP->szPassword[ARRAY_LENGTH(pGLSP->szPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(UNLOCKPHONE_PARAMS, RILDrv_UnlockPhone(dwOpenData, pParams->szPassword, \
                                                                                          (pParams->fNewPassword ? pParams->szNewPassword : NULL)));
                    break;

                    // RIL_GetLockingStatus()
                case IOCTL_RIL_GETLOCKINGSTATUS:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(GETLOCKINGSTATUS_PARAMS) == BufInDuplicate.size())
                    {
                        LPGETLOCKINGSTATUS_PARAMS pGLSP = (LPGETLOCKINGSTATUS_PARAMS)BufInDuplicate.ptr();
                        pGLSP->szPassword[ARRAY_LENGTH(pGLSP->szPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(GETLOCKINGSTATUS_PARAMS, RILDrv_GetLockingStatus(dwOpenData, pParams->dwFacility, \
                                                                                                    (pParams->fPassword ? pParams->szPassword : NULL)));
                    break;

                    // RIL_SetLockingStatus()
                case IOCTL_RIL_SETLOCKINGSTATUS:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(SETLOCKINGSTATUS_PARAMS) == BufInDuplicate.size())
                    {
                        LPSETLOCKINGSTATUS_PARAMS pSLSP = (LPSETLOCKINGSTATUS_PARAMS)BufInDuplicate.ptr();
                        pSLSP->szPassword[ARRAY_LENGTH(pSLSP->szPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(SETLOCKINGSTATUS_PARAMS, RILDrv_SetLockingStatus(dwOpenData, pParams->dwFacility, \
                                                                                                    (pParams->fPassword ? pParams->szPassword: NULL), pParams->dwStatus));
                    break;

                    // RIL_ChangeLockingPassword()
                case IOCTL_RIL_CHANGELOCKINGPASSWORD:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(CHANGELOCKINGPASSWORD_PARAMS) == BufInDuplicate.size())
                    {
                        LPCHANGELOCKINGPASSWORD_PARAMS pCLPP = (LPCHANGELOCKINGPASSWORD_PARAMS)BufInDuplicate.ptr();
                        pCLPP->szOldPassword[ARRAY_LENGTH(pCLPP->szOldPassword)-1] = 0;
                        pCLPP->szNewPassword[ARRAY_LENGTH(pCLPP->szNewPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(CHANGELOCKINGPASSWORD_PARAMS, RILDrv_ChangeLockingPassword(dwOpenData, \
                                                                                                              pParams->dwFacility, pParams->dwOldPasswordType, pParams->szOldPassword, pParams->szNewPassword));
                    break;

                    // RIL_GetCallBarringStatus()
                case IOCTL_RIL_GETCALLBARRINGSTATUS:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(GETCALLBARRINGSTATUS_PARAMS) == BufInDuplicate.size())
                    {
                        LPGETCALLBARRINGSTATUS_PARAMS pGCBSP = (LPGETCALLBARRINGSTATUS_PARAMS)BufInDuplicate.ptr();
                        pGCBSP->szPassword[ARRAY_LENGTH(pGCBSP->szPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(GETCALLBARRINGSTATUS_PARAMS, RILDrv_GetCallBarringStatus(dwOpenData, \
                                                                                                            pParams->dwType, pParams->dwInfoClass, (pParams->fPassword ? pParams->szPassword : NULL)));
                    break;

                    // RIL_SetCallBarringStatus()
                case IOCTL_RIL_SETCALLBARRINGSTATUS:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(SETCALLBARRINGSTATUS_PARAMS) == BufInDuplicate.size())
                    {
                        LPSETCALLBARRINGSTATUS_PARAMS pSCBSP = (LPSETCALLBARRINGSTATUS_PARAMS)BufInDuplicate.ptr();
                        pSCBSP->szPassword[ARRAY_LENGTH(pSCBSP->szPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(SETCALLBARRINGSTATUS_PARAMS, RILDrv_SetCallBarringStatus(dwOpenData, \
                                                                                                            pParams->dwType, pParams->dwInfoClass, (pParams->fPassword ? pParams->szPassword : NULL), pParams->dwStatus));
                    break;

                    // RIL_ChangeCallBarringPassword()
                case IOCTL_RIL_CHANGECALLBARRINGPASSWORD:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(CHANGECALLBARRINGPASSWORD_PARAMS) == BufInDuplicate.size())
                    {
                        LPCHANGECALLBARRINGPASSWORD_PARAMS pCCBPP = (LPCHANGECALLBARRINGPASSWORD_PARAMS)BufInDuplicate.ptr();
                        pCCBPP->szOldPassword[ARRAY_LENGTH(pCCBPP->szOldPassword)-1] = 0;
                        pCCBPP->szNewPassword[ARRAY_LENGTH(pCCBPP->szNewPassword)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(CHANGECALLBARRINGPASSWORD_PARAMS, RILDrv_ChangeCallBarringPassword(dwOpenData, \
                                                                                                                      pParams->dwType, pParams->szOldPassword, pParams->szNewPassword));
                    break;

#if defined (IOCTL_RIL_CHANGECALLBARRINGPASSWORDEX)
                    // RIL_ChangeCallBarringPasswordEx()
                case IOCTL_RIL_CHANGECALLBARRINGPASSWORDEX:
                    CALLDRVAPI_PARAMS(CHANGECALLBARRINGPASSWORDEX_PARAMS, RILDrv_ChangeCallBarringPasswordEx(dwOpenData, \
                                                                                                                      pParams->dwType, pParams->szOldPassword, pParams->szNewPassword, pParams->szNewPasswordConfirm));
                    break;
#endif
                    // RIL_GetEquipmentInfo()
                case IOCTL_RIL_GETEQUIPMENTINFO:
                    CALLDRVAPI(RILDrv_GetEquipmentInfo);
                    break;

                    // RIL_GetEquipmentState()
                case IOCTL_RIL_GETEQUIPMENTSTATE:
                    CALLDRVAPI(RILDrv_GetEquipmentState);
                    break;

                    // RIL_SetEquipmentState()
                case IOCTL_RIL_SETEQUIPMENTSTATE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetEquipmentState(dwOpenData, *pParams));
                    break;

                    // RIL_GetPhonebookOptions()
                case IOCTL_RIL_GETPHONEBOOKOPTIONS:
                    CALLDRVAPI(RILDrv_GetPhonebookOptions);
                    break;

                    // RIL_SetPhonebookOptions()
                case IOCTL_RIL_SETPHONEBOOKOPTIONS:
                    CALLDRVAPI_PARAMS(RILPHONEBOOKINFO, RILDrv_SetPhonebookOptions(dwOpenData, pParams));
                    break;

                    // RIL_ReadPhonebookEntries()
                case IOCTL_RIL_READPHONEBOOKENTRIES:
                    CALLDRVAPI_PARAMS(READPHONEBOOKENTRIES_PARAMS, RILDrv_ReadPhonebookEntries(dwOpenData, \
                                                                                                            pParams->dwStartIndex, pParams->dwEndIndex));
                    break;

                    // RIL_WritePhonebookEntry()
                case IOCTL_RIL_WRITEPHONEBOOKENTRY:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(RILPHONEBOOKENTRY) == BufInDuplicate.size())
                    {
                        LPRILPHONEBOOKENTRY pRPBE = (LPRILPHONEBOOKENTRY)BufInDuplicate.ptr();
                        pRPBE->wszText[ARRAY_LENGTH(pRPBE->wszText)-1] = 0;
                        pRPBE->raAddress.wszAddress[ARRAY_LENGTH(pRPBE->raAddress.wszAddress)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(RILPHONEBOOKENTRY, RILDrv_WritePhonebookEntry(dwOpenData, pParams));
                    break;

                    // RIL_DeletePhonebookEntry()
                case IOCTL_RIL_DELETEPHONEBOOKENTRY:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_DeletePhonebookEntry(dwOpenData, *pParams));
                    break;

                    // RIL_SendSimCmd()
                case IOCTL_RIL_SENDSIMCMD:
#ifdef RILDRV_CE6
                    CALLDRVAPI_CONSTARRAY(BYTE, RILDrv_SendSimCmd(dwOpenData, pParams, BufInDuplicate.size()));
#else
                    CALLDRVAPI_ARRAY(BYTE, RILDrv_SendSimCmd(dwOpenData, pParams, dwLenIn));
#endif
                    break;

                    // RIL_SendRestrictedSimCmd()
                case IOCTL_RIL_SENDRESTRICTEDSIMCMD:
#ifdef RILDRV_CE6
                    if ((BufInDuplicate.size()  >= sizeof(SENDRESTRICTEDSIMCMD_PARAMS)))
                    {
                        CALLDRVAPI_ARRAY(SENDRESTRICTEDSIMCMD_PARAMS, RILDrv_SendRestrictedSimCmd(dwOpenData, \
                                                                                                                   pParams->dwCommand, &pParams->rscpParameters, pParams->pbData, \
                                                                                                                   BufInDuplicate.size() - sizeof(SENDRESTRICTEDSIMCMD_PARAMS)));
                    }
#else
                    CALLDRVAPI_ARRAY(SENDRESTRICTEDSIMCMD_PARAMS, RILDrv_SendRestrictedSimCmd(dwOpenData, \
                                                                                                           pParams->dwCommand, &pParams->rscpParameters, pParams->pbData, \
                                                                                                           dwLenIn - sizeof(SENDRESTRICTEDSIMCMD_PARAMS)));
#endif
                    break;

                    // RIL_GetSimRecordStatus()
                case IOCTL_RIL_GETSIMRECORDSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetSimRecordStatus(dwOpenData, *pParams));
                    break;

                    // RIL_GetSimToolkitProfile()
                case IOCTL_RIL_GETSIMTOOLKITPROFILE:
                    CALLDRVAPI(RILDrv_GetSimToolkitProfile);
                    break;

                    // RIL_SetSimToolkitProfile()
                case IOCTL_RIL_SETSIMTOOLKITPROFILE:
#ifdef RILDRV_CE6
                    CALLDRVAPI_CONSTARRAY(BYTE, RILDrv_SetSimToolkitProfile(dwOpenData, pParams, BufInDuplicate.size()));
#else
                    CALLDRVAPI_ARRAY(BYTE, RILDrv_SetSimToolkitProfile(dwOpenData, pParams, dwLenIn));
#endif
                    break;

#ifdef RILDRV_CE6
                    // RIL_SendSimToolkitEnvelopeCmd()
                case IOCTL_RIL_SENDSIMTOOLKITENVELOPECMD:
                    CALLDRVAPI_CONSTARRAY(BYTE, RILDrv_SendSimToolkitEnvelopeCmd(dwOpenData, pParams, BufInDuplicate.size()));
                    break;
#endif
                    // RIL_FetchSimToolkitCmd()
                case IOCTL_RIL_FETCHSIMTOOLKITCMD:
                    CALLDRVAPI(RILDrv_FetchSimToolkitCmd);
                    break;

                    // RIL_TerminateSimToolkitSession()
                case IOCTL_RIL_TERMINATESIMTOOLKITSESSION:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_TerminateSimToolkitSession(dwOpenData, *pParams));
                    break;

                    // RIL_SendSimToolkitCmdResponse()
                case IOCTL_RIL_SENDSIMTOOLKITCMDRESPONSE:
#ifdef RILDRV_CE6
                    if ((BufInDuplicate.size()  >= sizeof(SENDSIMTOOLKITCMDRESPONSE_PARAMS)))
                    {

                        CALLDRVAPI_ARRAY(SENDSIMTOOLKITCMDRESPONSE_PARAMS, RILDrv_SendSimToolkitCmdResponse(dwOpenData,           \
                                                                                                             &pParams->rstrRsp,   \
                                                                                                             pParams->pbDetails,  \
                                                                                                             BufInDuplicate.size() - sizeof(SENDSIMTOOLKITCMDRESPONSE_PARAMS)));
                    }
#else
                    CALLDRVAPI_ARRAY(SENDSIMTOOLKITCMDRESPONSE_PARAMS, RILDrv_SendSimToolkitCmdResponse(dwOpenData,          \
                                                                                                        &pParams->rstrRsp,   \
                                                                                                        pParams->pbDetails,  \
                                                                                                        dwLenIn - sizeof(SENDSIMTOOLKITCMDRESPONSE_PARAMS)));
#endif
                    break;

                    // RIL_SendSimToolkitEventDownload()
                case IOCTL_RIL_SENDSIMTOOLKITEVENTDOWNLOAD:
#ifdef RILDRV_CE6
                    if ((BufInDuplicate.size()  >= sizeof(SENDSIMTOOLKITEVENTDOWNLOAD_PARAMS)))
                    {

                        CALLDRVAPI_ARRAY(SENDSIMTOOLKITEVENTDOWNLOAD_PARAMS, RILDrv_SendSimToolkitEventDownload(dwOpenData,       \
                                                                                                                pParams->dwEvent, \
                                                                                                                pParams->pbData,  \
                                                                                                                BufInDuplicate.size() - sizeof(SENDSIMTOOLKITEVENTDOWNLOAD_PARAMS)));
                    }
#else
                    CALLDRVAPI_ARRAY(SENDSIMTOOLKITEVENTDOWNLOAD_PARAMS, RILDrv_SendSimToolkitEventDownload(dwOpenData,       \
                                                                                                            pParams->dwEvent, \
                                                                                                            pParams->pbData,  \
                                                                                                            dwLenIn - sizeof(SENDSIMTOOLKITEVENTDOWNLOAD_PARAMS)));
#endif
                    break;

                    // RIL_GetCostInfo()
                case IOCTL_RIL_GETCOSTINFO:
                    CALLDRVAPI(RILDrv_GetCostInfo);
                    break;

                    // RIL_SetCostInfo()
                case IOCTL_RIL_SETCOSTINFO:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(SETCOSTINFO_PARAMS) == BufInDuplicate.size())
                    {
                        LPSETCOSTINFO_PARAMS pSCIP = (LPSETCOSTINFO_PARAMS)BufInDuplicate.ptr();
                        pSCIP->szPassword[ARRAY_LENGTH(pSCIP->szPassword)-1] = 0;
                        pSCIP->rciCostInfo.wszCurrency[ARRAY_LENGTH(pSCIP->rciCostInfo.wszCurrency)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(SETCOSTINFO_PARAMS, RILDrv_SetCostInfo(dwOpenData, &pParams->rciCostInfo, \
                                                                                          (pParams->fPassword ? pParams->szPassword : NULL)));
                    break;

#ifndef RILDRV_CE6
                    // RIL_GetSignalQuality() for Windows Mobile
                case IOCTL_RIL_GETSIGNALQUALITY:
                    CALLDRVAPI(RILDrv_GetSignalQuality);
                    break;
#endif
#ifdef RILDRV_CE7
                    // RIL_GetSignalQuality() for Windows CE7
                case IOCTL_RIL_GETSIGNALQUALITY:
                    if (BufInDuplicate.ptr()){
                        CALLDRVAPI_PARAMS(RILSIGNALQUALITY, RILDrv_GetSignalQuality(dwOpenData, pParams));
                    }
                    else {
                        *phr = RILDrv_GetSignalQuality(dwOpenData, NULL);
                        dwOutUsed = sizeof(HRESULT);
                        fRet = TRUE;
                    }
                    break;
#endif

                    // RIL_GetCellTowerInfo()
                case IOCTL_RIL_GETCELLTOWERINFO:
                    CALLDRVAPI(RILDrv_GetCellTowerInfo);
                    break;
#if defined(IOCTL_RIL_GETPOSITIONINFO)
                    // RILDrv_GetPositionInfo()
                case IOCTL_RIL_GETPOSITIONINFO:
                    CALLDRVAPI(RILDrv_GetPositionInfo);
                    break;
#endif
                    // RIL_DevSpecific()
                case IOCTL_RIL_DEVSPECIFIC:
#ifdef RILDRV_CE6
                    CALLDRVAPI_CONSTARRAY(BYTE, RILDrv_DevSpecific(dwOpenData, pParams, BufInDuplicate.size()));
#else
                    CALLDRVAPI_ARRAY(BYTE, RILDrv_DevSpecific(dwOpenData, pParams, dwLenIn));
#endif
                    break;

                    // RIL_GetDevCaps()
                case IOCTL_RIL_GETDEVCAPS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetDevCaps(dwOpenData, *pParams));
                    break;

                    // RIL_GetCCBSStatus()
                case IOCTL_RIL_GETCCBSSTATUS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetCCBSStatus(dwOpenData, *pParams));
                    break;

                    // RIL_ClearCCBSRegistration()
                case IOCTL_RIL_CLEARCCBSREGISTRATION:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_ClearCCBSRegistration(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GETSYSTEMTIME:
                    CALLDRVAPI(RILDrv_GetSystemTime);
                    break;

                case IOCTL_RIL_GETGPRSCONTEXTLIST:
                    CALLDRVAPI(RILDrv_GetGPRSContextList);
                    break;
                case IOCTL_RIL_SETGPRSCONTEXT:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(RILGPRSCONTEXT) >= BufInDuplicate.size())
                    {
                        LPRILGPRSCONTEXT pRGC = (LPRILGPRSCONTEXT)BufInDuplicate.ptr();
                        pRGC->wszAccessPointName[ARRAY_LENGTH(pRGC->wszAccessPointName)-1] = 0;
                        pRGC->wszAddress[ARRAY_LENGTH(pRGC->wszAddress)-1] = 0;
                        if ( BufInDuplicate.size() > sizeof(RILGPRSCONTEXT) )
                        {
                            ((LPBYTE)pRGC)[ BufInDuplicate.size() - 1 ] = 0;
                        }
                    }
#endif
                    CALLDRVAPI_VARPARAMS(RILGPRSCONTEXT, RILDrv_SetGPRSContext(dwOpenData, pParams));
                    break;
                case IOCTL_RIL_DELETEGPRSCONTEXT:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_DeleteGPRSContext(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GETREQUESTEDQUALITYOFSERVICELIST:
                    CALLDRVAPI(RILDrv_GetRequestedQualityOfServiceList);
                    break;
                case IOCTL_RIL_SETREQUESTEDQUALITYOFSERVICE:
                    CALLDRVAPI_PARAMS(RILGPRSQOSPROFILE, RILDrv_SetRequestedQualityOfService(dwOpenData, pParams));
                    break;
                case IOCTL_RIL_DELETEREQUESTEDQUALITYOFSERVICE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_DeleteRequestedQualityOfService(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GETMINIMUMQUALITYOFSERVICELIST:
                    CALLDRVAPI(RILDrv_GetMinimumQualityOfServiceList);
                    break;
                case IOCTL_RIL_SETMINIMUMQUALITYOFSERVICE:
                    CALLDRVAPI_PARAMS(RILGPRSQOSPROFILE, RILDrv_SetMinimumQualityOfService(dwOpenData, pParams));
                    break;
                case IOCTL_RIL_DELETEMINIMUMQUALITYOFSERVICE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_DeleteMinimumQualityOfService(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_SETGPRSATTACHED:
                    CALLDRVAPI_PARAMS(BOOL, RILDrv_SetGPRSAttached(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GETGPRSATTACHED:
                    CALLDRVAPI(RILDrv_GetGPRSAttached);
                    break;
                case IOCTL_RIL_SETGPRSCONTEXTACTIVATED:
                    CALLDRVAPI_PARAMS(SETGPRSCONTEXTACTIVATED_PARAMS, RILDrv_SetGPRSContextActivated(dwOpenData, pParams->dwContextID, pParams->fContextActivation));
                    break;
                case IOCTL_RIL_GETGPRSCONTEXTACTIVATEDLIST:
                    CALLDRVAPI(RILDrv_GetGPRSContextActivatedList);
                    break;
                case IOCTL_RIL_ENTERGPRSDATAMODE:
#ifdef RILDRV_CE6
                    CALLDRVAPI_VARPARAMS(RILENTERGPRSDATAMODE, RILDrv_EnterGPRSDataMode(dwOpenData, pParams));
#else
                    CALLDRVAPI_OPTVARPARAMS(RILENTERGPRSDATAMODE, RILDrv_EnterGPRSDataMode(dwOpenData, pParams));
#endif
                    break;
                case IOCTL_RIL_GETGPRSADDRESS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_GetGPRSAddress(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GPRSANSWER:
                    CALLDRVAPI_VARPARAMS(RILGPRSANSWER, RILDrv_GPRSAnswer(dwOpenData, pParams));
                    break;
                case IOCTL_RIL_GETGPRSREGISTRATIONSTATUS:
                    CALLDRVAPI(RILDrv_GetGPRSRegistrationStatus);
                    break;
                case IOCTL_RIL_GETGPRSCLASS:
                    CALLDRVAPI(RILDrv_GetGPRSClass);
                    break;
                case IOCTL_RIL_SETGPRSCLASS:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetGPRSClass(dwOpenData, *pParams));
                    break;
                case IOCTL_RIL_GETMOSMSSERVICE:
                    CALLDRVAPI(RILDrv_GetMOSMSService);
                    break;
                case IOCTL_RIL_SETMOSMSSERVICE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetMOSMSService(dwOpenData, *pParams));
                    break;
#ifndef RILDRV_CE6
                case IOCTL_RIL_NDIS_RECEIVEPACKETDONE:
                    CALLDRVAPI_VARPARAMS(RILNDISPACKET, RILDrv_NdisReceivePacketDone(dwOpenData, pParams));
                    break;
                case IOCTL_RIL_NDIS_SENDPACKET:
                    CALLDRVAPI_VARPARAMS(RILNDISPACKET, RILDrv_NdisSendPacket(dwOpenData, pParams));
                    break;
#endif
                case IOCTL_RIL_NDIS_SETGPRSCONTEXTACTIVATED:
#ifdef RILDRV_CE6
                    if ( BufInDuplicate.ptr() && sizeof(RILNDISGPRSCONTEXT) == BufInDuplicate.size())
                    {
                        LPRILNDISGPRSCONTEXT pRNGC = (LPRILNDISGPRSCONTEXT)BufInDuplicate.ptr();
                        pRNGC->tszDNS1[ARRAY_LENGTH(pRNGC->tszDNS1)-1] = 0;
                        pRNGC->tszDNS2[ARRAY_LENGTH(pRNGC->tszDNS2)-1] = 0;
                        pRNGC->tszPassword[ARRAY_LENGTH(pRNGC->tszPassword)-1] = 0;
                        pRNGC->tszUserName[ARRAY_LENGTH(pRNGC->tszUserName)-1] = 0;
                    }
#endif
                    CALLDRVAPI_PARAMS(RILNDISSETGPRSCONTEXTACTIVATED, RILDrv_NdisSetGPRSContextActivated(dwOpenData, pParams));
                    break;
#if defined(IOCTL_RIL_GETSMSNLTABLELIST)
                // RIL_GetSMSNLTableList()  (Windows Mobile 6.5)
                case IOCTL_RIL_GETSMSNLTABLELIST:
                    CALLDRVAPI(RILDrv_GetSMSNLTableList);
                    break;
#endif

                // CDMA functions
                case IOCTL_RIL_GETPACKETBYTECOUNT:
                    CALLDRVAPI(RILDrv_GetPacketByteCount);
                    break;

                case IOCTL_RIL_RESETPACKETBYTECOUNT:
                    CALLDRVAPI(RILDrv_ResetPacketByteCount);
                    break;

                case IOCTL_RIL_GETCURRENTSYSTEMTYPE:
                    CALLDRVAPI(RILDrv_GetCurrentSystemType);
                    break;

                case IOCTL_RIL_SENDFLASH:
#ifdef RILDRV_CE6
                    CALLDRVAPI_VARPARAMS(RILADDRESS, RILDrv_SendFlash(dwOpenData, pParams));
#else
                    CALLDRVAPI_OPTVARPARAMS(RILADDRESS, RILDrv_SendFlash(dwOpenData, pParams));
#endif
                    break;

                case IOCTL_RIL_GETROAMINGMODE:
                    CALLDRVAPI(RILDrv_GetRoamingMode);
                    break;

                case IOCTL_RIL_SETROAMINGMODE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetRoamingMode(dwOpenData, *pParams));
                    break;

                case IOCTL_RIL_GETPREFERREDPRIVACYMODE:
                    CALLDRVAPI(RILDrv_GetPreferredPrivacyMode);
                    break;

                case IOCTL_RIL_SETPREFERREDPRIVACYMODE:
                    CALLDRVAPI_PARAMS(DWORD, RILDrv_SetPreferredPrivacyMode(dwOpenData, *pParams));
                    break;

                case IOCTL_RIL_GETCURRENTPRIVACYSTATUS:
                    CALLDRVAPI(RILDrv_GetCurrentPrivacyStatus);
                    break;

                case IOCTL_RIL_GETCURRENTLOCATIONSTATUS:
                    CALLDRVAPI(RILDrv_GetCurrentLocationStatus);
                    break;

                case IOCTL_RIL_GETCURRENTROAMINGSTATUS:
                    CALLDRVAPI(RILDrv_GetCurrentRoamingStatus);
                    break;

                case IOCTL_RIL_SENDAKEY:
#ifdef RILDRV_CE6
                    NULLTERMINATE(CHAR);
                    CALLDRVAPI_CONSTARRAY(CHAR, RILDrv_SendAKey(dwOpenData, pParams));
#else
                    // parameters to SendAKey are a little wierd, so there isn't a suitable macro yet.
                    *phr = RILDrv_SendAKey(dwOpenData, (LPCSTR)pBufIn);
                    dwOutUsed = sizeof(HRESULT);
                    fRet = TRUE;
#endif
                    break;

                case IOCTL_RIL_REGISTER_AT_LOGGING:
                    CALLDRVAPI_PARAMS(BOOL, RILDrv_SetATLogging(dwOpenData, *pParams ));
                    break;

                case IOCTL_RIL_ATCOMMAND_LOGFILE:
                    CALLDRVAPI_ARRAY(TCHAR, RILDrv_ATLogFile(dwOpenData, pParams ));
                    break;

                case IOCTL_RIL_GETATR:
                    CALLDRVAPI(RILDrv_GetATR);
                    break;

                case IOCTL_RIL_LOGEVENTTORADIO:
                    CALLDRVAPI_ARRAY(CHAR, RILDrv_LogEventToRadio(dwOpenData, pParams));
                    break;

#ifdef IOCTL_RIL_DATADORMANT
                case IOCTL_RIL_DATADORMANT:
                    CALLDRVAPI(RILDrv_DataDormant);
                    break;
#endif

//////////////////////////////////////////////////////////////////////////////
//
// Microsoft Automotive
//
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// These definitions are used for the antenna diagnostic extension:
//
// #define RIL_ANTENNASTATUS_UNKNOWN        (0x00000000)  // @constdefine Unknown status
// #define RIL_ANTENNASTATUS_CONNECTED      (0x00000001)  // @constdefine Antenna connected
// #define RIL_ANTENNASTATUS_DISCONNECTED   (0x00000002)  // @constdefine Antenna disconnected
// #define RIL_ANTENNASTATUS_SHORTED        (0x00000003)  // @constdefine
// #define RIL_ANTENNASTATUS_SHORTEDGROUND  (0x00000004)  // @constdefine
//
// #define IOCTL_RIL_GETANTENNASTATUS       CTL_CODE(FILE_DEVICE_RIL, 166, METHOD_BUFFERED, FILE_ANY_ACCESS)
//
//////////////////////////////////////////////////////////////////////////////
#ifdef IOCTL_RIL_GETANTENNASTATUS
                case IOCTL_RIL_GETANTENNASTATUS:
                    CALLDRVAPI(RILDrv_GetAntennaStatus)
                    break;
#endif // IOCTL_RIL_GETANTENNASTATUS

//////////////////////////////////////////////////////////////////////////////
//
// End of Microsoft Automotive
//
//////////////////////////////////////////////////////////////////////////////
                }
                if (fRet)
                    TraceIOCTLCallReturn(dwCode, *phr);
                break;
            }
        }

    }

#ifdef RILDRV_CE6
    if (BufActualOut.ptr())
    {
        *((DWORD*)BufActualOut.ptr()) = dwOutUsed;
    }
#else
    if (pdwActualOut)
    {
        *pdwActualOut = dwOutUsed;
    }
#endif

    Error:
    return fRet;
}
#pragma warning( pop )

//
//
//
HRESULT RILDrv_GetNextNotification(DWORD dwParam, RILDRVNOTIFICATION* lpRilDrvNotification)
{
    HRESULT hr = S_OK;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam, TRUE);
    if (!pHandle)
    {
        hr = E_INVALIDARG;
        goto Error;
    }

    if (!pHandle->GetNextNotification(*lpRilDrvNotification))
    {
        hr = E_FAIL;
    }

    Error:
    return hr;
}


//
//
//
HRESULT RILDrv_GetSerialPortStatistics(DWORD dwParam, RILSERIALPORTSTATS* lpSerialPortStats)
{
    HRESULT hr = S_OK;
    CRilHandle* pRilDevice;
    CComHandle* pComDevice;
    CRilInstanceHandle* pHandle = ExtractHandle(dwParam);
    if (!pHandle)
    {
        hr = E_INVALIDARG;
        goto Error;
    }

    pRilDevice = pHandle->GetDevice();

    pComDevice = pRilDevice->GetComDevice(DATA_PORT);

    pComDevice->CalculateComStats(lpSerialPortStats->dwReadBitsPerSecond, lpSerialPortStats->dwWrittenBitsPerSecond);
    lpSerialPortStats->dwParams = RIL_PARAM_SPS_ALL;

    Error:
    return hr;
}


//
//
//
HRESULT RILDrv_SetPowerState(DWORD dwParam, CEDEVICE_POWER_STATE PowerState)
{
  CRilInstanceHandle* pHandle = ExtractHandle(dwParam);

  if (!pHandle) {
    return E_INVALIDARG;
  } else {
    if (g_PowerManager.EnterPowerState(pHandle, PowerState)) {
      return S_OK;
    }
  }
  return E_FAIL;
}


//
// Function passed to CQueue::Enum() above
//
static BOOL ClearCmdHandle(void* pItem, DWORD /*dwDummy*/)
{
    CCommand* pCmd = (CCommand*)pItem;
    pCmd->ClearHandle();

    // Continue enumeration
    return FALSE;
}


//
//
//
CRilInstanceHandle* const ExtractHandle(const DWORD dwParam, BOOL bOverrideEmergency)
{
    CRilInstanceHandle* pRet;
    CRilHandle* pRilDevice;

    // Cast the DWORD into a handle
    pRet = (CRilInstanceHandle*)dwParam;
    if (!pRet)
    {
        goto Error;
    }

    pRilDevice = pRet->GetDevice();

    // If we're in emergency mode, make sure this is a preferred handle
    if ((!bOverrideEmergency) && pRilDevice->FInEmergencyMode() && !pRet->FPreferred())
    {
        pRet = NULL;
        goto Error;
    }

    Error:
    return pRet;
}


//
//
//

void SignalCriticalError(void)
{
    RILRetailTraceZone(ZONE_ERROR, (TEXT("RilDrv: SignalCriticalError() called!")));
    (void)SetEvent(g_hCriticalErrorEvent);
}

void ReadDebugOptions()
{
    DWORD dwTemp;

#if defined(RIL_RETAIL_OUTPUT_PORT) || defined(RIL_RETAIL_OUTPUT_FILE)
    if(GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyIntrinsycRIL, TEXT("DisableDebugFile"), &dwTemp))
    {
        g_dwDisableTrace = dwTemp;
    }
#endif
    if(GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyIntrinsycRIL, TEXT("DebugTimeStampFormat"), &dwTemp))
        g_dwTraceTimeStampFormat = dwTemp;

    if(GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyIntrinsycRIL, TEXT("DebugZones"), &dwTemp))
        g_dwDebugZones = dwTemp;
    else
        g_dwDebugZones = DEFAULT_ZONE_ERROR|DEFAULT_ZONE_ATCOMMAND|DEFAULT_ZONE_INFO|DEFAULT_ZONE_IOCTL|DEFAULT_ZONE_NOTIFICATION|DEFAULT_ZONE_NMEA|DEFAULT_ZONE_RHA|DEFAULT_ZONE_RHA_POWER|DEFAULT_ZONE_PORT|DEFAULT_ZONE_DATA;
#if defined(RIL_RETAIL_OUTPUT_FILE)
    if(GetRegistryDWORD(HKEY_LOCAL_MACHINE, g_tszRegKeyIntrinsycRIL, TEXT("MaxDebugFileLen"), &dwTemp))
    {
        g_dwTraceFileLength = dwTemp * 1024;     // Registry key specifies limit in kBytes
    }
#endif
    return;
}

