This isn't pretty, nor is it optimal, but it covers the basics; You'll want to reindent the code, :) and I do things a little differently, by using raw interfaces when importing. Where there is a call to doQuery, you can put so UI in there to ask for & validate a query field. This is a bit rough in places, normally I use OLE DB rather than ADO, but it works. You'll need to change the name of the data source (obviously). The trick is to create the parameter and associate it with the command object. You can then use Execute to get a recordset, and having done that, you can ask the recordset to requery without needing the command object (once you've changed the parameter value. Add a different call to doQuery with a different string below the first one, and you'll see what I mean. The advantage over straight SQL text building is that in many cases, the SQL needs to be parsed only once, which is handy for complex queries, and in addition, it protects you from some nasty so-and-so from performing a SQL injection attack. (Yes, it was asking a bit much, but I had a spare 10 minutes at lunchtime[local time]) #include <windows.h> #include <tchar.h> #include <ole2.h> #import "c:\Program Files\Common Files\System\ADO\msado15.dll" \ no_namespace rename("EOF", "EndOfFile") raw_interfaces_only #include <stdio.h> #include <conio.h> void printRows(_Recordset* pRstTemp) { VARIANT_BOOL bEOF; // Ensure at top of recordset. pRstTemp->MoveFirst(); // If EOF is true, then no data and skip print loop. pRstTemp->get_EndOfFile(&bEOF); if (bEOF) { _tprintf(_T("\tRecordset empty\n")); } else { // Define temporary strings for output conversions. // Initialize to first record's values. _bstr_t bstrTitle; _bstr_t bstrType; // Enumerate Recordset and print from each. while(!bEOF) { // Convert variant string to convertable string type. FieldsPtr spFields; FieldPtr spField; long nFields; pRstTemp->get_Fields(&spFields); spFields->get_Count(&nFields); for(long f = 0; f < nFields; f++) { BSTR t = NULL; spFields->get_Item(_variant_t(f), &spField); _variant_t v; spField->get_Value(&v); spField->get_Name(&t); if (v.vt != VT_NULL) { v.ChangeType(VT_BSTR); #ifdef _UNICODE _tprintf(_T("%20.20s: %s\n"), (LPCWSTR)t, (LPCWSTR)v.bstrVal); #else _tprintf(_T("%20.20S: %S\n"), (LPCWSTR)t, (LP