Mobile Development - 'Support Side Story'

Broadcasting technical support to Windows Mobile\CE Application Developers to help realizing their potential

Broadcasting technical support to Windows Mobile\CE Application Developers to help realizing their potential

October, 2008

  • Mobile Development - 'Support Side Story'

    LAP Plugin freezes at startup on Windows Mobile 6 Classic

    • 0 Comments

    SDK Sample LAP for Pocket PC is meant to work on Windows Mobile 6 Professional only: here you can see how to modify it so that it can work on a Classic device as well.

     

    Have you ever tried to use the SDK Pocket PC's Sample for LAP on a Windows Mobile 6 CLASSIC device or emulator? Well, I've never done that and wasn't aware of a limitation of the sample code... Let me share a very good example of the added value that Microsoft Technical Support can give to ISV Application Developers out there! Wink

    Above all, thanks Masahiro for pointing this out! Masahiro is a new friend of mine, an ISV Application Developer from Japan, and pinged me last week with a weird issue: when running the WM6 SDK Sample LAP on a Classic device, he experienced a hung precisely as I described in a previous post of mine... absolutely the same code on a Professional device had no problems. Remember that Classic is a "Pocket PC with NO phone", while Professional is what we were used to call "Pocket PC Phone Edition"...

    So, why on the earth would the problem be repro-d on quite the same platform? Above all, I started with the usual initial troubleshooting steps: I've reproduced on an WM6 Classic Emulator to make sure it was not OEM-dependent. It was not. Then I tried with the WM6.1 Classic Emulator, to know if it was a platform issue addressed in 6.1. It was not. I made sure the problem was not with certificates as I mentioned in my other post: however the WM Emulators already come with SDK Certificates on them, therefore the issue must not be there. Then I researched in documentation and Technical Support archives, to make sure I wasn't missing something fundamental... I was not.

    So at this point some further deep digging was required: very likely the next step would have been to create a DEBUG image of the WM6 Classic through the "Windows Mobile Adaptation Kit" (you know, the "Platform Builder for Windows Mobile"), or a RETAIL image with some debug-version DLLs... and this is something that only Windows Mobile OEMs can use: the AK is not publicly available to ISV Developers, and many times this is one of the added values given by Microsoft Technical Support.

    As it was in this case: my colleagues in Japan (kudos to Ryoichi!) worked at the issue doing exactly what mentioned above, and discovered the following: they used a tool that is not available to ISV Application Developers, and log all "activities" of the boot phase: one of them was lap.dll trying to load phone.dll.

    DoImport Failed! Unable to import Library 'PHONE.dll' for 'lap.dll'

    So the problem is with the SDK Sample linking "phone.lib" (and doing some other functions available only on Professional\Standard devices -- emergency calls): if the phone.lib is linked to the LAP.DLL, the DLL need to load phone.dll simultaneously. But phone.dll is not available on a WM6 Classic device.

    Thus, to make LAP.DLL to load for WM6 classic device, you need to remove "phone.lib" from linker settings from project properties. Also, LAP sample is using following APIs to accomplish emergency calling. To support both Classic and Professional devices, you need to change function calling method to using LoadLibrary("phone.dll") and GetProcAddress().

    • PhoneIsEmergencyNumber
    • PhoneSendDTMFStart
    • PhoneSendDTMFStop
    • PhoneMakeCall

    In other words:

    1. Add following code to util.h in LAP sample.

    #include <phone.h>
    typedef BOOL (*PFN_PhoneIsEmergencyNumber)(BOOL,LPCTSTR,LPCTSTR*);
    typedef HRESULT (*PFN_PhoneSendDTMFStart)(TCHAR);
    typedef void (*PFN_PhoneSendDTMFStop)(void);
    typedef LONG (*PFN_PhoneMakeCall)(PHONEMAKECALLINFO *);
    
    extern HMODULE g_hModule;
    extern PFN_PhoneIsEmergencyNumber pfnPhoneIsEmergencyNumber;
    extern PFN_PhoneSendDTMFStart pfnPhoneSendDTMFStart;
    extern PFN_PhoneSendDTMFStop pfnPhoneSendDTMFStop;
    extern PFN_PhoneMakeCall pfnPhoneMakeCall;

     

    2. Add additional global variables to lap.cpp

    HMODULE g_hModule = NULL;
    PFN_PhoneIsEmergencyNumber pfnPhoneIsEmergencyNumber = NULL;
    PFN_PhoneSendDTMFStart pfnPhoneSendDTMFStart = NULL;
    PFN_PhoneSendDTMFStop pfnPhoneSendDTMFStop = NULL;
    PFN_PhoneMakeCall pfnPhoneMakeCall = NULL;

     

    3. Add following code sample into InitLAP and DeinitLAP in lap.cpp

    BOOL InitLAP(InitLap* il) 
    {
        ...
        // Check if policy requires us to force enrollment
        g_hPolicyThread = CreateThread(NULL, 0, PolicyThreadProc, NULL, 0, NULL);
        ASSERT(NULL != g_hPolicyThread);
    
        // ADD FROM HERE
        g_hModule = LoadLibrary(_T("phone.dll"));
        if (g_hModule)
        {
            pfnPhoneIsEmergencyNumber = (PFN_PhoneIsEmergencyNumber)GetProcAddress(g_hModule, _T("PhoneIsEmergencyNumber"));
            pfnPhoneSendDTMFStart = (PFN_PhoneSendDTMFStart)GetProcAddress(g_hModule, _T("PhoneSendDTMFStart"));
            pfnPhoneSendDTMFStop = (PFN_PhoneSendDTMFStop)GetProcAddress(g_hModule, _T("PhoneSendDTMFStop"));
            pfnPhoneMakeCall = (PFN_PhoneMakeCall)GetProcAddress(g_hModule, _T("PhoneMakeCall"));
            if (!pfnPhoneIsEmergencyNumber ||
                !pfnPhoneSendDTMFStart ||
                !pfnPhoneSendDTMFStop ||
                !pfnPhoneMakeCall)
            {
                FreeLibrary(g_hModule);
                pfnPhoneIsEmergencyNumber = NULL;
                pfnPhoneSendDTMFStart = NULL;
                pfnPhoneSendDTMFStop = NULL;
                pfnPhoneMakeCall = NULL;
            }
        }
        // ADD TO HERE
        
        return bInitialized;
    }
    
    void DeinitLAP()
    {
        ...
        // Free the critical section resources.
        DeleteCriticalSection(&g_csAuthResetSetup);
        
        // ADD FOLLOWING 2 LINES
        if (g_hModule)
        FreeLibrary(g_hModule);
    }

     

    4. Change some functions name like from PhoneMakeCall to pfnPhoneMakeCall in project. And NULL checking for function pointers before calling pfnXxxx functions.

     

    Moral of the story is: when you find yourself in "programming" troubles, get what you paid for and Make sure you realize (or realise...) Your Potential with Microsoft Technical Support!! Open-mouthed

     

    Cheers!

    ~raffaele

Page 1 of 1 (1 items)