home *** CD-ROM | disk | FTP | other *** search
- //
- // This file is part of Microsoft SQL Server online documentation.
- // Copyright (C) 1992-1997 Microsoft Corporation. All rights reserved.
- //
- // This source code is an intended supplement to the Microsoft SQL
- // Server online references and related electronic documentation.
- //
- // This sample is for instructional purposes only.
- // Code contained herein is not intended to be used "as is" in real applications.
- //
- // simple.cpp
- //
- // This is a sample program used to demonstrate the Virtual Device Interface
- // feature of Microsoft SQL Server.
- //
- // The program will backup or restore the 'pubs' sample database.
- //
- // The program accepts a single command line parameter.
- // One of:
- // b perform a backup
- // r perform a restore
- //
-
-
- // To gain access to free threaded COM, you'll need to define _WIN32_DCOM
- // before the system headers, either in the source (as in this example),
- // or when invoking the compiler (by using /D "_WIN32_DCOM")
- //
- #define _WIN32_DCOM
-
- #include <objbase.h> // for 'CoInitialize()'
- #include <stdio.h> // for file operations
- #include <ctype.h> // for toupper ()
- #include <process.h> // for spawn ()
-
- #include "vdi.h" // interface declaration
- #include "vdierror.h" // error constants
-
- #include "vdiguid.h" // define the interface identifiers.
- // IMPORTANT: vdiguid.h can only be included in one source file.
- //
-
-
- void performTransfer (
- IClientVirtualDevice* vd,
- int backup );
-
- int execSQL (int doBackup);
-
-
-
- //
- // main function
- //
- int main(int argc, char *argv[])
- {
- HRESULT hr;
- IClientVirtualDeviceSet* vds = NULL ;
- IClientVirtualDevice* vd=NULL;
-
- VDConfig config;
- int badParm=TRUE;
- int doBackup;
- int hProcess;
- int termCode;
-
- // Check the input parm
- //
- if (argc == 2)
- {
- if (toupper(argv[1][0]) == 'B')
- {
- doBackup = TRUE;
- badParm = FALSE;
- }
- else if (toupper(argv[1][0]) == 'R')
- {
- doBackup = FALSE;
- badParm = FALSE;
- }
- }
-
- if (badParm)
- {
- printf ("useage: simple {B|R}\n"
- "Demonstrate a Backup or Restore using the Virtual Device Interface\n");
- exit (1);
- }
-
- printf ("Performing a %s using a virtual device.\n",
- (doBackup) ? "BACKUP" : "RESTORE");
-
- // Initialize COM Library
- // Note: _WIN32_DCOM must be defined during the compile.
- //
- hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
-
- if (!SUCCEEDED (hr))
- {
- printf ("Coinit fails: x%X\n", hr);
- exit (1);
- }
-
- // Get an interface to the device set.
- // Notice how we use a single IID for both the class and interface
- // identifiers.
- //
- hr = CoCreateInstance (
- IID_IClientVirtualDeviceSet,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IClientVirtualDeviceSet,
- (void**)&vds);
-
- if (!SUCCEEDED (hr))
- {
- // This failure might happen if the DLL was not registered,
- // or if the application is using the wrong interface id (IID).
- //
- printf ("Could not create component: x%X\n", hr);
- printf ("Check registration of SQLVDI.DLL and value of IID\n");
- goto exit;
- }
-
- // Setup the VDI configuration we want to use.
- // This program doesn't use any fancy features, so the
- // only field to setup is the deviceCount.
- //
- // The server will treat the virtual device just like a pipe:
- // I/O will be strictly sequential with only the basic commands.
- //
- memset (&config, 0, sizeof(config));
- config.deviceCount = 1;
-
- // Create the virtual device set
- //
- hr = vds->Create (L"SUPERBAK", &config);
- if (!SUCCEEDED (hr))
- {
- printf ("VDS::Create fails: x%X", hr);
- goto exit;
- }
-
- // Send the SQL command, by starting 'isql' in a subprocess.
- //
- printf("\nSending the SQL...\n");
-
- hProcess = execSQL (doBackup);
- if (hProcess == -1)
- {
- printf ("execSQL failed.\n");
- goto shutdown;
- }
-
- // Wait for the server to connect, completing the configuration.
- //
- hr = vds->GetConfiguration (10000, &config);
- if (!SUCCEEDED (hr))
- {
- printf ("VDS::Getconfig fails: x%X\n", hr);
- if (hr == VD_E_TIMEOUT)
- {
- printf ("Timed out. Was Microsoft SQLServer running?\n");
- }
- goto shutdown;
- }
-
- // Open the single device in the set.
- //
- hr = vds->OpenDevice (L"SUPERBAK", &vd);
- if (!SUCCEEDED(hr))
- {
- printf ("VDS::OpenDevice fails: x%X\n", hr);
- goto shutdown;
- }
-
- printf ("\nPerforming data transfer...\n");
-
- performTransfer (vd, doBackup);
-
-
- shutdown:
-
- // Close the set
- //
- vds->Close ();
-
- // Obtain the SQL completion information, by waiting for isql to exit.
- //
- if (hProcess == _cwait( &termCode, hProcess, NULL))
- {
- if (termCode == 0)
- printf("\nThe SQL command executed successfully.\n");
- else
- printf("\nThe SQL command failed.\n");
- }
- else
- {
- printf ("cwait failed: %d\n", errno);
- }
-
- // COM reference counting: Release the interface.
- //
- // Rather than releasing it, the application has the
- // option to 'Create' another set, reusing the interface
- // that it currently has. Of course that applies to
- // a real application, not this simple sample!
- //
- vds->Release () ;
-
- exit:
-
- // Uninitialize COM Library
- //
- CoUninitialize () ;
-
- return 0 ;
- }
-
- //
- // Execute a basic backup/restore, by spawning a process to execute 'isql'.
- //
- // Returns:
- // -1 : failed to spawn
- // else : a "process handle"
- //
- int execSQL (int doBackup)
- {
- const char *const bCmd = "-Q\"BACKUP DATABASE PUBS TO VIRTUAL_DEVICE='SUPERBAK'\"";
-
- const char *const rCmd = "-Q\"RESTORE DATABASE PUBS FROM VIRTUAL_DEVICE='SUPERBAK'\"";
- int rc;
-
- // Spawn off the isql utility to execute the SQL.
- // Notice the '-b' which causes an error to set a non-zero
- // exit code on error.
- //
- rc = _spawnlp( _P_NOWAIT, "isql", "isql", "-Usa", "-P", "-b",
- (doBackup) ? bCmd : rCmd, NULL);
-
- if (rc == -1)
- {
- printf ("Spawn failed with error: %d\n", errno);
- }
-
- return (rc);
- }
-
- // This routine reads commands from the server until a 'Close' status is received.
- // It simply reads or writes a file 'superbak.dmp' in the current directory.
- //
- void performTransfer (
- IClientVirtualDevice* vd,
- int backup )
- {
- FILE * fh;
- char* fname = "superbak.dmp";
- VDC_Command * cmd;
- DWORD completionCode;
- DWORD bytesTransferred;
- HRESULT hr;
-
- fh = fopen (fname, (backup)? "wb" : "rb");
- if (fh == NULL )
- {
- printf ("Failed to open: %s\n", fname);
- return;
- }
-
- while (SUCCEEDED (hr=vd->GetCommand (INFINITE, &cmd)))
- {
- bytesTransferred = 0;
- switch (cmd->commandCode)
- {
- case VDC_Read:
- bytesTransferred = fread (cmd->buffer, 1, cmd->size, fh);
- if (bytesTransferred == cmd->size)
- completionCode = ERROR_SUCCESS;
- else
- // assume failure is eof
- completionCode = ERROR_HANDLE_EOF;
- break;
-
- case VDC_Write:
- bytesTransferred = fwrite (cmd->buffer, 1, cmd->size, fh);
- if (bytesTransferred == cmd->size )
- {
- completionCode = ERROR_SUCCESS;
- }
- else
- // assume failure is disk full
- completionCode = ERROR_DISK_FULL;
- break;
-
- case VDC_Flush:
- fflush (fh);
- completionCode = ERROR_SUCCESS;
- break;
-
- case VDC_ClearError:
- completionCode = ERROR_SUCCESS;
- break;
-
- default:
- // If command is unknown...
- completionCode = ERROR_NOT_SUPPORTED;
- }
-
- hr = vd->CompleteCommand (cmd, completionCode, bytesTransferred, 0);
- if (!SUCCEEDED (hr))
- {
- printf ("Completion Failed: x%X\n", hr);
- break;
- }
- }
-
- if (hr != VD_E_CLOSE)
- {
- printf ("Unexpected termination: x%X\n", hr);
- }
- else
- {
- // As far as the data transfer is concerned, no
- // errors occurred. The code which issues the SQL
- // must determine if the backup/restore was
- // really successful.
- //
- printf ("Successfully completed data transfer.\n");
- }
-
- fclose (fh);
- }
-
-
-