Application Security Testing: An Integral Part of DevOps
Environment: VC6, MDAC 2.1 ( ADO 2.1 ), Win9x / NT
I recently needed to allow a user to have the ability to configure a connection string for one of my applications that uses ADO. After searching relentlessly through the docs, there was absolutely no information available on how to do this, except for a knowledge base article (Q225132) that described a problem with the #import statements when going from MDAC 2.0 to 2.1. This spurred me into writing this short article to demonstrate how you can use the standard OLE DB Data link configuration dialog in your own applications.
Ok, so lets take a look at how to do it. Ive created a simple console app project that demonstrates how to do this, download it by following the link at the bottom of this article.
Importing the type libraries
Firstly load up the simple source project and open the one and only source file ( datalink.cpp ) contained therein. The source is quite well commented so it should be straight forward to read it, but here are the main points.
Note from Web Master: The following #import pragmas are broken only due to formatting reasons.
#import "c:\program files\common files\system\ado" "\msado20.tlb" no_namespace rename("EOF", "IsEOF") rename("BOF", "IsBOF") #import "c:\program files\common files\system\ole " db\oledb32.dll" rename_namespace("oledb")
The #import statements at the top of the source file tell the compiler to generate some files that allow us to use smart pointers on the data link objects and the ADO objects. These import statements will allow us to use the ADO objects, and importantly for this article the Data Link properties dialog object.
Displaying the Data Link Properties Dialog
The function main() mostly contains some code to allow us to load and save a pre-configured connection string. I'm assuming you're familiar with the ios classes, so I'll skip this part as it was only put there to demonstrate you can display the dialog based on a pre-configured connection string.
When you want to display the dialog, you simply declare a IDataSourceLocatorPtr smart pointer object ( created from the #import statements ), and create an instance of it. You are then free to call its PromptNew() and PromptEdit( IDispatch *ptr ) methods.
For example, this code segment shows how to display the dialog for creating a new connection string (error checking etc has been removed for brevity);
oledb::IDataSourceLocatorPtr p_IDSL = NULL; _ConnectionPtr p_conn = NULL; p_IDSL.CreateInstance( __uuidof( oledb::DataLinks )); p_conn = p_IDSL->PromptNew();
The PromptNew function will display a fresh dialog for all the parameters to be entered by the user, and upon return, p_conn will be set to either NULL, indicating the user clicked cancel, or it will contain a created Connection object with its data member ConnectionString set to the ADO connection string that represents the users choices.
To display the dialog, based upon a pre-existing connection string, its slightly more convoluted. Here's an example;
oledb::IDataSourceLocatorPtr p_IDSL = NULL; _ConnectionPtr p_conn = NULL; p_IDSL.CreateInstance( __uuidof( oledb::DataLinks )); p_conn.CreateInstance( "ADODB.Connection" ); p_conn->ConnectionString = _bstr_t("your connection string"); IDispatch * p_Dispatch = NULL; p_conn.QueryInterface( IID_IDispatch, (LPVOID*) & p_Dispatch ); p_IDSL->PromptEdit( &p_Dispatch ); p_Dispatch->Release();
The edit version of the dialog needs these extra steps. Firstly you need to create a Connection object and set its connection string yourself, this is then converted into an IDispatch pointer using QueryInterface, and passed into the PromptEdit function.
PromptEdit returns a BOOL as TRUE if the user clicked OK, or FALSE if cancel was clicked. If it's TRUE the p_conn object's ConnectionString property will be set to the new connection parameters defined by the user.