XP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:31k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // This is an example of an extended procedure DLL built with Open Data
  2. // Services. The functions within the DLL can be invoked by using the extended
  3. // stored procedures support in SQL Server.  To register the functions 
  4. // and allow all users to use them run the ISQL script INSTXP.SQL.
  5. //
  6. // For further information on Open Data Services refer to the Microsoft Open 
  7. // Data Services Programmer's Reference.
  8. //
  9. //  The extended procedures implemented in this DLL are:
  10. //
  11. //  XP_PROCLIST Returns all this DLL's extended stored procedures and 
  12. // their usuage.
  13. //
  14. //  XP_DISKLIST Returns a row for each defined drive containing its name 
  15. // and the amount of disk space available.
  16. //
  17. //  XP_DISKFREE   Returns the amount of space available on a given drive.
  18. //             The value is placed into the defined return parameter of
  19. //             the stored procedure.
  20. //
  21. //  XP_SCAN_XBASE Reads an xBase file and sends it to the client as if it 
  22. // were a SQL Server query result set (the equivalent of a 
  23. // 'SELECT * FROM tablename' SQL statement).
  24. //
  25. //  XP_ECHO Used to demo the handling of output parameters in
  26. // extended procedures.
  27. //
  28. //  XP_TRACE Used to show the installation and removal of pre-handlers
  29. // for language and rpc events. The pre-handlers installed
  30. // just print langauge and rpc events to the console in
  31. // readable form.  Start SQL Server at the command line
  32. // to see the output.
  33. //
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <windows.h>
  39. #include <srv.h>
  40. #include <time.h>
  41. // Miscellaneous defines
  42. //
  43. #define  XP_NOERROR 0
  44. #define  XP_ERROR 1
  45. #define  MAXNAME       31 // Maximum extended procedure name length
  46. #define  MAXLEN        80 // Maximum string length
  47. #define  COMMAND_PARAM 1 // Command Parameter
  48. #define  OUTPUT_PARAM 2 // Command Parameter
  49. // Extended procedure error codes
  50. //
  51. #define  SRV_MAXERROR           20000
  52. #define  XP_PROCLIST_ERROR      SRV_MAXERROR + 1
  53. #define  CMDSHELL_ERROR         SRV_MAXERROR + 2
  54. #define  DISKLIST_ERROR         SRV_MAXERROR + 3
  55. #define  SCAN_XBASE_ERROR       SRV_MAXERROR + 4
  56. #define  TRACE_ERROR       SRV_MAXERROR + 6
  57. // Standard error macro for reporting API errors
  58. //
  59. #define SETERROR( api, retstring)               
  60.     sprintf(retstring,"%s: Error %d from %s on line %dn",  
  61.         __FILE__, GetLastError(), api, __LINE__);
  62.  
  63. // SCAN_XBASE defines
  64. //
  65. #define XBASE_HDR_SIZE   32
  66. #define XBASE_MAX_COLUMNS  128
  67. #define XBASE_BUF_SIZE     2048
  68. // function prototypes for xp_trace callbacks
  69. SRVRETCODE trace_lang(SRV_PROC *);
  70. SRVRETCODE trace_rpc(SRV_PROC *);
  71. // Stored Procedure information structure.
  72. //
  73. typedef struct xp_info {
  74.     DBCHAR name[MAXNAME];    // Extended procedure name
  75.     DBCHAR usage[MAXLEN];    // Usage string
  76. } XP_INFO;
  77. // Array of Extended Stored Procedures supported by this DLL.
  78. //
  79. XP_INFO Xps[] = 
  80. {
  81.     "xp_proclist", // Procedure name
  82.     "usage: xp_proclist",   // Procedure usage string
  83.     "xp_disklist",
  84.     "usage: xp_disklist",
  85.     "xp_diskfree",
  86.     "usage: xp_diskfree <[@drive =] drive letter> [,] <[@space =] free space>",
  87.     "xp_scan_xbase",
  88.     "usage: xp_scan_xbase <xbase file name>",
  89.     "xp_echo",
  90.     "usage: xp_echo @p1=<input> , @p2=<output-param> output",
  91.     "xp_trace",
  92.     "usage: xp_trace <[@state=] 'on'|'off'> [, [@users=] NULL | 'all']",
  93. };
  94. #define Xpcnumber sizeof(Xps) / sizeof(XP_INFO)
  95. //
  96. // PROCLIST
  97. //    Returns the usage for all defined stored procedures
  98. //
  99. // Parameters:
  100. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  101. //
  102. // Returns:
  103. //    XP_NOERROR
  104. //    XP_ERROR
  105. //
  106. // Side Effects:
  107. //    Returns a result set to client
  108. //
  109. SRVRETCODE xp_proclist(srvproc)
  110. SRV_PROC *srvproc;
  111. {
  112.     int paramnum;
  113.     DBCHAR colname1[MAXNAME];
  114.     DBCHAR colname2[MAXNAME];
  115.     int i;
  116.     // Get number of parameters
  117.     //
  118.     paramnum = srv_rpcparams(srvproc);
  119.     // Check number of parameters
  120.     //
  121.     if (paramnum != -1) {
  122.         // Send error message and return
  123.         //
  124.         srv_sendmsg(srvproc, SRV_MSG_ERROR, XP_PROCLIST_ERROR, SRV_INFO, (DBTINYINT)0,
  125.                     NULL, 0, 0, "Error executing extended stored procedure: Invalid Parameter",
  126.                     SRV_NULLTERM);
  127.     // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  128.     // result set of an Extended Stored Procedure.
  129.     //
  130.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  131. return(XP_ERROR);
  132.     }
  133.     sprintf(colname1, "spname");
  134.     srv_describe(srvproc, 1, colname1, SRV_NULLTERM, SRVCHAR, MAXNAME,
  135.                  SRVCHAR, 0, NULL);
  136.     sprintf(colname2, "spusage");
  137.     srv_describe(srvproc, 2, colname2, SRV_NULLTERM, SRVCHAR, MAXLEN, SRVCHAR,
  138.                  0, NULL);
  139.     // Return each XP handler as a row
  140.     //
  141.     for (i = 0; i < Xpcnumber; i++) {
  142.         srv_setcoldata(srvproc, 1, Xps[i].name);
  143.         srv_setcollen(srvproc, 1, strlen(Xps[i].name));
  144.         srv_setcoldata(srvproc, 2, Xps[i].usage);
  145.         srv_setcollen(srvproc, 2, strlen(Xps[i].usage));
  146.         srv_sendrow(srvproc);
  147.     }
  148.  // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  149.  // result set of an Extended Stored Procedure.
  150.  //
  151.     srv_senddone(srvproc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, i);
  152.     return(XP_NOERROR);
  153. }
  154. //
  155. // XP_ECHO
  156. // Used to demo the handling of output parameters in extended procedures.
  157. // The first parameter should be the input parameter and the second
  158. // parameter should be the output.  The input parameter is placed in the
  159. // output parameter and returned.
  160. //
  161. // Parameters:
  162. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  163. //
  164. // Returns:
  165. //    XP_NOERROR
  166. //    XP_ERROR
  167. //
  168. //
  169. SRVRETCODE xp_echo(srvproc)
  170. SRV_PROC *srvproc;
  171. {
  172.     int paramnum;
  173.     // Check number of parameters
  174.     //
  175.     if ((paramnum = srv_rpcparams(srvproc)) != 2) {
  176.         // Send error message and return
  177.         //
  178.         srv_sendmsg(srvproc, SRV_MSG_ERROR, CMDSHELL_ERROR, SRV_INFO, (DBTINYINT)0,
  179.     NULL, 0, 0, "Error executing extended stored procedure: Invalid # of Parameters",
  180.                     SRV_NULLTERM);
  181.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  182.      // result set of an Extended Stored Procedure.
  183.      //
  184.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  185. return(XP_ERROR);
  186.     }
  187.     // Set output parameter to input parameter.
  188.     //
  189.     srv_paramset(srvproc, 2, srv_paramdata(srvproc,1), srv_paramlen(srvproc,1));
  190.     srv_senddone(srvproc, SRV_DONE_MORE, 0, 0);
  191.     return(XP_NOERROR);
  192. }
  193. //
  194. // XP_DISKLIST
  195. //     Returns a row for each defined drive containing its name and the
  196. //     amount of disk space available.
  197. //
  198. // Parameters:
  199. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  200. //
  201. // Returns:
  202. //    XP_NOERROR
  203. //    XP_ERROR
  204. //
  205. // Side Effects:
  206. //     Returns a result set to client
  207. //
  208. SRVRETCODE xp_disklist(srvproc)
  209. SRV_PROC *srvproc;
  210. {
  211.     int paramnum;
  212.     DBCHAR colname1[MAXNAME];
  213.     DBCHAR colname2[MAXNAME];
  214.     DBCHAR drivename;
  215.     DBCHAR rootname[16];
  216.     int drivenum;
  217.     int secPerCluster;
  218.     int bytesPerSector;
  219.     int freeClusters;
  220.     int totalClusters;
  221.     int drivenums;
  222.     int space_remaining;
  223.     int i = 0;
  224.     // Get number of parameters
  225.     //
  226.     paramnum = srv_rpcparams(srvproc);
  227.     // Check number of parameters
  228.     //
  229.     if (paramnum != -1) {
  230.         // Send error message and return
  231.         //
  232.         srv_sendmsg(srvproc, SRV_MSG_ERROR, DISKLIST_ERROR, SRV_INFO, (DBTINYINT)0,
  233.                     NULL, 0, 0, "Error executing extended stored procedure: Invalid Parameter",
  234.                     SRV_NULLTERM);
  235.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  236.      // result set of an Extended Stored Procedure.
  237.      //
  238.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  239. return(XP_ERROR);
  240.     }
  241.     sprintf(colname1, "drive");
  242.     srv_describe(srvproc, 1, colname1, SRV_NULLTERM, SRVCHAR, 1, SRVCHAR, 1,
  243.                  (BYTE *)&drivename);
  244.     sprintf(colname2, "bytes free");
  245.     srv_describe(srvproc, 2, colname2, SRV_NULLTERM, SRVINT4, 4, SRVINT4, 4,
  246.                  (BYTE *)&space_remaining);
  247.     drivenums = GetLogicalDrives();
  248.     drivenums >>= 2;        //Ignore drives A and B
  249.     for (drivename = 'C', drivenum = 3; drivename <= 'Z';
  250.          drivename++, drivenum++) {
  251.         if (drivenums & 1) {
  252.             i++;
  253.             sprintf(rootname, "%c:\", drivename);
  254.             GetDiskFreeSpace(rootname, &secPerCluster, &bytesPerSector,
  255.                              &freeClusters, &totalClusters);
  256.             space_remaining = secPerCluster * freeClusters * bytesPerSector;
  257.             srv_sendrow(srvproc);
  258.         }
  259.         drivenums >>= 1;
  260.     }
  261.     // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  262.     // result set of an Extended Stored Procedure.
  263.     //
  264.     srv_senddone(srvproc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, i);
  265.     return(XP_NOERROR);
  266. }
  267. //
  268. // XP_DISKFREE
  269. //    Returns the amount of space available on a given drive. The value
  270. //     is placed into the defined return parameter of the stored procedure.
  271. //
  272. // Parameters:
  273. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  274. //
  275. // Returns:
  276. //    XP_NOERROR
  277. //    XP_ERROR
  278. //
  279. // Side Effects:
  280. //    Returns messages and/or a result set to client. Returns a value in the
  281. //     defined return parameter.
  282. //
  283. SRVRETCODE xp_diskfree(srvproc)
  284. SRV_PROC *srvproc;
  285. {
  286.     DBCHAR *drive;
  287.     DBCHAR colname1[MAXNAME];
  288.     DBCHAR colname2[MAXNAME];
  289.     DBINT paramlength;
  290.     DBCHAR rootname[16];
  291.     DBCHAR bErrorMsg[MAXLEN];
  292.     int drivenum;
  293.     int drivenums;
  294.     int secPerCluster;
  295.     int bytesPerSector;
  296.     int freeClusters;
  297.     int totalClusters;
  298.     int space_remaining = -1;
  299.     // Check number of parameters
  300.     //
  301.     if (srv_rpcparams(srvproc) > 0) {
  302. // Allocation local storage for drive name.
  303. //
  304. paramlength = srv_paramlen(srvproc, 1);
  305. drive = (DBCHAR *)malloc(paramlength);
  306. if (!drive) {
  307.     SETERROR("Malloc", bErrorMsg);
  308.     srv_sendmsg(srvproc, SRV_MSG_ERROR, CMDSHELL_ERROR, SRV_INFO, (DBTINYINT)0,
  309.        NULL, 0, 0, bErrorMsg, SRV_NULLTERM);
  310.     // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  311.     // result set of an Extended Stored Procedure.
  312.     //
  313.     srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  314.     return(XP_ERROR);
  315. }
  316. // Fetch drive letter.
  317. srv_bmove(srv_paramdata(srvproc, 1), drive, paramlength);
  318. drive = strupr(drive);
  319.     } else
  320. // Default drive is C.
  321. drive = "C";
  322.     drivenums = GetLogicalDrives();
  323.     drivenum = drive[0] - 'A' + 1;
  324.     drivenums >>= drivenum - 1; //Ignore drives A and B
  325.     if (drivenums & 0x01) {
  326.         sprintf(rootname, "%c:\", drive[0]);
  327.         GetDiskFreeSpace(rootname, &secPerCluster, &bytesPerSector,
  328.                          &freeClusters, &totalClusters);
  329.         space_remaining = secPerCluster * freeClusters * bytesPerSector;
  330.     }
  331.     // Process return values
  332.     //
  333.     if (srv_paramstatus(srvproc, 2) < 0 ) {
  334. // Setup column heading
  335. sprintf(colname1, "drive");
  336. sprintf(colname2, "space");
  337. srv_describe(srvproc, 1, colname1, SRV_NULLTERM, SRVCHAR, 1, SRVCHAR, 1,
  338.      (BYTE *)drive);
  339. srv_describe(srvproc, 2, colname2, SRV_NULLTERM,
  340.      SRVINT4, sizeof(space_remaining), SRVINT4,
  341.      sizeof(space_remaining), &space_remaining);
  342. srv_sendrow(srvproc);
  343. srv_senddone(srvproc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, 1);
  344.    }
  345.     else {
  346. srv_paramset(srvproc, 2, (BYTE *)&space_remaining, 4);
  347. srv_senddone(srvproc, SRV_DONE_MORE, 0, 0);
  348.     }
  349.     return(XP_NOERROR);
  350. }
  351. //
  352. // XP_SCAN_XBASE
  353. //    Reads an xBase file and sends it to the client as if it were a SQL
  354. //    Server query result set (the equivalent of a 'SELECT * FROM
  355. //    tablename' SQL statement).
  356. //
  357. // Parameters:
  358. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  359. //
  360. // Returns:
  361. //    XP_NOERROR
  362. //    XP_ERROR
  363. //
  364. // Side Effects:
  365. //    Returns messages and/or a result set to client
  366. //
  367. SRVRETCODE xp_scan_xbase(srvproc)
  368. SRV_PROC *srvproc;
  369. {
  370.     int paramnum;
  371.     DBINT paramtype;
  372.     DBCHAR *filename;
  373.     FILE *xbasefile;
  374.     size_t count;
  375.     char buffer[XBASE_BUF_SIZE];
  376.     short numrecords;
  377.     short headerlength;
  378.     short recordlength;
  379.     short lengthlist[XBASE_MAX_COLUMNS];
  380.     int i;
  381.     short j;
  382.     short position;
  383.     short numcolumns;
  384.     // Get number of parameters
  385.     //
  386.     paramnum = srv_rpcparams(srvproc);
  387.     // Check number of parameters
  388.     //
  389.     if (paramnum != 1) {
  390.         // Send error message and return
  391.         //
  392.         srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  393.                     NULL, 0, 0, "Error executing extended stored procedure: Invalid Parameter",
  394.                     SRV_NULLTERM);
  395.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  396.      // result set of an Extended Stored Procedure.
  397.      //
  398.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  399. return(XP_ERROR);
  400.     }
  401.     // Check parameters for correct type
  402.     //
  403.     paramtype = srv_paramtype(srvproc, paramnum);
  404.     if (paramtype != SRVVARCHAR) {
  405.         // Send error message and return
  406.         //
  407.         srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  408.                     NULL, 0, 0,
  409.                     "Error executing extended stored procedure: Invalid Parameter Type",
  410.                     SRV_NULLTERM);
  411.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  412.      // result set of an Extended Stored Procedure.
  413.      //
  414.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  415. return(XP_ERROR);
  416.     }
  417.     filename = srv_paramdata(srvproc, 1);
  418.     // now read the database header info
  419.     //
  420.     if ((xbasefile = fopen(filename, "r")) == NULL) {
  421.         srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  422.                     NULL, 0, 0, "Error reading xBase file", SRV_NULLTERM);
  423.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  424.      // result set of an Extended Stored Procedure.
  425.      //
  426.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  427. return(XP_ERROR);
  428.     }
  429.     count = fread(buffer, XBASE_HDR_SIZE, 1, xbasefile);
  430.     if (count == 0) {
  431.         srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  432.                     NULL, 0, 0, "Error reading xBase file", SRV_NULLTERM);
  433.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  434.      // result set of an Extended Stored Procedure.
  435.      //
  436.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  437.         fclose(xbasefile);
  438. return(XP_ERROR);
  439.     }
  440.     numrecords = *((short *)&buffer[4]);
  441.     headerlength = *((short *)&buffer[8]);
  442.     recordlength = *((short *)&buffer[10]);
  443.     numcolumns = (headerlength - 32 - 1) / 32;
  444.     // now get the column header information
  445.     //
  446.     for (j = 0; j < numcolumns; j++) {
  447.         count = fread(buffer,
  448.         XBASE_HDR_SIZE,
  449.         1,
  450.         xbasefile);
  451.         if (count == 0) {
  452.             srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  453.                         NULL, 0, 0, "Error reading xBase file", SRV_NULLTERM);
  454.          // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  455.          // result set of an Extended Stored Procedure.
  456.          //
  457.             srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  458.             fclose(xbasefile);
  459.     return(XP_ERROR);
  460.         }
  461.         // we need to NULL terminate the column name (if it is a
  462.         // full 11 characters int)
  463.         //
  464.         buffer[11] = '';
  465.         // now find our the column length for this data buffer
  466.         //
  467.         lengthlist[j] = (short)buffer[16];
  468.         // now 'describe' this column
  469.         //
  470.         srv_describe(srvproc, j + 1,// column number
  471.                 buffer,     // pointer to column name
  472.                 SRV_NULLTERM,// column name is NULL terminated
  473.                 SRVCHAR,    // datatype is char (xBase numbers are ASCII
  474.                 lengthlist[j],// column length
  475.                 SRVCHAR,    // destination datatype is also char
  476.                 lengthlist[j],// destination column length
  477.                 NULL);      // pointer to where the data will be
  478.     }
  479.     // now read the one byte 'column header seperator'
  480.     //
  481.     count = fread(buffer, 1, 1, xbasefile);
  482.     if (count == 0) {
  483.         srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  484.                     NULL, 0, 0, "Error reading xBase file", SRV_NULLTERM);
  485.      // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  486.      // result set of an Extended Stored Procedure.
  487.      //
  488.         srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  489.         fclose(xbasefile);
  490. return(XP_ERROR);
  491.     }
  492.     for (i = 0; i < numrecords; i++) {
  493.         count = fread(buffer, recordlength, 1, xbasefile);
  494.         if (count == 0 && !feof(xbasefile)) {
  495.             srv_sendmsg(srvproc, SRV_MSG_ERROR, SCAN_XBASE_ERROR, SRV_INFO, (DBTINYINT)0,
  496.                         NULL, 0, 0, "Error reading xBase file", SRV_NULLTERM);
  497.          // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  498.          // result set of an Extended Stored Procedure.
  499.          //
  500.             srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  501.             fclose(xbasefile);
  502.     return(XP_ERROR);
  503.         }
  504.         // check to see if this is a deleted row
  505.         //
  506.         if (buffer[0] == '*')
  507.             break;
  508.         // Now set the length and data pointers for each column
  509.         for (j = 0, position = 1; j < numcolumns; j++) {
  510.             srv_setcollen(srvproc, j + 1, lengthlist[j]);
  511.             srv_setcoldata(srvproc, j + 1, &buffer[position]);
  512.             position += lengthlist[j];
  513.         }
  514.         // send the row to the client.
  515.         //
  516.         srv_sendrow(srvproc);
  517.     }
  518.  // A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  519.  // result set of an Extended Stored Procedure.
  520.  //
  521.     srv_senddone(srvproc, SRV_DONE_COUNT | SRV_DONE_MORE, 0, i);
  522.     fclose(xbasefile);
  523.     return(XP_NOERROR);
  524. }
  525. //
  526. // XP_TRACE
  527. // Used to demo the proc-specific pre-handlers in extended procedures.
  528. // Parameter 1 is @state, "on" or "off" to install or remove.  
  529. // Parameter 2 is @users, NULL to install pre-handlers on this
  530. // srvproc only , or 'all' to install server-wide pre-handlers
  531. //
  532. // Parameters:
  533. //    srvproc - the handle to the client connection that got the SRV_CONNECT.
  534. //
  535. // Returns:
  536. //    XP_NOERROR
  537. //    XP_ERROR
  538. //
  539. SRVRETCODE xp_trace(srvproc)
  540. SRV_PROC *srvproc;
  541. {
  542.     int      numparams;
  543.     DBCHAR * paramname;
  544.     int      i;
  545.     int      position;
  546.     int      len;
  547.     DBINT    paramtype;
  548.     DBINT    paramlength;
  549. char state[4];
  550. char users[4];
  551. char timestr[9];
  552. char *errmsg;
  553. SRV_SERVER *server;
  554. int retcode;
  555. state[0] = '';
  556. users[0] = '';
  557.     // Check parameters
  558. // Support both named and positional parameters
  559. //
  560. numparams = srv_rpcparams( srvproc );
  561.     if ((numparams < 1) || (numparams > 2)) {
  562.         errmsg = "Error: Invalid number of Parameters";
  563. goto ErrorExit;                    
  564.     }
  565.     for( i = 1; i <= numparams; i++ )
  566.     {
  567.         paramname = srv_paramname( srvproc, i, &len );
  568.         if( len )
  569.         {
  570.             if( !stricmp(paramname, "@state") )
  571.                 position = 1;
  572.             else if( !stricmp(paramname, "@users") )
  573.                 position = 2;
  574.             else {
  575.                 srv_sendmsg( srvproc,SRV_MSG_ERROR,TRACE_ERROR,
  576.                              16,(DBTINYINT)1,NULL,0,0,"Invalid Parameter",SRV_NULLTERM );
  577.                 return FAIL;
  578.             }
  579.         }
  580.         else
  581.             position = i;
  582.         paramtype   = srv_paramtype( srvproc, i );
  583.         if ( (paramlength = srv_paramlen( srvproc, i )) > 3 )
  584.          {
  585. errmsg = "Error:  Parameter value too long";
  586. goto ErrorExit;
  587. }        
  588.         switch( position )
  589.         {
  590.         case 1: // @state
  591.             if( paramtype != SRVVARCHAR && paramtype != SRVNULL )
  592.             {
  593.         errmsg = "Error:  Invalid @state parameter type, expecting varchar";
  594. goto ErrorExit;                    
  595.             }
  596. srv_bmove(srv_paramdata(srvproc, i), state, paramlength);
  597. state[paramlength] = '';
  598.         break;
  599.         case 2: // @users
  600.             if( paramtype != SRVVARCHAR && paramtype != SRVNULL )
  601.             {
  602.         errmsg = "Error:  Invalid @users parameter type, expecting varchar";
  603. goto ErrorExit;                    
  604.             }
  605. srv_bmove(srv_paramdata(srvproc, i), users, paramlength);
  606. users[paramlength] = '';
  607.             
  608.             if ( (stricmp(users,"all") != 0) && paramlength ) 
  609. {
  610.         errmsg = "Error:  Invalid @users parameter, must be 'all' or NULL";
  611. goto ErrorExit;                    
  612. }
  613. break;
  614.         } // switch( position )
  615.     } // for( i = 1; i <= numparams; i++ )
  616. // check for required 1st parameter
  617. if ( (stricmp(state,"on") != 0) && (stricmp(state,"off") != 0) ) 
  618. {
  619. errmsg = "Error:  Required @state parameter must be 'on' or 'off'";
  620. goto ErrorExit;                    
  621. }    
  622. if (!stricmp(state,"on") && !strlen(users)) {
  623. // turn on trace for just this srvproc
  624. srv_pre_handle(NULL,srvproc,SRV_LANGUAGE,trace_lang,FALSE);
  625. retcode = srv_pre_handle(NULL,srvproc,SRV_RPC,trace_rpc,FALSE);
  626. switch (retcode) {
  627. case FAIL:
  628. errmsg = "Error installing pre-handlers";
  629. goto ErrorExit;                    
  630. case SRV_DUPLICATE_HANDLER:
  631. errmsg = "Pre-handler already installed";
  632. goto ErrorExit;                    
  633. default:
  634. printf("%s  starting trace for KPID %sn", _strtime(timestr),
  635. srv_pfield(srvproc, SRV_SPID, NULL));
  636. }
  637. }
  638. else if (!stricmp(state,"off") && !strlen(users)) {
  639. // set remove flag to true
  640. srv_pre_handle(NULL,srvproc,SRV_LANGUAGE,trace_lang,TRUE);
  641. retcode = srv_pre_handle(NULL,srvproc,SRV_RPC,trace_rpc,TRUE);
  642. switch (retcode) {
  643. case FAIL:
  644. errmsg = "Pre-handler not found";
  645. goto ErrorExit;                    
  646. default:
  647. printf("%s  stopping trace for KPID %sn", _strtime(timestr),
  648. srv_pfield(srvproc, SRV_SPID, NULL));
  649. }
  650. }
  651. else if (!stricmp(state,"on") && !stricmp(users, "all")) {
  652. // turn on trace for all connections
  653. server = SRV_GETSERVER(srvproc);
  654. srv_pre_handle(server,NULL,SRV_LANGUAGE,trace_lang,FALSE);
  655. retcode = srv_pre_handle(server,NULL,SRV_RPC,trace_rpc,FALSE);
  656. switch (retcode) {
  657. case FAIL:
  658. errmsg = "Error installing pre-handlers";
  659. goto ErrorExit;                    
  660. case SRV_DUPLICATE_HANDLER:
  661. errmsg = "Pre-handler already installed";
  662. goto ErrorExit;                    
  663. default:
  664. printf("%s  starting trace for all connections n", _strtime(timestr));
  665. }
  666. }
  667. else if (!stricmp(state,"off") && !stricmp(users, "all")) {
  668. // set remove flag to true
  669. server = SRV_GETSERVER(srvproc);
  670. srv_pre_handle(server,NULL,SRV_LANGUAGE,trace_lang,TRUE);
  671. retcode = srv_pre_handle(server,NULL,SRV_RPC,trace_rpc,TRUE);
  672. switch (retcode) {
  673. case FAIL:
  674. errmsg = "Pre-handler not found";
  675. goto ErrorExit;                    
  676. default:
  677. printf("%s  stopping trace for all connections n", _strtime(timestr));
  678. }
  679. }
  680. else {
  681.         errmsg = "Error in xp_trace logic";
  682. goto ErrorExit;                    
  683. }
  684.     
  685.     return(XP_NOERROR);
  686. ErrorExit:
  687. // Send error message and return
  688.     //
  689.     srv_sendmsg(srvproc, SRV_MSG_ERROR, TRACE_ERROR, SRV_INFO, (DBTINYINT)0,
  690.     NULL, 0, 0, errmsg, SRV_NULLTERM);
  691.      
  692.     srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
  693. return(XP_ERROR);
  694. }
  695. //****************************************************************************
  696. // trace_lang
  697. //      This is the pre-language handler routine to print language requests to 
  698. // stdio
  699. //
  700. // Parameters:
  701. //    srvproc - a pointer to SRV_PROC stucture
  702. //
  703. // Returns:
  704. //    SRV_CONTINUE
  705. //
  706. // Side Effects:
  707. //
  708. //****************************************************************************
  709. SRVRETCODE trace_lang(srvproc)
  710. SRV_PROC *srvproc;
  711. {
  712.     char timestr[9];
  713. DBCHAR *query;
  714. int query_len;
  715. query= srv_langptr(srvproc);
  716. query_len = srv_langlen(srvproc);
  717.     //print the request
  718.     printf("%s  KPID %s lang:  %sn", _strtime(timestr),
  719.      srv_pfield(srvproc, SRV_SPID, (int *)NULL),query);
  720. if (query[query_len-1] != 'n')
  721. printf("n");
  722.     return(SRV_CONTINUE);
  723. }
  724. //****************************************************************************
  725. // trace_rpc
  726. //      This is the pre-rpc handler routine to print language requests to 
  727. // stdio
  728. //
  729. // Parameters:
  730. //    srvproc - a pointer to SRV_PROC stucture
  731. //
  732. // Returns:
  733. //    SRV_CONTINUE
  734. //
  735. // Side Effects:
  736. //
  737. //****************************************************************************
  738. SRVRETCODE trace_rpc(srvproc)
  739. SRV_PROC *srvproc;
  740. {
  741.     int i;                  // Index variable
  742.     short params;
  743.     DBCHAR complete_rpc_name[4 * (MAXNAME + 1)]; //database.owner.name;#
  744. DBCHAR *rpc_db;
  745. DBCHAR *rpc_owner;
  746. DBCHAR *rpc_name;
  747. int rpc_number;
  748. char rpc_number_char[17];
  749. DBCHAR *rpc_paramname;
  750. DBCHAR * rpc_paramstatus;
  751. int rpc_paramtype;
  752. DBINT rpc_parammaxlen;
  753. DBINT rpc_paramlen;
  754. void *rpc_paramdata;
  755. char rpc_paramstr[256];
  756. char timestr[9];
  757. DBCHAR * rpc_typename;
  758. DBCHAR sztypestr[20];
  759. DBNUMERIC numeric;
  760.     
  761.     // Construct full RPC name 
  762.     //
  763. memset (complete_rpc_name, 0, sizeof(complete_rpc_name));
  764. rpc_db = srv_rpcdb(srvproc, (int *)NULL);
  765. rpc_owner = srv_rpcowner(srvproc, (int *)NULL);
  766. rpc_name = srv_rpcname(srvproc, (int *)NULL);
  767. rpc_number = srv_rpcnumber(srvproc);
  768. if (rpc_db != NULL) {
  769. strcat(complete_rpc_name,rpc_db);
  770. strcat(complete_rpc_name,".");
  771. };
  772. if (rpc_owner != NULL) {
  773. strcat(complete_rpc_name,rpc_owner);
  774. strcat(complete_rpc_name,".");
  775. };
  776. strcat(complete_rpc_name,rpc_name);
  777. if (rpc_number > 0) {
  778.      strcat(complete_rpc_name,";");
  779. _itoa(rpc_number,rpc_number_char,10);
  780. strcat(complete_rpc_name, rpc_number_char);
  781. };
  782. //start printing the request
  783.     printf("%s  KPID %s rpc:  %s", _strtime(timestr),
  784.      srv_pfield(srvproc, SRV_SPID, (int *)NULL),complete_rpc_name);
  785.     
  786.     // Set up any RPC parameters.
  787.     //
  788.     params = srv_rpcparams(srvproc);
  789.     for (i = 1; i <= params; i++) {
  790. rpc_paramname = srv_paramname(srvproc, i, (int *)NULL);
  791. if (strlen(rpc_paramname) == 0) rpc_paramname = NULL;
  792.         if ((BYTE)srv_paramstatus(srvproc, i) == SRV_PARAMRETURN)
  793.          rpc_paramstatus = "OUT";
  794. else
  795. rpc_paramstatus = " ";
  796.         rpc_paramtype = srv_paramtype(srvproc, i);
  797.         rpc_parammaxlen = srv_parammaxlen(srvproc, i);
  798. rpc_paramlen = srv_paramlen(srvproc, i);
  799.         rpc_paramdata = srv_paramdata(srvproc, i);      
  800. switch (rpc_paramtype) {
  801. case SRVVARCHAR:
  802. sprintf(sztypestr, "%s(%d)","varchar",rpc_parammaxlen);
  803. break;
  804. case SRVCHAR:
  805. sprintf(sztypestr, "%s(%d)","char",rpc_parammaxlen);
  806. break;
  807. case SRVINTN:
  808. switch (rpc_paramlen) {
  809. case 1:
  810. rpc_typename = "tinyint";
  811. break;
  812. case 2:
  813. rpc_typename = "smallint";
  814. break;
  815. default:
  816. rpc_typename = "int";
  817. break;
  818. }
  819. sprintf(sztypestr, "%s null",rpc_typename);
  820. break;
  821. case SRVINT1:
  822. sprintf(sztypestr, "tinyint");
  823. break;
  824. case SRVINT2:
  825. sprintf(sztypestr, "smallint");
  826. break;
  827. case SRVINT4:
  828. sprintf(sztypestr, "int");
  829. break;
  830. case SRVMONEYN:
  831. switch (rpc_paramlen) {
  832. case 4:
  833. rpc_typename = "smallmoney";
  834. break;
  835. default:
  836. rpc_typename = "money";
  837. break;
  838. }
  839. sprintf(sztypestr, "%s null",rpc_typename);
  840. break;
  841. case SRVMONEY4:
  842. sprintf(sztypestr, "smallmoney");
  843. break;
  844. case SRVMONEY:
  845. sprintf(sztypestr, "money");
  846. break;
  847. case SRVDATETIMN:
  848. switch (rpc_paramlen) {
  849. case 4:
  850. rpc_typename = "smalldatetime";
  851. break;
  852. default:
  853. rpc_typename = "datetime";
  854. break;
  855. }
  856. sprintf(sztypestr, "%s null",rpc_typename);
  857. break;
  858. case SRVDATETIM4:
  859. sprintf(sztypestr, "smalldatetime");
  860. break;
  861. case SRVDATETIME:
  862. sprintf(sztypestr, "datetime");
  863. break;
  864. case SRVFLTN:
  865. switch (rpc_paramlen) {
  866. case 4:
  867. rpc_typename = "real";
  868. break;
  869. default:
  870. rpc_typename = "float";
  871. break;
  872. }
  873. sprintf(sztypestr, "%s null",rpc_typename);
  874. break;
  875. case SRVFLT4:
  876. sprintf(sztypestr, "real");
  877. break;
  878. case SRVFLT8:
  879. sprintf(sztypestr, "float");
  880. break;
  881. case SRVNUMERIC:
  882. case SRVNUMERICN:
  883. case SRVDECIMAL:
  884. case SRVDECIMALN:
  885. memset (&numeric, 0, sizeof(DBNUMERIC));
  886. memmove (&numeric, rpc_paramdata, rpc_paramlen);
  887. rpc_paramdata = &numeric;
  888. switch (rpc_paramtype) {
  889. case SRVNUMERIC:
  890. case SRVNUMERICN:
  891. rpc_typename = "numeric";
  892. break;
  893. case SRVDECIMAL:
  894. case SRVDECIMALN:
  895. rpc_typename = "decimal";
  896. break;
  897. }
  898. sprintf(sztypestr, "%s(%d,%d)",rpc_typename, numeric.precision, numeric.scale);
  899. if (rpc_paramlen == 2) 
  900. rpc_paramlen = 0;
  901. break;
  902. case SRVTEXT:
  903. sprintf(sztypestr, "text");
  904. break;
  905. case SRVIMAGE:
  906. sprintf(sztypestr, "image");
  907. break;
  908. case SRVVARBINARY:
  909. sprintf(sztypestr, "%s(%d)","varbinary",rpc_parammaxlen);
  910. break;
  911. case SRVBINARY:
  912. sprintf(sztypestr, "%s(%d)","binary",rpc_parammaxlen);
  913. break;
  914. case SRVBIT:
  915. sprintf(sztypestr, "bit");
  916. break;
  917. case SRVNULL:
  918. sprintf(sztypestr, "srvnull");
  919. break;
  920. default:
  921. sprintf(sztypestr, "unknown type");
  922. break;
  923. } // end of switch (rpc_paramtype)
  924.         if (rpc_paramlen > 0) {
  925. if (rpc_paramtype != SRVVARBINARY)  
  926. srv_convert(srvproc,rpc_paramtype,rpc_paramdata,
  927. rpc_paramlen,SRVCHAR,rpc_paramstr,-1);
  928. else
  929. strcpy(rpc_paramstr,"<conversion not supported>");
  930. }
  931. else 
  932. strcpy(rpc_paramstr,"<null>");
  933. printf("rn   P%3d: %-10s %-15s %4s %s",i,rpc_paramname, sztypestr, rpc_paramstatus, rpc_paramstr);
  934.     }
  935. printf("nn");
  936.     return(SRV_CONTINUE);
  937. }