There is a new API available for retrieving a device id in Windows Mobile 5.0 for both Pocket PC and Smartphone. The first question: why do we need a new way of getting the device ID, what’s wrong with the old? To answer this you need to know what a device ID is. There is a very good and detailed explanation here, but in essence it’s a 16 byte code derived from hardware specific information that is unique to each device. This ID is not the same as an IMEI or a phone number found on a phone based device, both of which can be changed, but instead this code lives and dies with the device.

So the device ID is a very useful thing for software that wants to target just your device, e.g. copy protection, or to provide immutable identity to web service calls. Equally so it’s a resource that should be protected to mitigate the risk of identity theft.

Getting at the device id is relatively straight forward but requires either some C++ or a reasonable amount of interop code. The api is something like this:

KernelIoControl(IOCTL_HAL_GET_DEVICEID, 0, 0, buffer, GuidLength,out, bytesReturned);

Protecting Device ID has always been present as part of the Smartphone security model by making the KernelIoControl API a privileged operation, meaning your code must be running in the trusted code group to be able to access this API. But there are two problems with this:

1> Up to and including Pocket PC 2003SE there is no security model to protect the API, so Pocket PC didn’t have any protection on the Device ID.

2> what do untrusted applications do when they want to get access to this API?

3> having lots of applications read and use the device id potentially increases the attack surface for identity theft.

GetDeviceUniqueID attempts to address these issues and to reduce applications dependency on the precious device id. Firstly GetDeviceUniqueID can be called from the trusted or untrusted code group, but the code returned is not the same as a call to KernelIoControl, its a 20 byte code not a 16 byte code. GetDeviceUniqueID takes an additional parameters of an application defined char array, and uses a one way hash to combine the real device id and the char array parameter to generate the new 20 byte code. This means that an application will always get the same 20 byte code if it calls GetDeviceUniqueID on the same device, with the same char array. It also means there is no practical way of asserting the true device id from the 20 byte key an application uses.

This is a native API exposed by coredll.dll so here is a managed code snippet showing how to get the info through interop. Standard Code disclaimer applies


HRESULT GetDeviceUniqueID(

  LPBYTE pbApplicationData,

  DWORD cbApplictionData,

  DWORD dwDeviceIDVersion,

  LPBYTE pbDeviceIDOutput,

  DWORD* pcbDeviceIDOutput




private extern static int GetDeviceUniqueID([In, Out] byte[] appdata,

                                            int cbApplictionData,

                                            int dwDeviceIDVersion,

                                            [In, Out] byte[] deviceIDOuput,

                                            out uint pcbDeviceIDOutput);


private byte[] GetDeviceID(string AppString)


    // Call the GetDeviceUniqueID

    byte[] AppData = new byte[AppString.Length];

    for (int count = 0; count < AppString.Length; count++)

        AppData[count] = (byte)AppString[count];

    int appDataSize = AppData.Length;

    byte[] DeviceOutput = new byte[20];

    uint SizeOut = 20;

    GetDeviceUniqueID(AppData, appDataSize, 1, DeviceOutput, out SizeOut);

    return DeviceOutput;



The full project code is here.




Comments (61)

  1. Sven Rutten says:


    Thanks for this, it’s working without any problem. For a project I need to have this in VB.NET but I can’t seem to convert it correctly with some tools on the net…

    Could you post the VB.NET-Code of this?



  2. Joe says:

    Using the same salt but on 3 different smartphone mobile 5 devices I’m getting back the exact same ID. I do not have that problem on CE mobile 5 devices. Has anyone seen this problem? Thanks.

  3. scyost says:

    Hi Joe, Can you e-mail me and tell me which models of smartphones you’re seeing this behavior with? (scyost at Thanks, Scott

  4. joe says:

    Scott, I just did. Let me know if you don’t received it. Thanks.

  5. Gerrit says:

    Thanks for the couple of references and the information. The documentation in CE5.0 for IOCTL_HAL_GET_DEVICEID is incorrect. They have transposed the description of the Platform and Preset ID and there is no restriction/recommendation to the length of the returned ID. This created some incompatibilities for our device with other third party SW until we implemented it as a standard GUID with the description of Platform and Preset ID as per 4.1 documentation.

  6. Eriks says:


    I have the same problem too. The GetDeviceUniqueID returns the same number on O2 Atom even for different devices. But the same routine works perfectly fine on Dell X51V.

    Is there any solution ?

  7. scyost says:

    The unique part of the data that goes into that function comes out of the BSP for the platform. The OEM implements that code, so I can’t comment that behavior.

  8. john says:

    Has anyone found a solution to this? We really need to find a way to uniquely identify the device so that we can protect our software… and we have found several devices giving the same results using GetDeviceUniqueId.

    So, it seems that the OEMs have once again spoiled the party.

    We then thought of combining the results from GetDeviceUniqueId with the "old" KernelIoControl(IOCTL_HAL_GET_DEVICEID), but still that shows the same results on some devices.

    So, what else is left to determine the uniqueness of the device? We are thinking of the Bluetooth Address and the WIFI card MAC… but is that guaranteed to be unique? I mean, if the OEMs can’t correctly implement GetDeviceUniqueId() then how can we be sure that they haven’t done the same mistake with any piece of hardware that comes inside the device.

    Advise anyone?

  9. joe says:

    I was able to use KernelIoControl(IOCTL_HAL_GET_DEVICEID), instead of GetDeviceUniqueId(), to get a unique ID on SP mobile 5 devices.  Of course the app has to be signed or it won’t work.

  10. Josh says:

    Hi all,

    Nobody have cab file or exe file i can execute to retrieve a device ID of my SPV 600 smartphone running under Windows Mobile 2005.

    Thanks in advance for your help

  11. David says:

    Sorry to digress from device id. I just remembered mid last year there were news that Flextronics was making ready (nearly complete) a lowcost WM5 unit code name Peabody.

    I cannot find any more news regarding that development? Has it evaporated?

    Thanks for sharing your info

  12. Hermione says:

    Is it possible to get the IMEI number for windows mobile 2003 for smartphones?

  13. At our Technet Mobility event we asked the attendees to text questions to us for the Q&amp;amp;A session……

  14. cesarbremer says:

    I am developing an application for the smartphone platform (windows mobile 2003, second edition), in my case a secure phone. I need to get an unique device information in order to implement a copy protection for my application.The GetDeviceUniqueID  is a very nice solution, but only works with windows mobile 5.

    Do you have an easy solution for this kind of problem that doesn’t need the privileged access to the kernel functions using certificates?

  15. is there any guarantee that an application, using the same AppData, will *always* get a different DeviceID when calling GetDeviceUniqueID an different devices?

    Or is there a mathematical chance that two different devices will return the same DeviceID ?

  16. Ratheesh says:

    Can this code work with windows mobile2.0..?

  17. TIENG Sunheng says:

    Is it a IMEI of Pocket PC and SmartPhone

    Can it work on all device

  18. Claudia says:

    When I run this code within my VB .Net (CF 1.0) Application for WM 5.0 on Pocket PC, I just get back an empty Byte Array. Anyone an Idea why this might happen?

  19. upto says:


  20. Keith Ludwig says:

    Thanks for the code snippet to get the unique ID…

    Not sure where to ask this, so I’ll ask here.  How does one programmatically check for presence of the following hardware on a given WM device?

    – infrared

    – bluetooth

    – wi-fi

    – camera

    I would’ve also added ‘keyboard’ to this list, but I already saw your post on how to do this.

    Any insight is greatly appreciated!


  21. R-ya says:

    private byte[] GetDeviceID(string AppString)

    what’s parameter AppString used?

    what’s "AppString" means?How can I catch it?

  22. scyost says:

    It’s a string that identifies the caller of the API. It gets hashed into the data that is returned, so different callers will get different results. There’s more explanation on the MSDN page.

  23. CeGetLocked says:

    How do you retrieve the imei from a Pocket PC Phone Edition or smartphone?

  24. Richard says:

    Anyone know whether MS have fixed the problems with this API call?  If not should we be reverting back to KernelIoControl() call with signed applications?

  25. Mike Landis says:

    How does knowing a deviceID pose an identity theft threat?

    Mike Landis

  26. minstn says:

    iam having the same problem with GetDeviceUniqueID. It is always the same on my Qtek 8310 and Orange C600, the ID i get is:


    please paste yours!

  27. Feel free to a free trial of LicenseKey2Go.

  28. Tapas says:

    Is there any way out  to retrieve Pocket PC DeviceID from a desktop application? Please help me in this context iff any solution exists.  

  29. Chee says:

    Any way to Get Owner name for device

  30. mohs_cool says:

    i have tried , i got the following Id in the emulator


    moreover i also tried the code given in the following Link : but the emulator shows a different Id . for your reference the link is as follows :

    when tried with the above code i got the following Id:


    i want to check wheather the Id generate is right or wrong .



  31. scyost says:

    GetDeviceUniqueId and the IOCTL method will give you different data back. That’s expected.

  32. is there any problem using

    GetDeviceUniqueID() native call in Windows Mobile 5.0

    I’m getting always the same result a list of 0000000000, in my emulator.

    is there any difference using

    KernelIoControl() I heard that the function returns a 16 bytes instead of the 20 on GetDeviceId, but how really affects my software, that issue?

    My mail is


  33. Samuel Yang says:

    I got the device ID by using your code.

    But I still have another problem.

    I want to get the device ID via desktop programm.

    How can I do?

    I want use it like this:

    There is a winform has a button and a textbox in it.

    When click the button,the win programm to get the device ID and show it in the textbox(device already connected to the PC by ActiveSync).

    Is there has a solution?


    My mail is

  34. Bob Li says:

    获取 Windows Mobile 设备的唯一标识各种方法。

  35. Kent Yang says:

    thanks a lot, i am get the guid successfuly!

  36. vladan says:

    It’s not the problem with OEMs. It is problem with Microsoft who didn’t controlled OEMs. This would never happen on Symbian devices. Someone should pay for GetDeviceUniqueID non working.

  37. Jim Arnell says:

    Anyone who have managed to use the GetDeviceUniqueID or the IOCTL_HAL_GET_DEVICEID so that it corresponds to the device id shown in Exchange 2003/2007?

  38. Ashwin says:

    is the deviceid that shows up in the exchange 2003 interface related to the imei or meid of that device?

    is there a way to find the device id based on the imei/meid or vice versa?

  39. Dmytro B. says:

    Can I use the hashed output of KernelIoControl as the unique identifier of the mobile device?


  40. scyost says:

    You can do that if you want, but don’t count on being able to call IOCTL_HAL_GET_DEVICEID on Windows Mobile Standard/Smartphone or in future versions. GetDeviceUniqueId is the supported way to do it.

  41. MK says:

    Thanks for this post.  I would like to access the "Device Serial No" on our Windows Mobile 5 device programmatically.  This is the number that can be found in settings->system->systemInformation->identity->device serial no.  

    Can anyone tell me how to access that number?  It doesn’t seem to be in the registry.

    We need to access it to do inventory tracking.  It matches the bar code on the device.


  42. scyost says:


    That control panel is provided by the OEM, not Microsoft, so I don’t actually know what it’s doing. Does it match anything like what IOCTL_HAL_GET_DEVICEID returns?

  43. MK says:

    Thanks, Scott.  No, it doesn’t match any part of the value returned by IOCTL_HAL_GET_DEVICEID.  There may be some hidden relationship there, but I don’t see it in any case.  There is a file call SystemInfo.cpl in Windows, but it appears to be a ROMMODULE file and hence I can’t seem to read it.  Any suggestions there?

  44. scyost says:

    No, you won’t be able to easily read the contents of the in-rom binaries.

    Try calling that IOCTL with both the sizeof(UNIQUE_DEVICEID) and the sizeof(DEVICE_ID). Sometimes it’s implemented to return a different value in those cases. Maybe one of those values is the one you’re looking for.

  45. johng says:

    Can someone tell me if the results of GetDeviceUniqueID remain the same after a device is upgraded from wm5 to 6/6.1?

  46. scyost says:

    The simple answer is "yes"

    The complicated answer is:

    We require of our partners that the results of that API are consistent in the field. If you buy a WM5 device and the OEM provides an upgrade to WM6, it is one of our requirements that the ID does not change. We have some certification tests around it. There are cases where it would have to change, like if the WM5 version were returning inconsistent results. In those cases we waive the test in favor of fixing the behavior.

  47. johng says:

    Thanks for the info, Scott.  I appreciate it.

  48. andyp says:

    We have two E-TEN Glofiish X600 devices here and GetDeviceUniqueID returns exactly the same value for them. This method is definitely not reliable.

  49. Mike says:

    I’ve been trying to get the code working in with no luck so far. I’ve found the following conversion on a web site (might have been Peter Foots??) but I dont know what to do with it to get a sensible answer back.

    Can anyone be of help! Its driving me nuts!

       Declare Function GetDeviceUniqueID Lib "Coredll" (ByVal appdata As Byte(), ByVal cbApplictionData As Integer, ByVal dwDeviceIDVersion As Integer, ByVal deviceIDOuput As Byte(), ByRef pcbDeviceIDOutput As Integer) As Integer

       Private Function GetDeviceId(ByVal appData As String) As Byte()

           Dim appDataBytes As Byte() = System.Text.Encoding.ASCII.GetBytes(appData)

           Dim outputSize As Integer = 20

           Dim output(19) As Byte

           Dim result As Integer = GetDeviceUniqueID(appDataBytes, appDataBytes.Length, 1, output, outputSize)


           Return output

       End Function

       Public Function getDevId() As String

           Dim devId As Byte()

           devId = GetDeviceId("MyAppName")

           getDevId = System.Text.Encoding.ASCII.GetString(devId, 0, 20)

       End Function

  50. Alon says:


    this function is not supported by WM because the file Pkfuncs.h is missing.

    Where can i get this file ?

  51. Alx says:

    Translation for

    Declare Function GetDeviceUniqueID Lib "Coredll" (ByVal appdata As Byte(), ByVal cbApplictionData As Integer, ByVal dwDeviceIDVersion As Integer, ByVal deviceIDOuput As Byte(), ByRef pcbDeviceIDOutput As Integer) As Integer

    Private Function GetUniqueDeviceId() As String

           Dim AppString As String = "Appication Name"

           Dim AppData(AppString.Length) As Byte

           Dim count As Integer = 0

           While count < AppString.Length

               AppData(count) = Convert.ToByte(AppString.Chars(count))

               count += 1

           End While

           Dim appDataSize As Integer = AppData.Length

           Dim DeviceOutput(20) As Byte

           Dim SizeOut As UInteger = 20

           GetDeviceUniqueID(AppData, appDataSize, 1, DeviceOutput, SizeOut)

           Dim sb As StringBuilder = New StringBuilder()

           Dim x As Integer = 0

           While x < DeviceOutput.Length

               sb.Append(String.Format("{0:x2}", DeviceOutput(x)))

               x += 1

           End While

           Return sb.ToString()

       End Function

  52. James Devitt says:

    This code compiles OK but produced zeros. I found success using an 11+ AppString. Carriers want to hide the natural ID and don’t want it found out too easily.

    using System;

    using System.Runtime.InteropServices; //needed to use [dllimport], <dllimport> in

    namespace sdGetID


       public class GetDeviceIdentity_Class



           private extern static int GetDeviceUniqueID([In, Out] byte[] AppData, int cbApplictionData, int dwDeviceIDVersion, [In, Out] byte[] deviceIDOuput, out uint pcbDeviceIDOutput);

           // The article shows getting more then one ID so I added

           // IDVer as an integer – only 1 works but left it in.

           public byte[] GetDeviceID(string AppString, int IDVer)


               // Call the GetDeviceUniqueID

               byte[] AppData = new byte[AppString.Length];

               for (int count = 0; count < AppString.Length; count++)

                   AppData[count] = (byte)AppString[count];

               int AppDataSize = AppData.Length;

               byte[] DeviceOutput = new byte[20];

               uint SizeOut = 20;

               GetDeviceUniqueID(AppData, AppDataSize, IDVer, DeviceOutput, out SizeOut);

               return DeviceOutput;




  53. Vaidhees says:

    im using this code to get device unique id. it works well in wm5.0 and 6.0 but it not works on windows mobile 2003(pocketpc and smartphone). it throws missing method exception.. is there any other way?

  54. Thanks for your info… the Vb.NET sample will help me a lot.

  55. Ted Nichols says:

    I’ve read through all these comments and the question is…  Does GetUniqueDeviceID return a unique ID or not?  At least 3 people are saying the ID’s returned from different devices are the same, but the author has not commented on this?

  56. pete says:

    It does not! blackjack II confirmed returning the same device ID… come on microsoft give us a simple way like every other mobile OS out there to get a unique ID. Ill post if i find a way for this.

  57. MSDNArchive says:

    While there is not a comprehensive list of devices affected, we are aware of some older device models that do not have a unique device ID.   Since the rollout of our certification tests (during the Windows Mobile 6.x era), OEM devices are now required by Microsoft to have a unique device ID.  This blog entry is thus only relevant for getting the unique device ID of properly certified devices.

  58. rat says:

    GetUniqueDeviceID and IOCTL_HAL_GET_DEVICEID gives the same values on different devices Gigabyte GSmart MS802 with WM6 (5.2.1623).

  59. Danny says:

    Got this link from google on searching for "retrieve imei windows mobile" .

    Will this work?

Skip to main content