SIM Manager

Every phone or data device that operates on the GSM (Global System for Mobile) network contains a small, postage stamp sized card that is known as the Subscriber Identity Module (SIM). The SIM is actually a smart card that contains both a processor and storage for contacts, messages, and data. Typical SIM cards have between 16KB and 64KB of storage, which provides you with plenty of room for hundreds of phone numbers, messages, or other information.

You can usually remove the SIM card from the phone, which enables you to move your phone numbers, contacts, and other data between devices. For example, if you remove the SIM card from your GSM phone and place it into a Pocket PC Phone Edition device, the Pocket PC will have access to all of the dialing information, messages, and even phone numbers that the old device had. In essence, the SIM card is the storage medium for all of your personal and subscription data.

Pocket PC Phone Edition provides a set of functions called the SIM Manager (see Figure 8.3), which enables you to interact with the SIM card currently in the device. These APIs enable you to change the status of the phone locked state, manipulate contact entries that are on the SIM card, and read messages currently stored on the card.

Figure 8.3. Pocket PC Phone Edition SIM Manager

graphics/08fig03.gif

In order to use the SIM Manager APIs in your applications, you need to include the simmgr.h header file in your project, and link with the cellcore.lib library.

Initialization and Notifications

Before you can access any information on the SIM card, you first must call the SimInitialize() function. This function actually has two purposes: One, it provides a handle to the SIM, which you will use for additional calls to get information from the card. Two, SimInitialize() can be used to register a callback function that will send you notifications whenever changes occur to the SIM while you have the handle open:

 HRESULT SimInitialize(DWORD dwFlags, SIMCALLBACK    lpfnCallBack, DWORD dwParam, LPHSIM lphSim); 

The first parameter, dwFlags, specifies whether or not you want to receive notification messages from the SIM. By setting the flag to SIM_INIT_SIMCARD_NOTIFICATIONS, notifications will be sent to the callback function that is pointed to by the lpfnCallback parameter. If you do not need to receive informational messages from the SIM, you can set dwFlags to 0, and lpfnCallBack to NULL. The dwParam parameter is a DWORD value that is sent to your callback function every time a notification is sent. The last parameter, lphSim, is a pointer to an HSIM handle that you will use for making additional calls to the SIM card.

The following example initializes the SIM card for reading data without using a callback:

 HRESULT hr = S_OK; HSIM hSim = NULL; // Initialize and open the SIM w/o a callback hr = SimInitialize(0, NULL, 0, &hSim); if(FAILED(hr)) {    MessageBox(NULL, TEXT("Could not open the SIM"),       TEXT("Error"), MB_OK|MB_ICONERROR);    return FALSE; } // Continue with app... 

If you decide to receive notifications from the SIM when changes occur, then you need to pass a pointer to a callback function (identified by the lpfnCallBack parameter). Whenever the device or another application attempts to modify the contents of the SIM card, your function will then be called. The callback function you create must have the following definition:

 void SIMCallbackFunction(DWORD dwNotifyCode,    const void *lpData, DWORD dwDataSize, DWORD dwParam); 

The first parameter that will be sent to your function specifies the notification that was received from the SIM. Next, the contents of the lpData pointer will depend on which notification message you are receiving. For example, if you are sent a SIM_NOTIFY_CARD_REMOVED, then lpData will be NULL. However, if you received a SIM_NOTIFY_PBE_DELETED notification, lpData will point to a SIMPBECHANGE structure that provides additional information about the phonebook entry that has been modified.

Table 8.1 lists both the notification messages and the structure information sent to lpData.

Table 8.1. SIM Callback Notifications

Notification

lpData

Description

SIM_NOTIFY_CARD_REMOVED

NULL

The SIM card has been removed.

SIM_NOTIFY_FILE_REFRESH

SIMFILEREFRESH

Files on the SIM have been refreshed.

SIM_NOTIFY_MSG_STORED

SIMMESSAGECHANGE

A message has been stored on the SIM.

SIM_NOTIFY_MSG_DELETED

SIMMESSAGECHANGE

A message has been deleted from the SIM.

SIM_NOTIFY_MSG_RECEIVED

SIMMESSAGECHANGE

A message was sent directly to the SIM.

SIM_NOTIFY_PBE_STORED

SIMPBECHANGE

A phonebook entry has been stored on the SIM.

SIM_NOTIFY_PBE_DELETED

SIMPBECHANGE

A phonebook entry has been deleted from the SIM.

SIM_NOTIFY_RADIOOFF

NULL

The modem radio has been turned off.

SIM_NOTIFY_RADIOON

NULL

The modem radio has been turned on.

SIM_NOTIFY_RADIOPRESENT

DWORD

The modem radio has been installed. The DWORD value stored in lpData will indicate 0 if the radio is off, and 1 if it is on.

SIM_NOTIFY_RADIOREMOVED

NULL

The modem radio has been removed.

The dwDataSize parameter will specify, in bytes, the size of the structure returned in lpData. The final parameter, dwParam, is the DWORD value that was previously set in your original call to the SimInitialize() function.

If any changes to the files on the SIM occur (SIM_NOTIFY_FILE_REFRESH), your callback function will be passed a SIMFILEREFRESH structure that looks like the following:

 typedef struct simfilerefresh_tag{    DWORD cbSize;    DWORD dwParams;    DWORD dwFlags;    DWORD dwFileCount;    DWORD rgdwAddress[MAX_FILES]; } SIMFILEREFRESH, FAR *LPSIMFILEREFRESH; 

The first field, cbSize, is the size, in bytes, of the SIMFILEREFRESH structure. Next, the dwParams field specifies which of the fields in the SIMFILEREFRESH structure are valid, and can be one or more of the following values:

  • SIM_PARAM_FILEREFRESH_FLAGS indicates that the dwFlags field is valid.

  • SIM_PARAM_FILEREFRESH_FILECOUNT indicates that the dwFileCount field is valid.

  • SIM_PARAM_FILEREFRESH_FILEARRAY indicates that the rgdwAddress field is valid.

  • SIM_PARAM_FILEREFRESH_ALL indicates that all the fields are valid.

The dwFlags field contains additional details about what has changed with regard to the SIM's file system, and can be one or more of the following:

  • SIMFILE_FULLFILECHANGE specifies that all files have changed.

  • SIMFILE_FILECHANGE specifies that only a few files have changed.

  • SIMFILE_SIMINIT specifies that the SIM has been initialized.

  • SIMFILE_SIMRESET specifies that the SIM has been reset.

The dwFileCount field, as the name implies, contains a DWORD value that indicates how many files have changed, and indicates the number of rgdwAddress structures in the array of files.

For example, the following code would handle a notification that some files have changed on the SIM:

   // The SIM notification callback   void SimCallbackProc(DWORD dwNotifyCode, const void *lpData,      DWORD dwDataSize, DWORD dwParam)   {      // Handle a file change      if(dwNotifyCode == SIM_NOTIFY_FILE_REFRESH) {      SIMFILEREFRESH *pfileRefresh = (SIMFILEREFRESH *)lpData;      TCHAR tchNotifyMessage[1024] = TEXT("\0");      if(!pfileRefresh)         return;      // Handle the file change notification      if(pfileRefresh->dwParams & SIM_PARAM_FILEREFRESH_FILECOUNT) {         wsprintf(tchNotifyMessage, TEXT("%d files have         changed"), pfileRefresh->dwFileCount);         MessageBox(NULL, tchNotifyMessage, TEXT("SIM File            Change"), MB_OK);      }      // Get the DWORD address of the SIM files that have changed      // if(pfileRefresh->dwParams &         SIM_PARAM_FILEREFRESH_FILEARRAY) {         DWORD dwFiles = 0;         for(dwFiles; dwFiles < pfileRefresh->dwFileCount;            dwFiles++) {            wsprintf(tchNotifyMessage, TEXT("File change               #%d. File address: %d"), dwFiles,               pfileRefresh->rgdwAddress[dwFiles]);            MessageBox(NULL, tchNotifyMessage, TEXT("SIM               Files Change"), MB_OK);        }      }   }   return; } // Initialize the SIM BOOL InitializeSIM(HSIM *phSim) {    HRESULT hr = S_OK;    // Initialize and open the SIM w/ a callback    hr = SimInitialize(SIM_INIT_SIMCARD_NOTIFICATIONS,       (SIMCALLBACK)SimCallbackProc, 0, phSim);    if(FAILED(hr)) {       MessageBox(NULL, TEXT("Could not open the SIM"),          TEXT("Error"), MB_OK|MB_ICONERROR);       return FALSE;    }    return TRUE; } 

If the SIM detects any changes to a message located on the card (SIM_NOTIFY_MSG_STORED, SIM_NOTIFY_MSG_DELETED, or SIM_NOTIFY_MSG_RECIEVED), the callback function is passed a SIMMESSAGECHANGE structure, which is defined as follows:

 typedef struct simmessagechange_tag{     DWORD dwEntry;     DWORD dwStorage; } SIMMESSAGECHANGE, FAR *LPSIMMESSAGECHANGE; 

This structure has only two fields: the index to the entry that has changed and its storage location. The dwStorage field will be set to the SIM_SMSSTORAGE_BROADCAST location if its storage location is with system broadcast messages; otherwise, it will be set to SIM_SMSSTORAGE_SIM.

Finally, the last type of notification you can receive deals with entries in SIM's phonebook (SIM_NOTIFY_PBE_STORED, SIM_NOTIFY_PBE_DELETED), and uses the SIMPBECHANGE structure:

 typedef struct simpbechange_tag{    DWORD dwEntry;    DWORD dwStorage; } SIMPBECHANGE, FAR *LPSIMPBECHANGE; 

The first field is the index to the phonebook entry that has changed. The dwStorage field specifies the phonebook in which the entry is located, and can be one of the following values:

  • SIM_PBSTORAGE_EMERGENCY, if the entry is located in the Emergency dial list

  • SIM_PBSTORAGE_FIXEDDIALING, if the entry is in the SIM fixed dialing list SIM_PBSTORAGE_LASTDIALING, if the entry is in the SIM last dialing list

  • SIM_PBSTORAGE_OWNNUMBERS, if the entry is in the SIM ownnumbers list

  • SIM_PBSTORAGE_SIM, if the entry is in the general SIM storage

The following code shows how to handle a notification message that indicates a change to one of the phonebook entries:

 // The SIM notification callback void SimCallbackProc(DWORD dwNotifyCode, const void *lpData,    DWORD dwDataSize, DWORD dwParam) {    // Handle a phonebook change    if(dwNotifyCode == SIM_NOTIFY_PBE_STORED ||       dwNotifyCode == SIM_NOTIFY_PBE_DELETED) {       SIMPBECHANGE *pPBNotify = (SIMPBECHANGE *)lpData;       TCHAR tchNotifyMessage[1024] = TEXT("\0");       TCHAR tchPhonebook[256] = TEXT("\0");       if(!pPBNotify)           return;       switch(pPBNotify->dwStorage) {          case SIM_PBSTORAGE_EMERGENCY:             wsprintf(tchPhonebook, TEXT("Emergency Number List"));             break;          case SIM_PBSTORAGE_FIXEDDIALING:             wsprintf(tchPhonebook, TEXT("Fixed Dialing List"));             break;          case SIM_PBSTORAGE_LASTDIALING:             wsprintf(tchPhonebook, TEXT("Last Numbered                Dialed List"));             break;          case SIM_PBSTORAGE_OWNNUMBERS:             wsprintf(tchPhonebook, TEXT("Own Number List"));             break;          case SIM_PBSTORAGE_SIM:             wsprintf(tchPhonebook, TEXT("General List"));             break;          default:             wsprintf(tchPhonebook, TEXT("Unknown List"));             break;      }      // Build a message      wsprintf(tchNotifyMessage, TEXT("A phonebook entry in         the %s at index %d has been "), tchPhonebook,         pPBNotify->dwEntry);       // Type of notification       if(dwNotifyCode == SIM_NOTIFY_PBE_DELETED)          _tcscat(tchNotifyMessage, TEXT("deleted."));       else if(dwNotifyCode == SIM_NOTIFY_PBE_STORED)          _tcscat(tchNotifyMessage, TEXT("modified."));     }     return;  } 

When you are finished working with information on the SIM, you can simply call the SimDeinitialize() function, which is defined as follows:

 HRESULT SimDeinitialize(HSIM hSim); 

The only parameter that the function needs is a handle to the SIM module that was previously returned by the original call to SimInitialize().

The following code sample shows how to properly release the handle to the SIM module:

 // Close the SIM handle if(hSim)    SimDeinitialize(hSim); 

SIM Details

To get more information about what functionality the SIM supports, you can use the following function:

 HRESULT SimGetDevCaps(HSIM hSim, DWORD dwCapsType, LPSIMCAPS   lpSimCaps); 

This function can be used to query specific capabilities of the SIM by functional area, or to return information about the phonebook or locking passwords. To use it, you need to pass the handle to the SIM that was returned from a previous call to SimInitialize() in the hSim parameter. The dwCapsType parameter can be used to set which capabilities you are interested in, and can be one or more of the following values:

  • SIM_CAPSTYPE_PBENTRYLENGTH, to query phonebook entry lengths

  • SIM_CAPSTYPE_PBSTORELOCATIONS, to query phonebook storage locations

  • SIM_CAPSTYPE_LOCKFACILITIES, to query the available Lock facilities

  • SIM_CAPSTYPE_PBINDEXRANGE, to query valid phonebook entry indexes

  • SIM_CAPSTYPE_LOCKINGPWDLENGTHS, to query the Locking password lengths

  • SIM_CAPSTYPE_MSGMEMORYLOCATIONS, to query Message memory locations

  • SIM_CAPSTYPE_ALL, to query all of the SIM capabilities

The last parameter, lpSimCaps, should point to a SIMCAPS structure that will receive the capabilities specified in the dwCapsType parameter. The structure is defined as follows:

 typedef struct simcaps_tag{    DWORD cbSize;    DWORD dwParams;    DWORD dwPBStorages;    DWORD dwMinPBIndex;    DWORD dwMaxPBIndex;    DWORD dwMaxPBEAddressLength;    DWORD dwMaxPBETextLength;    DWORD dwLockFacilities;    DWORD dwReadMsgStorages;    DWORD dwWriteMsgStorages;    DWORD dwNumLockingPwdLengths;    SIMLOCKINGPWDLENGTH rgLockingPwdLengths[SIM_NUMLOCKFACILITIES]; } SIMCAPS, FAR *LPSIMCAPS; 

The cbSize field must be set to the size of the SIMCAPS structure before calling the SimGetDevCaps() function. The dwParams field indicates what other fields in the structure contain data, and can be set to one or more of the values described in Table 8.2.

Table 8.2. SIM Device Capabilities Parameters

Value

Valid Fields

SIM_PARAM_CAPS_PBSTORAGES

dwPBStorages is valid.

SIM_PARAM_CAPS_PBEMAXADDRESSLENGTH

dwMaxPBEAddressLength is valid.

SIM_PARAM_CAPS_PBEMAXTEXTLENGTH

dwMaxPBETextLength is valid.

SIM_PARAM_CAPS_PBEMININDEX

dwMinPBIndex is valid.

SIM_PARAM_CAPS_PBEMAXINDEX

dwMaxPBIndex is valid.

SIM_PARAM_CAPS_LOCKFACILITIES

dwLockFacilities is valid.

SIM_PARAM_CAPS_LOCKINGPWDLENGTH

dwNumLockingPwdLengths and rgLockingPwdLengths are valid.

SIM_PARAM_CAPS_READMSGSTORAGES

dwReadMsgStorages is valid.

SIM_PARAM_CAPS_WRITEMSGSTORAGES

dwWriteMsgStorages is valid.

 

SIM_PARAM_CAPS_ALL

All fields are valid.

The dwPBStorages, dwMinPBIndex, and dwMaxPBIndex fields contain the total number (as well as the minimum and maximum number) of entries that are available for the SIM card's phonebook. The maximum length of an address is stored in the dwMaxPBEAddressLength field, and dwMaxPBETextLength will contain the maximum length for any text string in an entry.

The dwReadMsgStorages and dwWriteMsgStorages fields pertain to the total number of read and write storage areas that are available on the SIM, respectively.

The last set of available fields deals with the locking capabilities of the SIM card. The dwLockFacilities field contains the total number of supported locking facilities that are available on the SIM. Each of these is described in the array of SIMLOCKINGPWDLENGTH structures specified by the rgLockingPwdLengths field. The SIMLOCKINGPWDLENGTH structure contains information about the locking facility index and its maximum password length, and has the following prototype:

 typedef struct simlockingpwdlength{    DWORD dwFacility;    DWORD dwPasswordLength; } SIMLOCKINGPWDLENGTH, FAR *LPSIMLOCKINGPWDLENGTH; 

The following example queries the available capabilities of a SIM card:

 // Get the SIM capabilities SIMCAPS simInfo; memset(&simInfo, 0, sizeof(SIMCAPS)); simInfo.cbSize = sizeof(SIMCAPS); hr = SimGetDevCaps(hSim, SIM_CAPSTYPE_ALL, &simInfo); if(FAILED(hr)) {    SimDeinitialize(hSim);    MessageBox(NULL, TEXT("Could not query the SIM module"),       TEXT("Error"), MB_OK|MB_ICONERROR);    return FALSE; } 

To get the status of an SMS storage location, you can call the following function:

 HRESULT SimGetSmsStorageStatus(HSIM hSim, DWORD dwStorage,    LPDWORD lpdwUsed, LPDWORD lpdwTotal); 

The first parameter is the previously opened handle to the SIM card, and is followed by dwStorage, which should indicate which storage location on the SIM to query. This can be set to either the SIM_SMSSTORAGE_BROADCAST location for the broadcast message location or SIM_SMSSTORAGE_SIM, for the general storage location.

The lpdwUsed parameter should point to a DWORD value that will receive the number of locations that are used, and lpdwTotal is the total number of locations available.

The following example shows how you can use SimGetSmsStorageStatus() to query the storage locations on the SIM:

 // Get the SIM general storage usage DWORD dwUsed = 0, dwTotal = 0; TCHAR tchStorage[1024] = TEXT("\0"); hr = SimGetSmsStorageStatus(hSim, SIM_SMSSTORAGE_SIM,   &dwUsed, &dwTotal); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not get general storage       information"), TEXT("Error"), MB_OK|MB_ICONERROR); else {    wsprintf(tchStorage, TEXT("General SIM Storage:\r\n%d       Used\r\n%d Free\r\n%d Total"), dwUsed, dwTotal-dwUsed,       dwTotal);    MessageBox(NULL, tchStorage, TEXT("SIM Usage"),       MB_OK|MB_ICONINFORMATION); } // Get the SIM broadcast storage usage dwUsed = dwTotal = 0; hr = SimGetSmsStorageStatus(hSim, SIM_SMSSTORAGE_BROADCAST,    &dwUsed, &dwTotal); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not get broadcast storage       information"), TEXT("Error"), MB_OK|MB_ICONERROR); else {    wsprintf(tchStorage, TEXT("General SIM Storage:\r\n%d       Used\r\n%d Free\r\n%d Total"), dwUsed, dwTotal-dwUsed,       dwTotal);    MessageBox(NULL, tchStorage, TEXT("SIM Broadcast Usage"),       MB_OK|MB_ICONINFORMATION); } 

The SIM Phonebook

Before you start reading and writing entries to the SIM phonebooks, let's first examine how to obtain the number of entries in a particular phonebook location (such as the Emergency dial list). To do so, you can call the following function:

 HRESULT SimGetPhonebookStatus(HSIM hSim, DWORD dwLocation,    LPDWORD lpdwUsed, LPDWORD lpdwTotal); 

The first parameter is the previously opened handle to the SIM card, and is followed by dwLocation, which indicates what phonebook on the SIM to query. This should be set to one of the following: SIM_PBSTORAGE_EMERGENCY, SIM_PBSTORAGE_FIXEDDIALING, SIM_PBSTORAGE_LASTDIALING, SIM_PBSTORAGE_OWNNUMBERS, or SIM_PBSTORAGE_SIM.

The lpdwUsed parameter should point to a DWORD value that will receive the number of entries used in the specified phonebook. The last parameter, lpdwTotal, is the total number of entry "slots" that are available for the phonebook.

The following example shows how you can use SimGetPhonebookStatus() to retrieve the number of entries in the Emergency phonebook:

 // Get phonebook status DWORD dwUsed = 0, dwTotal = 0; TCHAR tchPhonebook[1024] = TEXT("\0"); hr = SimGetPhonebookStatus(hSim, SIM_PBSTORAGE_EMERGENCY,    &dwUsed, &dwTotal); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not get Emergency Phonebook       information"), TEXT("Error"), MB_OK|MB_ICONERROR); else {    wsprintf(tchPhonebook, TEXT("Phonebook Usage:\r\n%d       Used\r\n%d Free\r\n%d Total"), dwUsed, dwTotal-dwUsed,       dwTotal);    MessageBox(NULL, tchPhonebook, TEXT("SIM Emergency Phonebook"),       MB_OK|MB_ICONINFORMATION); } 

To read and write entries from the SIM phonebook, you use the following two functions:

 HRESULT SimReadPhonebookEntry(HSIM hSim, DWORD dwLocation,    DWORD dwIndex, LPSIMPHONEBOOKENTRY lpPhonebookEntry); 

and

 HRESULT SimWritePhonebookEntry(HSIM hSim, DWORD dwLocation,    DWORD dwIndex, LPSIMPHONEBOOKENTRY lpPhonebookEntry); 

Both functions take the same four parameters: the hSim parameter should be the handle to the device's SIM card, dwLocation should be set to one of the phonebook locations (such as SIM_PBSTORAGE_EMERGENCY), and the dwIndex parameter should be the index of the entry to write or read.

The lpPhonebookEntry parameter points to a SIMPHONEBOOKENTRY structure that contains information about the phonebook entry. If you are using the SimWritePhonebookEntry() function, the entry will be saved to the location specified by the dwLocation parameter. When reading an entry, the structure will be filled with the data from the SIM.

The structure used for a phonebook entry is defined as follows:

 typedef struct simphonebookentry_tag{    DWORD cbSize;    DWORD dwParams;    TCHAR lpszAddress[MAX_LENGTH_ADDRESS];    DWORD dwAddressType;    DWORD dwNumPlan;    TCHAR lpszText[MAX_LENGTH_PHONEBOOKENTRYTEXT]; } SIMPHONEBOOKENTRY, *LPSIMPHONEBOOKENTRY; 

The first field, cbSize, should be set to the size of the SIMPHONEBOOKENTRY structure before calling either the SimReadPhonebookEntry() or SimWritePhonebookEntry() functions. The dwParams field will indicate which of the fields in the structure contain valid data, and can be one or more of the values in Table 8.3.

Table 8.3. SIM Phonebook Entry Flags

Value

Valid Fields

SIM_PARAM_PBE_ADDRESS

The lpszAddress field is valid.

SIM_PARAM_PBE_ADDRESS_TYPE

The dwAddressType field is valid.

SIM_PARAM_PBE_NUMPLAN

The dwNumPlan field is valid.

SIM_PARAM_PBE_TEXT

The lpszText field is valid.

SIM_PARAM_PBE_ALL

All fields are valid.

The entry's phone number is stored as a null-terminated string in the lpszAddress field. Details about what type of number the entry is will be indicated by using one of the flags in Table 8.4 in the dwAddressType field.

Table 8.4. SIM Phonebook Address Types

Value

Description

SIM_ADDRTYPE_UNKNOWN

Unknown address type.

SIM_ADDRTYPE_INTERNATIONAL

International number. Note that numbers stored as international should be prefixed with a plus (+) sign before being displayed to the user.

SIM_ADDRTYPE_NATIONAL

National number.

SIM_ADDRTYPE_NETWKSPECIFIC

Network-specific number.

SIM_ADDRTYPE_SUBSCRIBER

Protocol-specific subscriber number.

SIM_ADDRTYPE_ALPHANUM

Alphanumeric number.

SIM_ADDRTYPE_ABBREV

Abbreviated number.

If the entry is a SIM_ADDRTYPE_UNKNOWN, SIM_ADDRTYPE_INTERNATIONAL, or SIM_ADDRTYPE_NATIONAL address type, the dwNumPlan field will provide additional information about the numbering plan (i.e., the format) used for the address. It can be one of the following:

  • SIM_NUMPLAN_UNKNOWN specifies that the numbering plan is unknown.

  • SIM_NUMPLAN_TELEPHONE specifies that a standard telephone or ISDN numbering plan (E.164/E.163) is used.

  • SIM_NUMPLAN_DATA specifies an X.121 data numbering plan.

  • SIM_NUMPLAN_TELEX specifies a Telex numbering plan.

  • SIM_NUMPLAN_NATIONAL specifies a national numbering plan.

  • SIM_NUMPLAN_PRIVATE specifies a private numbering plan.

  • SIM_NUMPLAN_ERMES specifies that an ERMES (ETSI DE/PS 3 01-3) numbering plan is used.

Finally, the lpszText field contains a null-terminated string that contains any text associated with this entry.

The following code reads the first phonebook entry from the general SIM phonebook:

 SIMPHONEBOOKENTRY simPhoneEntry; memset(&simPhoneEntry, 0, sizeof(SIMPHONEBOOKENTRY)); simPhoneEntry.cbSize = sizeof(SIMPHONEBOOKENTRY); hr = SimReadPhonebookEntry(hSim, SIM_PBSTORAGE_SIM, 1,   &simPhoneEntry); if(FAILED(hr)) {    MessageBox(NULL, TEXT("Could not read phonebook entry"),       TEXT("Error"), MB_OK|MB_ICONERROR);    return FALSE; } // Process entry here 

If you need to write an entry to the phonebook, you can use the following:

 // Write a phonebook entry to the SIM SIMPHONEBOOKENTRY simPhoneEntry; memset(&simPhoneEntry, 0, sizeof(SIMPHONEBOOKENTRY)); simPhoneEntry.cbSize = sizeof(SIMPHONEBOOKENTRY); simPhoneEntry.dwParams = SIM_PARAM_PBE_ALL; simPhoneEntry.dwAddressType = SIM_ADDRTYPE_NATIONAL; simPhoneEntry.dwNumPlan = SIM_NUMPLAN_TELEPHONE; wsprintf(simPhoneEntry.lpszAddress, TEXT("5555551212")); wsprintf(simPhoneEntry.lpszText, TEXT("Jeremy")); hr = SimWritePhonebookEntry(hSim, SIM_PBSTORAGE_SIM, 3,   &simPhoneEntry); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not write new phonebook       entry"), TEXT("Error"), MB_OK|MB_ICONERROR); else    MessageBox(NULL, TEXT("New entry added successfully"),       TEXT("SIM Write"), MB_OK); 

Finally, to delete a phonebook entry from the SIM card, you can use the SimDeletePhonebookEntry() function, which is defined as follows:

 HRESULT SimDeletePhonebookEntry(HSIM hSim, DWORD dwLocation,    DWORD dwIndex); 

The only parameters that the function needs are the handle to the SIM card, the phonebook location, and the index to the entry to delete.

The following short code sample shows how you can delete a SIM phonebook entry:

 hr = SimDeletePhonebookEntry(hSim, SIM_PBSTORAGE_SIM, 3); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not delete entry"),       TEXT("Error"), MB_OK|MB_ICONERROR); else    MessageBox(NULL, TEXT("Entry deleted."), TEXT("SIM       Delete"), MB_OK); 

Working with SIM-Based Messages

To read or write a Short Message Service text message in a specific storage location on the SIM, you can call the following two functions:

 HRESULT SimReadMessage(HSIM hSim, DWORD dwStorage, DWORD    dwIndex, LPSIMMESSAGE lpSimMessage); 

and

 HRESULT SimWriteMessage(HSIM hSim, DWORD dwStorage, LPDWORD    lpdwIndex, LPSIMMESSAGE lpSimMessage); 

Both of these functions need an open handle to the SIM card, as well as a storage location (either SIM_SMSSTORAGE_BROADCAST or SIM_SMSSTORAGE_SIM) as the first two parameters. When you are reading a message from the SIM, the third parameter, dwIndex, should be set to the index of the message you want to read. If you are writing a message, lpdwIndex will point to a DWORD value that receives the index of the message that was written when you called SimWriteMessage().

The last parameter is a pointer to a SIMMESSAGE structure. When reading a message, this structure's fields will be filled in with the contents of the message you specify with the dwIndex parameter. If you are writing a message, you should fill in the structure with the details of the message you want to save.

The SIMMESSAGE structure is defined as follows:

 typedef struct simmessage_tag{    DWORD cbSize;    DWORD dwParams;    TCHAR lpszAddress[MAX_LENGTH_ADDRESS];    DWORD dwAddressType;    DWORD dwNumPlan;    SYSTEMTIME stReceiveTime;    DWORD cbHdrLength;    BYTE rgbHeader[MAX_LENGTH_HEADER];    TCHAR lpszMessage[MAX_LENGTH_MESSAGE]; } SIMMESSAGE, FAR *LPSIMMESSAGE; 

The first field, cbSize, should be set to the size of the SIMMESSAGE structure before calling either the SimReadMessage() or SimWriteMessage() functions. The dwParams field will indicate which of the fields in the structure contain valid data, and can be set to one or more of the values in Table 8.5.

Table 8.5. SIM Message Parameters

Value

Valid Fields

SIM_PARAM_MSG_ADDRESS

The lpszAddress field is valid.

SIM_PARAM_MSG_ADDRESS_TYPE

The lpszAddressType field is valid.

SIM_PARAM_MSG_NUMPLAN

The dwNumPlan field is valid.

SIM_PARAM_MSG_RECEIVE_TIME

The stReceiveTime field is valid.

SIM_PARAM_MSG_HEADER

The rgbHeader field is valid.

SIM_PARAM_MSG_HEADER_LENGTH

The cbHdrLength field is valid.

SIM_PARAM_MSG_MESSAGE

The lpszMessage field is valid.

SIM_PARAM_PBE_ALL

All fields are valid.

The incoming message address and numbering plan information fields are similar to those described for SIM phonebook entries.

The stReceiveTime field will contain a SYSTEMTIME structure that contains the timestamp for the incoming message. The message header is stored in rgbHeader, and its length is specified by the cbHdrLength field.

The actual message body is stored in lpszMessage.

To delete a message from the SIM, you can use the SimDeleteMessage() function. This function needs a handle to the open a SIM card, a storage location (either SIM_SMSSTORAGE_BROADCAST or SIM_SMSSTORAGE_SIM), and the index of the message to delete. The function is defined as follows:

 HRESULT SimDeleteMessage(HSIM hSim, DWORD dwStorage, DWORD   dwIndex); 

The SIM File System

Recall that the Subscriber Identity Module (SIM) card not only contains your phonebook and text messages, but is actually a smart card containing a processor and a file system. The file system that a SIM card uses is based on the ISO-7816 standard for smart card devices, and is fully specified by the GSM 11.11 standard (more information about both standards can be downloaded from http://www.etsi.org).

Although the file system on the SIM card is analogous to that of a file system on the desktop or Pocket PC device (you can read, write, or delete files), there are a few subtle differences:

  • The root level of the file system is known as the Master file.

  • Directories are known as Dedicated files and are of a fixed size.

  • Individual records (or files) are known as Elementary files.

  • All files are identified as an address (a DWORD value), rather than a filename.

  • Before you can read from or write to a particular file in the SIM file system, you must first get information about the record.

Figure 8.4 shows the basic tree structure of the SIM file system.

Figure 8.4. SIM card file system structure

graphics/08fig04.gif

The most noticeable difference between a regular file system (typically found on a PC) and the SIM file system (besides basic terminology) is that each file in the latter has a four-byte file identifier that uniquely identifies it, rather than a filename.

File identifiers are constructed in the following manner on a GSM SIM card. The first two bytes are used to identify the type of file:

  • 3F Master file (file system root)

  • 7F Dedicated file (a directory)

  • 2F Elementary file underneath the Master file

  • 6F Elementary file underneath the Dedicated file

The second two bytes are a unique identifier for the file, and are subject to the following rules:

  • The file ID is created at the time of file creation.

  • No two files can have the same identifier under the same parent.

  • A child and a parent shall never have the same identifier.

Table 8.6 describes the different record types that the SIM card file system can store.

Table 8.6. SIM File Types

File Type

Description

Transparent

A random access file that can contain any type of data.

Linear Fixed File

A fixed-length record that can be navigated through by using next, first, last, and so on. The SIM phonebook is an example of records that are Linear Fixed.

Cyclic

A fixed-length set of records that will loop to the first entry after the last entry is read; they are stored in chronological order. The "last number dialed" list is an example of records that are Cyclic.

Variable-length records

Not supported.

Incremental

A single-byte record that can be incremented or decremented by one.

Every SIM card that is provisioned with a Pocket PC Phone Edition device already contains several required files that are needed in order to maintain compatibility with the GSM protocol. Although most of these records are marked as read-only by your wireless carrier, they contain a lot of useful information that can be used in your own applications.

Table 8.7 describes the files located in the GSM SIM file system (more detailed information about each file can also be found in the GSM 11.11 specification).

Table 8.7. The GSM File System

Name

Address (ID)

Level

Type

Description

ICC-ID

0x2FE2

Master

Transparent

ICC card serial number

GSM

0x7F20

N/A

N/A

Directory for GSM files

LP

0x6F05

Application

Transparent

Language preference

IMSI

0x6F07

Application

Transparent

International Mobile Subscriber Identity (IMSI)

KC

0x6F20

Application

Transparent

Ciphering key

PLMN

0x6F30

Application

Transparent

PLMN Selector

HPLMN

0x6F31

Application

Transparent

HPLMN search interval time

ACMMAX

0x6F37

Application

Transparent

Accumulated call meter maximum

SST

0x6F38

Application

Transparent

SIM service table

ACM

0x6F39

Application

Cyclic

Accumulated call meter

GID1

0x6F3E

Application

Transparent

Group Identifier Level 1

GID2

0x6F3F

Application

Transparent

Group Identifier Level 2

SPN

0x6F46

Application

Transparent

Service provider name

PUCT

0x6F41

Application

Transparent

Price per unit and currency table

CBMI

0x6F45

Application

Transparent

Cell Broadcast Message Identifier selection

CBMID

0x6F48

Application

Transparent

Cell Broadcast Message Identifier for Data Download

CBMIR

0x6F50

Application

Transparent

Cell Broadcast Message Identifier

BCCH

0x6F74

Application

Transparent

Broadcast control channels

ACC

0x6F78

Application

Transparent

Access control class

FPLMN

0x6F7B

Application

Transparent

Forbidden PLMNs

LOCI

0x6F7E

Application

Transparent

Location information

AD

0x6FAD

Application

Transparent

Administrative data

PHASE

0x6FAE

Application

Transparent

Phase identification

VGCS

0x6FB1

Application

Transparent

Voice Group Call Service

VGCSS

0x6FB2

Application

Transparent

Voice Group Call Service status

VBS

0x6FB3

Application

Transparent

Voice Broadcast Service

VBSS

0x6FB4

Application

Transparent

Voice Broadcast Service Status

eMLPP

0x6FB5

Application

Transparent

Enhanced Multi-Level Preemption and Priority

AAeM

0x6FB6

Application

Transparent

Automatic Answer for eMLPP Service

ECC

0x6FB7

Application

Transparent

Emergency Call Codes

Telcom

0x7F10

N/A

N/A

Directory for Telcom files

ADN

0x6F3A

Telcom

Linear Fixed

Abbreviated dialing numbers

FDN

0x6F3B

Telcom

Linear Fixed

Fixed dialing numbers

SMS

0x6F3C

Telcom

Linear Fixed

Short messages

CCP

0x6F3D

Telcom

Linear Fixed

Capability configuration parameters

MSISDN

0x6F40

Telcom

Linear Fixed

MSISDN

SMSP

0x6F42

Telcom

Linear Fixed

Short message service parameters

SMSS

0x6F43

Telcom

Transparent

Short message service status

LND

0x6F44

Telcom

Cyclic

Last number dialed

SDN

0x6F49

Telcom

Linear Fixed

Service Dialing Numbers

EXT1

0x6F4A

Telcom

Linear Fixed

Extension 1

EXT2

0x6F4B

Telcom

Linear Fixed

Extension 2

EXT3

0x6F4C

Telcom

Linear Fixed

Extension 3

Reading and Writing Records

Now that you have a general idea about how the SIM file system is laid out, you can examine what is required to read and write records.

Before you can read the contents of an actual record, you must first get information from the SIM about the record such as the type of file it is, the buffer length you need to allocate, and so on. To do so, you can use the SimGetRecordInfo() function, which is defined as follows:

 HRESULT SimGetRecordInfo(HSIM hSim, DWORD dwAddress,    LPSIMRECORDINFO lpSimRecordInfo); 

The first parameter for this function is the handle to the open SIM card that you previously received from your call to SimInitialize(). The dwAddress parameter is the file identifier of the record you want to open (in Table 8.7, for example, the SIM card serial number would have the file address of 0x2FE2).

The last parameter should point to a SIMRECORDINFO structure. After the function returns, the structure will contain information about the record that will enable you to read the record's contents.

The SIMRECORDINFO structure looks like the following:

 typedef struct simrecordinfo_tag{    DWORD cbSize;    DWORD dwParams;    DWORD dwRecordType;    DWORD dwItemCount;    DWORD dwSize; } SIMRECORDINFO, FAR *LPSIMRECORDINFO; 

The first field, cbSize, should be set to the size of a SIMRECORDINFO structure before calling the SimGetRecordInfo() function. The dwParams field will indicate which of the remaining fields of the structure contain valid data, as described in Table 8.8.

Table 8.8. SIM Record Parameters

Value

Valid Fields

SIM_PARAM_RECORDINFO_RECORDTYPE

The dwRecordType field is valid.

SIM_PARAM_RECORDINFO_ITEMCOUNT

The dwItemCount field is valid.

SIM_PARAM_RECORDINFO_SIZE

The dwSize field is valid.

SIM_PARAM_RECORDINFO_ALL

All fields are valid.

The dwRecordType field indicates the type of record for which you are requesting information, and can be one of the following values:

  • SIM_RECORDTYPE_UNKNOWN, if the record is an unknown file type

  • SIM_RECORDTYPE_TRANSPARENT, if the record is a single-variable-length record set

  • SIM_RECORDTYPE_CYCLIC, if the record is a Cyclic set of records, each of the same length

  • SIM_RECORDTYPE_LINEAR, if the record is a Linear set of records, each of the same length

  • SIM_RECORDTYPE_MASTER, if the record is the Master record (root) of the file system

  • SIM_RECORDTYPE_DEDICATED, if the record is a parent of other records (a directory)

The dwItemCount field specifies the number of items in the record, and is typically used with records that are either SIM_RECORDTYPE_CYCLIC or SIM_RECORDTYPE_LINEAR. The last field, dwSize, is the size, in bytes, of each item.

The following example reads the record information for the IMSI (or subscriber identity 0x6F07) from the SIM:

 // Read from the SIM file system SIMRECORDINFO srecordInfo; DWORD dwIMSIAddress = 0x6f07; memset(&srecordInfo, 0, sizeof(SIMRECORDINFO)); srecordInfo.cbSize = sizeof(SIMRECORDINFO); hr = SimGetRecordInfo(hSim, dwIMSIAddress, &srecordInfo); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not read from SIM file       system"), TEXT("Error"), MB_OK|MB_ICONERROR); // Continue to read record... 

Now that you have the record information for the file you are interested in, you can read the actual contents of the record. You can read the contents of a SIM file by calling the SimReadRecord() function, which is defined as follows:

 HRESULT SimReadRecord(HSIM hSim, DWORD dwAddress, DWORD    dwRecordType, DWORD dwIndex, LPBYTE lpData, DWORD dwBufferSize,    LPDWORD lpdwBytesRead); 

The first parameter is the handle to the open SIM, and is followed by dwAddress, which should specify the unique file identifier for the record you are interested in reading. The next parameter, dwRecordType, specifies the type of record that you are reading, which was returned from your previous call to SimGetRecordInfo(). The dwIndex parameter is used when you have either a SIM_RECORDTYPE_CYCLIC or SIM_RECORDTYPE_LINEAR type of record, and should specify which index within the record to read.

The actual contents of the record are returned to the buffer specified by the lpData parameter. The size of the buffer should be set in the dwBufferSize parameter, and the actual number of bytes that are returned to you will be placed in the pointer specified by the lpdwBytesRead parameter.

Reading a record is fairly straightforward, as shown by the following sample code that reads in the IMSI information from the SIM:

 // Continue to read record... LPBYTE lpIMSIBuffer = NULL; DWORD dwBytesRead = 0; // Allocate a buffer to read in the IMSI lpIMSIBuffer = (LPBYTE)LocalAlloc(LPTR, srecordInfo.dwSize); if(!lpIMSIBuffer) {    OutputDebugString(TEXT("Could not allocate buffer for       IMSI."));    return FALSE; } hr = SimReadRecord(hSim, dwIMSIAddress, srecordInfo.dwRecordType, 0,    lpIMSIBuffer, srecordInfo.dwSize, &dwBytesRead); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not read IMSI number"),       TEXT("Error"), MB_OK|MB_ICONERROR); // Do something here with the IMSI number... // Free up used buffer LocalFree(lpIMSIBuffer); 

You can store information on the SIM card by calling the following function:

 HRESULT SimWriteRecord(HSIM hSim, DWORD dwAddress, DWORD    dwRecordType, DWORD dwIndex, LPBYTE lpData, DWORD dwByteCount); 

The parameters for writing a SIM file are similar to those for the SimReadRecord() function. The first parameter is the handle to the SIM card, dwAddress is the file identifier for the record you want to write, and dwRecordType is the type of SIM file record. The dwIndex parameter is used with records that are either SIM_RECORDTYPE_CYCLIC or SIM_RECORDTYPE_LINEAR and specifies which index within the record to write.

The data to be written to the SIM card is specified by the lpData parameter, and the dwByteCount parameter should contain the number of bytes to write to the SIM.

SIM Locking

SIM cards have built-in security features that enable you to lock the card so that unauthorized calls cannot be made using your phone account. If the SIM itself is locked, the PIN number you specify will need to be entered before you can place a call, regardless of the device or phone in which the SIM is placed.

WARNING:

You should use the SIM locking facilities with caution. If you forget your password or PIN, the SIM card will be in a locked state and you will need to contact your carrier to unlock the SIM card.


You can check the current status of the SIM by calling the following function:

 HRESULT SimGetLockingStatus(HSIM hSim, DWORD dwLockingFacility,    LPTSTR lpszPassword, BOOL *pfEnabled); 

The first parameter is the open handle to the SIM card. The second parameter specifies a locking mechanism for the SIM, and can be one of the values described in Table 8.9.

Table 8.9. SIM Locking Facilities

Value

Description

SIM_LOCKFACILITY_CNTRL

Lock control surface (keyboard lock)

SIM_LOCKFACILITY_PH_SIM

Lock phone to SIM card (device will request password when anything other than current SIM is inserted)

SIM_LOCKFACILITY_PH_FSIM

Lock phone to first SIM card (device will be locked to the first SIM card that is inserted)

SIM_LOCKFACILITY_SIM

Lock SIM card (device will request password when SIM is powered up)

SIM_LOCKFACILITY_SIM_PIN2

Lock SIM card

SIM_LOCKFACILITY_SIM_FIXEDDIALING

SIM fixed dialing memory (device will dial numbers on the SIM only)

SIM_LOCKFACILITY_NETWORKPERS

Network personalization

SIM_LOCKFACILITY_NETWORKSUBPERS

Network subset personalization

SIM_LOCKFACILITY_SERVICEPROVPERS

Service provider personalization

SIM_LOCKFACILITY_CORPPERS

Corporate provider personalization

The lpszPassword parameter should point to a null-terminated string that contains the facility's password. The last parameter, pfEnabled, should point to a Boolean value that will be filled in when the function returns with a TRUE value if the particular password facility is enabled.

The following example determines whether the SIM card is locked:

 // Get the locking status... BOOL fLock = FALSE; hr = SimGetLockingStatus(hSim, SIM_LOCKFACILITY_SIM,   TEXT(""), &fLock); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not get the Locking status       from the SIM!"), TEXT("Error"), MB_OK|MB_ICONERROR); if(fLock)    MessageBox(NULL, TEXT("SIM is currently locked"),       TEXT("SIM Password"), MB_OK|MB_ICONINFORMATION); else    MessageBox(NULL, TEXT("SIM is currently unlocked"),       TEXT("SIM Password"), MB_OK|MB_ICONINFORMATION); 

To set the locking status (again, use with caution!), you can use the SimSetLockingStatus() function:

 HRESULT SimSetLockingStatus(HSIM hSim, DWORD    dwLockingFacility, LPTSTR lpszPassword, BOOL fEnabled); 

The first parameter is the handle to the SIM card, and is followed by the locking facility you want to enable. The lpszPassword parameter is a null-terminated string containing the password you want to set. The last parameter, fEnabled, should be set to TRUE to enable locking. To unlock a particular facility, you would also call SimSetLockingStatus() with the fEnabled parameter set to FALSE.

To change the password for a specific locking facility, you can call the following function:

 HRESULT SimChangeLockingPassword(HSIM hSim, DWORD dwLockingFacility,    LPTSTR lpszOldPassword, LPTSTR lpszNewPassword); 

As with all of the other SIM functions, the first parameter is an open handle to the SIM card. The second parameter, dwLockingFacility, is the locking mechanism for which you want to change the password. The last two parameters are null-terminated strings that should specify both the old and new passwords, respectively.

To see if the SIM is currently waiting for a password to be entered, you can simply call the SimGetPhoneLockedState() function. The function requires an open handle to the SIM card, and will return a SIM_LOCKEDSTATE value in the lpdwLockedState pointer when it returns. The function is defined as follows:

 HRESULT SimGetPhoneLockedState(HSIM hSim, LPDWORD lpdwLockedState); 

The possible locked states for a SIM card are listed in Table 8.10.

Table 8.10. SIM Locked States

Value

Locked State

SIM_LOCKEDSTATE_UNKNOWN

Unknown

SIM_LOCKEDSTATE_READY

Unlocked (Ready)

SIM_LOCKEDSTATE_SIM_PIN

Waiting for SIM PIN

SIM_LOCKEDSTATE_SIM_PUK

Waiting for SIM PUK (Pin Unblocking Key)

SIM_LOCKEDSTATE_PH_SIM_PIN

Waiting for SIM Personalization PIN

SIM_LOCKEDSTATE_PH_FSIM_PIN

Waiting for first SIM Personalization PIN

SIM_LOCKEDSTATE_PH_FSIM_PUK

Waiting for first SIM Personalization PUK

SIM_LOCKEDSTATE_SIM_PIN2

Waiting for SIM PIN2

SIM_LOCKEDSTATE_SIM_PUK2

Waiting for SIM PUK2

SIM_LOCKEDSTATE_PH_NET_PIN

Waiting for Network Personalization PIN

SIM_LOCKEDSTATE_PH_NET_PUK

Waiting for Network Personalization PUK

SIM_LOCKEDSTATE_PH_NETSUB_PIN

Waiting for Network Subset Personalization PIN

SIM_LOCKEDSTATE_PH_NETSUB_PUK

Waiting for Network Subset Personalization PUK

SIM_LOCKEDSTATE_PH_SP_PIN

Waiting for Service Provider Personalization PIN

SIM_LOCKEDSTATE_PH_SP_PUK

Waiting for Service Provider Personalization PUK

SIM_LOCKEDSTATE_PH_CORP_PIN

Waiting for Corporate Personalization PIN

SIM_LOCKEDSTATE_PH_CORP_PUK

Waiting for Corporate Personalization PUK

You can use the following code fragment to find out the current locked state for a SIM:

 // Get the current locked state DWORD dwLockedState = 0; TCHAR tchLocked[256] = TEXT("\0"); hr = SimGetPhoneLockedState(hSim, &dwLockedState); if(FAILED(hr))    MessageBox(NULL, TEXT("Could not get the current SIM locked state!"), TEXT("Error"), MB_OK|MB_ICONERROR); switch(dwLockedState) {    case SIM_LOCKEDSTATE_READY:       wsprintf(tchLocked, TEXT("SIM Ready (Unlocked)"));       break;    case SIM_LOCKEDSTATE_SIM_PIN:       wsprintf(tchLocked, TEXT("Waiting for the SIM PIN"));       break;    case SIM_LOCKEDSTATE_SIM_PUK:       wsprintf(tchLocked, TEXT("Waiting for the SIM Unblock          key"));       break;    case SIM_LOCKEDSTATE_PH_SIM_PIN:       wsprintf(tchLocked, TEXT("Waiting for the SIM          Personalization PIN"));       break;    case SIM_LOCKEDSTATE_PH_FSIM_PIN:       wsprintf(tchLocked, TEXT("Waiting for the first SIM          Personalization PIN"));       break;    case SIM_LOCKEDSTATE_PH_FSIM_PUK:       wsprintf(tchLocked, TEXT("Waiting for the first SIM          Unblock Key"));       break;    case SIM_LOCKEDSTATE_SIM_PIN2:       wsprintf(tchLocked, TEXT("Waiting for the SIM PIN2"));       break;    case SIM_LOCKEDSTATE_SIM_PUK2:       wsprintf(tchLocked, TEXT("Waiting for the SIM Unblock          Key 2"));       break;    case SIM_LOCKEDSTATE_PH_NET_PIN:       wsprintf(tchLocked, TEXT("Waiting for Network          Personalization Pin"));       break;    case SIM_LOCKEDSTATE_PH_NET_PUK:       wsprintf(tchLocked, TEXT("Waiting for Network          Personalization Unblock Key"));       break;    case SIM_LOCKEDSTATE_PH_NETSUB_PIN:       wsprintf(tchLocked, TEXT("Waiting for Network Subset          Personalization Pin"));       break;    case SIM_LOCKEDSTATE_PH_NETSUB_PUK:       wsprintf(tchLocked, TEXT("Waiting for Network Subset          Personalization Unblock Key"));       break;    case SIM_LOCKEDSTATE_PH_SP_PIN:       wsprintf(tchLocked, TEXT("Waiting for Service Provider          Personalization PIN"));       break;    case SIM_LOCKEDSTATE_PH_SP_PUK:       wsprintf(tchLocked, TEXT("Waiting for Service Provider          Personalization Unblock Key"));       break;    case SIM_LOCKEDSTATE_PH_CORP_PIN:       wsprintf(tchLocked, TEXT("Waiting for Corporate          Pin"));       break;    case SIM_LOCKEDSTATE_PH_CORP_PUK:       wsprintf(tchLocked, TEXT("Waiting for Corporate          Unblock Key"));       break; default:    wsprintf(tchLocked, TEXT("Unknown")); } MessageBox(NULL, tchLocked, TEXT("SIM Locked State"),    MB_OK|MB_ICONINFORMATION); 

Finally, to have your application send a password to unlock a phone, you can simply use the following function:

 HRESULT SimUnlockPhone(HSIM hSim, LPTSTR lpszPassword,   LPTSTR lpszNewPin); 

The first parameter should point to a valid handle for the SIM. The lpszPassword parameter should be a null-terminated string that specifies the password to unlock the device. The last parameter, lpszNewPin, is an optional second password string, and can be set to NULL if it is not required.



Pocket PC Network Programming
Pocket PC Network Programming
ISBN: 0321133528
EAN: 2147483647
Year: 2005
Pages: 90

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net