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

May, 2008

  • Mobile Development - 'Support Side Story'

    [**From Alberto**] Socket-based application loses data when finishing communication

    • 0 Comments

    Subtitle -- How to implement graceful disconnection in a .NET (and .NET Compact Framework) application

    Alberto is one of my direct colleagues and works on the same kind of issues and with the same developers, that I work. We'll possibly share this blog since it's all about "Mobile Development - Support Side Story", in the meantime I'm lending this space... Smile

     

    1. Introduction

    Graceful disconnection is always an important topic in a client - server application, because when one writes such an application, the first questions is: “When I’m done and I close the connection, how can I assure that the whole data will be transferred from client to server and vice-versa?”

    In order to answer this question, we have to clarify some important things: first of all, we have to distinguish between connection-oriented and connectionless transport. In connection-oriented based application, we usually make use of TCP protocol as transport protocol, while in connectionless based application we usually make use of UDP protocol. This means that with TCP we have a message exchange to setup, control and teardown the connection, while with UDP there’s no need to setup a connection, because each block of data is self-contained in the so-called DATAGRAM, and this single “message” (block of data) is sent in a single step, without any warranties about the correct reception of the message from the counterpart.

    In managed world, these two connection ways are mapped into two enumerative constants used by the Socket class during Socket object construction (Socket type is the basic building block of network managed application and is part of System.Net.Socket namespace). Documentation reference about Socket class is here.

     

    2. TCP Internals

    I pointed out this introduction because it’s important to understand that the graceful disconnection pattern applies only to connection-oriented based application, because in connectionless transport data are unreliably forwarded to the counterpart, so we have to implement some other mechanism in order to check integrity of data received.

    So, let’s switch back to connection oriented (TCP based) application and look what happens under the hood: the lifecycle of a typical TCP connection is SETUP – SEND/RECEIVE data (with ACKnowledge packets) – TEARDOWN.

    The SETUP phase consist in a “three way handshake”, that allows client and server to move through a FSM (Finite State Machine) in order to cover the TCP setup algorithm and managed errors; from network perspective, the handshake is completed when SYN, SYN-ACK, ACK packets are exchanged correctly between client and server (this is done when eventually the connect() unmanaged API is called from the client towards the server).

    The SEND/RECEIVE phase consist in data exchange (two ways) between client and server, with a windowed-base flow control mechanism that ensures reliable transfer of blocks of data between two endpoints; the important thing to notice is that such a protocol allows usage of prioritized message by means of a parallel channel, called OOB (Out Of Band). This way, each part can send an urgent message that can overcome currently ongoing packets over connection and it will be processed by the counterpart before other data packets. Such messages can be normal flow control messages (window resizing, counter updating) or also RST packets, that will broke up connection immediately: they are very useful in order to recover error scenarios, but RST packets can also be sent during normal operations when one side decide to forcibly close the connection calling closesocket() unmanaged API (For example, this API is called by OS when an application crashes or its process exits).

    The TEARDOWN phase is symmetric to the SETUP phase, except for the handshake that should involve four messages: FIN [ACK], ACK , FIN-ACK, ACK. This is due to the fact that this is a two-way connection, so we have to ensure that both the client and the server correctly receive all data and stop their TCP sender (this avoid that some zombie packets are sent over network). If we recognize such a pattern in a network trace, we are confident that the connection is correctly (gracefully) closed. So, let’s have a look how this pattern can be achieved through native and managed programming.

     

    3. Graceful disconnection: native (unmanaged) applications

    For native applications, there is a good article that shows the details of the graceful disconnection: "Graceful Shutdown, Linger Options, and Socket Closure". Basically, this is the code snippet for server and/or client to ensure graceful disconnection by their own side; notice that the implementation is independent from entity.

    // SOCKET CHANNEL:
    // Tx --->\ /---> Rx
    // ============
    // Rx <---/ \<--- Tx
    //
    
    // NOTE: I assume here we are not willing to accept nor parse more data from counterpart, 
    // but only to close the socket gracefully
    void socket_disc(SOCKET s)
    {
        // shutdown SEND channel 
        // (cause FD_CLOSE to be generated on the counterpart)
        if(shutdown(s, SD_SEND) == SOCKET_ERROR)
        {
        printf("Error while shutdown socket: GetSocketLastError=0x%x", WSAGetLastError());
        
        // check the error .. possibly act according to error code
        closesocket(s);
        
        return;
        }
        
        // wait for FD_CLOSE message – any data discarded
        int rec_res;
        char c;
        do
        {
            rec_res = recv(s, &c, sizeof(char), 0);
        } while (rec_res != 0 && rec_res != SOCKET_ERROR)
        
        // check the code – recv() can exit for an error, due to a RST packet from other side
        if(WSAGetLastError() != 0) // errors -> maybe notify ...
        {
            ...
        }
        
        // else: FD_CLOSE received, socket gracefully closed from remote side
        closesocket(s);
        
        return;
    }

     

    With the code above, you should get a network trace pattern like this (Network Monitor trace):

    FINACK

    Note the pattern:

    •        Client --> Server: [FIN, ACK]
    •        Server --> Client: [ACK]
    •        Server --> Client: [FIN, ACK]
    •        Client --> Server: [ACK]

    If everything works fine, you should not see any RST packet related to lost segments.

     

    4. Graceful disconnection: managed (.NET) applications

    As I said in the first paragraph, in managed .NET world the basic building block of connection-aware applications is the Socket class. Socket class is a thin wrapper onto the socket native handle, so it provides all the operations available for sockets: hence, the above code snippet can be easily mapped into managed application:

    public void GracefulDisconnection(Socket s)
    {
        byte[] buf = new byte[1];
        try
        {
            s.Shutdown(SocketShutdown.Send);
            while (s.Receive(buf, 1, SocketFlags.None) != 0)
                ;
        }
        catch (SocketException s_ex)
        {
            Debug.Write("Socket Exception: ");
            Debug.Write(s_ex.ErrorCode + s_ex.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
        finally
        {
            s.Close();
        }
    }

     

    Usually you won’t deal directly with Socket object, but with higher-level protocol classes that inherit from Socket class or embed a Socket object instance: anyway, you should always have access to socket-related operations, either directly or indirectly. For example, you can have a NetworkStream object that involves a TCP connection info and objects, then you can associate a StreamReader and/or StreamWriter objects in order to have an handy way to manage data; in this case, you have to call the proper method, which in turn eventually cause Socket object methods to be called.

    Here follows an example of a case study, using TCPClient and NetworkStream classes:

    try
    {
        using ( NetworkStream stream = tcpClient.GetStream() )
        {
            // Write some data onto the stream
            StreamWriter w = new StreamWriter( stream );
            w.Write( s );
            w.Flush();
            
            // force shutdown 
            tcpClient.Client.Shutdown(SocketShutdown.Send);
            
            StreamReader r = new StreamReader(stream);
            try
            {
                r.Read();
            }
            catch (System.IO.IOException ex)
            {
                Debug.WriteLine("End of connection (forced)");
            }
            
            w.Close();
            r.Close();
        }
    }
    catch ( Exception e )
    {
        Debug.WriteLine( e.ToString() );
    }

    Notice that Close() method has always to be called in order to dispose of the Socket object and to close native socket handle (this in turns raise a call to closesocket() API).

     

    Cheers,

    ALBERTO!

  • Mobile Development - 'Support Side Story'

    GPS Antenna on Windows Mobile: Internal or External?

    • 2 Comments

    - Do we really care?

    - GPS Hardware Port settings

    - Avoid end-user actions

    - A possible programmatic solution

     

    For whatever reason you may want to know if the GPS Antenna your Windows Mobile device is connected to is internal or external... but... are we sure we should care? If you’re using GPSID APIs, then you shouldn’t care if the GPS Antenna is external or internal: in both cases it must be set in the OS’ GPS control panel applet by the user (this is not the only option, see below). Programmatically speaking, once you’ll call GpsOpenDevice to create a connection to the GPSID, then it’s up to the Intermediate Driver to internally take care if the antenna is internal or external.

    In contrast, if you’re NOT using GPSID APIs (as I did in my previous test application I talked about in my blog), then probably your only option is as many 3rd party software do, i.e. scanning all the COM ports. In any case, also by using this approach you won’t be able to discriminate if the COM port you’re opening is related to an internal or external GPS antenna (for example if it’s a COM Port associated to the “Serial Port” service exposed by a Bluetooth GPS Antenna).

    So the question may become: why do you need to care if the antenna is internal or external? Well... for example you may think that if external then the user is required to explicitly set the "GPS Hardware Port" within the GPS control panel applet (Start\Settings-System\GPS), contrarily to the case where the antenna is internal, because the manufacturer very likely configured its properties when building the platform... I'm talking about the following:

    GPSSettingsHardware

    GPS Settings: Specify the hardware port to which your GPS device is connected. For more information, see the GPS device manufacturer's documentation.

    And since, as I've already written, every developer must know the motto "KNOW THY USER, FOR HE IS NOT THEE" [cit. from David S. Platt, President of Rolling Thunder Computing] Smile, you may want to provide users with as few as possible steps.

    Ok, consider that at the moment there's no Configuration Service Provider for GPSID, however all the properties are retrieved through the Registry! So, for example, the Hardware Port is set under the keys documented at GPS Intermediate Driver GPS Hardware Registry Settings. So, if you know how the user will set the "Serial Port Service" of the external GPS Antenna (Bluetooth, SD or any other hardware), then it's a matter of using the Registry functions, or Microsoft.Win32.Registry NETCF class or even the Registry Configuration Service Provider for example. If you can't know a priori how the user will set his external device, then even knowing if it's indeed an external device doesn't help...  probably the only option is at this point to instruct the user on how to set the external antenna's COM service and the associated Hardware Port within the GPSID control panel applet... This is basically what I saw in the manual of another great piece of software: Run.GPS! (thanks Giorgio for this hint!) -- see chapter 3 "GPS Support". I looked at SportsDo's user guide as well, and didn't find such info, probably purely because its GPS Data Interpreter engine is not based on Windows Mobile's GPSID (manual here).

     

    In any case, to verify if the target device has an integrated GPS Antenna or not, accordingly to the documentation above you can check the GPS Intermediate Driver GPS Hardware Registry Settings, and analyze the keys under [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]: I've found something interesting in this case...

    • example of some devices WITH integrated antenna (note key "CurrentDriver"):
      [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]
      "SleepOnNoData"=dword:000003e8
      "RetryWaitOnError"=dword:00000003
      "OutputBufferSize"=dword:00001000
      "InputBufferSize"=dword:00001000
      "CurrentDriver"="GPSOneDevice"
      
      [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOneDevice]
      "Version"=dword:00000001
      "PollInterval"=dword:000001f4
      "DriverName"="TAI"
      "FriendlyName"="QualComm GpsOne Card, version 0.0"
      "InterfaceType"="POLL"
      
      [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOneEmulate]
      "Filex"="\\windows\\GPSOneFileSimulation.txt"
      "FriendlyName"="QualComm GpsOne File, version 0.0"
      "InterfaceType"="File"
      
      [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOnePort]
      "CommPort"="COM1:"
      "FriendlyName"="QualComm GpsOne Card, version 0.0"
      "InterfaceType"="COMM"
    • other example of devices WITH integrated antenna (note key "CurrentDriver"):
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]
    "CurrentDriver"="Samsung GPS Hardware"
    
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\Samsung GPS Hardware]
    "CommPort"="COM9:"
    "FriendlyName"="Samsung GPS Card, version 1.0"
    "InputBufferSize"=dword:00001000
    "InterfaceType"="COMM"
    "OutputBufferSize"=dword:00001000
    "RetryWaitOnError"=dword:00002710
    "SleepOnNoData"=dword:00000064
    • devices WITHOUT integrated antenna:
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers] 
    "CurrentDriver"="Control Panel Configured Device"
    
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\Control Panel Configured Device] 
    "Baud"=dword:0000e100 
    "CommPort"="COM7:" 
    "InterfaceType"="COMM" 

    I've tried with a few devices (thanks Nicola, Carlo, Fernando and JP!! Tongue out) and in all of them the result is the same, i.e. when OEMs place a integrated antenna then they also "configure" its specific hardware through the [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers] key.

    I noted a different set of keys on one device only, on which by the way the integrate GPS Antenna was working as expected... the CurrentDriver was NOT there! (see below) Looking at WM6 documentation, if it's not set the GPS Intermediate Driver uses plug and play GPS hardware. So? Does "plug&play GPS Hardware" have sense on a device with integrated GPS Antenna?? Thinking  Without the CurrentDriver registry entry, multiple registry entries would have to change to switch between different GPS devices... without that set, does the device.exe load the first "driver" listed under [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]? Very likely yes (I should confirm looking at source-code).

    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers] 
    
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOneDevice] 
    "Version"=dword:00000001 
    "PollInterval"=dword:000001f4 
    "DriverName"="TAI" 
    "FriendlyName"="QualComm GpsOne Card, version 0.0" 
    "InterfaceType"="POLL" 
    
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOneEmulate] 
    "Filex"="\\windows\\GPSOneFileSimulation.txt" 
    "FriendlyName"="QualComm GpsOne File, version 0.0" 
    "InterfaceType"="File" 
    
    [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\GPSOnePort] 
    "CommPort"="COM1:" 
    "FriendlyName"="QualComm GpsOne Card, version 0.0" 
    "InterfaceType"="COMM"

     

    Even if we had such a confirmation, at this point the only thing that may discriminate if the GPS Antenna is internal or external SEEMS TO BE (I sure haven't tried on enough devices, so feel free to let me know!) *IF* [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers\Control Panel Configured Device] key *exists*.  I was initially thinking at checking the value of [HKEY_LOCAL_MACHINE\System\CurrentControlSet\GPS Intermediate Driver\Drivers]CurrentDriver, however as you noticed I found at least one device without it and yet with integrated antenna... To wrap up the discussion, a possible programmatic approach may be:

    - MANAGED:

    static void Main(string[] args)
    {
        RegistryKey rk = Registry.LocalMachine.OpenSubKey(
            @"System\CurrentControlSet\GPS Intermediate Driver\Drivers\Control Panel Configured Device");
        bool HasIntegratedGpsAntenna = (rk == null);
        if (rk != null)
            rk.Close();
    
        if (HasIntegratedGpsAntenna)
            MessageBox.Show("Integrated", "GPS Antenna");
        else
            MessageBox.Show("External", "GPS Antenna");
    }

     

    - NATIVE:

    int _tmain(int argc, _TCHAR* argv[])
    {
        HKEY hKey = NULL;
        LONG rc = NULL;
        BOOL HasIntegratedGpsAntenna = FALSE;
    
        rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
            L"System\\CurrentControlSet\\GPS Intermediate Driver\\Drivers\\Control Panel Configured Device", 
            0, 0, &hKey);
        
        HasIntegratedGpsAntenna = (rc != ERROR_SUCCESS); 
    
        //or probably better, including other error-check:
        //HasIntegratedGpsAntenna = (rc == ERROR_FILE_NOT_FOUND); 
    
        if (hKey != NULL)
            rc = RegCloseKey(hKey);
    
        if (HasIntegratedGpsAntenna)
            MessageBox(NULL, L"Integrated", L"GPS Antenna", MB_OK);
        else
            MessageBox(NULL, L"External", L"GPS Antenna", MB_OK);
    
        return 0;
    }

     

    Cheers,

    ~raffaele

  • Mobile Development - 'Support Side Story'

    LAP plugin hangs the device at startup

    • 1 Comments

    I handled a couple of cases related to this and therefore I think it's worth mentioning it here, to help other developers with the same issue. Basically this is precisely what this blog is all about, isn't it? Nerd 

    Imagine you’re developing a LAP plugin for devices running Windows Mobile 6. A custom LAP DLL is what you need if you want to change the way user authenticates to the device, basically implementing device-lock. A pretty common scenario is if you want to change the simple 4-digit PIN with a strong alpha-numeric password, which is precisely the aim of the 2 SDKs' samples C:\Program Files\Windows Mobile 6 SDK\Samples\PocketPC\CPP\win32\LAP and C:\Program Files\Windows Mobile 6 SDK\Samples\Smartphone\cpp\Win32\LAP.

    When developing this, the very first step may (should?) be to start from such SDKs' samples, however you may immediately find a problem: after installing the LAP DLL (which requires setting some registry keys apart from copying the DLL under \Windows -- it's all in the samples' readme files), after a soft-reset the OS does no longer start up: it completely freezes at Windows Mobile logo. This can be even reproduced on the emulators as well, therefore the problem must not be related to the customization of the platform done by the OEM. And this may happen on both Pocket PCs and Smartphones (oops, WM6 Professional\Classic and Standard).

    So, what's going on -- are the SDK samples buggy? No, this is not the case... Angel

    Above all, there are some differences between the LAP implementation on Pocket PC and Smartphone: that’s why the 2 SDKs contain 2 different sample codes. And if you want to start from the SDK Samples then you must use them to target the relevant platform. If you try to run the Pocket PC's sample on a Smartphone it may hang at startup, and viceversa.

    Secondly, remember (as the readme files state), that after installing the LAP CAB (which copies the DLL and set the registry), you must SOFT-RESET the device. This may be avoided by programmatically invoking LASSReloadConfig() API though.

    Thirdly , the LAP DLL MUST be signed with a certificate stored on the Priviledge Certificate Store of the target device, otherwise it won’t be loaded at OS boot (setting registry keys is not enough). For testing purposes only, you can sign the DLL with a SDK Certificate *AND* install the SDK Certificates on the target device (otherwise it won’t be recognized and the dll won’t be loaded). See for example: "[...] In Windows Mobile-based devices, the LAP DLL must run privileged. The DLL must be signed with a privileged certificate." (from Creating a LAP-page on Channel 9).

    So, the only thing you should do with the sample is to sign it with a Privileged Certificate - well, a second thing may be to add a Smart Device CAB project to set all those registry keys - and for our testing we'll use the SDK Privileged Test certificate. You can do that in many ways:

    1. In project properties, select “Authenticode Signing” node and set “Authenticode Signature” to “Yes” and “Certificate” to the “TEST USE ONLY – Sample Privileged Developer – Windows Mobile SDK”.

    clip_image001

    If you can’t see any certificate to choose, it means you’ve never enrolled them on the desktop PC. In such a case, simply click on “Manage Certificates” and navigate to “C:\Program Files\Windows Mobile 6 SDK\Tools\Security\SDK Development Certificates” to enroll SamplePrivDeveloper.pfx (note the .PFX extension). Follow the wizard by choosing all the default options.

    2. Or after compiled the project into a DLL, by using C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\signtool.exe. You can create a .bat with the following command, so that you don't have to launch it from a command-line every time your build the project:

    “C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\signtool.exe” sign /f “C:\Program Files\Windows Mobile 6 SDK\Tools\Security\SDK Development Certificates\SamplePrivDeveloper.pfx” LAP.DLL

    3. Or even after compiled the project and placed the DLL into the CAB, by using C:\Program Files\Windows Mobile 6 SDK\Tools\Security\CabSignTool\cabsigntool.exe (this signs CAB and inside executable in one shot).

     

    To recap, the OS hangs at startup if:

    • the DLL is not signed with a certificate registered under the Privileged Certificate Store of the device
    • the DLL is compiled for a platform different from the one you’re testing (Standard --> smartphone; Professional\Classic --> Pocket PC)

    If you're sure about the previous points and the hang issue continues appearing (even with the SDK Samples), then you should make sure that the certificate you're signing the DLL with is really registered in the Privileged Certificate Store of the device. To do so, you can use RapiConfig to query the CertificateStore CSP by using the following XML Provisioning:

    <wap-provisioningdoc> 
      <characteristic type="CertificateStore"> 
        <characteristic-query type="Privileged Execution Trust Authorities"/> 
      </characteristic> 
    </wap-provisioningdoc>

    Steps are:

    • create a .xml file with the XML described above (“queryCert.xml”) 
    • cradle the device and establish an ActiveSync\WMDC connection (a partnership is not necessary)
    • start a command-prompt and launch the command < "C:\Program Files\Windows Mobile 6 SDK\Tools\PocketPC\RapiSecurity\RapiConfig" /P /M queryCert.xml >
    • analyze the output to see if you can see the certificate you're signing the DLL with

    Alternatively you can use the Security Power Toy, whose installation package is available at C:\Program Files\Windows Mobile 6 SDK\Tools\Security\Security Powertoy.

    If RAPI are disabled or restricted on the device (hence you can't use RapiConfig), then you can use the a very simple managed code tp be run directly on the device, based on the ConfigurationManager.ProcessConfiguration() method:

    string XmlQuery = "<wap-provisioningdoc>\r\n" +
    "<characteristic type=\"CertificateStore\">\r\n" +
    "<characteristic-query type=\"Privileged Execution Trust Authorities\"/>\r\n" +
    "</characteristic>\r\n" +
    "</wap-provisioningdoc>";
    
    Cursor.Current = Cursors.WaitCursor;
    XmlDocument queryDoc = new XmlDocument();
    XmlDocument resultDoc = new XmlDocument();
    try{
        queryDoc.LoadXml(XmlQuery);
        try{
            resultDoc = ConfigurationManager.ProcessConfiguration(queryDoc, true);
            resultDoc.Save("\\ConfigXmlOut.xml");
        }
        catch (Exception eProcessConfiguration){
            MessageBox.Show("ProcessConfiguration error:\r\n" + eProcessConfiguration.ToString());
        }
    }
    catch (Exception eLoadXml){
        MessageBox.Show("LoadXml error:\r\n\r\n" + eLoadXml.ToString());
    }
    Cursor.Current = Cursors.Default;
    MessageBox.Show("Done!");

     

    If the problem continues, then you may open a case at Technical Support to further investigate about it...

     

    REFERENCES about Windows Mobile 5.0 Local Authentication Sub System (LASS):

     

    Cheers,

    ~raffaele

  • Mobile Development - 'Support Side Story'

    get what you paid for!!

    • 3 Comments

    [subtitle: How to open a Service Request at Microsoft Technical Support]

    I've been contacted by some developers asking details about how to open a Service Request at Microsoft Technical Support: after my interview with Chris pointed by my previous post, I'm extremely glad to provide details about this... Smile As I said there: "It’s simply great that nowadays many developers rely on newsgroups and forums! I was there when Microsoft newsgroups were born and personally helped them to grow up, until they became auto-sufficient thanks to the great support given by Microsoft MVPs. When you don’t find an answer through your favourite Microsoft newsgroup or MSDN forums (or whatever!), just give the Microsoft Technical Support the chance to show what added value it can offer. If you have a contract (“Premier” or “Partner”) you will already be using it. If you have a MSDN Subscription or simply bought a Visual Studio box, chances are that you don’t know that you have the opportunity to open Service Requests thanks to a certain number of so-called “incidents”… so my suggestion is: make sure you use everything you’ve ALREADY paid for! :-)"

     

    Partners and Premier Customers have their Account Managers in Microsoft, so they know how to create requests: they can contact their references in Microsoft but also have dedicated phone numbers.

    MSDN Subscriptions' owners: start here and see below (it mentions VS2005, but it's the same for VS2008):

    image 

     

    Visual Studio-boxes' owners [the first time you'll have to register the product through its PID, which you can also do through VS' menu Help\About - Register Product]

    - by phone: search your local Customer Service's phone number here, by selecting your country under the "Contact Information" drop-down list (I imagine the same list is indirectly available here).

    - via web: starting here, you'll need to select your product -- for example, if you select "VS2005 Professional" you'll end up here -- note "E-mail support"\"Submit Online"\"Submit Request by phone":

    image

      

    You've finished your incidents and need support? Then you have the "Pay Per Incident" option available. You can buy a single incident or a 5-pack: however I think this depends on your country and therefore the best approach is to engage your local Customer Service over the phone (again, selecting your country under the "Contact Information" drop-down list at this page).

     

    Happy submitting!

    ~raffaele

  • Mobile Development - 'Support Side Story'

    SetWindowsHookEx on Windows Mobile

    • 2 Comments
    • "supported"??
    • An interesting API: GetForegroundKeyboardTarget

    Sometimes cases arrive to my desk with issues regarding the usage of SetWindowsHookEx() API on Windows Mobile. As per Kiosk-applications, we should simply reject such requests, because the developer is asking about something "unsupported" -- that API is not documented on the Windows CE or the Windows Mobile SDK Documentation. It's the usual story: "technically achievable" doesn't mean "supported". In this case it's even worse because SetWindowsHookEx is a Private API and it's even not documented in the OEM Adaptation Kit's Documentation (which is different from the doc for ISV Developers coming with the SDKs and it's available to OEMs only, as they need to know internal details about the platform they're adapting for their hardware basically). This means that the Dev Team can change coredll.dll at any point in time by for example no longer exposing that API without breaking any backward-compatibility... I remember a post by Daniel Moth about using undocumented features... yes, here it is: #NETCF_AGL_ (cit.: "The moral of the story is, if you do take advantage of undocumented features, your application may break when you move it to the next version regardless of the compatibility efforts of the product teams at MSFT.")

    So, even if on the web you'll find many ways to hook keyboards or windows-procedure (and even a NETCF wrapper done by Alex Yakhnin), you should use them with care and consider that it may also be that new images of the OS may not support it. If you really want to use (read: "if you can't find alternatives") on Windows Mobile, at least make sure you sign the executable with a certificate registered on the Privileged Certificate Store of the target devices: I found many entries about this on the MSDN Forums and newsgroups.

    In a particular case, a developer was having troubles with SetWindowsHookEx on one particular device model only... so the issue was OEM-specific. How can we know how the OEM customized the image (by adding particular applications in ROM, for example) so that precisely the same application doesn't work? We couldn't go on with the support in this case and we had to revert to using "supported" techniques, such as subclassing, which in some cases is still more appropriate than a system-wide hook, especially in low-resources OSs like Windows CE or Mobile.

    I've already discussed here about subclassing NETCF Applications, however this time a developer I recently worked with pointed my attention to an API I had forgot (GetForegroundKeyboardTarget) and that in our case it helped us on achieving precisely what we were looking for: intercepting keyboard presses when focus was given to an editbox. Here it is a snippet (note that the technique for subclassing is always the same).

    s_hExit = CreateEvent(NULL, FALSE, FALSE, NULL); 
    HWND hWnd = GetForegroundKeyboardTarget();
    if (hWnd!=NULL) 
    { 
        s_OldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC); 
        BOOL bSetNewProc = SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)NewWndProc); 
        WaitForSingleObject(s_hExit, INFINITE); 
        SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)s_OldWndProc); 
    } 

     

    A nice idea he had was to associate a hardware button to a console application, so that he subclassed only the window of an editbox when this had the focus (and this is where GetForegroundKeyboardTarget comes to help). A possible code sample is:

    static WNDPROC s_OldWndProc = NULL;
    static HANDLE s_hExit = NULL;
     
    LRESULT CALLBACK NewWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CHAR:
            {
                TCHAR chCharCode = (TCHAR) wParam; 
                switch (chCharCode)
                {
                    case _T('a'):
                    //...
                        break;
                }
            }
            break;
     
        case WM_DESTROY:
            {
                if (s_hExit)
                {
                    SetEvent(s_hExit);
                }
            }
            break;
     
        if (s_OldWndProc)
        {
            return CallWindowProc(s_OldWndProc, hwnd, uMsg, wParam, lParam);   
        }
        return 0;
    }
     
    int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
    {
        s_hExit = CreateEvent(NULL, FALSE, FALSE, NULL);
        HWND hWnd = GetForegroundKeyboardTarget(); 
        if (hWnd!=NULL)
        {
            s_OldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
            BOOL bSetNewProc = SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)NewWndProc);
            WaitForSingleObject(s_hExit, INFINITE);
            SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)s_OldWndProc);
        }
        return (0);
    }

     

     

    Cheers,

    ~raffaele

  • Mobile Development - 'Support Side Story'

    Arabic Support on Windows Mobile

    • 0 Comments

    [- subtitle: languages natively supported on Windows Mobile]

    Sometimes colleagues and customers posed this question... so maybe it's worth writing its answer here: "Is Arabic language supported on Windows Mobile and CE??". Looking at the documentation available to Windows Mobile manufacturers, there are no Arabic-based locales available for Windows Mobile; in contrast Windows *CE*-manufacturers can choose all the OS languages and locales available at "Language Identifiers and Locales (Platform Builder for Microsoft Windows CE 5.0)".

    Windows Mobile OEM  Documentation is not public, however publicly available is the “Windows Mobile 6 Product Reference Guide”, whose Appendix B lists all the supported International SKUs - over the years SKUs have been added and possibly new ones will be added as well in future versions of the OS: have a look -- we've reached 20 for WM6 Professional(\Classic) and 25 for WM6 Standard!

    image

    Therefore:

    - Windows MOBILE-manufacturers canNOT choose to support Arabic language nor Arabic locale

    - Windows CE-manufacturers can choose to support Arabic language and Arabic locale

    As a double-check, the following MSDN Doc page “Arabic OS Design Development” is relevant to Windows CE but NOT to Windows Mobile:

    image

     

    *HOWEVER* this doesn't mean that third party developers can provide locales or controls supporting Arabic internationalization. In the past I had the opportunity to work with one of this third parties for a problem a common customer was having... Surfing the web you'll surely find them and you may want to try their software: I can for example mention Paragon Software (SHDD) solution, because they're a Microsoft Gold Certified Partner. I hope I'm not missing any other Partner... Open-mouthed [let me know if that's the case!]

     

    Cheers,

    ~raffaele

     

    P.S. Pasting the table above as text, so that it can be indexed:

    Supported International SKUs on Windows Mobile

    LCID  Professional  Standard  Language
    409 WWE  X X WWE
    407 GER  X X German
    804 CHS X X Chinese S.
    809 UKE    X UK English
    040C FRE X X French
    410 ITA X X Italian
    0C0A ESN  X X Spanish
    412 KOR  X X Korean
    411 JPN  X X Japanese
    404 CHT  X X Chinese T.
    413 NLD  X X Dutch
    406 DAN  X X Danish
    41D SVE  X X Swedish
    40B FIN  X X Finnish
    414 NOR  X X Norwegian
    416 PTB  X X Br. Port.
    816 PTG  X X Eur. Port.
    405 CSY  X X Czech
    418 ROM    X Romanian
    41B SKY    X Slovak
    415 PLK  X X Polish
    40E HUN    X Hungarian
    41F TUR    X Turkish
    419 RUS  X X Russian
    408 ELL  X X Greek
Page 1 of 1 (6 items)