Các ví dụ và hướng dẫn sử dụng RAPI trong lập trình Windows CE

Giới thiệu về RAPI

Sau khi Windows CE hỗ trợ RAPI, các ứng dụng trên máy tính để bàn có thể quản lý từ xa thiết bị Windows CE. Các hàm được xuất ra xử lý hệ thống tệp tin, registry và cơ sở dữ liệu cũng như các hàm truy vấn cấu hình hệ thống. Hầu hết các hàm RAPI đều là bản sao của các hàm API Windows CE, chỉ một số ít hàm mở rộng thêm chức năng.

Các hàm RAPI được liệt kê trong tài liệu tham khảo API Windows CE nhưng sẽ do ứng dụng máy tính để bàn gọi chứ không phải do ứng dụng Windows CE gọi. Tên các hàm đều có tiền tố Ce để phân biệt với phiên bản Windows CE tương ứng; ví dụ: hàm GetStoreInformation trong Windows CE sẽ được gọi là CeGetStoreInformation trong phiên bản RAPI.

Ví dụ thực tế: Sao chép tệp tin đến thiết bị

Chúng ta sẽ xây dựng một lớp bao quanh RAPI để thực hiện chức năng sao chép tệp tin. Đầu tiên là phần khai báo lớp:

Tập tin tiêu đề: RapiWrapper.h

#ifndef AFX_RAPIWRAPPER_H__INCLUDED_
#define AFX_RAPIWRAPPER_H__INCLUDED_

#define CHUNK_SIZE 8192

typedef struct _REMOTE_API_INIT
{
    DWORD dwStructureSize;
    HANDLE hEventHandle;
    HRESULT hResultValue;
} REMOTE_API_INIT;

class CRapiWrapper
{
public:
    HMODULE hModuleHandle;

    typedef HANDLE (WINAPI * CreateFileFunc)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
    typedef BOOL (WINAPI * WriteFileFunc)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
    typedef BOOL (WINAPI * CloseHandleFunc)(HANDLE);
    typedef HANDLE (WINAPI * FindFirstFileFunc)(LPCWSTR, LPCE_FIND_DATA);
    typedef DWORD (WINAPI * GetFileSizeFunc)(HANDLE, LPDWORD);
    typedef BOOL (WINAPI * ReadFileFunc)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
    typedef BOOL (WINAPI * FindNextFileFunc)(HANDLE, LPCE_FIND_DATA);
    typedef BOOL (WINAPI * CreateDirectoryFunc)(LPCWSTR, LPSECURITY_ATTRIBUTES);
    typedef BOOL (WINAPI * CopyFileFunc)(LPCWSTR, LPCWSTR, BOOL);
    typedef DWORD (WINAPI * GetLastErrorFunc)();
    typedef HRESULT (WINAPI * GetErrorFunc)();

    CreateFileFunc pCreateFile;
    WriteFileFunc pWriteFile;
    CloseHandleFunc pCloseHandle;
    FindFirstFileFunc pFindFirstFile;
    GetFileSizeFunc pGetFileSize;
    ReadFileFunc pReadFile;
    FindNextFileFunc pFindNextFile;
    CreateDirectoryFunc pCreateDirectory;
    CopyFileFunc pCopyFile;
    GetLastErrorFunc pGetLastError;
    GetErrorFunc pGetError;

    typedef HRESULT (WINAPI * InitExFunc)(REMOTE_API_INIT*);
    InitExFunc pInitApi;

    FARPROC pUninitApi;

    bool m_bInitialized;

    bool ConnectToDevice();
    bool TransferFileToTarget(CString sSourcePath, CString sTargetPath);
    bool RetrieveFileFromTarget(CString sTargetPath, CString sLocalPath);
    bool SetupRemoteApi();
    
    CRapiWrapper();
    virtual ~CRapiWrapper();
};

#endif

Tập tin triển khai: RapiWrapper.cpp

#include "stdafx.h"
#include "RapiWrapper.h"

CRapiWrapper::CRapiWrapper()
{
    m_bInitialized = false;
}

CRapiWrapper::~CRapiWrapper()
{
}

bool CRapiWrapper::SetupRemoteApi()
{
    TCHAR szDllLocation[MAX_PATH + 20];
    GetSystemDirectory(szDllLocation, MAX_PATH);
    CString sDllFullName(szDllLocation);
    sDllFullName += "\\rapi.dll";

    hModuleHandle = LoadLibrary(sDllFullName);
    if (hModuleHandle)
    {
        pInitApi = (InitExFunc)GetProcAddress(hModuleHandle, "CeRapiInitEx");
        pUninitApi = GetProcAddress(hModuleHandle, "CeRapiUninit");
        pCreateFile = (CreateFileFunc)GetProcAddress(hModuleHandle, "CeCreateFileW");
        pWriteFile = (WriteFileFunc)GetProcAddress(hModuleHandle, "CeWriteFile");
        pCloseHandle = (CloseHandleFunc)GetProcAddress(hModuleHandle, "CeCloseHandle");
        pFindFirstFile = (FindFirstFileFunc)GetProcAddress(hModuleHandle, "CeFindFirstFileW");
        pGetFileSize = (GetFileSizeFunc)GetProcAddress(hModuleHandle, "CeGetFileSize");
        pReadFile = (ReadFileFunc)GetProcAddress(hModuleHandle, "CeReadFile");
        pFindNextFile = (FindNextFileFunc)GetProcAddress(hModuleHandle, "CeFindNextFileW");
        pCreateDirectory = (CreateDirectoryFunc)GetProcAddress(hModuleHandle, "CeCreateDirectoryW");
        pCopyFile = (CopyFileFunc)GetProcAddress(hModuleHandle, "CeCopyFileW");
        pGetLastError = (GetLastErrorFunc)GetProcAddress(hModuleHandle, "CeGetLastError");
        pGetError = (GetErrorFunc)GetProcAddress(hModuleHandle, "CeRapiGetError");

        return true;
    }
    else
    {
        if (hModuleHandle)
            FreeLibrary(hModuleHandle);
        return false;
    }
}

bool CRapiWrapper::RetrieveFileFromTarget(CString sTargetPath, CString sLocalPath)
{
    HANDLE hTargetFile;
    DWORD dwFileSizeLow = 0;
    int nChunkCount = 0;
    DWORD dwReadBytes = 0;
    char buffer[CHUNK_SIZE];
    int nIndex = 0;
    DWORD dwTotalSize = 0;

    CFile localFile;
    BSTR bstrPath = sTargetPath.AllocSysString();
    
    hTargetFile = pCreateFile(bstrPath, GENERIC_READ, 0, NULL,
                              OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hTargetFile)
    {
        return false;
    }

    dwTotalSize = pGetFileSize(hTargetFile, &dwFileSizeLow);
    dwTotalSize = dwTotalSize + (dwFileSizeLow << 32);

    nChunkCount = dwTotalSize / CHUNK_SIZE;

    localFile.Open(sLocalPath, CFile::modeReadWrite | CFile::typeBinary | CFile::modeCreate);

    for (nIndex = 0; nIndex < nChunkCount; nIndex++)
    {
        memset(buffer, 0, sizeof(char) * CHUNK_SIZE);
        pReadFile(hTargetFile, buffer, CHUNK_SIZE, &dwReadBytes, NULL);
        localFile.Write(buffer, CHUNK_SIZE);
    }

    if (0 != dwTotalSize % CHUNK_SIZE)
    {
        memset(buffer, 0, sizeof(char) * CHUNK_SIZE);
        pReadFile(hTargetFile, buffer, dwTotalSize % CHUNK_SIZE, &dwReadBytes, NULL);
        localFile.Write(buffer, dwTotalSize % CHUNK_SIZE);
    }

    pCloseHandle(hTargetFile);
    localFile.Close();
    SysFreeString(bstrPath);
    return true;
}

bool CRapiWrapper::TransferFileToTarget(CString sSourcePath, CString sTargetPath)
{
    CFile sourceFile;
    HANDLE hTargetHandle;
    char tempBuffer[CHUNK_SIZE];
    DWORD dwWrittenBytes = 0;
    int nSourceLength = 0;
    int nBlockCount = 0;
    int nIndex = 0;

    sourceFile.Open(sSourcePath, CFile::modeRead | CFile::typeBinary);
    nSourceLength = sourceFile.GetLength();
    nBlockCount = nSourceLength / CHUNK_SIZE;

    BSTR bstrDest = sTargetPath.AllocSysString();

    hTargetHandle = pCreateFile(bstrDest, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                                OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == hTargetHandle)
    {
        SysFreeString(bstrDest);
        return false;
    }

    for (nIndex = 0; nIndex < nBlockCount; nIndex++)
    {
        memset(tempBuffer, 0, sizeof(char) * CHUNK_SIZE);
        if (sourceFile.Read(tempBuffer, CHUNK_SIZE) >= 1)
        {
            pWriteFile(hTargetHandle, tempBuffer, CHUNK_SIZE, &dwWrittenBytes, NULL);
        }
    }

    if (0 != nSourceLength % CHUNK_SIZE)
    {
        memset(tempBuffer, 0, sizeof(char) * CHUNK_SIZE);
        if (sourceFile.Read(tempBuffer, nSourceLength % CHUNK_SIZE) >= 1)
        {
            pWriteFile(hTargetHandle, tempBuffer, nSourceLength % CHUNK_SIZE, &dwWrittenBytes, NULL);
        }
    }

    pCloseHandle(hTargetHandle);
    sourceFile.Close();
    SysFreeString(bstrDest);
    return true;
}

bool CRapiWrapper::ConnectToDevice()
{
    REMOTE_API_INIT initParams;
    DWORD dwWaitStatus = 0;
    HRESULT hInitResult = S_FALSE;

    if (!m_bInitialized)
    {
        initParams.dwStructureSize = sizeof(REMOTE_API_INIT);
        initParams.hResultValue = S_FALSE;
        initParams.hEventHandle = NULL;

        hInitResult = pInitApi(&initParams);
        dwWaitStatus = WaitForSingleObject(initParams.hEventHandle, 3000);

        if (hInitResult == S_OK && initParams.hResultValue == S_OK &&
            dwWaitStatus != WAIT_TIMEOUT)
        {
            m_bInitialized = true;
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return true;
    }
}

Hướng dẫn sử dụng

Để sử dụng RAPI, bạn cần thực hiện các bước sau:

1. Khởi tạo RAPI

Trước khi gọi bất kỳ hàm RAPI nào, bạn phải gọi hàm CeRapiInit hoặc CeRapiInitEx để khởi tạo thư viện RAPI. Sự khác biệt giữa hai hàm này là CeRapiInit sẽ chặn chương trình cho đến khi kết nối với thiết bị Windows CE thành công, trong khi CeRapiInitEx không chờ đợi.

2. Kết thúc phiên làm việc RAPI

Khi hoàn tất các cuộc gọi RAPI cần thiết, bạn nên gọi hàm CeRapiUninit để dọn dẹp. Hàm này đóng kết nối RAPI với thiết bị từ xa một cách hiệu quả.

3. Các hàm RAPI phổ biến

Một số hàm quản lý tệp tin và thư mục:

  • CeCopyFile: Sao chép tệp tin
  • CeCreateDirectory: Tạo thư mục
  • CeCreateFile: Tạo hoặc mở tệp tin, ống dẫn, tài nguyên truyền thông
  • CeDeleteFile: Xóa tệp tin
  • CeFindFirstFile: Tìm kiếm tệp tin đầu tiên phù hợp với tên đã cho
  • CeGetFileSize: Lấy kích thước tệp tin tính bằng byte
  • CeReadFile: Đọc dữ liệu từ vị trí con trỏ tệp tin
  • CeWriteFile: Ghi dữ liệu tại vị trí con trỏ tệp tin

Ngoài ra còn có các hàm lấy thông tin hệ thống như CeGetSystemInfo, CeGetVersionEx, CeGlobalMemoryStatus, v.v.

Thẻ: windows-ce rapi remote-api embedded-systems mobile-development

Đăng vào ngày 19 tháng 6 lúc 06:04