XP_DBLIB.C

//This is an example of an extended procedure DLL built with Open Data 
//Services. The functions within the DLL can be invoked by using the extended
//stored procedures support in SQL Server. To register the functions
//and allow all users to use them run the ISQL script XP_DBLIB.SQL.
//
//For further information on Open Data Services refer to the Microsoft Open
//Data Services Programmer's Reference.
//
// The extended procedures implemented in this DLL is:
//
// XP_GETTABLEUsed to show the creation of a new connection to SQL Server
//using DBLIB that is bound to the initial client connection;
//retrieves all rows from the table <table_name>, which is passed
//as an input parameter
//

#defineDBNTWIN32

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include<ctype.h>
#include<time.h>
#include <windows.h>

#include <sqlfront.h>
#include <sqldb.h>

#include <srv.h>


// Miscellaneous defines
//
#define XP_NOERROR0
#define XP_ERROR1

#define MAXLEN 255// Maximum string length
#define MAXNAME 31// Maximum name length

// Extended procedure error codes
#define SRV_MAXERROR 20000
#define GETTABLE_ERRORSRV_MAXERROR + 1
#define REMOTE_FAIL4002
#define REMOTE_MSGSRV_MAXERROR + 3


// Stored Procedure information structure.
typedef struct xp_info {
DBCHAR name[MAXNAME]; // Extended procedure name
DBCHAR usage[MAXLEN]; // Usage string
} XP_INFO;


int err_handler();
int msg_handler();


// Array of Extended Stored Procedures supported by this DLL.
XP_INFO Xps[] =
{

"xp_gettable",
"usage: xp_gettable <table_name>",
};


//
// XP_GETTABLE
// Returns the result of the SQL statement
//select * from <table_name>
//
// Parameters:
// srvproc - the handle to the client connection that got the SRV_CONNECT.
//
// Returns:
// XP_NOERROR
// XP_ERROR
//
// Side Effects:
// Returns messages and/or a result set to client.
//


RETCODE xp_gettable(srvproc)
SRV_PROC *srvproc;
{

DBPROCESS*dbproc;// DBPROCESS handle for the new connection
LOGINREC*loginrec;


intparamnum;
intbImpersonated;
DBCHARtable_name[MAXLEN];
DBINTparamtype;

charbindtoken[MAXLEN];
charSqlStmt[MAXLEN];

shortcols;// Data columns returned
inti;// Index variable
DBINTrows;// Number of rows sent
RETCODErc;// Value returned from DB-Library calls

// Get number of parameters
paramnum = srv_rpcparams(srvproc);

// Check number of parameters
if (paramnum != 1) {
// Send error message and return
srv_sendmsg(srvproc, SRV_MSG_ERROR, GETTABLE_ERROR, SRV_INFO, (DBTINYINT)0,
NULL, 0, 0, "Error executing extended stored procedure: Invalid Parameter",
SRV_NULLTERM);
// A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
// result set of an Extended Stored Procedure.
srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
return(XP_ERROR);
}

// Check parameters for correct type
paramtype = srv_paramtype(srvproc, paramnum);
if (paramtype != SRVVARCHAR) {
// Send error message and return
srv_sendmsg(srvproc, SRV_MSG_ERROR, GETTABLE_ERROR, SRV_INFO, (DBTINYINT)0,
NULL, 0, 0,
"Error executing extended stored procedure: Invalid Parameter Type",
SRV_NULLTERM);
// A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
// result set of an Extended Stored Procedure.
srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
return(XP_ERROR);
}

// Terminate parameter string with NULL
sprintf(table_name, srv_paramdata(srvproc, 1));
table_name[srv_paramlen(srvproc, 1)] = '\0';

loginrec = dblogin();

dbprocerrhandle(loginrec, (DBERRHANDLE_PROC)err_handler);
dbprocmsghandle(loginrec, (DBMSGHANDLE_PROC)msg_handler);



// Check for integrated security
if (strcmp(srv_pfield(srvproc, SRV_LSECURE, (int *)NULL), "TRUE") == 0) {
// Client has accessed using some form of integrated security
// Impersonate client and set DBSETLSECURE flag

bImpersonated = srv_impersonate_client( srvproc );
DBSETLSECURE(loginrec);
}
else {
// Client used standard login
// Set the user name, password, and application name for the remote

DBSETLUSER( loginrec, srv_pfield(srvproc, SRV_USER, (int *)NULL) );
DBSETLPWD( loginrec, srv_pfield(srvproc, SRV_PWD, (int *)NULL) );
}


DBSETLAPP (loginrec, "xp_gettable");

// Try to open a connection to the local DBMS.
// Since the servername parameter is set to NULL, the connection will be
// opened to the local DBMS

//dbproc = dbopen(loginrec, "server_name");
dbproc = dbopen(loginrec, NULL);

dbsetuserdata(dbproc, (VOID *)srvproc);

//get the client session token
srv_getbindtoken (srvproc, bindtoken);

// put the SQL statement in the command buffer
srv_bzero(SqlStmt, MAXLEN);
sprintf (SqlStmt, "exec sp_bindsession \'%s\' ", bindtoken);

dbcmd (dbproc, SqlStmt);
dbsqlexec(dbproc);

while ((rc = dbresults (dbproc)) == NO_MORE_RESULTS);

// put the SQL statement in the command buffer
sprintf (SqlStmt, "select * from %s ", table_name);
rc=dbcmd (dbproc, SqlStmt);

//send the command buffer to SQL Server for execution
rc=dbsqlexec(dbproc);

// Process the results
while ((rc = dbresults (dbproc)) != NO_MORE_RESULTS)
{

// How many data columns are in the row?
cols = dbnumcols (dbproc);

// Build the row description for the client return.
for (i = 1; i <= cols; i++) {

// Call srv_describe for each column that will be sent back via ODS
//to the caller of the extended procedure
srv_describe (srvproc, i, (DBCHAR *)dbcolname (dbproc, i), SRV_NULLTERM,
(DBINT)dbcoltype (dbproc, i), dbcollen (dbproc, i),
(DBINT)dbcoltype (dbproc, i), dbcollen (dbproc, i),
(BYTE *)NULL);

}
rows = 0; // Initialize a counter for the row number.
while (dbnextrow (dbproc) != NO_MORE_ROWS){

// For each data field in the current row, fill the structure that will
// be sent back to the caller of the extended procedure
for (i = 1; i <= cols; i++){
srv_setcollen (srvproc, i, (short)dbdatlen (dbproc, i));
srv_setcoldata (srvproc, i, dbdata(dbproc, i));
}

// Send the data row back to SQL Server via ODS
if (srv_sendrow (srvproc) == SUCCEED)
rows++; // Go to the next row.
}
}


// Send the final done packet for the execution of the command
// batch. The previous batch was one that might have returned
// rows, so set the DONE status accordingly.
if (rows > 0)
srv_senddone (srvproc, SRV_DONE_COUNT | SRV_DONE_MORE,
(DBUSMALLINT) 0, rows);
else
srv_senddone (srvproc, SRV_DONE_MORE, (DBUSMALLINT) 0, (DBINT) 0);


// Close the connection to SQL Server.
dbclose( dbproc );
dbfreelogin( loginrec );

// Revert back to SQL Server's user account
//
if( bImpersonated )
srv_revert_to_self(srvproc);

return(XP_NOERROR);

}


int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
DBPROCESS*dbproc;
intseverity;
intdberr;
intoserr;
char*dberrstr;
char*oserrstr;
{

SRV_PROC *srvproc = (SRV_PROC *)NULL;

srvproc = (SRV_PROC *)dbgetuserdata(dbproc);

srv_sendmsg(srvproc, SRV_MSG_ERROR, (DBINT)REMOTE_MSG,
(DBTINYINT)severity, (DBTINYINT)0, NULL, 0, 0, dberrstr,
SRV_NULLTERM);

if ((dbproc == NULL) || (DBDEAD(dbproc)))
return(INT_EXIT);

return(INT_CANCEL);
}


int msg_handler(dbproc, msgno, msgstate, severity, msgtext)
DBPROCESS*dbproc;
DBINTmsgno;
intmsgstate;
intseverity;
char*msgtext;
{

SRV_PROC *srvproc = (SRV_PROC *)NULL;

srvproc = (SRV_PROC *)dbgetuserdata(dbproc);

if (severity < 10) { // if informational message

srv_sendmsg(srvproc, SRV_MSG_INFO, msgno, (DBTINYINT)severity,
(DBTINYINT)msgstate, NULL, 0, 0, (DBCHAR *)msgtext, SRV_NULLTERM);
return(0);
}

// Trap login fail message
if (msgno == REMOTE_FAIL){
// Send a message to the client that
// the remote connection failed.
//
srv_sendmsg(srvproc, SRV_MSG_ERROR, (DBINT)msgno, (DBTINYINT)severity,
(DBTINYINT)msgstate, NULL, 0, 0,
"Login to remote DBMS failed (dbopen).", SRV_NULLTERM);
}

// must be an error message
srv_sendmsg(srvproc, SRV_MSG_ERROR, msgno, (DBTINYINT)severity,
(DBTINYINT)msgstate, NULL, 0, 0, (DBCHAR *)msgtext, SRV_NULLTERM);

return(0);

}