2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1997
8 Copyright (C) John H Terpstra 1995-1997
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern int DEBUGLEVEL;
38 extern files_struct Files[];
39 extern connection_struct Connections[];
41 extern fstring local_machine;
42 extern fstring myworkgroup;
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
53 #define ERROR_MORE_DATA 234
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
65 extern int oplock_sock;
66 extern int smb_read_error;
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69 int mdrcnt,int mprcnt,
70 char **rdata,char **rparam,
71 int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73 int mdrcnt,int mprcnt,
74 char **rdata,char **rparam,
75 int *rdata_len,int *rparam_len);
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
83 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(buf,src,sizeof(buf)/2);
86 string_sub(buf,"%S",lp_servicename(snum));
87 standard_sub(cnum,buf);
95 static int CopyAndAdvance(char** dst, char* src, int* n)
98 if (!src || !dst || !n || !(*dst)) return(0);
100 l = strlen(*dst) + 1;
106 static int StrlenExpanded(int cnum, int snum, char* s)
110 StrnCpy(buf,s,sizeof(buf)/2);
111 string_sub(buf,"%S",lp_servicename(snum));
112 standard_sub(cnum,buf);
113 return strlen(buf) + 1;
116 static char* Expand(int cnum, int snum, char* s)
119 if (!s) return(NULL);
120 StrnCpy(buf,s,sizeof(buf)/2);
121 string_sub(buf,"%S",lp_servicename(snum));
122 standard_sub(cnum,buf);
126 /*******************************************************************
127 check a API string for validity when we only need to check the prefix
128 ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
131 return(strncmp(str,prefix,strlen(prefix)) == 0);
135 /****************************************************************************
137 ****************************************************************************/
138 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
139 int ldata,int lparam,int lsetup)
142 int this_ldata,this_lparam;
143 int tot_data=0,tot_param=0;
146 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
147 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
149 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
150 /* if you don't want Net Monitor to decode your packets, do this!!! */
151 align = ((this_lparam+1)%4);
153 align = (this_lparam%4);
156 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
158 memcpy(smb_buf(outbuf),param,this_lparam);
160 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
162 SSVAL(outbuf,smb_vwv0,lparam);
163 SSVAL(outbuf,smb_vwv1,ldata);
164 SSVAL(outbuf,smb_vwv3,this_lparam);
165 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
166 SSVAL(outbuf,smb_vwv5,0);
167 SSVAL(outbuf,smb_vwv6,this_ldata);
168 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
169 SSVAL(outbuf,smb_vwv8,0);
170 SSVAL(outbuf,smb_vwv9,lsetup);
171 for (i=0;i<lsetup;i++)
172 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
175 send_smb(Client,outbuf);
177 tot_data = this_ldata;
178 tot_param = this_lparam;
180 while (tot_data < ldata || tot_param < lparam)
182 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
183 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
185 align = (this_lparam%4);
187 set_message(outbuf,10,this_ldata+this_lparam+align,False);
189 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
191 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
193 SSVAL(outbuf,smb_vwv3,this_lparam);
194 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
195 SSVAL(outbuf,smb_vwv5,tot_param);
196 SSVAL(outbuf,smb_vwv6,this_ldata);
197 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
198 SSVAL(outbuf,smb_vwv8,tot_data);
199 SSVAL(outbuf,smb_vwv9,0);
202 send_smb(Client,outbuf);
204 tot_data += this_ldata;
205 tot_param += this_lparam;
210 char* format; /* formatstring for structure */
211 char* subformat; /* subformat for structure */
212 char* base; /* baseaddress of buffer */
213 int buflen; /* remaining size for fixed part; on init: length of base */
214 int subcount; /* count of substructures */
215 char* structbuf; /* pointer into buffer for remaining fixed part */
216 int stringlen; /* remaining size for variable part */
217 char* stringbuf; /* pointer into buffer for remaining variable part */
218 int neededlen; /* total needed size */
219 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
220 char* curpos; /* current position; pointer into format or subformat */
224 static int get_counter(char** p)
227 if (!p || !(*p)) return(1);
228 if (!isdigit(**p)) return 1;
232 n = 10 * n + (i - '0');
239 static int getlen(char* p)
245 case 'W': /* word (2 byte) */
248 case 'N': /* count of substructures (word) at end */
251 case 'D': /* double word (4 byte) */
252 case 'z': /* offset to zero terminated string (4 byte) */
253 case 'l': /* offset to user data (4 byte) */
256 case 'b': /* offset to data (with counter) (4 byte) */
260 case 'B': /* byte (with optional counter) */
261 n += get_counter(&p);
268 static BOOL init_package(struct pack_desc* p, int count, int subcount)
273 if (!p->format || !p->base) return(False);
275 i = count * getlen(p->format);
276 if (p->subformat) i += subcount * getlen(p->subformat);
277 p->structbuf = p->base;
281 p->curpos = p->format;
284 p->errcode = NERR_BufTooSmall;
287 p->errcode = NERR_Success;
290 p->stringbuf = p->base + i;
292 return(p->errcode == NERR_Success);
296 static int package(struct pack_desc* p, ...)
299 static int package(va_alist)
305 int needed=0, stringneeded;
307 int is_string=0, stringused;
314 p = va_arg(args,struct pack_desc *);
319 p->curpos = p->format;
321 p->curpos = p->subformat;
326 str = va_arg(args,char*);
327 if (strncmp(str,p->curpos,strlen(str)) != 0) {
328 DEBUG(2,("type error in package: %s instead of %*s\n",str,
329 strlen(str),p->curpos));
339 if (!p->curpos) return(0);
341 switch( *p->curpos++ ) {
342 case 'W': /* word (2 byte) */
344 temp = va_arg(args,int);
345 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
347 case 'N': /* count of substructures (word) at end */
349 p->subcount = va_arg(args,int);
350 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
352 case 'D': /* double word (4 byte) */
354 temp = va_arg(args,int);
355 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
357 case 'B': /* byte (with optional counter) */
358 needed = get_counter(&p->curpos);
360 char *s = va_arg(args,char*);
361 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
364 case 'z': /* offset to zero terminated string (4 byte) */
365 str = va_arg(args,char*);
366 stringneeded = (str ? strlen(str)+1 : 0);
369 case 'l': /* offset to user data (4 byte) */
370 str = va_arg(args,char*);
371 stringneeded = va_arg(args,int);
374 case 'b': /* offset to data (with counter) (4 byte) */
375 str = va_arg(args,char*);
376 stringneeded = get_counter(&p->curpos);
381 if (stringneeded >= 0) {
383 if (p->buflen >= needed) {
384 stringused = stringneeded;
385 if (stringused > p->stringlen) {
386 stringused = (is_string ? p->stringlen : 0);
387 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
390 SIVAL(p->structbuf,0,0);
392 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
393 memcpy(p->stringbuf,str?str:"",stringused);
394 if (is_string) p->stringbuf[stringused-1] = '\0';
395 p->stringbuf += stringused;
396 p->stringlen -= stringused;
397 p->usedlen += stringused;
400 p->neededlen += stringneeded;
402 p->neededlen += needed;
403 if (p->buflen >= needed) {
404 p->structbuf += needed;
406 p->usedlen += needed;
409 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
415 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
416 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
418 #define PACK(desc,t,v) package(desc,v)
419 #define PACKl(desc,t,v,l) package(desc,v,l)
422 static void PACKI(struct pack_desc* desc,char *t,int v)
427 static void PACKS(struct pack_desc* desc,char *t,char *v)
433 /****************************************************************************
435 ****************************************************************************/
437 static void PackDriverData(struct pack_desc* desc)
439 char drivdata[4+4+32];
440 SIVAL(drivdata,0,sizeof drivdata); /* cb */
441 SIVAL(drivdata,4,1000); /* lVersion */
442 memset(drivdata+8,0,32); /* szDeviceName */
443 strcpy(drivdata+8,"NULL");
444 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
447 static int check_printq_info(struct pack_desc* desc,
448 int uLevel, char *id1, char *id2)
450 desc->subformat = NULL;
453 desc->format = "B13";
456 desc->format = "B13BWWWzzzzzWW";
459 desc->format = "B13BWWWzzzzzWN";
460 desc->subformat = "WB21BB16B10zWWzDDz";
463 desc->format = "zWWWWzzzzWWzzl";
466 desc->format = "zWWWWzzzzWNzzl";
467 desc->subformat = "WWzWWDDzz";
473 desc->format = "WzzzzzzzzN";
474 desc->subformat = "z";
476 default: return False;
478 if (strcmp(desc->format,id1) != 0) return False;
479 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
483 static void fill_printjob_info(int cnum, int snum, int uLevel,
484 struct pack_desc* desc,
485 print_queue_struct* queue, int n)
487 time_t t = queue->time;
489 /* the client expects localtime */
492 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
494 PACKS(desc,"B21",queue->user); /* szUserName */
495 PACKS(desc,"B",""); /* pad */
496 PACKS(desc,"B16",""); /* szNotifyName */
497 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
498 PACKS(desc,"z",""); /* pszParms */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKS(desc,"z",""); /* pszStatus */
502 PACKI(desc,"D",t); /* ulSubmitted */
503 PACKI(desc,"D",queue->size); /* ulSize */
504 PACKS(desc,"z",queue->file); /* pszComment */
506 if (uLevel == 2 || uLevel == 3) {
507 PACKI(desc,"W",queue->priority); /* uPriority */
508 PACKS(desc,"z",queue->user); /* pszUserName */
509 PACKI(desc,"W",n+1); /* uPosition */
510 PACKI(desc,"W",queue->status); /* fsStatus */
511 PACKI(desc,"D",t); /* ulSubmitted */
512 PACKI(desc,"D",queue->size); /* ulSize */
513 PACKS(desc,"z","Samba"); /* pszComment */
514 PACKS(desc,"z",queue->file); /* pszDocument */
516 PACKS(desc,"z",""); /* pszNotifyName */
517 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
518 PACKS(desc,"z",""); /* pszParms */
519 PACKS(desc,"z",""); /* pszStatus */
520 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
521 PACKS(desc,"z","lpd"); /* pszQProcName */
522 PACKS(desc,"z",""); /* pszQProcParms */
523 PACKS(desc,"z","NULL"); /* pszDriverName */
524 PackDriverData(desc); /* pDriverData */
525 PACKS(desc,"z",""); /* pszPrinterName */
530 static void fill_printq_info(int cnum, int snum, int uLevel,
531 struct pack_desc* desc,
532 int count, print_queue_struct* queue,
533 print_status_struct* status)
538 PACKS(desc,"B13",SERVICE(snum));
543 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
547 if (uLevel == 1 || uLevel == 2) {
548 PACKS(desc,"B",""); /* alignment */
549 PACKI(desc,"W",5); /* priority */
550 PACKI(desc,"W",0); /* start time */
551 PACKI(desc,"W",0); /* until time */
552 PACKS(desc,"z",""); /* pSepFile */
553 PACKS(desc,"z","lpd"); /* pPrProc */
554 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
555 PACKS(desc,"z",""); /* pParms */
557 PACKS(desc,"z","UNKNOWN PRINTER");
558 PACKI(desc,"W",LPSTAT_ERROR);
560 else if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
562 PACKI(desc,"W",LPSTAT_OK); /* status */
564 PACKS(desc,"z",status->message);
565 PACKI(desc,"W",status->status); /* status */
567 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
569 if (uLevel == 3 || uLevel == 4) {
570 PACKI(desc,"W",5); /* uPriority */
571 PACKI(desc,"W",0); /* uStarttime */
572 PACKI(desc,"W",0); /* uUntiltime */
573 PACKI(desc,"W",5); /* pad1 */
574 PACKS(desc,"z",""); /* pszSepFile */
575 PACKS(desc,"z","WinPrint"); /* pszPrProc */
576 PACKS(desc,"z",""); /* pszParms */
577 if (!status || !status->message[0]) {
578 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
579 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
581 PACKS(desc,"z",status->message); /* pszComment */
582 PACKI(desc,"W",status->status); /* fsStatus */
584 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
585 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
586 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
587 PackDriverData(desc); /* pDriverData */
589 if (uLevel == 2 || uLevel == 4) {
591 for (i=0;i<count;i++)
592 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
597 pstring tok,driver,datafile,langmon,helpfile,datatype;
602 strcpy(fname,lp_driverfile());
605 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
606 desc->errcode=NERR_notsupported;
610 p=(char *)malloc(8192*sizeof(char));
611 bzero(p, 8192*sizeof(char));
614 /* lookup the long printer driver name in the file description */
615 while (f && !feof(f) && !ok)
617 p = q; /* reset string pointer */
620 if (next_token(&p,tok,":") &&
621 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
626 /* driver file name */
627 if (ok && !next_token(&p,driver,":")) ok = 0;
629 if (ok && !next_token(&p,datafile,":")) ok = 0;
631 * for the next tokens - which may be empty - I have to check for empty
632 * tokens first because the next_token function will skip all empty
640 } else if (!next_token(&p,helpfile,":")) ok = 0;
644 /* language monitor */
648 } else if (!next_token(&p,langmon,":")) ok = 0;
651 /* default data type */
652 if (ok && !next_token(&p,datatype,":")) ok = 0;
655 PACKI(desc,"W",0x0400); /* don't know */
656 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
657 PACKS(desc,"z",driver); /* Driverfile Name */
658 PACKS(desc,"z",datafile); /* Datafile name */
659 PACKS(desc,"z",langmon); /* language monitor */
660 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
661 PACKS(desc,"z",datatype); /* default data type */
662 PACKS(desc,"z",helpfile); /* helpfile name */
663 PACKS(desc,"z",driver); /* driver name */
664 DEBUG(3,("Driver:%s:\n",driver));
665 DEBUG(3,("Data File:%s:\n",datafile));
666 DEBUG(3,("Language Monitor:%s:\n",langmon));
667 DEBUG(3,("Data Type:%s:\n",datatype));
668 DEBUG(3,("Help File:%s:\n",helpfile));
669 PACKI(desc,"N",count); /* number of files to copy */
670 for (i=0;i<count;i++)
672 /* no need to check return value here - it was already tested in
673 * get_printerdrivernumber
675 next_token(&p,tok,",");
676 PACKS(desc,"z",tok); /* driver files to copy */
677 DEBUG(3,("file:%s:\n",tok));
680 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
681 SERVICE(snum),count));
683 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
684 desc->errcode=NERR_notsupported;
690 /* This function returns the number of files for a given driver */
691 int get_printerdrivernumber(int snum)
699 strcpy(fname,lp_driverfile());
701 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
704 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
708 p=(char *)malloc(8192*sizeof(char));
709 q=p; /* need it to free memory because p change ! */
711 /* lookup the long printer driver name in the file description */
712 while (!feof(f) && !ok)
714 p = q; /* reset string pointer */
716 if (next_token(&p,tok,":") &&
717 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
726 if (*p++ == ':') i--;
731 /* count the number of files */
732 while (next_token(&p,tok,","))
740 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
741 int mdrcnt,int mprcnt,
742 char **rdata,char **rparam,
743 int *rdata_len,int *rparam_len)
745 char *str1 = param+2;
746 char *str2 = skip_string(str1,1);
747 char *p = skip_string(str2,1);
753 struct pack_desc desc;
754 print_queue_struct *queue=NULL;
755 print_status_struct status;
757 bzero(&status,sizeof(status));
758 bzero(&desc,sizeof(desc));
760 p = skip_string(p,1);
765 /* remove any trailing username */
766 if ((p = strchr(QueueName,'%'))) *p = 0;
768 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
770 /* check it's a supported varient */
771 if (!prefix_ok(str1,"zWrLh")) return False;
772 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
774 snum = lp_servicenumber(QueueName);
775 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
776 int pnum = lp_servicenumber(PRINTERS_NAME);
778 lp_add_printer(QueueName,pnum);
779 snum = lp_servicenumber(QueueName);
783 if (snum < 0 || !VALID_SNUM(snum)) return(False);
787 count = get_printerdrivernumber(snum);
788 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
791 count = get_printqueue(snum,cnum,&queue,&status);
793 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
795 desc.buflen = mdrcnt;
796 if (init_package(&desc,1,count)) {
797 desc.subcount = count;
798 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
801 *rdata_len = desc.usedlen;
804 *rparam = REALLOC(*rparam,*rparam_len);
805 SSVALS(*rparam,0,desc.errcode);
807 SSVAL(*rparam,4,desc.neededlen);
809 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
811 if (queue) free(queue);
817 /****************************************************************************
818 view list of all print jobs on all queues
819 ****************************************************************************/
820 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
821 int mdrcnt, int mprcnt,
822 char **rdata, char** rparam,
823 int *rdata_len, int *rparam_len)
825 char *param_format = param+2;
826 char *output_format1 = skip_string(param_format,1);
827 char *p = skip_string(output_format1,1);
828 int uLevel = SVAL(p,0);
829 char *output_format2 = p + 4;
830 int services = lp_numservices();
832 struct pack_desc desc;
833 print_queue_struct **queue = NULL;
834 print_status_struct *status = NULL;
835 int* subcntarr = NULL;
836 int queuecnt, subcnt=0, succnt=0;
838 bzero(&desc,sizeof(desc));
840 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
842 if (!prefix_ok(param_format,"WrLeh")) return False;
843 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
846 for (i = 0; i < services; i++)
847 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
850 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
851 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
852 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
853 memset(status,0,queuecnt*sizeof(print_status_struct));
854 subcntarr = (int*)malloc(queuecnt*sizeof(int));
857 for (i = 0; i < services; i++)
858 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
859 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
860 subcnt += subcntarr[n];
864 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
866 desc.buflen = mdrcnt;
868 if (init_package(&desc,queuecnt,subcnt)) {
871 for (i = 0; i < services; i++)
872 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
873 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
875 if (desc.errcode == NERR_Success) succnt = n;
879 if (subcntarr) free(subcntarr);
881 *rdata_len = desc.usedlen;
883 *rparam = REALLOC(*rparam,*rparam_len);
884 SSVALS(*rparam,0,desc.errcode);
886 SSVAL(*rparam,4,succnt);
887 SSVAL(*rparam,6,queuecnt);
889 for (i = 0; i < queuecnt; i++) {
890 if (queue && queue[i]) free(queue[i]);
893 if (queue) free(queue);
894 if (status) free(status);
899 /****************************************************************************
900 get info level for a server list query
901 ****************************************************************************/
902 static BOOL check_server_info(int uLevel, char* id)
906 if (strcmp(id,"B16") != 0) return False;
909 if (strcmp(id,"B16BBDz") != 0) return False;
917 struct srv_info_struct
927 /*******************************************************************
928 get server info lists from the files saved by nmbd. Return the
930 ******************************************************************/
931 static int get_server_info(uint32 servertype,
932 struct srv_info_struct **servers,
940 BOOL local_list_only;
942 pstrcpy(fname,lp_lockdir());
943 trim_string(fname,NULL,"/");
945 strcat(fname,SERVER_LIST);
947 f = fopen(fname,"r");
950 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
954 /* request for everything is code for request all servers */
955 if (servertype == SV_TYPE_ALL)
956 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
958 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
960 DEBUG(4,("Servertype search: %8x\n",servertype));
965 struct srv_info_struct *s;
970 fgets(line,sizeof(line)-1,f);
971 if (!*line) continue;
973 if (count == alloced) {
975 (*servers) = (struct srv_info_struct *)
976 Realloc(*servers,sizeof(**servers)*alloced);
977 if (!(*servers)) return(0);
978 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
980 s = &(*servers)[count];
982 if (!next_token(&ptr,s->name , NULL)) continue;
983 if (!next_token(&ptr,stype , NULL)) continue;
984 if (!next_token(&ptr,s->comment, NULL)) continue;
985 if (!next_token(&ptr,s->domain , NULL)) {
986 /* this allows us to cope with an old nmbd */
987 strcpy(s->domain,myworkgroup);
990 if (sscanf(stype,"%X",&s->type) != 1) {
991 DEBUG(4,("r:host file "));
995 /* Filter the servers/domains we return based on what was asked for. */
997 /* Check to see if we are being asked for a local list only. */
998 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
999 DEBUG(4,("r: local list only"));
1003 /* doesn't match up: don't want it */
1004 if (!(servertype & s->type)) {
1005 DEBUG(4,("r:serv type "));
1009 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1010 (s->type & SV_TYPE_DOMAIN_ENUM))
1012 DEBUG(4,("s: dom mismatch "));
1016 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1021 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1022 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1026 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1027 s->name, s->type, s->comment, s->domain));
1029 s->server_added = True;
1034 DEBUG(4,("%20s %8x %25s %15s\n",
1035 s->name, s->type, s->comment, s->domain));
1044 /*******************************************************************
1045 fill in a server info structure
1046 ******************************************************************/
1047 static int fill_srv_info(struct srv_info_struct *service,
1048 int uLevel, char **buf, int *buflen,
1049 char **stringbuf, int *stringspace, char *baseaddr)
1058 case 0: struct_len = 16; break;
1059 case 1: struct_len = 26; break;
1069 len = strlen(service->comment)+1;
1073 if (buflen) *buflen = struct_len;
1074 if (stringspace) *stringspace = len;
1075 return struct_len + len;
1080 if (*buflen < struct_len) return -1;
1088 p2 = p + struct_len;
1089 l2 = *buflen - struct_len;
1091 if (!baseaddr) baseaddr = p;
1096 StrnCpy(p,service->name,15);
1100 StrnCpy(p,service->name,15);
1101 SIVAL(p,18,service->type);
1102 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1103 len += CopyAndAdvance(&p2,service->comment,&l2);
1109 *buf = p + struct_len;
1110 *buflen -= struct_len;
1123 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1125 return(strcmp(s1->name,s2->name));
1128 /****************************************************************************
1129 view list of servers available (or possibly domains). The info is
1130 extracted from lists saved by nmbd on the local host
1131 ****************************************************************************/
1132 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1133 int mdrcnt, int mprcnt, char **rdata,
1134 char **rparam, int *rdata_len, int *rparam_len)
1136 char *str1 = param+2;
1137 char *str2 = skip_string(str1,1);
1138 char *p = skip_string(str2,1);
1139 int uLevel = SVAL(p,0);
1140 int buf_len = SVAL(p,2);
1141 uint32 servertype = IVAL(p,4);
1143 int data_len, fixed_len, string_len;
1145 struct srv_info_struct *servers=NULL;
1146 int counted=0,total=0;
1149 BOOL domain_request;
1152 /* If someone sets all the bits they don't really mean to set
1153 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1156 if (servertype == SV_TYPE_ALL)
1157 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1159 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1160 any other bit (they may just set this bit on it's own) they
1161 want all the locally seen servers. However this bit can be
1162 set on its own so set the requested servers to be
1163 ALL - DOMAIN_ENUM. */
1165 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1166 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1168 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1169 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1173 if (!prefix_ok(str1,"WrLehD")) return False;
1174 if (!check_server_info(uLevel,str2)) return False;
1176 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1177 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1178 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1180 if (strcmp(str1, "WrLehDz") == 0) {
1181 StrnCpy(domain, p, sizeof(fstring)-1);
1183 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1186 if (lp_browse_list())
1187 total = get_server_info(servertype,&servers,domain);
1189 data_len = fixed_len = string_len = 0;
1192 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1195 char *lastname=NULL;
1197 for (i=0;i<total;i++)
1199 struct srv_info_struct *s = &servers[i];
1200 if (lastname && strequal(lastname,s->name)) continue;
1202 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1203 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1204 s->name, s->type, s->comment, s->domain));
1206 if (data_len <= buf_len) {
1209 string_len += s_len;
1216 *rdata_len = fixed_len + string_len;
1217 *rdata = REALLOC(*rdata,*rdata_len);
1218 bzero(*rdata,*rdata_len);
1220 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1226 char *lastname=NULL;
1227 int count2 = counted;
1228 for (i = 0; i < total && count2;i++)
1230 struct srv_info_struct *s = &servers[i];
1231 if (lastname && strequal(lastname,s->name)) continue;
1233 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1234 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1235 s->name, s->type, s->comment, s->domain));
1241 *rparam = REALLOC(*rparam,*rparam_len);
1242 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1244 SSVAL(*rparam,4,counted);
1245 SSVAL(*rparam,6,counted+missed);
1247 if (servers) free(servers);
1249 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1250 domain,uLevel,counted,counted+missed));
1256 /****************************************************************************
1257 get info about a share
1258 ****************************************************************************/
1259 static BOOL check_share_info(int uLevel, char* id)
1263 if (strcmp(id,"B13") != 0) return False;
1266 if (strcmp(id,"B13BWz") != 0) return False;
1269 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1272 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1274 default: return False;
1279 static int fill_share_info(int cnum, int snum, int uLevel,
1280 char** buf, int* buflen,
1281 char** stringbuf, int* stringspace, char* baseaddr)
1290 case 0: struct_len = 13; break;
1291 case 1: struct_len = 20; break;
1292 case 2: struct_len = 40; break;
1293 case 91: struct_len = 68; break;
1301 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1302 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1303 if (buflen) *buflen = struct_len;
1304 if (stringspace) *stringspace = len;
1305 return struct_len + len;
1310 if ((*buflen) < struct_len) return -1;
1318 p2 = p + struct_len;
1319 l2 = (*buflen) - struct_len;
1321 if (!baseaddr) baseaddr = p;
1323 StrnCpy(p,lp_servicename(snum),13);
1329 type = STYPE_DISKTREE;
1330 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1331 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1332 SSVAL(p,14,type); /* device type */
1333 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1334 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1339 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1340 SSVALS(p,22,-1); /* max uses */
1341 SSVAL(p,24,1); /* current uses */
1342 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1343 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1344 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1349 memset(p+40,0,SHPWLEN+2);
1361 (*buf) = p + struct_len;
1362 (*buflen) -= struct_len;
1364 (*stringspace) = l2;
1374 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1375 int mdrcnt,int mprcnt,
1376 char **rdata,char **rparam,
1377 int *rdata_len,int *rparam_len)
1379 char *str1 = param+2;
1380 char *str2 = skip_string(str1,1);
1381 char *netname = skip_string(str2,1);
1382 char *p = skip_string(netname,1);
1383 int uLevel = SVAL(p,0);
1384 int snum = find_service(netname);
1386 if (snum < 0) return False;
1388 /* check it's a supported varient */
1389 if (!prefix_ok(str1,"zWrLh")) return False;
1390 if (!check_share_info(uLevel,str2)) return False;
1392 *rdata = REALLOC(*rdata,mdrcnt);
1394 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1395 if (*rdata_len < 0) return False;
1398 *rparam = REALLOC(*rparam,*rparam_len);
1399 SSVAL(*rparam,0,NERR_Success);
1400 SSVAL(*rparam,2,0); /* converter word */
1401 SSVAL(*rparam,4,*rdata_len);
1406 /****************************************************************************
1407 view list of shares available
1408 ****************************************************************************/
1409 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1410 int mdrcnt,int mprcnt,
1411 char **rdata,char **rparam,
1412 int *rdata_len,int *rparam_len)
1414 char *str1 = param+2;
1415 char *str2 = skip_string(str1,1);
1416 char *p = skip_string(str2,1);
1417 int uLevel = SVAL(p,0);
1418 int buf_len = SVAL(p,2);
1420 int count=lp_numservices();
1421 int total=0,counted=0;
1423 int data_len, fixed_len, string_len;
1426 if (!prefix_ok(str1,"WrLeh")) return False;
1427 if (!check_share_info(uLevel,str2)) return False;
1429 data_len = fixed_len = string_len = 0;
1430 for (i=0;i<count;i++)
1431 if (lp_browseable(i) && lp_snum_ok(i))
1434 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1435 if (data_len <= buf_len)
1439 string_len += s_len;
1442 *rdata_len = fixed_len + string_len;
1443 *rdata = REALLOC(*rdata,*rdata_len);
1444 memset(*rdata,0,*rdata_len);
1446 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1450 for (i = 0; i < count;i++)
1451 if (lp_browseable(i) && lp_snum_ok(i))
1452 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1456 *rparam = REALLOC(*rparam,*rparam_len);
1457 SSVAL(*rparam,0,NERR_Success);
1459 SSVAL(*rparam,4,counted);
1460 SSVAL(*rparam,6,total);
1462 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1463 counted,total,uLevel,
1464 buf_len,*rdata_len,mdrcnt));
1470 /****************************************************************************
1471 get the time of day info
1472 ****************************************************************************/
1473 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1474 int mdrcnt,int mprcnt,
1475 char **rdata,char **rparam,
1476 int *rdata_len,int *rparam_len)
1480 *rparam = REALLOC(*rparam,*rparam_len);
1483 *rdata = REALLOC(*rdata,*rdata_len);
1485 SSVAL(*rparam,0,NERR_Success);
1486 SSVAL(*rparam,2,0); /* converter word */
1492 time_t unixdate = time(NULL);
1494 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1495 by NT in a "net time" operation,
1496 it seems to ignore the one below */
1498 /* the client expects to get localtime, not GMT, in this bit
1499 (I think, this needs testing) */
1500 t = LocalTime(&unixdate);
1502 SIVAL(p,4,0); /* msecs ? */
1503 CVAL(p,8) = t->tm_hour;
1504 CVAL(p,9) = t->tm_min;
1505 CVAL(p,10) = t->tm_sec;
1506 CVAL(p,11) = 0; /* hundredths of seconds */
1507 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1508 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1509 CVAL(p,16) = t->tm_mday;
1510 CVAL(p,17) = t->tm_mon + 1;
1511 SSVAL(p,18,1900+t->tm_year);
1512 CVAL(p,20) = t->tm_wday;
1519 /****************************************************************************
1520 set the user password
1521 ****************************************************************************/
1522 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1523 int mdrcnt,int mprcnt,
1524 char **rdata,char **rparam,
1525 int *rdata_len,int *rparam_len)
1527 char *p = skip_string(param+2,2);
1529 fstring pass1,pass2;
1533 p = skip_string(p,1);
1535 StrnCpy(pass1,p,16);
1536 StrnCpy(pass2,p+16,16);
1539 *rparam = REALLOC(*rparam,*rparam_len);
1543 SSVAL(*rparam,0,NERR_badpass);
1544 SSVAL(*rparam,2,0); /* converter word */
1546 DEBUG(3,("Set password for <%s>\n",user));
1548 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1549 chgpasswd(user,pass1,pass2))
1551 SSVAL(*rparam,0,NERR_Success);
1554 bzero(pass1,sizeof(fstring));
1555 bzero(pass2,sizeof(fstring));
1560 /****************************************************************************
1563 ****************************************************************************/
1564 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1565 int mdrcnt,int mprcnt,
1566 char **rdata,char **rparam,
1567 int *rdata_len,int *rparam_len)
1569 int function = SVAL(param,0);
1570 char *str1 = param+2;
1571 char *str2 = skip_string(str1,1);
1572 char *p = skip_string(str2,1);
1576 printjob_decode(SVAL(p,0), &snum, &jobid);
1578 /* check it's a supported varient */
1579 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1583 *rparam = REALLOC(*rparam,*rparam_len);
1587 SSVAL(*rparam,0,NERR_Success);
1589 if (snum >= 0 && VALID_SNUM(snum))
1591 print_queue_struct *queue=NULL;
1593 count = get_printqueue(snum,cnum,&queue,NULL);
1595 for (i=0;i<count;i++)
1596 if ((queue[i].job&0xFF) == jobid)
1599 case 81: /* delete */
1600 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1601 del_printqueue(cnum,snum,queue[i].job);
1603 case 82: /* pause */
1604 case 83: /* resume */
1605 DEBUG(3,("%s queue entry %d\n",
1606 (function==82?"pausing":"resuming"),queue[i].job));
1607 status_printjob(cnum,snum,queue[i].job,
1608 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1615 SSVAL(*rparam,0,NERR_JobNotFound);
1617 if (queue) free(queue);
1620 SSVAL(*rparam,2,0); /* converter word */
1625 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1626 int mdrcnt,int mprcnt,
1627 char **rdata,char **rparam,
1628 int *rdata_len,int *rparam_len)
1630 char *str1 = param+2;
1631 char *str2 = skip_string(str1,1);
1632 char *QueueName = skip_string(str2,1);
1635 /* check it's a supported varient */
1636 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1640 *rparam = REALLOC(*rparam,*rparam_len);
1644 SSVAL(*rparam,0,NERR_Success);
1645 SSVAL(*rparam,2,0); /* converter word */
1647 snum = lp_servicenumber(QueueName);
1648 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1649 int pnum = lp_servicenumber(PRINTERS_NAME);
1651 lp_add_printer(QueueName,pnum);
1652 snum = lp_servicenumber(QueueName);
1656 if (snum >= 0 && VALID_SNUM(snum)) {
1657 print_queue_struct *queue=NULL;
1661 count = get_printqueue(snum,cnum,&queue,NULL);
1662 for (i = 0; i < count; i++)
1663 del_printqueue(cnum,snum,queue[i].job);
1665 if (queue) free(queue);
1668 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1674 /****************************************************************************
1675 set the property of a print job (undocumented?)
1676 ? function = 0xb -> set name of print job
1677 ? function = 0x6 -> move print job up/down
1678 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1679 or <WWsTP> <WB21BB16B10zWWzDDz>
1680 ****************************************************************************/
1681 static int check_printjob_info(struct pack_desc* desc,
1682 int uLevel, char* id)
1684 desc->subformat = NULL;
1686 case 0: desc->format = "W"; break;
1687 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1688 case 2: desc->format = "WWzWWDDzz"; break;
1689 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1690 default: return False;
1692 if (strcmp(desc->format,id) != 0) return False;
1696 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1697 int mdrcnt,int mprcnt,
1698 char **rdata,char **rparam,
1699 int *rdata_len,int *rparam_len)
1701 struct pack_desc desc;
1702 char *str1 = param+2;
1703 char *str2 = skip_string(str1,1);
1704 char *p = skip_string(str2,1);
1706 int uLevel = SVAL(p,2);
1707 int function = SVAL(p,4); /* what is this ?? */
1711 printjob_decode(SVAL(p,0), &snum, &jobid);
1714 *rparam = REALLOC(*rparam,*rparam_len);
1718 /* check it's a supported varient */
1719 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1723 case 0x6: /* change job place in the queue, data gives the new place */
1724 if (snum >= 0 && VALID_SNUM(snum))
1726 print_queue_struct *queue=NULL;
1730 count = get_printqueue(snum,cnum,&queue,NULL);
1731 for (i=0;i<count;i++) /* find job */
1732 if ((queue[i].job&0xFF) == jobid) break;
1735 desc.errcode=NERR_JobNotFound;
1736 if (queue) free(queue);
1739 desc.errcode=NERR_Success;
1743 int place= SVAL(data,0);
1744 /* we currently have no way of doing this. Can any unix do it? */
1745 if (i < place) /* move down */;
1746 else if (i > place ) /* move up */;
1749 desc.errcode=NERR_notsupported; /* not yet supported */
1750 if (queue) free(queue);
1753 else desc.errcode=NERR_JobNotFound;
1755 case 0xb: /* change print job name, data gives the name */
1756 /* jobid, snum should be zero */
1763 if (issafe(*s)) name[l++] = *s;
1768 DEBUG(3,("Setting print name to %s\n",name));
1772 for (i=0;i<MAX_OPEN_FILES;i++)
1773 if (Files[i].open && Files[i].print_file)
1776 int fcnum = Files[i].cnum;
1780 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1781 !become_service(fcnum,True))
1784 if (sys_rename(Files[i].name,name) == 0)
1785 string_set(&Files[i].name,name);
1789 unbecome_root(True);
1791 desc.errcode=NERR_Success;
1794 default: /* not implemented */
1798 SSVALS(*rparam,0,desc.errcode);
1799 SSVAL(*rparam,2,0); /* converter word */
1805 /****************************************************************************
1806 get info about the server
1807 ****************************************************************************/
1808 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1809 int mdrcnt,int mprcnt,
1810 char **rdata,char **rparam,
1811 int *rdata_len,int *rparam_len)
1813 char *str1 = param+2;
1814 char *str2 = skip_string(str1,1);
1815 char *p = skip_string(str2,1);
1816 int uLevel = SVAL(p,0);
1820 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1822 /* check it's a supported varient */
1823 if (!prefix_ok(str1,"WrLh")) return False;
1826 if (strcmp(str2,"B16") != 0) return False;
1830 if (strcmp(str2,"B16BBDz") != 0) return False;
1834 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1839 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1844 if (strcmp(str2,"DN") != 0) return False;
1848 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1851 default: return False;
1854 *rdata_len = mdrcnt;
1855 *rdata = REALLOC(*rdata,*rdata_len);
1858 p2 = p + struct_len;
1860 StrnCpy(p,local_machine,16);
1866 struct srv_info_struct *servers=NULL;
1869 uint32 servertype= lp_default_server_announce();
1871 pstrcpy(comment,lp_serverstring());
1873 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1874 for (i=0;i<count;i++)
1875 if (strequal(servers[i].name,local_machine))
1877 servertype = servers[i].type;
1878 pstrcpy(comment,servers[i].comment);
1881 if (servers) free(servers);
1883 SCVAL(p,0,lp_major_announce_version());
1884 SCVAL(p,1,lp_minor_announce_version());
1885 SIVAL(p,2,servertype);
1887 if (mdrcnt == struct_len) {
1890 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1891 standard_sub(cnum,comment);
1892 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1893 p2 = skip_string(p2,1);
1898 return False; /* not yet implemented */
1901 *rdata_len = PTR_DIFF(p2,*rdata);
1904 *rparam = REALLOC(*rparam,*rparam_len);
1905 SSVAL(*rparam,0,NERR_Success);
1906 SSVAL(*rparam,2,0); /* converter word */
1907 SSVAL(*rparam,4,*rdata_len);
1913 /****************************************************************************
1914 get info about the server
1915 ****************************************************************************/
1916 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1917 int mdrcnt,int mprcnt,
1918 char **rdata,char **rparam,
1919 int *rdata_len,int *rparam_len)
1921 char *str1 = param+2;
1922 char *str2 = skip_string(str1,1);
1923 char *p = skip_string(str2,1);
1925 extern pstring sesssetup_user;
1926 int level = SVAL(p,0);
1928 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1931 *rparam = REALLOC(*rparam,*rparam_len);
1933 /* check it's a supported varient */
1934 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1937 *rdata_len = mdrcnt + 1024;
1938 *rdata = REALLOC(*rdata,*rdata_len);
1940 SSVAL(*rparam,0,NERR_Success);
1941 SSVAL(*rparam,2,0); /* converter word */
1947 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1948 strcpy(p2,local_machine);
1950 p2 = skip_string(p2,1);
1953 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1954 strcpy(p2,sesssetup_user);
1955 p2 = skip_string(p2,1);
1958 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1959 strcpy(p2,myworkgroup);
1961 p2 = skip_string(p2,1);
1964 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1965 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1968 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1969 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1970 p2 = skip_string(p2,1);
1973 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1975 p2 = skip_string(p2,1);
1978 *rdata_len = PTR_DIFF(p2,*rdata);
1980 SSVAL(*rparam,4,*rdata_len);
1985 /****************************************************************************
1986 get info about a user
1988 struct user_info_11 {
1989 char usri11_name[21]; 0-20
1991 char *usri11_comment; 22-25
1992 char *usri11_usr_comment; 26-29
1993 unsigned short usri11_priv; 30-31
1994 unsigned long usri11_auth_flags; 32-35
1995 long usri11_password_age; 36-39
1996 char *usri11_homedir; 40-43
1997 char *usri11_parms; 44-47
1998 long usri11_last_logon; 48-51
1999 long usri11_last_logoff; 52-55
2000 unsigned short usri11_bad_pw_count; 56-57
2001 unsigned short usri11_num_logons; 58-59
2002 char *usri11_logon_server; 60-63
2003 unsigned short usri11_country_code; 64-65
2004 char *usri11_workstations; 66-69
2005 unsigned long usri11_max_storage; 70-73
2006 unsigned short usri11_units_per_week; 74-75
2007 unsigned char *usri11_logon_hours; 76-79
2008 unsigned short usri11_code_page; 80-81
2013 usri11_name specifies the user name for which information is retireved
2015 usri11_pad aligns the next data structure element to a word boundary
2017 usri11_comment is a null terminated ASCII comment
2019 usri11_user_comment is a null terminated ASCII comment about the user
2021 usri11_priv specifies the level of the privilege assigned to the user.
2022 The possible values are:
2024 Name Value Description
2025 USER_PRIV_GUEST 0 Guest privilege
2026 USER_PRIV_USER 1 User privilege
2027 USER_PRV_ADMIN 2 Administrator privilege
2029 usri11_auth_flags specifies the account operator privileges. The
2030 possible values are:
2032 Name Value Description
2033 AF_OP_PRINT 0 Print operator
2036 Leach, Naik [Page 28]
\r\f
2039 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2042 AF_OP_COMM 1 Communications operator
2043 AF_OP_SERVER 2 Server operator
2044 AF_OP_ACCOUNTS 3 Accounts operator
2047 usri11_password_age specifies how many seconds have elapsed since the
2048 password was last changed.
2050 usri11_home_dir points to a null terminated ASCII string that contains
2051 the path name of the user's home directory.
2053 usri11_parms points to a null terminated ASCII string that is set
2054 aside for use by applications.
2056 usri11_last_logon specifies the time when the user last logged on.
2057 This value is stored as the number of seconds elapsed since
2058 00:00:00, January 1, 1970.
2060 usri11_last_logoff specifies the time when the user last logged off.
2061 This value is stored as the number of seconds elapsed since
2062 00:00:00, January 1, 1970. A value of 0 means the last logoff
2065 usri11_bad_pw_count specifies the number of incorrect passwords
2066 entered since the last successful logon.
2068 usri11_log1_num_logons specifies the number of times this user has
2069 logged on. A value of -1 means the number of logons is unknown.
2071 usri11_logon_server points to a null terminated ASCII string that
2072 contains the name of the server to which logon requests are sent.
2073 A null string indicates logon requests should be sent to the
2076 usri11_country_code specifies the country code for the user's language
2079 usri11_workstations points to a null terminated ASCII string that
2080 contains the names of workstations the user may log on from.
2081 There may be up to 8 workstations, with the names separated by
2082 commas. A null strings indicates there are no restrictions.
2084 usri11_max_storage specifies the maximum amount of disk space the user
2085 can occupy. A value of 0xffffffff indicates there are no
2088 usri11_units_per_week specifies the equal number of time units into
2089 which a week is divided. This value must be equal to 168.
2091 usri11_logon_hours points to a 21 byte (168 bits) string that
2092 specifies the time during which the user can log on. Each bit
2093 represents one unique hour in a week. The first bit (bit 0, word
2094 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2098 Leach, Naik [Page 29]
\r\f
2101 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2104 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2105 are no restrictions.
2107 usri11_code_page specifies the code page for the user's language of
2110 All of the pointers in this data structure need to be treated
2111 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2112 to be ignored. The converter word returned in the parameters section
2113 needs to be subtracted from the lower 16 bits to calculate an offset
2114 into the return buffer where this ASCII string resides.
2116 There is no auxiliary data in the response.
2118 ****************************************************************************/
2120 #define usri11_name 0
2121 #define usri11_pad 21
2122 #define usri11_comment 22
2123 #define usri11_usr_comment 26
2124 #define usri11_full_name 30
2125 #define usri11_priv 34
2126 #define usri11_auth_flags 36
2127 #define usri11_password_age 40
2128 #define usri11_homedir 44
2129 #define usri11_parms 48
2130 #define usri11_last_logon 52
2131 #define usri11_last_logoff 56
2132 #define usri11_bad_pw_count 60
2133 #define usri11_num_logons 62
2134 #define usri11_logon_server 64
2135 #define usri11_country_code 68
2136 #define usri11_workstations 70
2137 #define usri11_max_storage 74
2138 #define usri11_units_per_week 78
2139 #define usri11_logon_hours 80
2140 #define usri11_code_page 84
2141 #define usri11_end 86
2143 #define USER_PRIV_GUEST 0
2144 #define USER_PRIV_USER 1
2145 #define USER_PRIV_ADMIN 2
2147 #define AF_OP_PRINT 0
2148 #define AF_OP_COMM 1
2149 #define AF_OP_SERVER 2
2150 #define AF_OP_ACCOUNTS 3
2153 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2154 int mdrcnt,int mprcnt,
2155 char **rdata,char **rparam,
2156 int *rdata_len,int *rparam_len)
2158 char *str1 = param+2;
2159 char *str2 = skip_string(str1,1);
2160 char *UserName = skip_string(str2,1);
2161 char *p = skip_string(UserName,1);
2162 int uLevel = SVAL(p,0);
2165 /* get NIS home of a previously validated user - simeon */
2166 user_struct *vuser = get_valid_user_struct(vuid);
2167 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2170 *rparam = REALLOC(*rparam,*rparam_len);
2172 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2174 /* check it's a supported variant */
2175 if (strcmp(str1,"zWrLh") != 0) return False;
2178 case 0: p2 = "B21"; break;
2179 case 1: p2 = "B21BB16DWzzWz"; break;
2180 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2181 case 10: p2 = "B21Bzzz"; break;
2182 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2183 default: return False;
2186 if (strcmp(p2,str2) != 0) return False;
2188 *rdata_len = mdrcnt + 1024;
2189 *rdata = REALLOC(*rdata,*rdata_len);
2191 SSVAL(*rparam,0,NERR_Success);
2192 SSVAL(*rparam,2,0); /* converter word */
2195 p2 = p + usri11_end;
2198 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2202 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2207 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2208 strcpy(p2,"Comment");
2209 p2 = skip_string(p2,1);
2211 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2212 strcpy(p2,"UserComment");
2213 p2 = skip_string(p2,1);
2215 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2216 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2217 strcpy(p2,vuser->real_name); /* simeon */
2218 p2 = skip_string(p2,1);
2221 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2223 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2224 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2225 SIVALS(p,usri11_password_age,-1); /* password age */
2226 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2227 strcpy(p2, lp_logon_path());
2228 p2 = skip_string(p2,1);
2229 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2231 p2 = skip_string(p2,1);
2232 SIVAL(p,usri11_last_logon,0); /* last logon */
2233 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2234 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2235 SSVALS(p,usri11_num_logons,-1); /* num logons */
2236 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2238 p2 = skip_string(p2,1);
2239 SSVAL(p,usri11_country_code,0); /* country code */
2241 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2243 p2 = skip_string(p2,1);
2245 SIVALS(p,usri11_max_storage,-1); /* max storage */
2246 SSVAL(p,usri11_units_per_week,168); /* units per week */
2247 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2249 /* a simple way to get logon hours at all times. */
2251 SCVAL(p2,21,0); /* fix zero termination */
2252 p2 = skip_string(p2,1);
2254 SSVAL(p,usri11_code_page,0); /* code page */
2256 if (uLevel == 1 || uLevel == 2)
2258 memset(p+22,' ',16); /* password */
2259 SIVALS(p,38,-1); /* password age */
2261 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2262 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2263 strcpy(p2,lp_logon_path());
2264 p2 = skip_string(p2,1);
2265 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2267 SSVAL(p,52,0); /* flags */
2268 SIVAL(p,54,0); /* script_path */
2271 SIVAL(p,60,0); /* auth_flags */
2272 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2273 strcpy(p2,vuser->real_name); /* simeon */
2274 p2 = skip_string(p2,1);
2275 SIVAL(p,68,0); /* urs_comment */
2276 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2278 p2 = skip_string(p2,1);
2279 SIVAL(p,76,0); /* workstations */
2280 SIVAL(p,80,0); /* last_logon */
2281 SIVAL(p,84,0); /* last_logoff */
2282 SIVALS(p,88,-1); /* acct_expires */
2283 SIVALS(p,92,-1); /* max_storage */
2284 SSVAL(p,96,168); /* units_per_week */
2285 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2288 SSVALS(p,102,-1); /* bad_pw_count */
2289 SSVALS(p,104,-1); /* num_logons */
2290 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2291 strcpy(p2,"\\\\%L");
2292 standard_sub_basic(p2);
2293 p2 = skip_string(p2,1);
2294 SSVAL(p,110,49); /* country_code */
2295 SSVAL(p,112,860); /* code page */
2299 *rdata_len = PTR_DIFF(p2,*rdata);
2301 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2306 /*******************************************************************
2307 get groups that a user is a member of
2308 ******************************************************************/
2309 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2310 int mdrcnt,int mprcnt,
2311 char **rdata,char **rparam,
2312 int *rdata_len,int *rparam_len)
2314 char *str1 = param+2;
2315 char *str2 = skip_string(str1,1);
2316 char *UserName = skip_string(str2,1);
2317 char *p = skip_string(UserName,1);
2318 int uLevel = SVAL(p,0);
2323 *rparam = REALLOC(*rparam,*rparam_len);
2325 /* check it's a supported varient */
2326 if (strcmp(str1,"zWrLeh") != 0) return False;
2328 case 0: p2 = "B21"; break;
2329 default: return False;
2331 if (strcmp(p2,str2) != 0) return False;
2333 *rdata_len = mdrcnt + 1024;
2334 *rdata = REALLOC(*rdata,*rdata_len);
2336 SSVAL(*rparam,0,NERR_Success);
2337 SSVAL(*rparam,2,0); /* converter word */
2341 /* XXXX we need a real SAM database some day */
2342 strcpy(p,"Users"); p += 21; count++;
2343 strcpy(p,"Domain Users"); p += 21; count++;
2344 strcpy(p,"Guests"); p += 21; count++;
2345 strcpy(p,"Domain Guests"); p += 21; count++;
2347 *rdata_len = PTR_DIFF(p,*rdata);
2349 SSVAL(*rparam,4,count); /* is this right?? */
2350 SSVAL(*rparam,6,count); /* is this right?? */
2356 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2357 int mdrcnt,int mprcnt,
2358 char **rdata,char **rparam,
2359 int *rdata_len,int *rparam_len)
2361 char *str1 = param+2;
2362 char *str2 = skip_string(str1,1);
2363 char *p = skip_string(str2,1);
2365 struct pack_desc desc;
2372 bzero(&desc,sizeof(desc));
2374 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2376 /* check it's a supported varient */
2377 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2378 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2379 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2381 desc.buflen = mdrcnt;
2382 desc.subformat = NULL;
2385 if (init_package(&desc,1,0))
2387 PACKI(&desc,"W",0); /* code */
2388 PACKS(&desc,"B21",name); /* eff. name */
2389 PACKS(&desc,"B",""); /* pad */
2391 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2392 PACKI(&desc,"D",0); /* auth flags XXX */
2393 PACKI(&desc,"W",0); /* num logons */
2394 PACKI(&desc,"W",0); /* bad pw count */
2395 PACKI(&desc,"D",0); /* last logon */
2396 PACKI(&desc,"D",-1); /* last logoff */
2397 PACKI(&desc,"D",-1); /* logoff time */
2398 PACKI(&desc,"D",-1); /* kickoff time */
2399 PACKI(&desc,"D",0); /* password age */
2400 PACKI(&desc,"D",0); /* password can change */
2401 PACKI(&desc,"D",-1); /* password must change */
2404 strcpy(mypath,"\\\\");
2405 strcat(mypath,local_machine);
2407 PACKS(&desc,"z",mypath); /* computer */
2409 PACKS(&desc,"z",myworkgroup);/* domain */
2411 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2412 /* made sure all macros are fully substituted and available */
2413 logon_script = lp_logon_script();
2414 standard_sub( cnum, logon_script );
2415 PACKS(&desc,"z", logon_script); /* script path */
2416 /* End of JHT mods */
2418 PACKI(&desc,"D",0x00000000); /* reserved */
2421 *rdata_len = desc.usedlen;
2423 *rparam = REALLOC(*rparam,*rparam_len);
2424 SSVALS(*rparam,0,desc.errcode);
2426 SSVAL(*rparam,4,desc.neededlen);
2428 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2433 /****************************************************************************
2434 api_WAccessGetUserPerms
2435 ****************************************************************************/
2436 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2437 int mdrcnt,int mprcnt,
2438 char **rdata,char **rparam,
2439 int *rdata_len,int *rparam_len)
2441 char *str1 = param+2;
2442 char *str2 = skip_string(str1,1);
2443 char *user = skip_string(str2,1);
2444 char *resource = skip_string(user,1);
2446 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2448 /* check it's a supported varient */
2449 if (strcmp(str1,"zzh") != 0) return False;
2450 if (strcmp(str2,"") != 0) return False;
2453 *rparam = REALLOC(*rparam,*rparam_len);
2454 SSVALS(*rparam,0,0); /* errorcode */
2455 SSVAL(*rparam,2,0); /* converter word */
2456 SSVAL(*rparam,4,0x7f); /* permission flags */
2461 /****************************************************************************
2462 api_WPrintJobEnumerate
2463 ****************************************************************************/
2464 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2465 int mdrcnt,int mprcnt,
2466 char **rdata,char **rparam,
2467 int *rdata_len,int *rparam_len)
2469 char *str1 = param+2;
2470 char *str2 = skip_string(str1,1);
2471 char *p = skip_string(str2,1);
2477 struct pack_desc desc;
2478 print_queue_struct *queue=NULL;
2479 print_status_struct status;
2484 bzero(&desc,sizeof(desc));
2485 bzero(&status,sizeof(status));
2487 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2489 /* check it's a supported varient */
2490 if (strcmp(str1,"WWrLh") != 0) return False;
2491 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2493 printjob_decode(SVAL(p,0), &snum, &job);
2495 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2497 count = get_printqueue(snum,cnum,&queue,&status);
2498 for (i = 0; i < count; i++) {
2499 if ((queue[i].job & 0xFF) == job) break;
2501 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2503 desc.buflen = mdrcnt;
2505 if (init_package(&desc,1,0)) {
2507 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2508 *rdata_len = desc.usedlen;
2511 desc.errcode = NERR_JobNotFound;
2517 *rparam = REALLOC(*rparam,*rparam_len);
2518 SSVALS(*rparam,0,desc.errcode);
2520 SSVAL(*rparam,4,desc.neededlen);
2522 if (queue) free(queue);
2524 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2528 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2529 int mdrcnt,int mprcnt,
2530 char **rdata,char **rparam,
2531 int *rdata_len,int *rparam_len)
2533 char *str1 = param+2;
2534 char *str2 = skip_string(str1,1);
2535 char *p = skip_string(str2,1);
2541 struct pack_desc desc;
2542 print_queue_struct *queue=NULL;
2543 print_status_struct status;
2545 bzero(&desc,sizeof(desc));
2546 bzero(&status,sizeof(status));
2548 p = skip_string(p,1);
2552 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2554 /* check it's a supported varient */
2555 if (strcmp(str1,"zWrLeh") != 0) return False;
2556 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2557 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2559 snum = lp_servicenumber(name);
2560 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2561 int pnum = lp_servicenumber(PRINTERS_NAME);
2563 lp_add_printer(name,pnum);
2564 snum = lp_servicenumber(name);
2568 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2570 count = get_printqueue(snum,cnum,&queue,&status);
2571 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2573 desc.buflen = mdrcnt;
2575 if (init_package(&desc,count,0)) {
2577 for (i = 0; i < count; i++) {
2578 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2579 if (desc.errcode == NERR_Success) succnt = i+1;
2583 *rdata_len = desc.usedlen;
2586 *rparam = REALLOC(*rparam,*rparam_len);
2587 SSVALS(*rparam,0,desc.errcode);
2589 SSVAL(*rparam,4,succnt);
2590 SSVAL(*rparam,6,count);
2592 if (queue) free(queue);
2594 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2598 static int check_printdest_info(struct pack_desc* desc,
2599 int uLevel, char* id)
2601 desc->subformat = NULL;
2603 case 0: desc->format = "B9"; break;
2604 case 1: desc->format = "B9B21WWzW"; break;
2605 case 2: desc->format = "z"; break;
2606 case 3: desc->format = "zzzWWzzzWW"; break;
2607 default: return False;
2609 if (strcmp(desc->format,id) != 0) return False;
2613 static void fill_printdest_info(int cnum, int snum, int uLevel,
2614 struct pack_desc* desc)
2617 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2618 buf[sizeof(buf)-1] = 0;
2621 PACKS(desc,"B9",buf); /* szName */
2623 PACKS(desc,"B21",""); /* szUserName */
2624 PACKI(desc,"W",0); /* uJobId */
2625 PACKI(desc,"W",0); /* fsStatus */
2626 PACKS(desc,"z",""); /* pszStatus */
2627 PACKI(desc,"W",0); /* time */
2630 if (uLevel == 2 || uLevel == 3) {
2631 PACKS(desc,"z",buf); /* pszPrinterName */
2633 PACKS(desc,"z",""); /* pszUserName */
2634 PACKS(desc,"z",""); /* pszLogAddr */
2635 PACKI(desc,"W",0); /* uJobId */
2636 PACKI(desc,"W",0); /* fsStatus */
2637 PACKS(desc,"z",""); /* pszStatus */
2638 PACKS(desc,"z",""); /* pszComment */
2639 PACKS(desc,"z","NULL"); /* pszDrivers */
2640 PACKI(desc,"W",0); /* time */
2641 PACKI(desc,"W",0); /* pad1 */
2646 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2647 int mdrcnt,int mprcnt,
2648 char **rdata,char **rparam,
2649 int *rdata_len,int *rparam_len)
2651 char *str1 = param+2;
2652 char *str2 = skip_string(str1,1);
2653 char *p = skip_string(str2,1);
2654 char* PrinterName = p;
2656 struct pack_desc desc;
2659 bzero(&desc,sizeof(desc));
2661 p = skip_string(p,1);
2665 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2667 /* check it's a supported varient */
2668 if (strcmp(str1,"zWrLh") != 0) return False;
2669 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2671 snum = lp_servicenumber(PrinterName);
2672 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2673 int pnum = lp_servicenumber(PRINTERS_NAME);
2675 lp_add_printer(PrinterName,pnum);
2676 snum = lp_servicenumber(PrinterName);
2682 desc.errcode = NERR_DestNotFound;
2686 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2688 desc.buflen = mdrcnt;
2689 if (init_package(&desc,1,0)) {
2690 fill_printdest_info(cnum,snum,uLevel,&desc);
2692 *rdata_len = desc.usedlen;
2696 *rparam = REALLOC(*rparam,*rparam_len);
2697 SSVALS(*rparam,0,desc.errcode);
2699 SSVAL(*rparam,4,desc.neededlen);
2701 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2705 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2706 int mdrcnt,int mprcnt,
2707 char **rdata,char **rparam,
2708 int *rdata_len,int *rparam_len)
2710 char *str1 = param+2;
2711 char *str2 = skip_string(str1,1);
2712 char *p = skip_string(str2,1);
2716 struct pack_desc desc;
2717 int services = lp_numservices();
2719 bzero(&desc,sizeof(desc));
2724 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2726 /* check it's a supported varient */
2727 if (strcmp(str1,"WrLeh") != 0) return False;
2728 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2731 for (i = 0; i < services; i++)
2732 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2735 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2737 desc.buflen = mdrcnt;
2738 if (init_package(&desc,queuecnt,0)) {
2741 for (i = 0; i < services; i++) {
2742 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2743 fill_printdest_info(cnum,i,uLevel,&desc);
2745 if (desc.errcode == NERR_Success) succnt = n;
2750 *rdata_len = desc.usedlen;
2753 *rparam = REALLOC(*rparam,*rparam_len);
2754 SSVALS(*rparam,0,desc.errcode);
2756 SSVAL(*rparam,4,succnt);
2757 SSVAL(*rparam,6,queuecnt);
2759 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2763 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2764 int mdrcnt,int mprcnt,
2765 char **rdata,char **rparam,
2766 int *rdata_len,int *rparam_len)
2768 char *str1 = param+2;
2769 char *str2 = skip_string(str1,1);
2770 char *p = skip_string(str2,1);
2773 struct pack_desc desc;
2775 bzero(&desc,sizeof(desc));
2780 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2782 /* check it's a supported varient */
2783 if (strcmp(str1,"WrLeh") != 0) return False;
2784 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2786 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2788 desc.buflen = mdrcnt;
2789 if (init_package(&desc,1,0)) {
2790 PACKS(&desc,"B41","NULL");
2793 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2795 *rdata_len = desc.usedlen;
2798 *rparam = REALLOC(*rparam,*rparam_len);
2799 SSVALS(*rparam,0,desc.errcode);
2801 SSVAL(*rparam,4,succnt);
2804 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2808 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2809 int mdrcnt,int mprcnt,
2810 char **rdata,char **rparam,
2811 int *rdata_len,int *rparam_len)
2813 char *str1 = param+2;
2814 char *str2 = skip_string(str1,1);
2815 char *p = skip_string(str2,1);
2818 struct pack_desc desc;
2820 bzero(&desc,sizeof(desc));
2825 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2827 /* check it's a supported varient */
2828 if (strcmp(str1,"WrLeh") != 0) return False;
2829 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2831 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2833 desc.buflen = mdrcnt;
2835 if (init_package(&desc,1,0)) {
2836 PACKS(&desc,"B13","lpd");
2839 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2841 *rdata_len = desc.usedlen;
2844 *rparam = REALLOC(*rparam,*rparam_len);
2845 SSVALS(*rparam,0,desc.errcode);
2847 SSVAL(*rparam,4,succnt);
2850 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2854 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2855 int mdrcnt,int mprcnt,
2856 char **rdata,char **rparam,
2857 int *rdata_len,int *rparam_len)
2859 char *str1 = param+2;
2860 char *str2 = skip_string(str1,1);
2861 char *p = skip_string(str2,1);
2864 struct pack_desc desc;
2866 bzero(&desc,sizeof(desc));
2871 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2873 /* check it's a supported varient */
2874 if (strcmp(str1,"WrLeh") != 0) return False;
2875 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2877 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2878 bzero(&desc,sizeof(desc));
2880 desc.buflen = mdrcnt;
2882 if (init_package(&desc,1,0)) {
2883 PACKS(&desc,"B13","lp0");
2886 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2888 *rdata_len = desc.usedlen;
2891 *rparam = REALLOC(*rparam,*rparam_len);
2892 SSVALS(*rparam,0,desc.errcode);
2894 SSVAL(*rparam,4,succnt);
2897 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2905 char * pipe_clnt_name;
2907 char * pipe_srv_name;
2911 } api_fd_commands [] =
2914 { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP },
2915 { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP },
2916 { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP },
2917 { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP },
2918 { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP },
2919 { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2921 { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
2922 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2926 /****************************************************************************
2927 handle remote api calls delivered to a named pipe already opened.
2928 ****************************************************************************/
2929 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2930 uint16 *setup,char *data,char *params,
2931 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2934 char *rparam = NULL;
2939 BOOL bind_req = False;
2940 BOOL set_nphs = False;
2947 DEBUG(5,("api_fd_reply\n"));
2948 /* First find out the name of this file. */
2951 DEBUG(0,("Unexpected named pipe transaction.\n"));
2955 /* Get the file handle and hence the file name. */
2957 subcommand = setup[0];
2958 pipe_name = get_rpc_pipe_hnd_name(fd);
2960 if (pipe_name == NULL)
2962 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
2965 DEBUG(3,("Got API command %d on pipe %s (fd %x)",
2966 subcommand, pipe_name, fd));
2967 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2968 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2970 for (i = 0; api_fd_commands[i].name; i++)
2972 if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
2973 api_fd_commands[i].subcommand == subcommand &&
2974 api_fd_commands[i].fn)
2976 DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
2981 rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2982 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2985 /* RPC Pipe command 0x26. */
2986 if (data != NULL && api_fd_commands[i].subcommand == 0x26)
2990 /* process the rpc header */
2991 char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
2993 /* bind request received */
2994 if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
2998 /* decode the bind request */
2999 char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
3001 if ((bind_req = (p != NULL)))
3004 fstring ack_pipe_name;
3006 /* name has to be \PIPE\xxxxx */
3007 strcpy(ack_pipe_name, "\\PIPE\\");
3008 strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
3010 /* make a bind acknowledgement */
3011 make_rpc_hdr_ba(&hdr_ba,
3012 hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
3015 &(hdr_rb.transfer));
3017 p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
3019 rdata_len = PTR_DIFF(p, rdata);
3021 make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
3023 p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
3025 reply = (p != NULL);
3031 /* Set Named Pipe Handle state */
3032 if (subcommand == 0x1)
3035 reply = api_LsarpcSNPHS(fd, cnum, params);
3038 if (!bind_req && !set_nphs)
3040 DEBUG(10,("calling api_fd_command\n"));
3042 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3043 &rdata,&rparam,&rdata_len,&rparam_len);
3044 DEBUG(10,("called api_fd_command\n"));
3047 if (rdata_len > mdrcnt || rparam_len > mprcnt)
3049 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3050 &rdata,&rparam,&rdata_len,&rparam_len);
3053 /* if we get False back then it's actually unsupported */
3056 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3057 &rdata,&rparam,&rdata_len,&rparam_len);
3060 /* now send the reply */
3061 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3063 if (rdata ) free(rdata );
3064 if (rparam) free(rparam);
3071 /****************************************************************************
3072 the buffer was too small
3073 ****************************************************************************/
3074 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3075 int mdrcnt,int mprcnt,
3076 char **rdata,char **rparam,
3077 int *rdata_len,int *rparam_len)
3079 *rparam_len = MIN(*rparam_len,mprcnt);
3080 *rparam = REALLOC(*rparam,*rparam_len);
3084 SSVAL(*rparam,0,NERR_BufTooSmall);
3086 DEBUG(3,("Supplied buffer too small in API command\n"));
3092 /****************************************************************************
3093 the request is not supported
3094 ****************************************************************************/
3095 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3096 int mdrcnt,int mprcnt,
3097 char **rdata,char **rparam,
3098 int *rdata_len,int *rparam_len)
3101 *rparam = REALLOC(*rparam,*rparam_len);
3105 SSVAL(*rparam,0,NERR_notsupported);
3106 SSVAL(*rparam,2,0); /* converter word */
3108 DEBUG(3,("Unsupported API command\n"));
3122 } api_commands[] = {
3123 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3124 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3125 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3126 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3127 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3128 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3129 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3130 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3131 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3132 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3133 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3134 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3135 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3136 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3137 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3138 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3139 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3140 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3141 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3142 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3143 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3144 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3145 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3146 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3147 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3148 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3151 /****************************************************************************
3152 handle remote api calls
3153 ****************************************************************************/
3154 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3155 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3157 int api_command = SVAL(params,0);
3159 char *rparam = NULL;
3165 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3166 api_command,params+2,skip_string(params+2,1),
3167 tdscnt,tpscnt,mdrcnt,mprcnt));
3169 for (i=0;api_commands[i].name;i++)
3170 if (api_commands[i].id == api_command && api_commands[i].fn)
3172 DEBUG(3,("Doing %s\n",api_commands[i].name));
3176 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3177 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3179 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3180 &rdata,&rparam,&rdata_len,&rparam_len);
3183 if (rdata_len > mdrcnt ||
3184 rparam_len > mprcnt)
3186 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3187 &rdata,&rparam,&rdata_len,&rparam_len);
3191 /* if we get False back then it's actually unsupported */
3193 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3194 &rdata,&rparam,&rdata_len,&rparam_len);
3198 /* now send the reply */
3199 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3209 /****************************************************************************
3210 handle named pipe commands
3211 ****************************************************************************/
3212 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3213 uint16 *setup,char *data,char *params,
3214 int suwcnt,int tdscnt,int tpscnt,
3215 int msrcnt,int mdrcnt,int mprcnt)
3217 DEBUG(3,("named pipe command on <%s> name\n", name));
3219 if (strequal(name,"LANMAN"))
3221 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3224 if (strlen(name) < 1)
3226 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3231 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3238 /****************************************************************************
3240 ****************************************************************************/
3241 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3245 char *data=NULL,*params=NULL;
3249 int cnum = SVAL(inbuf,smb_tid);
3250 uint16 vuid = SVAL(inbuf,smb_uid);
3252 int tpscnt = SVAL(inbuf,smb_vwv0);
3253 int tdscnt = SVAL(inbuf,smb_vwv1);
3254 int mprcnt = SVAL(inbuf,smb_vwv2);
3255 int mdrcnt = SVAL(inbuf,smb_vwv3);
3256 int msrcnt = CVAL(inbuf,smb_vwv4);
3257 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3258 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3259 int pscnt = SVAL(inbuf,smb_vwv9);
3260 int psoff = SVAL(inbuf,smb_vwv10);
3261 int dscnt = SVAL(inbuf,smb_vwv11);
3262 int dsoff = SVAL(inbuf,smb_vwv12);
3263 int suwcnt = CVAL(inbuf,smb_vwv13);
3265 bzero(name, sizeof(name));
3266 fstrcpy(name,smb_buf(inbuf));
3268 if (dscnt > tdscnt || pscnt > tpscnt) {
3269 exit_server("invalid trans parameters\n");
3274 data = (char *)malloc(tdscnt);
3275 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3279 params = (char *)malloc(tpscnt);
3280 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3286 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3287 for (i=0;i<suwcnt;i++)
3288 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3292 if (pscnt < tpscnt || dscnt < tdscnt)
3294 /* We need to send an interim response then receive the rest
3295 of the parameter/data bytes */
3296 outsize = set_message(outbuf,0,0,True);
3298 send_smb(Client,outbuf);
3301 /* receive the rest of the trans packet */
3302 while (pscnt < tpscnt || dscnt < tdscnt)
3305 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3307 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3309 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3312 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3314 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3315 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3316 if (params) free(params);
3317 if (data) free(data);
3318 if (setup) free(setup);
3319 return(ERROR(ERRSRV,ERRerror));
3324 tpscnt = SVAL(inbuf,smb_vwv0);
3325 tdscnt = SVAL(inbuf,smb_vwv1);
3327 pcnt = SVAL(inbuf,smb_vwv2);
3328 poff = SVAL(inbuf,smb_vwv3);
3329 pdisp = SVAL(inbuf,smb_vwv4);
3331 dcnt = SVAL(inbuf,smb_vwv5);
3332 doff = SVAL(inbuf,smb_vwv6);
3333 ddisp = SVAL(inbuf,smb_vwv7);
3338 if (dscnt > tdscnt || pscnt > tpscnt) {
3339 exit_server("invalid trans parameters\n");
3343 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3345 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3349 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3351 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3353 DEBUG(5,("calling named_pipe\n"));
3354 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3355 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3359 DEBUG(3,("invalid pipe name\n"));
3364 if (data) free(data);
3365 if (params) free(params);
3366 if (setup) free(setup);
3368 if (close_on_completion)
3369 close_cnum(cnum,vuid);
3375 return(ERROR(ERRSRV,ERRnosupport));