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