Let’s clarify what the device id is: the device id is an umbrella term form the device UUID and for the IMEI/ESN identifiers on phones. Let’s remember that UUID is a type of GUID which exists in every device (including desktop/laptop computers).

For getting the device UUID Microsoft has defined two methods: application specific hash and the real UUID. For getting the IMEI/ESM there is a method which uses TAPI. All of them are explained here:

·         Real UUID: by using the KernelIoControl method with the  IOCTL_HAL_GET_UUID parameter you can get the UUID which is an Universal identifier for the device hardware, a sample of using this method is below:

TCHAR* GetDeviceUUID()


      TCHAR *pszGuuid=NULL;

      TCHAR szFormat[]=TEXT(“%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n”);


      GUID myUUID;

      DWORD dwBytesReturned;                  

      DWORD dwError=0;                  


      if(KernelIoControl(IOCTL_HAL_GET_UUID, NULL, 0, &myUUID,sizeof(myUUID),&dwBytesReturned))


            pszGuuid=new TCHAR[MAX_HW_VALUE];

            LPCTSTR pszFormat=szFormat;







            delete[] pszFormat;








      return pszGuuid;



·         Application specific hash: as you can imagine there is a security threat if applications can read the device UUID because identity can be stolen, so for preventing it Microsoft defined the new API method GetDeviceUniqueID (starting with Windows Mobile 6) for generating a hash based application specific identifier. That’s means that method returns an application specific hash for every requester, those hash are guaranteed to be unique for every single application. Here there is a sample:


#define APPLICATION_DATA “@^!MyAppName!^@”





DWORD cbDeviceId = sizeof(appDeviceId);


hr = GetDeviceUniqueID(reinterpret_cast(APPLICATION_DATA),






//do whatever with appDeviceId

As shown above, the unique id is hashed with the input you provide in the APPLICATION_DATA parameter. Every time you change that parameter, the generated id will be different.


·         IMEI/ESN: on Windows phones there is an additional unique identifier given by the mobile operator. On GSM devices the serial number returned is the equipment identity International Mobile Equipment Identity (IMEI) code and on CDMA devices, the serial number returned is the Electronic Serial Number (ESN). The method for getting this data is named lineGetGeneralInfo. There is an example of using it next:

TCHAR* GetImeiEsn()


      DWORD       dwLineID;

      HLINEAPP    hLineApp = NULL;

      HINSTANCE   hInst=NULL;

      DWORD       dwReturn;

      DWORD       dwNumDevs = 0;

      LINEINFO    *g_lpLineInfo = NULL; // Array that contains all the lines’


      dwReturn = lineInitialize (&hLineApp, hInst,

                                           (LINECALLBACK) lineCallbackFunc,

                                            NULL, &dwNumDevs);


      if (! (g_lpLineInfo = (LPLINEINFO) LocalAlloc(

            LPTR, sizeof (LINEINFO) * dwNumDevs)))

            return NULL;


      if(dwReturn || (dwNumDevs==0)) return NULL;


      DWORD           rc;    

      TCHAR*          pszValue=new TCHAR[MIN_HW_VALUE];                     


      // Fill lpLineInfo[] for every line.

      for (dwLineID = 0; dwLineID < dwNumDevs; ++dwLineID)


            GetLineInfo (dwLineID, &g_lpLineInfo [dwLineID],hLineApp);


         if (rc = lineOpen (

                  hLineApp,              // Usage handle for TAPI

                  dwLineID,                  // Cannot use the LINEMAPPER value

                  &g_lpLineInfo->hLine,  // Line handle

                  g_lpLineInfo->dwAPIVersion, // API version number

                  0,                          // Must set to zero for Windows CE

                  0,                          // No data passed back

                  LINECALLPRIVILEGE_NONE,     // Can only make an outgoing call

                  0,                          // Media mode

                  NULL))                      // Must set to NULL for Windows CE





            LINEGENERALINFO LineGeneralInfo;

            memset( &LineGeneralInfo, 0, sizeof(LineGeneralInfo));

            LineGeneralInfo.dwTotalSize  = sizeof(LineGeneralInfo);                    


            rc = lineGetGeneralInfo(g_lpLineInfo->hLine, &LineGeneralInfo);




                  case LINEERR_RESOURCEUNAVAIL:

                  case LINEERR_INVALLINEHANDLE:

                  case LINEERR_STRUCTURETOOSMALL:

                  case LINEERR_INVALPOINTER:

                  case LINEERR_UNINITIALIZED:

                  case LINEERR_OPERATIONUNAVAIL:

                  case LINEERR_OPERATIONFAILED:

                  case LINEERR_NOMEM:

                        return NULL;



            memcpy(pszValue, (TCHAR*)((&LineGeneralInfo)+LineGeneralInfo.dwSerialNumberOffset),



            return pszValue;



      return NULL;


Previous sample is a little more difficult than other methods because lineGetGeneralInfo uses the Telephony Application Programming Interface (TAPI) and then phone line must be initialized, opened and then read. By the way, TAPI can be used to query much information about phone line (usage, statics and so on).


Methods mentioned here are the most common used by getting the device id, so evaluate your current need and use the one which suits you best.