using System; using System.Text; using System.Runtime.InteropServices; using System.ComponentModel; namespace PhoneGap { internal partial class PInvoke { private static Int32 FILE_DEVICE_HAL = 0x00000101; private static Int32 FILE_ANY_ACCESS = 0x0; private static Int32 METHOD_BUFFERED = 0x0; private static Int32 IOCTL_HAL_GET_DEVICEID = ((FILE_DEVICE_HAL) << 16) | ((FILE_ANY_ACCESS) << 14) | ((21) << 2) | (METHOD_BUFFERED); private const Int32 ERROR_NOT_SUPPORTED = 0x32; private const Int32 ERROR_INSUFFICIENT_BUFFER = 0x7A; [DllImport("Coredll.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode)] static extern int SystemParametersInfo4Strings(uint uiAction, uint uiParam, StringBuilder pvParam, uint fWinIni); public enum SystemParametersInfoActions : uint { SPI_GETPLATFORMTYPE = 257, // this is used elsewhere for Smartphone/PocketPC detection SPI_GETOEMINFO = 258, } public static string GetOemInfo() { StringBuilder oemInfo = new StringBuilder(50); if (SystemParametersInfo4Strings((uint)SystemParametersInfoActions.SPI_GETOEMINFO, (uint)oemInfo.Capacity, oemInfo, 0) == 0) throw new Exception("Error getting OEM info."); return oemInfo.ToString(); } [DllImport("coredll.dll", SetLastError = true)] private static extern bool KernelIoControl(Int32 dwIoControlCode, IntPtr lpInBuf, Int32 nInBufSize, byte[] lpOutBuf, Int32 nOutBufSize, ref Int32 lpBytesReturned); public static string GetDeviceID() { // Initialize the output buffer to the size of a // Win32 DEVICE_ID structure. byte[] outbuff = new byte[20]; Int32 dwOutBytes; bool done = false; Int32 nBuffSize = outbuff.Length; // Set DEVICEID.dwSize to size of buffer. Some platforms look at // this field rather than the nOutBufSize param of KernelIoControl // when determining if the buffer is large enough. BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0); dwOutBytes = 0; // Loop until the device ID is retrieved or an error occurs. while (!done) { if (KernelIoControl(IOCTL_HAL_GET_DEVICEID, IntPtr.Zero, 0, outbuff, nBuffSize, ref dwOutBytes)) { done = true; } else { int error = Marshal.GetLastWin32Error(); switch (error) { case ERROR_NOT_SUPPORTED: throw new NotSupportedException( "IOCTL_HAL_GET_DEVICEID is not supported on this device", new Win32Exception(error)); case ERROR_INSUFFICIENT_BUFFER: // The buffer is not big enough for the data. The // required size is in the first 4 bytes of the output // buffer (DEVICE_ID.dwSize). nBuffSize = BitConverter.ToInt32(outbuff, 0); outbuff = new byte[nBuffSize]; // Set DEVICEID.dwSize to size of buffer. Some // platforms look at this field rather than the // nOutBufSize param of KernelIoControl when // determining if the buffer is large enough. BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0); break; default: throw new Win32Exception(error, "Unexpected error"); } } } // Copy the elements of the DEVICE_ID structure. Int32 dwPresetIDOffset = BitConverter.ToInt32(outbuff, 0x4); Int32 dwPresetIDSize = BitConverter.ToInt32(outbuff, 0x8); Int32 dwPlatformIDOffset = BitConverter.ToInt32(outbuff, 0xc); Int32 dwPlatformIDSize = BitConverter.ToInt32(outbuff, 0x10); StringBuilder sb = new StringBuilder(); for (int i = dwPresetIDOffset; i < dwPresetIDOffset + dwPresetIDSize; i++) { sb.Append(String.Format("{0:X2}", outbuff[i])); } sb.Append("-"); for (int i = dwPlatformIDOffset; i < dwPlatformIDOffset + dwPlatformIDSize; i++) { sb.Append(String.Format("{0:X2}", outbuff[i])); } return sb.ToString(); } } internal partial class PlatformDetection { private const string MicrosoftEmulatorOemValue = "Microsoft DeviceEmulator"; public static bool IsEmulator() { return PInvoke.GetOemInfo() == MicrosoftEmulatorOemValue; } } class InitializationCommand : Command { #region Command Members Boolean Command.accept(String instruction) { return "/initialize".Equals(instruction); } String Command.execute(string instruction) { string retVal = ";device.name = '" + PInvoke.GetOemInfo() + "';"; retVal += "device.uuid = '" + PInvoke.GetDeviceID() + "';"; return retVal; } #endregion } }