Building a Simple Provider
The OLE DB Simple Provider (OSP) Toolkit simplifies the provider creation process. In most cases, you should only need to implement the OSP methods, code a data source object, fill out a copy of the supplied registration template, and register the OLE DB Simple Provider DLL (Msdaosp.dll) and the OSP Data Object (which will be a compiled DLL in Microsoft® Visual Basic® and in Microsoft Visual C++®, and a Java class in Microsoft Visual J++®). The other files supplied with each language implementation (header and library files) do not normally require modification.
Following is a summary of the main steps you need to follow when building a simple provider:
- Choose a language. You can write a simple provider using Visual Basic, Visual C++, or Visual J++. The general process of creating a provider is the same in each environment, although certain implementation details vary. The OSP Toolkit contains a set of code samples for each visual language.
- Implement OSP. Most of your work will be in implementing the OSP functions described in the OSP Language Reference. You can use the OSP Toolkit's sample OSP implementation file in the language of your choice as a starting point, changing the implementations so that the methods work with your data.
- Implement an OSP data source object. You need to implement a data source object (as part of the OSP Data Object) to expose the correct OSP implementation to the OLE DB Simple Provider DLL (Msdaosp.dll). Use either IDataSource (in Visual C++ implementations) or msDataSourceObject and the appropriate IDispatch methods (in Visual Basic or Visual J++ implementations).
- Implement notifications. Several of the OSP methods require notifications. Code your notifications in the OSP methods where applicable (for example, implementing the OSP notification methods aboutToChangeCell and cellChanged in the body of SetVariant).
- Register the OLE DB Simple Provider DLL (Msdaosp.dll). Register Msdaosp.dll using Regsvr32.exe.
- Register the OSP Data Object. Once you have finished coding the OSP Data Object, you need to assign it a GUID and register it using Regsvr32.exe (in Visual Basic and Visual C++ implementations) or Javareg (in Visual J++).
- Choose a registration option.
- If you are fully registering a simple provider, you need to fill out a copy of the registration template (the RegisterProvider.reg file) supplied with the OSP Toolkit and import that file's settings into the registry. This eliminates the need to write code that loads the OSP Data Object and hands it off to Msdaosp.dll.
- If you want to write your own consumer code to instantiate the provider, do not use the RegisterProvider.reg template file. (See Registration Without a .reg File.)
Asynchronous Programming Considerations
When implementing an OSP simple provider, it is the consumer's responsibility to marshal notification between threads. The consumer has two choices of threading models: free-threaded or apartment. Each is explained in "Consumer Threading Responsibilities," in the OLE DB Programmer's Reference. The way notifications are handled in the two threading models is described in "Threading and Notifications."
Asynchronous processing enables methods to return immediately without blocking on the calling thread. Consumers must explicitly request asynchronous processing when initializing a data source object or when opening or populating a rowset. Otherwise, the provider can perform asynchronous operations in the background but must behave synchronously, blocking if necessary, until the underlying asynchronous operation completes. For more information about asynchronous behavior in OLE DB, see the topics "Asynchronous Processing" and "Asynchronous Rowset Population. "
If an asynchronous OLE DB simple provider spawns a thread to populate rows and sends notifications from within that thread, it cannot call notification methods on the OLEDBSimpleProviderListener interface for that spawned thread. Instead, in the implementation of OLEDBSimpleProvider::addOLEDBSimpleProviderListener, the OSP should marshal IID_IOLEDBSimpleProviderListener to a stream object. Marshaling can be accomplished using CoMarshalInterThreadInterfaceInStream, or simply, CoMarshalInterface. The OSP may need a list of the listeners since multiple listeners are possible, depending on whether the threads are multicast or single cast.
Before calling any notification methods, within the asynchronous thread, the OSP must unmarshal the stream object into an interface within that thread. Because the streams were set up before the thread was started, the procedure is as follows:
- Call CoGetInterfaceandReleaseStream, or simply, CoUnmarsalInterface, for IID_IOLEDBSimpleProviderListener.
- Call the notification methods directly from the interface (now that it has been marshaled to this thread).
- If the threading model is apartment, which means CoInitialize was called, the consumer must have a message pump within the apartment model thread to push a copy of the same message (or notification) onto each thread. This is done by using MsgWaitForMultipleObjects to pump any waiting COM messages through each thread between the population of rows.