OSVERSIONINFO VersionInformation;
GetVersionEx(&VersionInformation);
SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(szOSPlatform), szOSPlatform, 0);
ret = GetLastError();
if (ret==ERROR_ACCESS_DENIED)
{
wcscpy(szOSPlatform, L"SmartPhone");
}
wsprintf(g_OSVer, L"WM %d.%d.%lu %s", VersionInformation.dwMajorVersion, VersionInformation.dwMinorVersion, VersionInformation.dwBuildNumber, szOSPlatform);
有時候在寫WM上程式時需要對不同的WM版本做不同的處理, 於是這就需要判斷出不同的版本來. sdk提供了一個api, 讓開發人員獲知運行該程式的系統版本.
BOOL GetVersionEx(
LPOSVERSIONINFO lpVersionInformation
);
這個api很簡單, 沒啥好說的. 主要是這個結構體
typedef struct _OSVERSIONINFO{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[128];
} OSVERSIONINFO;
dwOSVersionInfoSize 這個結構的大小, 使用之前, sizeof(OSVERSIONINFO)賦值給它就是了.
dwMajorVersion 主要版本號
dwMinorVersion 次版本號碼
dwBuildNumber 編譯時間的版本戳記
dwPlatformID 作業系統的標識, 在mobile系統上這個值都是 VER_PLATFORM_WIN32_CE, 及wince系統
szCSDVersion 附加說明, 字串格式.從我測試的情況看, 好像都是Null 字元串.
這裡的版本號碼實際上指的的wince的版本號碼, 而不是我們熟悉的什麼 wm2003, wm5, wm6之類的.
比如說 DOPOD D600 上的系統版本號碼 5.1.422 . dwMajorVersion 對應的是5; dwMinorVersion 對應的是1; dwBuildNumber對應的是422 .
判斷sp還是ppc, 則需要用到另外一個函數:
BOOL SystemParametersInfo(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni
);
這個函數的使用也很簡單, 要擷取系統平台, 將uiAction傳進參數SPI_GETPLATFORMTYPE, uiParam是pvParam的大小, pvParam是接收資料的buf, fWinIni設為0即可.
如果pvParam傳出的值是"Smartphone", 則表示是sp, 否則是ppc.
----------------------------------------------------------------------------------------------------------------------------------------------------
怎麼獲得SIM卡號和IMEI號
首先需要用到以下幾個API:
[DllImport("cellcore.dll")]//初始化Sim卡列表,並返回一個可以操作的控制代碼lphSim
private static extern IntPtr SimInitialize(IntPtr dwFlags, IntPtr lpfnCallBack, IntPtr dwParam, out IntPtr lphSim);
開門用的,而且把門把手(lphSim)交給你掌握。
[DllImport("cellcore.dll")]//關閉Sim卡列表
private static extern IntPtr SimDeinitialize(IntPtr hSim);
出門後一定要記得不要留任何把柄在門把手上。
[DllImport("cellcore.dll")]//讀取指定的記錄
private static extern IntPtr SimReadRecord(IntPtr hSim, IntPtr dwAddress, IntPtr dwRecordType, IntPtr dwIndex, byte[] lpData, IntPtr dwBufferSize, ref IntPtr lpdwBytesRead);
進門後翻東西了唄。hSim,門把手記得不要留在外面,否則讓人鎖在屋裡;dwAddress,要在哪拿東西;dwRecordType,拿什麼東西;dwIndex,從哪開始拿;lpData,自己的兜;dwBufferSize,兜的大小;lpdwBytesRead,實際上拿了多少東西。
[DllImport("cellcore.dll")]//擷取Sim卡指定記錄的資訊(資料結構)
private static extern IntPtr SimGetRecordInfo(IntPtr hSim, IntPtr dwAddress, ref SimRecord lpSimRecordInfo);
計劃一下應該拿什麼東西,用此門磚。hSim,門把手,不要丟;dwAddress,東西放在哪;lpSimRecordInfo,門磚是要回收地(沾滿鑽石的羊肉啊)。
//定義常量
const int EF_ICCID = 0x2FE2;//ICCID號碼在Sim卡的儲存地址
const int SIM_RECORDTYPE_TRANSPARENT = 0x00000001; //只擷取單個記錄
[StructLayout(LayoutKind.Sequential)]//Sim卡記錄的資料結構
private struct SimRecord
{
public IntPtr cbSize;
public IntPtr dwParams;
public IntPtr dwRecordType;
public IntPtr dwItemCount;
public IntPtr dwSize;
}
擷取資訊的過程如下:
//擷取Sim卡的ICCID
IntPtr res, hSim;
//初始化Sim卡列表
res = SimInitialize(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out hSim);
if (res != IntPtr.Zero)
throw new Exception("Can not Initialize Sim.");
SimRecord rec = new SimRecord();
rec.cbSize = (IntPtr)Marshal.SizeOf(rec);
res = SimGetRecordInfo(hSim, (IntPtr)EF_ICCID, ref rec);//擷取ICCID的資料結構資訊
if (res != IntPtr.Zero)
throw new Exception("Could not read the ICCID information from the SIM.");
byte[] bData = new byte[(int)rec.dwSize + 1];//這裡多加了一個位元組來擴充一下緩衝區
IntPtr dwBytesRead = IntPtr.Zero;
res = SimReadRecord(hSim, (IntPtr)EF_ICCID, rec.dwRecordType, IntPtr.Zero, bData, (IntPtr)bData.Length, ref dwBytesRead);
if (res != IntPtr.Zero)
throw new Exception("Could not read the ICCID from the SIM");
SimDeinitialize(hSim);
string str="";
for (int i = 0; i < bData.Length - 1; i++)//這裡當然要把前面多加的那個位元組給去掉啦,否則會多些資料
{
str = str + ReversByte(bData[i]);
}
Info.SimIccid = str;
Info.SimIccid = Info.SimIccid.Replace("/0", "");
ReversByte這個函數是個自己寫的函數,具體的功能就是把一個byte的高4位和低4位的值顛倒過來(也就是把byte轉成hex字串之後吧第一位和第二位互換位置即可)。
從SimReadRecord讀取到的資料是10個byte,轉成hex之後大致會如下:98680055518014043250,把每個byte的高低位互轉之後再組合起來就成了89860055150841003452,這個也就是Sim卡的ICCID了,每個卡背面的那唯一的20位元字。
為了防止人為的修改ICCID來達到混淆的目的,可以再擷取IMSI號碼(這個是移動側資料庫中的,人為一般不可能修改)和ICCID綁定並儲存到伺服器中來達到唯一識別客戶的目的,如果還覺得不夠,可以再擷取客戶的那個13×××××××××的號碼或者15×××××××××的號碼(不過我覺得這個沒什麼必要,之前那2個已經足夠了)。