Microsoft Knowledge Base Email Alertz

KBAlertz.com: (831883) - Desktop applications call the CeRapiInitEx function to initialize Remote API (RAPI) before the applications make any RAPI calls to communicate with Pocket PC or Microsoft Smartphone devices. CeRapiInitEx can be called asynchronously by passing in a...

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]

Search KbAlertz

Advanced Search

Webmasters
Put kbAlertz on your website.
[ Click Here for more! ]





ASP.NET 3.5 Web Hosting with Windows 2008 and SQL 2008: Click Here!
Discount ASP.NET Hosting
ASP.NET 2.0 and 3.5
Windows2008 and SQL2008
US and UK Hosting
The ad says 3 - but KBAlertz referrals get
** SIX MONTHS FREE **


Bug Tracking Software
For bug tracking software or defect tracking software or issue tracking software, visit Axosoft.


Community Site



We Send hundreds of thousands of emails using ASP.NET Email



Expert Web Design & Graphic Design
Design44.com

ASP.NET 3.5 Web Hosting with Windows 2008 and SQL 2008: Click Here!
Discount ASP.NET Hosting
ASP.NET 2.0 and 3.5
Windows2008 and SQL2008
US and UK Hosting
The ad says 3 - but KBAlertz referrals get
** SIX MONTHS FREE **




Mentioned In








Microsoft Knowledge Base Article

This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks




Article ID: 831883 - Last Review: November 29, 2007 - Revision: 1.5

HOWTO: Initialize RAPI Asynchronously with CeRapiInitEx()

On This Page

SUMMARY

Desktop applications call the CeRapiInitEx function to initialize Remote API (RAPI) before the applications make any RAPI calls to communicate with Pocket PC or Microsoft Smartphone devices. CeRapiInitEx can be called asynchronously by passing in a valid pointer to the RAPIINIT structure, and the caller can determine how long it wants to wait before RAPI is initialized by using the WaitForSingleObject function.

In Microsoft ActiveSync 3.7 and earlier, RAPI was designed to be initialized on threads with message pumps. RAPI was not designed to be initialized asychronously on worker threads in client applications. Microsoft does not recommend that you use unofficial workarounds to make RAPI initialize asychronously on worker threads in client applications.


The RAPI thread model was changed in ActiveSync 3.7.1 so that it can be freely initialized on either message pump threads (UI threads) or on simple worker threads. Therefore, if you use CeRapiInitEx correctly, no workaround is necessary and you will be able to initialize RAPI in any context. As a side effect, unofficial workarounds will not work. This article includes samples for how to correctly use CeRapiInitEx to initialize RAPI asynchronously.

Note To initialize RAPI synchronously, make a blocking call by using the CeRapiInit function. The behavior change in ActiveSync 3.7.1 does not affect applications that call CeRapiInit to initialize RAPI synchronously.

MORE INFORMATION

Example of Incorrect Workaround Code

This sample code demonstrates a typical unofficial workaround that worked in ActiveSync 3.7 or earlier. It is an inefficient solution because it calls the CeRapiInitEx and CeRapiUninit functions many times. This code does not work in ActiveSync 3.7.1 or later because the thread model inside RAPI was changed.
RAPIINIT ri; 			
BOOL    bCancel;
DWORD   dwWait;

while (!bCancel)
{
	// This is incorrect because it repeatedly calls CeRapiInitEx. 
	CeRapiInitEx(&ri);		
	
	// This is incorrect because in ActiveSync 3.7.1, the event may not be signaled before CeRapiInitEx
	//returns if a device is already connected.
	dwWait = WaitForSingleObject(ri.heRapiInit, 0);
		
	if (dwWait == WAIT_OBJECT_0)
	{
		// Succeeded.
		goto Succeeded;
	}
	else if (dwWait == WAIT_TIMEOUT)
	{
		 // This is incorrect because it repeatedly calls CeRapiUninit.
		CeRapiUninit(); 
		Continue;
	}
	else
	{
		// Failed.
		CeRapiUninit();
		goto failed;
	}
}

Examples

The following code examples demonstrate how to initialize RAPI asynchronously. These examples are not the only method of initializing RAPI asynchronously, but they demonstrate the general principle: Call CeRapiInitEx one time, then wait for the RAPI event to initialize based on your requirements. You may use a timeout value, a timer, or other event mechanisms to wait for initialization to finish.

Note The samples are based on ActiveSync 3.7.1. If you want to make sure your application works fine with both ActiveSync 3.7.1 and earlier version of ActiveSync, you must initialize RAPI on a thread with a message pump. For more information, see Example 2.

Example 1

To initialize RAPI asynchronously in a simple worker thread, use the following code. In the code, the CeRapiUninit function is called to uninitialize RAPI if the WaitForSingleObject function returns a value that is other than WAIT_OBJECT_0. This behavior is most likely caused by a timeout event (in this example, the timeout is 30 seconds).
#define ONE_SECOND 1000
            
RAPIINIT ri = {sizeof(RAPIINIT), 0, 0};

HRESULT hr = E_FAIL;
DWORD   dwWaitRet = 0;
DWORD   dwTimeout = 30  * ONE_SECOND; // Wait for 30 seconds. You can specify a different value here.

// Call CeRapiInitEx one time.
hr = CeRapiInitEx(&ri);
	
if (FAILED(hr))
{
	goto failed;
}

// Wait for the RAPI event until timeout.
	
// Use the WaitForSingleObject function for the worker thread.
// Use the WaitForMultipleObjects function if you are also waiting for other events.
dwWaitRet = WaitForSingleObject(ri.heRapiInit, dwTimeout);

if (dwWaitRet == WAIT_OBJECT_0)
{
	// If the RAPI init is returned, check the result.
	if (SUCCEEDED(ri.hrRapiInit))
	{
		// Succeeded.
		goto succeeded;
	}
	else
	{
		goto failed;
	}	
}
else 
{
	// Timeout or failed.
	goto failed;
}

succeeded:
	// Now you can make RAPI calls.

failed:
	// Uninitialize RAPI if you ever called CeRapiInitEx.
	if (SUCCEEDED(hr))
	{
		CeRapiUninit();
	}
Example 2

To initialize RAPI asynchronously in a UI thread (a thread with a message pump), abort when timeout


To initialize RAPI asynchronously in a UI thread, use the following code. In the code, the CeRapiUninit function is called to uninitialize RAPI if the MsgWaitForMultipleObjects function returns a value that is other than WAIT_OBJECT_0. This behavior is most likely caused by a timeout (in this example, the timeout is 30 seconds) or if any message is in the queue.
#define ONE_SECOND 1000
            
RAPIINIT ri = {sizeof(RAPIINIT), 0, 0};

HRESULT 	hr = E_FAIL;
DWORD   	dwWaitRet = 0;
DWORD   	dwTimeout = 30 * ONE_SECOND; // Wait for 30 seconds, or specify your own value here.
DWORD		dwEndTime;
DWORD		dwCurrentTime;

// Call CeRapiInitEx one time.
ri.cbSize = sizeof(ri);
hr = CeRapiInitEx(&ri);
	
if (FAILED(hr))
{
	goto failed;
}
	
// Calculate the time that you want to wait until.
dwCurrentTime  = GetTickCount();
dwEndTime = dwCurrentTime  + dwTimeout;

// Now wait for the RAPI event until timeout.
while (dwEndTime > dwCurrentTime)
{
	//
	// Wait for the RAPI event until timeout.  Use the MsgWaitForMultipleObjects function for the 
 // UI thread because otherwise the thread will be blocked for message processing.
	//
	dwWaitRet = MsgWaitForMultipleObjects(1, &ri.heRapiInit, FALSE, dwEndTime - dwCurrentTime,QS_ALLINPUT);

	if (dwWaitRet == WAIT_OBJECT_0)
	{
		// RAPI init returned, check result
		if (SUCCEEDED(ri.hrRapiInit))
		{
			// Succeeded.
			goto succeeded;
		}
		else
		{
			goto failed;
		}

	}
	else if (dwWaitRet == WAIT_OBJECT_0 + 1)
	{
		// Process the messages.
		BOOL bQuit = FALSE;
		MSG msg;
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			bQuit = (msg.message == WM_QUIT);
			TranslateMessage(&msg);	
			DispatchMessage(&msg);
		}
		if (bQuit)
		{
			goto failed;
		} 

		// Update the timer.
		dwCurrentTime  = GetTickCount();
			
		// Loop back, and thencontinue to wait.
		continue;
	}
	else
	{
		// Timed out or failed.
		goto failed;
	}
}

succeeded:
	// Now you can make RAPI calls.

failed:
	// Uninitialize RAPI if CeRapiInitEx was called.
	if (SUCCEEDED(hr))
	{
		CeRapiUninit();
	}

REFERENCES

For more information about ActiveSync and RAPI, visit the following Microsoft Developer Network (MSDN) Web sites:
http://msdn2.microsoft.com/en-us/library/ms879784.aspx (http://msdn2.microsoft.com/en-us/library/ms879784.aspx)

http://msdn2.microsoft.com/en-us/library/ms860198.aspx (http://msdn2.microsoft.com/en-us/library/ms860198.aspx)

APPLIES TO
  • Microsoft ActiveSync 4.1
  • Microsoft Windows CE Palm-size PC 2.01 software
  • Microsoft Pocket PC 2002 Software Standard Edition
Keywords: 
kbhowtomaster KB831883
       

Community Feedback System

Very often, it takes hours to solve a problem. Very often, you've looked high and low, and have tried a lot of solutions. When you finally found it, chances are, it was because someone else helped you. Here's your chance to give back. Use our community feedback tool to let others know what worked for you and what didn't.

Please also understand that the community feedback system is not warranted to be correct, it's simply a system that we've built to let people try and help each other. If something in a feedback response doesn't make sense to you, or you're not comfortable making changes that the feedback talks about (like registry edits), please consult a professional.

Thank you for using kbAlertz.com Feedback System.

-- Scott Cate

Be the first to leave feedback, to help others about this knowledge base article.

(Optional) Name

(Optional) Public URL Or Email

Comments
No HTML -- Text Only Please