Phone API

The phone API provides a basic set of functions to make calls and query the call log. The phone API is convenient because it avoids the need for most applications to dive directly into the TAPI and make calls with that rather involved interface. TAPI is supported on the Smartphone and Pocket PC Phone edition, but working with it isn't required for all but the most manipulative of applications.

Dialing the Phone

The first communication feature likely to be tried by a programmer new to the Smartphone or Pocket PC Phone edition is to dial the phone. The system provides a simple and effective function for this, PhoneMakeCall, prototyped as:

LONG PhoneMakeCall (PHONEMAKECALLINFO *ppmci);

The PHONEMAKECALLINFO structure is defined as:

typedef struct tagPHONEMAKECALLINFO{
    DWORD cbSize;
    DWORD dwFlags;
    PCWSTR pszDestAddress;
    PCWSTR pszAppName;
    PCWSTR pszCalledParty;
    PCWSTR pszComment;
} PHONEMAKECALLINFO, * PHONEMAKECALLINFO;

The first field is the standard size field that needs to be filled with the size of the structure. The dwFlags field can contain one of two flags: PMCF_PROMPTBEFORECALLING, which tells the system to prompt the user before initiating the call, or PMCF_DEFAULT, which tells the system to make the call without asking the user whether the call should be made. Even with the PMCF_DEFAULT flag, the system will display a notification that the call is being made. The pszDestAddress field should point to a string containing the phone number to call. The string can contain the standard phone number separator characters such as dashes, spaces, and parentheses. The pszCalledParty field should point to a string that identifies the called party. This string is displayed, along with the number, on the call-in-progress notification that is displayed when the call is made. The pszAppName and pszComment fields should be set to 0.

Viewing the Call Log

The system maintains a log of all calls made to and from the phone. The call log is a simple database that keeps information such as the time of the call, its duration, and the number of the other phone, as well as details such as whether the call was incoming, the phone is roaming, and so on. The call log can be accessed with a few simple functions. To open the call log, call the aptly named PhoneOpenCallLog, prototyped as:

HRESULT PhoneOpenCallLog (HANDLE * ph);

The function returns S_OK if successful and ERROR_FAIL otherwise. An extended error code can be retrieved with GetLastError. Some Smartphone systems don't allow the call log to be opened. There might or might not be a system reason for getting this error, but many phones don't allow this function to succeed. There isn't an issue with Pocket PC phone edition systems. Also, opening the call log isn't necessary for calling PhoneMakeCall. If PhoneOpenCallLog is successful, a handle will be placed in the value pointed to by the parameter ph, and the seek pointer of the call log will be set to point to the first entry in the log.

Once opened, entries in the call log can be queried with the function PhoneGetCallLogEntry, prototyped as:

HRESULT PhoneGetCallLogEntry (HANDLE h, PCALLLOGENTRY pentry);

The handle is the one received from the call to PhoneOpenCallLog. The dbSize field of the CALLLOGENTRY structure needs to be initialized with the size of the structure before the function is called.

If the function returns without error, pentry points to a structure that contains data about the call, and the seek pointer of the call log is moved to the next entry. Repeated calls to PhoneGetCallLogEntry will enumerate the entire call log. When no more entries are in the log, the function will fail with the extended error code 259 indicating no more entries are available.

The CALLLOGENTRY structure is defined as:

typedef struct {
    DWORD cbSize;
    FILETIME ftStartTime;
    FILETIME ftEndTime;
    IOM iom;
    BOOL fOutgoing:1;
    BOOL fConnected:1;
    BOOL fEnded:1;
    BOOL fRoam:1;
    CALLERIDTYPE cidt;
    PTSTR pszNumber;
    PTSTR pszName;
    PTSTR pszNameType;
    PTSTR pszNote;
} CALLLOGENTRY, * PCALLLOGENTRY;

The ftStartTime and ftEndTime fields are FILETIME structures that provide the start and end times of the call. The iom field contains an enumeration indicating if the call was incoming, was outgoing, or was missed. The next four fields are Booleans detailing the conditions of the call: fOutgoing is TRUE if the call was made from the device; fConnected is set if the call actually made a connection; fEnded is TRUE if the call was terminated by the callers and FALSE if the call was dropped; and fRoam is set if the call was made from outside the phone's home area. The cidt field is an enumeration indicating if the caller ID for the call was available, blocked, or unavailable.

The pszNumber field points to a string indicating the number of the phone number of the calling phone or the phone being called. The pszName field identifies the name associated with the number. The pszNameType field points to a string that indicates which number — home, work, or mobile — was associated with the contact. The string is in the form of a character, typically either h, w, or m for home, work, or mobile, respectively. The pszNote field is a string that is supposed to point to a string containing the name of a notes file for the call. This field isn't always filled in by the system.

The seek pointer of the call log can be moved with

HRESULT PhoneSeekCallLog (HANDLE h, CALLLOGSEEK seek, DWORD iRecord,
                          LPDWORD piRecord);

The handle value is the handle returned by PhoneOpenCallLog. The seek value can be set to either CALLLOGSEEK_BEGINNING or CALLLOGSEEK_END, depending of whether the passed offset is based from the beginning or end of the log. The parameter iRecord is the zero-based offset from the beginning or end of the log. The piRecord parameter points to a DWORD that receives the index, from the beginning of the log, of the resulting record. Once the seek pointer is moved to a specific record, the record can then be read with PhoneGetCallLogEntry.

The phone log should be closed with a call to PhoneCloseCallLog, prototyped as:

HRESULT PhoneCloseCallLog (HANDLE h);

The single parameter is the handle returned from PhoneOpenCallLog.

This topic is from Programming Microsoft Windows CE, Third Edition, by Douglas Boling, published by Microsoft Press. © 2003 by Douglas McConnaughey Boling. Reprinted here by permission of the author.