天天看點

WINCE開發集錦

如何讓系統加載自己寫的驅動程式?  

兩種辦法:

1、在[HKEY_LOCAL_MACHINE/Drivers/BuiltIn]下添加注冊鍵。

2、在應用程式中調用ActivateDeviceEx。

在一些檔案中用分号來表示注釋,例如下面的内容  

; @CESYSGEN IF SERVERS_MODULES_HTTPD

; @CESYSGEN ENDIF

在“CESYSGEN...”前加了“@”,有沒有什麼特别的含義?

在WINCE的一些檔案中,用“;”作為注釋并在注釋文字中用@CESYSGEN作為标記,後面接條件語句。Cefilter.exe工具負責按照條件來篩選檔案内容,是以不要輕易地删除包含@CESYSGEN的注釋語句。

通過序列槽建立ActiveSync聯接,序列槽線用三線的可以嗎?  

不可以,因為用序列槽同步時要用到其餘口的狀态。 

觸摸屏校準資料儲存位置:

[HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP/TOUCH]

 "CalibrationData"="487,652 182,240 186,1052 792,1052 792,244 "

燒寫系統觸摸屏校準後,用EVC->Tools->Remote Registry Editor擷取 "CalibrationData"值,在platform.reg修改,再生成核心,就不用燒一遍校準一遍了。 

工作列:

[HKEY_LOCAL_MACHINE/Software/Microsoft/Shell/SlideTaskBar]

"Default"="0" ;是關閉隐藏工具欄

[HKEY_LOCAL_MACHINE/Software/Microsoft/Shell/AutoHide]

"Default"=dword:1 ;自動隐藏工作列

[HKEY_LOCAL_MACHINE/Software/Microsoft/Shell/OnTop]

"Default"="0" ;使工作列不總在最前端

 4.wince核心超過32m的,在config.bib檔案修改:

MEMORY;配置核心大小

   ;注釋bymjf NK      80200000  01E00000  RAMIMAGE

   ;bymjf RAM     82000000  01E00000  RAM

   ;bymjfFLASH   92000000  00100000  RESERVED

    NK      80200000  02000000  RAMIMAGE

    RAM     82200000  01E00000  RAM

    FLASH   92200000  00100000  RESERVED

5.windows mobile6.5RAS撥号Entry Name位置:

[HKEY_CURRENT_USER/Comm/RasBook]

  WINCE是否支援MAPI?

不支援。WINCE自帶的pmail.exe軟體也不是很好用。建議自開發郵件收發軟體。如果需要購買WINCE下郵件收發軟體可以聯系我。

如何旋轉螢幕顯示的内容?

例子代碼如下(前提是顯示驅動程式支援旋轉):

DEVMODE   devmode = {0};

devmode.dmSize = sizeof(DEVMODE);

devmode.dmDisplayOrientation = DMDO_90;        ///垂直模式

devmode.dmFields = DM_DISPLAYORIENTATION;

ChangeDisplaySettingsEx(NULL, &devmode, NULL, 0, NULL);   ///改變顯示的設定

CRect   rcWorkArea(0, 0, 320, 240);     ///整個螢幕尺寸

///設定客戶區大小并廣播消息,這樣所有軟體也就随之更改顯示

SystemParametersInfo(SPI_SETWORKAREA, 0, (void*)&rcWorkArea, SPIF_SENDCHANGE);  

請問如何修改字形緩存的容量?

[HKEY_LOCAL_MACHINE/System/GDI/GLYPHCACHE]

"limit"=dword:0400

如何得到從WINCE啟動開始到現在的時間?

調用API GetTickCount,得到的值為32位整數,機關為毫秒。

如何調用WINCE的軟鍵盤?

調用API SipShowIM(SIPF_ON),前提是核心加入了軟鍵盤元件。

基于HIVE的系統資料庫,如何在系統關閉前儲存系統資料庫的資料到檔案system.hv?

調用API RegFlushKey函數。

使用VirtualAlloc和VirtualCopy的時候需要注意哪些事項?

1、VirtualAlloc的作用是申請虛拟位址空間,這肯定不是最終的目的,最終目的可能是申請實體記憶體、映射寄存器、送出檔案等。沒有一個目的會在意虛拟位址空間的位置,是以盡量傳遞參數1為0,也就是讓WINCE自動配置設定虛拟位址空間。VirtualAlloc配置設定位址空間實際上是以64KB為機關,是以要指定申請的虛拟空間的首位址的話,參數1應該為64KB的整數倍,申請的長度也應該為64KB的整數倍,即使你不需要那麼大。

2、VirtualCopy的主要作用是映射實體位址空間,如果參數2為實體位址,那麼最後一個參數要添加PAGE_PHYSICAL,參數2必須是256的整數倍。如果參數2為虛拟位址(0x80000000以上),那麼最後一個參數就不要添加PAGE_PHYSICAL,WINCE核心會根據這個虛拟位址找到對應的實體位址。

驅動程式和應用程式之間傳遞資料時何時調用MapPtrToProcess?

因為裝置管理器負責加載驅動程式DLL,這意味着當應用程式調用驅動程式接口函數的時候,WINCE核心會将調用驅動程式接口函數的線程轉移到裝置管理器的程序空間然後執行具體的驅動程式代碼,應用程式和裝置管理器處于兩個程序空間,這就造成裝置管理器無法通路應用程式傳遞的指針(虛拟位址),是以當我們在應用程式中傳遞指針給流驅動程式接口函數時,WINCE核心從中作了一個位址映射,例如ReadFile、WriteFile、DeviceIoControl函數的參數凡是指針都經過了映射才傳遞給驅動程式,是以很多驅動程式開發者并不了解其中的奧秘就可以程式設計了。但是如果參數是一個指向一個結構體的指針,而結構體裡包括一個或多個指針,那麼WINCE核心并不負責映射,是以就需要開發者在驅動程式接口函數中調用API函數MapPtrToProcess來映射位址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());  

如何判斷可插拔的裝置是否存在?

1、通過查找系統資料庫的值。凡是由API ActivateDeviceEx加載的驅動程式都在[HKEY_LOCAL_MACHINE/Drivers/Active]鍵下有注冊鍵,通過查找“name”或者其它鍵值就能夠找到。裝置管理器就調用這個API。如果是PCI裝置,在系統資料庫[HLM/Drivers/BuiltIn/PCI/Instance]下查找關鍵字,例如[HLM/Drivers/BuiltIn/PCI/Instance/WaveDev1],說明音頻驅動已經加載。

2、調用驅動程式接口函數,根據傳回值或者執行結果來判斷。

如何做到通過序列槽過來的一個信号啟動自己開發的應用程式?

建立一個線程負責等待序列槽過來的信号,調用API SetCommMask設定要等待的信号種類,具體可以等待的信号種類參見參數2的說明。然後再調用API WaitCommEvent函數等待這個信号,接收之後再調用API CreateProcess啟動應用程式。

在WINCE中如何隻能啟動應用程式的一個執行個體?

常用的兩種辦法:

1、如果應用程式執行個體建立了視窗,可通過API FindWindow函數通過視窗類名和視窗标題名稱來查找,前提是系統内不會出現視窗名稱重複的情況。

2、應用程式初始化的時候建立一個事件或互斥等核心對象,因為核心對象是由核心建立,名稱在系統内唯一。

能不能自己編輯一個數字簽名檔案導入到手機上,這樣就可以用這個簽名簽自己的程式了?

WINCE的核心簽名機制的用途是限制非法的可執行子產品EXE、DLL等在裝置上運作。要求核心的加載子產品用公鑰驗證請求加載的EXE、DLL的簽名是否合法,而這個公鑰是在定制核心的時候加進去的,是以除核心的定制者以外的人無法修改這個驗證機制。

我按照版主的文章《加密WINCE系統》裡操作,提示錯誤如下:

Error 80090016 during CryptSignHash 1!

Error signing hash

這是因為傳遞了無效的鑰容器名稱,使CryptoAPI調用失敗。應該在使用signfile工具之前建立一個鑰容器,在桌面Windows中調用API CryptAcquireContext建立一個指定名稱的鑰容器,接着再建立一個簽名密鑰對,這時再使用signfile工具就可以了。我在文章裡寫成-kfulinlin是因為我建立鑰容器的時候沒有指定名稱,系統就采用目前登入的使用者名為容器名。

編譯錯誤:CVTRES : fatal error CVT1102: out of memory; 42 bytes required ?

多數情況下出現這種錯誤是因EVC的bug而起,應該在安裝EVC之後就立刻安裝EVC的SP更新檔。另外為了避開BUG,使用EVC程式設計應該養成一些習慣,比如定期備份工程所有檔案,每次編譯時采用Clean + Rebuild All,正調試時不要關閉模拟器等等。

在WINCE下是否能夠得到某一程序使用的實體記憶體總量?

目前沒發現有這樣一個API能夠得到指定程序使用的實體記憶體總量。隻有GlobalMemoryStatus能夠得到整個系統使用的實體記憶體總量。

應用程式如何控制lcd的亮度?如何獲得電池的電量?

從常見的平台如Geode、三星ARM系列來看,的确在驅動方面沒有統一的控制LCD或者其它種類螢幕亮度的接口函數,是以隻能根據具體平台提供的接口來做。從幫助文檔來看微軟的帶有DirectDraw功能的顯示驅動程式的确有标準的增加亮度的接口函數,關于背景光參見标題為“Enabling a Backlight”的幫助文檔。

獲得電池電量有标準的接口函數GetSystemPowerStatusEx,前提是驅動程式和硬體都要支援。

WINCE的socket函數好像不支援發送/接收逾時?

是的,最早版本的WINCE支援選項SO_RCVTIMEO、SO_SNDTIMEO,後來卻不支援了。

WINCE下如何設定視窗最大化和最小化?

WINCE的幫助文檔在介紹API ShowWindow函數的參數時指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支援,但實際上并不完全是這樣,具體來說:

SW_MAXIMIZE             比原來視窗大,但不是最大化

SW_MINIMIZE              編譯成功,但是不起作用

SW_SHOWMAXIMIZED      最大化

SW_SHOWMINIMIZED       編譯出錯

SW_RESTORE               能恢複

SW_SHOWDEFAULT         編譯出錯

SW_SHOWMINNOACTIVE    編譯出錯

SW_HIDE                   能夠隐藏

如何用程式調用控制台的觸摸屏校對程式?  

兩種辦法:

1、調用API TouchCalibrate函數

2、調用CreateProcess,參數1為L"//windows//ctlpnl.exe",參數2為L"cplmain.cpl,9"。

如何獲得U盤或者其它類型的存儲器總容量和剩餘可用容量?

調用API GetStoreInfo得到扇區數、每扇區位元組數,相乘即是總容量。調用API GetDiskFreeSpaceEx得到剩餘可用容量。

三星2440頭檔案定義#define IIC_BASE 0xB1400000 // 54000000,datasheet是54000000,那麼怎麼轉成0xB1400000?

實體位址映射方法分為兩種,一種靜态映射另一種為動态映射。在OEMAddressTable中定義了實體位址與虛拟位址的映射關系屬于靜态映射,用VirtualCopy映射屬于動态映射,采用哪種辦法都可以。問題中提到的屬于靜态映射,2440的BSP在map.a檔案中定義了IIC控制寄存器的實體起始位址和對應的虛拟位址如下:

DCD 0x91400000, 0x54000000, 1 ;

在OEMAddressTable中定義的虛拟位址範圍在0x8000 0000—0x9FFF FFFF,這部分可緩存,适合核心程式和應用程式使用,同時WINCE核心在0xA000 0000—0xBFFF FFFF中映射了另一份,指向了同樣的實體位址,這部分不可緩存,适合驅動程式使用。三星ARM處理器帶有L1級高速緩存,可緩存會提高執行效率。對于特殊的裝置寄存器适合映射到不可緩存的虛拟位址。

當驅動程式調用VirtualCopy對0xB1400000位址讀寫時,WINCE自動将這個位址減去0x2000 0000,也就是0x91400000,對應的實體位址就是0x54000000,也就是IIC控制寄存器的實體起始位址。

基于RAM的系統資料庫如何儲存資料?

調用API RegCopyFile備份系統資料庫。調用API RegRestoreFile恢複系統資料庫,然後調用KernelIoControl熱啟動使恢複生效。

如何隐藏和顯示winCE下标準外殼的工作列?

HANDLE   hTaskBar = FindWindow(L"HHTaskBar", NULL);  

ShowWindow(hTaskBar, SW_HIDE);  

ShowWindow(hTaskBar, SW_SHOWNORMAL);  

如果能讓WINCE的IE浏覽器播放flash動畫?

播放flash需要Macromedia Flash Player SDK,參見http://www.adobe.com/products/flashplayer_sdk/。這和real player相似,都需要WINCE平台的SDK,都需要申請。

WINCE下核心模式和使用者模式有什麼差別?

為了使讀者能夠詳細了解WINCE的位址映射原理還有兩種模式,在這裡我分幾個部分說明:

1、WINCE核心nk.exe的任務是管理作業系統核心功能。按照OEMAddressTable的映射要求,所有實體位址都映射到0x80000000以上,是以對于核心程式nk.exe和核心模式下的線程來說,隻要通路0x80000000以上的有效虛拟位址經MMU就能夠通路實體位址,無需再映射是核心模式的一個特點。核心模式的第二個特點是沒有位址通路限制,核心模式線程可以通路任何有效虛拟位址,所謂有效虛拟位址是指有實際事物對應。

2、使用者模式線程隻能通路0x80000000以下的虛拟位址空間,WINCE6.0之前版本的核心為每個程序劃分32MB的位址空間,在不調用特殊函數的情況下不能互相通路,這樣的設計使得WINCE系統更安全、更穩定,限制通路位址是使用者模式的第一個特點。第二個特點就是需要多一層映射,如果線程要通路實體記憶體的話需要先映射到0x80000000以上,再經MMU通路實體記憶體位址。

WINCE的線程具有轉移性(參考API GetCallerProcess的說明,有一個很好的例子),當應用程式的線程調用API或者調用驅動程式接口函數時,該線程會轉移到gwes.exe、device.exe、filesys.exe等程序中執行,轉移是由WINCE核心操作的,它會修改線程的上下文,記錄線程的目前程序、調用者程序、擁有者程序三個值。

3、如果在定制核心的時候選擇了“Full Kernel Mode”,那麼在這個核心上運作的所有線程都處于核心模式,即使調用SetKMode(FALSE)後線程仍然具有核心模式的特點,能夠通路任何有效的虛拟位址。假設現有一個64MB RAM的WINCE産品,RAM映射從0x80000000到0x84000000,如果線程處于核心模式,它就直接可以通路這個範圍的虛拟位址:

在OnButton1()中編寫

DWORD oldMode = SetKMode(FALSE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

*piTemp = 12345;

在OnButton2()中編寫

DWORD oldMode = SetKMode(FALSE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

int iTemp = *piTemp;

先隻執行OnButton1()然後關閉程式,再重新開機程式然後執行OnButton2(),iTemp仍然等于12345。結果說明了兩點:核心模式線程可以直接通路0x80000000以上的有效虛拟位址;我們寫到RAM中的資料沒有丢失,說明虛拟位址有效。

如果在定制核心的時候沒有選擇“Full Kernel Mode”,那麼在這個核心上運作的所有線程都處于使用者模式。可以調用SetKMode(TRUE)使調用線程暫時處于核心模式,還是原來的假設環境,我再舉個例子:

在OnButton1()中編寫

DWORD oldMode = SetKMode(TRUE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

*piTemp = 12345;

在使用者模式下,如果不調用SetKMode(TRUE),那麼執行*piTemp = 12345一定會彈出對話框,提示位址通路非法,如果調用SetKMode(TRUE)就不會提示位址通路非法,而且在OnButton2()中仍然能得到12345這個值。

通過這兩個例子我相信讀者能夠完全了解兩種模式的差別了。

4、WINCE提供了兩個函數SetKMode和SetProcPermissions,其中SetKMode能夠把調用線程切換到核心模式,還可以切換回使用者模式。SetProcPermissions + GetCurrentPermissions添加目前程序通路權限給調用線程,SetProcPermissions (0xFFFFFFFF)能讓調用線程通路所有程序空間,但是調用線程仍然處于使用者模式。SetKMode和SetProcPermissions函數使得使用者模式的特點不那麼明晰。

如上所說一個應用程式的線程可能轉移到其它兩個程序位址空間中讀寫資料,而每一個線程在被建立的時候隻有通路建立它的程序位址空間的權限,是以驅動程式開發者必須在驅動程式讀寫資料前調用SetKMode或者SetProcPermissions增加調用此函數的線程通路其它程序空間的權限。如果一個應用程式的線程隻轉移到一個程序位址空間,一般為裝置管理器程序device.exe,這種情況下不必增加線程通路其它程序空間的權限,但如果驅動程式本身建立了一個線程,那還是要調用SetKMode或者SetProcPermissions增加新的線程通路其它程序的權限的,因為驅動程式建立線程時,目前程序為裝置管理器,是以新線程隻具有通路裝置管理器程序空間的權限,而不具備通路應用程式程序空間的權限。

5、可能一個編寫過簡單的流驅動的初學者會很疑惑,因為開發一個簡單的流驅動程式根本不需要調用這些函數,也沒有調用過MapPtrToProcess,那是因為如果标準流驅動接口函數的參數為指針(ReadFile、WriteFile、DeviceIoControl參數都有指針),WINCE核心會自動映射指針包含的位址,但僅此而已,其餘任何情況都要求開發者自行處理,比如流接口函數的參數是一個指向結構體的指針PA,而結構體中包括指針PB,PB指針就必須在流接口函數中映射,映射後才能通路,否則就會造成位址通路非法。是以結構體中每個指針都要映射。

為了讓讀者能了解其中的原因,我舉個例子:

假設裝置管理器被加載到Slot4,應用程式A被加載到Slot 8,A隻有一個主線程T,T開始執行,按照WINCE的規定,正獲得CPU的程序必須映射到Slot0,那麼在執行代碼的時候A的所有虛拟位址都被減去一個偏移值,也就是8×0x02000000,A調用DeviceIoControl,傳遞一個指向一個結構體的指針B,而這個結構體中包含一個指針C,指針C包含的位址假設為0x00030000,當執行DeviceIoControl時WINCE把裝置管理器的程序位址空間映射到Slot0,因為放在系統資料庫[HKLM/Drivers/BuiltIn]下的驅動程式是由裝置管理器加載的,自然驅動程式的代碼段被加載到裝置管理器程序空間,但是線程仍然是T,此時T的目前所在程序為裝置管理器(CurrentProcess),A變成了T的調用者程序(CallerProcess),T自動具有了通路調用者程序空間的權限。這時通路Slot0中的虛拟位址其實質就是通路裝置管理器的程序位址空間,要把位址加上一個偏移值,也就是4×0x02000000,是以DeviceIoControl通路指針C包含的位址時本應該加上8×0x02000000,卻加上4×0x02000000,結果位址并不是裝置管理器的合法區域,系統就會提示位址通路非法。而如果做了一個映射,指針C包含的位址就會被加一個正确的偏移值,使位址處于A的位址空間Slot 8中,T此時具有通路A程序空間的權限,通路到正确的虛拟位址當然會得到正确的資料了。

為什麼WINCE目錄下的例子用build+sysgen能夠編譯成EXE檔案,而我添加的例子就不能編譯呢?

如果這個例子是一個應用程式,那麼肯定包括代碼檔案(.h .c .cpp)和資源檔案(.rc和其它資源檔案),build工具根據source檔案内容把代碼檔案編譯成lib檔案,資源檔案編譯成.res檔案,sysgen工具根據makefile檔案内容将source檔案中列出的需要連結的各個庫檔案合并成一個EXE檔案。是以說關鍵在于makefile檔案,WINCE目錄下凡是能夠用build+sysgen編譯的都在makefile中有如何連結的設定,而我們添加的例子當然沒有在makefile中找到如何連結的設定,nmake工具就會提示不知道如何建立。

pcienum.exe幹什麼用的?

如果你要開發某一個PCI裝置的驅動程式,首先要知道這個PCI裝置的資訊(如VendorID、DeviceID、BaseClass、SubClass)和PCI總線的資訊。運作這個pcienum.exe就能得到相關資訊。pcienum.exe提供了源碼,位置/Public/Common/Oak/Drivers/Ceddk/Test/Pcienum。

wince下如何讓作業系統進入待機模式?又如何把它激活?

通過系統資料庫就可以設定,前提是你的驅動和硬體都支援。系統資料庫項參見标題為“GWES Suspend Time-outs”的幫助文檔。

[HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power]

     "BattPowerOff"=dword:300

     "ExtPowerOff"=dword:0

     "WakeupPowerOff"=dword:60

     "ScreenPowerOff"=dword:0

現有一個GPRS子產品,如何通過GPRS連接配接到Internet?

1、先在核心中加入WAN下面的幾個元件,如RAS/PPP、TAPI。WINCE采用unimodem驅動,是以不必擔心沒有Modem驅動的支援。

2、WINCE啟動後建立一個撥接上網,比如名稱叫“gprs1”,輸入使用者名、密碼、電話号碼。電話号碼不同,所采用的模式不一樣,例如“*99#”是GPRS模式,“17201”是普通的資料模式,速度差很多,價錢也差很多。

3、開始連接配接,連接配接過程會在對話框中顯示,直到顯示“連接配接成功”。

4、打開浏覽器或者自己開發的通訊軟體測試網絡連接配接情況。

5、關閉連接配接。

6、儲存[HKEY_CURRENT_USER/Comm/RasBook/gprs1]下的所有資料,添加到project.reg中,重新編譯後核心中就有了一個撥接上網“gprs1”。

7、調用RAS函數可以修改撥接上網“gprs1”的參數,如使用者名、密碼、電話号碼,但是不能修改硬體設定,如波特率、序列槽、資料位、停止位等。RAS函數還能夠撥号、挂斷。為了修改波特率可以多儲存幾個撥接上網,也可以直接調用TAPI開發撥号軟體,另外WINCE自帶的撥接上網是有源碼的,位置在/PUBLIC/COMMON/OAK/DRIVERS/NETSAMP/CONNMC。

采用基于HIVE的系統資料庫如何删除使用者儲存在系統資料庫中的資料,恢複到出廠時的系統資料庫?

使用者修改的資料儲存在user.hv檔案中,直接删除一定失敗,是以不能通過删除檔案實作恢複出廠設定。微軟考慮到了這個問題,在WINCE啟動過程中filesys.exe加載系統資料庫時會調用OEMIoControl函數并傳遞一個IOCTL,這個IOCTL在pkfuncs.h中定義如下:

#define   IOCTL_HAL_GET_HIVE_CLEAN_FLAG   CTL_CODE(FILE_DEVICE_HAL, 49, METHOD_BUFFERED, FILE_ANY_ACCESS)

filesys.exe會分别傳遞參數HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERS,如果傳回值為TRUE那麼filesys.exe清除原來的系統資料庫檔案,如果傳回值為FALSE那麼filesys.exe保留原來的系統資料庫檔案。預設WINCE并沒有實作這個IOCTL,是以OEM要删除系統資料庫檔案就必須先編寫這個IOCTL代碼。代碼的例子可參考标題為“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的幫助文檔。另外必須在ioctl.h和ioctl.c兩個檔案中編寫該代碼。在ioctl.c檔案中找到const OAL_IOCTL_HANDLER g_oalIoCtlTable[],添加IOCTL和對應的處理函數。要進一步了解這個全局數組,參見标題為“IOCTL Library”的幫助文檔。

如何在不删除必要元件的前提下減小核心檔案長度?

要減小核心檔案長度首先要在使用PB的定制核心向導中選擇自定義,也就是說對于每個元件都由自己來選擇,而不是選擇PB的标準配置。但減小核心檔案長度最有效最直接的辦法是縮小字型,尤其對于東亞字型,采用字型壓縮技術并且選擇合理的字庫檔案将明顯縮小檔案長度。

1、在定制核心時選擇AGFA AC3 Font Compression元件。SYSGEN變量為SYSGEN_AGFA_FONT。

2、參考标題為“East Asian Font Versions”的幫助文檔,從中選擇你需要的字庫檔案加到核心中,從文檔可以看出加AC3壓縮比不加壓縮在檔案長度方面差距很大。

如何得到WAV檔案播放的總時間?

1、直接讀取wav檔案頭資訊,從檔案起始位址偏移28個位元組長度為4個位元組儲存的是每秒鐘播放的位元組數,從檔案起始位址偏移40個位元組長度為4個位元組儲存的是聲音資料的總的位元組數,相除就是播放時間。

2、調用IGraphBuilder::RenderFile打開一個wav檔案,然後通過IGraphBuilder得到IMediaSeeking指針,再調用IMediaSeeking::GetDuration得到總的時間(結果要除以10000000),IMediaSeeking::GetCurrentPosition得到目前播放時間。

如何在Dialog-Based程式中加入menubar?

先調用CommandBar_Create再調用CommandBar_InsertMenubar。

請問MultiByteToWideChar與_T、L、TEXT的差別?

MultiByteToWideChar函數轉換的對象可以是常量也可以是變量。其它隻能轉換常量。_T和TEXT會根據目前系統是否定義_UNICODE宏來決定是否轉換,而L就是轉換成寬字元,當然也包括其他類型常量的轉換。

在用UBS線纜通過ActiveSync同步有效的情況下,如何插上USB線纜後WINCE自動與PC同步?

1、建立一個撥接上網,假設名稱為“usb1”,選擇連接配接類型為“直接連接配接”,并在連接配接裝置裡選擇通過USB線纜連接配接。

2、将系統資料庫[HKEY_CURRENT_USER/Comm/RasBook/usb1]下的資料添加到project.reg或者platform.reg中。

3、在[HKEY_CURRENT_USER/ControlPanel/Comm]下添加如下:

"AutoCnct"=dword:1   ///直接連接配接

"Cnct"="usb1"        ///連接配接名稱

4、重新編譯核心。為了節省編譯時間也可以在核心工程下搜尋*.reg檔案,将2、3步驟中的系統資料庫資料添加其中,然後直接make image。

如何通過程序句柄來獲得該程序的主視窗句柄?

好像沒有API能夠通過程序句柄直接獲得主視窗的句柄,因為并非每個應用程式都帶UI。但是可以反過來,先枚舉目前系統所有主視窗,然後根據每個視窗的句柄調用GetWindowThreadProcessId函數得到程序的ID,再調用OpenProcess得到程序句柄,與現有的程序句柄比較。

我做的顯示驅動DLL已經編譯成功了,但是在加載顯示驅動的過程中彈出話框,提示如下:

unhandled exception   in   gwes.exe   (0xc0000005 access violation)

提示的錯誤——位址通路非法,表明你的驅動程式代碼并沒有在讀寫資料前添加SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數讓線程能夠通路任何程序的位址空間。你可以調用 IsBadReadPtr和IsBadWritePtr函數檢測位址是否能夠合法通路。編寫和gwes有關的驅動程式應該首先調用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數,這是一個好習慣。

請問在嵌入式系統中如何設定GPRS拔号用的APN?

對一個撥接上網比如“我的連接配接”單擊滑鼠右鍵,在彈出的菜單中選擇“屬性”,然後單擊“配置”—“撥号選項”,在“附加設定”中添加AT指令如“+cgdcont=1,"ip","cmnet"”。“cmnet”位置即為APN。

WINCE的IP Phone功能如何?

WINCE的voip需要c-s-c結構,既需要伺服器的中轉,而skype采用第三代p2p技術就不需要中轉,但是在gprs下也做不到語音流暢。skype有pocket pc版本,但是無線方面需要wlan或者cdma。

三星ARM平台如何定義自己的中斷ID?

以S3C2410為例,在oalintr.h檔案中定義中斷ID,也稱SYSINTR,例如 #define SYSINTR_MYINT   (SYSINTR_FIRMWARE+20),最大值不能超過SYSINTR_FIRMWARE+23。然後在armint.c檔案中找到OEMInterruptHandler函數,用if (IntPendVal == INTSRC_XXX) 判斷目前發生的中斷源号,然後傳回SYSINTR_MYINT。核心分别調用OEMInterruptDisable(禁止目前中斷)、OEMInterruptDone(中斷處理結束)、OEMInterruptEnable(目前中斷有效)三個函數,參數都為中斷ID,在這三個函數中用 case SYSINTR_MYINT判斷目前要處理的中斷。

如何開發軟體從PC端複制檔案到基于WINCE的裝置?

調用RAPI(Remote Application Programming Interface)函數,此函數集由桌面計算機調用,由基于WINCE的裝置執行。一旦連接配接上就可以在桌面計算機端調用RAPI。通過系統資料庫還可以限制RAPI能夠通路目錄的範圍。具體參考RAPI和RDP(遠端桌面協定)。

請問如何對NandFlash分區、格式化?

你看看WINCE420/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp,在Eboot中先要調用BP_LowLevelFormat(

DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)再flash的一個區域建立空的MBR,然後連續兩次調用BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)函數來建立BINFS和FAT分區。建好後,将nk.bin燒入binfs分區中。

  要做個彈出對話框具有 always on top 屬性,如何實作?

調用SetWindowPos(.. , HWND_TOPMOST, ...., SWP_NOACTIVATE)。

s3c2410+WINCE下網絡PING一會就斷,如何解決?

原因在于中斷處理程式把已經産生的中斷标志清除掉了,這樣就丢失一次中斷。因為原驅動裡配置中斷為上升沿觸發,一次中斷丢失就導緻不會再産生中斷信号跳變,因為隻有在中斷服務中讀取了cs8900的 Interrupt status queue寄存器後,才會産生下一次中斷!解決辦法:

1、在cfw.c檔案中全局定義BOOL Inited = FALSE

2、修改OEMInterruptEnable()中case SYSINTR_ETHER: 下面的語句為:

if(Inited == FALSE)  

{  

s2410IOP->rEINTPEND = 0x200;  

s2410INT->rSRCPND = BIT_EINT8_23;  

if (s2410INT->rINTPND & BIT_EINT8_23)  

s2410INT->rINTPND = BIT_EINT8_23;  

Inited = TRUE;  

}  

s2410IOP->rEINTMASK &= ~0x200;  

s2410INT->rINTMSK &= ~BIT_EINT8_23;  

break;  

注:本解決辦法轉載于http://stoned.blogchina.com/stoned/3083045.html,非我本人研究成果。

已經搜尋到檔案,如何用CListBox以圖示形式顯示出來?

CListCtrl         ListCtrl;

CImageList       ImageList;

ImageList.Create(IDB_BITMAP, 48, 2, RGB(0,0,0));

ListCtrl.SetImageList(&ImageList, LVSIL_NORMAL);

ListCtrl.InsertItem(iListIndex, strItem, 1);  

如何改變控制台中電源屬性對話框的尺寸?  

1、需要修改對話框的尺寸是因為對話框是以資源方式加載的,不會根據目前系統顯示分辨率而自我調節尺寸。

2、安裝WINCE後有一些元件(feature)的資源檔案*.res就已經有了,如果你不改變,那麼build核心的時候PB隻是把這些.res複制到工程目錄下,然後與*.obj合并成EXE、DLL、CPL。是以修改了.rc檔案裡面的對話框尺寸後要重新編譯.rc檔案為.res檔案,然後再覆寫原來WINCE自帶的.res檔案。

3、改變對話框尺寸有兩種辦法:一種方法是更改系統字型字号,系統字型的字号變化會影響對話框的尺寸,但是缺點是所有系統字型有關的UI都會改變。另一種是在.rc檔案中調整對話框尺寸,然後編譯成.res檔案,再将.res複制到對應的語言目錄裡,比如目錄名為0804(中文),再執行Rebuild指令重新編譯核心,或者執行sysgen+build。在研究中我發現.res檔案雖然能夠直接用EVC打開、修改、儲存,但是和其它Obj連結成EXE、DLL、CPL後并不能運作,是以還是建議讀者用CE自帶的rc工具編譯最好。讀者可在PB的指令行中鍵入“rc /?”了解rc.exe工具的用途和參數。

使用EVC build之後連接配接模拟器的時候,提示download file等了一會又出現download failed?

一般這樣的問題從下面幾個步驟解決:

1、如果之前能啟動模拟器而現在不能,那麼先clean然後重新開機計算機再build。

2、如果開發的主機為WINXP+SP2,可能存在與EVC模拟器不相容的情況,檢查C:/boot.ini,将/noexecute=optin改為/execute=optin。

3、檢查你的模拟器是否能運作,假設你正用的SDK名稱為MYSDK,單擊菜單tools—configure platform manager,選擇MYSDK—MYSDK emulator,再單擊properties—test,看看模拟器是否能夠啟動,如果能啟動那問題就不大。

4、單擊菜單build—update remote output files,看看模拟器是否能夠啟動。

5、如果上述辦法均不行,關閉EVC然後重建立立一個新的工程,編譯,看看模拟器是否能夠啟動,如果能啟動說明原來工程出了問題,最好恢複原工程的備份。

如何設定能夠自動撥号、禁止自動撥号?

在[HKEY_LOCAL_MACHINE/Comm/Autodial]下是自動撥号的系統資料庫設定。

Enabled=DWORD:1           ///是否能夠自動撥号

FailRetryWaitMS=DWORD     ///如果失敗再次撥号的等待時間

RasEntryName1= REG_SZ      ///自動撥号采用的撥接上網名稱

更多細節請參考标題為“Auto Dial Registry Settings”的幫助文檔。

請問如何修改字形緩存的容量?

[HKEY_LOCAL_MACHINE/System/GDI/GLYPHCACHE]

"limit"=dword:0400

如何得到從WINCE啟動開始到現在的時間?

調用API GetTickCount,得到的值為32位整數,機關為毫秒。

如何調用WINCE的軟鍵盤?

調用API SipShowIM(SIPF_ON),前提是核心加入了軟鍵盤元件。

基于HIVE的系統資料庫,如何在系統關閉前儲存系統資料庫的資料到檔案system.hv?

調用API RegFlushKey函數。

使用VirtualAlloc和VirtualCopy的時候需要注意哪些事項?

1、VirtualAlloc的作用是申請虛拟位址空間,這肯定不是最終的目的,最終目的可能是申請實體記憶體、映射寄存器、送出檔案等。沒有一個目的會在意虛拟位址空間的位置,是以盡量傳遞參數1為0,也就是讓WINCE自動配置設定虛拟位址空間。VirtualAlloc配置設定位址空間實際上是以64KB為機關,是以要指定申請的虛拟空間的首位址的話,參數1應該為64KB的整數倍,申請的長度也應該為64KB的整數倍,即使你不需要那麼大。

2、VirtualCopy的主要作用是映射實體位址空間,如果參數2為實體位址,那麼最後一個參數要添加PAGE_PHYSICAL,參數2必須是256的整數倍。如果參數2為虛拟位址(0x80000000以上),那麼最後一個參數就不要添加PAGE_PHYSICAL,WINCE核心會根據這個虛拟位址找到對應的實體位址。

驅動程式和應用程式之間傳遞資料時何時調用MapPtrToProcess?

因為裝置管理器負責加載驅動程式DLL,這意味着當應用程式調用驅動程式接口函數的時候,WINCE核心會将調用驅動程式接口函數的線程轉移到裝置管理器的程序空間然後執行具體的驅動程式代碼,應用程式和裝置管理器處于兩個程序空間,這就造成裝置管理器無法通路應用程式傳遞的指針(虛拟位址),是以當我們在應用程式中傳遞指針給流驅動程式接口函數時,WINCE核心從中作了一個位址映射,例如ReadFile、WriteFile、DeviceIoControl函數的參數凡是指針都經過了映射才傳遞給驅動程式,是以很多驅動程式開發者并不了解其中的奧秘就可以程式設計了。但是如果參數是一個指向一個結構體的指針,而結構體裡包括一個或多個指針,那麼WINCE核心并不負責映射,是以就需要開發者在驅動程式接口函數中調用API函數MapPtrToProcess來映射位址。例如:pPointer_retval = MapPtrToProcess(pPointer, GetCallerProcess());  

如何判斷可插拔的裝置是否存在?

1、通過查找系統資料庫的值。凡是由API ActivateDeviceEx加載的驅動程式都在[HKEY_LOCAL_MACHINE/Drivers/Active]鍵下有注冊鍵,通過查找“name”或者其它鍵值就能夠找到。裝置管理器就調用這個API。如果是PCI裝置,在系統資料庫[HLM/Drivers/BuiltIn/PCI/Instance]下查找關鍵字,例如[HLM/Drivers/BuiltIn/PCI/Instance/WaveDev1],說明音頻驅動已經加載。

2、調用驅動程式接口函數,根據傳回值或者執行結果來判斷。

如何做到通過序列槽過來的一個信号啟動自己開發的應用程式?

建立一個線程負責等待序列槽過來的信号,調用API SetCommMask設定要等待的信号種類,具體可以等待的信号種類參見參數2的說明。然後再調用API WaitCommEvent函數等待這個信号,接收之後再調用API CreateProcess啟動應用程式。

在WINCE中如何隻能啟動應用程式的一個執行個體?

常用的兩種辦法:

1、如果應用程式執行個體建立了視窗,可通過API FindWindow函數通過視窗類名和視窗标題名稱來查找,前提是系統内不會出現視窗名稱重複的情況。

2、應用程式初始化的時候建立一個事件或互斥等核心對象,因為核心對象是由核心建立,名稱在系統内唯一。

能不能自己編輯一個數字簽名檔案導入到手機上,這樣就可以用這個簽名簽自己的程式了?

WINCE的核心簽名機制的用途是限制非法的可執行子產品EXE、DLL等在裝置上運作。要求核心的加載子產品用公鑰驗證請求加載的EXE、DLL的簽名是否合法,而這個公鑰是在定制核心的時候加進去的,是以除核心的定制者以外的人無法修改這個驗證機制。

我按照版主的文章《加密WINCE系統》裡操作,提示錯誤如下:

Error 80090016 during CryptSignHash 1!

Error signing hash

這是因為傳遞了無效的鑰容器名稱,使CryptoAPI調用失敗。應該在使用signfile工具之前建立一個鑰容器,在桌面Windows中調用API CryptAcquireContext建立一個指定名稱的鑰容器,接着再建立一個簽名密鑰對,這時再使用signfile工具就可以了。我在文章裡寫成-kfulinlin是因為我建立鑰容器的時候沒有指定名稱,系統就采用目前登入的使用者名為容器名。

編譯錯誤:CVTRES : fatal error CVT1102: out of memory; 42 bytes required ?

多數情況下出現這種錯誤是因EVC的bug而起,應該在安裝EVC之後就立刻安裝EVC的SP更新檔。另外為了避開BUG,使用EVC程式設計應該養成一些習慣,比如定期備份工程所有檔案,每次編譯時采用Clean + Rebuild All,正調試時不要關閉模拟器等等。

在WINCE下是否能夠得到某一程序使用的實體記憶體總量?

目前沒發現有這樣一個API能夠得到指定程序使用的實體記憶體總量。隻有GlobalMemoryStatus能夠得到整個系統使用的實體記憶體總量。

應用程式如何控制lcd的亮度?如何獲得電池的電量?

從常見的平台如Geode、三星ARM系列來看,的确在驅動方面沒有統一的控制LCD或者其它種類螢幕亮度的接口函數,是以隻能根據具體平台提供的接口來做。從幫助文檔來看微軟的帶有DirectDraw功能的顯示驅動程式的确有标準的增加亮度的接口函數,關于背景光參見标題為“Enabling a Backlight”的幫助文檔。

獲得電池電量有标準的接口函數GetSystemPowerStatusEx,前提是驅動程式和硬體都要支援。

WINCE的socket函數好像不支援發送/接收逾時?

是的,最早版本的WINCE支援選項SO_RCVTIMEO、SO_SNDTIMEO,後來卻不支援了。

WINCE下如何設定視窗最大化和最小化?

WINCE的幫助文檔在介紹API ShowWindow函數的參數時指出SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, SW_SHOWDEFAULT, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWMINNOACTIVE都不被支援,但實際上并不完全是這樣,具體來說:

SW_MAXIMIZE             比原來視窗大,但不是最大化

SW_MINIMIZE              編譯成功,但是不起作用

SW_SHOWMAXIMIZED      最大化

SW_SHOWMINIMIZED       編譯出錯

SW_RESTORE               能恢複

SW_SHOWDEFAULT         編譯出錯

SW_SHOWMINNOACTIVE    編譯出錯

SW_HIDE                   能夠隐藏

如何用程式調用控制台的觸摸屏校對程式?  

兩種辦法:

1、調用API TouchCalibrate函數

2、調用CreateProcess,參數1為L"//windows//ctlpnl.exe",參數2為L"cplmain.cpl,9"。

如何獲得U盤或者其它類型的存儲器總容量和剩餘可用容量?

調用API GetStoreInfo得到扇區數、每扇區位元組數,相乘即是總容量。調用API GetDiskFreeSpaceEx得到剩餘可用容量。

三星2440頭檔案定義#define IIC_BASE 0xB1400000 // 54000000,datasheet是54000000,那麼怎麼轉成0xB1400000?

實體位址映射方法分為兩種,一種靜态映射另一種為動态映射。在OEMAddressTable中定義了實體位址與虛拟位址的映射關系屬于靜态映射,用VirtualCopy映射屬于動态映射,采用哪種辦法都可以。問題中提到的屬于靜态映射,2440的BSP在map.a檔案中定義了IIC控制寄存器的實體起始位址和對應的虛拟位址如下:

DCD 0x91400000, 0x54000000, 1 ;

在OEMAddressTable中定義的虛拟位址範圍在0x8000 0000—0x9FFF FFFF,這部分可緩存,适合核心程式和應用程式使用,同時WINCE核心在0xA000 0000—0xBFFF FFFF中映射了另一份,指向了同樣的實體位址,這部分不可緩存,适合驅動程式使用。三星ARM處理器帶有L1級高速緩存,可緩存會提高執行效率。對于特殊的裝置寄存器适合映射到不可緩存的虛拟位址。

當驅動程式調用VirtualCopy對0xB1400000位址讀寫時,WINCE自動将這個位址減去0x2000 0000,也就是0x91400000,對應的實體位址就是0x54000000,也就是IIC控制寄存器的實體起始位址。

基于RAM的系統資料庫如何儲存資料?

調用API RegCopyFile備份系統資料庫。調用API RegRestoreFile恢複系統資料庫,然後調用KernelIoControl熱啟動使恢複生效。

如何隐藏和顯示winCE下标準外殼的工作列?

HANDLE   hTaskBar = FindWindow(L"HHTaskBar", NULL);  

ShowWindow(hTaskBar, SW_HIDE);  

ShowWindow(hTaskBar, SW_SHOWNORMAL);  

如果能讓WINCE的IE浏覽器播放flash動畫?

播放flash需要Macromedia Flash Player SDK,參見http://www.adobe.com/products/flashplayer_sdk/。這和real player相似,都需要WINCE平台的SDK,都需要申請。

WINCE下核心模式和使用者模式有什麼差別?

為了使讀者能夠詳細了解WINCE的位址映射原理還有兩種模式,在這裡我分幾個部分說明:

1、WINCE核心nk.exe的任務是管理作業系統核心功能。按照OEMAddressTable的映射要求,所有實體位址都映射到0x80000000以上,是以對于核心程式nk.exe和核心模式下的線程來說,隻要通路0x80000000以上的有效虛拟位址經MMU就能夠通路實體位址,無需再映射是核心模式的一個特點。核心模式的第二個特點是沒有位址通路限制,核心模式線程可以通路任何有效虛拟位址,所謂有效虛拟位址是指有實際事物對應。

2、使用者模式線程隻能通路0x80000000以下的虛拟位址空間,WINCE6.0之前版本的核心為每個程序劃分32MB的位址空間,在不調用特殊函數的情況下不能互相通路,這樣的設計使得WINCE系統更安全、更穩定,限制通路位址是使用者模式的第一個特點。第二個特點就是需要多一層映射,如果線程要通路實體記憶體的話需要先映射到0x80000000以上,再經MMU通路實體記憶體位址。

WINCE的線程具有轉移性(參考API GetCallerProcess的說明,有一個很好的例子),當應用程式的線程調用API或者調用驅動程式接口函數時,該線程會轉移到gwes.exe、device.exe、filesys.exe等程序中執行,轉移是由WINCE核心操作的,它會修改線程的上下文,記錄線程的目前程序、調用者程序、擁有者程序三個值。

3、如果在定制核心的時候選擇了“Full Kernel Mode”,那麼在這個核心上運作的所有線程都處于核心模式,即使調用SetKMode(FALSE)後線程仍然具有核心模式的特點,能夠通路任何有效的虛拟位址。假設現有一個64MB RAM的WINCE産品,RAM映射從0x80000000到0x84000000,如果線程處于核心模式,它就直接可以通路這個範圍的虛拟位址:

在OnButton1()中編寫

DWORD oldMode = SetKMode(FALSE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

*piTemp = 12345;

在OnButton2()中編寫

DWORD oldMode = SetKMode(FALSE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

int iTemp = *piTemp;

先隻執行OnButton1()然後關閉程式,再重新開機程式然後執行OnButton2(),iTemp仍然等于12345。結果說明了兩點:核心模式線程可以直接通路0x80000000以上的有效虛拟位址;我們寫到RAM中的資料沒有丢失,說明虛拟位址有效。

如果在定制核心的時候沒有選擇“Full Kernel Mode”,那麼在這個核心上運作的所有線程都處于使用者模式。可以調用SetKMode(TRUE)使調用線程暫時處于核心模式,還是原來的假設環境,我再舉個例子:

在OnButton1()中編寫

DWORD oldMode = SetKMode(TRUE);

volatile int *piTemp = (volatile int*)(0x20000000+0x84000000-0x00019000); ///或者(0x84000000-0x00019000)

*piTemp = 12345;

在使用者模式下,如果不調用SetKMode(TRUE),那麼執行*piTemp = 12345一定會彈出對話框,提示位址通路非法,如果調用SetKMode(TRUE)就不會提示位址通路非法,而且在OnButton2()中仍然能得到12345這個值。

通過這兩個例子我相信讀者能夠完全了解兩種模式的差別了。

4、WINCE提供了兩個函數SetKMode和SetProcPermissions,其中SetKMode能夠把調用線程切換到核心模式,還可以切換回使用者模式。SetProcPermissions + GetCurrentPermissions添加目前程序通路權限給調用線程,SetProcPermissions (0xFFFFFFFF)能讓調用線程通路所有程序空間,但是調用線程仍然處于使用者模式。SetKMode和SetProcPermissions函數使得使用者模式的特點不那麼明晰。

如上所說一個應用程式的線程可能轉移到其它兩個程序位址空間中讀寫資料,而每一個線程在被建立的時候隻有通路建立它的程序位址空間的權限,是以驅動程式開發者必須在驅動程式讀寫資料前調用SetKMode或者SetProcPermissions增加調用此函數的線程通路其它程序空間的權限。如果一個應用程式的線程隻轉移到一個程序位址空間,一般為裝置管理器程序device.exe,這種情況下不必增加線程通路其它程序空間的權限,但如果驅動程式本身建立了一個線程,那還是要調用SetKMode或者SetProcPermissions增加新的線程通路其它程序的權限的,因為驅動程式建立線程時,目前程序為裝置管理器,是以新線程隻具有通路裝置管理器程序空間的權限,而不具備通路應用程式程序空間的權限。

5、可能一個編寫過簡單的流驅動的初學者會很疑惑,因為開發一個簡單的流驅動程式根本不需要調用這些函數,也沒有調用過MapPtrToProcess,那是因為如果标準流驅動接口函數的參數為指針(ReadFile、WriteFile、DeviceIoControl參數都有指針),WINCE核心會自動映射指針包含的位址,但僅此而已,其餘任何情況都要求開發者自行處理,比如流接口函數的參數是一個指向結構體的指針PA,而結構體中包括指針PB,PB指針就必須在流接口函數中映射,映射後才能通路,否則就會造成位址通路非法。是以結構體中每個指針都要映射。

為了讓讀者能了解其中的原因,我舉個例子:

假設裝置管理器被加載到Slot4,應用程式A被加載到Slot 8,A隻有一個主線程T,T開始執行,按照WINCE的規定,正獲得CPU的程序必須映射到Slot0,那麼在執行代碼的時候A的所有虛拟位址都被減去一個偏移值,也就是8×0x02000000,A調用DeviceIoControl,傳遞一個指向一個結構體的指針B,而這個結構體中包含一個指針C,指針C包含的位址假設為0x00030000,當執行DeviceIoControl時WINCE把裝置管理器的程序位址空間映射到Slot0,因為放在系統資料庫[HKLM/Drivers/BuiltIn]下的驅動程式是由裝置管理器加載的,自然驅動程式的代碼段被加載到裝置管理器程序空間,但是線程仍然是T,此時T的目前所在程序為裝置管理器(CurrentProcess),A變成了T的調用者程序(CallerProcess),T自動具有了通路調用者程序空間的權限。這時通路Slot0中的虛拟位址其實質就是通路裝置管理器的程序位址空間,要把位址加上一個偏移值,也就是4×0x02000000,是以DeviceIoControl通路指針C包含的位址時本應該加上8×0x02000000,卻加上4×0x02000000,結果位址并不是裝置管理器的合法區域,系統就會提示位址通路非法。而如果做了一個映射,指針C包含的位址就會被加一個正确的偏移值,使位址處于A的位址空間Slot 8中,T此時具有通路A程序空間的權限,通路到正确的虛拟位址當然會得到正确的資料了。

為什麼WINCE目錄下的例子用build+sysgen能夠編譯成EXE檔案,而我添加的例子就不能編譯呢?

如果這個例子是一個應用程式,那麼肯定包括代碼檔案(.h .c .cpp)和資源檔案(.rc和其它資源檔案),build工具根據source檔案内容把代碼檔案編譯成lib檔案,資源檔案編譯成.res檔案,sysgen工具根據makefile檔案内容将source檔案中列出的需要連結的各個庫檔案合并成一個EXE檔案。是以說關鍵在于makefile檔案,WINCE目錄下凡是能夠用build+sysgen編譯的都在makefile中有如何連結的設定,而我們添加的例子當然沒有在makefile中找到如何連結的設定,nmake工具就會提示不知道如何建立。

pcienum.exe幹什麼用的?

如果你要開發某一個PCI裝置的驅動程式,首先要知道這個PCI裝置的資訊(如VendorID、DeviceID、BaseClass、SubClass)和PCI總線的資訊。運作這個pcienum.exe就能得到相關資訊。pcienum.exe提供了源碼,位置/Public/Common/Oak/Drivers/Ceddk/Test/Pcienum。

wince下如何讓作業系統進入待機模式?又如何把它激活?

通過系統資料庫就可以設定,前提是你的驅動和硬體都支援。系統資料庫項參見标題為“GWES Suspend Time-outs”的幫助文檔。

[HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power]

     "BattPowerOff"=dword:300

     "ExtPowerOff"=dword:0

     "WakeupPowerOff"=dword:60

     "ScreenPowerOff"=dword:0

現有一個GPRS子產品,如何通過GPRS連接配接到Internet?

1、先在核心中加入WAN下面的幾個元件,如RAS/PPP、TAPI。WINCE采用unimodem驅動,是以不必擔心沒有Modem驅動的支援。

2、WINCE啟動後建立一個撥接上網,比如名稱叫“gprs1”,輸入使用者名、密碼、電話号碼。電話号碼不同,所采用的模式不一樣,例如“*99#”是GPRS模式,“17201”是普通的資料模式,速度差很多,價錢也差很多。

3、開始連接配接,連接配接過程會在對話框中顯示,直到顯示“連接配接成功”。

4、打開浏覽器或者自己開發的通訊軟體測試網絡連接配接情況。

5、關閉連接配接。

6、儲存[HKEY_CURRENT_USER/Comm/RasBook/gprs1]下的所有資料,添加到project.reg中,重新編譯後核心中就有了一個撥接上網“gprs1”。

7、調用RAS函數可以修改撥接上網“gprs1”的參數,如使用者名、密碼、電話号碼,但是不能修改硬體設定,如波特率、序列槽、資料位、停止位等。RAS函數還能夠撥号、挂斷。為了修改波特率可以多儲存幾個撥接上網,也可以直接調用TAPI開發撥号軟體,另外WINCE自帶的撥接上網是有源碼的,位置在/PUBLIC/COMMON/OAK/DRIVERS/NETSAMP/CONNMC。

采用基于HIVE的系統資料庫如何删除使用者儲存在系統資料庫中的資料,恢複到出廠時的系統資料庫?

使用者修改的資料儲存在user.hv檔案中,直接删除一定失敗,是以不能通過删除檔案實作恢複出廠設定。微軟考慮到了這個問題,在WINCE啟動過程中filesys.exe加載系統資料庫時會調用OEMIoControl函數并傳遞一個IOCTL,這個IOCTL在pkfuncs.h中定義如下:

#define   IOCTL_HAL_GET_HIVE_CLEAN_FLAG   CTL_CODE(FILE_DEVICE_HAL, 49, METHOD_BUFFERED, FILE_ANY_ACCESS)

filesys.exe會分别傳遞參數HIVECLEANFLAG_SYSTEM和HIVECLEANFLAG_USERS,如果傳回值為TRUE那麼filesys.exe清除原來的系統資料庫檔案,如果傳回值為FALSE那麼filesys.exe保留原來的系統資料庫檔案。預設WINCE并沒有實作這個IOCTL,是以OEM要删除系統資料庫檔案就必須先編寫這個IOCTL代碼。代碼的例子可參考标題為“IOCTL_HAL_GET_HIVE_CLEAN_FLAG”的幫助文檔。另外必須在ioctl.h和ioctl.c兩個檔案中編寫該代碼。在ioctl.c檔案中找到const OAL_IOCTL_HANDLER g_oalIoCtlTable[],添加IOCTL和對應的處理函數。要進一步了解這個全局數組,參見标題為“IOCTL Library”的幫助文檔。

如何在不删除必要元件的前提下減小核心檔案長度?

要減小核心檔案長度首先要在使用PB的定制核心向導中選擇自定義,也就是說對于每個元件都由自己來選擇,而不是選擇PB的标準配置。但減小核心檔案長度最有效最直接的辦法是縮小字型,尤其對于東亞字型,采用字型壓縮技術并且選擇合理的字庫檔案将明顯縮小檔案長度。

1、在定制核心時選擇AGFA AC3 Font Compression元件。SYSGEN變量為SYSGEN_AGFA_FONT。

2、參考标題為“East Asian Font Versions”的幫助文檔,從中選擇你需要的字庫檔案加到核心中,從文檔可以看出加AC3壓縮比不加壓縮在檔案長度方面差距很大。

如何得到WAV檔案播放的總時間?

1、直接讀取wav檔案頭資訊,從檔案起始位址偏移28個位元組長度為4個位元組儲存的是每秒鐘播放的位元組數,從檔案起始位址偏移40個位元組長度為4個位元組儲存的是聲音資料的總的位元組數,相除就是播放時間。

2、調用IGraphBuilder::RenderFile打開一個wav檔案,然後通過IGraphBuilder得到IMediaSeeking指針,再調用IMediaSeeking::GetDuration得到總的時間(結果要除以10000000),IMediaSeeking::GetCurrentPosition得到目前播放時間。

如何在Dialog-Based程式中加入menubar?

先調用CommandBar_Create再調用CommandBar_InsertMenubar。

請問MultiByteToWideChar與_T、L、TEXT的差別?

MultiByteToWideChar函數轉換的對象可以是常量也可以是變量。其它隻能轉換常量。_T和TEXT會根據目前系統是否定義_UNICODE宏來決定是否轉換,而L就是轉換成寬字元,當然也包括其他類型常量的轉換。

在用UBS線纜通過ActiveSync同步有效的情況下,如何插上USB線纜後WINCE自動與PC同步?

1、建立一個撥接上網,假設名稱為“usb1”,選擇連接配接類型為“直接連接配接”,并在連接配接裝置裡選擇通過USB線纜連接配接。

2、将系統資料庫[HKEY_CURRENT_USER/Comm/RasBook/usb1]下的資料添加到project.reg或者platform.reg中。

3、在[HKEY_CURRENT_USER/ControlPanel/Comm]下添加如下:

"AutoCnct"=dword:1   ///直接連接配接

"Cnct"="usb1"        ///連接配接名稱

4、重新編譯核心。為了節省編譯時間也可以在核心工程下搜尋*.reg檔案,将2、3步驟中的系統資料庫資料添加其中,然後直接make image。

如何通過程序句柄來獲得該程序的主視窗句柄?

好像沒有API能夠通過程序句柄直接獲得主視窗的句柄,因為并非每個應用程式都帶UI。但是可以反過來,先枚舉目前系統所有主視窗,然後根據每個視窗的句柄調用GetWindowThreadProcessId函數得到程序的ID,再調用OpenProcess得到程序句柄,與現有的程序句柄比較。

我做的顯示驅動DLL已經編譯成功了,但是在加載顯示驅動的過程中彈出話框,提示如下:

unhandled exception   in   gwes.exe   (0xc0000005 access violation)

提示的錯誤——位址通路非法,表明你的驅動程式代碼并沒有在讀寫資料前添加SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數讓線程能夠通路任何程序的位址空間。你可以調用 IsBadReadPtr和IsBadWritePtr函數檢測位址是否能夠合法通路。編寫和gwes有關的驅動程式應該首先調用SetKMode(TRUE)或者SetProcPermissions(0xFFFFFFFF)函數,這是一個好習慣。

請問在嵌入式系統中如何設定GPRS拔号用的APN?

對一個撥接上網比如“我的連接配接”單擊滑鼠右鍵,在彈出的菜單中選擇“屬性”,然後單擊“配置”—“撥号選項”,在“附加設定”中添加AT指令如“+cgdcont=1,"ip","cmnet"”。“cmnet”位置即為APN。

WINCE的IP Phone功能如何?

WINCE的voip需要c-s-c結構,既需要伺服器的中轉,而skype采用第三代p2p技術就不需要中轉,但是在gprs下也做不到語音流暢。skype有pocket pc版本,但是無線方面需要wlan或者cdma。

三星ARM平台如何定義自己的中斷ID?

以S3C2410為例,在oalintr.h檔案中定義中斷ID,也稱SYSINTR,例如 #define SYSINTR_MYINT   (SYSINTR_FIRMWARE+20),最大值不能超過SYSINTR_FIRMWARE+23。然後在armint.c檔案中找到OEMInterruptHandler函數,用if (IntPendVal == INTSRC_XXX) 判斷目前發生的中斷源号,然後傳回SYSINTR_MYINT。核心分别調用OEMInterruptDisable(禁止目前中斷)、OEMInterruptDone(中斷處理結束)、OEMInterruptEnable(目前中斷有效)三個函數,參數都為中斷ID,在這三個函數中用 case SYSINTR_MYINT判斷目前要處理的中斷。

如何開發軟體從PC端複制檔案到基于WINCE的裝置?

調用RAPI(Remote Application Programming Interface)函數,此函數集由桌面計算機調用,由基于WINCE的裝置執行。一旦連接配接上就可以在桌面計算機端調用RAPI。通過系統資料庫還可以限制RAPI能夠通路目錄的範圍。具體參考RAPI和RDP(遠端桌面協定)。

請問如何對NandFlash分區、格式化?

你看看WINCE420/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/BOOTPART/bootpart.cpp,在Eboot中先要調用BP_LowLevelFormat(

DWORD dwStartBlock, DWORD dwNumBlocks, DWORD dwFlags)再flash的一個區域建立空的MBR,然後連續兩次調用BP_OpenPartition(DWORD dwStartSector, DWORD dwNumSectors, DWORD dwPartType, BOOL fActive, DWORD dwCreationFlags)函數來建立BINFS和FAT分區。建好後,将nk.bin燒入binfs分區中。

  要做個彈出對話框具有 always on top 屬性,如何實作?

調用SetWindowPos(.. , HWND_TOPMOST, ...., SWP_NOACTIVATE)。

s3c2410+WINCE下網絡PING一會就斷,如何解決?

原因在于中斷處理程式把已經産生的中斷标志清除掉了,這樣就丢失一次中斷。因為原驅動裡配置中斷為上升沿觸發,一次中斷丢失就導緻不會再産生中斷信号跳變,因為隻有在中斷服務中讀取了cs8900的 Interrupt status queue寄存器後,才會産生下一次中斷!解決辦法:

1、在cfw.c檔案中全局定義BOOL Inited = FALSE

2、修改OEMInterruptEnable()中case SYSINTR_ETHER: 下面的語句為:

if(Inited == FALSE)  

{  

s2410IOP->rEINTPEND = 0x200;  

s2410INT->rSRCPND = BIT_EINT8_23;  

if (s2410INT->rINTPND & BIT_EINT8_23)  

s2410INT->rINTPND = BIT_EINT8_23;  

Inited = TRUE;  

}  

s2410IOP->rEINTMASK &= ~0x200;  

s2410INT->rINTMSK &= ~BIT_EINT8_23;  

break;  

注:本解決辦法轉載于http://stoned.blogchina.com/stoned/3083045.html,非我本人研究成果。

已經搜尋到檔案,如何用CListBox以圖示形式顯示出來?

CListCtrl         ListCtrl;

CImageList       ImageList;

ImageList.Create(IDB_BITMAP, 48, 2, RGB(0,0,0));

ListCtrl.SetImageList(&ImageList, LVSIL_NORMAL);

ListCtrl.InsertItem(iListIndex, strItem, 1);  

如何改變控制台中電源屬性對話框的尺寸?  

1、需要修改對話框的尺寸是因為對話框是以資源方式加載的,不會根據目前系統顯示分辨率而自我調節尺寸。

2、安裝WINCE後有一些元件(feature)的資源檔案*.res就已經有了,如果你不改變,那麼build核心的時候PB隻是把這些.res複制到工程目錄下,然後與*.obj合并成EXE、DLL、CPL。是以修改了.rc檔案裡面的對話框尺寸後要重新編譯.rc檔案為.res檔案,然後再覆寫原來WINCE自帶的.res檔案。

3、改變對話框尺寸有兩種辦法:一種方法是更改系統字型字号,系統字型的字号變化會影響對話框的尺寸,但是缺點是所有系統字型有關的UI都會改變。另一種是在.rc檔案中調整對話框尺寸,然後編譯成.res檔案,再将.res複制到對應的語言目錄裡,比如目錄名為0804(中文),再執行Rebuild指令重新編譯核心,或者執行sysgen+build。在研究中我發現.res檔案雖然能夠直接用EVC打開、修改、儲存,但是和其它Obj連結成EXE、DLL、CPL後并不能運作,是以還是建議讀者用CE自帶的rc工具編譯最好。讀者可在PB的指令行中鍵入“rc /?”了解rc.exe工具的用途和參數。

使用EVC build之後連接配接模拟器的時候,提示download file等了一會又出現download failed?

一般這樣的問題從下面幾個步驟解決:

1、如果之前能啟動模拟器而現在不能,那麼先clean然後重新開機計算機再build。

2、如果開發的主機為WINXP+SP2,可能存在與EVC模拟器不相容的情況,檢查C:/boot.ini,将/noexecute=optin改為/execute=optin。

3、檢查你的模拟器是否能運作,假設你正用的SDK名稱為MYSDK,單擊菜單tools—configure platform manager,選擇MYSDK—MYSDK emulator,再單擊properties—test,看看模拟器是否能夠啟動,如果能啟動那問題就不大。

4、單擊菜單build—update remote output files,看看模拟器是否能夠啟動。

5、如果上述辦法均不行,關閉EVC然後重建立立一個新的工程,編譯,看看模拟器是否能夠啟動,如果能啟動說明原來工程出了問題,最好恢複原工程的備份。

如何設定能夠自動撥号、禁止自動撥号?

在[HKEY_LOCAL_MACHINE/Comm/Autodial]下是自動撥号的系統資料庫設定。

Enabled=DWORD:1           ///是否能夠自動撥号

FailRetryWaitMS=DWORD     ///如果失敗再次撥号的等待時間

RasEntryName1= REG_SZ      ///自動撥号采用的撥接上網名稱

更多細節請參考标題為“Auto Dial Registry Settings”的幫助文檔。

繼續閱讀