Initializing and Terminating Remote Application Programming Interface

Before making RAPI calls, you must call the CeRapiInit or CeRapiInitEx function. These functions perform routine initialization and set up the communications link between the desktop computer and the platform.

The CeRapiInit call is a synchronous operation. It does not return control to the application until a connection is made or an error occurs. In contrast, the CeRapiInitEx call is an asynchronous operation and it returns immediately. CeRapiInitEx continues the initialization until a connection is made, an error occurs, or there is a call to CeRapiUninit. Although CeRapiInitEx avoids blocking any threads, it is a more complicated method of initialization.

    To initialize RAPI using CeRapiInitEx
  1. Call CeRapiInitEx.
  2. If an error is returned, exit.
  3. If successful, call WaitForSingleObject or WaitForMultipleObjects to wait on the event handle passed back in the heRapiInit member of RAPIINIT.
  4. When heRapiInit is signaled, check for a successful connection or an error value.
  5. Check the hrRapiInit member of the RAPIINIT structure for the final return value.

When you are finished with RAPI, call CeRapiUninit to terminate the connection and perform any necessary cleanup. Because creating and terminating connections are fairly expensive operations, establish and terminate the link only once per session, not on a per-call basis.

The following code example shows how to use the CeRapiInitEx function. Following the CeRapiInitEx call, the MsgWaitForMultipleObjects function is used to wait on one of two events. The first event is when the event handle is passed back through the heRapiInit member of the RAPIINIT structure. The second event is when a user terminates a connection.

HRESULT InitRapi(HEVENT hExit)
{
   RAPIINIT ri = { sizeof(RAPIINIT) };
   HRESULT hr = CeRapiInitEx(&ri);
   if ( FAILED( hr ) )
   {
      return(hr);
   }

   HANDLE ahWait[] = { hExit                  , ri.heRapiInit };
   enum              { WAIT_EXIT=WAIT_OBJECT_0, WAIT_INIT     };

   DWORD dwObj = WaitAndDispatch(ARRAYSIZE(ahWait), ahWait);

   if (WAIT_INIT == dwObj)            //Event signaled by RAPI
   {
      if (FAILED(ri.hrRapiInit))      //Connection failed
      {
         CeRapiUninit();
      }

      return(ri.hrRapiInit);
   }

                           //Event signaled by user or timeout occurred
      CeRapiUninit();

      if (WAIT_EXIT == dwObj)
      {
         return(HRESULT_FROM_WIN32(ERROR_CANCELLED));
      }

      return(E_FAIL);
}

enum
{
   WAD_ALLINPUT    = 0x0000,
   WAD_SENDMESSAGE = 0x0001,
} ;

DWORD WaitAndDispatch(DWORD nCount, HANDLE *phWait, DWORD dwTimeout, UINT uFlags)
{
   DWORD dwObj;
   DWORD dwStart = GetTickCount();
   DWORD dwTimeLeft = dwTimeout;

   for ( ; ; )
   {
      dwObj = MsgWaitForMultipleObjects(nCount, phWait, FALSE,
         dwTimeLeft, (uFlags&WAD_SENDMESSAGE) ? QS_SENDMESSAGE : QS_ALLINPUT);
      if (dwObj == (DWORD)-1)
      {
         dwObj = WaitForMultipleObjects(nCount, phWait, FALSE, 100);
         if (dwObj == (DWORD)-1)
         {
            break;
         }
        }
        else if (dwObj == WAIT_TIMEOUT)
        {
            break;
        }

      if ((UINT)(dwObj-WAIT_OBJECT_0) < nCount)
      {
         break;
      }

      MSG msg;
      if (uFlags & WAD_SENDMESSAGE)
      {
         PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
      }
      else
      {
         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
         {
            DispatchMessage(&msg);
         }
      }

      if (INFINITE != dwTimeout)
      {
         dwTimeLeft = dwTimeout - (GetTickCount() - dwStart);
         if ((int)dwTimeLeft < 0)
         {
            break;
         }
      }
   }

   return(dwObj);
}