patch to fix NetServerEnum with multiple workgroup lists kindly supplied.
[Samba.git] / source / smbd / ipc.c
blobc5c87ea07f6599c1e7264c07aefe0cbf2b5cef0d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles the named pipe and mailslot calls
23 in the SMBtrans protocol
26 #include "includes.h"
28 #ifdef CHECK_TYPES
29 #undef CHECK_TYPES
30 #endif
31 #define CHECK_TYPES 0
33 extern int DEBUGLEVEL;
34 extern int maxxmit;
35 extern files_struct Files[];
36 extern connection_struct Connections[];
38 extern fstring local_machine;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ERROR_INVALID_LEVEL 124
49 #define ERROR_MORE_DATA 234
51 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
62 extern int Client;
64 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
66 pstring buf;
67 int l;
69 if (!src || !dst || !n || !(*dst)) return(0);
71 StrnCpy(buf,src,sizeof(buf)/2);
72 string_sub(buf,"%S",lp_servicename(snum));
73 standard_sub(cnum,buf);
74 StrnCpy(*dst,buf,*n);
75 l = strlen(*dst) + 1;
76 (*dst) += l;
77 (*n) -= l;
78 return l;
81 static int CopyAndAdvance(char** dst, char* src, int* n)
83 int l;
84 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(*dst,src,*n);
86 l = strlen(*dst) + 1;
87 (*dst) += l;
88 (*n) -= l;
89 return l;
92 static int StrlenExpanded(int cnum, int snum, char* s)
94 pstring buf;
95 if (!s) return(0);
96 StrnCpy(buf,s,sizeof(buf)/2);
97 string_sub(buf,"%S",lp_servicename(snum));
98 standard_sub(cnum,buf);
99 return strlen(buf) + 1;
102 static char* Expand(int cnum, int snum, char* s)
104 static pstring buf;
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 string_sub(buf,"%S",lp_servicename(snum));
108 standard_sub(cnum,buf);
109 return &buf[0];
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL prefix_ok(char *str,char *prefix)
117 return(strncmp(str,prefix,strlen(prefix)) == 0);
121 /****************************************************************************
122 send a trans reply
123 ****************************************************************************/
124 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
125 int ldata,int lparam,int lsetup)
127 int i;
128 int this_ldata,this_lparam;
129 int tot_data=0,tot_param=0;
130 int align;
132 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
133 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
135 align = (this_lparam%4);
137 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
138 if (this_lparam)
139 memcpy(smb_buf(outbuf),param,this_lparam);
140 if (this_ldata)
141 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
143 SSVAL(outbuf,smb_vwv0,lparam);
144 SSVAL(outbuf,smb_vwv1,ldata);
145 SSVAL(outbuf,smb_vwv3,this_lparam);
146 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
147 SSVAL(outbuf,smb_vwv5,0);
148 SSVAL(outbuf,smb_vwv6,this_ldata);
149 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
150 SSVAL(outbuf,smb_vwv8,0);
151 SSVAL(outbuf,smb_vwv9,lsetup);
152 for (i=0;i<lsetup;i++)
153 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
155 show_msg(outbuf);
156 send_smb(Client,outbuf);
158 tot_data = this_ldata;
159 tot_param = this_lparam;
161 while (tot_data < ldata || tot_param < lparam)
163 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
164 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
166 align = (this_lparam%4);
168 set_message(outbuf,10,this_ldata+this_lparam+align,False);
169 if (this_lparam)
170 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
171 if (this_ldata)
172 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
174 SSVAL(outbuf,smb_vwv3,this_lparam);
175 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
176 SSVAL(outbuf,smb_vwv5,tot_param);
177 SSVAL(outbuf,smb_vwv6,this_ldata);
178 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
179 SSVAL(outbuf,smb_vwv8,tot_data);
180 SSVAL(outbuf,smb_vwv9,0);
182 show_msg(outbuf);
183 send_smb(Client,outbuf);
185 tot_data += this_ldata;
186 tot_param += this_lparam;
192 /****************************************************************************
193 get a print queue
194 ****************************************************************************/
196 struct pack_desc {
197 char* format; /* formatstring for structure */
198 char* subformat; /* subformat for structure */
199 char* base; /* baseaddress of buffer */
200 int buflen; /* remaining size for fixed part; on init: length of base */
201 int subcount; /* count of substructures */
202 char* structbuf; /* pointer into buffer for remaining fixed part */
203 int stringlen; /* remaining size for variable part */
204 char* stringbuf; /* pointer into buffer for remaining variable part */
205 int neededlen; /* total needed size */
206 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
207 char* curpos; /* current position; pointer into format or subformat */
208 int errcode;
211 static int get_counter(char** p)
213 int i, n;
214 if (!p || !(*p)) return(1);
215 if (!isdigit(**p)) return 1;
216 for (n = 0;;) {
217 i = **p;
218 if (isdigit(i))
219 n = 10 * n + (i - '0');
220 else
221 return n;
222 (*p)++;
226 static int getlen(char* p)
228 int n = 0;
229 if (!p) return(0);
230 while (*p) {
231 switch( *p++ ) {
232 case 'W': /* word (2 byte) */
233 n += 2;
234 break;
235 case 'N': /* count of substructures (word) at end */
236 n += 2;
237 break;
238 case 'D': /* double word (4 byte) */
239 case 'z': /* offset to zero terminated string (4 byte) */
240 case 'l': /* offset to user data (4 byte) */
241 n += 4;
242 break;
243 case 'b': /* offset to data (with counter) (4 byte) */
244 n += 4;
245 get_counter(&p);
246 break;
247 case 'B': /* byte (with optional counter) */
248 n += get_counter(&p);
249 break;
252 return n;
255 static BOOL init_package(struct pack_desc* p, int count, int subcount)
257 int n = p->buflen;
258 int i;
260 if (!p->format || !p->base) return(False);
262 i = count * getlen(p->format);
263 if (p->subformat) i += subcount * getlen(p->subformat);
264 p->structbuf = p->base;
265 p->neededlen = 0;
266 p->usedlen = 0;
267 p->subcount = 0;
268 p->curpos = p->format;
269 if (i > n) {
270 i = n = 0;
271 p->errcode = NERR_BufTooSmall;
274 p->errcode = NERR_Success;
275 p->buflen = i;
276 n -= i;
277 p->stringbuf = p->base + i;
278 p->stringlen = n;
279 return(p->errcode == NERR_Success);
282 #ifdef __STDC__
283 static int package(struct pack_desc* p, ...)
285 #else
286 static int package(va_alist)
287 va_dcl
289 struct pack_desc* p;
290 #endif
291 va_list args;
292 int needed=0, stringneeded;
293 char* str=NULL;
294 int is_string=0, stringused;
295 int32 temp;
297 #ifdef __STDC__
298 va_start(args,p);
299 #else
300 va_start(args);
301 p = va_arg(args,struct pack_desc *);
302 #endif
304 if (!*p->curpos) {
305 if (!p->subcount)
306 p->curpos = p->format;
307 else {
308 p->curpos = p->subformat;
309 p->subcount--;
312 #if CHECK_TYPES
313 str = va_arg(args,char*);
314 if (strncmp(str,p->curpos,strlen(str)) != 0) {
315 DEBUG(2,("type error in package: %s instead of %*s\n",str,
316 strlen(str),p->curpos));
317 va_end(args);
318 #if AJT
319 ajt_panic();
320 #endif
321 return 0;
323 #endif
324 stringneeded = -1;
326 if (!p->curpos) return(0);
328 switch( *p->curpos++ ) {
329 case 'W': /* word (2 byte) */
330 needed = 2;
331 temp = va_arg(args,int);
332 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
333 break;
334 case 'N': /* count of substructures (word) at end */
335 needed = 2;
336 p->subcount = va_arg(args,int);
337 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
338 break;
339 case 'D': /* double word (4 byte) */
340 needed = 4;
341 temp = va_arg(args,int);
342 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
343 break;
344 case 'B': /* byte (with optional counter) */
345 needed = get_counter(&p->curpos);
347 char *s = va_arg(args,char*);
348 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
350 break;
351 case 'z': /* offset to zero terminated string (4 byte) */
352 str = va_arg(args,char*);
353 stringneeded = (str ? strlen(str)+1 : 0);
354 is_string = 1;
355 break;
356 case 'l': /* offset to user data (4 byte) */
357 str = va_arg(args,char*);
358 stringneeded = va_arg(args,int);
359 is_string = 0;
360 break;
361 case 'b': /* offset to data (with counter) (4 byte) */
362 str = va_arg(args,char*);
363 stringneeded = get_counter(&p->curpos);
364 is_string = 0;
365 break;
367 va_end(args);
368 if (stringneeded >= 0) {
369 needed = 4;
370 if (p->buflen >= needed) {
371 stringused = stringneeded;
372 if (stringused > p->stringlen) {
373 stringused = (is_string ? p->stringlen : 0);
374 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
376 if (!stringused)
377 SIVAL(p->structbuf,0,0);
378 else {
379 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
380 memcpy(p->stringbuf,str?str:"",stringused);
381 if (is_string) p->stringbuf[stringused-1] = '\0';
382 p->stringbuf += stringused;
383 p->stringlen -= stringused;
384 p->usedlen += stringused;
387 p->neededlen += stringneeded;
389 p->neededlen += needed;
390 if (p->buflen >= needed) {
391 p->structbuf += needed;
392 p->buflen -= needed;
393 p->usedlen += needed;
395 else {
396 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
398 return 1;
401 #if CHECK_TYPES
402 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
403 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
404 #else
405 #define PACK(desc,t,v) package(desc,v)
406 #define PACKl(desc,t,v,l) package(desc,v,l)
407 #endif
409 static void PACKI(struct pack_desc* desc,char *t,int v)
411 PACK(desc,t,v);
414 static void PACKS(struct pack_desc* desc,char *t,char *v)
416 PACK(desc,t,v);
419 static void PackDriverData(struct pack_desc* desc)
421 char drivdata[4+4+32];
422 SIVAL(drivdata,0,sizeof drivdata); /* cb */
423 SIVAL(drivdata,4,1000); /* lVersion */
424 memset(drivdata+8,0,32); /* szDeviceName */
425 strcpy(drivdata+8,"NULL");
426 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
429 static int check_printq_info(struct pack_desc* desc,
430 int uLevel, const char* id1, const char* id2)
432 desc->subformat = NULL;
433 switch( uLevel ) {
434 case 0:
435 desc->format = "B13";
436 break;
437 case 1:
438 desc->format = "B13BWWWzzzzzWW";
439 break;
440 case 2:
441 desc->format = "B13BWWWzzzzzWN";
442 desc->subformat = "WB21BB16B10zWWzDDz";
443 break;
444 case 3:
445 desc->format = "zWWWWzzzzWWzzl";
446 break;
447 case 4:
448 desc->format = "zWWWWzzzzWNzzl";
449 desc->subformat = "WWzWWDDzz";
450 break;
451 case 5:
452 desc->format = "z";
453 break;
454 default: return False;
456 if (strcmp(desc->format,id1) != 0) return False;
457 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
458 return True;
461 static void fill_printjob_info(int cnum, int snum, int uLevel,
462 struct pack_desc* desc,
463 print_queue_struct* queue, int n)
465 time_t t = queue->time;
467 /* the client expects localtime */
468 t -= TimeDiff(t);
470 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
471 if (uLevel == 1) {
472 PACKS(desc,"B21",queue->user); /* szUserName */
473 PACKS(desc,"B",""); /* pad */
474 PACKS(desc,"B16",""); /* szNotifyName */
475 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
476 PACKS(desc,"z",""); /* pszParms */
477 PACKI(desc,"W",n+1); /* uPosition */
478 PACKI(desc,"W",queue->status); /* fsStatus */
479 PACKS(desc,"z",""); /* pszStatus */
480 PACKI(desc,"D",t); /* ulSubmitted */
481 PACKI(desc,"D",queue->size); /* ulSize */
482 PACKS(desc,"z",queue->file); /* pszComment */
484 if (uLevel == 2 || uLevel == 3) {
485 PACKI(desc,"W",queue->priority); /* uPriority */
486 PACKS(desc,"z",queue->user); /* pszUserName */
487 PACKI(desc,"W",n+1); /* uPosition */
488 PACKI(desc,"W",queue->status); /* fsStatus */
489 PACKI(desc,"D",t); /* ulSubmitted */
490 PACKI(desc,"D",queue->size); /* ulSize */
491 PACKS(desc,"z","Samba"); /* pszComment */
492 PACKS(desc,"z",queue->file); /* pszDocument */
493 if (uLevel == 3) {
494 PACKS(desc,"z",""); /* pszNotifyName */
495 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
496 PACKS(desc,"z",""); /* pszParms */
497 PACKS(desc,"z",""); /* pszStatus */
498 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
499 PACKS(desc,"z","lpd"); /* pszQProcName */
500 PACKS(desc,"z",""); /* pszQProcParms */
501 PACKS(desc,"z","NULL"); /* pszDriverName */
502 PackDriverData(desc); /* pDriverData */
503 PACKS(desc,"z",""); /* pszPrinterName */
508 static void fill_printq_info(int cnum, int snum, int uLevel,
509 struct pack_desc* desc,
510 int count, print_queue_struct* queue,
511 print_status_struct* status)
513 if (uLevel < 3) {
514 PACKS(desc,"B13",SERVICE(snum));
515 } else {
516 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
518 if (uLevel == 1 || uLevel == 2) {
519 PACKS(desc,"B",""); /* alignment */
520 PACKI(desc,"W",5); /* priority */
521 PACKI(desc,"W",0); /* start time */
522 PACKI(desc,"W",0); /* until time */
523 PACKS(desc,"z",""); /* pSepFile */
524 PACKS(desc,"z","lpd"); /* pPrProc */
525 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
526 PACKS(desc,"z",""); /* pParms */
527 if (snum < 0) {
528 PACKS(desc,"z","UNKNOWN PRINTER");
529 PACKI(desc,"W",LPSTAT_ERROR);
531 else if (!status || !status->message[0]) {
532 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
533 PACKI(desc,"W",LPSTAT_OK); /* status */
534 } else {
535 PACKS(desc,"z",status->message);
536 PACKI(desc,"W",status->status); /* status */
538 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
540 if (uLevel == 3 || uLevel == 4) {
541 PACKI(desc,"W",5); /* uPriority */
542 PACKI(desc,"W",0); /* uStarttime */
543 PACKI(desc,"W",0); /* uUntiltime */
544 PACKI(desc,"W",5); /* pad1 */
545 PACKS(desc,"z",""); /* pszSepFile */
546 PACKS(desc,"z","lpd"); /* pszPrProc */
547 PACKS(desc,"z",""); /* pszParms */
548 if (!status || !status->message[0]) {
549 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
550 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
551 } else {
552 PACKS(desc,"z",status->message); /* pszComment */
553 PACKI(desc,"W",status->status); /* fsStatus */
555 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
556 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
557 PACKS(desc,"z","NULL"); /* pszDriverName */
558 PackDriverData(desc); /* pDriverData */
560 if (uLevel == 2 || uLevel == 4) {
561 int i;
562 for (i=0;i<count;i++)
563 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
566 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
569 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
570 int mdrcnt,int mprcnt,
571 char **rdata,char **rparam,
572 int *rdata_len,int *rparam_len)
574 char *str1 = param+2;
575 char *str2 = skip_string(str1,1);
576 char *p = skip_string(str2,1);
577 char *QueueName = p;
578 int uLevel,cbBuf;
579 int count=0;
580 int snum;
581 char* str3;
582 struct pack_desc desc;
583 print_queue_struct *queue=NULL;
584 print_status_struct status;
586 bzero(&status,sizeof(status));
587 bzero(&desc,sizeof(desc));
589 p = skip_string(p,1);
590 uLevel = SVAL(p,0);
591 cbBuf = SVAL(p,2);
592 str3 = p + 4;
594 if ((p = strchr(QueueName,'%'))) *p = 0;
596 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
598 /* check it's a supported varient */
599 if (!prefix_ok(str1,"zWrLh")) return False;
600 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
602 snum = lp_servicenumber(QueueName);
603 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
604 int pnum = lp_servicenumber(PRINTERS_NAME);
605 if (pnum >= 0) {
606 lp_add_printer(QueueName,pnum);
607 snum = lp_servicenumber(QueueName);
611 if (snum < 0 || !VALID_SNUM(snum)) return(False);
613 count = get_printqueue(snum,cnum,&queue,&status);
614 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
615 desc.base = *rdata;
616 desc.buflen = mdrcnt;
617 if (init_package(&desc,1,count)) {
618 desc.subcount = count;
619 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
622 *rdata_len = desc.usedlen;
624 *rparam_len = 6;
625 *rparam = REALLOC(*rparam,*rparam_len);
626 SSVALS(*rparam,0,desc.errcode);
627 SSVAL(*rparam,2,0);
628 SSVAL(*rparam,4,desc.neededlen);
630 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
632 if (queue) free(queue);
634 return(True);
638 /****************************************************************************
639 view list of all print jobs on all queues
640 ****************************************************************************/
641 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
642 int mdrcnt, int mprcnt,
643 char **rdata, char** rparam,
644 int *rdata_len, int *rparam_len)
646 char *param_format = param+2;
647 char *output_format1 = skip_string(param_format,1);
648 char *p = skip_string(output_format1,1);
649 int uLevel = SVAL(p,0);
650 char *output_format2 = p + 4;
651 int services = lp_numservices();
652 int i, n;
653 struct pack_desc desc;
654 print_queue_struct **queue = NULL;
655 print_status_struct *status = NULL;
656 int* subcntarr = NULL;
657 int queuecnt, subcnt=0, succnt=0;
659 bzero(&desc,sizeof(desc));
661 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
663 if (prefix_ok(param_format,"WrLeh")) return False;
664 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
665 return False;
666 queuecnt = 0;
667 for (i = 0; i < services; i++)
668 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
669 queuecnt++;
670 if (uLevel > 0) {
671 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
672 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
673 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
674 memset(status,0,queuecnt*sizeof(print_status_struct));
675 subcntarr = (int*)malloc(queuecnt*sizeof(int));
676 subcnt = 0;
677 n = 0;
678 for (i = 0; i < services; i++)
679 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
680 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
681 subcnt += subcntarr[n];
682 n++;
685 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
686 desc.base = *rdata;
687 desc.buflen = mdrcnt;
689 if (init_package(&desc,queuecnt,subcnt)) {
690 n = 0;
691 succnt = 0;
692 for (i = 0; i < services; i++)
693 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
694 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
695 n++;
696 if (desc.errcode == NERR_Success) succnt = n;
700 if (subcntarr) free(subcntarr);
702 *rdata_len = desc.usedlen;
703 *rparam_len = 8;
704 *rparam = REALLOC(*rparam,*rparam_len);
705 SSVALS(*rparam,0,desc.errcode);
706 SSVAL(*rparam,2,0);
707 SSVAL(*rparam,4,succnt);
708 SSVAL(*rparam,6,queuecnt);
710 for (i = 0; i < queuecnt; i++) {
711 if (queue && queue[i]) free(queue[i]);
714 if (queue) free(queue);
715 if (status) free(status);
717 return True;
720 /****************************************************************************
721 get info level for a server list query
722 ****************************************************************************/
723 static BOOL check_server_info(int uLevel, char* id)
725 switch( uLevel ) {
726 case 0:
727 if (strcmp(id,"B16") != 0) return False;
728 break;
729 case 1:
730 if (strcmp(id,"B16BBDz") != 0) return False;
731 break;
732 default:
733 return False;
735 return True;
738 /* used for server information: client, nameserv and ipc */
739 struct srv_info_struct
741 fstring name;
742 uint32 type;
743 fstring comment;
744 fstring domain; /* used ONLY in ipc.c NOT namework.c */
745 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
748 /*******************************************************************
749 filter out unwanted server info
750 This function returns True if the entry is wanted.
751 ******************************************************************/
752 static BOOL filter_server_info(struct srv_info_struct *server,
753 BOOL domains,
754 char *domain, uint32 request)
756 /* If no domain was specified, */
757 if (*domain == 0)
759 /* If entry's domain matches this server's domain,
760 accept this entry. */
761 if (strequal(lp_workgroup(), server->domain)) {
762 return True;
765 /* If specific domain requested, reject this entry. */
766 else if (domains)
768 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
769 return False;
772 /* If the request was for a list of domain enumerators,
773 we don't care what domain this entry is in as long
774 as it is a domain enumerator. */
775 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
776 (server->type & SV_TYPE_DOMAIN_ENUM))
778 return True;
781 DEBUG(4,("wrong domain: %8x: %s %s\n",server->type,server->name,server->domain));
782 return False;
785 /* If a domain name was specified, */
786 else
788 /* If this entry is in the requested domain, */
789 if (strequal(domain, server->domain))
792 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
793 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
795 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
796 return False;
799 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
800 !(server->type&SV_TYPE_DOMAIN_ENUM))
802 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
803 return False;
806 return True;
809 /* If the user didn't pick a domain,
810 (I don't think this can happen.) */
811 else if (!domains)
813 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
814 return False;
817 return True;
821 /*******************************************************************
822 get server info lists from the files saved by nmbd. Return the
823 number of entries
824 ******************************************************************/
825 static int get_server_info(uint32 servertype,
826 struct srv_info_struct **servers, BOOL domains,
827 char *domain)
829 FILE *f;
830 pstring fname;
831 int count=0;
832 int alloced=0;
833 pstring line;
835 strcpy(fname,lp_lockdir());
836 trim_string(fname,NULL,"/");
837 strcat(fname,"/");
838 strcat(fname,SERVER_LIST);
840 f = fopen(fname,"r");
842 if (!f) {
843 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
844 return(0);
847 /* request for everything is code for request all servers */
848 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
850 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
852 while (!feof(f))
854 fstring stype;
855 struct srv_info_struct *s;
856 char *ptr = line;
857 BOOL ok = True;
858 *ptr = 0;
860 fgets(line,sizeof(line)-1,f);
861 if (!*line) continue;
863 if (count == alloced) {
864 alloced += 10;
865 (*servers) = (struct srv_info_struct *)
866 Realloc(*servers,sizeof(**servers)*alloced);
867 if (!(*servers)) return(0);
868 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
870 s = &(*servers)[count];
872 if (!next_token(&ptr,s->name , NULL)) continue;
873 if (!next_token(&ptr,stype , NULL)) continue;
874 if (!next_token(&ptr,s->comment, NULL)) continue;
875 if (!next_token(&ptr,s->domain , NULL)) {
876 /* this allows us to cope with an old nmbd */
877 strcpy(s->domain,my_workgroup());
880 if (sscanf(stype,"%X",&s->type) != 1) {
881 DEBUG(4,("r:host file "));
882 ok = False;
885 /* doesn't match up: don't want it */
886 if (!(servertype & s->type)) {
887 DEBUG(4,("r:serv type "));
888 ok = False;
891 /* If all server, reject DOMIAN_ENUM entries? */
892 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
893 (s->type & SV_TYPE_DOMAIN_ENUM))
895 DEBUG(4,("s:all x dom "));
896 ok = False;
899 /* If a domain is specified, reject all except the
900 domain enumerators for the specified domain. */
901 if (domains && !(domain && *domain && strequal(domain, s->domain)))
903 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
905 DEBUG(4,("r:dom enum "));
906 ok = False;
910 if (ok)
912 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
913 s->name, s->type, s->comment, s->domain));
915 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
916 s->server_added = True;
917 count++;
919 else
921 DEBUG(4,("%20s %8x %25s %15s\n",
922 s->name, s->type, s->comment, s->domain));
926 fclose(f);
927 return(count);
931 /*******************************************************************
932 fill in a server info structure
933 ******************************************************************/
934 static int fill_srv_info(struct srv_info_struct *service,
935 int uLevel, char **buf, int *buflen,
936 char **stringbuf, int *stringspace, char *baseaddr)
938 int struct_len;
939 char* p;
940 char* p2;
941 int l2;
942 int len;
944 switch (uLevel) {
945 case 0: struct_len = 16; break;
946 case 1: struct_len = 26; break;
947 default: return -1;
950 if (!buf)
952 len = 0;
953 switch (uLevel)
955 case 1:
956 len = strlen(service->comment)+1;
957 break;
960 if (buflen) *buflen = struct_len;
961 if (stringspace) *stringspace = len;
962 return struct_len + len;
965 len = struct_len;
966 p = *buf;
967 if (*buflen < struct_len) return -1;
968 if (stringbuf)
970 p2 = *stringbuf;
971 l2 = *stringspace;
973 else
975 p2 = p + struct_len;
976 l2 = *buflen - struct_len;
978 if (!baseaddr) baseaddr = p;
980 switch (uLevel)
982 case 0:
983 StrnCpy(p,service->name,15);
984 break;
986 case 1:
987 StrnCpy(p,service->name,15);
988 SIVAL(p,18,service->type);
989 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
990 len += CopyAndAdvance(&p2,service->comment,&l2);
991 break;
994 if (stringbuf)
996 *buf = p + struct_len;
997 *buflen -= struct_len;
998 *stringbuf = p2;
999 *stringspace = l2;
1001 else
1003 *buf = p2;
1004 *buflen -= len;
1006 return len;
1010 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1012 return(strcmp(s1->name,s2->name));
1015 /****************************************************************************
1016 view list of servers available (or possibly domains). The info is
1017 extracted from lists saved by nmbd on the local host
1018 ****************************************************************************/
1019 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1020 int mdrcnt, int mprcnt, char **rdata,
1021 char **rparam, int *rdata_len, int *rparam_len)
1023 char *str1 = param+2;
1024 char *str2 = skip_string(str1,1);
1025 char *p = skip_string(str2,1);
1026 int uLevel = SVAL(p,0);
1027 int buf_len = SVAL(p,2);
1028 uint32 servertype = IVAL(p,4);
1029 char *p2;
1030 int data_len, fixed_len, string_len;
1031 int f_len, s_len;
1032 struct srv_info_struct *servers=NULL;
1033 int counted=0,total=0;
1034 int i;
1035 fstring domain;
1036 BOOL domains;
1037 BOOL domain_request;
1038 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1040 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1041 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1043 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1045 domain[0] = 0;
1046 p += 8;
1048 if (!prefix_ok(str1,"WrLehD")) return False;
1049 if (!check_server_info(uLevel,str2)) return False;
1051 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1052 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1053 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1055 if (strcmp(str1, "WrLehDO") == 0)
1057 domains = False;
1058 DEBUG(4, ("all domains\n"));
1060 else if (strcmp(str1, "WrLehDz") == 0)
1062 domains = True;
1063 StrnCpy(domain, p, sizeof(fstring)-1);
1064 DEBUG(4, ("domains must match \"%s\"\n", domains));
1067 if (lp_browse_list())
1069 total = get_server_info(servertype,&servers,domains,domain);
1072 data_len = fixed_len = string_len = 0;
1074 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1076 /* A dry run */
1078 char *lastname=NULL;
1080 for (i=0;i<total;i++)
1082 struct srv_info_struct *s = &servers[i];
1083 if (filter_server_info(s,domains,domain,
1084 local_request|domain_request))
1086 if (lastname && strequal(lastname,s->name)) continue;
1087 lastname = s->name;
1088 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1089 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1090 s->name, s->type, s->comment, s->domain));
1092 if (data_len <= buf_len)
1094 counted++;
1095 fixed_len += f_len;
1096 string_len += s_len;
1102 *rdata_len = fixed_len + string_len;
1103 *rdata = REALLOC(*rdata,*rdata_len);
1104 bzero(*rdata,*rdata_len);
1106 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1107 p = *rdata;
1108 f_len = fixed_len;
1109 s_len = string_len;
1111 /* the real thing */
1113 char *lastname=NULL;
1114 int count2 = counted;
1115 for (i = 0; i < total && count2;i++)
1117 struct srv_info_struct *s = &servers[i];
1118 if (filter_server_info(s,domains,domain,local_request|domain_request))
1120 if (lastname && strequal(lastname,s->name)) continue;
1121 lastname = s->name;
1122 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1123 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1124 s->name, s->type, s->comment, s->domain));
1125 count2--;
1130 *rparam_len = 8;
1131 *rparam = REALLOC(*rparam,*rparam_len);
1132 SSVAL(*rparam,0,NERR_Success);
1133 SSVAL(*rparam,2,0);
1134 SSVAL(*rparam,4,counted);
1135 SSVAL(*rparam,6,total);
1137 if (servers) free(servers);
1139 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1140 domain,uLevel,counted,total));
1142 return(True);
1146 /****************************************************************************
1147 get info about a share
1148 ****************************************************************************/
1149 static BOOL check_share_info(int uLevel, char* id)
1151 switch( uLevel ) {
1152 case 0:
1153 if (strcmp(id,"B13") != 0) return False;
1154 break;
1155 case 1:
1156 if (strcmp(id,"B13BWz") != 0) return False;
1157 break;
1158 case 2:
1159 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1160 break;
1161 case 91:
1162 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1163 break;
1164 default: return False;
1166 return True;
1169 static int fill_share_info(int cnum, int snum, int uLevel,
1170 char** buf, int* buflen,
1171 char** stringbuf, int* stringspace, char* baseaddr)
1173 int struct_len;
1174 char* p;
1175 char* p2;
1176 int l2;
1177 int len;
1179 switch( uLevel ) {
1180 case 0: struct_len = 13; break;
1181 case 1: struct_len = 20; break;
1182 case 2: struct_len = 40; break;
1183 case 91: struct_len = 68; break;
1184 default: return -1;
1188 if (!buf)
1190 len = 0;
1191 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1192 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1193 if (buflen) *buflen = struct_len;
1194 if (stringspace) *stringspace = len;
1195 return struct_len + len;
1198 len = struct_len;
1199 p = *buf;
1200 if ((*buflen) < struct_len) return -1;
1201 if (stringbuf)
1203 p2 = *stringbuf;
1204 l2 = *stringspace;
1206 else
1208 p2 = p + struct_len;
1209 l2 = (*buflen) - struct_len;
1211 if (!baseaddr) baseaddr = p;
1213 StrnCpy(p,lp_servicename(snum),13);
1215 if (uLevel > 0)
1217 int type;
1218 CVAL(p,13) = 0;
1219 type = STYPE_DISKTREE;
1220 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1221 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1222 SSVAL(p,14,type); /* device type */
1223 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1224 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1227 if (uLevel > 1)
1229 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1230 SSVALS(p,22,-1); /* max uses */
1231 SSVAL(p,24,1); /* current uses */
1232 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1233 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1234 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1237 if (uLevel > 2)
1239 memset(p+40,0,SHPWLEN+2);
1240 SSVAL(p,50,0);
1241 SIVAL(p,52,0);
1242 SSVAL(p,56,0);
1243 SSVAL(p,58,0);
1244 SIVAL(p,60,0);
1245 SSVAL(p,64,0);
1246 SSVAL(p,66,0);
1249 if (stringbuf)
1251 (*buf) = p + struct_len;
1252 (*buflen) -= struct_len;
1253 (*stringbuf) = p2;
1254 (*stringspace) = l2;
1256 else
1258 (*buf) = p2;
1259 (*buflen) -= len;
1261 return len;
1264 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1265 int mdrcnt,int mprcnt,
1266 char **rdata,char **rparam,
1267 int *rdata_len,int *rparam_len)
1269 char *str1 = param+2;
1270 char *str2 = skip_string(str1,1);
1271 char *netname = skip_string(str2,1);
1272 char *p = skip_string(netname,1);
1273 int uLevel = SVAL(p,0);
1274 int snum = find_service(netname);
1276 if (snum < 0) return False;
1278 /* check it's a supported varient */
1279 if (!prefix_ok(str1,"zWrLh")) return False;
1280 if (!check_share_info(uLevel,str2)) return False;
1282 *rdata = REALLOC(*rdata,mdrcnt);
1283 p = *rdata;
1284 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1285 if (*rdata_len < 0) return False;
1287 *rparam_len = 6;
1288 *rparam = REALLOC(*rparam,*rparam_len);
1289 SSVAL(*rparam,0,NERR_Success);
1290 SSVAL(*rparam,2,0); /* converter word */
1291 SSVAL(*rparam,4,*rdata_len);
1293 return(True);
1296 /****************************************************************************
1297 view list of shares available
1298 ****************************************************************************/
1299 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1300 int mdrcnt,int mprcnt,
1301 char **rdata,char **rparam,
1302 int *rdata_len,int *rparam_len)
1304 char *str1 = param+2;
1305 char *str2 = skip_string(str1,1);
1306 char *p = skip_string(str2,1);
1307 int uLevel = SVAL(p,0);
1308 int buf_len = SVAL(p,2);
1309 char *p2;
1310 int count=lp_numservices();
1311 int total=0,counted=0;
1312 int i;
1313 int data_len, fixed_len, string_len;
1314 int f_len, s_len;
1316 if (!prefix_ok(str1,"WrLeh")) return False;
1317 if (!check_share_info(uLevel,str2)) return False;
1319 data_len = fixed_len = string_len = 0;
1320 for (i=0;i<count;i++)
1321 if (lp_browseable(i) && lp_snum_ok(i))
1323 total++;
1324 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1325 if (data_len <= buf_len)
1327 counted++;
1328 fixed_len += f_len;
1329 string_len += s_len;
1332 *rdata_len = fixed_len + string_len;
1333 *rdata = REALLOC(*rdata,*rdata_len);
1334 memset(*rdata,0,*rdata_len);
1336 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1337 p = *rdata;
1338 f_len = fixed_len;
1339 s_len = string_len;
1340 for (i = 0; i < count;i++)
1341 if (lp_browseable(i) && lp_snum_ok(i))
1342 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1343 break;
1345 *rparam_len = 8;
1346 *rparam = REALLOC(*rparam,*rparam_len);
1347 SSVAL(*rparam,0,NERR_Success);
1348 SSVAL(*rparam,2,0);
1349 SSVAL(*rparam,4,counted);
1350 SSVAL(*rparam,6,total);
1352 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1353 counted,total,uLevel,
1354 buf_len,*rdata_len,mdrcnt));
1355 return(True);
1360 /****************************************************************************
1361 get the time of day info
1362 ****************************************************************************/
1363 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1364 int mdrcnt,int mprcnt,
1365 char **rdata,char **rparam,
1366 int *rdata_len,int *rparam_len)
1368 char *p;
1369 *rparam_len = 4;
1370 *rparam = REALLOC(*rparam,*rparam_len);
1372 *rdata_len = 21;
1373 *rdata = REALLOC(*rdata,*rdata_len);
1375 SSVAL(*rparam,0,NERR_Success);
1376 SSVAL(*rparam,2,0); /* converter word */
1378 p = *rdata;
1381 struct tm *t;
1382 time_t unixdate = time(NULL);
1384 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1385 by NT in a "net time" operation,
1386 it seems to ignore the one below */
1388 /* the client expects to get localtime, not GMT, in this bit
1389 (I think, this needs testing) */
1390 t = LocalTime(&unixdate);
1392 SIVAL(p,4,0); /* msecs ? */
1393 CVAL(p,8) = t->tm_hour;
1394 CVAL(p,9) = t->tm_min;
1395 CVAL(p,10) = t->tm_sec;
1396 CVAL(p,11) = 0; /* hundredths of seconds */
1397 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1398 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1399 CVAL(p,16) = t->tm_mday;
1400 CVAL(p,17) = t->tm_mon + 1;
1401 SSVAL(p,18,1900+t->tm_year);
1402 CVAL(p,20) = t->tm_wday;
1406 return(True);
1409 /****************************************************************************
1410 set the user password
1411 ****************************************************************************/
1412 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1413 int mdrcnt,int mprcnt,
1414 char **rdata,char **rparam,
1415 int *rdata_len,int *rparam_len)
1417 char *p = skip_string(param+2,2);
1418 fstring user;
1419 fstring pass1,pass2;
1421 strcpy(user,p);
1423 p = skip_string(p,1);
1425 StrnCpy(pass1,p,16);
1426 StrnCpy(pass2,p+16,16);
1428 *rparam_len = 4;
1429 *rparam = REALLOC(*rparam,*rparam_len);
1431 *rdata_len = 0;
1433 SSVAL(*rparam,0,NERR_Success);
1434 SSVAL(*rparam,2,0); /* converter word */
1436 DEBUG(3,("Set password for <%s>\n",user));
1438 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1439 !chgpasswd(user,pass1,pass2))
1440 SSVAL(*rparam,0,NERR_badpass);
1442 bzero(pass1,sizeof(fstring));
1443 bzero(pass2,sizeof(fstring));
1445 return(True);
1448 /****************************************************************************
1449 delete a print job
1450 Form: <W> <>
1451 ****************************************************************************/
1452 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1453 int mdrcnt,int mprcnt,
1454 char **rdata,char **rparam,
1455 int *rdata_len,int *rparam_len)
1457 int function = SVAL(param,0);
1458 char *str1 = param+2;
1459 char *str2 = skip_string(str1,1);
1460 char *p = skip_string(str2,1);
1461 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1462 by the print queue api */
1463 int snum = (SVAL(p,0)>>8);
1464 int i, count;
1467 /* check it's a supported varient */
1468 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1469 return(False);
1471 *rparam_len = 4;
1472 *rparam = REALLOC(*rparam,*rparam_len);
1474 *rdata_len = 0;
1476 SSVAL(*rparam,0,NERR_Success);
1478 if (snum >= 0 && VALID_SNUM(snum))
1480 print_queue_struct *queue=NULL;
1481 lpq_reset(snum);
1482 count = get_printqueue(snum,cnum,&queue,NULL);
1484 for (i=0;i<count;i++)
1485 if ((queue[i].job%0xFF) == jobid)
1487 switch (function) {
1488 case 81: /* delete */
1489 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1490 del_printqueue(cnum,snum,queue[i].job);
1491 break;
1492 case 82: /* pause */
1493 case 83: /* resume */
1494 DEBUG(3,("%s queue entry %d\n",
1495 (function==82?"pausing":"resuming"),queue[i].job));
1496 status_printjob(cnum,snum,queue[i].job,
1497 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1498 break;
1500 break;
1503 if (i==count)
1504 SSVAL(*rparam,0,NERR_JobNotFound);
1506 if (queue) free(queue);
1509 SSVAL(*rparam,2,0); /* converter word */
1511 return(True);
1514 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1515 int mdrcnt,int mprcnt,
1516 char **rdata,char **rparam,
1517 int *rdata_len,int *rparam_len)
1519 char *str1 = param+2;
1520 char *str2 = skip_string(str1,1);
1521 char *QueueName = skip_string(str2,1);
1522 int snum;
1524 /* check it's a supported varient */
1525 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1526 return(False);
1528 *rparam_len = 4;
1529 *rparam = REALLOC(*rparam,*rparam_len);
1531 *rdata_len = 0;
1533 SSVAL(*rparam,0,NERR_Success);
1534 SSVAL(*rparam,2,0); /* converter word */
1536 snum = lp_servicenumber(QueueName);
1537 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1538 int pnum = lp_servicenumber(PRINTERS_NAME);
1539 if (pnum >= 0) {
1540 lp_add_printer(QueueName,pnum);
1541 snum = lp_servicenumber(QueueName);
1545 if (snum >= 0 && VALID_SNUM(snum)) {
1546 print_queue_struct *queue=NULL;
1547 int i, count;
1548 lpq_reset(snum);
1550 count = get_printqueue(snum,cnum,&queue,NULL);
1551 for (i = 0; i < count; i++)
1552 del_printqueue(cnum,snum,queue[i].job);
1554 if (queue) free(queue);
1557 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1559 return(True);
1563 /****************************************************************************
1564 set the property of a print job (undocumented?)
1565 ? function = 0xb -> set name of print job
1566 ? function = 0x6 -> move print job up/down
1567 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1568 or <WWsTP> <WB21BB16B10zWWzDDz>
1569 ****************************************************************************/
1570 static int check_printjob_info(struct pack_desc* desc,
1571 int uLevel, char* id)
1573 desc->subformat = NULL;
1574 switch( uLevel ) {
1575 case 0: desc->format = "W"; break;
1576 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1577 case 2: desc->format = "WWzWWDDzz"; break;
1578 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1579 default: return False;
1581 if (strcmp(desc->format,id) != 0) return False;
1582 return True;
1585 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1586 int mdrcnt,int mprcnt,
1587 char **rdata,char **rparam,
1588 int *rdata_len,int *rparam_len)
1590 struct pack_desc desc;
1591 char *str1 = param+2;
1592 char *str2 = skip_string(str1,1);
1593 char *p = skip_string(str2,1);
1594 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1595 by the print queue api */
1596 int snum = (SVAL(p,0)>>8);
1597 int uLevel = SVAL(p,2);
1598 int function = SVAL(p,4); /* what is this ?? */
1599 int i;
1600 char *s = data;
1602 *rparam_len = 4;
1603 *rparam = REALLOC(*rparam,*rparam_len);
1605 *rdata_len = 0;
1607 /* check it's a supported varient */
1608 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1609 return(False);
1611 switch (function) {
1612 case 0x6: /* change job place in the queue, data gives the new place */
1613 if (snum >= 0 && VALID_SNUM(snum))
1615 print_queue_struct *queue=NULL;
1616 int count;
1618 lpq_reset(snum);
1619 count = get_printqueue(snum,cnum,&queue,NULL);
1620 for (i=0;i<count;i++) /* find job */
1621 if ((queue[i].job%0xFF) == jobid) break;
1623 if (i==count) {
1624 desc.errcode=NERR_JobNotFound;
1625 if (queue) free(queue);
1627 else {
1628 desc.errcode=NERR_Success;
1629 i++;
1630 #if 0
1632 int place= SVAL(data,0);
1633 /* we currently have no way of doing this. Can any unix do it? */
1634 if (i < place) /* move down */;
1635 else if (i > place ) /* move up */;
1637 #endif
1638 desc.errcode=NERR_notsupported; /* not yet supported */
1639 if (queue) free(queue);
1642 else desc.errcode=NERR_JobNotFound;
1643 break;
1644 case 0xb: /* change print job name, data gives the name */
1645 /* jobid, snum should be zero */
1646 if (isalpha(*s))
1648 pstring name;
1649 int l = 0;
1650 while (l<64 && *s)
1652 if (issafe(*s)) name[l++] = *s;
1653 s++;
1655 name[l] = 0;
1657 DEBUG(3,("Setting print name to %s\n",name));
1659 for (i=0;i<MAX_OPEN_FILES;i++)
1660 if (Files[i].open && Files[i].print_file)
1662 pstring wd;
1663 GetWd(wd);
1664 unbecome_user();
1666 if (!become_user(Files[i].cnum,uid) ||
1667 !become_service(Files[i].cnum,True))
1668 break;
1670 if (sys_rename(Files[i].name,name) == 0)
1671 string_set(&Files[i].name,name);
1672 break;
1675 desc.errcode=NERR_Success;
1677 break;
1678 default: /* not implemented */
1679 return False;
1682 SSVALS(*rparam,0,desc.errcode);
1683 SSVAL(*rparam,2,0); /* converter word */
1685 return(True);
1689 /****************************************************************************
1690 get info about the server
1691 ****************************************************************************/
1692 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1693 int mdrcnt,int mprcnt,
1694 char **rdata,char **rparam,
1695 int *rdata_len,int *rparam_len)
1697 char *str1 = param+2;
1698 char *str2 = skip_string(str1,1);
1699 char *p = skip_string(str2,1);
1700 int uLevel = SVAL(p,0);
1701 char *p2;
1702 int struct_len;
1704 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1706 /* check it's a supported varient */
1707 if (!prefix_ok(str1,"WrLh")) return False;
1708 switch( uLevel ) {
1709 case 0:
1710 if (strcmp(str2,"B16") != 0) return False;
1711 struct_len = 16;
1712 break;
1713 case 1:
1714 if (strcmp(str2,"B16BBDz") != 0) return False;
1715 struct_len = 26;
1716 break;
1717 case 2:
1718 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1719 != 0) return False;
1720 struct_len = 134;
1721 break;
1722 case 3:
1723 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1724 != 0) return False;
1725 struct_len = 144;
1726 break;
1727 case 20:
1728 if (strcmp(str2,"DN") != 0) return False;
1729 struct_len = 6;
1730 break;
1731 case 50:
1732 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1733 struct_len = 42;
1734 break;
1735 default: return False;
1738 *rdata_len = mdrcnt;
1739 *rdata = REALLOC(*rdata,*rdata_len);
1741 p = *rdata;
1742 p2 = p + struct_len;
1743 if (uLevel != 20) {
1744 StrnCpy(p,local_machine,16);
1745 strupper(p);
1747 p += 16;
1748 if (uLevel > 0)
1750 struct srv_info_struct *servers=NULL;
1751 int i,count;
1752 pstring comment;
1753 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1754 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1756 strcpy(comment,lp_serverstring());
1758 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1759 for (i=0;i<count;i++)
1760 if (strequal(servers[i].name,local_machine)) {
1761 servertype = servers[i].type;
1762 strcpy(comment,servers[i].comment);
1765 if (servers) free(servers);
1767 SCVAL(p,0,2); /* version_major */
1768 SCVAL(p,1,0); /* version_minor */
1769 SIVAL(p,2,servertype);
1770 if (mdrcnt == struct_len) {
1771 SIVAL(p,6,0);
1772 } else {
1773 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1774 standard_sub(cnum,comment);
1775 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1776 p2 = skip_string(p2,1);
1779 if (uLevel > 1)
1781 return False; /* not yet implemented */
1784 *rdata_len = PTR_DIFF(p2,*rdata);
1786 *rparam_len = 6;
1787 *rparam = REALLOC(*rparam,*rparam_len);
1788 SSVAL(*rparam,0,NERR_Success);
1789 SSVAL(*rparam,2,0); /* converter word */
1790 SSVAL(*rparam,4,*rdata_len);
1792 return(True);
1796 /****************************************************************************
1797 get info about the server
1798 ****************************************************************************/
1799 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1800 int mdrcnt,int mprcnt,
1801 char **rdata,char **rparam,
1802 int *rdata_len,int *rparam_len)
1804 char *str1 = param+2;
1805 char *str2 = skip_string(str1,1);
1806 char *p = skip_string(str2,1);
1807 char *p2;
1808 extern pstring sesssetup_user;
1809 int level = SVAL(p,0);
1811 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1813 *rparam_len = 6;
1814 *rparam = REALLOC(*rparam,*rparam_len);
1816 /* check it's a supported varient */
1817 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1818 return(False);
1820 *rdata_len = mdrcnt + 1024;
1821 *rdata = REALLOC(*rdata,*rdata_len);
1823 SSVAL(*rparam,0,NERR_Success);
1824 SSVAL(*rparam,2,0); /* converter word */
1826 p = *rdata;
1827 p2 = p + 22;
1829 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1830 strcpy(p2,local_machine);
1831 p2 = skip_string(p2,1);
1832 p += 4;
1834 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1835 strcpy(p2,sesssetup_user);
1836 p2 = skip_string(p2,1);
1837 p += 4;
1839 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1840 strcpy(p2,my_workgroup());
1841 p2 = skip_string(p2,1);
1842 p += 4;
1844 SCVAL(p,0,2); /* major version?? */
1845 SCVAL(p,1,1); /* minor version?? */
1846 p += 2;
1848 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1849 strcpy(p2,my_workgroup()); /* login domain?? */
1850 p2 = skip_string(p2,1);
1851 p += 4;
1853 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1854 strcpy(p2,"");
1855 p2 = skip_string(p2,1);
1856 p += 4;
1858 *rdata_len = PTR_DIFF(p2,*rdata);
1860 SSVAL(*rparam,4,*rdata_len);
1862 return(True);
1866 /****************************************************************************
1867 get info about a user
1868 ****************************************************************************/
1870 #define USER_PRIV_GUEST 0
1871 #define USER_PRIV_USER 1
1872 #define USER_PRIV_ADMIN 2
1874 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1875 int mdrcnt,int mprcnt,
1876 char **rdata,char **rparam,
1877 int *rdata_len,int *rparam_len)
1879 char *str1 = param+2;
1880 char *str2 = skip_string(str1,1);
1881 char *UserName = skip_string(str2,1);
1882 char *p = skip_string(UserName,1);
1883 int uLevel = SVAL(p,0);
1884 char *p2;
1886 *rparam_len = 6;
1887 *rparam = REALLOC(*rparam,*rparam_len);
1889 /* check it's a supported varient */
1890 if (strcmp(str1,"zWrLh") != 0) return False;
1891 switch( uLevel ) {
1892 case 0: p2 = "B21"; break;
1893 case 1: p2 = "B21BB16DWzzWz"; break;
1894 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1895 case 10: p2 = "B21Bzzz"; break;
1896 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1897 default: return False;
1899 if (strcmp(p2,str2) != 0) return False;
1901 *rdata_len = mdrcnt + 1024;
1902 *rdata = REALLOC(*rdata,*rdata_len);
1904 SSVAL(*rparam,0,NERR_Success);
1905 SSVAL(*rparam,2,0); /* converter word */
1907 p = *rdata;
1908 p2 = p + 86;
1910 memset(p,0,21);
1911 strcpy(p,UserName);
1912 if (uLevel > 0) {
1913 SCVAL(p,21,0);
1914 *p2 = 0;
1915 if (uLevel >= 10) {
1916 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1917 strcpy(p2,"<Comment>");
1918 p2 = skip_string(p2,1);
1919 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1920 strcpy(p2,"<UserComment>");
1921 p2 = skip_string(p2,1);
1922 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1923 strcpy(p2,"<FullName>");
1924 p2 = skip_string(p2,1);
1926 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1927 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1928 SIVAL(p,36,0); /* auth flags */
1929 SIVALS(p,40,-1); /* password age */
1930 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1931 strcpy(p2,"\\\\%L\\HOMES");
1932 standard_sub_basic(p2);
1933 p2 = skip_string(p2,1);
1934 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1935 strcpy(p2,"");
1936 p2 = skip_string(p2,1);
1937 SIVAL(p,52,0); /* last logon */
1938 SIVAL(p,56,0); /* last logoff */
1939 SSVALS(p,60,-1); /* bad pw counts */
1940 SSVALS(p,62,-1); /* num logons */
1941 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1942 strcpy(p2,"\\\\*");
1943 p2 = skip_string(p2,1);
1944 SSVAL(p,68,0); /* country code */
1946 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1947 strcpy(p2,"");
1948 p2 = skip_string(p2,1);
1950 SIVALS(p,74,-1); /* max storage */
1951 SSVAL(p,78,168); /* units per week */
1952 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1953 memset(p2,-1,21);
1954 SCVAL(p2,21,0); /* fix zero termination */
1955 p2 = skip_string(p2,1);
1957 SSVAL(p,84,0); /* code page */
1959 if (uLevel == 1 || uLevel == 2) {
1960 memset(p+22,' ',16); /* password */
1961 SIVALS(p,38,-1); /* password age */
1962 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1963 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1964 strcpy(p2,"\\\\%L\\HOMES");
1965 standard_sub_basic(p2);
1966 p2 = skip_string(p2,1);
1967 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1968 *p2++ = 0;
1969 SSVAL(p,52,0); /* flags */
1970 SIVAL(p,54,0); /* script_path */
1971 if (uLevel == 2) {
1972 SIVAL(p,60,0); /* auth_flags */
1973 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1974 strcpy(p2,"<Full Name>");
1975 p2 = skip_string(p2,1);
1976 SIVAL(p,68,0); /* urs_comment */
1977 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1978 strcpy(p2,"");
1979 p2 = skip_string(p2,1);
1980 SIVAL(p,76,0); /* workstations */
1981 SIVAL(p,80,0); /* last_logon */
1982 SIVAL(p,84,0); /* last_logoff */
1983 SIVALS(p,88,-1); /* acct_expires */
1984 SIVALS(p,92,-1); /* max_storage */
1985 SSVAL(p,96,168); /* units_per_week */
1986 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1987 memset(p2,-1,21);
1988 p2 += 21;
1989 SSVALS(p,102,-1); /* bad_pw_count */
1990 SSVALS(p,104,-1); /* num_logons */
1991 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1992 strcpy(p2,"\\\\%L");
1993 standard_sub_basic(p2);
1994 p2 = skip_string(p2,1);
1995 SSVAL(p,110,49); /* country_code */
1996 SSVAL(p,112,860); /* code page */
2001 *rdata_len = PTR_DIFF(p2,*rdata);
2003 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2005 return(True);
2009 /*******************************************************************
2010 get groups that a user is a member of
2011 ******************************************************************/
2012 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
2013 int mdrcnt,int mprcnt,
2014 char **rdata,char **rparam,
2015 int *rdata_len,int *rparam_len)
2017 char *str1 = param+2;
2018 char *str2 = skip_string(str1,1);
2019 char *UserName = skip_string(str2,1);
2020 char *p = skip_string(UserName,1);
2021 int uLevel = SVAL(p,0);
2022 char *p2;
2023 int count=0;
2025 *rparam_len = 8;
2026 *rparam = REALLOC(*rparam,*rparam_len);
2028 /* check it's a supported varient */
2029 if (strcmp(str1,"zWrLeh") != 0) return False;
2030 switch( uLevel ) {
2031 case 0: p2 = "B21"; break;
2032 default: return False;
2034 if (strcmp(p2,str2) != 0) return False;
2036 *rdata_len = mdrcnt + 1024;
2037 *rdata = REALLOC(*rdata,*rdata_len);
2039 SSVAL(*rparam,0,NERR_Success);
2040 SSVAL(*rparam,2,0); /* converter word */
2042 p = *rdata;
2044 /* XXXX we need a real SAM database some day */
2045 strcpy(p,"Users"); p += 21; count++;
2046 strcpy(p,"Domain Users"); p += 21; count++;
2047 strcpy(p,"Guests"); p += 21; count++;
2048 strcpy(p,"Domain Guests"); p += 21; count++;
2050 *rdata_len = PTR_DIFF(p,*rdata);
2052 SSVAL(*rparam,4,count); /* is this right?? */
2053 SSVAL(*rparam,6,count); /* is this right?? */
2055 return(True);
2059 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2060 int mdrcnt,int mprcnt,
2061 char **rdata,char **rparam,
2062 int *rdata_len,int *rparam_len)
2064 char *str1 = param+2;
2065 char *str2 = skip_string(str1,1);
2066 char *p = skip_string(str2,1);
2067 int uLevel;
2068 struct pack_desc desc;
2069 char* name;
2071 uLevel = SVAL(p,0);
2072 name = p + 2;
2074 bzero(&desc,sizeof(desc));
2076 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2078 /* check it's a supported varient */
2079 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2080 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2081 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2082 desc.base = *rdata;
2083 desc.buflen = mdrcnt;
2084 desc.subformat = NULL;
2085 desc.format = str2;
2089 if (init_package(&desc,1,0)) {
2090 PACKI(&desc,"W",0); /* code */
2091 PACKS(&desc,"B21",name); /* eff. name */
2092 PACKS(&desc,"B",""); /* pad */
2093 PACKI(&desc,"W",
2094 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2095 PACKI(&desc,"D",0); /* auth flags XXX */
2096 PACKI(&desc,"W",0); /* num logons */
2097 PACKI(&desc,"W",0); /* bad pw count */
2098 PACKI(&desc,"D",-1); /* last logon */
2099 PACKI(&desc,"D",-1); /* last logoff */
2100 PACKI(&desc,"D",-1); /* logoff time */
2101 PACKI(&desc,"D",-1); /* kickoff time */
2102 PACKI(&desc,"D",0); /* password age */
2103 PACKI(&desc,"D",0); /* password can change */
2104 PACKI(&desc,"D",-1); /* password must change */
2106 fstring mypath;
2107 strcpy(mypath,"\\\\");
2108 strcat(mypath,local_machine);
2109 strupper(mypath);
2110 PACKS(&desc,"z",mypath); /* computer */
2112 PACKS(&desc,"z",my_workgroup());/* domain */
2113 PACKS(&desc,"z",lp_logon_script()); /* script path */
2114 PACKI(&desc,"D",0); /* reserved */
2117 *rdata_len = desc.usedlen;
2118 *rparam_len = 6;
2119 *rparam = REALLOC(*rparam,*rparam_len);
2120 SSVALS(*rparam,0,desc.errcode);
2121 SSVAL(*rparam,2,0);
2122 SSVAL(*rparam,4,desc.neededlen);
2124 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2125 return(True);
2129 /****************************************************************************
2130 api_WAccessGetUserPerms
2131 ****************************************************************************/
2132 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2133 int mdrcnt,int mprcnt,
2134 char **rdata,char **rparam,
2135 int *rdata_len,int *rparam_len)
2137 char *str1 = param+2;
2138 char *str2 = skip_string(str1,1);
2139 char *user = skip_string(str2,1);
2140 char *resource = skip_string(user,1);
2142 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2144 /* check it's a supported varient */
2145 if (strcmp(str1,"zzh") != 0) return False;
2146 if (strcmp(str2,"") != 0) return False;
2148 *rparam_len = 6;
2149 *rparam = REALLOC(*rparam,*rparam_len);
2150 SSVALS(*rparam,0,0); /* errorcode */
2151 SSVAL(*rparam,2,0); /* converter word */
2152 SSVAL(*rparam,4,0x7f); /* permission flags */
2154 return(True);
2157 /****************************************************************************
2158 api_WPrintJobEnumerate
2159 ****************************************************************************/
2160 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2161 int mdrcnt,int mprcnt,
2162 char **rdata,char **rparam,
2163 int *rdata_len,int *rparam_len)
2165 char *str1 = param+2;
2166 char *str2 = skip_string(str1,1);
2167 char *p = skip_string(str2,1);
2168 int uJobId = SVAL(p,0);
2169 int uLevel,cbBuf;
2170 int count;
2171 int i;
2172 int snum;
2173 int job;
2174 struct pack_desc desc;
2175 print_queue_struct *queue=NULL;
2176 print_status_struct status;
2178 uLevel = SVAL(p,2);
2179 cbBuf = SVAL(p,4);
2181 bzero(&desc,sizeof(desc));
2182 bzero(&status,sizeof(status));
2184 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2186 /* check it's a supported varient */
2187 if (strcmp(str1,"WWrLh") != 0) return False;
2188 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2190 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2191 job = uJobId & 0xFF;
2193 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2195 count = get_printqueue(snum,cnum,&queue,&status);
2196 for (i = 0; i < count; i++) {
2197 if ((queue[i].job % 0xFF) == job) break;
2199 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2200 desc.base = *rdata;
2201 desc.buflen = mdrcnt;
2203 if (init_package(&desc,1,0)) {
2204 if (i < count) {
2205 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2206 *rdata_len = desc.usedlen;
2208 else {
2209 desc.errcode = NERR_JobNotFound;
2210 *rdata_len = 0;
2214 *rparam_len = 6;
2215 *rparam = REALLOC(*rparam,*rparam_len);
2216 SSVALS(*rparam,0,desc.errcode);
2217 SSVAL(*rparam,2,0);
2218 SSVAL(*rparam,4,desc.neededlen);
2220 if (queue) free(queue);
2222 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2223 return(True);
2226 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2227 int mdrcnt,int mprcnt,
2228 char **rdata,char **rparam,
2229 int *rdata_len,int *rparam_len)
2231 char *str1 = param+2;
2232 char *str2 = skip_string(str1,1);
2233 char *p = skip_string(str2,1);
2234 char* name = p;
2235 int uLevel,cbBuf;
2236 int count;
2237 int i, succnt=0;
2238 int snum;
2239 struct pack_desc desc;
2240 print_queue_struct *queue=NULL;
2241 print_status_struct status;
2243 bzero(&desc,sizeof(desc));
2244 bzero(&status,sizeof(status));
2246 p = skip_string(p,1);
2247 uLevel = SVAL(p,0);
2248 cbBuf = SVAL(p,2);
2250 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2252 /* check it's a supported varient */
2253 if (strcmp(str1,"zWrLeh") != 0) return False;
2254 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2255 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2257 snum = lp_servicenumber(name);
2258 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2259 int pnum = lp_servicenumber(PRINTERS_NAME);
2260 if (pnum >= 0) {
2261 lp_add_printer(name,pnum);
2262 snum = lp_servicenumber(name);
2266 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2268 count = get_printqueue(snum,cnum,&queue,&status);
2269 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2270 desc.base = *rdata;
2271 desc.buflen = mdrcnt;
2273 if (init_package(&desc,count,0)) {
2274 succnt = 0;
2275 for (i = 0; i < count; i++) {
2276 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2277 if (desc.errcode == NERR_Success) succnt = i+1;
2281 *rdata_len = desc.usedlen;
2283 *rparam_len = 8;
2284 *rparam = REALLOC(*rparam,*rparam_len);
2285 SSVALS(*rparam,0,desc.errcode);
2286 SSVAL(*rparam,2,0);
2287 SSVAL(*rparam,4,succnt);
2288 SSVAL(*rparam,6,count);
2290 if (queue) free(queue);
2292 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2293 return(True);
2296 static int check_printdest_info(struct pack_desc* desc,
2297 int uLevel, char* id)
2299 desc->subformat = NULL;
2300 switch( uLevel ) {
2301 case 0: desc->format = "B9"; break;
2302 case 1: desc->format = "B9B21WWzW"; break;
2303 case 2: desc->format = "z"; break;
2304 case 3: desc->format = "zzzWWzzzWW"; break;
2305 default: return False;
2307 if (strcmp(desc->format,id) != 0) return False;
2308 return True;
2311 static void fill_printdest_info(int cnum, int snum, int uLevel,
2312 struct pack_desc* desc)
2314 char buf[100];
2315 strcpy(buf,SERVICE(snum));
2316 strupper(buf);
2317 if (uLevel <= 1) {
2318 PACKS(desc,"B9",buf); /* szName */
2319 if (uLevel == 1) {
2320 PACKS(desc,"B21",""); /* szUserName */
2321 PACKI(desc,"W",0); /* uJobId */
2322 PACKI(desc,"W",0); /* fsStatus */
2323 PACKS(desc,"z",""); /* pszStatus */
2324 PACKI(desc,"W",0); /* time */
2327 if (uLevel == 2 || uLevel == 3) {
2328 PACKS(desc,"z",buf); /* pszPrinterName */
2329 if (uLevel == 3) {
2330 PACKS(desc,"z",""); /* pszUserName */
2331 PACKS(desc,"z",""); /* pszLogAddr */
2332 PACKI(desc,"W",0); /* uJobId */
2333 PACKI(desc,"W",0); /* fsStatus */
2334 PACKS(desc,"z",""); /* pszStatus */
2335 PACKS(desc,"z",""); /* pszComment */
2336 PACKS(desc,"z","NULL"); /* pszDrivers */
2337 PACKI(desc,"W",0); /* time */
2338 PACKI(desc,"W",0); /* pad1 */
2343 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2344 int mdrcnt,int mprcnt,
2345 char **rdata,char **rparam,
2346 int *rdata_len,int *rparam_len)
2348 char *str1 = param+2;
2349 char *str2 = skip_string(str1,1);
2350 char *p = skip_string(str2,1);
2351 char* PrinterName = p;
2352 int uLevel,cbBuf;
2353 struct pack_desc desc;
2354 int snum;
2356 bzero(&desc,sizeof(desc));
2358 p = skip_string(p,1);
2359 uLevel = SVAL(p,0);
2360 cbBuf = SVAL(p,2);
2362 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2364 /* check it's a supported varient */
2365 if (strcmp(str1,"zWrLh") != 0) return False;
2366 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2368 snum = lp_servicenumber(PrinterName);
2369 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2370 int pnum = lp_servicenumber(PRINTERS_NAME);
2371 if (pnum >= 0) {
2372 lp_add_printer(PrinterName,pnum);
2373 snum = lp_servicenumber(PrinterName);
2377 if (snum < 0) {
2378 *rdata_len = 0;
2379 desc.errcode = NERR_DestNotFound;
2380 desc.neededlen = 0;
2382 else {
2383 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2384 desc.base = *rdata;
2385 desc.buflen = mdrcnt;
2386 if (init_package(&desc,1,0)) {
2387 fill_printdest_info(cnum,snum,uLevel,&desc);
2389 *rdata_len = desc.usedlen;
2392 *rparam_len = 6;
2393 *rparam = REALLOC(*rparam,*rparam_len);
2394 SSVALS(*rparam,0,desc.errcode);
2395 SSVAL(*rparam,2,0);
2396 SSVAL(*rparam,4,desc.neededlen);
2398 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2399 return(True);
2402 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2403 int mdrcnt,int mprcnt,
2404 char **rdata,char **rparam,
2405 int *rdata_len,int *rparam_len)
2407 char *str1 = param+2;
2408 char *str2 = skip_string(str1,1);
2409 char *p = skip_string(str2,1);
2410 int uLevel,cbBuf;
2411 int queuecnt;
2412 int i, n, succnt=0;
2413 struct pack_desc desc;
2414 int services = lp_numservices();
2416 bzero(&desc,sizeof(desc));
2418 uLevel = SVAL(p,0);
2419 cbBuf = SVAL(p,2);
2421 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2423 /* check it's a supported varient */
2424 if (strcmp(str1,"WrLeh") != 0) return False;
2425 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2427 queuecnt = 0;
2428 for (i = 0; i < services; i++)
2429 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2430 queuecnt++;
2432 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2433 desc.base = *rdata;
2434 desc.buflen = mdrcnt;
2435 if (init_package(&desc,queuecnt,0)) {
2436 succnt = 0;
2437 n = 0;
2438 for (i = 0; i < services; i++) {
2439 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2440 fill_printdest_info(cnum,i,uLevel,&desc);
2441 n++;
2442 if (desc.errcode == NERR_Success) succnt = n;
2447 *rdata_len = desc.usedlen;
2449 *rparam_len = 8;
2450 *rparam = REALLOC(*rparam,*rparam_len);
2451 SSVALS(*rparam,0,desc.errcode);
2452 SSVAL(*rparam,2,0);
2453 SSVAL(*rparam,4,succnt);
2454 SSVAL(*rparam,6,queuecnt);
2456 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2457 return(True);
2460 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2461 int mdrcnt,int mprcnt,
2462 char **rdata,char **rparam,
2463 int *rdata_len,int *rparam_len)
2465 char *str1 = param+2;
2466 char *str2 = skip_string(str1,1);
2467 char *p = skip_string(str2,1);
2468 int uLevel,cbBuf;
2469 int succnt;
2470 struct pack_desc desc;
2472 bzero(&desc,sizeof(desc));
2474 uLevel = SVAL(p,0);
2475 cbBuf = SVAL(p,2);
2477 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2479 /* check it's a supported varient */
2480 if (strcmp(str1,"WrLeh") != 0) return False;
2481 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2483 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2484 desc.base = *rdata;
2485 desc.buflen = mdrcnt;
2486 if (init_package(&desc,1,0)) {
2487 PACKS(&desc,"B41","NULL");
2490 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2492 *rdata_len = desc.usedlen;
2494 *rparam_len = 8;
2495 *rparam = REALLOC(*rparam,*rparam_len);
2496 SSVALS(*rparam,0,desc.errcode);
2497 SSVAL(*rparam,2,0);
2498 SSVAL(*rparam,4,succnt);
2499 SSVAL(*rparam,6,1);
2501 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2502 return(True);
2505 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2506 int mdrcnt,int mprcnt,
2507 char **rdata,char **rparam,
2508 int *rdata_len,int *rparam_len)
2510 char *str1 = param+2;
2511 char *str2 = skip_string(str1,1);
2512 char *p = skip_string(str2,1);
2513 int uLevel,cbBuf;
2514 int succnt;
2515 struct pack_desc desc;
2517 bzero(&desc,sizeof(desc));
2519 uLevel = SVAL(p,0);
2520 cbBuf = SVAL(p,2);
2522 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2524 /* check it's a supported varient */
2525 if (strcmp(str1,"WrLeh") != 0) return False;
2526 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2528 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2529 desc.base = *rdata;
2530 desc.buflen = mdrcnt;
2531 desc.format = str2;
2532 if (init_package(&desc,1,0)) {
2533 PACKS(&desc,"B13","lpd");
2536 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2538 *rdata_len = desc.usedlen;
2540 *rparam_len = 8;
2541 *rparam = REALLOC(*rparam,*rparam_len);
2542 SSVALS(*rparam,0,desc.errcode);
2543 SSVAL(*rparam,2,0);
2544 SSVAL(*rparam,4,succnt);
2545 SSVAL(*rparam,6,1);
2547 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2548 return(True);
2551 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2552 int mdrcnt,int mprcnt,
2553 char **rdata,char **rparam,
2554 int *rdata_len,int *rparam_len)
2556 char *str1 = param+2;
2557 char *str2 = skip_string(str1,1);
2558 char *p = skip_string(str2,1);
2559 int uLevel,cbBuf;
2560 int succnt;
2561 struct pack_desc desc;
2563 bzero(&desc,sizeof(desc));
2565 uLevel = SVAL(p,0);
2566 cbBuf = SVAL(p,2);
2568 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2570 /* check it's a supported varient */
2571 if (strcmp(str1,"WrLeh") != 0) return False;
2572 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2574 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2575 bzero(&desc,sizeof(desc));
2576 desc.base = *rdata;
2577 desc.buflen = mdrcnt;
2578 desc.format = str2;
2579 if (init_package(&desc,1,0)) {
2580 PACKS(&desc,"B13","lp0");
2583 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2585 *rdata_len = desc.usedlen;
2587 *rparam_len = 8;
2588 *rparam = REALLOC(*rparam,*rparam_len);
2589 SSVALS(*rparam,0,desc.errcode);
2590 SSVAL(*rparam,2,0);
2591 SSVAL(*rparam,4,succnt);
2592 SSVAL(*rparam,6,1);
2594 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2595 return(True);
2598 /****************************************************************************
2599 the buffer was too small
2600 ****************************************************************************/
2601 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2602 int mdrcnt,int mprcnt,
2603 char **rdata,char **rparam,
2604 int *rdata_len,int *rparam_len)
2606 *rparam_len = MIN(*rparam_len,mprcnt);
2607 *rparam = REALLOC(*rparam,*rparam_len);
2609 *rdata_len = 0;
2611 SSVAL(*rparam,0,NERR_BufTooSmall);
2613 DEBUG(3,("Supplied buffer too small in API command\n"));
2615 return(True);
2619 /****************************************************************************
2620 the request is not supported
2621 ****************************************************************************/
2622 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2623 int mdrcnt,int mprcnt,
2624 char **rdata,char **rparam,
2625 int *rdata_len,int *rparam_len)
2627 *rparam_len = 4;
2628 *rparam = REALLOC(*rparam,*rparam_len);
2630 *rdata_len = 0;
2632 SSVAL(*rparam,0,NERR_notsupported);
2633 SSVAL(*rparam,2,0); /* converter word */
2635 DEBUG(3,("Unsupported API command\n"));
2637 return(True);
2643 struct
2645 char *name;
2646 int id;
2647 BOOL (*fn)();
2648 int flags;
2649 } api_commands[] = {
2650 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2651 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2652 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2653 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2654 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2655 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2656 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2657 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2658 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2659 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2660 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2661 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2662 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2663 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2664 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2665 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2666 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2667 {"NetServerEnum", 104, api_RNetServerEnum,0},
2668 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2669 {"SetUserPassword", 115, api_SetUserPassword,0},
2670 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2671 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2672 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2673 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2674 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2675 {NULL, -1, api_Unsupported,0}};
2678 /****************************************************************************
2679 handle remote api calls
2680 ****************************************************************************/
2681 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2682 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2684 int api_command = SVAL(params,0);
2685 char *rdata = NULL;
2686 char *rparam = NULL;
2687 int rdata_len = 0;
2688 int rparam_len = 0;
2689 BOOL reply=False;
2690 int i;
2692 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2693 api_command,params+2,skip_string(params+2,1),
2694 tdscnt,tpscnt,mdrcnt,mprcnt));
2696 for (i=0;api_commands[i].name;i++)
2697 if (api_commands[i].id == api_command && api_commands[i].fn)
2699 DEBUG(3,("Doing %s\n",api_commands[i].name));
2700 break;
2703 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2704 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2706 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2707 &rdata,&rparam,&rdata_len,&rparam_len);
2710 if (rdata_len > mdrcnt ||
2711 rparam_len > mprcnt)
2713 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2714 &rdata,&rparam,&rdata_len,&rparam_len);
2718 /* if we get False back then it's actually unsupported */
2719 if (!reply)
2720 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2721 &rdata,&rparam,&rdata_len,&rparam_len);
2725 /* now send the reply */
2726 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2728 if (rdata)
2729 free(rdata);
2730 if (rparam)
2731 free(rparam);
2733 return(-1);
2736 /****************************************************************************
2737 handle named pipe commands
2738 ****************************************************************************/
2739 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2740 uint16 *setup,char *data,char *params,
2741 int suwcnt,int tdscnt,int tpscnt,
2742 int msrcnt,int mdrcnt,int mprcnt)
2745 if (strequal(name,"LANMAN"))
2746 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2748 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2749 name,(int)setup[0],(int)setup[1]));
2751 return(0);
2755 /****************************************************************************
2756 reply to a SMBtrans
2757 ****************************************************************************/
2758 int reply_trans(char *inbuf,char *outbuf)
2760 fstring name;
2762 char *data=NULL,*params=NULL;
2763 uint16 *setup=NULL;
2765 int outsize = 0;
2766 int cnum = SVAL(inbuf,smb_tid);
2767 int uid = SVAL(inbuf,smb_uid);
2769 int tpscnt = SVAL(inbuf,smb_vwv0);
2770 int tdscnt = SVAL(inbuf,smb_vwv1);
2771 int mprcnt = SVAL(inbuf,smb_vwv2);
2772 int mdrcnt = SVAL(inbuf,smb_vwv3);
2773 int msrcnt = CVAL(inbuf,smb_vwv4);
2774 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2775 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2776 int pscnt = SVAL(inbuf,smb_vwv9);
2777 int psoff = SVAL(inbuf,smb_vwv10);
2778 int dscnt = SVAL(inbuf,smb_vwv11);
2779 int dsoff = SVAL(inbuf,smb_vwv12);
2780 int suwcnt = CVAL(inbuf,smb_vwv13);
2782 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2784 if (tdscnt)
2786 data = (char *)malloc(tdscnt);
2787 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2789 if (tpscnt)
2791 params = (char *)malloc(tpscnt);
2792 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2795 if (suwcnt)
2797 int i;
2798 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2799 for (i=0;i<suwcnt;i++)
2800 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2804 if (pscnt < tpscnt || dscnt < tdscnt)
2806 /* We need to send an interim response then receive the rest
2807 of the parameter/data bytes */
2808 outsize = set_message(outbuf,0,0,True);
2809 show_msg(outbuf);
2810 send_smb(Client,outbuf);
2813 /* receive the rest of the trans packet */
2814 while (pscnt < tpscnt || dscnt < tdscnt)
2816 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2818 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
2819 CVAL(inbuf, smb_com) != SMBtrans)
2821 DEBUG(2,("Invalid secondary trans2 packet\n"));
2822 if (params) free(params);
2823 if (data) free(data);
2824 if (setup) free(setup);
2825 return(ERROR(ERRSRV,ERRerror));
2828 show_msg(inbuf);
2830 tpscnt = SVAL(inbuf,smb_vwv0);
2831 tdscnt = SVAL(inbuf,smb_vwv1);
2833 pcnt = SVAL(inbuf,smb_vwv2);
2834 poff = SVAL(inbuf,smb_vwv3);
2835 pdisp = SVAL(inbuf,smb_vwv4);
2837 dcnt = SVAL(inbuf,smb_vwv5);
2838 doff = SVAL(inbuf,smb_vwv6);
2839 ddisp = SVAL(inbuf,smb_vwv7);
2841 pscnt += pcnt;
2842 dscnt += dcnt;
2844 if (pcnt)
2845 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2846 if (dcnt)
2847 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2851 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2854 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2855 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2856 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2859 if (data) free(data);
2860 if (params) free(params);
2861 if (setup) free(setup);
2863 if (close_on_completion)
2864 close_cnum(cnum,uid);
2866 if (one_way)
2867 return(-1);
2869 if (outsize == 0)
2870 return(ERROR(ERRSRV,ERRnosupport));
2872 return(outsize);