How To Use CeRapiInvoke()
View products that this article applies to.
Article ID : 299891
Last Review : August 30, 2004
Revision : 1.0
This article was previously published under Q299891
On This Page
SUMMARY
MORE INFORMATION
Using CeRapiInvoke() in Block Mode
Using CeRapiInvoke in Stream Mode
Building Modules That Use RAPI
APPLIES TO
SUMMARY
The remote API (RAPI) CeRapiInvoke() enables you to invoke your routines in the Windows CE device from a desktop application. The routines are implemented in a DLL and the DLL must export those routines. You can use CeRapiInvoke() in two ways: in block mode or in stream mode. This article demonstrates how to use CeRapiInvoke() in both ways.
Back to the top
MORE INFORMATION
The following is a prototype for CeRapiInvoke in RAPI.dll to be used by an application running on the desktop.
HRESULT CeRapiInvoke(LPCWSTR pDllPath, LPCWSTR pFunctionName,
DWORD cbInput, BYTE *pInput, DWORD *pcbOutput,
BYTE **ppOutput, IRAPIStream **ppIRAPIStream,
DWORD dwReserved)
CeRapiInvoke() will be called in block mode if IRAPIStream** is NULL. Otherwise it will be called in the stream mode.
The following is a prototype DLL routine that runs on the device: int CallMyFunction(DWORD cbInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
Back to the top
Using CeRapiInvoke() in Block Mode
In the block mode, calls to CeRapiInvoke() return only after the DLL routine has executed and returned. The ppOutput pointer must be allocated by the DLL through the use of LocalAlloc() and the desktop application must call LocalFree() on the same [what?]. In block mode, ppIRAPIStream must be set to NULL. The value returned by the DLL routine will be returned by CeRapiInvoke.
The following sample code demonstrates use of CeRapiInvoke() in the block mode by calling a method in the DLL that resides in the \Windows folder of the device. The DLL method returns the available physical memory in the device in kilobytes. // test console application to call in blocking mode
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "rapi.h"
int main(int argc, char* argv[])
{
DWORD cbOut;
BYTE* pOut;
HRESULT hr;
//Initialize Windows CE RAPI
hr = CeRapiInit();
//Invoke CallMyFunction routine in MyRapi DLL in the \Windows directory.
hr = CeRapiInvoke(L"MyRapi", L"CallMyFunction",
0, NULL, &cbOut, &pOut, NULL, 0);
if(cbOut)
printf("Your device got %s KB of Physical Memory available", pOut);
else
printf("No memory available in the device");
//Uninitialize Windows CE RAPI
hr = CeRapiUninit();
//Free the DLL allocated memory.
if(pOut)
LocalFree(pOut);
return 0;
}
The following code shows implementation of the CallMyFunction routine inside MyRapi.dll: #include <windows.h>
#include "rapi.h"
extern "C"
{
__declspec(dllexport) int CallMyFunction(DWORD cbInput,
BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream);
}
int CallMyFunction(DWORD cbInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
{
MEMORYSTATUS structMemStatus;
DWORD dwMemAvailPhys;
char szFree[10];
//Initialize buffer to all NULLs
ZeroMemory(szFree, 10);
GlobalMemoryStatus(&structMemStatus);
dwMemAvailPhys = structMemStatus.dwAvailPhys;
sprintf(szFree, "%d", dwMemAvailPhys/1024);
//Provide extra char for NULL
*ppOutput = (BYTE*)LocalAlloc(LPTR, strlen(szFree)+1);
if(*ppOutput)
{
//Copy along with NULL
strncpy((char*)*ppOutput, szFree, strlen(szFree)+1);
*pcbOutput = strlen(szFree) + 1;
}
else
*pcbOutput = 0;
return 0;
}
Back to the top
Using CeRapiInvoke in Stream Mode
The following code demonstrates how to use CeRapiInvoke() in stream mode. It communicates with the device through IRAPIStream interface and displays the available physical memory in an Edit control. This simple application will loop indefinitely when reading data from the RAPI stream until a key is pressed. Once a key is pressed, the application exits the loop and writes to the RAPI stream, notifying code in MyRapi.dll that it is exiting. // test console application to call in stream mode
//
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include "rapi.h"
//Serious Error conditions and execution paths are not
//considered in this example. Purpose is just to demonstrate
//the usage of CeRapiInvoke() in Stream mode.
struct MY_MEM_STRUCT
{
DWORD dwPhysMemAvail;
DWORD dwPhysTotal;
};
int main(int argc, char* argv[])
{
IRAPIStream *pStream;
DWORD cbOut;
DWORD dwLength, cbBytesRead;
MY_MEM_STRUCT structMyDeviceMem;
HRESULT hr = CeRapiInit();
hr = CeRapiInvoke(L"MyRapi", L"CallMyFunction", NULL,
NULL, &cbOut, NULL, &pStream, 0);
_tprintf(_T("Press any key to exit\n"));
fflush(stdin);
while(!kbhit())
{
cbBytesRead = 0;
//First read the length information.
hr = pStream->Read(&dwLength, sizeof(DWORD), &cbBytesRead);
if(FAILED(hr) || (dwLength != sizeof(MY_MEM_STRUCT)))
{
_tprintf(_T("Error while reading from stream"));
break;
}
//Read the bytes into the structure.
hr = pStream->Read(&structMyDeviceMem, dwLength,
&cbBytesRead);
if(FAILED(hr))
{
break;
}
if(cbBytesRead > 0)
{
_tprintf(_T("\rTotal Physical Memory = %d KB, Available Memory = %d KB."),
structMyDeviceMem.dwPhysTotal, structMyDeviceMem.dwPhysMemAvail);
}
Sleep(2000);
}
fflush(stdin);
DWORD dwDataWrite = 1 ;
DWORD cbWritten;
hr = pStream->Write(&dwDataWrite, sizeof(dwDataWrite), &cbWritten);
hr = CeRapiUninit();
return 0;
}
On the device a separate thread is dedicated for reading the notification from the desktop. The read operation will block the thread until it reads the notification from the stream. The main thread writes to the stream every two seconds. struct MY_MEM_STRUCT
{
DWORD dwPhysMemAvail;
DWORD dwPhysTotal;
};
UINT MyThreadProc(LPVOID pParam);
CRITICAL_SECTION g_structCriticalSect;
BOOL g_fContinue = TRUE;
HRESULT SendToMyRapiStream(IRAPIStream* pStream,
void* pWriteStruct, int nDataWrite)
{
HRESULT hr;
DWORD cbWritten, dwWrite;
dwWrite = sizeof(nDataWrite);
//Write the length information first
hr = pStream->Write(&nDataWrite, dwWrite, &cbWritten);
if(FAILED(hr))
return E_FAIL;
//Write the structure into the stream
hr = pStream->Write(pWriteStruct, nDataWrite, &cbWritten);
if(FAILED(hr))
return E_FAIL;
return S_OK;
}
int CallMyFunction(DWORD dwInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
{
MEMORYSTATUS structMemStatus;
BOOL bContinue = TRUE;
MY_MEM_STRUCT structMyMem;
HRESULT hr;
DWORD dwThreadId;
InitializeCriticalSection(&g_structCriticalSect);
HANDLE hThread = CreateThread(NULL, NULL,
(LPTHREAD_START_ROUTINE)MyThreadProc, pStream,
NULL, &dwThreadId);
while(1)
{
EnterCriticalSection(&g_structCriticalSect);
if(g_fContinue == FALSE)
{
LeaveCriticalSection(&g_structCriticalSect);
break;
}
LeaveCriticalSection(&g_structCriticalSect);
GlobalMemoryStatus(&structMemStatus);
structMyMem.dwPhysMemAvail = structMemStatus.dwAvailPhys / 1024;
structMyMem.dwPhysTotal = structMemStatus.dwTotalPhys / 1024;
hr = SendToMyRapiStream(pStream, &structMyMem, sizeof(structMyMem));
if(FAILED(hr))
{
break;
}
/*wait for 2 seconds. if WaitForSingleObject() comes out
in less than 2 seconds then client has requested to stop
sending the data or an error has occured.*/
if(WaitForSingleObject(hThread, 2000) != WAIT_TIMEOUT)
break;
}
//Make sure the other thread has terminated
WaitForSingleObject(hThread, 5000);
DeleteCriticalSection(&g_structCriticalSect);
g_fContinue = FALSE;
return 0;
}
UINT MyThreadProc(LPVOID pParam)
{
DWORD dwInput, cbReadBytes;
IRAPIStream* pStream = (IRAPIStream*)pParam;
HRESULT hrStream = pStream->Read(&dwInput, sizeof(dwInput), &cbReadBytes);
EnterCriticalSection(&g_structCriticalSect);
g_fContinue = FALSE;
LeaveCriticalSection(&g_structCriticalSect);
return 0;
}
For additional information, see the MSDN CeRapiInvoke function reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdkr/htm/_wcesdk_cerapiinvoke.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdkr/htm/_wcesdk_cerapiinvoke.asp)
Back to the top
Building Modules That Use RAPI
The Rapi.h header file and Rapi.lib library file are available for use in compiling and linking desktop code to use RAPI. The header file and library files for use with RAPI functions are found in the following folder in a typical installation:
C:\Windows CE Tools\wce300\MS Pocket PC\support\ActiveSync\Inc
C:\Windows CE Tools\wce300\MS Pocket PC\support\ActiveSync\Lib
To compile the device-side DLL, you can use the same Rapi.h file mentioned earlier. There is no RAPI library file necessary to create the device DLL.
NOTE: RAPI.dll is not redistributable. It is installed when ActiveSync is installed on the desktop host computer.
[출처]
http://www.kbalertz.com/kb_Q299891.aspx
View products that this article applies to.
Article ID : 299891
Last Review : August 30, 2004
Revision : 1.0
This article was previously published under Q299891
On This Page
SUMMARY
MORE INFORMATION
Using CeRapiInvoke() in Block Mode
Using CeRapiInvoke in Stream Mode
Building Modules That Use RAPI
APPLIES TO
SUMMARY
The remote API (RAPI) CeRapiInvoke() enables you to invoke your routines in the Windows CE device from a desktop application. The routines are implemented in a DLL and the DLL must export those routines. You can use CeRapiInvoke() in two ways: in block mode or in stream mode. This article demonstrates how to use CeRapiInvoke() in both ways.
Back to the top
MORE INFORMATION
The following is a prototype for CeRapiInvoke in RAPI.dll to be used by an application running on the desktop.
HRESULT CeRapiInvoke(LPCWSTR pDllPath, LPCWSTR pFunctionName,
DWORD cbInput, BYTE *pInput, DWORD *pcbOutput,
BYTE **ppOutput, IRAPIStream **ppIRAPIStream,
DWORD dwReserved)
CeRapiInvoke() will be called in block mode if IRAPIStream** is NULL. Otherwise it will be called in the stream mode.
The following is a prototype DLL routine that runs on the device: int CallMyFunction(DWORD cbInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
Back to the top
Using CeRapiInvoke() in Block Mode
In the block mode, calls to CeRapiInvoke() return only after the DLL routine has executed and returned. The ppOutput pointer must be allocated by the DLL through the use of LocalAlloc() and the desktop application must call LocalFree() on the same [what?]. In block mode, ppIRAPIStream must be set to NULL. The value returned by the DLL routine will be returned by CeRapiInvoke.
The following sample code demonstrates use of CeRapiInvoke() in the block mode by calling a method in the DLL that resides in the \Windows folder of the device. The DLL method returns the available physical memory in the device in kilobytes. // test console application to call in blocking mode
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "rapi.h"
int main(int argc, char* argv[])
{
DWORD cbOut;
BYTE* pOut;
HRESULT hr;
//Initialize Windows CE RAPI
hr = CeRapiInit();
//Invoke CallMyFunction routine in MyRapi DLL in the \Windows directory.
hr = CeRapiInvoke(L"MyRapi", L"CallMyFunction",
0, NULL, &cbOut, &pOut, NULL, 0);
if(cbOut)
printf("Your device got %s KB of Physical Memory available", pOut);
else
printf("No memory available in the device");
//Uninitialize Windows CE RAPI
hr = CeRapiUninit();
//Free the DLL allocated memory.
if(pOut)
LocalFree(pOut);
return 0;
}
The following code shows implementation of the CallMyFunction routine inside MyRapi.dll: #include <windows.h>
#include "rapi.h"
extern "C"
{
__declspec(dllexport) int CallMyFunction(DWORD cbInput,
BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream);
}
int CallMyFunction(DWORD cbInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
{
MEMORYSTATUS structMemStatus;
DWORD dwMemAvailPhys;
char szFree[10];
//Initialize buffer to all NULLs
ZeroMemory(szFree, 10);
GlobalMemoryStatus(&structMemStatus);
dwMemAvailPhys = structMemStatus.dwAvailPhys;
sprintf(szFree, "%d", dwMemAvailPhys/1024);
//Provide extra char for NULL
*ppOutput = (BYTE*)LocalAlloc(LPTR, strlen(szFree)+1);
if(*ppOutput)
{
//Copy along with NULL
strncpy((char*)*ppOutput, szFree, strlen(szFree)+1);
*pcbOutput = strlen(szFree) + 1;
}
else
*pcbOutput = 0;
return 0;
}
Back to the top
Using CeRapiInvoke in Stream Mode
The following code demonstrates how to use CeRapiInvoke() in stream mode. It communicates with the device through IRAPIStream interface and displays the available physical memory in an Edit control. This simple application will loop indefinitely when reading data from the RAPI stream until a key is pressed. Once a key is pressed, the application exits the loop and writes to the RAPI stream, notifying code in MyRapi.dll that it is exiting. // test console application to call in stream mode
//
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include "rapi.h"
//Serious Error conditions and execution paths are not
//considered in this example. Purpose is just to demonstrate
//the usage of CeRapiInvoke() in Stream mode.
struct MY_MEM_STRUCT
{
DWORD dwPhysMemAvail;
DWORD dwPhysTotal;
};
int main(int argc, char* argv[])
{
IRAPIStream *pStream;
DWORD cbOut;
DWORD dwLength, cbBytesRead;
MY_MEM_STRUCT structMyDeviceMem;
HRESULT hr = CeRapiInit();
hr = CeRapiInvoke(L"MyRapi", L"CallMyFunction", NULL,
NULL, &cbOut, NULL, &pStream, 0);
_tprintf(_T("Press any key to exit\n"));
fflush(stdin);
while(!kbhit())
{
cbBytesRead = 0;
//First read the length information.
hr = pStream->Read(&dwLength, sizeof(DWORD), &cbBytesRead);
if(FAILED(hr) || (dwLength != sizeof(MY_MEM_STRUCT)))
{
_tprintf(_T("Error while reading from stream"));
break;
}
//Read the bytes into the structure.
hr = pStream->Read(&structMyDeviceMem, dwLength,
&cbBytesRead);
if(FAILED(hr))
{
break;
}
if(cbBytesRead > 0)
{
_tprintf(_T("\rTotal Physical Memory = %d KB, Available Memory = %d KB."),
structMyDeviceMem.dwPhysTotal, structMyDeviceMem.dwPhysMemAvail);
}
Sleep(2000);
}
fflush(stdin);
DWORD dwDataWrite = 1 ;
DWORD cbWritten;
hr = pStream->Write(&dwDataWrite, sizeof(dwDataWrite), &cbWritten);
hr = CeRapiUninit();
return 0;
}
On the device a separate thread is dedicated for reading the notification from the desktop. The read operation will block the thread until it reads the notification from the stream. The main thread writes to the stream every two seconds. struct MY_MEM_STRUCT
{
DWORD dwPhysMemAvail;
DWORD dwPhysTotal;
};
UINT MyThreadProc(LPVOID pParam);
CRITICAL_SECTION g_structCriticalSect;
BOOL g_fContinue = TRUE;
HRESULT SendToMyRapiStream(IRAPIStream* pStream,
void* pWriteStruct, int nDataWrite)
{
HRESULT hr;
DWORD cbWritten, dwWrite;
dwWrite = sizeof(nDataWrite);
//Write the length information first
hr = pStream->Write(&nDataWrite, dwWrite, &cbWritten);
if(FAILED(hr))
return E_FAIL;
//Write the structure into the stream
hr = pStream->Write(pWriteStruct, nDataWrite, &cbWritten);
if(FAILED(hr))
return E_FAIL;
return S_OK;
}
int CallMyFunction(DWORD dwInput, BYTE* pInput,
DWORD* pcbOutput, BYTE** ppOutput,
IRAPIStream* pStream)
{
MEMORYSTATUS structMemStatus;
BOOL bContinue = TRUE;
MY_MEM_STRUCT structMyMem;
HRESULT hr;
DWORD dwThreadId;
InitializeCriticalSection(&g_structCriticalSect);
HANDLE hThread = CreateThread(NULL, NULL,
(LPTHREAD_START_ROUTINE)MyThreadProc, pStream,
NULL, &dwThreadId);
while(1)
{
EnterCriticalSection(&g_structCriticalSect);
if(g_fContinue == FALSE)
{
LeaveCriticalSection(&g_structCriticalSect);
break;
}
LeaveCriticalSection(&g_structCriticalSect);
GlobalMemoryStatus(&structMemStatus);
structMyMem.dwPhysMemAvail = structMemStatus.dwAvailPhys / 1024;
structMyMem.dwPhysTotal = structMemStatus.dwTotalPhys / 1024;
hr = SendToMyRapiStream(pStream, &structMyMem, sizeof(structMyMem));
if(FAILED(hr))
{
break;
}
/*wait for 2 seconds. if WaitForSingleObject() comes out
in less than 2 seconds then client has requested to stop
sending the data or an error has occured.*/
if(WaitForSingleObject(hThread, 2000) != WAIT_TIMEOUT)
break;
}
//Make sure the other thread has terminated
WaitForSingleObject(hThread, 5000);
DeleteCriticalSection(&g_structCriticalSect);
g_fContinue = FALSE;
return 0;
}
UINT MyThreadProc(LPVOID pParam)
{
DWORD dwInput, cbReadBytes;
IRAPIStream* pStream = (IRAPIStream*)pParam;
HRESULT hrStream = pStream->Read(&dwInput, sizeof(dwInput), &cbReadBytes);
EnterCriticalSection(&g_structCriticalSect);
g_fContinue = FALSE;
LeaveCriticalSection(&g_structCriticalSect);
return 0;
}
For additional information, see the MSDN CeRapiInvoke function reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdkr/htm/_wcesdk_cerapiinvoke.asp (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdkr/htm/_wcesdk_cerapiinvoke.asp)
Back to the top
Building Modules That Use RAPI
The Rapi.h header file and Rapi.lib library file are available for use in compiling and linking desktop code to use RAPI. The header file and library files for use with RAPI functions are found in the following folder in a typical installation:
C:\Windows CE Tools\wce300\MS Pocket PC\support\ActiveSync\Inc
C:\Windows CE Tools\wce300\MS Pocket PC\support\ActiveSync\Lib
To compile the device-side DLL, you can use the same Rapi.h file mentioned earlier. There is no RAPI library file necessary to create the device DLL.
NOTE: RAPI.dll is not redistributable. It is installed when ActiveSync is installed on the desktop host computer.
[출처]
http://www.kbalertz.com/kb_Q299891.aspx
반응형
'Dev > Mobile' 카테고리의 다른 글
mobile개발 (0) | 2006.08.08 |
---|---|
PDA 가로보기, 세로보기 전환 (Landscape, Portrait) (0) | 2006.02.09 |
PDA에서 외장 메모리 삽입/삭제 시 이벤트 (0) | 2005.09.02 |
WinCE에서 폰트 설치 및 삭제 (0) | 2005.03.02 |
CF기반에서 c#코딩한 소스 봤습니다. 질문좀 드릴께요 (1) | 2004.10.19 |