Tuesday, February 28, 2006

So today I'm working at home listening to a new found online 80's radio station from somewhere on the other side of the pond and on came a song that actually somewhat shocked me.  I mean I'm not offended - I thought it was funny as hell, and being offended is what being free is about anyway. 

Anyway it was a guy I'd never heard of before: Ivor Biggun.  Now I imagine if you're from that side of the pond you've heard of him - he's been around for decades and has loads of albums out, but after reviewing a little of it - just scanning track titles even - I think I know why I've never heard him before.

Long live the uncensored world of online radio.

2/28/2006 4:52:42 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  | 
 Monday, February 27, 2006

So the OpenNETCF.Desktop.Communication library has been used in the "first malware to cross-infect a handheld phone or PDA from a desktop PC binary file...." (reported by the Mobile Antivirus Research Association).

The quote from the author is as follows:

The crossover virus was written in C# (C Sharp) using Visual Studio .NET 2003, the Communications Library of openNETCF.org was used and a great help

As part of such a "first" I'm not so sure I'm proud of, it does show how pervasive something as useful as our libraries can be.

 

2/27/2006 7:41:29 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, February 23, 2006

If you're building a CE image and want to include CF 1.0 or CF 2.0, then it's pretty simple - just drag the component from the catalog into your workspace.  But what if you don't want to include the CF at all, but still have the plumbing there so your end-user can install the CF themselves and have it work?  One could look through the cesysgen.bat files and decipher what needs to be set or, if you're lazy like me, you could ask the CF team.

Here's the answer, courtesy of Jim Suplizio:

The appropriate support sysgen will have to be added to the image depending on what version of CF is going to be installed.

  • SYSGEN_DOTNET_SUPPORT is the CF 1.0 support sysgen.
  • SYSGEN_DOTNETV2_SUPPORT is the CF 2.0 support sysgen. SYSGEN_DOTNETV2_SUPPORT is a super-set of the CF 1.0 support.

Effectively if SYSGEN_DOTNETV2_SUPPORT is added to the image then the end user can deploy either 1.0 or 2.0 and all of the required underlying CE OS pieces will be there.

Keep in mind that required means "base functionality". CF 2.0 has optional functionality that requires other SYSGENS and they are as follows:

  • Message Queuing - SYSGEN_MSMQ
  • Soap Reliable Messaging Protocol - SYSGEN_MSMQ_SRMP
  • SQLMobile (2005) requires CoCreateGuid functionality - SYSGEN_OLE_GUIDS
  • IPv6 - SYSGEN_TCPIP6
  • IE, PIE, HTMLView (htmlview.dll) or nothing - SYSGEN_IE, SYSGEN_PIE, SYSGEN_HELP or simply nothing.
  • The following only apply to the MainstoneII, other devices will only have null driver sets:
    • D3D Mobile - BSP_D3DM_XSCALE
    • D3D Mobile - SYSGEN_D3DMXSCALE

 

2/23/2006 4:47:21 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Wednesday, February 22, 2006

It's been a while since we visited the OpenNETCF.Deskop.Communication library, but there have been lingering issues that ActiveSync 4.x have exposed (a stack imbalance exception).  So today I revisited the library and did some fixes to it as well as to the sample app (bad, bad me for not marshaling calls to the UI from a thread.  It's now a Studio 2005 project.

The latest code is in Vault and the downloads on the site are updated to this new version (2.9) as well.

2/22/2006 2:09:33 PM (Eastern Standard Time, UTC-05:00)  #    Comments [2]  | 
 Sunday, February 19, 2006

SDF 2.0 continues to have functionality for working with the time and time zones for devices.  The differences from SDF 1.x are a namespace change, a classname change (don't believe the beta docs or the beta, these have changed since that drop), and under the hood a lot more internal checks are going on to head off errors and to provide correct device support.  Basically this one has been pretty heavily tested across a broad range of devices.

Some quick highlights:

Getting and Displaying a List of Time Zones

using OpenNETCF.WindowsCE;
...
// get and display all available zones
TimeZoneCollection tzc = new TimeZoneCollection();
tzc.Initialize();

foreach (TimeZoneInformation tzi in tzc)
{
    lstZones.Items.Add(tzi);
}

Displaying the Currently Set Time Zone

using OpenNETCF.WindowsCE;
...
// get and display the currrent zone

TimeZoneInformation currentTz = new TimeZoneInformation();
DateTimeHelper.GetTimeZoneInformation(ref currentTz);
lblCurrentZone.Text = currentTz.StandardName;

Setting the Current Time Zone (from the Listing above)

using OpenNETCF.WindowsCE;
...
if
(lstZones.SelectedItem != null)
{
    TimeZoneInformation tzi = (TimeZoneInformation)lstZones.SelectedItem;
    DateTimeHelper.SetTimeZoneInformation(tzi);

    // this verifies that the time zone did indeed get changed
    TimeZoneInformation tz = new TimeZoneInformation(
        (byte[])Registry.LocalMachine.OpenSubKey("Time").GetValue(
            "TimeZoneInformation"));
    MessageBox.Show("Current Timezone in Registry is:\r\n" 
        + tz.StandardName, "Verified");
}

Displaying the Current Time (without DateTime.Now)

using OpenNETCF.WindowsCE;
...
DateTime dt = DateTimeHelper.SystemTime;

txtHour.Text = dt.Hour.ToString();
txtMinute.Text = string.Format("{0:00}", dt.Minute);
txtSecond.Text = string.Format("{0:00}", dt.Second);

Setting The Current System Time (Local Time is Analogous)

using OpenNETCF.WindowsCE;
...
// get the current time so we can copy the date part

DateTime dt = DateTimeHelper.SystemTime;

DateTimeHelper.SystemTime = new DateTime(dt.Year, dt.Month, dt.Day,
    int.Parse(txtHour.Text), int.Parse(txtMinute.Text), int.Parse(txtSecond.Text));

 

2/19/2006 6:17:03 PM (Eastern Standard Time, UTC-05:00)  #    Comments [4]  | 
 Saturday, February 18, 2006

I'm trying to debug an error in some managed code related to timezones when a P/Invoke is throwing a native access violation exception.  To make sure it's not something with the platform itself I decided to do the same in native code first to ensure that it's not some platform limitation or bug.  Surprisingly I didn't readily find any sample code for doing it, so here's my contribution to the community at large.  It uses dynamic loading (and it doesn't make sure that the function loads succeed, so you might want to add error checking if you actually intend to use this):

#include <windows.h>

typedef void    (*INITCITYDB)(void);
typedef void    (*UNINITCITYDB)(void);
typedef void    (*LOADTZDATA)(void);
typedef void    (*FREETZDATA)(void);
typedef int        (*GETNUMZONES)(void);
typedef void *    (*GETTZDATABYOFFSET)(int, int*);
typedef void *    (*GETTZDATA)(int);

struct TZData
{
    TCHAR *Name;
    TCHAR *ShortName;
    TCHAR *DSTName;
    int GMTOffset;
    int DSTOffset;
};

int _tmain(int argc, _TCHAR* argv[])
{
    TZData *pTZ = NULL;
    int index;

    // load the library
    HINSTANCE hLib = LoadLibrary(_T("CityDB.dll"));

    // load the CityDB functions
    INITCITYDB InitCityDB = (INITCITYDB)GetProcAddress(
            hLib, _T("InitCityDb"));
    UNINITCITYDB UninitCityDB = (UNINITCITYDB)GetProcAddress(
            hLib, _T("UninitCityDb"));
    LOADTZDATA ClockLoadAllTimeZoneData = (LOADTZDATA)GetProcAddress(
            hLib, _T("ClockLoadAllTimeZoneData"));
    FREETZDATA ClockFreeAllTimeZoneData = (FREETZDATA)GetProcAddress(
            hLib, _T("ClockFreeAllTimeZoneData"));
    GETNUMZONES ClockGetNumTimezones = (GETNUMZONES)GetProcAddress(
            hLib, _T("ClockGetNumTimezones"));
    GETTZDATABYOFFSET ClockGetTimeZoneDataByOffset = 
            
(GETTZDATABYOFFSET)GetProcAddress(hLib, _T("ClockGetTimeZoneDataByOffset"));
    GETTZDATA ClockGetTimeZoneData = (GETTZDATA)GetProcAddress(
            hLib, _T("ClockGetTimeZoneData"));

    // Init the library
    InitCityDB();

    // load the TZ data
    ClockLoadAllTimeZoneData();

    // find out how many zones are defined
    int zoneCount = ClockGetNumTimezones();

    // interate through them all
    for(int zone = 0 ; zone < zoneCount ; zone++)
    {
        // these are pointers to a timezone data struct
        pTZ = (TZData*)ClockGetTimeZoneDataByOffset(zone, &index);
    }

    // unload the TZ data
    ClockFreeAllTimeZoneData();

    // uninit the library
    UninitCityDB();

    return 0;
}

2/18/2006 1:45:07 PM (Eastern Standard Time, UTC-05:00)  #    Comments [3]  |