throbber
Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`Home (/) / Programming (/Programming/)
`/ Pocket pc network programming (/Programming/Pocket+pc+network+programming/)
`
`21
`
`The Remote API (RAPI) provides a set
`of helper functions that enable a
`desktop-based application to execute
`code on a connected Pocket PC device.
`Once a function has returned, the
`results are sent back to the PC. In
`essence, RAPI is a type of one-way
`Remote Procedure Call (RPC)?the
`client (your desktop application) makes
`a request to the server (a connected
`Pocket PC device) to execute some
`functionality, and returns the results to
`it.
`
`RAPI was originally designed as a way
`to manage a Pocket PC device from the
`desktop. It includes functions that enable an application to query the file system, registry, and
`device databases, as well as get information about the Pocket PC's system configuration. You
`can even create your own functions, which can be run over the RAPI APIs.
`
`You will quickly notice that most of the functions in RAPI look similar to the functions in the
`standard Pocket PC and Windows 32 API. In fact, they typically have the same definition and
`number of parameters, as well as the same return values, as a standard desktop function call.
`The only difference is that they all are prefixed with the letters Ce. For example, the RAPI
`function CeFindFirstFile() is the same as the desktop FindFirstFile() API, except
`that it will enumerate the files on a connected Pocket PC device, rather than those on the
`desktop. This being the case, I will not provide a detailed description of each function available
`via the RAPI API.
`
`Because RAPI is run on the desktop, you must ensure that the computer running your
`application has the latest version of ActiveSync installed on it. This will ensure that rapi.dll
`(which is required for your application to work) is present on the desktop, as you may not
`distribute rapi.dll on your own. You can call RAPI from console applications, window
`applications, and even a .NET assembly.
`In order to use the Remote API within your applications, you need to include the rapi.h
`header file in your project, as well as link with the rapi.lib library (note that because this is a
`desktop library, it is located in the .\wce300\Pocket PC 2002\support
`
`1 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0001
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`\ActiveSync\lib directory in the folder where you have installed Embedded Visual C++).
`Using RAPI
`Before you can use any of the RAPI functions, you must first initialize Windows CE's remote
`services and establish a communications link with a connected device by calling either the
`CeRapiInit() or CeRapiInitEx() functions.
`The simplest way to start RAPI is by calling the synchronous (i.e., blocking) function
`CeRapiInit(), which is defined as follows:
`
`HRESULT CeRapiInit();
`
`Once the function is called, it will immediately attempt to establish a connection to a Pocket PC
`device, and will not return control to your application until either a connection has been made or
`the function fails. CeRapiInit() will return E_SUCCESS if a successful connection can be
`made and RAPI has initialized without a problem; otherwise, you will be returned E_FAIL. If
`RAPI has already been initialized, you will receive CERAPI_E_ALREADYINITIALIZED as the
`return value.
`The following short code sample shows you how to use the CeRapiInit() function:
`
`HRESULT hr = S_OK;
`hr = CeRapiInit();
`
`if(FAILED(hr)) {
`   if(hr == CERAPI_E_ALREADYINITIALIZED)
`      OutputDebugString(TEXT("RAPI has already been
`          initalized"));
`   return FALSE;
`}
`
`Although using the CeRapiInitEx() function is a bit more involved, you will find that it
`provides you with a greater amount of control because it is asynchronous (the function will
`return to you immediately). This means, of course, that you will have to periodically check the
`RAPI event handle you are returned in order to find out when it has become signaled.
`The CeRapiInitEx() function is defined as follows:
`
`HRESULT CeRapiInitEx(RAPIINIT *pRapiInit);
`
`The only parameter that the function takes is a pointer to a RAPIINIT structure, which contains
`information about the RAPI event handle and its status. The structure is defined as follows:
`
`typedef struct _RAPIINIT {
`   DWORD cbSize;
`   HANDLE heRapiInit;
`   HRESULT hrRapiInit;
`} RAPIINIT;
`
`The first field, cbSize, should be set before calling CeRapiInitEx() with the size of the
`RAPIINIT structure. This is followed by heRapiInit, which will be filled in with the event
`handle that you can use to check on the status of your RAPI connection. The last field,
`
`2 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0002
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`hrRapiInit, will be filled in with the return code from CeRapiInitEx() once heRapiInit
`becomes signaled.
`The following code snippet shows how you can use the CeRapiInitEx() function to initialize
`your RAPI connection by using the WaitForSingleObject() function to monitor the RAPI
`event handle:
`
`HRESULT hr = S_OK;
`RAPIINIT rapiInit;
`
`memset(&rapiInit, 0, sizeof(RAPIINIT));
`rapiInit.cbSize = sizeof(RAPIINIT);
`
`hr = CeRapiInitEx(&rapiInit);
`if(FAILED(hr)) {
`   if(hr == CERAPI_E_ALREADYINITIALIZED)
`      OutputDebugString(TEXT("RAPI has already been
`      initalized"));
`   return FALSE;
`
`} /
`
`/ Wait for RAPI to be signaled
`DWORD dwResult = 0;
`dwResult = WaitForSingleObject(rapiInit.heRapiInit, 5000);
`if(dwResult == WAIT_TIMEOUT || dwResult == WAIT_ABANDONED) {
`   // RAPI has failed or timed out. Proceed with cleanup
`   CeRapiUninit();
`   return FALSE;
`
`} i
`
`f(dwResult == WAIT_OBJECT_0 && SUCCEEDED(rapiInit.hrRapiInit)) {
`   // RAPI has succeeded.
`   OutputDebugString(TEXT("RAPI Initialized."));
`
`   // Do something here
`}
`
`When working with applications that use RAPI, it is important to remember that you are relying
`on a network connection between the desktop and a device. When a function fails, an error can
`occur in either the RAPI layer or the function itself. You can determine where the error has
`actually occurred by calling into the CeRapiGetError() function, which is defined as follows:
`
`HRESULT CeRapiGetError(void);
`
`The function takes no parameters, and will return a value other than 0 if RAPI itself was
`responsible for the function failing. If CeRapiGetError() returns 0, however, you know that
`the error occurred in the actual remote function, and you can use the CeGetLastError()
`function to determine the error code, as shown in the following example:
`
`3 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0003
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`DWORD dwError = CeRapiGetError();
`
`if(dwError == 0) {
`   // The error did not occur in RAPI, find out what the
`   // remote function returned
`   dwError = CeGetLastError();
`}
`
`A few functions (CeFindAllDatabases(), CeFindAllFiles(), and
`CeReadRecordProps()) will allocate memory on the desktop when they are called. In order to
`properly free this memory, you can use the following function:
`
`HRESULT CeRapiFreeBuffer(LPVOID);
`
`The only parameter you need to pass in is a pointer to the buffer that was allocated. If the
`function succeeds, then you will be returned a value of S_OK.
`When you have finished using RAPI, you must also make sure that you properly shut down the
`remote connection services. To do so, you can simply use the following function:
`
`HRESULT CeRapiUninit();
`
`The function takes no parameters, and will return a value of E_FAIL if RAPI has not been
`previously initialized.
`File System RAPI Functions
`Table 9.2 lists the Remote API functions for working with the Pocket PC file system.
`
`Table 9.2. RAPI File System Functions
`
`Remote File System Functions
`
`4 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0004
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`Remote File System Functions
`
`[View full width]
`
`BOOL CeCloseHandle(HANDLE);
`BOOL CeCopyFile(LPCWSTR, LPCWSTR, BOOL);
`BOOL CeCreateDirectory(LPCWSTR, 
`LPSECURITY_ATTRIBUTES);
`BOOL CeDeleteFile(LPCWSTR);
`BOOL CeFindAllFiles(LPCWSTR, DWORD, LPDWORD,
`  LPLPCE_FIND_DATA);
`BOOL CeFindClose(HANDLE);
`BOOL CeFindNextFile(HANDLE, LPCE_FIND_DATA);
`BOOL CeGetFileSize(HANDLE, LPDWORD);
`BOOL CeGetFileTime(HANDLE, LPFILETIME, LPFILETIME,
`  LPFILETIME);
`BOOL CeMoveFile(LPCWSTR, LPCWSTR);
`BOOL CeReadFile(HANDLE, LPVOID, DWORD, LPDWORD,
`  LPOVERLAPPED);
`BOOL CeRemoveDirectory(LPCWSTR);
`BOOL CeSetEndOfFile(HANDLE);
`BOOL CeSetFileAttributes(LPCWSTR, DWORD);
`BOOL CeSetFileTime(HANDLE, LPFILETIME, LPFILETIME,
`  LPFILETIME);
`BOOL CeWriteFile(HANDLE, LPCVOID, DWORD, LPDWORD,
`  LPOVERLAPPED);
`DWORD CeGetFileAttributes(LPCWSTR);
`DWORD CeSetFilePointer(HANDLE, LONG, PLONG, 
`DWORD);
`HANDLE CeCreateFile(LPCWSTR, DWORD, DWORD,
`  LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
`HANDLE CeFindFirstFile(LPCWSTR, LPCE_FIND_DATA);
`
`The following example shows how you can use the Remote API's CeFindAllFiles() (as well
`as CeRapiFreeBuffer()) function on the desktop to easily retrieve a list of the wave files that
`are located on the device:
`
`5 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0005
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`LPVOID lpvFindData = NULL;
`DWORD dwFileCount = 0;
`
`// Get a list of the WAV files in the \Windows folder
`if(CeFindAllFiles(TEXT("\\Windows\\*.wav"),
`   FAF_NO_HIDDEN_SYS_ROMMODULES|FAF_NAME, &dwFileCount,
`   (LPLPCE_FIND_DATA)&lpvFindData) == FALSE) {
`
`   DWORD dwError = CeRapiGetError();
`   TCHAR tchError[128] = TEXT("\0");
`
`   if(dwError == 0)
`      dwError = CeGetLastError();
`
`   wsprintf(tchError, TEXT("Error: %d"), dwError);
`   OutputDebugString(tchError);
`   return FALSE;
`
`} /
`
`/ Walk through the files
`LPCE_FIND_DATA pFindData = (LPCE_FIND_DATA)lpvFindData;
`
`for(DWORD dwCount = 0; dwCount<dwFileCount; dwCount++) {
`   TCHAR tchFile[MAX_PATH+1] = TEXT("\0");
`
`   wsprintf(tchFile, TEXT("Remote File:%s\r\n"),
`      pFindData[dwCount].cFileName);
`   OutputDebugString(tchFile);
`
`} /
`
`/ Clean up the buffer
`if(lpvFindData)
`   CeRapiFreeBuffer(lpvFindData);
`
`Registry RAPI Functions
`Table 9.3 lists the Remote API functions that are available for manipulating the Pocket PC
`registry from the desktop host.
`
`Table 9.3. RAPI Registry Functions
`
`Remote Registry Functions
`
`6 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0006
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`Remote Registry Functions
`
`[View full width]
`
`LONG CeRegCloseKey(HKEY);
`LONG CeRegCreateKeyEx(HKEY, LPCWSTR, DWORD, 
`LPWSTR, DWORD,
`  REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
`LONG CeRegDeleteKey(HKEY, LPCWSTR);
`LONG CeRegDeleteValue(HKEY, LPCWSTR);
`LONG CeRegEnumKeyEx(HKEY, DWORD, LPWSTR, LPDWORD, 
`LPDWORD,
`  LPWSTR, LPDWORD, PFILETIME);
`LONG CeRegEnumValue(HKEY, DWORD, LPWSTR, LPDWORD, 
`LPDWORD,
`  LPDWORD, LPBYTE, LPDWORD);
`LONG CeRegOpenKeyEx(HKEY, LPCWSTR, DWORD, REGSAM, 
`PHKEY);
`LONG CeRegQueryInfoKey(HKEY, LPWSTR, LPDWORD, 
`LPDWORD,
`  LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, 
`LPDWORD,
`  LPDWORD, PFILETIME);
`LONG CeRegQueryValueEx(HKEY, LPCWSTR, LPDWORD, 
`LPDWORD,
`  LPBYTE, LPDWORD);
`LONG CeRegSetValueEx(HKEY, LPCWSTR, DWORD, DWORD, 
`LPBYTE,
`  DWORD);
`
`Database RAPI Functions
`Table 9.4 lists the Remote API functions for working with Pocket PC databases.
`
`Table 9.4. RAPI Database Functions
`
`Remote Database Functions
`
`7 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0007
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`Remote Database Functions
`
`[View full width]
`
`BOOL CeDeleteDatabase(CEOID);
`BOOL CeDeleteDatabaseEx(PCEGUID, CEOID);
`BOOL CeDeleteRecord(HANDLE, CEOID);
`BOOL CeEnumDBVolumes(PCEGUID, LPWSTR, DWORD);
`BOOL CeFindAllDatabases(DWORD, WORD, LPWORD,
`  LPLPCEDB_FIND_DATA);
`BOOL CeFlushDBVol(PCEGUID);
`BOOL CeMountDBVol(PCEGUID, LPWSTR, DWORD);
`BOOL CeOidGetInfo(CEOID, CEOIDINFO*);
`BOOL CeOidGetInfoEx(PCEGUID, CEOID, CEOIDINFO*);
`BOOL CeSetDatabaseInfo(CEOID, CEDBASEINFO*);
`BOOL CeSetDatabaseInfoEx(PCEGUID, CEOID, 
`CEDBASEINFO*);
`BOOL CeUnmountDBVol(PCEGUID);
`CEOID CeCreateDatabase(LPWSTR, DWORD, WORD, 
`SORTORDERSPEC*);
`CEOID CeFindNextDatabase(HANDLE);
`CEOID CeCreateDatabaseEx(PCEGUID, CEDBASEINFO*);
`CEOID CeFindNextDatabaseEx(HANDLE, PCEGUID);
`CEOID CeReadRecordProps(HANDLE, DWORD, LPWORD, 
`CEPROPID*,
`  LPBYTE*, LPDWORD);
`CEOID CeReadRecordPropsEx(HANDLE, DWORD, LPWORD, 
`CEPROPID*,
`  LPBYTE*, LPDWORD, HANDLE);
`CEOID CeSeekDatabase(HANDLE, DWORD, DWORD, 
`LPDWORD);
`CEOID CeWriteRecordProps(HANDLE, CEOID, WORD, 
`CEPROPVAL*);
`CEOID CeWriteRecordProps(HANDLE, CEOID, WORD, 
`CEPROPVAL*);
`HANDLE CeFindFirstDatabase(DWORD);
`HANDLE CeFindFirstDatabaseEx(PCEGUID, DWORD);
`HANDLE CeOpenDatabase(PCEOID, LPWSTR, CEPROPID, 
`DWORD, HWND);
`HANDLE CeOpenDatabaseEx(PCEGUID, PCEOID, LPWSTR, 
`CEPROPID,
`  DWORD, CENOTIFYREQUEST *);
`
`System Configuration and Information RAPI Functions
`Table 9.5 lists the Remote API functions for retrieving Pocket PC configuration and system
`information.
`
`Table 9.5. RAPI System Information Functions
`
`Remote System Configuration and Information Functions
`
`8 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0008
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`Remote System Configuration and Information Functions
`
`[View full width]
`
`BOOL CeCheckPassword(LPWSTR);
`BOOL CeCreateProcess(LPCWSTR, LPCWSTR, 
`LPSECURITY_ATTRIBUTES,
`  LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, 
`LPWSTR,
`  LPSTARTUPINFO, LPPROCESS_INFORMATION);
`BOOL CeGetStoreInformation(LPSTORE_INFORMATION);
`BOOL CeGetSystemPowerStatusEx(
`PSYSTEM_POWER_STATUS_EX, BOOL);
`BOOL CeGetVersionEx(LPCEOSVERSIONINFO);
`DWORD CeGetLastError(void);
`int CeGetDesktopDeviceCaps(int);
`int CeGetSystemMetrics(int);
`VOID CeGetSystemInfo(LPSYSTEM_INFO);
`VOID CeGlobalMemoryStatus(LPMEMORYSTATUS);
`
`Shell RAPI Functions
`Table 9.6 lists the Remote API shell management functions.
`
`Table 9.6. RAPI Shell Management Functions
`
`Remote Shell Functions
`
`BOOL CeSHGetShortcutTarget(LPWSTR, LPWSTR, int);
`DWORD CeGetSpecialFolderPath(int, DWORD, LPWSTR);
`DWORD CeGetTempPath(DWORD, LPWSTR);
`DWORD CeSHCreateShortcut(LPWSTR, LPWSTR);
`
`Window RAPI Functions
`Table 9.7 lists the Remote API window management functions.
`
`Table 9.7. RAPI Window Management Functions
`
`Remote Window Functions
`
`HWND CeGetWindow(HWND, UINT);
`int CeGetClassName(HWND, LPWSTR, int);
`int CeGetWindowText(HWND, LPWSTR, int);
`LONG CeGetWindowLong(HWND, int);
`
`Creating Your Own RAPI Functions
`While the Remote API provides a wide breadth of functions that cover most of the basic
`information you need about your Pocket PC device, there are certainly going to be times when
`
`9 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0009
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`you will need to communicate with your device in a way that isn't supported by the supplied
`functions. Fortunately, RAPI also provides you with an API that gives you the capability to create
`and execute your own functions on the Pocket PC.
`
`You can use two different methods to call your own RAPI functions:
`
`1.
`Block mode. When you call a remote function through RAPI in block (or synchronous)
`mode, your desktop application will not be returned control until the function has
`completed. RAPI will send the command to the device, load the specified DLL into
`memory, call the function you want to execute, and return any data through RAPI when it
`is finished.
`
`2.
`Stream mode. When calling a remote function in stream (or asynchronous) mode, your
`application is returned control immediately after making the call. You then need to use an
`IRAPIStream COM interface (based on IStream) to send data back and forth between
`the desktop and the remote device. Using stream mode typically provides faster
`communications with a remote device than block mode.
`Both block mode and stream mode use the same function, CeRapiInvoke(), to execute your
`own user-defined function, and is defined as follows:
`
`HRESULT CeRapiInvoke(LPCWSTR pDllPath, LPCWSTR
`   pFunctionName, DWORD cbInput, BYTE *pInput, DWORD *pcbOutput,
`   BYTE **ppOutput, IRAPIStream **ppIRAPIStream, DWORD dwReserved);
`
`The first parameter, pDllPath, should point to a null-terminated string that contains the full
`name and path of the DLL (in Unicode) on the Pocket PC that contains the function you are
`calling. The next parameter, pFunctionName, is the name of the function that you want RAPI
`to execute.
`
`The next two parameters are used to set up the data you are going to send to the remote
`function. The cbInput parameter should specify the number of bytes that are located in the
`data buffer, which is specified by the pointer to which you set the pInput parameter. Be aware
`that the buffer you pass in the pInput parameter will be freed by the function you are calling
`into, so you should make sure that you allocate it by using the LocalAlloc() function.
`The pcbOutput and ppOutput parameters are used to receive data from the remote function.
`The pcbOutput parameter is a pointer to a DWORD value that will be filled in with the number of
`bytes that are contained in the data buffer to which ppOutput points. Because the remote
`function (and RAPI) has allocated memory on the desktop for the returned data buffer, you need
`to remember to call the LocalFree() function to free the memory that is being used by the
`ppOutput buffer when you are finished using it.
`The ppIRAPIStream parameter will determine whether you are using stream mode or block
`mode to call the remote function. To call your function using block mode, you can simply set this
`to NULL. To use stream mode, you need to set this parameter to a pointer of an IRAPIStream
`interface.
`
`The last parameter is reserved, and should be set to 0.
`
`Although you can name your remote function anything you like, you have to make sure that it
`
`10 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0010
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`matches the following prototype:
`
`STDAPI RAPIFunctionName(DWORD cbInput, BYTE *pInput, DWORD
`   *pcbOutput, BYTE **ppOutput, IRAPIStream *pIRAPIStream);
`
`The first two parameters, cbInput and pInput, specify the size and data buffer parameters,
`respectively, that are passed from the desktop call to CeRapiInvoke(). Because RAPI has
`automatically allocated data for pInput, your function needs to call LocalFree() on the
`buffer that is being passed in so that memory can be properly managed.
`The next two parameters, pcbOutput and ppOutput, are used to allocate a buffer, set the
`size of it, and return data to the desktop. The desktop application calling your remote function is
`responsible for freeing any data you allocate for the output buffer.
`The last parameter, pIRAPIStream, will point to an IRAPIStream object that RAPI has
`allocated if you are communicating with your desktop counterpart in stream mode.
`Now that you know how to call your own remote functions using CeRapiInvoke(), let's take a
`look at what's actually involved with writing a remote function that returns information from the
`Subscriber Identity Module (SIM) phonebook on a Pocket PC Phone Edition device (see
`Chapter 8 for more information about using the SIM Manager APIs).
`Using Block Mode
`Calling your own functions using RAPI's block mode interface is extremely straightforward. All
`you need to do is create a DLL for the Pocket PC device that contains the functions you need
`(following the prototype shown above). A desktop application can then use CeRapiInvoke()
`to call your function (be sure to pass in NULL for the ppIRAPIStream parameter). Essentially,
`this operates in the same fashion as all of the standard RAPI function calls.
`
`Let's take a look at how you can create a RAPI function to read a specific phonebook entry by
`using the SimReadPhonebookEntry() function on a Pocket PC Phone Edition device.
`The code for the DLL that you will be putting on your Pocket PC Phone Edition device would
`look like the following:
`
`11 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0011
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`#include <windows.h>
`#include <Simmgr.h>
`
`// Exported function prototypes
`#ifdef __cplusplus
`extern "C" {
`#endif
`__declspec(dllexport) INT MyCeGetPhonebookEntry(DWORD,
`   BYTE *, DWORD *, BYTE **, PVOID);
`#ifdef __cplusplus
`
`}#
`
`endif
`
`// Standard DLL entry point
`BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD dwReason,
`   LPVOID lpvReserved)
`
`{ 
`
`  return TRUE;
`
`} /
`
`/ Remote Block Function
`int MyCeGetPhonebookEntry(DWORD cbInput, BYTE *pInput,
`   DWORD *pcbOutput, BYTE **ppOutput, PVOID *pVoid)
`
`{ 
`
`  // Check to see if we have an input buffer
`   if(!pInput || sizeof(cbInput)>4)
`      return ‐1;
`
`   // Get the phone entry that was requested
`   DWORD dwEntry = 0;
`   memcpy(&dwEntry, pInput, cbInput);
`
`   // Free up the buffer that was passed in
`   LocalFree(pInput);
`
`// Initialize the SIM
`HRESULT hr = S_OK;
`HSIM hSim = NULL;
`
`if(FAILED(SimInitialize(0, NULL, 0, &hSim)))
`   return ‐1;
`
`// Get the data from the SIM
`SIMPHONEBOOKENTRY simEntry;
`
`memset(&simEntry, 0, sizeof(SIMPHONEBOOKENTRY));
`simEntry.cbSize = sizeof(SIMPHONEBOOKENTRY);
`
`hr = SimReadPhonebookEntry(hSim, SIM_PBSTORAGE_SIM,
`   dwEntry, &simEntry);
`
`SimDeinitialize(hSim);
`
`12 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0012
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`// If the read failed, just exit
`if(FAILED(hr))
`   return ‐1;
`
`// Allocate the return buffer
`DWORD dwBufferLength =
`   (MAX_LENGTH_PHONEBOOKENTRYTEXT+MAX_LENGTH_ADDRESS+1);
`TCHAR tchBuffer[MAX_LENGTH_PHONEBOOKENTRYTEXT+MAX_
`   LENGTH_ADDRESS+1];
`BYTE *pOutputBuffer = NULL;
`
`pOutputBuffer = (BYTE*)LocalAlloc(LPTR, dwBufferLength);
`
`if(!pOutputBuffer)
`   return ‐1;
`
`// Copy the name and phone to the buffer
`wsprintf(tchBuffer, TEXT("%s %s"), simEntry.lpszText,
`   simEntry.lpszAddress);
`
`// Convert it to non‐unicode
`wcstombs((char *)pOutputBuffer, tchBuffer,
`   dwBufferLength);
`
`// Set up for the return
`*ppOutput = (BYTE *)pOutputBuffer;
`  *pcbOutput = dwBufferLength;
`  return 1;
`}
`
`Your code on the desktop for calling the remote function, MyCeGetPhonebookEntry(), in
`block mode is as follows:
`
`13 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0013
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`#include <windows.h>
`#include <stdio.h>
`#include <tchar.h>
`#include <rapi.h>
`
`// Entry point for a console app on the desktop
`int wmain()
`
`{  
`
`  HRESULT hr = S_OK;
`
`   // Initalize RAPI
`   hr = CeRapiInit();
`   if(FAILED(hr)) {
`      printf("Could not initialize RAPI\r\n");
`      return ‐1;
`   }
`
`   // Set up stuff to send over
`   DWORD dwSIMEntry = 1;
`   DWORD dwSize = sizeof(dwSIMEntry);
`   DWORD dwOutputSize = 0;
`   BYTE *pOutput = NULL;
`   BYTE *pInput = NULL;
`
`   pInput = (BYTE *)LocalAlloc(LPTR, dwSize);
`   memcpy(pInput, &dwSIMEntry, dwSize);
`
`   // Call into the Remote API function
`   hr = CeRapiInvoke(TEXT("myrapice"),
`      TEXT("MyCeGetPhonebookEntry"), dwSize,
`      pInput, &dwOutputSize, &pOutput, NULL, 0);
`
`   if(FAILED(hr)) {
`      printf("Could not get SIM information!\r\n");
`      CeRapiUninit();
`      return ‐1;
`   }
`
`   if(pOutput) {
`      printf((char *)pOutput);
`      LocalFree(pOutput);
`   }
`
`   CeRapiUninit();
`   return 0;
`}
`
`In order to call this function in block mode from the desktop, you need to first allocate a buffer
`that will be used to pass information to the remote function. In this case, you want to pass in an
`argument that indicates which entry number from the SIM phonebook you are interested in.
`Once you have allocated a DWORD, you set it with the entry number you would like, and call the
`
`14 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0014
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`CeRapiInvoke() function. When the call returns, the output buffer will be filled in with a
`null-terminated string that contains the name and phone number of the entry. You must
`remember to call LocalFree() on the returned buffer in order to properly free the allocated
`memory.
`Using Stream Mode
`Although using the Remote API's stream mode to communicate with a device might seem a bit
`more complicated because it uses a COM object to send and receive data, using it is actually
`fairly straightforward, and the benefits outweigh the additional code. Not only will you have
`control returned to your application immediately after calling CeRapiInvoke(), using stream
`mode also enables you to more precisely control the flow of data between the desktop and a
`device.
`To use stream mode, all you need to do is call the CeRapiInvoke() function and pass in a
`pointer to an IRAPIStream object that has been initialized and set to NULL for the
`ppIRAPIStream parameter, as shown in the following example:
`
`IRAPIStream *pIRAPIStream = NULL;
`DWORD dwOutputSize = 0;
`BYTE *pOutput = NULL;
`
`// Initalize the RAPI Stream interface
`CoInitialize(NULL);
`
`// Call into the Remote API function
`hr = CeRapiInvoke(TEXT("myrapice"), TEXT("MyCeSimDir"),
`   0, NULL, &dwOutputSize, &pOutput, &pIRAPIStream, 0);
`
`As you can see, what makes using stream mode easy is that RAPI itself implements the
`IRAPIStream object?you only need to talk to the object to send and receive data.
`The IRAPIStream interface is based on the standard IStream, which generically supports
`sending and receiving data from other stream objects. Only two additional methods have been
`added to the IRAPIStream interface, and they enable you to get and set timeout values for
`your communications stream. They are defined as follows:
`
`HRESULT SetRapiStat(RAPISTREAMFLAG Flag, DWORD dwValue);
`HRESULT GetRapiStat(RAPISTREAMFLAG Flag, DWORD *pdwValue);
`
`For both setting and getting the timeout value, the first parameter must be set to
`STREAM_TIMEOUT_READ. If you are setting the timeout value, you should set dwValue to the
`amount of time you want to elapse before the communications stream times out. If you are
`getting the value, then you need to pass in only a pointer to a DWORD variable that will receive
`the set timeout.
`When calling a remote function using stream mode, you can still use CeRapiInvoke() to pass
`in some initial data using its cbInput and pInput parameters. However, once the initial call
`has been made, it is recommended that you use the stream object's Read() and Write()
`methods to pass data back and forth.
`
`Let's take a look at what would be involved if you wanted to use RAPI's stream mode to get a
`directory of phonebook entries from the SIM card on a Pocket PC Phone Edition device.
`
`15 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0015
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`The code for the DLL that contains the MyCeSimDir() command you will be putting on your
`Pocket PC Phone Edition device would look like the following:
`
`16 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0016
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`#include <windows.h>
`#include <Simmgr.h>
`#include <rapi.h>
`
`#ifdef __cplusplus
`extern "C" {
`#endif
`
`__declspec(dllexport) INT MyCeSimDir(DWORD, BYTE *, DWORD *,
`   BYTE **, IRAPIStream *);
`#ifdef __cplusplus
`
`}#
`
`endif
`
`BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD dwReason,
`   LPVOID lpvReserved)
`
`{ 
`
`  return TRUE;
`
`} i
`
`nt MyCeSimDir(DWORD cbInput, BYTE *pInput,
`   DWORD *pcbOutput, BYTE **ppOutput, IRAPIStream *pIRAPIStream)
`
`{ 
`
`  // This sample will return all entries, so ignore the
`   // buffer that was passed in
`   if(pInput)
`      LocalFree(pInput);
`
`   // Make sure that the IRAPIStream is valid
`   if(!pIRAPIStream)
`      return ‐1;
`
`   // Initialize the SIM
`   HRESULT hr = S_OK;
`   HSIM hSim = NULL;
`
`   if(FAILED(SimInitialize(0, NULL, 0, &hSim)))
`      return ‐1;
`
`   // Get the total number of entries
`   DWORD dwUsed = 0, dwTotal = 0;
`
`   hr = SimGetPhonebookStatus(hSim, SIM_PBSTORAGE_SIM,
`      &dwUsed, &dwTotal);
`
`   if(FAILED(hr)) {
`      SimDeinitialize(hSim);
`      return ‐1;
`   }
`
`   // Make sure there's something to return
`   if(dwUsed == 0) {
`      SimDeinitialize(hSim);
`
`17 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0017
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`      return ‐1;
`   }
`
`   // Get each entry
`   // We'll pass them back as a Name [Phonenumber] string.
`   SIMPHONEBOOKENTRY simEntry;
`   TCHAR tchEntry[MAX_LENGTH_PHONEBOOKENTRYTEXT+
`      MAX_LENGTH_ADDRESS+1];
`   DWORD dwLength = 0, dwBytesWritten = 0;
`
`   for(DWORD dwEntry = 0; dwEntry<dwUsed; dwEntry++) {
`      memset(&simEntry, 0, sizeof(SIMPHONEBOOKENTRY));
`      simEntry.cbSize = sizeof(SIMPHONEBOOKENTRY);
`
`      hr = SimReadPhonebookEntry(hSim, SIM_PBSTORAGE_SIM,
`         dwEntry, &simEntry);
`      if(FAILED(hr))
`         break;
`
`      // Build the string
`      memset(tchEntry, 0,
`         MAX_LENGTH_PHONEBOOKENTRYTEXT+MAX_LENGTH_ADDRESS+1);
`      wsprintf(tchEntry, TEXT("%s [%s]"), simEntry.lpszText,
`         simEntry.lpszAddress);
`
`      // Write it to the stream
`      // First, send the length
`      dwLength = (lstrlen(tchEntry)+1)*sizeof(TCHAR);
`      hr = pIRAPIStream‐>Write(&dwLength, sizeof(dwLength),
`         &dwBytesWritten);
`
`      // Next, send the buffer
`      hr = pIRAPIStream‐>Write(tchEntry, dwLength,
`         &dwBytesWritten);
`      if(FAILED(hr))
`         break;
`
`} /
`
`/ Clean up
`SimDeinitialize(hSim);
`
`   // Send that there's "No more data"
`   DWORD dwFinished = 0xFFFFFFFF;
`   hr = pIRAPIStream‐>Write(&dwFinished, sizeof(dwFinished),
`      &dwBytesWritten);
`
`   // Release the stream interface
`   pIRAPIStream‐>Release();
`   return 0;
`}
`
`On the desktop side, you can create a simple console application that will call into your remote
`function using stream mode to output the contents of the SIM phonebook:
`
`18 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0018
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`#include <windows.h>
`#include <stdio.h>
`#include <tchar.h>
`#include <rapi.h>
`
`#define BUFFER_SIZE 1024
`
`// Entry point for a console app on the desktop
`int wmain()
`
`{ 
`
`  HRESULT hr = S_OK;
`
`   // Initalize RAPI
`   hr = CeRapiInit();
`   if(FAILED(hr)) {
`      printf("Could not initialize RAPI\r\n");
`      return ‐1;
`   }
`
`   // Set up stuff to send over
`   IRAPIStream *pIRAPIStream = NULL;
`   DWORD dwOutputSize = 0;
`   BYTE *pOutput = NULL;
`
`   // Initalize the RAPI Stream interface
`   CoInitialize(NULL);
`
`   // Call into the Remote API function
`   hr = CeRapiInvoke(TEXT("myrapice"), TEXT("MyCeSimDir"),
`      0, NULL, &dwOutputSize, &pOutput, &pIRAPIStream, 0);
`
`   if(FAILED(hr)) {
`      DWORD dwError = CeRapiGetError();
`      if(dwError == 0)
`         dwError = CeGetLastError();
`
`      printf("Could not get SIM information! Error: %u\r\n",
`         dwError);
`      CeRapiUninit();
`      return ‐1;
`   }
`
`   // Read from the remote stream
`   TCHAR tchEntry[BUFFER_SIZE+1];
`   DWORD dwSize = BUFFER_SIZE;
`   DWORD dwBytesRead = 0;
`   DWORD dwLength = 0;
`
`   do {
`      // Get the length. If it is 0xFFFFFFFF, we're done.
`      hr = pIRAPIStream‐>Read(&dwLength, sizeof(dwLength),
`         &dwBytesRead);
`
`19 of 22
`
`11/21/2016 8:17 PM
`
`Rosetta-2029
`
`0019
`
`

`
`Remote API (RAPI) :: Chapter 9. Desktop Synchronization :: Pocket pc ...
`
`http://etutorials.org/Programming/Pocket+pc+network+programming/Ch...
`
`      if(FAILED(hr) || dwLength == 0xFFFFFFFF)
`         break;
`
`      // Ok, read the buffer
`      hr = pIRAPIStream‐>Read(tchE

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket