Emptying the Deleted Items Folder (OLEDB)

Topic Last Modified: 2007-03-06

The following example uses a file URL with the Exchange OLE DB (ExOLEDB) provider. The ExOLEDB provider also supports The HTTP: URL Scheme. Using The HTTP: URL Scheme enables both client and server applications to use a single URL scheme.

// Empty the Deleted Items Folder with OLEDB
// This sample demonstrates how to delete mail items in the Deleted Items folder
// using OLEDB.

#define DBINITCONSTANTS
#define NUMROWS_CHUNK  5
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <oledb.h>
#include <oledberr.h>

int main(int argc, char** argv)
{
   HRESULT hr = NULL;

   if (argc !=2)
   {
      printf("Usage: EmptyDeletedItems\r\n");
      printf("Example: EmptyDeletedItems \"file://./backofficestorage/mydomain.contoso.com/MBX/User1/Deleted Items\"\n");
      exit(0);
   }

   wchar_t* folderURL = NULL;
   size_t size;

   // Note: It is recommended that all input parameters be validated when they are
   // first obtained from the user or user interface.
   size = mbstowcs(NULL,argv[1],0);
   folderURL = (wchar_t*)malloc(size * sizeof(wchar_t*) + 1);
   mbstowcs(folderURL,argv[1],size+1);

   printf("folderURL: %ls\n", folderURL);
   BSTR bstrFolderURL = SysAllocString(folderURL);
   printf("Folder URL: %S\n", bstrFolderURL);

   wchar_t* strURL = NULL;
   wchar_t* str1 = L"Select * from scope('shallow traversal of \"";
   wchar_t* str2 = L"\"')";
   size_t size2, size3;
   size2 = mbstowcs(NULL, "Select * from scope('shallow traversal of \"", 0);
   size3 = mbstowcs(NULL, "\')", 0);
   strURL = (wchar_t*)malloc(size * sizeof(wchar_t*) + size2 + size3 + 1);
   wcscpy(strURL, str1);
   wcscat(strURL, folderURL);
   wcscat(strURL, str2);
   printf("strURL: %ls\n", strURL);

   IDBInitialize *pIDBInitialize;

   // Database property variables
   const ULONG nProps = 4;
   IDBProperties *pIDBProperties;
   DBPROP        InitProp[nProps];
   DBPROPSET     rgInitPropSet;

   // Session variables
   IDBCreateSession *pIDBCreateSession;

   // Command variables
   IDBCreateCommand *pIDBCreateCommand;
   ICommandText     *pICommandText;

   LONG      cRowsAffected;

   // Rowset variables
   IRowset *pIRowset;
   IRowsetChange *pIRowsetChange;

   // Rows fetched
   ULONG cRowsObtained ;

   // Rows handle
   HROW  rghRows[NUMROWS_CHUNK] ;

   // Pointer to the row
   HROW *pRows = &rghRows[0];

   DBROWSTATUS *rgRowStatus = NULL;

   CLSID CLSID_EXOLEDB;
   int MsgCount = 0;

   // Initialize OLE and set up the DLLs.
   CoInitialize(NULL);

   // Create an instance of the Exchange OLEDB provider.
   // Request one of the instances, such as IDBInitialize or IDBProperties.

   hr = CLSIDFromProgID(OLESTR("Exoledb.DataSource"), &CLSID_EXOLEDB);
   if (FAILED(hr))
   {
      printf("CLSIDFromProgID failed\n");
      return (E_FAIL);
   }

   hr = CoCreateInstance(CLSID_EXOLEDB,
                    NULL,
                    CLSCTX_INPROC_SERVER,
                    IID_IDBInitialize,
                    (void**)&pIDBInitialize);

   if(pIDBInitialize == NULL)
   {
      printf("CoCreateInstance of Provider failed\n");
      return (E_FAIL);
   }

   // Get or set the property data source
   // Total of four properties
   // Level of prompting you prefer
   // Data source name
   // User ID
   // Password
   // Initialize common property options
   for (ULONG i=0; i<nProps; i++)
   {
      VariantInit(&InitProp[i].vValue);
      InitProp[i].dwOptions = DBPROPOPTIONS_REQUIRED;
      InitProp[i].colid = DB_NULLID;
   }

   // Set the level of prompting.
   InitProp[0].dwPropertyID = DBPROP_INIT_PROMPT;
   InitProp[0].vValue.vt = VT_I2;
   InitProp[0].vValue.intVal = DBPROMPT_NOPROMPT;

   // Data source name
   InitProp[1].dwPropertyID = DBPROP_INIT_DATASOURCE;
   InitProp[1].vValue.vt = VT_BSTR;
   InitProp[1].vValue.bstrVal = bstrFolderURL;

   // User ID
   InitProp[2].dwPropertyID = DBPROP_AUTH_USERID;
   InitProp[2].vValue.vt = VT_BSTR;
   InitProp[2].vValue.bstrVal = SysAllocString(OLESTR(""));

   // Password
   InitProp[3].dwPropertyID = DBPROP_AUTH_PASSWORD;
   InitProp[3].vValue.vt = VT_BSTR;
   InitProp[3].vValue.bstrVal = SysAllocString(OLESTR(""));

   rgInitPropSet.guidPropertySet = DBPROPSET_DBINIT;
   rgInitPropSet.rgProperties = InitProp;
   rgInitPropSet.cProperties = nProps;

   // Set the initialization properties.
   // Query the IDBProperties interface first.
   hr = pIDBInitialize->QueryInterface(IID_IDBProperties,
                              (void**)&pIDBProperties);
   if( FAILED(hr))
   {
      printf("Query of IDBProperties interface failed\n");
      return E_FAIL;
   }

   hr = pIDBProperties->SetProperties(1,
                              &rgInitPropSet);
   if( FAILED(hr))
   {
      printf("Set IDBProperties failed\n");
      return E_FAIL;
   }

   // Setting of properties was successful.
   SysFreeString(InitProp[1].vValue.bstrVal);
   SysFreeString(InitProp[2].vValue.bstrVal);
   SysFreeString(InitProp[3].vValue.bstrVal);

   // Release the properties.
   pIDBProperties->Release();

   // Call IDBInitialize::Initilize() to get the data source.
   hr = pIDBInitialize->Initialize();
   if(FAILED(hr))
   {
      printf("IDBInitialize failed\n");
      return E_FAIL;
   }

   // QI IDBCreateSession
   hr = pIDBInitialize->QueryInterface(IID_IDBCreateSession,
                              (void **)&pIDBCreateSession);

   if( FAILED(hr))
   {
      printf("Query IDBCreateSession failed\n");
      return E_FAIL;
   }

   // Create the session, Session object: IDBCreateCommand::CreateCommand.
   hr = pIDBCreateSession->CreateSession(NULL,
                                IID_IDBCreateCommand,
                                (IUnknown**) &pIDBCreateCommand);
   // Release the session.
   pIDBCreateSession->Release();

   if( FAILED(hr))
   {
      printf("CreateSession failed\n");
      return E_FAIL;
   }

   // Create the command object.
   hr = pIDBCreateCommand->CreateCommand(NULL,
                                IID_ICommandText,
                                (IUnknown**)&pICommandText);

   pIDBCreateCommand->Release();

   if( FAILED(hr))
   {
      printf("CreateCommand failed");
      return E_FAIL;
   }

   // ICommandText::SetCommandText()
   hr = pICommandText->SetCommandText(DBGUID_DBSQL,
                              strURL);

   if( FAILED(hr))
   {
      printf("set CommandText failed");
      return E_FAIL;
   }

   // ICommand::Execute() to retrieve the rowset.
   hr = pICommandText->Execute(NULL,
                              IID_IRowset,
                        NULL,
                        &cRowsAffected,
                        (IUnknown**)&pIRowset);

   pICommandText->Release();

   if(FAILED(hr))
   {
      printf("Exe CommandText failed\n");
      return E_FAIL;
   }

   // Query IRowsetChange to delete rows.
   hr = pIRowset->QueryInterface(IID_IRowsetChange,
                         (void**)&pIRowsetChange);
   if( FAILED(hr))
   {
      printf("Query IRowsetChange failed\n");
      return E_FAIL;
   }

   // Move through the rowset using GetNextRow() to retrieve the handles
   // to the next row.
   while(TRUE)
   {
      pIRowset ->GetNextRows(

         // Reserved
         0,

         // cRowsToSkip
         0,
         NUMROWS_CHUNK,
         &cRowsObtained,

         // Filled in w/row handle
         &pRows
         );

      // Completed. There are no more rows left to get.
      if(cRowsObtained == 0)
         break;

      MsgCount += cRowsObtained;

      rgRowStatus = new DBROWSTATUS[cRowsObtained];

      // Delete messages.
      pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,
                           cRowsObtained,
                           rghRows,
                           rgRowStatus);

      // Release the row handles.
      pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL);

      delete [] rgRowStatus;

   }// End of while
   printf("\nNumber of items(messages) deleted from Deleted Items Folder: %d\n", MsgCount);

   // Release IRowsetChange
   pIRowsetChange->Release();

   SysFreeString(folderURL);
   SysFreeString(strURL);
   CoUninitialize();
   return NOERROR;
}