1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2012-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% module 10 11/** No warnings from WinSock about deprecated functions. 12*/ 13#define _WINSOCK_DEPRECATED_NO_WARNINGS 1 14 15#include <libdk3c/dk3all.h> 16#include <dkwt/dkt.h> 17#include <dkwt/dkwt.h> 18#include <libdk3c/dk3unused.h> 19 20 21 22$!trace-include 23 24 25/** Buffer size to enumerate printers. 26*/ 27#define DKWT_PRINTER_ENUM_BUFFER_SIZE 1024 28 29/** Buffer size to enumerate print jobs. 30*/ 31#define DKWT_PRINTER_ENUM_JOBS_SIZE 8192 32 33/** Number of print jobs to show in one request. 34*/ 35#define DKWT_PRINTER_NUMBER_OF_JOBS 64 36 37 38/** Local print queue. 39*/ 40typedef struct { 41 dkChar *qn; /**< Queue name. */ 42} DKWT_CP_QUEUE; 43 44 45 46/** Print job. 47*/ 48typedef struct { 49 DWORD jobId; /**< Job ID. */ 50 DWORD pos; /**< Position in queue. */ 51 dkChar const *docName; /**< Print job name. */ 52} DKWT_CP_JOB; 53 54 55 56/** Compare two print queues by name. 57 @param l Left object. 58 @param r Right object. 59 @param cr Comparison criteria (0=queue/queue, 1=queue/name) 60 @return Comparison result. 61*/ 62static 63int 64dkwt_cp_queue_comp(void const *l, void const *r, int cr) 65{ 66 DKWT_CP_QUEUE const *ql; 67 DKWT_CP_QUEUE const *qr; 68 int back = 0; 69 if(l) { 70 if(r) { 71 ql = (DKWT_CP_QUEUE const *)l; 72 switch(cr) { 73 case 1: { 74 if(ql->qn) { 75 back = dk3str_casecmp(ql->qn, (dkChar const *)r); 76 if(back < -1) back = -1; 77 if(back > 1) back = 1; 78 } else back = -1; 79 } break; 80 default: { 81 qr = (DKWT_CP_QUEUE const *)r; 82 if(ql->qn) { 83 if(qr->qn) { 84 back = dk3str_casecmp(ql->qn, qr->qn); 85 if(back < -1) back = -1; 86 if(back > 1) back = 1; 87 } else back = 1; 88 } else { 89 if(qr->qn) back = -1; 90 } 91 } break; 92 } 93 } else back = 1; 94 } else { 95 if(r) back = -1; 96 } 97 return back; 98} 99 100 101 102/** Destroy queue structure, release memory. 103 @param q Queue structure to destroy. 104*/ 105static 106void 107dkwt_cp_queue_del(DKWT_CP_QUEUE *q) 108{ 109 if(q) { 110 dk3_release(q->qn); 111 dk3_delete(q); 112 } 113} 114 115 116 117/** Create queue structure, allocate memory. 118 @param app Application structure for diagnostics, may be NULL. 119 @param n Queue name. 120 @return Pointer to new structure on success, NULL on error. 121*/ 122static 123DKWT_CP_QUEUE * 124dkwt_cp_queue_new(dk3_app_t *app, dkChar const *n) 125{ 126 DKWT_CP_QUEUE *back = NULL; 127 if(n) { 128 back = dk3_new_app(DKWT_CP_QUEUE,1,app); 129 if(back) { 130 back->qn = NULL; 131 back->qn = dk3str_dup_app(n, app); 132 if(!(back->qn)) { 133 dkwt_cp_queue_del(back); 134 back = NULL; 135 } 136 } 137 } 138 return back; 139} 140 141 142 143/** Destroy job structure, release memory. 144 @param j Job structure to delete. 145*/ 146static 147void 148dkwt_cp_job_del(DKWT_CP_JOB *j) 149{ 150 if(j) { 151 dk3_release(j->docName); 152 j->jobId = 0; 153 j->pos = 0; 154 dk3_delete(j); 155 } 156} 157 158 159 160/** Create new job structure, allocate memory. 161 @param app Application structure for diagnostics. 162 @param jobid Job ID. 163 @param pos Job position in the queue. 164 @param dn Document name. 165 @return Pointer to new structure on success, NULL on error. 166*/ 167static 168DKWT_CP_JOB * 169dkwt_cp_job_new(dk3_app_t *app, DWORD jobid, DWORD pos, dkChar const *dn) 170{ 171 DKWT_CP_JOB *back = NULL; 172 back = dk3_new_app(DKWT_CP_JOB,1,app); 173 if(back) { 174 back->docName = NULL; 175 back->jobId = jobid; 176 back->pos = pos; 177 if(dn) { 178 back->docName = dk3str_dup_app(dn, app); 179 if(!(back->docName)) { 180 dkwt_cp_job_del(back); 181 back = NULL; 182 } 183 } 184 } 185 return back; 186} 187 188 189 190/** Compare 2 jobs to find which one to delete first. 191 @param l Left job. 192 @param r Right job. 193 @param cr Comparison criteria (ignored). 194 @return Comparison result, jobs with higher position are deleted first. 195*/ 196static 197int 198dkwt_cp_job_comp(void const *l, void const *r, int DK3_ARG_UNUSED(cr)) 199{ 200 DKWT_CP_JOB const *jl; 201 DKWT_CP_JOB const *jr; 202 int back = 0; 203 DK3_UNUSED_ARG(cr) 204 if(l) { 205 if(r) { 206 jl = (DKWT_CP_JOB const *)l; 207 jr = (DKWT_CP_JOB const *)r; 208 if(jl->pos < jr->pos) { 209 back = 1; 210 } else { 211 if(jl->pos > jr->pos) { 212 back = -1; 213 } 214 } 215 } else back = 1; 216 } else { 217 if(r) back = -1; 218 } 219 return back; 220} 221 222 223 224 225/** Remove all print jobs for one user from a single queue. 226 @param app Application structure for diagnostics. 227 @param msg Localized message texts. 228 @param userName User name. 229 @param hostName Host name. 230 @param queue Queue to modify. 231*/ 232static 233void 234dkwt_cp_remove_all_jobs( 235 dk3_app_t *app, 236 dkChar const * const *msg, 237 dkChar const *userName, 238 dkChar const *hostName, 239 DKWT_CP_QUEUE *queue 240) 241{ 242 char jeb[DKWT_PRINTER_ENUM_JOBS_SIZE]; /* Enum buffer. */ 243 dkChar idbuf[64]; 244 dk3_sto_t *s_j; /* Jobs storage. */ 245 dk3_sto_it_t *i_j; /* Iterator for jobs storage. */ 246#if DK3_CHAR_SIZE > 1 247 JOB_INFO_1W *ji1; /* Job information pointer. */ 248#else 249 JOB_INFO_1A *ji1; /* Job information pointer. */ 250#endif 251 DKWT_CP_JOB *job; /* Current job. */ 252 HANDLE hPrinter; /* Handle for printer. */ 253 DWORD szjeb; /* Size of jeb buffer. */ 254 DWORD bneed; /* Bytes needed. */ 255 DWORD nj; /* Number of jobs found. */ 256 DWORD i; /* Index of current job to process. */ 257 int rmj; /* Flag: Remove this job. */ 258 BOOL res; /* Operation result. */ 259 $? "+ dkwt_cp_remove_all_jobs" 260 s_j = NULL; i_j = NULL; 261 s_j = dk3sto_open_app(app); 262 if(s_j) { 263 dk3sto_set_comp(s_j, dkwt_cp_job_comp, 0); 264 i_j = dk3sto_it_open(s_j); 265 } 266 if((s_j) && (i_j)) { 267 /* PROGRESS: Cleaning up local queue... */ 268 dk3app_log_3(app, DK3_LL_PROGRESS, msg, 83, 84, queue->qn); 269#if DK3_CHAR_SIZE > 1 270 res = OpenPrinterW(queue->qn, &hPrinter, NULL); 271#else 272 res = OpenPrinterA(queue->qn, &hPrinter, NULL); 273#endif 274 if(res) { 275 /* Enumerate print jobs, save jobs to delete. 276 */ 277 szjeb = sizeof(jeb); bneed = 0; nj = 0; 278#if DK3_CHAR_SIZE > 1 279 res = EnumJobsW( 280 hPrinter, 0, DKWT_PRINTER_NUMBER_OF_JOBS, 1, (LPBYTE)jeb, szjeb, 281 &bneed, &nj 282 ); 283#else 284 res = EnumJobsA( 285 hPrinter, 0, DKWT_PRINTER_NUMBER_OF_JOBS, 1, (LPBYTE)jeb, szjeb, 286 &bneed, &nj 287 ); 288#endif 289 if(res) { $? ". EnumJobs" 290 if(nj > 0) { $? ". nj=%d", (int)nj 291#if DK3_CHAR_SIZE > 1 292 ji1 = (JOB_INFO_1W *)jeb; 293#else 294 ji1 = (JOB_INFO_1A *)jeb; 295#endif 296 for(i = 0; i < nj; i++) { 297 rmj = 0; 298 if(ji1[i].pUserName) { $? ". job user \"%!ds\" / user \"%!ds\"", ji1[i].pUserName, userName 299 if(0 == dk3str_casecmp(ji1[i].pUserName, userName)) { $? ". equal" 300 rmj = 1; 301 if(hostName) { $? ". have host name \"%!ds\"", hostName 302 rmj = 0; 303 if(ji1[i].pMachineName) { $? ". job host \"%!ds\"", ji1[i].pMachineName 304 if(0 == dk3str_casecmp(ji1[i].pMachineName, hostName)) { $? ". ok" 305 rmj = 1; 306 } else { 307 if(dkT('\\') == (ji1[i].pMachineName)[0]) { 308 if(dkT('\\') == (ji1[i].pMachineName)[1]) { 309 if(0 == dk3str_casecmp(&((ji1[i].pMachineName)[2]), hostName)) { 310 rmj = 1; 311 } 312 } 313 } 314 } 315 } else { $? ". no job host name" 316 rmj = 1; 317 } 318 } else { $? ". host name not found" 319 } 320 } else { $? ". other user name" 321 } 322 } 323 if(rmj) { $? ". must remove job" 324 job = dkwt_cp_job_new(app, ji1[i].JobId, ji1[i].Position, ji1[i].pDocument); 325 if(job) { 326 if(!dk3sto_add(s_j, (void *)job)) { $? "! memory" 327 dkwt_cp_job_del(job); 328 } else { 329 } 330 } else { $? "! memory" 331 } 332 } 333 } 334 } else { $? ". no jobs in queue" 335 } 336 } else { $? "! EnumJobs" 337 } 338 /* Delete saved print jobs if any. 339 */ 340 dk3sto_it_reset(i_j); 341 while(NULL != (job = (DKWT_CP_JOB *)dk3sto_it_next(i_j))) { 342 $? ". deleting print job %lu", (unsigned long)(job->jobId) 343#if VERSION_20140716 344 dk3sf_sprintf3(idbuf, dkT("%lu"), (unsigned long)(job->jobId)); 345#else 346 if (!(dk3ma_um_to_string(idbuf, DK3_SIZEOF(idbuf,dkChar), (dk3_um_t)(job->jobId)))) { 347 idbuf[0] = dkT('\0'); 348 } 349#endif 350 if(SetJob(hPrinter, job->jobId, 0, NULL, JOB_CONTROL_DELETE)) { 351 /* PROGRESS: Print job deleted. */ $? ". deleted" 352 dk3app_log_5( 353 app, DK3_LL_PROGRESS, msg, 85, 86, 87, idbuf, 354 ((job->docName) ? (job->docName) : msg[88]) 355 ); 356 } else { $? "! failed to delete" 357 /* ERROR: Failed to delete print job! */ 358 dk3app_log_5( 359 app, DK3_LL_ERROR, msg, 89, 90, 91, idbuf, 360 ((job->docName) ? (job->docName) : msg[88]) 361 ); 362 } 363 } 364 ClosePrinter(hPrinter); 365 } else { $? "! failed to open printer" 366 /* ERROR: Failed to open printer! */ 367 dk3app_log_3(app, DK3_LL_ERROR, msg, 92, 93, queue->qn); 368 } 369 } else { $? "! arguments" 370 } 371 /* Release memory. 372 */ 373 if(s_j) { 374 if(i_j) { 375 dk3sto_it_reset(i_j); 376 while(NULL !=(job = (DKWT_CP_JOB *)dk3sto_it_next(i_j))) { 377 dkwt_cp_job_del(job); 378 } 379 dk3sto_it_close(i_j); 380 } 381 dk3sto_close(s_j); 382 } $? "- dkwt_cp_remove_all_jobs" 383} 384 385 386 387void 388dkwt_clear_printers_local( 389 dk3_app_t *app, 390 dkChar const * const *msg, 391 dkChar const * const * DK3_ARG_UNUSED(kwnl), 392 dkChar const *userName 393) 394{ 395 char peb[DKWT_PRINTER_ENUM_BUFFER_SIZE]; 396 dkChar hn[256]; /* Host name. */ 397 dk3_sto_t *s_q; /* Storage for print queues. */ 398 dk3_sto_it_t *i_q; /* Iterator for print queues storage. */ 399 DKWT_CP_QUEUE *q; /* Current queue to process. */ 400#if DK3_CHAR_SIZE > 1 401 PRINTER_INFO_4W *pi4; /* Printer information array. */ 402#else 403 PRINTER_INFO_4A *pi4; /* Printer information array. */ 404#endif 405 DWORD szpeb; /* Size of peb buffer. */ 406 DWORD bneed; /* Needed bytes. */ 407 DWORD np; /* Number of printers found. */ 408 DWORD i; /* Index of current printer. */ 409 DWORD szhn; /* Size of host name. */ 410 BOOL res; /* Result from printer enumeration. */ 411 DK3_UNUSED_ARG(kwnl) 412 s_q = NULL; i_q = NULL; 413 if(userName) { 414 hn[0] = dkT('\0'); 415 szhn = DK3_SIZEOF(hn,dkChar); 416#if DK3_CHAR_SIZE > 1 417 res = GetComputerNameExW(ComputerNameNetBIOS, hn, &szhn); 418#else 419 res = GetComputerNameExA(ComputerNameNetBIOS, hn, &szhn); 420#endif 421 if(res) { 422 hn[(szhn < (DK3_SIZEOF(hn,dkChar)-1)) ? szhn : (DK3_SIZEOF(hn,dkChar)-1)] = dkT('\0'); 423 } else { 424 szhn = 0; 425 } 426 s_q = dk3sto_open_app(app); 427 if(s_q) { 428 dk3sto_set_comp(s_q, dkwt_cp_queue_comp, 0); 429 i_q = dk3sto_it_open(s_q); 430 } 431 if((s_q) && (i_q)) { 432 /* Enumerate printers, fill s_q 433 */ 434 szpeb = sizeof(peb); 435 bneed = 0; 436 np = 0; 437#if DK3_CHAR_SIZE > 1 438 res = EnumPrintersW( 439 PRINTER_ENUM_LOCAL, 440 NULL, 441 4, 442 (LPBYTE)peb, 443 szpeb, 444 &bneed, 445 &np 446 ); 447#else 448 res = EnumPrintersA( 449 PRINTER_ENUM_LOCAL, 450 NULL, 451 4, 452 (LPBYTE)peb, 453 szpeb, 454 &bneed, 455 &np 456 ); 457#endif 458 if(res) { 459#if DK3_CHAR_SIZE > 1 460 pi4 = (PRINTER_INFO_4W *)peb; 461#else 462 pi4 = (PRINTER_INFO_4A *)peb; 463#endif 464 if(np > 0) { 465 for(i = 0; i < np; i++) { 466 if(pi4[i].pPrinterName) { 467 q = dkwt_cp_queue_new(app, pi4[i].pPrinterName); 468 if(q) { 469 if(!dk3sto_add(s_q, (void *)q)) { 470 dkwt_cp_queue_del(q); 471 } 472 } 473 } 474 } 475 } 476 } else { 477 /* ERROR: Failed to enumerate local printers */ 478 dk3app_log_1(app, DK3_LL_ERROR, msg, 94); 479 } 480 /* Handle all the queues in i_q. 481 */ 482 dk3sto_it_reset(i_q); 483 while(NULL != (q = (DKWT_CP_QUEUE *)dk3sto_it_next(i_q))) { 484 dkwt_cp_remove_all_jobs(app,msg,userName,((szhn > 0) ? hn : NULL),q); 485 } 486 } 487 /* Release memory. 488 */ 489 if(s_q) { 490 if(i_q) { 491 dk3sto_it_reset(i_q); 492 while(NULL != (q = (DKWT_CP_QUEUE *)dk3sto_it_next(i_q))) { 493 dkwt_cp_queue_del(q); 494 } 495 dk3sto_it_close(i_q); 496 } 497 dk3sto_close(s_q); 498 } 499 } else { 500 /* ERROR: Missing user name! */ 501 dk3app_log_1(app, DK3_LL_ERROR, msg, 95); 502 } 503} 504 505 506 507/** Send request to host. 508 @param app Application structure. 509 @param msg Localized message texts. 510 @param rq Request to send. 511 @param hn Host name to send the request to. 512*/ 513static 514void 515dkwt_cp_send_request( 516 dk3_app_t *app, 517 dkChar const * const *msg, 518 char const *rq, 519 dkChar const *hn 520) 521{ 522 char buf[512]; 523 dkChar eb[64]; 524 struct sockaddr_in in; 525 struct hostent *he; 526 unsigned long ip; 527 unsigned long *ptr; 528 unsigned long **pptr; 529 size_t lgt; 530 SOCKET sock; 531 int res; 532 int cc; 533 int ie; 534 535 ip = 0UL; 536 dk3enc_ipaddr_to_ul_app(hn, &ip, app); 537 if(ip) { 538 ip = dk3enc_htonl(ip); 539 } else { 540 ie = dk3app_get_encoding(app); 541 if(dk3str_to_c8u_app(buf, sizeof(buf), hn, ie, app)) { 542 he = gethostbyname(buf); 543 if(he) { 544 if(he->h_addr_list) { 545 pptr = (unsigned long **)he->h_addr_list; 546 ptr = *pptr; 547 if(ptr) { 548 ip = *ptr; 549 } 550 } 551 } 552 } else { 553 /* ERROR: Failed to convert host name to UTF-8! */ 554 } 555 } 556 if(ip) { 557 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 558 if(INVALID_SOCKET != sock) { 559 in.sin_family = AF_INET; 560 in.sin_addr.s_addr = ip; /* already in network byte order */ 561 in.sin_port = dk3enc_htons(515); 562 ip = dk3enc_ntohl(ip); 563 sprintf( 564 buf, "%lu.%lu.%lu.%lu", 565 ((ip >> 24) & 0x000000FFUL), 566 ((ip >> 16) & 0x000000FFUL), 567 ((ip >> 8) & 0x000000FFUL), 568 ( ip & 0x000000FFUL) 569 ); 570 if(dk3str_c8_to_str_simple_app(eb, DK3_SIZEOF(eb,dkChar), buf, app)) 571 { 572 dk3app_log_3(app, DK3_LL_DEBUG, msg, 115, 116, eb); 573 } 574 res = connect( 575 sock, 576 (const struct sockaddr *)(&in), 577 sizeof(struct sockaddr_in) 578 ); 579 if(0 == res) { 580 lgt = strlen(rq); 581 res = send(sock, rq, (int)lgt, 0); 582 if(res == (int)lgt) { 583 shutdown(sock, SD_SEND); 584 cc = 1; 585 while(cc) { 586 cc = 0; 587 res = recv(sock, buf, sizeof(buf), 0); 588 if(res > 0) { 589 cc = 1; 590 } 591 } 592 /* PROGRESS: Print queue cleaned up successfully. */ 593 dk3app_log_1(app, DK3_LL_PROGRESS, msg, 96); 594 } else { 595 /* ERROR: Failed to send request! */ 596 dk3app_log_1(app, DK3_LL_ERROR, msg, 97); 597#if VERSION_BEFORE_20140716 598 dk3sf_sprintf3(eb, dkT("%d"), WSAGetLastError()); 599 dk3app_log_3(app, DK3_LL_ERROR, msg, 113, 114, eb); 600#else 601 if (dk3ma_im_to_string(eb, DK3_SIZEOF(eb,dkChar), (dk3_im_t)WSAGetLastError())) { 602 dk3app_log_3(app, DK3_LL_ERROR, msg, 113, 114, eb); 603 } 604#endif 605 } 606 } else { 607 /* ERROR: Failed to connect! */ 608 dk3app_log_1(app, DK3_LL_ERROR, msg, 98); 609#if VERSION_BEFORE_20140716 610 dk3sf_sprintf3(eb, dkT("%d"), WSAGetLastError()); 611 dk3app_log_3(app, DK3_LL_ERROR, msg, 113, 114, eb); 612#else 613 if (dk3ma_im_to_string(eb, DK3_SIZEOF(eb,dkChar), (dk3_im_t)WSAGetLastError())) { 614 dk3app_log_3(app, DK3_LL_ERROR, msg, 113, 114, eb); 615 } 616#endif 617 } 618 closesocket(sock); 619 } else { 620 /* ERROR: Failed to obtain socket! */ 621 dk3app_log_1(app, DK3_LL_ERROR, msg, 99); 622 } 623 } else { 624 /* ERROR: Failed to find IP address for host! */ 625 dk3app_log_1(app, DK3_LL_ERROR, msg, 100); 626 } 627} 628 629 630 631/** Clean up one remote print queue. 632 @param app Application structure. 633 @param msg Localized message texts. 634 @param userName User name. 635 @param queueName Print queue name. 636*/ 637static 638void 639dkwt_clear_one_remote_queue( 640 dk3_app_t *app, 641 dkChar const * const *msg, 642 dkChar const *userName, 643 dkChar const *queueName 644) 645{ 646 dkChar qnb[256]; /* Copy of queue name. */ 647 char qnc[256]; /* Queue name as char. */ 648 char unc[256]; /* User name as char. */ 649 char rqc[512]; /* Request. */ 650 dkChar *p1; /* Host name part. */ 651 size_t sz; 652 int ie; /* Used encoding. */ 653 ie = dk3app_get_encoding(app); 654 if(dk3str_len(queueName) < DK3_SIZEOF(qnb,dkChar)) { 655 dk3str_cpy_not_overlapped(qnb, queueName); 656 p1 = dk3str_chr(qnb, dkT('@')); 657 if(p1) { 658 *(p1++) = dkT('\0'); 659 p1 = dk3str_start(p1, NULL); 660 if(p1) { 661 dk3str_normalize(qnb, NULL, dkT(' ')); 662 if(dk3str_len(qnb) > 0) { 663 if(dk3str_to_c8u_app(qnc, sizeof(qnc), qnb, ie, app)) { 664 if(dk3str_to_c8u_app(unc, sizeof(unc), userName, ie, app)) { 665 sz = strlen(qnc) + strlen(unc) + 8; 666 if(sz < sizeof(rqc)) { 667#if DK3_HAVE_SNPRINTF 668 snprintf(rqc, sizeof(rqc), "%c%s %s all\n", 0x05, qnc, unc); 669#else 670 sprintf(rqc, "%c%s %s all\n", 0x05, qnc, unc); 671#endif 672 /* PROGRESS: Cleaning up remote print queue ... */ 673 dk3app_log_3(app, DK3_LL_PROGRESS, msg, 101, 102, queueName); 674 dkwt_cp_send_request(app, msg, rqc, p1); 675 } else { 676 /* ERROR: Reqeust becomes too long! */ 677 dk3app_log_1(app, DK3_LL_ERROR, msg, 103); 678 } 679 } else { 680 /* ERROR: Failed to re-encode user name to UTF-8! */ 681 } 682 } else { 683 /* ERROR: Failed to re-encode the queue name to UTF-8! */ 684 } 685 } else { 686 /* ERROR: Empty queue name! */ 687 dk3app_log_3(app, DK3_LL_ERROR, msg, 104, 105, queueName); 688 } 689 } else { 690 /* ERROR: Empty host name! */ 691 dk3app_log_3(app, DK3_LL_ERROR, msg, 106, 107, queueName); 692 } 693 } else { 694 /* ERROR: Not a queue@host name! */ 695 dk3app_log_3(app, DK3_LL_ERROR, msg, 108, 109, queueName); 696 } 697 } else { 698 /* ERROR: Queue name too long! */ 699 dk3app_log_3(app, DK3_LL_ERROR, msg, 110, 111, queueName); 700 } 701} 702 703 704 705void 706dkwt_clear_printers_remote( 707 dk3_app_t *app, 708 dkChar const * const *msg, 709 dkChar const * const * DK3_ARG_UNUSED(kwnl), 710 dkChar const *userName, 711 dk3_sto_it_t *iterator 712) 713{ 714 WORD vrq; 715 WSADATA wsa; 716 dkChar const *qn; 717 DK3_UNUSED_ARG(kwnl) 718 vrq = MAKEWORD(2,0); 719 if(0 == WSAStartup(vrq, &wsa)) { 720 dk3sto_it_reset(iterator); 721 while(NULL != (qn = (dkChar const *)dk3sto_it_next(iterator))) { 722 dkwt_clear_one_remote_queue(app, msg, userName, qn); 723 } 724 (void)WSACleanup(); 725 } else { 726 /* ERROR: Failed to initialize Windows socket! */ 727 dk3app_log_1(app, DK3_LL_ERROR, msg, 112); 728 } 729} 730 731 732 733/* vim: set ai sw=2 : */ 734 735