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 */
66 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
67 int mdrcnt,int mprcnt,
68 char **rdata,char **rparam,
69 int *rdata_len,int *rparam_len);
70 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
71 int mdrcnt,int mprcnt,
72 char **rdata,char **rparam,
73 int *rdata_len,int *rparam_len);
76 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 string_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(cnum,buf);
93 static int CopyAndAdvance(char** dst, char* src, int* n)
96 if (!src || !dst || !n || !(*dst)) return(0);
104 static int StrlenExpanded(int cnum, int snum, char* s)
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(cnum,buf);
111 return strlen(buf) + 1;
114 static char* Expand(int cnum, int snum, char* s)
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 string_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(cnum,buf);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
133 /****************************************************************************
135 ****************************************************************************/
136 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
137 int ldata,int lparam,int lsetup)
140 int this_ldata,this_lparam;
141 int tot_data=0,tot_param=0;
144 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
145 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
147 align = (this_lparam%4);
149 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
151 memcpy(smb_buf(outbuf),param,this_lparam);
153 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
155 SSVAL(outbuf,smb_vwv0,lparam);
156 SSVAL(outbuf,smb_vwv1,ldata);
157 SSVAL(outbuf,smb_vwv3,this_lparam);
158 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
159 SSVAL(outbuf,smb_vwv5,0);
160 SSVAL(outbuf,smb_vwv6,this_ldata);
161 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
162 SSVAL(outbuf,smb_vwv8,0);
163 SSVAL(outbuf,smb_vwv9,lsetup);
164 for (i=0;i<lsetup;i++)
165 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
168 send_smb(Client,outbuf);
170 tot_data = this_ldata;
171 tot_param = this_lparam;
173 while (tot_data < ldata || tot_param < lparam)
175 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
176 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
178 align = (this_lparam%4);
180 set_message(outbuf,10,this_ldata+this_lparam+align,False);
182 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
184 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
186 SSVAL(outbuf,smb_vwv3,this_lparam);
187 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
188 SSVAL(outbuf,smb_vwv5,tot_param);
189 SSVAL(outbuf,smb_vwv6,this_ldata);
190 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
191 SSVAL(outbuf,smb_vwv8,tot_data);
192 SSVAL(outbuf,smb_vwv9,0);
195 send_smb(Client,outbuf);
197 tot_data += this_ldata;
198 tot_param += this_lparam;
203 char* format; /* formatstring for structure */
204 char* subformat; /* subformat for structure */
205 char* base; /* baseaddress of buffer */
206 int buflen; /* remaining size for fixed part; on init: length of base */
207 int subcount; /* count of substructures */
208 char* structbuf; /* pointer into buffer for remaining fixed part */
209 int stringlen; /* remaining size for variable part */
210 char* stringbuf; /* pointer into buffer for remaining variable part */
211 int neededlen; /* total needed size */
212 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 char* curpos; /* current position; pointer into format or subformat */
217 static int get_counter(char** p)
220 if (!p || !(*p)) return(1);
221 if (!isdigit(**p)) return 1;
225 n = 10 * n + (i - '0');
232 static int getlen(char* p)
238 case 'W': /* word (2 byte) */
241 case 'N': /* count of substructures (word) at end */
244 case 'D': /* double word (4 byte) */
245 case 'z': /* offset to zero terminated string (4 byte) */
246 case 'l': /* offset to user data (4 byte) */
249 case 'b': /* offset to data (with counter) (4 byte) */
253 case 'B': /* byte (with optional counter) */
254 n += get_counter(&p);
261 static BOOL init_package(struct pack_desc* p, int count, int subcount)
266 if (!p->format || !p->base) return(False);
268 i = count * getlen(p->format);
269 if (p->subformat) i += subcount * getlen(p->subformat);
270 p->structbuf = p->base;
274 p->curpos = p->format;
277 p->errcode = NERR_BufTooSmall;
280 p->errcode = NERR_Success;
283 p->stringbuf = p->base + i;
285 return(p->errcode == NERR_Success);
289 static int package(struct pack_desc* p, ...)
292 static int package(va_alist)
298 int needed=0, stringneeded;
300 int is_string=0, stringused;
307 p = va_arg(args,struct pack_desc *);
312 p->curpos = p->format;
314 p->curpos = p->subformat;
319 str = va_arg(args,char*);
320 if (strncmp(str,p->curpos,strlen(str)) != 0) {
321 DEBUG(2,("type error in package: %s instead of %*s\n",str,
322 strlen(str),p->curpos));
332 if (!p->curpos) return(0);
334 switch( *p->curpos++ ) {
335 case 'W': /* word (2 byte) */
337 temp = va_arg(args,int);
338 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
340 case 'N': /* count of substructures (word) at end */
342 p->subcount = va_arg(args,int);
343 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
345 case 'D': /* double word (4 byte) */
347 temp = va_arg(args,int);
348 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
350 case 'B': /* byte (with optional counter) */
351 needed = get_counter(&p->curpos);
353 char *s = va_arg(args,char*);
354 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
357 case 'z': /* offset to zero terminated string (4 byte) */
358 str = va_arg(args,char*);
359 stringneeded = (str ? strlen(str)+1 : 0);
362 case 'l': /* offset to user data (4 byte) */
363 str = va_arg(args,char*);
364 stringneeded = va_arg(args,int);
367 case 'b': /* offset to data (with counter) (4 byte) */
368 str = va_arg(args,char*);
369 stringneeded = get_counter(&p->curpos);
374 if (stringneeded >= 0) {
376 if (p->buflen >= needed) {
377 stringused = stringneeded;
378 if (stringused > p->stringlen) {
379 stringused = (is_string ? p->stringlen : 0);
380 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
383 SIVAL(p->structbuf,0,0);
385 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
386 memcpy(p->stringbuf,str?str:"",stringused);
387 if (is_string) p->stringbuf[stringused-1] = '\0';
388 p->stringbuf += stringused;
389 p->stringlen -= stringused;
390 p->usedlen += stringused;
393 p->neededlen += stringneeded;
395 p->neededlen += needed;
396 if (p->buflen >= needed) {
397 p->structbuf += needed;
399 p->usedlen += needed;
402 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
408 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
409 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
411 #define PACK(desc,t,v) package(desc,v)
412 #define PACKl(desc,t,v,l) package(desc,v,l)
415 static void PACKI(struct pack_desc* desc,char *t,int v)
420 static void PACKS(struct pack_desc* desc,char *t,char *v)
426 /****************************************************************************
428 ****************************************************************************/
430 static void PackDriverData(struct pack_desc* desc)
432 char drivdata[4+4+32];
433 SIVAL(drivdata,0,sizeof drivdata); /* cb */
434 SIVAL(drivdata,4,1000); /* lVersion */
435 memset(drivdata+8,0,32); /* szDeviceName */
436 strcpy(drivdata+8,"NULL");
437 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
440 static int check_printq_info(struct pack_desc* desc,
441 int uLevel, char *id1, char *id2)
443 desc->subformat = NULL;
446 desc->format = "B13";
449 desc->format = "B13BWWWzzzzzWW";
452 desc->format = "B13BWWWzzzzzWN";
453 desc->subformat = "WB21BB16B10zWWzDDz";
456 desc->format = "zWWWWzzzzWWzzl";
459 desc->format = "zWWWWzzzzWNzzl";
460 desc->subformat = "WWzWWDDzz";
466 desc->format = "WzzzzzzzzN";
467 desc->subformat = "z";
469 default: return False;
471 if (strcmp(desc->format,id1) != 0) return False;
472 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
476 static void fill_printjob_info(int cnum, int snum, int uLevel,
477 struct pack_desc* desc,
478 print_queue_struct* queue, int n)
480 time_t t = queue->time;
482 /* the client expects localtime */
485 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
487 PACKS(desc,"B21",queue->user); /* szUserName */
488 PACKS(desc,"B",""); /* pad */
489 PACKS(desc,"B16",""); /* szNotifyName */
490 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
491 PACKS(desc,"z",""); /* pszParms */
492 PACKI(desc,"W",n+1); /* uPosition */
493 PACKI(desc,"W",queue->status); /* fsStatus */
494 PACKS(desc,"z",""); /* pszStatus */
495 PACKI(desc,"D",t); /* ulSubmitted */
496 PACKI(desc,"D",queue->size); /* ulSize */
497 PACKS(desc,"z",queue->file); /* pszComment */
499 if (uLevel == 2 || uLevel == 3) {
500 PACKI(desc,"W",queue->priority); /* uPriority */
501 PACKS(desc,"z",queue->user); /* pszUserName */
502 PACKI(desc,"W",n+1); /* uPosition */
503 PACKI(desc,"W",queue->status); /* fsStatus */
504 PACKI(desc,"D",t); /* ulSubmitted */
505 PACKI(desc,"D",queue->size); /* ulSize */
506 PACKS(desc,"z","Samba"); /* pszComment */
507 PACKS(desc,"z",queue->file); /* pszDocument */
509 PACKS(desc,"z",""); /* pszNotifyName */
510 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
511 PACKS(desc,"z",""); /* pszParms */
512 PACKS(desc,"z",""); /* pszStatus */
513 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
514 PACKS(desc,"z","lpd"); /* pszQProcName */
515 PACKS(desc,"z",""); /* pszQProcParms */
516 PACKS(desc,"z","NULL"); /* pszDriverName */
517 PackDriverData(desc); /* pDriverData */
518 PACKS(desc,"z",""); /* pszPrinterName */
523 static void fill_printq_info(int cnum, int snum, int uLevel,
524 struct pack_desc* desc,
525 int count, print_queue_struct* queue,
526 print_status_struct* status)
531 PACKS(desc,"B13",SERVICE(snum));
536 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
540 if (uLevel == 1 || uLevel == 2) {
541 PACKS(desc,"B",""); /* alignment */
542 PACKI(desc,"W",5); /* priority */
543 PACKI(desc,"W",0); /* start time */
544 PACKI(desc,"W",0); /* until time */
545 PACKS(desc,"z",""); /* pSepFile */
546 PACKS(desc,"z","lpd"); /* pPrProc */
547 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
548 PACKS(desc,"z",""); /* pParms */
550 PACKS(desc,"z","UNKNOWN PRINTER");
551 PACKI(desc,"W",LPSTAT_ERROR);
553 else if (!status || !status->message[0]) {
554 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
555 PACKI(desc,"W",LPSTAT_OK); /* status */
557 PACKS(desc,"z",status->message);
558 PACKI(desc,"W",status->status); /* status */
560 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
562 if (uLevel == 3 || uLevel == 4) {
563 PACKI(desc,"W",5); /* uPriority */
564 PACKI(desc,"W",0); /* uStarttime */
565 PACKI(desc,"W",0); /* uUntiltime */
566 PACKI(desc,"W",5); /* pad1 */
567 PACKS(desc,"z",""); /* pszSepFile */
568 PACKS(desc,"z","WinPrint"); /* pszPrProc */
569 PACKS(desc,"z",""); /* pszParms */
570 if (!status || !status->message[0]) {
571 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
572 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
574 PACKS(desc,"z",status->message); /* pszComment */
575 PACKI(desc,"W",status->status); /* fsStatus */
577 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
578 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
579 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
580 PackDriverData(desc); /* pDriverData */
582 if (uLevel == 2 || uLevel == 4) {
584 for (i=0;i<count;i++)
585 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
590 pstring tok,driver,short_name;
595 strcpy(fname,lp_driverfile());
599 DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
602 p=(char *)malloc(8192*sizeof(char));
603 bzero(p, 8192*sizeof(char));
606 /* lookup the long printer driver name in the file description */
607 while (f && !feof(f) && !ok)
611 next_token(&p,tok,":");
612 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
617 next_token(&p,short_name,":");
618 next_token(&p,driver,":");
620 PACKI(desc,"W",0x0400); /* don't know */
621 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
625 PACKS(desc,"z",driver); /* Driver Name */
626 PACKS(desc,"z",short_name); /* short printer name */
627 DEBUG(3,("Driver:%s:\n",driver));
628 DEBUG(3,("short name:%s:\n",short_name));
637 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
638 PACKS(desc,"z","EMF");
641 PACKS(desc,"z",driver); /* driver name */
644 PACKI(desc,"N",count); /* number of files to copy */
645 for (i=0;i<count;i++)
647 next_token(&p,tok,",");
648 PACKS(desc,"z",tok); /* driver files to copy */
649 DEBUG(3,("file:%s:\n",tok));
654 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
657 /* This function returns the number of file for a given driver */
658 int get_printerdrivernumber(int snum)
666 strcpy(fname,lp_driverfile());
668 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
671 DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
675 p=(char *)malloc(8192*sizeof(char));
676 q=p; /* need it to free memory because p change ! */
678 /* lookup the long printer driver name in the file description */
679 while (!feof(f) && !ok)
682 next_token(&p,tok,":");
683 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
688 next_token(&p,tok,":"); /* short name */
689 next_token(&p,tok,":"); /* driver name */
690 /* count the number of files */
691 while (next_token(&p,tok,","))
700 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
701 int mdrcnt,int mprcnt,
702 char **rdata,char **rparam,
703 int *rdata_len,int *rparam_len)
705 char *str1 = param+2;
706 char *str2 = skip_string(str1,1);
707 char *p = skip_string(str2,1);
713 struct pack_desc desc;
714 print_queue_struct *queue=NULL;
715 print_status_struct status;
717 bzero(&status,sizeof(status));
718 bzero(&desc,sizeof(desc));
720 p = skip_string(p,1);
725 /* remove any trailing username */
726 if ((p = strchr(QueueName,'%'))) *p = 0;
728 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
730 /* check it's a supported varient */
731 if (!prefix_ok(str1,"zWrLh")) return False;
732 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
734 snum = lp_servicenumber(QueueName);
735 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
736 int pnum = lp_servicenumber(PRINTERS_NAME);
738 lp_add_printer(QueueName,pnum);
739 snum = lp_servicenumber(QueueName);
743 if (snum < 0 || !VALID_SNUM(snum)) return(False);
747 count = get_printerdrivernumber(snum);
748 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
751 count = get_printqueue(snum,cnum,&queue,&status);
753 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
755 desc.buflen = mdrcnt;
756 if (init_package(&desc,1,count)) {
757 desc.subcount = count;
758 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
761 *rdata_len = desc.usedlen;
764 *rparam = REALLOC(*rparam,*rparam_len);
765 SSVALS(*rparam,0,desc.errcode);
767 SSVAL(*rparam,4,desc.neededlen);
769 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
771 if (queue) free(queue);
777 /****************************************************************************
778 view list of all print jobs on all queues
779 ****************************************************************************/
780 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
781 int mdrcnt, int mprcnt,
782 char **rdata, char** rparam,
783 int *rdata_len, int *rparam_len)
785 char *param_format = param+2;
786 char *output_format1 = skip_string(param_format,1);
787 char *p = skip_string(output_format1,1);
788 int uLevel = SVAL(p,0);
789 char *output_format2 = p + 4;
790 int services = lp_numservices();
792 struct pack_desc desc;
793 print_queue_struct **queue = NULL;
794 print_status_struct *status = NULL;
795 int* subcntarr = NULL;
796 int queuecnt, subcnt=0, succnt=0;
798 bzero(&desc,sizeof(desc));
800 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
802 if (!prefix_ok(param_format,"WrLeh")) return False;
803 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
806 for (i = 0; i < services; i++)
807 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
810 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
811 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
812 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
813 memset(status,0,queuecnt*sizeof(print_status_struct));
814 subcntarr = (int*)malloc(queuecnt*sizeof(int));
817 for (i = 0; i < services; i++)
818 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
819 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
820 subcnt += subcntarr[n];
824 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
826 desc.buflen = mdrcnt;
828 if (init_package(&desc,queuecnt,subcnt)) {
831 for (i = 0; i < services; i++)
832 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
833 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
835 if (desc.errcode == NERR_Success) succnt = n;
839 if (subcntarr) free(subcntarr);
841 *rdata_len = desc.usedlen;
843 *rparam = REALLOC(*rparam,*rparam_len);
844 SSVALS(*rparam,0,desc.errcode);
846 SSVAL(*rparam,4,succnt);
847 SSVAL(*rparam,6,queuecnt);
849 for (i = 0; i < queuecnt; i++) {
850 if (queue && queue[i]) free(queue[i]);
853 if (queue) free(queue);
854 if (status) free(status);
859 /****************************************************************************
860 get info level for a server list query
861 ****************************************************************************/
862 static BOOL check_server_info(int uLevel, char* id)
866 if (strcmp(id,"B16") != 0) return False;
869 if (strcmp(id,"B16BBDz") != 0) return False;
877 struct srv_info_struct
887 /*******************************************************************
888 get server info lists from the files saved by nmbd. Return the
890 ******************************************************************/
891 static int get_server_info(uint32 servertype,
892 struct srv_info_struct **servers,
900 BOOL local_list_only;
902 pstrcpy(fname,lp_lockdir());
903 trim_string(fname,NULL,"/");
905 strcat(fname,SERVER_LIST);
907 f = fopen(fname,"r");
910 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
914 /* request for everything is code for request all servers */
915 if (servertype == SV_TYPE_ALL)
916 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
918 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
920 DEBUG(4,("Servertype search: %8x\n",servertype));
925 struct srv_info_struct *s;
930 fgets(line,sizeof(line)-1,f);
931 if (!*line) continue;
933 if (count == alloced) {
935 (*servers) = (struct srv_info_struct *)
936 Realloc(*servers,sizeof(**servers)*alloced);
937 if (!(*servers)) return(0);
938 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
940 s = &(*servers)[count];
942 if (!next_token(&ptr,s->name , NULL)) continue;
943 if (!next_token(&ptr,stype , NULL)) continue;
944 if (!next_token(&ptr,s->comment, NULL)) continue;
945 if (!next_token(&ptr,s->domain , NULL)) {
946 /* this allows us to cope with an old nmbd */
947 strcpy(s->domain,myworkgroup);
950 if (sscanf(stype,"%X",&s->type) != 1) {
951 DEBUG(4,("r:host file "));
955 /* Filter the servers/domains we return based on what was asked for. */
957 /* Check to see if we are being asked for a local list only. */
958 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
959 DEBUG(4,("r: local list only"));
963 /* doesn't match up: don't want it */
964 if (!(servertype & s->type)) {
965 DEBUG(4,("r:serv type "));
969 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
970 (s->type & SV_TYPE_DOMAIN_ENUM))
972 DEBUG(4,("s: dom mismatch "));
976 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
981 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
982 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
986 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
987 s->name, s->type, s->comment, s->domain));
989 s->server_added = True;
994 DEBUG(4,("%20s %8x %25s %15s\n",
995 s->name, s->type, s->comment, s->domain));
1004 /*******************************************************************
1005 fill in a server info structure
1006 ******************************************************************/
1007 static int fill_srv_info(struct srv_info_struct *service,
1008 int uLevel, char **buf, int *buflen,
1009 char **stringbuf, int *stringspace, char *baseaddr)
1018 case 0: struct_len = 16; break;
1019 case 1: struct_len = 26; break;
1029 len = strlen(service->comment)+1;
1033 if (buflen) *buflen = struct_len;
1034 if (stringspace) *stringspace = len;
1035 return struct_len + len;
1040 if (*buflen < struct_len) return -1;
1048 p2 = p + struct_len;
1049 l2 = *buflen - struct_len;
1051 if (!baseaddr) baseaddr = p;
1056 StrnCpy(p,service->name,15);
1060 StrnCpy(p,service->name,15);
1061 SIVAL(p,18,service->type);
1062 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1063 len += CopyAndAdvance(&p2,service->comment,&l2);
1069 *buf = p + struct_len;
1070 *buflen -= struct_len;
1083 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1085 return(strcmp(s1->name,s2->name));
1088 /****************************************************************************
1089 view list of servers available (or possibly domains). The info is
1090 extracted from lists saved by nmbd on the local host
1091 ****************************************************************************/
1092 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1093 int mdrcnt, int mprcnt, char **rdata,
1094 char **rparam, int *rdata_len, int *rparam_len)
1096 char *str1 = param+2;
1097 char *str2 = skip_string(str1,1);
1098 char *p = skip_string(str2,1);
1099 int uLevel = SVAL(p,0);
1100 int buf_len = SVAL(p,2);
1101 uint32 servertype = IVAL(p,4);
1103 int data_len, fixed_len, string_len;
1105 struct srv_info_struct *servers=NULL;
1106 int counted=0,total=0;
1109 BOOL domain_request;
1112 /* If someone sets all the bits they don't really mean to set
1113 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1116 if (servertype == SV_TYPE_ALL)
1117 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1119 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1120 any other bit (they may just set this bit on it's own) they
1121 want all the locally seen servers. However this bit can be
1122 set on its own so set the requested servers to be
1123 ALL - DOMAIN_ENUM. */
1125 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1126 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1128 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1129 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1133 if (!prefix_ok(str1,"WrLehD")) return False;
1134 if (!check_server_info(uLevel,str2)) return False;
1136 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1137 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1138 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1140 if (strcmp(str1, "WrLehDz") == 0) {
1141 StrnCpy(domain, p, sizeof(fstring)-1);
1143 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1146 if (lp_browse_list())
1147 total = get_server_info(servertype,&servers,domain);
1149 data_len = fixed_len = string_len = 0;
1152 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1155 char *lastname=NULL;
1157 for (i=0;i<total;i++)
1159 struct srv_info_struct *s = &servers[i];
1160 if (lastname && strequal(lastname,s->name)) continue;
1162 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1163 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1164 s->name, s->type, s->comment, s->domain));
1166 if (data_len <= buf_len) {
1169 string_len += s_len;
1176 *rdata_len = fixed_len + string_len;
1177 *rdata = REALLOC(*rdata,*rdata_len);
1178 bzero(*rdata,*rdata_len);
1180 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1186 char *lastname=NULL;
1187 int count2 = counted;
1188 for (i = 0; i < total && count2;i++)
1190 struct srv_info_struct *s = &servers[i];
1191 if (lastname && strequal(lastname,s->name)) continue;
1193 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1194 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1195 s->name, s->type, s->comment, s->domain));
1201 *rparam = REALLOC(*rparam,*rparam_len);
1202 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1204 SSVAL(*rparam,4,counted);
1205 SSVAL(*rparam,6,counted+missed);
1207 if (servers) free(servers);
1209 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1210 domain,uLevel,counted,counted+missed));
1216 /****************************************************************************
1217 get info about a share
1218 ****************************************************************************/
1219 static BOOL check_share_info(int uLevel, char* id)
1223 if (strcmp(id,"B13") != 0) return False;
1226 if (strcmp(id,"B13BWz") != 0) return False;
1229 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1232 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1234 default: return False;
1239 static int fill_share_info(int cnum, int snum, int uLevel,
1240 char** buf, int* buflen,
1241 char** stringbuf, int* stringspace, char* baseaddr)
1250 case 0: struct_len = 13; break;
1251 case 1: struct_len = 20; break;
1252 case 2: struct_len = 40; break;
1253 case 91: struct_len = 68; break;
1261 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1262 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1263 if (buflen) *buflen = struct_len;
1264 if (stringspace) *stringspace = len;
1265 return struct_len + len;
1270 if ((*buflen) < struct_len) return -1;
1278 p2 = p + struct_len;
1279 l2 = (*buflen) - struct_len;
1281 if (!baseaddr) baseaddr = p;
1283 StrnCpy(p,lp_servicename(snum),13);
1289 type = STYPE_DISKTREE;
1290 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1291 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1292 SSVAL(p,14,type); /* device type */
1293 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1294 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1299 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1300 SSVALS(p,22,-1); /* max uses */
1301 SSVAL(p,24,1); /* current uses */
1302 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1303 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1304 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1309 memset(p+40,0,SHPWLEN+2);
1321 (*buf) = p + struct_len;
1322 (*buflen) -= struct_len;
1324 (*stringspace) = l2;
1334 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1335 int mdrcnt,int mprcnt,
1336 char **rdata,char **rparam,
1337 int *rdata_len,int *rparam_len)
1339 char *str1 = param+2;
1340 char *str2 = skip_string(str1,1);
1341 char *netname = skip_string(str2,1);
1342 char *p = skip_string(netname,1);
1343 int uLevel = SVAL(p,0);
1344 int snum = find_service(netname);
1346 if (snum < 0) return False;
1348 /* check it's a supported varient */
1349 if (!prefix_ok(str1,"zWrLh")) return False;
1350 if (!check_share_info(uLevel,str2)) return False;
1352 *rdata = REALLOC(*rdata,mdrcnt);
1354 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1355 if (*rdata_len < 0) return False;
1358 *rparam = REALLOC(*rparam,*rparam_len);
1359 SSVAL(*rparam,0,NERR_Success);
1360 SSVAL(*rparam,2,0); /* converter word */
1361 SSVAL(*rparam,4,*rdata_len);
1366 /****************************************************************************
1367 view list of shares available
1368 ****************************************************************************/
1369 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1370 int mdrcnt,int mprcnt,
1371 char **rdata,char **rparam,
1372 int *rdata_len,int *rparam_len)
1374 char *str1 = param+2;
1375 char *str2 = skip_string(str1,1);
1376 char *p = skip_string(str2,1);
1377 int uLevel = SVAL(p,0);
1378 int buf_len = SVAL(p,2);
1380 int count=lp_numservices();
1381 int total=0,counted=0;
1383 int data_len, fixed_len, string_len;
1386 if (!prefix_ok(str1,"WrLeh")) return False;
1387 if (!check_share_info(uLevel,str2)) return False;
1389 data_len = fixed_len = string_len = 0;
1390 for (i=0;i<count;i++)
1391 if (lp_browseable(i) && lp_snum_ok(i))
1394 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1395 if (data_len <= buf_len)
1399 string_len += s_len;
1402 *rdata_len = fixed_len + string_len;
1403 *rdata = REALLOC(*rdata,*rdata_len);
1404 memset(*rdata,0,*rdata_len);
1406 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1410 for (i = 0; i < count;i++)
1411 if (lp_browseable(i) && lp_snum_ok(i))
1412 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1416 *rparam = REALLOC(*rparam,*rparam_len);
1417 SSVAL(*rparam,0,NERR_Success);
1419 SSVAL(*rparam,4,counted);
1420 SSVAL(*rparam,6,total);
1422 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1423 counted,total,uLevel,
1424 buf_len,*rdata_len,mdrcnt));
1430 /****************************************************************************
1431 get the time of day info
1432 ****************************************************************************/
1433 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1434 int mdrcnt,int mprcnt,
1435 char **rdata,char **rparam,
1436 int *rdata_len,int *rparam_len)
1440 *rparam = REALLOC(*rparam,*rparam_len);
1443 *rdata = REALLOC(*rdata,*rdata_len);
1445 SSVAL(*rparam,0,NERR_Success);
1446 SSVAL(*rparam,2,0); /* converter word */
1452 time_t unixdate = time(NULL);
1454 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1455 by NT in a "net time" operation,
1456 it seems to ignore the one below */
1458 /* the client expects to get localtime, not GMT, in this bit
1459 (I think, this needs testing) */
1460 t = LocalTime(&unixdate);
1462 SIVAL(p,4,0); /* msecs ? */
1463 CVAL(p,8) = t->tm_hour;
1464 CVAL(p,9) = t->tm_min;
1465 CVAL(p,10) = t->tm_sec;
1466 CVAL(p,11) = 0; /* hundredths of seconds */
1467 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1468 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1469 CVAL(p,16) = t->tm_mday;
1470 CVAL(p,17) = t->tm_mon + 1;
1471 SSVAL(p,18,1900+t->tm_year);
1472 CVAL(p,20) = t->tm_wday;
1479 /****************************************************************************
1480 set the user password
1481 ****************************************************************************/
1482 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1483 int mdrcnt,int mprcnt,
1484 char **rdata,char **rparam,
1485 int *rdata_len,int *rparam_len)
1487 char *p = skip_string(param+2,2);
1489 fstring pass1,pass2;
1493 p = skip_string(p,1);
1495 StrnCpy(pass1,p,16);
1496 StrnCpy(pass2,p+16,16);
1499 *rparam = REALLOC(*rparam,*rparam_len);
1503 SSVAL(*rparam,0,NERR_badpass);
1504 SSVAL(*rparam,2,0); /* converter word */
1506 DEBUG(3,("Set password for <%s>\n",user));
1508 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1509 chgpasswd(user,pass1,pass2))
1511 SSVAL(*rparam,0,NERR_Success);
1514 bzero(pass1,sizeof(fstring));
1515 bzero(pass2,sizeof(fstring));
1520 /****************************************************************************
1523 ****************************************************************************/
1524 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1525 int mdrcnt,int mprcnt,
1526 char **rdata,char **rparam,
1527 int *rdata_len,int *rparam_len)
1529 int function = SVAL(param,0);
1530 char *str1 = param+2;
1531 char *str2 = skip_string(str1,1);
1532 char *p = skip_string(str2,1);
1536 printjob_decode(SVAL(p,0), &snum, &jobid);
1538 /* check it's a supported varient */
1539 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1543 *rparam = REALLOC(*rparam,*rparam_len);
1547 SSVAL(*rparam,0,NERR_Success);
1549 if (snum >= 0 && VALID_SNUM(snum))
1551 print_queue_struct *queue=NULL;
1553 count = get_printqueue(snum,cnum,&queue,NULL);
1555 for (i=0;i<count;i++)
1556 if ((queue[i].job&0xFF) == jobid)
1559 case 81: /* delete */
1560 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1561 del_printqueue(cnum,snum,queue[i].job);
1563 case 82: /* pause */
1564 case 83: /* resume */
1565 DEBUG(3,("%s queue entry %d\n",
1566 (function==82?"pausing":"resuming"),queue[i].job));
1567 status_printjob(cnum,snum,queue[i].job,
1568 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1575 SSVAL(*rparam,0,NERR_JobNotFound);
1577 if (queue) free(queue);
1580 SSVAL(*rparam,2,0); /* converter word */
1585 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1586 int mdrcnt,int mprcnt,
1587 char **rdata,char **rparam,
1588 int *rdata_len,int *rparam_len)
1590 char *str1 = param+2;
1591 char *str2 = skip_string(str1,1);
1592 char *QueueName = skip_string(str2,1);
1595 /* check it's a supported varient */
1596 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1600 *rparam = REALLOC(*rparam,*rparam_len);
1604 SSVAL(*rparam,0,NERR_Success);
1605 SSVAL(*rparam,2,0); /* converter word */
1607 snum = lp_servicenumber(QueueName);
1608 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1609 int pnum = lp_servicenumber(PRINTERS_NAME);
1611 lp_add_printer(QueueName,pnum);
1612 snum = lp_servicenumber(QueueName);
1616 if (snum >= 0 && VALID_SNUM(snum)) {
1617 print_queue_struct *queue=NULL;
1621 count = get_printqueue(snum,cnum,&queue,NULL);
1622 for (i = 0; i < count; i++)
1623 del_printqueue(cnum,snum,queue[i].job);
1625 if (queue) free(queue);
1628 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1634 /****************************************************************************
1635 set the property of a print job (undocumented?)
1636 ? function = 0xb -> set name of print job
1637 ? function = 0x6 -> move print job up/down
1638 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1639 or <WWsTP> <WB21BB16B10zWWzDDz>
1640 ****************************************************************************/
1641 static int check_printjob_info(struct pack_desc* desc,
1642 int uLevel, char* id)
1644 desc->subformat = NULL;
1646 case 0: desc->format = "W"; break;
1647 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1648 case 2: desc->format = "WWzWWDDzz"; break;
1649 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1650 default: return False;
1652 if (strcmp(desc->format,id) != 0) return False;
1656 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1657 int mdrcnt,int mprcnt,
1658 char **rdata,char **rparam,
1659 int *rdata_len,int *rparam_len)
1661 struct pack_desc desc;
1662 char *str1 = param+2;
1663 char *str2 = skip_string(str1,1);
1664 char *p = skip_string(str2,1);
1666 int uLevel = SVAL(p,2);
1667 int function = SVAL(p,4); /* what is this ?? */
1671 printjob_decode(SVAL(p,0), &snum, &jobid);
1674 *rparam = REALLOC(*rparam,*rparam_len);
1678 /* check it's a supported varient */
1679 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1683 case 0x6: /* change job place in the queue, data gives the new place */
1684 if (snum >= 0 && VALID_SNUM(snum))
1686 print_queue_struct *queue=NULL;
1690 count = get_printqueue(snum,cnum,&queue,NULL);
1691 for (i=0;i<count;i++) /* find job */
1692 if ((queue[i].job&0xFF) == jobid) break;
1695 desc.errcode=NERR_JobNotFound;
1696 if (queue) free(queue);
1699 desc.errcode=NERR_Success;
1703 int place= SVAL(data,0);
1704 /* we currently have no way of doing this. Can any unix do it? */
1705 if (i < place) /* move down */;
1706 else if (i > place ) /* move up */;
1709 desc.errcode=NERR_notsupported; /* not yet supported */
1710 if (queue) free(queue);
1713 else desc.errcode=NERR_JobNotFound;
1715 case 0xb: /* change print job name, data gives the name */
1716 /* jobid, snum should be zero */
1723 if (issafe(*s)) name[l++] = *s;
1728 DEBUG(3,("Setting print name to %s\n",name));
1732 for (i=0;i<MAX_OPEN_FILES;i++)
1733 if (Files[i].open && Files[i].print_file)
1736 int fcnum = Files[i].cnum;
1740 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1741 !become_service(fcnum,True))
1744 if (sys_rename(Files[i].name,name) == 0)
1745 string_set(&Files[i].name,name);
1749 unbecome_root(True);
1751 desc.errcode=NERR_Success;
1754 default: /* not implemented */
1758 SSVALS(*rparam,0,desc.errcode);
1759 SSVAL(*rparam,2,0); /* converter word */
1765 /****************************************************************************
1766 get info about the server
1767 ****************************************************************************/
1768 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1769 int mdrcnt,int mprcnt,
1770 char **rdata,char **rparam,
1771 int *rdata_len,int *rparam_len)
1773 char *str1 = param+2;
1774 char *str2 = skip_string(str1,1);
1775 char *p = skip_string(str2,1);
1776 int uLevel = SVAL(p,0);
1780 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1782 /* check it's a supported varient */
1783 if (!prefix_ok(str1,"WrLh")) return False;
1786 if (strcmp(str2,"B16") != 0) return False;
1790 if (strcmp(str2,"B16BBDz") != 0) return False;
1794 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1799 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1804 if (strcmp(str2,"DN") != 0) return False;
1808 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1811 default: return False;
1814 *rdata_len = mdrcnt;
1815 *rdata = REALLOC(*rdata,*rdata_len);
1818 p2 = p + struct_len;
1820 StrnCpy(p,local_machine,16);
1826 struct srv_info_struct *servers=NULL;
1829 uint32 servertype= lp_default_server_announce();
1831 pstrcpy(comment,lp_serverstring());
1833 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1834 for (i=0;i<count;i++)
1835 if (strequal(servers[i].name,local_machine))
1837 servertype = servers[i].type;
1838 pstrcpy(comment,servers[i].comment);
1841 if (servers) free(servers);
1843 SCVAL(p,0,lp_major_announce_version());
1844 SCVAL(p,1,lp_minor_announce_version());
1845 SIVAL(p,2,servertype);
1847 if (mdrcnt == struct_len) {
1850 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1851 standard_sub(cnum,comment);
1852 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1853 p2 = skip_string(p2,1);
1858 return False; /* not yet implemented */
1861 *rdata_len = PTR_DIFF(p2,*rdata);
1864 *rparam = REALLOC(*rparam,*rparam_len);
1865 SSVAL(*rparam,0,NERR_Success);
1866 SSVAL(*rparam,2,0); /* converter word */
1867 SSVAL(*rparam,4,*rdata_len);
1873 /****************************************************************************
1874 get info about the server
1875 ****************************************************************************/
1876 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1877 int mdrcnt,int mprcnt,
1878 char **rdata,char **rparam,
1879 int *rdata_len,int *rparam_len)
1881 char *str1 = param+2;
1882 char *str2 = skip_string(str1,1);
1883 char *p = skip_string(str2,1);
1885 extern pstring sesssetup_user;
1886 int level = SVAL(p,0);
1888 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1891 *rparam = REALLOC(*rparam,*rparam_len);
1893 /* check it's a supported varient */
1894 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1897 *rdata_len = mdrcnt + 1024;
1898 *rdata = REALLOC(*rdata,*rdata_len);
1900 SSVAL(*rparam,0,NERR_Success);
1901 SSVAL(*rparam,2,0); /* converter word */
1907 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1908 strcpy(p2,local_machine);
1910 p2 = skip_string(p2,1);
1913 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1914 strcpy(p2,sesssetup_user);
1915 p2 = skip_string(p2,1);
1918 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1919 strcpy(p2,myworkgroup);
1921 p2 = skip_string(p2,1);
1924 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1925 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1928 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1929 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1930 p2 = skip_string(p2,1);
1933 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1935 p2 = skip_string(p2,1);
1938 *rdata_len = PTR_DIFF(p2,*rdata);
1940 SSVAL(*rparam,4,*rdata_len);
1945 /****************************************************************************
1946 get info about a user
1948 struct user_info_11 {
1949 char usri11_name[21]; 0-20
1951 char *usri11_comment; 22-25
1952 char *usri11_usr_comment; 26-29
1953 unsigned short usri11_priv; 30-31
1954 unsigned long usri11_auth_flags; 32-35
1955 long usri11_password_age; 36-39
1956 char *usri11_homedir; 40-43
1957 char *usri11_parms; 44-47
1958 long usri11_last_logon; 48-51
1959 long usri11_last_logoff; 52-55
1960 unsigned short usri11_bad_pw_count; 56-57
1961 unsigned short usri11_num_logons; 58-59
1962 char *usri11_logon_server; 60-63
1963 unsigned short usri11_country_code; 64-65
1964 char *usri11_workstations; 66-69
1965 unsigned long usri11_max_storage; 70-73
1966 unsigned short usri11_units_per_week; 74-75
1967 unsigned char *usri11_logon_hours; 76-79
1968 unsigned short usri11_code_page; 80-81
1973 usri11_name specifies the user name for which information is retireved
1975 usri11_pad aligns the next data structure element to a word boundary
1977 usri11_comment is a null terminated ASCII comment
1979 usri11_user_comment is a null terminated ASCII comment about the user
1981 usri11_priv specifies the level of the privilege assigned to the user.
1982 The possible values are:
1984 Name Value Description
1985 USER_PRIV_GUEST 0 Guest privilege
1986 USER_PRIV_USER 1 User privilege
1987 USER_PRV_ADMIN 2 Administrator privilege
1989 usri11_auth_flags specifies the account operator privileges. The
1990 possible values are:
1992 Name Value Description
1993 AF_OP_PRINT 0 Print operator
1996 Leach, Naik [Page 28]
\r\f
1999 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2002 AF_OP_COMM 1 Communications operator
2003 AF_OP_SERVER 2 Server operator
2004 AF_OP_ACCOUNTS 3 Accounts operator
2007 usri11_password_age specifies how many seconds have elapsed since the
2008 password was last changed.
2010 usri11_home_dir points to a null terminated ASCII string that contains
2011 the path name of the user's home directory.
2013 usri11_parms points to a null terminated ASCII string that is set
2014 aside for use by applications.
2016 usri11_last_logon specifies the time when the user last logged on.
2017 This value is stored as the number of seconds elapsed since
2018 00:00:00, January 1, 1970.
2020 usri11_last_logoff specifies the time when the user last logged off.
2021 This value is stored as the number of seconds elapsed since
2022 00:00:00, January 1, 1970. A value of 0 means the last logoff
2025 usri11_bad_pw_count specifies the number of incorrect passwords
2026 entered since the last successful logon.
2028 usri11_log1_num_logons specifies the number of times this user has
2029 logged on. A value of -1 means the number of logons is unknown.
2031 usri11_logon_server points to a null terminated ASCII string that
2032 contains the name of the server to which logon requests are sent.
2033 A null string indicates logon requests should be sent to the
2036 usri11_country_code specifies the country code for the user's language
2039 usri11_workstations points to a null terminated ASCII string that
2040 contains the names of workstations the user may log on from.
2041 There may be up to 8 workstations, with the names separated by
2042 commas. A null strings indicates there are no restrictions.
2044 usri11_max_storage specifies the maximum amount of disk space the user
2045 can occupy. A value of 0xffffffff indicates there are no
2048 usri11_units_per_week specifies the equal number of time units into
2049 which a week is divided. This value must be equal to 168.
2051 usri11_logon_hours points to a 21 byte (168 bits) string that
2052 specifies the time during which the user can log on. Each bit
2053 represents one unique hour in a week. The first bit (bit 0, word
2054 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2058 Leach, Naik [Page 29]
\r\f
2061 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2064 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2065 are no restrictions.
2067 usri11_code_page specifies the code page for the user's language of
2070 All of the pointers in this data structure need to be treated
2071 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2072 to be ignored. The converter word returned in the parameters section
2073 needs to be subtracted from the lower 16 bits to calculate an offset
2074 into the return buffer where this ASCII string resides.
2076 There is no auxiliary data in the response.
2078 ****************************************************************************/
2080 #define usri11_name 0
2081 #define usri11_pad 21
2082 #define usri11_comment 22
2083 #define usri11_usr_comment 26
2084 #define usri11_full_name 30
2085 #define usri11_priv 34
2086 #define usri11_auth_flags 36
2087 #define usri11_password_age 40
2088 #define usri11_homedir 44
2089 #define usri11_parms 48
2090 #define usri11_last_logon 52
2091 #define usri11_last_logoff 56
2092 #define usri11_bad_pw_count 60
2093 #define usri11_num_logons 62
2094 #define usri11_logon_server 64
2095 #define usri11_country_code 68
2096 #define usri11_workstations 70
2097 #define usri11_max_storage 74
2098 #define usri11_units_per_week 78
2099 #define usri11_logon_hours 80
2100 #define usri11_code_page 84
2101 #define usri11_end 86
2103 #define USER_PRIV_GUEST 0
2104 #define USER_PRIV_USER 1
2105 #define USER_PRIV_ADMIN 2
2107 #define AF_OP_PRINT 0
2108 #define AF_OP_COMM 1
2109 #define AF_OP_SERVER 2
2110 #define AF_OP_ACCOUNTS 3
2113 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2114 int mdrcnt,int mprcnt,
2115 char **rdata,char **rparam,
2116 int *rdata_len,int *rparam_len)
2118 char *str1 = param+2;
2119 char *str2 = skip_string(str1,1);
2120 char *UserName = skip_string(str2,1);
2121 char *p = skip_string(UserName,1);
2122 int uLevel = SVAL(p,0);
2125 /* get NIS home of a previously validated user - simeon */
2126 user_struct *vuser = get_valid_user_struct(vuid);
2127 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2130 *rparam = REALLOC(*rparam,*rparam_len);
2132 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2134 /* check it's a supported variant */
2135 if (strcmp(str1,"zWrLh") != 0) return False;
2138 case 0: p2 = "B21"; break;
2139 case 1: p2 = "B21BB16DWzzWz"; break;
2140 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2141 case 10: p2 = "B21Bzzz"; break;
2142 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2143 default: return False;
2146 if (strcmp(p2,str2) != 0) return False;
2148 *rdata_len = mdrcnt + 1024;
2149 *rdata = REALLOC(*rdata,*rdata_len);
2151 SSVAL(*rparam,0,NERR_Success);
2152 SSVAL(*rparam,2,0); /* converter word */
2155 p2 = p + usri11_end;
2158 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2162 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2167 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2168 strcpy(p2,"Comment");
2169 p2 = skip_string(p2,1);
2171 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2172 strcpy(p2,"UserComment");
2173 p2 = skip_string(p2,1);
2175 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2176 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2177 strcpy(p2,vuser->real_name); /* simeon */
2178 p2 = skip_string(p2,1);
2181 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2183 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2184 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2185 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2186 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2187 strcpy(p2, lp_logon_path());
2188 p2 = skip_string(p2,1);
2189 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2191 p2 = skip_string(p2,1);
2192 SIVAL(p,usri11_last_logon,0); /* last logon */
2193 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2194 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2195 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2196 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2198 p2 = skip_string(p2,1);
2199 SSVAL(p,usri11_country_code,0); /* country code */
2201 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2203 p2 = skip_string(p2,1);
2205 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2206 SSVAL(p,usri11_units_per_week,168); /* units per week */
2207 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2209 /* a simple way to get logon hours at all times. */
2211 SCVAL(p2,21,0); /* fix zero termination */
2212 p2 = skip_string(p2,1);
2214 SSVAL(p,usri11_code_page,0); /* code page */
2216 if (uLevel == 1 || uLevel == 2)
2218 memset(p+22,' ',16); /* password */
2219 SIVALS(p,38,-1); /* password age */
2221 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2222 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2223 strcpy(p2,lp_logon_path());
2224 p2 = skip_string(p2,1);
2225 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2227 SSVAL(p,52,0); /* flags */
2228 SIVAL(p,54,0); /* script_path */
2231 SIVAL(p,60,0); /* auth_flags */
2232 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2233 strcpy(p2,vuser->real_name); /* simeon */
2234 p2 = skip_string(p2,1);
2235 SIVAL(p,68,0); /* urs_comment */
2236 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2238 p2 = skip_string(p2,1);
2239 SIVAL(p,76,0); /* workstations */
2240 SIVAL(p,80,0); /* last_logon */
2241 SIVAL(p,84,0); /* last_logoff */
2242 SIVALS(p,88,-1); /* acct_expires */
2243 SIVALS(p,92,-1); /* max_storage */
2244 SSVAL(p,96,168); /* units_per_week */
2245 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2248 SSVALS(p,102,-1); /* bad_pw_count */
2249 SSVALS(p,104,-1); /* num_logons */
2250 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2251 strcpy(p2,"\\\\%L");
2252 standard_sub_basic(p2);
2253 p2 = skip_string(p2,1);
2254 SSVAL(p,110,49); /* country_code */
2255 SSVAL(p,112,860); /* code page */
2259 *rdata_len = PTR_DIFF(p2,*rdata);
2261 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2266 /*******************************************************************
2267 get groups that a user is a member of
2268 ******************************************************************/
2269 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2270 int mdrcnt,int mprcnt,
2271 char **rdata,char **rparam,
2272 int *rdata_len,int *rparam_len)
2274 char *str1 = param+2;
2275 char *str2 = skip_string(str1,1);
2276 char *UserName = skip_string(str2,1);
2277 char *p = skip_string(UserName,1);
2278 int uLevel = SVAL(p,0);
2283 *rparam = REALLOC(*rparam,*rparam_len);
2285 /* check it's a supported varient */
2286 if (strcmp(str1,"zWrLeh") != 0) return False;
2288 case 0: p2 = "B21"; break;
2289 default: return False;
2291 if (strcmp(p2,str2) != 0) return False;
2293 *rdata_len = mdrcnt + 1024;
2294 *rdata = REALLOC(*rdata,*rdata_len);
2296 SSVAL(*rparam,0,NERR_Success);
2297 SSVAL(*rparam,2,0); /* converter word */
2301 /* XXXX we need a real SAM database some day */
2302 strcpy(p,"Users"); p += 21; count++;
2303 strcpy(p,"Domain Users"); p += 21; count++;
2304 strcpy(p,"Guests"); p += 21; count++;
2305 strcpy(p,"Domain Guests"); p += 21; count++;
2307 *rdata_len = PTR_DIFF(p,*rdata);
2309 SSVAL(*rparam,4,count); /* is this right?? */
2310 SSVAL(*rparam,6,count); /* is this right?? */
2316 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2317 int mdrcnt,int mprcnt,
2318 char **rdata,char **rparam,
2319 int *rdata_len,int *rparam_len)
2321 char *str1 = param+2;
2322 char *str2 = skip_string(str1,1);
2323 char *p = skip_string(str2,1);
2325 struct pack_desc desc;
2332 bzero(&desc,sizeof(desc));
2334 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2336 /* check it's a supported varient */
2337 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2338 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2339 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2341 desc.buflen = mdrcnt;
2342 desc.subformat = NULL;
2345 if (init_package(&desc,1,0))
2347 PACKI(&desc,"W",0); /* code */
2348 PACKS(&desc,"B21",name); /* eff. name */
2349 PACKS(&desc,"B",""); /* pad */
2351 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2352 PACKI(&desc,"D",0); /* auth flags XXX */
2353 PACKI(&desc,"W",0); /* num logons */
2354 PACKI(&desc,"W",0); /* bad pw count */
2355 PACKI(&desc,"D",0); /* last logon */
2356 PACKI(&desc,"D",-1); /* last logoff */
2357 PACKI(&desc,"D",-1); /* logoff time */
2358 PACKI(&desc,"D",-1); /* kickoff time */
2359 PACKI(&desc,"D",0); /* password age */
2360 PACKI(&desc,"D",0); /* password can change */
2361 PACKI(&desc,"D",-1); /* password must change */
2364 strcpy(mypath,"\\\\");
2365 strcat(mypath,local_machine);
2367 PACKS(&desc,"z",mypath); /* computer */
2369 PACKS(&desc,"z",myworkgroup);/* domain */
2371 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2372 /* made sure all macros are fully substituted and available */
2373 logon_script = lp_logon_script();
2374 standard_sub( cnum, logon_script );
2375 PACKS(&desc,"z", logon_script); /* script path */
2376 /* End of JHT mods */
2378 PACKI(&desc,"D",0x00000000); /* reserved */
2381 *rdata_len = desc.usedlen;
2383 *rparam = REALLOC(*rparam,*rparam_len);
2384 SSVALS(*rparam,0,desc.errcode);
2386 SSVAL(*rparam,4,desc.neededlen);
2388 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2393 /****************************************************************************
2394 api_WAccessGetUserPerms
2395 ****************************************************************************/
2396 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2397 int mdrcnt,int mprcnt,
2398 char **rdata,char **rparam,
2399 int *rdata_len,int *rparam_len)
2401 char *str1 = param+2;
2402 char *str2 = skip_string(str1,1);
2403 char *user = skip_string(str2,1);
2404 char *resource = skip_string(user,1);
2406 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2408 /* check it's a supported varient */
2409 if (strcmp(str1,"zzh") != 0) return False;
2410 if (strcmp(str2,"") != 0) return False;
2413 *rparam = REALLOC(*rparam,*rparam_len);
2414 SSVALS(*rparam,0,0); /* errorcode */
2415 SSVAL(*rparam,2,0); /* converter word */
2416 SSVAL(*rparam,4,0x7f); /* permission flags */
2421 /****************************************************************************
2422 api_WPrintJobEnumerate
2423 ****************************************************************************/
2424 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2425 int mdrcnt,int mprcnt,
2426 char **rdata,char **rparam,
2427 int *rdata_len,int *rparam_len)
2429 char *str1 = param+2;
2430 char *str2 = skip_string(str1,1);
2431 char *p = skip_string(str2,1);
2437 struct pack_desc desc;
2438 print_queue_struct *queue=NULL;
2439 print_status_struct status;
2444 bzero(&desc,sizeof(desc));
2445 bzero(&status,sizeof(status));
2447 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2449 /* check it's a supported varient */
2450 if (strcmp(str1,"WWrLh") != 0) return False;
2451 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2453 printjob_decode(SVAL(p,0), &snum, &job);
2455 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2457 count = get_printqueue(snum,cnum,&queue,&status);
2458 for (i = 0; i < count; i++) {
2459 if ((queue[i].job & 0xFF) == job) break;
2461 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2463 desc.buflen = mdrcnt;
2465 if (init_package(&desc,1,0)) {
2467 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2468 *rdata_len = desc.usedlen;
2471 desc.errcode = NERR_JobNotFound;
2477 *rparam = REALLOC(*rparam,*rparam_len);
2478 SSVALS(*rparam,0,desc.errcode);
2480 SSVAL(*rparam,4,desc.neededlen);
2482 if (queue) free(queue);
2484 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2488 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2489 int mdrcnt,int mprcnt,
2490 char **rdata,char **rparam,
2491 int *rdata_len,int *rparam_len)
2493 char *str1 = param+2;
2494 char *str2 = skip_string(str1,1);
2495 char *p = skip_string(str2,1);
2501 struct pack_desc desc;
2502 print_queue_struct *queue=NULL;
2503 print_status_struct status;
2505 bzero(&desc,sizeof(desc));
2506 bzero(&status,sizeof(status));
2508 p = skip_string(p,1);
2512 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2514 /* check it's a supported varient */
2515 if (strcmp(str1,"zWrLeh") != 0) return False;
2516 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2517 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2519 snum = lp_servicenumber(name);
2520 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2521 int pnum = lp_servicenumber(PRINTERS_NAME);
2523 lp_add_printer(name,pnum);
2524 snum = lp_servicenumber(name);
2528 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2530 count = get_printqueue(snum,cnum,&queue,&status);
2531 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2533 desc.buflen = mdrcnt;
2535 if (init_package(&desc,count,0)) {
2537 for (i = 0; i < count; i++) {
2538 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2539 if (desc.errcode == NERR_Success) succnt = i+1;
2543 *rdata_len = desc.usedlen;
2546 *rparam = REALLOC(*rparam,*rparam_len);
2547 SSVALS(*rparam,0,desc.errcode);
2549 SSVAL(*rparam,4,succnt);
2550 SSVAL(*rparam,6,count);
2552 if (queue) free(queue);
2554 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2558 static int check_printdest_info(struct pack_desc* desc,
2559 int uLevel, char* id)
2561 desc->subformat = NULL;
2563 case 0: desc->format = "B9"; break;
2564 case 1: desc->format = "B9B21WWzW"; break;
2565 case 2: desc->format = "z"; break;
2566 case 3: desc->format = "zzzWWzzzWW"; break;
2567 default: return False;
2569 if (strcmp(desc->format,id) != 0) return False;
2573 static void fill_printdest_info(int cnum, int snum, int uLevel,
2574 struct pack_desc* desc)
2577 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2578 buf[sizeof(buf)-1] = 0;
2581 PACKS(desc,"B9",buf); /* szName */
2583 PACKS(desc,"B21",""); /* szUserName */
2584 PACKI(desc,"W",0); /* uJobId */
2585 PACKI(desc,"W",0); /* fsStatus */
2586 PACKS(desc,"z",""); /* pszStatus */
2587 PACKI(desc,"W",0); /* time */
2590 if (uLevel == 2 || uLevel == 3) {
2591 PACKS(desc,"z",buf); /* pszPrinterName */
2593 PACKS(desc,"z",""); /* pszUserName */
2594 PACKS(desc,"z",""); /* pszLogAddr */
2595 PACKI(desc,"W",0); /* uJobId */
2596 PACKI(desc,"W",0); /* fsStatus */
2597 PACKS(desc,"z",""); /* pszStatus */
2598 PACKS(desc,"z",""); /* pszComment */
2599 PACKS(desc,"z","NULL"); /* pszDrivers */
2600 PACKI(desc,"W",0); /* time */
2601 PACKI(desc,"W",0); /* pad1 */
2606 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2607 int mdrcnt,int mprcnt,
2608 char **rdata,char **rparam,
2609 int *rdata_len,int *rparam_len)
2611 char *str1 = param+2;
2612 char *str2 = skip_string(str1,1);
2613 char *p = skip_string(str2,1);
2614 char* PrinterName = p;
2616 struct pack_desc desc;
2619 bzero(&desc,sizeof(desc));
2621 p = skip_string(p,1);
2625 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2627 /* check it's a supported varient */
2628 if (strcmp(str1,"zWrLh") != 0) return False;
2629 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2631 snum = lp_servicenumber(PrinterName);
2632 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2633 int pnum = lp_servicenumber(PRINTERS_NAME);
2635 lp_add_printer(PrinterName,pnum);
2636 snum = lp_servicenumber(PrinterName);
2642 desc.errcode = NERR_DestNotFound;
2646 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2648 desc.buflen = mdrcnt;
2649 if (init_package(&desc,1,0)) {
2650 fill_printdest_info(cnum,snum,uLevel,&desc);
2652 *rdata_len = desc.usedlen;
2656 *rparam = REALLOC(*rparam,*rparam_len);
2657 SSVALS(*rparam,0,desc.errcode);
2659 SSVAL(*rparam,4,desc.neededlen);
2661 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2665 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2666 int mdrcnt,int mprcnt,
2667 char **rdata,char **rparam,
2668 int *rdata_len,int *rparam_len)
2670 char *str1 = param+2;
2671 char *str2 = skip_string(str1,1);
2672 char *p = skip_string(str2,1);
2676 struct pack_desc desc;
2677 int services = lp_numservices();
2679 bzero(&desc,sizeof(desc));
2684 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2686 /* check it's a supported varient */
2687 if (strcmp(str1,"WrLeh") != 0) return False;
2688 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2691 for (i = 0; i < services; i++)
2692 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2695 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2697 desc.buflen = mdrcnt;
2698 if (init_package(&desc,queuecnt,0)) {
2701 for (i = 0; i < services; i++) {
2702 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2703 fill_printdest_info(cnum,i,uLevel,&desc);
2705 if (desc.errcode == NERR_Success) succnt = n;
2710 *rdata_len = desc.usedlen;
2713 *rparam = REALLOC(*rparam,*rparam_len);
2714 SSVALS(*rparam,0,desc.errcode);
2716 SSVAL(*rparam,4,succnt);
2717 SSVAL(*rparam,6,queuecnt);
2719 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2723 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2724 int mdrcnt,int mprcnt,
2725 char **rdata,char **rparam,
2726 int *rdata_len,int *rparam_len)
2728 char *str1 = param+2;
2729 char *str2 = skip_string(str1,1);
2730 char *p = skip_string(str2,1);
2733 struct pack_desc desc;
2735 bzero(&desc,sizeof(desc));
2740 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2742 /* check it's a supported varient */
2743 if (strcmp(str1,"WrLeh") != 0) return False;
2744 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2746 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2748 desc.buflen = mdrcnt;
2749 if (init_package(&desc,1,0)) {
2750 PACKS(&desc,"B41","NULL");
2753 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2755 *rdata_len = desc.usedlen;
2758 *rparam = REALLOC(*rparam,*rparam_len);
2759 SSVALS(*rparam,0,desc.errcode);
2761 SSVAL(*rparam,4,succnt);
2764 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2768 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2769 int mdrcnt,int mprcnt,
2770 char **rdata,char **rparam,
2771 int *rdata_len,int *rparam_len)
2773 char *str1 = param+2;
2774 char *str2 = skip_string(str1,1);
2775 char *p = skip_string(str2,1);
2778 struct pack_desc desc;
2780 bzero(&desc,sizeof(desc));
2785 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2787 /* check it's a supported varient */
2788 if (strcmp(str1,"WrLeh") != 0) return False;
2789 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2791 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2793 desc.buflen = mdrcnt;
2795 if (init_package(&desc,1,0)) {
2796 PACKS(&desc,"B13","lpd");
2799 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2801 *rdata_len = desc.usedlen;
2804 *rparam = REALLOC(*rparam,*rparam_len);
2805 SSVALS(*rparam,0,desc.errcode);
2807 SSVAL(*rparam,4,succnt);
2810 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2814 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2815 int mdrcnt,int mprcnt,
2816 char **rdata,char **rparam,
2817 int *rdata_len,int *rparam_len)
2819 char *str1 = param+2;
2820 char *str2 = skip_string(str1,1);
2821 char *p = skip_string(str2,1);
2824 struct pack_desc desc;
2826 bzero(&desc,sizeof(desc));
2831 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2833 /* check it's a supported varient */
2834 if (strcmp(str1,"WrLeh") != 0) return False;
2835 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2837 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2838 bzero(&desc,sizeof(desc));
2840 desc.buflen = mdrcnt;
2842 if (init_package(&desc,1,0)) {
2843 PACKS(&desc,"B13","lp0");
2846 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2848 *rdata_len = desc.usedlen;
2851 *rparam = REALLOC(*rparam,*rparam_len);
2852 SSVALS(*rparam,0,desc.errcode);
2854 SSVAL(*rparam,4,succnt);
2857 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2868 } api_fd_commands [] =
2871 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2872 { "SetNmdPpHndState", "srvsvc", 1, api_LsarpcSNPHS },
2873 { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS },
2874 { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP },
2875 { "TransactNmPipe", "srvsvc", 0x26, api_srvsvcTNP },
2876 { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP },
2878 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2879 { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
2881 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2884 /****************************************************************************
2885 handle remote api calls delivered to a named pipe already opened.
2886 ****************************************************************************/
2887 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2888 uint16 *setup,char *data,char *params,
2889 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2892 char *rparam = NULL;
2897 BOOL bind_req = False;
2904 DEBUG(5,("api_fd_reply\n"));
2905 /* First find out the name of this file. */
2908 DEBUG(0,("Unexpected named pipe transaction.\n"));
2912 /* Get the file handle and hence the file name. */
2914 subcommand = setup[0];
2915 if (fd >= 0 && fd < MAX_OPEN_FILES)
2917 pstrcpy(pipe_name, Files[fd].name);
2922 DEBUG(1,("api_fd_reply: INVALID FILE HANDLE: %x\n", fd));
2925 DEBUG(3,("Got API command %d on pipe %s (fd %x)",
2926 subcommand, pipe_name, fd));
2927 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2928 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2930 for (i = 0; api_fd_commands[i].name; i++)
2932 if (strequal(api_fd_commands[i].pipename, pipe_name) &&
2933 api_fd_commands[i].subcommand == subcommand &&
2934 api_fd_commands[i].fn)
2936 DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
2941 rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2942 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2945 if (api_fd_commands[i].subcommand != -1)
2948 char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
2950 if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
2954 char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
2956 if ((bind_req = (p != NULL)))
2959 make_rpc_hdr_ba(&hdr_ba,
2960 hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
2961 api_fd_commands[i].pipename,
2963 &(hdr_rb.transfer));
2965 p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
2967 rdata_len = PTR_DIFF(p, rdata);
2969 make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
2971 p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
2973 reply = (p != NULL);
2981 DEBUG(10,("calling api_fd_command\n"));
2983 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2984 &rdata,&rparam,&rdata_len,&rparam_len);
2985 DEBUG(10,("called api_fd_command\n"));
2988 if (rdata_len > mdrcnt || rparam_len > mprcnt)
2990 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2991 &rdata,&rparam,&rdata_len,&rparam_len);
2995 /* if we get False back then it's actually unsupported */
2997 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2998 &rdata,&rparam,&rdata_len,&rparam_len);
3000 /* now send the reply */
3001 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3013 /****************************************************************************
3014 the buffer was too small
3015 ****************************************************************************/
3016 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3017 int mdrcnt,int mprcnt,
3018 char **rdata,char **rparam,
3019 int *rdata_len,int *rparam_len)
3021 *rparam_len = MIN(*rparam_len,mprcnt);
3022 *rparam = REALLOC(*rparam,*rparam_len);
3026 SSVAL(*rparam,0,NERR_BufTooSmall);
3028 DEBUG(3,("Supplied buffer too small in API command\n"));
3034 /****************************************************************************
3035 the request is not supported
3036 ****************************************************************************/
3037 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3038 int mdrcnt,int mprcnt,
3039 char **rdata,char **rparam,
3040 int *rdata_len,int *rparam_len)
3043 *rparam = REALLOC(*rparam,*rparam_len);
3047 SSVAL(*rparam,0,NERR_notsupported);
3048 SSVAL(*rparam,2,0); /* converter word */
3050 DEBUG(3,("Unsupported API command\n"));
3064 } api_commands[] = {
3065 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3066 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3067 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3068 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3069 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3070 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3071 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3072 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3073 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3074 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3075 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3076 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3077 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3078 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3079 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3080 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3081 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3082 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3083 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3084 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3085 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3086 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3087 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3088 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3089 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3090 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3093 /****************************************************************************
3094 handle remote api calls
3095 ****************************************************************************/
3096 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3097 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3099 int api_command = SVAL(params,0);
3101 char *rparam = NULL;
3107 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3108 api_command,params+2,skip_string(params+2,1),
3109 tdscnt,tpscnt,mdrcnt,mprcnt));
3111 for (i=0;api_commands[i].name;i++)
3112 if (api_commands[i].id == api_command && api_commands[i].fn)
3114 DEBUG(3,("Doing %s\n",api_commands[i].name));
3118 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3119 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3121 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3122 &rdata,&rparam,&rdata_len,&rparam_len);
3125 if (rdata_len > mdrcnt ||
3126 rparam_len > mprcnt)
3128 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3129 &rdata,&rparam,&rdata_len,&rparam_len);
3133 /* if we get False back then it's actually unsupported */
3135 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3136 &rdata,&rparam,&rdata_len,&rparam_len);
3140 /* now send the reply */
3141 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3151 /****************************************************************************
3152 handle named pipe commands
3153 ****************************************************************************/
3154 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3155 uint16 *setup,char *data,char *params,
3156 int suwcnt,int tdscnt,int tpscnt,
3157 int msrcnt,int mdrcnt,int mprcnt)
3159 DEBUG(3,("named pipe command on <%s> name\n", name));
3161 if (strequal(name,"LANMAN"))
3163 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3166 if (strlen(name) < 1)
3168 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3173 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3180 /****************************************************************************
3182 ****************************************************************************/
3183 int reply_trans(char *inbuf,char *outbuf)
3187 char *data=NULL,*params=NULL;
3191 int cnum = SVAL(inbuf,smb_tid);
3192 uint16 vuid = SVAL(inbuf,smb_uid);
3194 int tpscnt = SVAL(inbuf,smb_vwv0);
3195 int tdscnt = SVAL(inbuf,smb_vwv1);
3196 int mprcnt = SVAL(inbuf,smb_vwv2);
3197 int mdrcnt = SVAL(inbuf,smb_vwv3);
3198 int msrcnt = CVAL(inbuf,smb_vwv4);
3199 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3200 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3201 int pscnt = SVAL(inbuf,smb_vwv9);
3202 int psoff = SVAL(inbuf,smb_vwv10);
3203 int dscnt = SVAL(inbuf,smb_vwv11);
3204 int dsoff = SVAL(inbuf,smb_vwv12);
3205 int suwcnt = CVAL(inbuf,smb_vwv13);
3207 bzero(name, sizeof(name));
3208 fstrcpy(name,smb_buf(inbuf));
3210 if (dscnt > tdscnt || pscnt > tpscnt) {
3211 exit_server("invalid trans parameters\n");
3216 data = (char *)malloc(tdscnt);
3217 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3221 params = (char *)malloc(tpscnt);
3222 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3228 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3229 for (i=0;i<suwcnt;i++)
3230 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3234 if (pscnt < tpscnt || dscnt < tdscnt)
3236 /* We need to send an interim response then receive the rest
3237 of the parameter/data bytes */
3238 outsize = set_message(outbuf,0,0,True);
3240 send_smb(Client,outbuf);
3243 /* receive the rest of the trans packet */
3244 while (pscnt < tpscnt || dscnt < tdscnt)
3246 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3248 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3249 CVAL(inbuf, smb_com) != SMBtrans)
3251 DEBUG(2,("Invalid secondary trans2 packet\n"));
3252 if (params) free(params);
3253 if (data) free(data);
3254 if (setup) free(setup);
3255 return(ERROR(ERRSRV,ERRerror));
3260 tpscnt = SVAL(inbuf,smb_vwv0);
3261 tdscnt = SVAL(inbuf,smb_vwv1);
3263 pcnt = SVAL(inbuf,smb_vwv2);
3264 poff = SVAL(inbuf,smb_vwv3);
3265 pdisp = SVAL(inbuf,smb_vwv4);
3267 dcnt = SVAL(inbuf,smb_vwv5);
3268 doff = SVAL(inbuf,smb_vwv6);
3269 ddisp = SVAL(inbuf,smb_vwv7);
3274 if (dscnt > tdscnt || pscnt > tpscnt) {
3275 exit_server("invalid trans parameters\n");
3279 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3281 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3285 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3287 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3289 DEBUG(5,("calling named_pipe\n"));
3290 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3291 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3295 DEBUG(3,("invalid pipe name\n"));
3300 if (data) free(data);
3301 if (params) free(params);
3302 if (setup) free(setup);
3304 if (close_on_completion)
3305 close_cnum(cnum,vuid);
3311 return(ERROR(ERRSRV,ERRnosupport));