Windows mobile/WinCE RAPI教程

http://blog.csdn.net/jinhaijian/article/details/2678751


1.RAPI概述

Windows CE中有了RAPI以後,PC應用程序就能遠程管理Windows CE設備。導出函數將處理文件系統、註冊表和數據庫以及用於查詢系統配置的函數。大多數RAPI是Windows CE API函數中的副本,只有少數的函數擴展了API。

   RAPI函數被列在Windows CE API 參考中,但是將有PC應用程序來調用而不是由Widows CE應用程序調用。在函數的名稱都有前綴Ce來與他們的Window CE的副本進行區分;例如:Windows CE中的函數GetStoreInformation將在該函數的RAPI版本中稱爲CeGetStoreInformation。在Windows CE應用程序將不會調用RAPI函數。

2.初始化RAPI

調用RAPI函數之前,你必須調用函數CeRapiInit或CeRapiInitEx來初始化RAPI庫。這兩個函數的區別在於CeRapiInit會阻塞(等待與Windows CE設備連接成功),而CeRapiInitEx不會等待連接成功。

這兩個函數的原形。

HRESULT CeRapiIni(void);

HRESULT CeRapiInitEx(RAPIINIT *pRapiInit);

typedef struct _RAPIINIT 

{

    DWORD cbSize;

    HANDLE heRapiInit;

    STDAPI hrRapiInit;

} RAPIINIT;

在調用CeRapiInitEx之前,必須填寫cbSize字段。

3.結束RAPI會話

結束所有必要的RAPI調用時,你應該調用下面這個函數來進行清除:

HRESULT CeRapiUninit(void);

這個函數很好地關閉與遠程設備地RAPI通信。如果RAPI會話沒有被初始化

CeRapiUninit將返回E_FAIL

4.預定義的RAPI函數

RAPI服務包括很多預定義的RAPI函數,這些在連接時,PC端複製Windows CE函數。因此,正如GetStoreInformation將把對象存儲哭得大小和空間返回到Windows CE程序,CeGetStoreInformation將把關於連接的Windows CE設備的相同信息返回到基於PC的應用程序。

4.1 RAPI系統信息函數

大多數函數都是Windows CE函數的副本,除了CeGetPassWord和CeRapiInvoke

系統信息函數

函數

描述

CeGetSystemInfo

返回當前系統信息

CeGetSystemMetrics

獲取Windows元素的尺寸和系統設置

CeGetVersionEx

獲取當前運行的操作系統版本的擴展信息

CeGetSystemPowerStatusEx

獲取電池狀態

CeGlobalMemoryStatus

獲取系統物理內存和虛擬內存信息

CeGetStoreInformation

獲取存儲器信息並填入STORE_INFORMATION結構

4.2 RAPI文件和目錄管理函數

下面的列表顯示的是RAPI文件管理函數,這個列表說明幾乎所有可用於Windows CE應用程序的文件函數都可以用於基於PC的程序。

函數

描述

CeCopyFile

複製文件

CeCreateDirectory

創建目錄

CeCreateFile

創建,打開文件、管道、通訊資源、磁盤設備或者控制檯。返回一個句柄用來訪問對象。

CeDeleteFile

刪除文件

CeFindAllFiles

從指定的Windows CE目錄中獲取所有文件和目錄的信息,並且複製到一個包含CE_FIND_DATA結構的數組中

CeFindFirstFile

在目錄中查找匹配給定文件名的一個文件

CeFindClose

關閉指定的查找句柄,CeFindFirstFileCeFindNextFile 函數用這個句柄查找文件

CeFindNextFile

從上一次訪問的CeFindFirstFile繼續查找文件

CeGetFileAttributes

返回指定文件或目錄的屬性

CeGetFileSize

獲取指定文件的字節大小

CeGetFileTime

獲取文件創建日期時間,最後訪問日期時間和最後修改日期時間

CeMoveFile

移動(重命名)一個文件或者目錄

CeReadFile

從文件指針處讀取文件數據

CeWriteFile

從文件指針處寫入文件數據

表內有一個新函數CeFindAllFiles,它對Windows CE 應用程序不可用。

原型:

BOOL CeFindAllFiles (LPCWSTR szPath, DWORD dwFlags,

                     LPDWORD lpdwFoundCount,

                     LPLPCE_FIND_DATA ppFindDataArray);

設計CeFindAllFiles 是爲了增強性能,只需調用它一次就能返回給定目錄的所有文件,而不需要使用CeFindFirstFile和CeFindNextFile來重複RAPI的調用。

具體參數參考SDK

4.3 RAPI數據庫函數

下面的列表中顯示的是RAPI數據庫函數。這些函數模擬了在Windows CE中找到的擴展數據庫API

數據庫函數

CeCreateDatabase 

CeOpenDatabaseEx 

CeCreateDatabaseEx 

CeReadRecordProps 

CeDeleteDatabase 

CeReadRecordPropsEx 

CeDeleteDatabaseEx 

CeSeekDatabase 

CeDeleteRecord 

CeSetDatabaseInfo 

CeFindFirstDatabase 

CeSetDatabaseInfoEx 

CeFindFirstDatabaseEx 

CeWriteRecordProps 

CeFindNextDatabase 

CeMountDBVol 

CeFindNextDatabaseEx 

CeUnmountDBVol 

CeOidGetInfo 

CeEnumDBVolumes 

CeOidGetInfoEx 

CeFindAllDatabases 

CeOpenDatabase 

 

幾乎所有的數據庫函數都有Windows CE副本。唯一的例外的是新函數CeCreateDatabase

CeFindAllFiles一樣,設計這個函數也是爲了增強性能。

函數原型:

BOOL CeFindAllDatabases (DWORD dwDbaseType, WORD wFlags,

                         LPWORD cFindData,

                         LPLPCEDB_FIND_DATA ppFindData);

具體參數參考SDK

RAPI註冊表管理函數

這些函數與它們的Windows CE副本的工作方式一樣,但是,要記住所有的字符串都是Unicode格式。

4.4 其他的API函數

可以說Windows CE上的功能,通過RAPI都能實現,我在這裏不可能不一一列舉了。

電量顯示函數

STDAPI_(BOOL) CeGetSystemPowerStatusEx

(

  PSYSTEM_POWER_STATUS_EX pstatus

  BOOL fUpdate 

);

創建進程,就是可以打開CE上的應用程序

CeCreateProcess

窗體管理函數

窗體管理函數

CeGetWindow 

CeGetWindowText 

CeGetWindowLong 

CeGetClassName 

5Pget例子程序

編寫RAPI應用程序需要加RAPI.h 和RAPI.lib

在EVC4.0下設置方法:

[Tools]/[Options]/[Directories]進行設置他們的目錄。

在VSS2005下的設置方法:

[Tools]/[Options]/[Projects and Solutions][VC++ Directories ]

下面時.h文件lib的存放目錄。

C:/Program Files/Windows CE Tools/wce420/POCKET PC 2003/Activesync/Inc

C:/Program Files/Windows CE Tools/wce420/POCKET PC 2003/Activesync/Lib

C:/Program Files/Windows CE Tools/wce500/Windows Mobile 5.0 Pocket PC SDK/Activesync/Inc

C:/Program Files/Windows CE Tools/wce500/Windows Mobile 5.0 Pocket PC SDK/Activesync/Lib

這個程序是SDK的例子代碼

具體路徑

PPC2003 和 WM5 PPC

C:/Program Files/Windows CE Tools/wce420/POCKET PC 2003/Samples/Win32/Rapi/Pget

C:/Program Files/Windows CE Tools/wce500/Windows Mobile 5.0 Pocket PC SDK/Samples/CPP/Win32/Rapi/Pget

WM5 SP

C:/Program Files/Windows CE Tools/wce500/Windows Mobile 5.0 Smartphone SDK/Samples/CPP/Win32/Rapi/Pget

這個程序是從小機器上覆制文件到PC的控制檯應用程序。

代碼部分就不具體寫出了。只說明一下流程

複製文件的命令是;

Pget  <CE源文件>   <PC目的文件>

1. CeRapiInit()進行初始化。

2. CeFindFirstFile()來判斷CE端是否存在該文件。

3. CeCreateFile()來打開CE端的文件。

4. CreateFile()來創建PC端的複製到的文件。

5. CeReadFile()把CE的文件讀到緩存區裏。

6. WriteFile()把緩存區裏的數據保存到PC端。

7. CeCloseHandle()和CloseHandle()關閉CE和PC上的文件句柄。

8. 最後調用CeRapiUninit(); 進行清楚。

下面的這張截圖就是把CE端的“/battery.png” 複製到 PC上的“c:/test.png”文件中。


6.自定義RAPI函數

無論RAPI接口支持多少函數,總會出現一些應用程序需要的但RAPI接口沒有提供的函數。RAPI爲PC提供一種方法去調用 Windows CE上的用戶定義的函數。

你可以使用兩種方法來調用用戶定義的函數。一種是“阻塞模式”,另一種是“流模式”

下面這段是它的英文介紹。

You can invoke a user-defined RAPI function in one of two ways. The first way is called block mode. In block mode, you make a call to the RAPI remote invocation function, the function makes the call to a specified function in a specified DLL, the DLL function does its thing and returns, and the RAPI function then returns to the calling PC program with the output. The second method is called stream mode. In this mode, the RAPI call to the function returns immediately, but a connection is maintained between the calling PC application and the Windows CE DLL–based function. This method allows information to be fed back to the PC on an ongoing basis.

6.1 使用RAPI調用自定義函數。

CeRapiInvoke將允許我們調用遠程設備中的任何API函數!不過不是直接調用,仍然需要對遠程API進行一些“包裝”。

CeRapiInvoke的原型如下:

STDAPI_( HRESULT ) CeRapiInvoke(
    LPCWSTR pDllPath,                      // 包含API的Dll文件完整路徑
    LPCWSTR pFunctionName,         // 要調用的函數名
    DWORD cbInput,                           // 函數輸入緩衝區大小
    BYTE * pInput,                               // 函數輸入緩衝區指針
    DWORD * pcbOutput,                  // 函數輸出緩衝區大小
    BYTE ** ppOutput,                       // 函數輸出緩衝區指針
    IRAPIStream ** ppIRAPIStream,  // 指定使用阻塞模式或流模式
    DWORD dwReserved);                // 保留

下面這段英文是它的詳細介紹

The first parameter to CeRapiInvoke is the name of the DLL on the Windows CE device that contains the function you want to call. The name must be in Unicode but can include a path. If no path is specified, the DLL is assumed to be in the /windows directory on the device. The second parameter is the name of the function to be called. The function name must be in Unicode and is case specific.

The next two parameters, cbInput and pInput, should be set to the buffer containing the data and the size of that data to be sent to the Windows CE–based function. The input buffer should be allocated in the local heap of the application. When you call CeRapiInvoke, this buffer will be freed by the function. The pcbOutput and ppOutput parameters are both pointers—the first a pointer to a DWORD that receives the size of the data returned and the second a pointer to a PBYTE variable that receives the pointer to the buffer containing the data returned by the Windows CE function. The buffer returned by CeRapiInvoke is allocated by the function in your local heap. You're responsible for freeing this buffer.

6.2 編寫RAPI服務器函數(CE端的DLL中的函數)

你不能調用Windows CE DLL 中的所有函數。函數結構必須符合下面的函數原型

STDAPI INT FuncName (DWORD cbInput, BYTE *pInput, DWORD *pcbOutput,

                     BYTE **ppOutput, IRAPIStream *pIRAPIStream);

這些參數與CeRapiInvoke非常匹配。

6.3 阻塞模式的例子代碼

CE端的DLL程序。

RapiServ.c

//===================================================================

#include <windows.h>                 // For all that Windows stuff

   

// The following ensures that the function will be exported from the DLL

// and that any C++ compilers used won't mangle the name.

#ifdef __cplusplus

extern "C" {

#endif

__declspec (dllexport) INT RAPIGetDiskSize (DWORD, BYTE *, DWORD *,

                                            BYTE **, PVOID);

#ifdef __cplusplus

}

#endif

//===================================================================

// DllMain - DLL initialization entry point

BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD dwReason,

                     LPVOID lpvReserved) {

    return TRUE;

}

//===================================================================

// RAPIGetDiskSize - Returns the disk size and free space.  Called from

// PC application using RAPI.

//

INT RAPIGetDiskSize (DWORD cbInput, BYTE *pInput, DWORD *pcbOutput,

                     BYTE **ppOutput, PVOID reserved) {

    PDWORD pdwLocal;

    LPTSTR pPtr;

    DWORD i;

    int rc = 0;

    ULARGE_INTEGER lnFree, lnTotal;

   

    *pcbOutput = 0;            // Zero output bytes for now.

if (!pInput) return –1;    // Make sure there is an input buffer.

    // 判斷是否已零結束的字符串

    pPtr = (LPTSTR)pInput;

    for (i = 0; i < cbInput / 2; i++)

        if (!*pPtr++)

            break;

    // 如果是非零結束或字符串長度等於零返回-2

if ((i >= cbInput / 2) || (i == 0)) 

{

        LocalFree (pInput);

        return -2;

    }

   

    // 調用GetDiskFreeSpaceEx函數

    if (GetDiskFreeSpaceEx ((LPTSTR)pInput, NULL, &lnTotal, &lnFree)) {

   

        // Allocate memory for the return buffer.

        pdwLocal = (PDWORD) LocalAlloc (LPTR, 2 * sizeof (DWORD));

        if (pdwLocal) {

            // Copy data from function to output buffer.

            pdwLocal[0] = lnTotal.LowPart;

            pdwLocal[1] = lnFree.LowPart;

            // Specify size and buffer.

            *pcbOutput = 2 * sizeof (DWORD);

            *ppOutput = (PBYTE)pdwLocal;

        } else

            rc = GetLastError();

    } else

        rc = GetLastError();

    // The function is responsible for freeing the input buffer.

    LocalFree (pInput);

    return rc;

}

__declspec (dllexport) INT RAPIGetDiskSize

告訴鏈接程序已導出的山數,這樣 外部模塊就可以直接調用這個函數。

  RAPIGetDiskSize的輸入緩衝區被用來將目錄名稱傳遞到DLL,而輸出緩衝區將返回傳遞的目錄的總的磁盤空間和自由空間。輸入和輸出緩衝區的格式完全由你決定,然而,輸入緩衝區應使用 LocalAlloc來分配,這樣RAPI庫可以在它使用完後釋放它。

   

   在PC端,調用堵塞模式RAPI服務器函數應像下面這樣。

//-----------------------------------------------------------------------

// MyCeGetDiskFreeSpaceEx - Homegrown implementation of a RAPI

// GetDiskFreeSpace function

//

BOOL MyCeGetDiskFreeSpaceEx (LPWSTR pszDir, PDWORD pdwTotal,

                             PDWORD pdwFree) {

    HRESULT hr;

    DWORD dwIn, dwOut;

    LPBYTE pInput;

    LPWSTR pPtr;

    PDWORD pOut;

    BOOL bRC = FALSE;

   

    // Get length of Unicode string.

    for (dwIn = 2, pPtr = pszDir; *pPtr++; dwIn+=2);

    // Allocate buffer for input.

    pInput = LocalAlloc (LPTR, dwIn);

    if (!pInput)

        return FALSE;

    // Copy directory name into input buffer.

    memcpy (pInput, pszDir, dwIn);

   

    // Call function on Windows CE device.

    hr = CeRapiInvoke (L"RapiServ", L"RAPIGetDiskSize", dwIn,

                       pInput, &dwOut, (PBYTE *)&pOut, NULL, 0);

   

    // If successful, return total and free values.

    if (hr == 0) {

        *pdwTotal = pOut[0];

        *pdwFree = pOut[1];

        bRC = TRUE;

    }

    LocalFree (pOut);

    return bRC;

}

這個函數封裝拉對CeRapiInvoke的調用,這樣該調用看起來就像另一個Windows CE RAPI調用。當函數返回時,由返回代碼指出調用的 成功或失敗。CeRapiInvoke將釋放傳遞給它的輸入緩衝區。然後從輸入緩衝區複製這些數據,並且那個緩衝區將用LocalFree()來釋放。

6.4 流模式

流模式RAPI調用與阻塞模式不同,在流模式中,初始化RAPI調用將創建PC應用程序與Windows CE設備上的服務器程序之間的鏈接。當在流模式中調用CeRapiInvoke時,這個函數將立即返回。你此時使用IRAPIStream接口來與服務器DLL通信。你可以使用一個指針訪問這個接口,該指針由CeRapiInvoke調用在由ppIRAPIStream指向的變量中返回。

Following is a call to CeRapiInvoke that establishes a stream connection and then writes and reads back 10 bytes from the remote server DLL.

DWORD dwIn, dwOut, cbBytes;

IRAPIStream *pIRAPIStream;

BYTE bBuff[BUFF_SIZE];

PBYTE pOut;

HRESULT hr;

   

// RAPI call

hr = CeRapiInvoke (L"ServDLL", L"RAPIRmtFunc", dwIn, bBuff,

                   &dwOut, &pOut, &pIRAPIStream, 0);

if (hr == S_OK) 

{

    // Write 10 bytes.

    pIRAPIStream->Write (bBuff, 10, &cbBytes);

    // Read data from server.

    pIRAPIStream->Read (bBuff, 10, &cbBytes);

}

pIRAPIStream->Release ();

When establishing a stream connection, you can still use the input buffer to pass initial data down to the remote server.
From then on, you should use the Read and Write methods of IRAPIStream to communicate with the server. 
When you&apos;re finished with the IRAPIStream interface, you must call Release to release the int

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章