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

Windows编程

开发平台:

Visual C++

  1. // NMPSDMP.C
  2. //
  3. // DBLIB program for using named pipe dump devices for backup and restore data
  4. // from SQL Server 95.This program is an example and shows the usage of named pipe
  5. // dump devices on the client side.
  6. //
  7. //
  8. // The program needs the following arguments (it asks from the user interactively) :
  9. // Operation : DUMP/LOAD
  10. // Servername : Name of the server to dump from/load into
  11. // Databasename: Name of the database to be dumped/loaded
  12. // Stripenum : How many pipes are to be used for dump/load
  13. // Dumpname : Prefix of the files to write/read the dumped/load data (DMP postfix)
  14. #define DBNTWIN32
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <process.h>
  19. #include <sqlfront.h>
  20. #include <sqldb.h>
  21. // definitions
  22. #define MAX_DEVICES 32 // maximum number of stripe devices
  23. #define PIPE_WAIT_TIME 500 // wait time in milliseconds
  24. #define DBPAGESIZE 2048 // size of physical page dumped
  25. // status values for dump/load threads
  26. #define STAT_SUCCESS 0x0 // default status
  27. #define STAT_ERROR 0x1    // error in the current thread
  28. #define STAT_ENDTHREAD 0x2 // the current thread has terminated
  29. // opcode values
  30. #define DUMP_MODE 0x1 // dump mode of operation
  31. #define LOAD_MODE 0x2 // load mode of operation
  32. // this structure is maintained on a global basis among all threads that
  33. // are doing reads/writes from pipe
  34. typedef struct ginfo
  35. {
  36. char  servername[30]; // server name
  37. char  dbname[30]; // database name
  38. char  dumpname[80]; // dump file prefix
  39. char password[30]; // dblogin password of SA
  40. long status; // global status flag for error recovery
  41. short opcode; // operation code
  42. short stripenum; // number of pipe devices to be used
  43. } GINFO;
  44. // this structure contains pipe specific info to be run by different threads
  45. // that read/write data during the stripe dump/load
  46. typedef struct pipeinfo
  47. {
  48. char pipename[80]; // Physical name of pipe used for client
  49. char spipename[80]; // Physical name of pipe sent to SQL Server
  50. char dumpname[80]; // Physical name of the dump file
  51. short slot; // which device slot
  52. GINFO *curinfo; // pointer to global info buffer
  53. long status; // thread local status
  54. } PIPEINFO;
  55. // Macros
  56. # define NEWARG(i)    (*(argv[i]) == '-' || *(argv[i]) == '/')
  57. # define BUFALIGN(a)    ( (BYTE *) ( ((long)a + 64) & 0xffffffc0) )
  58. // function prototypes
  59. void parse_parms(int argc, char *argv[], GINFO *curinfo);
  60. void argvalue(int i, int argc, char* argv[], char* out);
  61. int set_up_pipes(GINFO *curinfo, PIPEINFO **pipes);
  62. void close_up_pipes(GINFO *curinfo, PIPEINFO **pipes);
  63. void dump_proc(PIPEINFO *curpipe);
  64. void load_proc(PIPEINFO *curpipe);
  65. INT msg_handler(PDBPROCESS,DBINT,INT,INT,LPCSTR,LPCSTR,LPCSTR,DBUSMALLINT);
  66. INT err_handler(PDBPROCESS,INT,INT,INT,LPCSTR,LPCSTR);
  67. // start of the progam
  68. main(int argc, char *argv[])
  69. {
  70. RETCODE retcode; // DBLIB return code
  71. LOGINREC  *loginrec = NULL; // DBLIB LOGINREC pointer
  72. DBPROCESS  *dbproc = NULL; // DBLIB DBPROC pointer
  73. GINFO info; // to store global info & status
  74. PIPEINFO *pipes[MAX_DEVICES]; // array of PIPEINFO pointers
  75. char cmd[1024]; // SQL command buffer
  76.     // scratch variables
  77.    char scratch[80];
  78. int i;
  79.    // Initialize
  80. for (i=0; i<MAX_DEVICES; i++)
  81. pipes[i] = NULL;
  82. info.servername[0] = 0;
  83. info.dbname[0] = 0;
  84. info.dumpname[0] = 0;
  85. info.password[0] = 0;
  86. info.stripenum = 1;
  87. info.opcode = DUMP_MODE;
  88. info.status = STAT_SUCCESS;
  89. // read the user input
  90. parse_parms(argc, argv, &info);
  91. // Install the DBLIB handlers
  92. dberrhandle(err_handler);
  93. dbmsghandle(msg_handler);
  94. printf("Logging on to server...n");
  95. loginrec = dblogin();
  96. DBSETLUSER(loginrec, "sa");
  97. DBSETLPWD(loginrec,"");
  98. if ((dbproc = dbopen(loginrec, info.servername)) == (DBPROCESS *)NULL)
  99. {
  100.   printf("dbopen() failed");
  101.   info.status |= STAT_ERROR;
  102.   goto clean_up;
  103. };
  104. // Set up the thread(s) for reading/writing the pipe device
  105. if (!set_up_pipes(&info, pipes))
  106. {
  107. info.status |= STAT_ERROR;
  108. goto clean_up;
  109. }
  110. // prepare the command now
  111. if (info.opcode == DUMP_MODE)
  112. strcpy(cmd, "dump database ");
  113. else
  114. strcpy(cmd, "load database ");
  115. strcat(cmd, info.dbname);
  116. if (info.opcode == DUMP_MODE)
  117. strcat(cmd, " to ");
  118. else
  119. strcat(cmd, " from ");
  120. for (i=0; i < info.stripenum; i++)
  121. {
  122. sprintf(scratch, "pipe = '%s'", &pipes[i]->spipename);
  123. strcat(cmd, scratch);
  124. if ((i+1) < info.stripenum)
  125. strcat(cmd, ", ");
  126. }
  127. printf("Command : <%s>n", cmd);
  128. // this thread will be blocked till the dump/load command is not
  129. // completed; for changing the behavior to non blocking, use
  130. // dbsqlsend(), dbdataready() and dbsqlok() instead of dbsqlexec()
  131. retcode = dbcmd(dbproc, cmd);
  132.     retcode = dbsqlexec(dbproc);
  133.     if (retcode != SUCCEED)
  134. {
  135. printf("dbsqlexec failedn");
  136. info.status |= STAT_ERROR;
  137. goto clean_up;
  138. }
  139.     // discard results ; we do not need it
  140.     while (dbresults(dbproc) == SUCCEED)
  141.      while (dbnextrow(dbproc) != NO_MORE_ROWS)
  142. ;
  143. // We are done with all the work ; clean up the resources and exit
  144. // strictly speaking, cleanup is not necessary for this since we
  145. // will exit the program (but for implementing this as a procedures
  146. // would involve cleanup)
  147. clean_up:
  148. if (dbproc)
  149.     dbclose(dbproc);
  150. if (loginrec)
  151. dbfreelogin(loginrec);
  152. close_up_pipes(&info, pipes);
  153. exit(1);
  154.     return(0);
  155. }
  156. // procedure to get all the parameters
  157. void  parse_parms(int argc, char *argv[], GINFO *curinfo)
  158. {
  159. int     i;
  160. char    argval[30];
  161. for (i = 0 ; i < argc; i++)
  162. {
  163. if (NEWARG(i))
  164. {
  165. switch(*(argv[i] + 1))
  166. {
  167. case 'S' : // Servername
  168. argvalue(i,argc,argv,curinfo->servername);
  169. break;
  170. case 'D' : // Databasename
  171. argvalue(i,argc,argv,curinfo->dbname);
  172. break;
  173. case 'P' : // SA password
  174. argvalue(i,argc,argv,curinfo->password);
  175. break;
  176. case 'N' : // Stripe Number
  177. argvalue(i,argc,argv,argval);
  178. if ((curinfo->stripenum = (short)atoi(argval)) < 1)
  179. {
  180. printf("Invalid value %d for stripe device. Setting to 1n");
  181. curinfo->stripenum = 1;
  182. }
  183. else if (curinfo->stripenum > MAX_DEVICES)
  184. {
  185. printf("Invalid value %d for stripe device. Setting to %dn",
  186. MAX_DEVICES);
  187. curinfo->stripenum = MAX_DEVICES;
  188. }
  189. break;
  190. case 'F' : // Dump file prefix
  191. argvalue(i,argc,argv,curinfo->dumpname);
  192. break;
  193. case 'O' : // Mode of operation
  194. argvalue(i,argc,argv,argval);
  195. if ( (!strcmp(argval, "DUMP")) || (!strcmp(argval, "dump")) )
  196. curinfo->opcode = DUMP_MODE;
  197. else if ( (!strcmp(argval, "LOAD")) || (!strcmp(argval, "load")) )
  198. curinfo->opcode = LOAD_MODE;
  199. else
  200. {
  201. printf("Invalid mode %s specifiedn", argval);
  202. exit(1);
  203. }
  204. break;
  205. case '?' : // Help message
  206. printf("NMPSDMP -Sservername -Ppassword -O{dump | load} -Ddatabasename -Nstripenumber -Fdumpprefixn");
  207. exit(1);
  208. break;
  209. default:
  210. printf("Invalid parameter option : %sn", *(argv[i] + 1) );
  211. printf("NMPSDMP -Sservername -Ppassword -O{dump | load} -Ddatabasename -Nstripenumber -Fdumpprefixn");
  212. exit(1);
  213. }
  214. }
  215. }
  216. return;
  217. }
  218. // argument reading routine for parse_parms()
  219. void argvalue(
  220.     int   i,                           // parameter number
  221.     int   argc,                        // #args
  222.     char* argv[],                      // arglist
  223.     char* out                          // receives parm 'i'
  224. ){
  225. if( *(argv[i]+2) )
  226. strcpy(out, argv[i]+2);
  227. else
  228. {
  229. if( i+1<argc && !( NEWARG(i+1) ) )
  230.             strcpy(out, argv[i+1]);
  231. }
  232. }
  233. // procedure to setup all the threads for reading pipes
  234. //
  235. // return : 1 if success
  236. // 0 otherwise
  237. int set_up_pipes(GINFO *curinfo, PIPEINFO **pipes)
  238. {
  239. int i;
  240. PIPEINFO *curpipe;
  241. char pipebuf[30];
  242. // for every device
  243. for (i=0; i < curinfo->stripenum; i++)
  244. {
  245. // allocate for the current pipe
  246. if ((curpipe = malloc(sizeof(PIPEINFO))) == NULL)
  247. return 0;
  248. curpipe->slot = i;
  249. curpipe->curinfo = curinfo;
  250. curpipe->status = STAT_SUCCESS;
  251. // prepare the pipe name
  252. strcpy(curpipe->pipename, "\\");
  253. strcpy(curpipe->spipename, "\\");
  254. if (curinfo->servername[0])
  255. strcat(curpipe->pipename, curinfo->servername);
  256. else
  257. strcat(curpipe->pipename, ".");
  258. strcat(curpipe->spipename, ".");
  259. strcat(curpipe->pipename, "\pipe\");
  260. strcat(curpipe->spipename, "\pipe\");
  261. sprintf(pipebuf, "sqldmpld%d", i);
  262. strcat(curpipe->pipename, pipebuf);
  263. strcat(curpipe->spipename, pipebuf);
  264. // prepare the dump file name
  265. sprintf(curpipe->dumpname, "%s%d.dmp", curinfo->dumpname, i);
  266. // now start the thread for this device
  267. pipes[i] = curpipe;
  268. if (curinfo->opcode == DUMP_MODE)
  269. {
  270. if (!(_beginthread(dump_proc, 0, (LPVOID)curpipe)))
  271. {
  272. printf("beginthread failed for slot %dn", i);
  273. return 0;
  274. }
  275. }
  276. else
  277. {
  278. if (!(_beginthread(load_proc, 0, (LPVOID)curpipe)))
  279. {
  280. printf("beginthread failed for slot %dn", i);
  281. return 0;
  282. }
  283. }
  284. }
  285. // started all the threads
  286. return 1;
  287. }
  288. // procedure to close all the threads for reading/writing pipes
  289. //
  290. // return : nothing
  291. //
  292. void close_up_pipes(GINFO *curinfo, PIPEINFO **pipes)
  293. {
  294. int i;
  295. PIPEINFO *curpipe;
  296. // check if we need to clean up
  297. if (!curinfo->stripenum)
  298. return;
  299. // for every open device
  300. for (i=0; i < curinfo->stripenum; i++)
  301. {
  302. if (!(curpipe = pipes[i]))
  303. continue;
  304. // wait for the thread to close itself
  305. while (!(curpipe->status & STAT_ENDTHREAD))
  306. SleepEx(10, TRUE);
  307. // free the allocated memory
  308. free(curpipe);
  309. }
  310. }
  311. // DUMP_PROC
  312. //  This procedure does the opening and reading of dumped data sent
  313. // by the SQL Server. Each thread invoked with this routine services
  314. // one named pipe (instance) connection; for simplicity we are creating
  315. // separate named pipes for each stripe number.
  316. //
  317. // For dump process, the thread opens the pipe created by SQL Server
  318. //  and connects to it. Then keeps reading data and writing it
  319. // out to the dumpfile till the SQL Server is done.
  320. void dump_proc(PIPEINFO *curpipe)
  321. {
  322. GINFO *curinfo = curpipe->curinfo;
  323. HANDLE hpipe = NULL;
  324. HANDLE hfile = NULL;
  325. BYTE *buf_start = NULL;
  326. BYTE *buf_ptr;
  327. DWORD bufsize, cbread, cbwritten, mode;
  328. DWORD errcode = 0;
  329. DWORD offl, offh;
  330. // Open the pipe
  331. while (1)
  332. {
  333. // check the global flag
  334. if (curinfo->status & STAT_ERROR)
  335. goto dump_proc_cleanup;
  336. hpipe = CreateFile(curpipe->pipename,
  337. GENERIC_READ | GENERIC_WRITE, 0, NULL,
  338. OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
  339. // break if handle is valid
  340. if (hpipe != INVALID_HANDLE_VALUE)
  341. break;
  342. // check the pipe state
  343. errcode = GetLastError();
  344. if (errcode == ERROR_FILE_NOT_FOUND)
  345. {
  346. // SQL Server has not yet created the pipe; wait
  347. SleepEx(PIPE_WAIT_TIME, TRUE);
  348. continue;
  349. }
  350. else if (errcode != ERROR_PIPE_BUSY)
  351. {
  352. printf("Error in %s : %dn", "CreateFile", errcode);
  353. curpipe->status |= STAT_ERROR;
  354. goto dump_proc_cleanup;
  355. }
  356. // Wait for sometime if pipe is busy
  357. if (!WaitNamedPipe(curpipe->pipename, PIPE_WAIT_TIME))
  358. {
  359. printf("Error in %s : %dn", "WaitNamedPipe", GetLastError());
  360. curpipe->status |= STAT_ERROR;
  361. goto dump_proc_cleanup;
  362. }
  363. }
  364. printf("dump thread : %d : connected to servern", curpipe->slot);
  365. // get the buffer size
  366. if ((!GetNamedPipeInfo(hpipe, NULL, NULL, &bufsize, NULL)) || (bufsize == 0))
  367. {
  368. printf("Error in %s : %dn", "GetNamedPipeInfo", GetLastError());
  369. curpipe->status |= STAT_ERROR;
  370. goto dump_proc_cleanup;
  371. }
  372. // Align the buffer size to database pagesize if necessary
  373. if (bufsize % DBPAGESIZE)
  374. bufsize = ((bufsize / DBPAGESIZE) - 1) * DBPAGESIZE;
  375. //printf("dump thread : %d : buffer size %d n", curpipe->slot, bufsize);
  376. // allocate the buffer for reading incoming data and align it
  377. if ((buf_start = malloc(bufsize + 64)) == NULL)
  378. {
  379. printf("malloc failedn");
  380. curpipe->status |= STAT_ERROR;
  381. goto dump_proc_cleanup;
  382. }
  383. buf_ptr = BUFALIGN(buf_start);
  384. // Set the pipe mode to message read mode 
  385. mode = PIPE_READMODE_MESSAGE;
  386. if (!SetNamedPipeHandleState(hpipe, &mode, NULL, NULL))
  387. {
  388. printf("Error in %s : %dn", "SetNamedPipeHandleState", GetLastError());
  389. curpipe->status |= STAT_ERROR;
  390. goto dump_proc_cleanup;
  391. }
  392. // open the dump file ; if it exists then overwrite it
  393. // otherwise open a new file
  394. hfile = CreateFile(curpipe->dumpname,
  395.             GENERIC_READ | GENERIC_WRITE, 0, NULL,
  396.             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  397. if (hfile == INVALID_HANDLE_VALUE)
  398. {
  399. printf("Error in %s : %dn", "CreateFile", GetLastError());
  400. curpipe->status |= STAT_ERROR;
  401. goto dump_proc_cleanup;
  402. }
  403. // set the file pointer to start of file
  404. offh = 0;
  405. if ((offl = SetFilePointer(hfile, 0, &offh, FILE_BEGIN)) == -1)
  406. {
  407. printf("Error in %s : %dn", "SetFilePointer", GetLastError());
  408. curpipe->status |= STAT_ERROR;
  409. goto dump_proc_cleanup;
  410. }
  411. // now we are all set to read from the pipe; keep reading till the pipe is
  412. // closed.
  413. while (1)
  414. {
  415. // check the global flag
  416. if (curinfo->status & STAT_ERROR)
  417. goto dump_proc_cleanup;
  418. if (!ReadFile(hpipe, buf_ptr, bufsize, &cbread, NULL))
  419. {
  420. // Are we done reading
  421. if ((errcode = GetLastError()) == ERROR_BROKEN_PIPE)
  422. break;
  423. if (errcode != ERROR_MORE_DATA)
  424. {
  425. printf("Error in %s : %dn", "ReadFile", errcode);
  426. curpipe->status |= STAT_ERROR;
  427. goto dump_proc_cleanup;
  428. }
  429. }
  430. //printf("dump thread : %d : read %d bytesn", curpipe->slot, cbread);
  431. if (!WriteFile(hfile, buf_ptr, cbread, &cbwritten, NULL))
  432. {
  433. printf("Error in %s : %dn", "WriteFile", GetLastError());
  434. curpipe->status |= STAT_ERROR;
  435. goto dump_proc_cleanup;
  436. }
  437. }
  438. dump_proc_cleanup:
  439. // release the resources
  440. if (buf_start)
  441. free(buf_start);
  442. if (hfile)
  443. {
  444. FlushFileBuffers(hfile);
  445. CloseHandle(hfile);
  446. }
  447. if (hpipe)
  448. CloseHandle(hpipe);
  449. // set the status flags
  450. curpipe->status |= STAT_ENDTHREAD;
  451. if (curpipe->status & STAT_ERROR)
  452. curinfo->status |= STAT_ERROR;
  453. return;
  454. }
  455. // LOAD_PROC
  456. //  This procedure does the opening and writing of dumped data sent
  457. // to the SQL Server. Each thread invoked with this routine services
  458. // one named pipe (instance) connection; we are create
  459. // separate named pipes for each stripe number.
  460. //
  461. // For load process, the thread opens the pipe created by SQL Server
  462. //  and connects to it. Then keeps reading data from the dumpfile till end
  463. //  and writes to the pipe; Finally closes the pipe when done.
  464. void load_proc(PIPEINFO *curpipe)
  465. {
  466. GINFO *curinfo = curpipe->curinfo;
  467. HANDLE hpipe = NULL;
  468. HANDLE hfile = NULL;
  469. BYTE *buf_start = NULL;
  470. BYTE *buf_ptr;
  471. DWORD bufsize, cbread, cbwritten, mode;
  472. DWORD errcode = 0;
  473. DWORD offl, offh;
  474. // Open the pipe
  475. while (1)
  476. {
  477. // check the global flag
  478. if (curinfo->status & STAT_ERROR)
  479. goto load_proc_cleanup;
  480. hpipe = CreateFile(curpipe->pipename,
  481. GENERIC_READ | GENERIC_WRITE, 0, NULL,
  482. OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
  483. // break if handle is valid
  484. if (hpipe != INVALID_HANDLE_VALUE)
  485. break;
  486. // check the pipe state
  487. errcode = GetLastError();
  488. if (errcode == ERROR_FILE_NOT_FOUND)
  489. {
  490. // SQL Server has not yet created the pipe; wait
  491. SleepEx(PIPE_WAIT_TIME, TRUE);
  492. continue;
  493. }
  494. else if (errcode != ERROR_PIPE_BUSY)
  495. {
  496. printf("Error in %s : %dn", "CreateFile", errcode);
  497. curpipe->status |= STAT_ERROR;
  498. goto load_proc_cleanup;
  499. }
  500. // Wait for sometime if pipe is busy
  501. if (!WaitNamedPipe(curpipe->pipename, PIPE_WAIT_TIME))
  502. {
  503. printf("Error in %s : %dn", "WaitNamedPipe", GetLastError());
  504. curpipe->status |= STAT_ERROR;
  505. goto load_proc_cleanup;
  506. }
  507. }
  508. printf("load thread : %d : connected to servern", curpipe->slot);
  509. // get the buffer size
  510. if ((!GetNamedPipeInfo(hpipe, NULL, NULL, &bufsize, NULL)) || (bufsize == 0))
  511. {
  512. printf("Error in %s : %dn", "GetNamedPipeInfo", GetLastError());
  513. curpipe->status |= STAT_ERROR;
  514. goto load_proc_cleanup;
  515. }
  516. // Align the buffer size to database pagesize if necessary
  517. if (bufsize % DBPAGESIZE)
  518. bufsize = ((bufsize / DBPAGESIZE) - 1) * DBPAGESIZE;
  519. //printf("load thread : %d : buffer size %d n", curpipe->slot, bufsize);
  520. // allocate the buffer for reading incoming data and align it
  521. if ((buf_start = malloc(bufsize + 64)) == NULL)
  522. {
  523. printf("malloc failedn");
  524. curpipe->status |= STAT_ERROR;
  525. goto load_proc_cleanup;
  526. }
  527. buf_ptr = BUFALIGN(buf_start);
  528. // Set the pipe mode to message read mode 
  529. mode = PIPE_READMODE_MESSAGE;
  530. if (!SetNamedPipeHandleState(hpipe, &mode, NULL, NULL))
  531. {
  532. printf("Error in %s : %dn", "SetNamedPipeHandleState", GetLastError());
  533. curpipe->status |= STAT_ERROR;
  534. goto load_proc_cleanup;
  535. }
  536. // open the dump file ; it should exist
  537. hfile = CreateFile(curpipe->dumpname,
  538.             GENERIC_READ | GENERIC_WRITE, 0, NULL,
  539.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  540. if (hfile == INVALID_HANDLE_VALUE)
  541. {
  542. printf("Error in %s : %dn", "CreateFile", GetLastError());
  543. curpipe->status |= STAT_ERROR;
  544. goto load_proc_cleanup;
  545. }
  546. // set the file pointer to start of file
  547. offh = 0;
  548. if ((offl = SetFilePointer(hfile, 0, &offh, FILE_BEGIN)) == -1)
  549. {
  550. printf("Error in %s : %dn", "SetFilePointer", GetLastError());
  551. curpipe->status |= STAT_ERROR;
  552. goto load_proc_cleanup;
  553. }
  554. //
  555. // Read the first page and write it to the pipe
  556. //
  557. if ((!ReadFile(hfile, buf_ptr, DBPAGESIZE, &cbread, NULL)) || 
  558. (cbread != DBPAGESIZE))
  559. {
  560. printf("Error in %s : %dn", "ReadFile", GetLastError());
  561. curpipe->status |= STAT_ERROR;
  562. goto load_proc_cleanup;
  563. }
  564. if (!WriteFile(hpipe, buf_ptr, DBPAGESIZE, &cbwritten, NULL))
  565. {
  566. printf("Error in %s : %dn", "WriteFile", errcode);
  567. curpipe->status |= STAT_ERROR;
  568. goto load_proc_cleanup;
  569. }
  570. //printf("load thread : %d : wrote %d bytesn", curpipe->slot, cbwritten);
  571. // now we are all set to read from the dumpfile; keep reading till we reach
  572. // the end of dumpfile
  573. while (1)
  574. {
  575. // check the global flag
  576. if (curinfo->status & STAT_ERROR)
  577. goto load_proc_cleanup;
  578. // read from the dump file
  579. if (!ReadFile(hfile, buf_ptr, bufsize, &cbread, NULL))
  580. {
  581. // check if we are done reading
  582. if ((errcode = GetLastError()) == ERROR_HANDLE_EOF)
  583. break;
  584. printf("Error in %s : %dn", "ReadFile", GetLastError());
  585. curpipe->status |= STAT_ERROR;
  586. goto load_proc_cleanup;
  587. }
  588. // Done reading the dump file
  589. if (cbread == 0)
  590. break;
  591. // write to the pipe
  592. if (!WriteFile(hpipe, buf_ptr, cbread, &cbwritten, NULL))
  593. {
  594. printf("Error in %s : %dn", "WriteFile", GetLastError());
  595. curpipe->status |= STAT_ERROR;
  596. goto load_proc_cleanup;
  597. }
  598. //printf("load thread : %d : wrote %d bytesn", curpipe->slot, cbwritten);
  599. }
  600. load_proc_cleanup:
  601. // release the resources
  602. if (buf_start)
  603. free(buf_start);
  604. if (hfile)
  605. CloseHandle(hfile);
  606. if (hpipe)
  607. {
  608. FlushFileBuffers(hpipe);
  609. CloseHandle(hpipe);
  610. }
  611. // set the status flags
  612. curpipe->status |= STAT_ENDTHREAD;
  613. if (curpipe->status & STAT_ERROR)
  614. curinfo->status |= STAT_ERROR;
  615. return;
  616. }
  617. INT msg_handler(dbproc,msgno,msgstate, severity, msgtext,server,proc,line)
  618. PDBPROCESS  dbproc;
  619. DBINT  msgno;
  620. INT  msgstate;
  621. INT  severity;
  622. LPCSTR msgtext;
  623. LPCSTR server;
  624. LPCSTR proc;
  625. DBUSMALLINT line;
  626. {
  627.    if (severity)
  628.       printf("nDB-LIB message: %s n", msgtext);
  629.    return (0);
  630. };
  631. INT err_handler(dbproc, severity, herrno, oserr, dberrstr, oserrstr)
  632. PDBPROCESS  dbproc;
  633. INT     severity;
  634. INT  herrno;
  635. INT  oserr;
  636. LPCSTR  dberrstr;
  637. LPCSTR  oserrstr;
  638. {
  639. if (severity)
  640.       printf("nDB-LIBRARY error: %s n", dberrstr);
  641.     return (INT_CANCEL);
  642. };