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 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
148 /* if you don't want Net Monitor to decode your packets, do this!!! */
149 align = ((this_lparam+1)%4);
151 align = (this_lparam%4);
154 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
156 memcpy(smb_buf(outbuf),param,this_lparam);
158 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
160 SSVAL(outbuf,smb_vwv0,lparam);
161 SSVAL(outbuf,smb_vwv1,ldata);
162 SSVAL(outbuf,smb_vwv3,this_lparam);
163 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
164 SSVAL(outbuf,smb_vwv5,0);
165 SSVAL(outbuf,smb_vwv6,this_ldata);
166 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
167 SSVAL(outbuf,smb_vwv8,0);
168 SSVAL(outbuf,smb_vwv9,lsetup);
169 for (i=0;i<lsetup;i++)
170 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
173 send_smb(Client,outbuf);
175 tot_data = this_ldata;
176 tot_param = this_lparam;
178 while (tot_data < ldata || tot_param < lparam)
180 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
181 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
183 align = (this_lparam%4);
185 set_message(outbuf,10,this_ldata+this_lparam+align,False);
187 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
189 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
191 SSVAL(outbuf,smb_vwv3,this_lparam);
192 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
193 SSVAL(outbuf,smb_vwv5,tot_param);
194 SSVAL(outbuf,smb_vwv6,this_ldata);
195 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
196 SSVAL(outbuf,smb_vwv8,tot_data);
197 SSVAL(outbuf,smb_vwv9,0);
200 send_smb(Client,outbuf);
202 tot_data += this_ldata;
203 tot_param += this_lparam;
208 char* format; /* formatstring for structure */
209 char* subformat; /* subformat for structure */
210 char* base; /* baseaddress of buffer */
211 int buflen; /* remaining size for fixed part; on init: length of base */
212 int subcount; /* count of substructures */
213 char* structbuf; /* pointer into buffer for remaining fixed part */
214 int stringlen; /* remaining size for variable part */
215 char* stringbuf; /* pointer into buffer for remaining variable part */
216 int neededlen; /* total needed size */
217 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
218 char* curpos; /* current position; pointer into format or subformat */
222 static int get_counter(char** p)
225 if (!p || !(*p)) return(1);
226 if (!isdigit(**p)) return 1;
230 n = 10 * n + (i - '0');
237 static int getlen(char* p)
243 case 'W': /* word (2 byte) */
246 case 'N': /* count of substructures (word) at end */
249 case 'D': /* double word (4 byte) */
250 case 'z': /* offset to zero terminated string (4 byte) */
251 case 'l': /* offset to user data (4 byte) */
254 case 'b': /* offset to data (with counter) (4 byte) */
258 case 'B': /* byte (with optional counter) */
259 n += get_counter(&p);
266 static BOOL init_package(struct pack_desc* p, int count, int subcount)
271 if (!p->format || !p->base) return(False);
273 i = count * getlen(p->format);
274 if (p->subformat) i += subcount * getlen(p->subformat);
275 p->structbuf = p->base;
279 p->curpos = p->format;
282 p->errcode = NERR_BufTooSmall;
285 p->errcode = NERR_Success;
288 p->stringbuf = p->base + i;
290 return(p->errcode == NERR_Success);
294 static int package(struct pack_desc* p, ...)
297 static int package(va_alist)
303 int needed=0, stringneeded;
305 int is_string=0, stringused;
312 p = va_arg(args,struct pack_desc *);
317 p->curpos = p->format;
319 p->curpos = p->subformat;
324 str = va_arg(args,char*);
325 if (strncmp(str,p->curpos,strlen(str)) != 0) {
326 DEBUG(2,("type error in package: %s instead of %*s\n",str,
327 strlen(str),p->curpos));
337 if (!p->curpos) return(0);
339 switch( *p->curpos++ ) {
340 case 'W': /* word (2 byte) */
342 temp = va_arg(args,int);
343 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
345 case 'N': /* count of substructures (word) at end */
347 p->subcount = va_arg(args,int);
348 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
350 case 'D': /* double word (4 byte) */
352 temp = va_arg(args,int);
353 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
355 case 'B': /* byte (with optional counter) */
356 needed = get_counter(&p->curpos);
358 char *s = va_arg(args,char*);
359 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
362 case 'z': /* offset to zero terminated string (4 byte) */
363 str = va_arg(args,char*);
364 stringneeded = (str ? strlen(str)+1 : 0);
367 case 'l': /* offset to user data (4 byte) */
368 str = va_arg(args,char*);
369 stringneeded = va_arg(args,int);
372 case 'b': /* offset to data (with counter) (4 byte) */
373 str = va_arg(args,char*);
374 stringneeded = get_counter(&p->curpos);
379 if (stringneeded >= 0) {
381 if (p->buflen >= needed) {
382 stringused = stringneeded;
383 if (stringused > p->stringlen) {
384 stringused = (is_string ? p->stringlen : 0);
385 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
388 SIVAL(p->structbuf,0,0);
390 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
391 memcpy(p->stringbuf,str?str:"",stringused);
392 if (is_string) p->stringbuf[stringused-1] = '\0';
393 p->stringbuf += stringused;
394 p->stringlen -= stringused;
395 p->usedlen += stringused;
398 p->neededlen += stringneeded;
400 p->neededlen += needed;
401 if (p->buflen >= needed) {
402 p->structbuf += needed;
404 p->usedlen += needed;
407 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
413 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
414 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
416 #define PACK(desc,t,v) package(desc,v)
417 #define PACKl(desc,t,v,l) package(desc,v,l)
420 static void PACKI(struct pack_desc* desc,char *t,int v)
425 static void PACKS(struct pack_desc* desc,char *t,char *v)
431 /****************************************************************************
433 ****************************************************************************/
435 static void PackDriverData(struct pack_desc* desc)
437 char drivdata[4+4+32];
438 SIVAL(drivdata,0,sizeof drivdata); /* cb */
439 SIVAL(drivdata,4,1000); /* lVersion */
440 memset(drivdata+8,0,32); /* szDeviceName */
441 strcpy(drivdata+8,"NULL");
442 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
445 static int check_printq_info(struct pack_desc* desc,
446 int uLevel, char *id1, char *id2)
448 desc->subformat = NULL;
451 desc->format = "B13";
454 desc->format = "B13BWWWzzzzzWW";
457 desc->format = "B13BWWWzzzzzWN";
458 desc->subformat = "WB21BB16B10zWWzDDz";
461 desc->format = "zWWWWzzzzWWzzl";
464 desc->format = "zWWWWzzzzWNzzl";
465 desc->subformat = "WWzWWDDzz";
471 desc->format = "WzzzzzzzzN";
472 desc->subformat = "z";
474 default: return False;
476 if (strcmp(desc->format,id1) != 0) return False;
477 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
481 static void fill_printjob_info(int cnum, int snum, int uLevel,
482 struct pack_desc* desc,
483 print_queue_struct* queue, int n)
485 time_t t = queue->time;
487 /* the client expects localtime */
490 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
492 PACKS(desc,"B21",queue->user); /* szUserName */
493 PACKS(desc,"B",""); /* pad */
494 PACKS(desc,"B16",""); /* szNotifyName */
495 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
496 PACKS(desc,"z",""); /* pszParms */
497 PACKI(desc,"W",n+1); /* uPosition */
498 PACKI(desc,"W",queue->status); /* fsStatus */
499 PACKS(desc,"z",""); /* pszStatus */
500 PACKI(desc,"D",t); /* ulSubmitted */
501 PACKI(desc,"D",queue->size); /* ulSize */
502 PACKS(desc,"z",queue->file); /* pszComment */
504 if (uLevel == 2 || uLevel == 3) {
505 PACKI(desc,"W",queue->priority); /* uPriority */
506 PACKS(desc,"z",queue->user); /* pszUserName */
507 PACKI(desc,"W",n+1); /* uPosition */
508 PACKI(desc,"W",queue->status); /* fsStatus */
509 PACKI(desc,"D",t); /* ulSubmitted */
510 PACKI(desc,"D",queue->size); /* ulSize */
511 PACKS(desc,"z","Samba"); /* pszComment */
512 PACKS(desc,"z",queue->file); /* pszDocument */
514 PACKS(desc,"z",""); /* pszNotifyName */
515 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
516 PACKS(desc,"z",""); /* pszParms */
517 PACKS(desc,"z",""); /* pszStatus */
518 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
519 PACKS(desc,"z","lpd"); /* pszQProcName */
520 PACKS(desc,"z",""); /* pszQProcParms */
521 PACKS(desc,"z","NULL"); /* pszDriverName */
522 PackDriverData(desc); /* pDriverData */
523 PACKS(desc,"z",""); /* pszPrinterName */
528 static void fill_printq_info(int cnum, int snum, int uLevel,
529 struct pack_desc* desc,
530 int count, print_queue_struct* queue,
531 print_status_struct* status)
536 PACKS(desc,"B13",SERVICE(snum));
541 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
545 if (uLevel == 1 || uLevel == 2) {
546 PACKS(desc,"B",""); /* alignment */
547 PACKI(desc,"W",5); /* priority */
548 PACKI(desc,"W",0); /* start time */
549 PACKI(desc,"W",0); /* until time */
550 PACKS(desc,"z",""); /* pSepFile */
551 PACKS(desc,"z","lpd"); /* pPrProc */
552 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
553 PACKS(desc,"z",""); /* pParms */
555 PACKS(desc,"z","UNKNOWN PRINTER");
556 PACKI(desc,"W",LPSTAT_ERROR);
558 else if (!status || !status->message[0]) {
559 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
560 PACKI(desc,"W",LPSTAT_OK); /* status */
562 PACKS(desc,"z",status->message);
563 PACKI(desc,"W",status->status); /* status */
565 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
567 if (uLevel == 3 || uLevel == 4) {
568 PACKI(desc,"W",5); /* uPriority */
569 PACKI(desc,"W",0); /* uStarttime */
570 PACKI(desc,"W",0); /* uUntiltime */
571 PACKI(desc,"W",5); /* pad1 */
572 PACKS(desc,"z",""); /* pszSepFile */
573 PACKS(desc,"z","WinPrint"); /* pszPrProc */
574 PACKS(desc,"z",""); /* pszParms */
575 if (!status || !status->message[0]) {
576 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
577 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
579 PACKS(desc,"z",status->message); /* pszComment */
580 PACKI(desc,"W",status->status); /* fsStatus */
582 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
583 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
584 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
585 PackDriverData(desc); /* pDriverData */
587 if (uLevel == 2 || uLevel == 4) {
589 for (i=0;i<count;i++)
590 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
595 pstring tok,driver,short_name;
600 strcpy(fname,lp_driverfile());
604 DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
607 p=(char *)malloc(8192*sizeof(char));
608 bzero(p, 8192*sizeof(char));
611 /* lookup the long printer driver name in the file description */
612 while (f && !feof(f) && !ok)
616 next_token(&p,tok,":");
617 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
622 next_token(&p,short_name,":");
623 next_token(&p,driver,":");
625 PACKI(desc,"W",0x0400); /* don't know */
626 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
630 PACKS(desc,"z",driver); /* Driver Name */
631 PACKS(desc,"z",short_name); /* short printer name */
632 DEBUG(3,("Driver:%s:\n",driver));
633 DEBUG(3,("short name:%s:\n",short_name));
642 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
643 PACKS(desc,"z","EMF");
646 PACKS(desc,"z",driver); /* driver name */
649 PACKI(desc,"N",count); /* number of files to copy */
650 for (i=0;i<count;i++)
652 next_token(&p,tok,",");
653 PACKS(desc,"z",tok); /* driver files to copy */
654 DEBUG(3,("file:%s:\n",tok));
659 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
662 /* This function returns the number of file for a given driver */
663 int get_printerdrivernumber(int snum)
671 strcpy(fname,lp_driverfile());
673 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
676 DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
680 p=(char *)malloc(8192*sizeof(char));
681 q=p; /* need it to free memory because p change ! */
683 /* lookup the long printer driver name in the file description */
684 while (!feof(f) && !ok)
687 next_token(&p,tok,":");
688 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
693 next_token(&p,tok,":"); /* short name */
694 next_token(&p,tok,":"); /* driver name */
695 /* count the number of files */
696 while (next_token(&p,tok,","))
705 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
706 int mdrcnt,int mprcnt,
707 char **rdata,char **rparam,
708 int *rdata_len,int *rparam_len)
710 char *str1 = param+2;
711 char *str2 = skip_string(str1,1);
712 char *p = skip_string(str2,1);
718 struct pack_desc desc;
719 print_queue_struct *queue=NULL;
720 print_status_struct status;
722 bzero(&status,sizeof(status));
723 bzero(&desc,sizeof(desc));
725 p = skip_string(p,1);
730 /* remove any trailing username */
731 if ((p = strchr(QueueName,'%'))) *p = 0;
733 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
735 /* check it's a supported varient */
736 if (!prefix_ok(str1,"zWrLh")) return False;
737 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
739 snum = lp_servicenumber(QueueName);
740 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
741 int pnum = lp_servicenumber(PRINTERS_NAME);
743 lp_add_printer(QueueName,pnum);
744 snum = lp_servicenumber(QueueName);
748 if (snum < 0 || !VALID_SNUM(snum)) return(False);
752 count = get_printerdrivernumber(snum);
753 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
756 count = get_printqueue(snum,cnum,&queue,&status);
758 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
760 desc.buflen = mdrcnt;
761 if (init_package(&desc,1,count)) {
762 desc.subcount = count;
763 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
766 *rdata_len = desc.usedlen;
769 *rparam = REALLOC(*rparam,*rparam_len);
770 SSVALS(*rparam,0,desc.errcode);
772 SSVAL(*rparam,4,desc.neededlen);
774 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
776 if (queue) free(queue);
782 /****************************************************************************
783 view list of all print jobs on all queues
784 ****************************************************************************/
785 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
786 int mdrcnt, int mprcnt,
787 char **rdata, char** rparam,
788 int *rdata_len, int *rparam_len)
790 char *param_format = param+2;
791 char *output_format1 = skip_string(param_format,1);
792 char *p = skip_string(output_format1,1);
793 int uLevel = SVAL(p,0);
794 char *output_format2 = p + 4;
795 int services = lp_numservices();
797 struct pack_desc desc;
798 print_queue_struct **queue = NULL;
799 print_status_struct *status = NULL;
800 int* subcntarr = NULL;
801 int queuecnt, subcnt=0, succnt=0;
803 bzero(&desc,sizeof(desc));
805 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
807 if (!prefix_ok(param_format,"WrLeh")) return False;
808 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
811 for (i = 0; i < services; i++)
812 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
815 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
816 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
817 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
818 memset(status,0,queuecnt*sizeof(print_status_struct));
819 subcntarr = (int*)malloc(queuecnt*sizeof(int));
822 for (i = 0; i < services; i++)
823 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
824 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
825 subcnt += subcntarr[n];
829 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
831 desc.buflen = mdrcnt;
833 if (init_package(&desc,queuecnt,subcnt)) {
836 for (i = 0; i < services; i++)
837 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
838 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
840 if (desc.errcode == NERR_Success) succnt = n;
844 if (subcntarr) free(subcntarr);
846 *rdata_len = desc.usedlen;
848 *rparam = REALLOC(*rparam,*rparam_len);
849 SSVALS(*rparam,0,desc.errcode);
851 SSVAL(*rparam,4,succnt);
852 SSVAL(*rparam,6,queuecnt);
854 for (i = 0; i < queuecnt; i++) {
855 if (queue && queue[i]) free(queue[i]);
858 if (queue) free(queue);
859 if (status) free(status);
864 /****************************************************************************
865 get info level for a server list query
866 ****************************************************************************/
867 static BOOL check_server_info(int uLevel, char* id)
871 if (strcmp(id,"B16") != 0) return False;
874 if (strcmp(id,"B16BBDz") != 0) return False;
882 struct srv_info_struct
892 /*******************************************************************
893 get server info lists from the files saved by nmbd. Return the
895 ******************************************************************/
896 static int get_server_info(uint32 servertype,
897 struct srv_info_struct **servers,
905 BOOL local_list_only;
907 pstrcpy(fname,lp_lockdir());
908 trim_string(fname,NULL,"/");
910 strcat(fname,SERVER_LIST);
912 f = fopen(fname,"r");
915 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
919 /* request for everything is code for request all servers */
920 if (servertype == SV_TYPE_ALL)
921 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
923 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
925 DEBUG(4,("Servertype search: %8x\n",servertype));
930 struct srv_info_struct *s;
935 fgets(line,sizeof(line)-1,f);
936 if (!*line) continue;
938 if (count == alloced) {
940 (*servers) = (struct srv_info_struct *)
941 Realloc(*servers,sizeof(**servers)*alloced);
942 if (!(*servers)) return(0);
943 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
945 s = &(*servers)[count];
947 if (!next_token(&ptr,s->name , NULL)) continue;
948 if (!next_token(&ptr,stype , NULL)) continue;
949 if (!next_token(&ptr,s->comment, NULL)) continue;
950 if (!next_token(&ptr,s->domain , NULL)) {
951 /* this allows us to cope with an old nmbd */
952 strcpy(s->domain,myworkgroup);
955 if (sscanf(stype,"%X",&s->type) != 1) {
956 DEBUG(4,("r:host file "));
960 /* Filter the servers/domains we return based on what was asked for. */
962 /* Check to see if we are being asked for a local list only. */
963 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
964 DEBUG(4,("r: local list only"));
968 /* doesn't match up: don't want it */
969 if (!(servertype & s->type)) {
970 DEBUG(4,("r:serv type "));
974 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
975 (s->type & SV_TYPE_DOMAIN_ENUM))
977 DEBUG(4,("s: dom mismatch "));
981 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
986 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
987 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
991 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
992 s->name, s->type, s->comment, s->domain));
994 s->server_added = True;
999 DEBUG(4,("%20s %8x %25s %15s\n",
1000 s->name, s->type, s->comment, s->domain));
1009 /*******************************************************************
1010 fill in a server info structure
1011 ******************************************************************/
1012 static int fill_srv_info(struct srv_info_struct *service,
1013 int uLevel, char **buf, int *buflen,
1014 char **stringbuf, int *stringspace, char *baseaddr)
1023 case 0: struct_len = 16; break;
1024 case 1: struct_len = 26; break;
1034 len = strlen(service->comment)+1;
1038 if (buflen) *buflen = struct_len;
1039 if (stringspace) *stringspace = len;
1040 return struct_len + len;
1045 if (*buflen < struct_len) return -1;
1053 p2 = p + struct_len;
1054 l2 = *buflen - struct_len;
1056 if (!baseaddr) baseaddr = p;
1061 StrnCpy(p,service->name,15);
1065 StrnCpy(p,service->name,15);
1066 SIVAL(p,18,service->type);
1067 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1068 len += CopyAndAdvance(&p2,service->comment,&l2);
1074 *buf = p + struct_len;
1075 *buflen -= struct_len;
1088 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1090 return(strcmp(s1->name,s2->name));
1093 /****************************************************************************
1094 view list of servers available (or possibly domains). The info is
1095 extracted from lists saved by nmbd on the local host
1096 ****************************************************************************/
1097 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1098 int mdrcnt, int mprcnt, char **rdata,
1099 char **rparam, int *rdata_len, int *rparam_len)
1101 char *str1 = param+2;
1102 char *str2 = skip_string(str1,1);
1103 char *p = skip_string(str2,1);
1104 int uLevel = SVAL(p,0);
1105 int buf_len = SVAL(p,2);
1106 uint32 servertype = IVAL(p,4);
1108 int data_len, fixed_len, string_len;
1110 struct srv_info_struct *servers=NULL;
1111 int counted=0,total=0;
1114 BOOL domain_request;
1117 /* If someone sets all the bits they don't really mean to set
1118 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1121 if (servertype == SV_TYPE_ALL)
1122 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1124 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1125 any other bit (they may just set this bit on it's own) they
1126 want all the locally seen servers. However this bit can be
1127 set on its own so set the requested servers to be
1128 ALL - DOMAIN_ENUM. */
1130 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1131 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1133 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1134 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1138 if (!prefix_ok(str1,"WrLehD")) return False;
1139 if (!check_server_info(uLevel,str2)) return False;
1141 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1142 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1143 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1145 if (strcmp(str1, "WrLehDz") == 0) {
1146 StrnCpy(domain, p, sizeof(fstring)-1);
1148 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1151 if (lp_browse_list())
1152 total = get_server_info(servertype,&servers,domain);
1154 data_len = fixed_len = string_len = 0;
1157 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1160 char *lastname=NULL;
1162 for (i=0;i<total;i++)
1164 struct srv_info_struct *s = &servers[i];
1165 if (lastname && strequal(lastname,s->name)) continue;
1167 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1168 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1169 s->name, s->type, s->comment, s->domain));
1171 if (data_len <= buf_len) {
1174 string_len += s_len;
1181 *rdata_len = fixed_len + string_len;
1182 *rdata = REALLOC(*rdata,*rdata_len);
1183 bzero(*rdata,*rdata_len);
1185 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1191 char *lastname=NULL;
1192 int count2 = counted;
1193 for (i = 0; i < total && count2;i++)
1195 struct srv_info_struct *s = &servers[i];
1196 if (lastname && strequal(lastname,s->name)) continue;
1198 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1199 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1200 s->name, s->type, s->comment, s->domain));
1206 *rparam = REALLOC(*rparam,*rparam_len);
1207 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1209 SSVAL(*rparam,4,counted);
1210 SSVAL(*rparam,6,counted+missed);
1212 if (servers) free(servers);
1214 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1215 domain,uLevel,counted,counted+missed));
1221 /****************************************************************************
1222 get info about a share
1223 ****************************************************************************/
1224 static BOOL check_share_info(int uLevel, char* id)
1228 if (strcmp(id,"B13") != 0) return False;
1231 if (strcmp(id,"B13BWz") != 0) return False;
1234 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1237 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1239 default: return False;
1244 static int fill_share_info(int cnum, int snum, int uLevel,
1245 char** buf, int* buflen,
1246 char** stringbuf, int* stringspace, char* baseaddr)
1255 case 0: struct_len = 13; break;
1256 case 1: struct_len = 20; break;
1257 case 2: struct_len = 40; break;
1258 case 91: struct_len = 68; break;
1266 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1267 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1268 if (buflen) *buflen = struct_len;
1269 if (stringspace) *stringspace = len;
1270 return struct_len + len;
1275 if ((*buflen) < struct_len) return -1;
1283 p2 = p + struct_len;
1284 l2 = (*buflen) - struct_len;
1286 if (!baseaddr) baseaddr = p;
1288 StrnCpy(p,lp_servicename(snum),13);
1294 type = STYPE_DISKTREE;
1295 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1296 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1297 SSVAL(p,14,type); /* device type */
1298 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1299 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1304 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1305 SSVALS(p,22,-1); /* max uses */
1306 SSVAL(p,24,1); /* current uses */
1307 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1308 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1309 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1314 memset(p+40,0,SHPWLEN+2);
1326 (*buf) = p + struct_len;
1327 (*buflen) -= struct_len;
1329 (*stringspace) = l2;
1339 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1340 int mdrcnt,int mprcnt,
1341 char **rdata,char **rparam,
1342 int *rdata_len,int *rparam_len)
1344 char *str1 = param+2;
1345 char *str2 = skip_string(str1,1);
1346 char *netname = skip_string(str2,1);
1347 char *p = skip_string(netname,1);
1348 int uLevel = SVAL(p,0);
1349 int snum = find_service(netname);
1351 if (snum < 0) return False;
1353 /* check it's a supported varient */
1354 if (!prefix_ok(str1,"zWrLh")) return False;
1355 if (!check_share_info(uLevel,str2)) return False;
1357 *rdata = REALLOC(*rdata,mdrcnt);
1359 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1360 if (*rdata_len < 0) return False;
1363 *rparam = REALLOC(*rparam,*rparam_len);
1364 SSVAL(*rparam,0,NERR_Success);
1365 SSVAL(*rparam,2,0); /* converter word */
1366 SSVAL(*rparam,4,*rdata_len);
1371 /****************************************************************************
1372 view list of shares available
1373 ****************************************************************************/
1374 static BOOL api_RNetShareEnum(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 *p = skip_string(str2,1);
1382 int uLevel = SVAL(p,0);
1383 int buf_len = SVAL(p,2);
1385 int count=lp_numservices();
1386 int total=0,counted=0;
1388 int data_len, fixed_len, string_len;
1391 if (!prefix_ok(str1,"WrLeh")) return False;
1392 if (!check_share_info(uLevel,str2)) return False;
1394 data_len = fixed_len = string_len = 0;
1395 for (i=0;i<count;i++)
1396 if (lp_browseable(i) && lp_snum_ok(i))
1399 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1400 if (data_len <= buf_len)
1404 string_len += s_len;
1407 *rdata_len = fixed_len + string_len;
1408 *rdata = REALLOC(*rdata,*rdata_len);
1409 memset(*rdata,0,*rdata_len);
1411 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1415 for (i = 0; i < count;i++)
1416 if (lp_browseable(i) && lp_snum_ok(i))
1417 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1421 *rparam = REALLOC(*rparam,*rparam_len);
1422 SSVAL(*rparam,0,NERR_Success);
1424 SSVAL(*rparam,4,counted);
1425 SSVAL(*rparam,6,total);
1427 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1428 counted,total,uLevel,
1429 buf_len,*rdata_len,mdrcnt));
1435 /****************************************************************************
1436 get the time of day info
1437 ****************************************************************************/
1438 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1439 int mdrcnt,int mprcnt,
1440 char **rdata,char **rparam,
1441 int *rdata_len,int *rparam_len)
1445 *rparam = REALLOC(*rparam,*rparam_len);
1448 *rdata = REALLOC(*rdata,*rdata_len);
1450 SSVAL(*rparam,0,NERR_Success);
1451 SSVAL(*rparam,2,0); /* converter word */
1457 time_t unixdate = time(NULL);
1459 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1460 by NT in a "net time" operation,
1461 it seems to ignore the one below */
1463 /* the client expects to get localtime, not GMT, in this bit
1464 (I think, this needs testing) */
1465 t = LocalTime(&unixdate);
1467 SIVAL(p,4,0); /* msecs ? */
1468 CVAL(p,8) = t->tm_hour;
1469 CVAL(p,9) = t->tm_min;
1470 CVAL(p,10) = t->tm_sec;
1471 CVAL(p,11) = 0; /* hundredths of seconds */
1472 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1473 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1474 CVAL(p,16) = t->tm_mday;
1475 CVAL(p,17) = t->tm_mon + 1;
1476 SSVAL(p,18,1900+t->tm_year);
1477 CVAL(p,20) = t->tm_wday;
1484 /****************************************************************************
1485 set the user password
1486 ****************************************************************************/
1487 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1488 int mdrcnt,int mprcnt,
1489 char **rdata,char **rparam,
1490 int *rdata_len,int *rparam_len)
1492 char *p = skip_string(param+2,2);
1494 fstring pass1,pass2;
1498 p = skip_string(p,1);
1500 StrnCpy(pass1,p,16);
1501 StrnCpy(pass2,p+16,16);
1504 *rparam = REALLOC(*rparam,*rparam_len);
1508 SSVAL(*rparam,0,NERR_badpass);
1509 SSVAL(*rparam,2,0); /* converter word */
1511 DEBUG(3,("Set password for <%s>\n",user));
1513 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1514 chgpasswd(user,pass1,pass2))
1516 SSVAL(*rparam,0,NERR_Success);
1519 bzero(pass1,sizeof(fstring));
1520 bzero(pass2,sizeof(fstring));
1525 /****************************************************************************
1528 ****************************************************************************/
1529 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1530 int mdrcnt,int mprcnt,
1531 char **rdata,char **rparam,
1532 int *rdata_len,int *rparam_len)
1534 int function = SVAL(param,0);
1535 char *str1 = param+2;
1536 char *str2 = skip_string(str1,1);
1537 char *p = skip_string(str2,1);
1541 printjob_decode(SVAL(p,0), &snum, &jobid);
1543 /* check it's a supported varient */
1544 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1548 *rparam = REALLOC(*rparam,*rparam_len);
1552 SSVAL(*rparam,0,NERR_Success);
1554 if (snum >= 0 && VALID_SNUM(snum))
1556 print_queue_struct *queue=NULL;
1558 count = get_printqueue(snum,cnum,&queue,NULL);
1560 for (i=0;i<count;i++)
1561 if ((queue[i].job&0xFF) == jobid)
1564 case 81: /* delete */
1565 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1566 del_printqueue(cnum,snum,queue[i].job);
1568 case 82: /* pause */
1569 case 83: /* resume */
1570 DEBUG(3,("%s queue entry %d\n",
1571 (function==82?"pausing":"resuming"),queue[i].job));
1572 status_printjob(cnum,snum,queue[i].job,
1573 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1580 SSVAL(*rparam,0,NERR_JobNotFound);
1582 if (queue) free(queue);
1585 SSVAL(*rparam,2,0); /* converter word */
1590 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1591 int mdrcnt,int mprcnt,
1592 char **rdata,char **rparam,
1593 int *rdata_len,int *rparam_len)
1595 char *str1 = param+2;
1596 char *str2 = skip_string(str1,1);
1597 char *QueueName = skip_string(str2,1);
1600 /* check it's a supported varient */
1601 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1605 *rparam = REALLOC(*rparam,*rparam_len);
1609 SSVAL(*rparam,0,NERR_Success);
1610 SSVAL(*rparam,2,0); /* converter word */
1612 snum = lp_servicenumber(QueueName);
1613 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1614 int pnum = lp_servicenumber(PRINTERS_NAME);
1616 lp_add_printer(QueueName,pnum);
1617 snum = lp_servicenumber(QueueName);
1621 if (snum >= 0 && VALID_SNUM(snum)) {
1622 print_queue_struct *queue=NULL;
1626 count = get_printqueue(snum,cnum,&queue,NULL);
1627 for (i = 0; i < count; i++)
1628 del_printqueue(cnum,snum,queue[i].job);
1630 if (queue) free(queue);
1633 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1639 /****************************************************************************
1640 set the property of a print job (undocumented?)
1641 ? function = 0xb -> set name of print job
1642 ? function = 0x6 -> move print job up/down
1643 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1644 or <WWsTP> <WB21BB16B10zWWzDDz>
1645 ****************************************************************************/
1646 static int check_printjob_info(struct pack_desc* desc,
1647 int uLevel, char* id)
1649 desc->subformat = NULL;
1651 case 0: desc->format = "W"; break;
1652 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1653 case 2: desc->format = "WWzWWDDzz"; break;
1654 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1655 default: return False;
1657 if (strcmp(desc->format,id) != 0) return False;
1661 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1662 int mdrcnt,int mprcnt,
1663 char **rdata,char **rparam,
1664 int *rdata_len,int *rparam_len)
1666 struct pack_desc desc;
1667 char *str1 = param+2;
1668 char *str2 = skip_string(str1,1);
1669 char *p = skip_string(str2,1);
1671 int uLevel = SVAL(p,2);
1672 int function = SVAL(p,4); /* what is this ?? */
1676 printjob_decode(SVAL(p,0), &snum, &jobid);
1679 *rparam = REALLOC(*rparam,*rparam_len);
1683 /* check it's a supported varient */
1684 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1688 case 0x6: /* change job place in the queue, data gives the new place */
1689 if (snum >= 0 && VALID_SNUM(snum))
1691 print_queue_struct *queue=NULL;
1695 count = get_printqueue(snum,cnum,&queue,NULL);
1696 for (i=0;i<count;i++) /* find job */
1697 if ((queue[i].job&0xFF) == jobid) break;
1700 desc.errcode=NERR_JobNotFound;
1701 if (queue) free(queue);
1704 desc.errcode=NERR_Success;
1708 int place= SVAL(data,0);
1709 /* we currently have no way of doing this. Can any unix do it? */
1710 if (i < place) /* move down */;
1711 else if (i > place ) /* move up */;
1714 desc.errcode=NERR_notsupported; /* not yet supported */
1715 if (queue) free(queue);
1718 else desc.errcode=NERR_JobNotFound;
1720 case 0xb: /* change print job name, data gives the name */
1721 /* jobid, snum should be zero */
1728 if (issafe(*s)) name[l++] = *s;
1733 DEBUG(3,("Setting print name to %s\n",name));
1737 for (i=0;i<MAX_OPEN_FILES;i++)
1738 if (Files[i].open && Files[i].print_file)
1741 int fcnum = Files[i].cnum;
1745 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1746 !become_service(fcnum,True))
1749 if (sys_rename(Files[i].name,name) == 0)
1750 string_set(&Files[i].name,name);
1754 unbecome_root(True);
1756 desc.errcode=NERR_Success;
1759 default: /* not implemented */
1763 SSVALS(*rparam,0,desc.errcode);
1764 SSVAL(*rparam,2,0); /* converter word */
1770 /****************************************************************************
1771 get info about the server
1772 ****************************************************************************/
1773 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1774 int mdrcnt,int mprcnt,
1775 char **rdata,char **rparam,
1776 int *rdata_len,int *rparam_len)
1778 char *str1 = param+2;
1779 char *str2 = skip_string(str1,1);
1780 char *p = skip_string(str2,1);
1781 int uLevel = SVAL(p,0);
1785 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1787 /* check it's a supported varient */
1788 if (!prefix_ok(str1,"WrLh")) return False;
1791 if (strcmp(str2,"B16") != 0) return False;
1795 if (strcmp(str2,"B16BBDz") != 0) return False;
1799 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1804 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1809 if (strcmp(str2,"DN") != 0) return False;
1813 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1816 default: return False;
1819 *rdata_len = mdrcnt;
1820 *rdata = REALLOC(*rdata,*rdata_len);
1823 p2 = p + struct_len;
1825 StrnCpy(p,local_machine,16);
1831 struct srv_info_struct *servers=NULL;
1834 uint32 servertype= lp_default_server_announce();
1836 pstrcpy(comment,lp_serverstring());
1838 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1839 for (i=0;i<count;i++)
1840 if (strequal(servers[i].name,local_machine))
1842 servertype = servers[i].type;
1843 pstrcpy(comment,servers[i].comment);
1846 if (servers) free(servers);
1848 SCVAL(p,0,lp_major_announce_version());
1849 SCVAL(p,1,lp_minor_announce_version());
1850 SIVAL(p,2,servertype);
1852 if (mdrcnt == struct_len) {
1855 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1856 standard_sub(cnum,comment);
1857 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1858 p2 = skip_string(p2,1);
1863 return False; /* not yet implemented */
1866 *rdata_len = PTR_DIFF(p2,*rdata);
1869 *rparam = REALLOC(*rparam,*rparam_len);
1870 SSVAL(*rparam,0,NERR_Success);
1871 SSVAL(*rparam,2,0); /* converter word */
1872 SSVAL(*rparam,4,*rdata_len);
1878 /****************************************************************************
1879 get info about the server
1880 ****************************************************************************/
1881 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1882 int mdrcnt,int mprcnt,
1883 char **rdata,char **rparam,
1884 int *rdata_len,int *rparam_len)
1886 char *str1 = param+2;
1887 char *str2 = skip_string(str1,1);
1888 char *p = skip_string(str2,1);
1890 extern pstring sesssetup_user;
1891 int level = SVAL(p,0);
1893 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1896 *rparam = REALLOC(*rparam,*rparam_len);
1898 /* check it's a supported varient */
1899 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1902 *rdata_len = mdrcnt + 1024;
1903 *rdata = REALLOC(*rdata,*rdata_len);
1905 SSVAL(*rparam,0,NERR_Success);
1906 SSVAL(*rparam,2,0); /* converter word */
1912 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1913 strcpy(p2,local_machine);
1915 p2 = skip_string(p2,1);
1918 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1919 strcpy(p2,sesssetup_user);
1920 p2 = skip_string(p2,1);
1923 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1924 strcpy(p2,myworkgroup);
1926 p2 = skip_string(p2,1);
1929 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1930 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1933 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1934 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1935 p2 = skip_string(p2,1);
1938 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1940 p2 = skip_string(p2,1);
1943 *rdata_len = PTR_DIFF(p2,*rdata);
1945 SSVAL(*rparam,4,*rdata_len);
1950 /****************************************************************************
1951 get info about a user
1953 struct user_info_11 {
1954 char usri11_name[21]; 0-20
1956 char *usri11_comment; 22-25
1957 char *usri11_usr_comment; 26-29
1958 unsigned short usri11_priv; 30-31
1959 unsigned long usri11_auth_flags; 32-35
1960 long usri11_password_age; 36-39
1961 char *usri11_homedir; 40-43
1962 char *usri11_parms; 44-47
1963 long usri11_last_logon; 48-51
1964 long usri11_last_logoff; 52-55
1965 unsigned short usri11_bad_pw_count; 56-57
1966 unsigned short usri11_num_logons; 58-59
1967 char *usri11_logon_server; 60-63
1968 unsigned short usri11_country_code; 64-65
1969 char *usri11_workstations; 66-69
1970 unsigned long usri11_max_storage; 70-73
1971 unsigned short usri11_units_per_week; 74-75
1972 unsigned char *usri11_logon_hours; 76-79
1973 unsigned short usri11_code_page; 80-81
1978 usri11_name specifies the user name for which information is retireved
1980 usri11_pad aligns the next data structure element to a word boundary
1982 usri11_comment is a null terminated ASCII comment
1984 usri11_user_comment is a null terminated ASCII comment about the user
1986 usri11_priv specifies the level of the privilege assigned to the user.
1987 The possible values are:
1989 Name Value Description
1990 USER_PRIV_GUEST 0 Guest privilege
1991 USER_PRIV_USER 1 User privilege
1992 USER_PRV_ADMIN 2 Administrator privilege
1994 usri11_auth_flags specifies the account operator privileges. The
1995 possible values are:
1997 Name Value Description
1998 AF_OP_PRINT 0 Print operator
2001 Leach, Naik [Page 28]
\r\f
2004 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2007 AF_OP_COMM 1 Communications operator
2008 AF_OP_SERVER 2 Server operator
2009 AF_OP_ACCOUNTS 3 Accounts operator
2012 usri11_password_age specifies how many seconds have elapsed since the
2013 password was last changed.
2015 usri11_home_dir points to a null terminated ASCII string that contains
2016 the path name of the user's home directory.
2018 usri11_parms points to a null terminated ASCII string that is set
2019 aside for use by applications.
2021 usri11_last_logon specifies the time when the user last logged on.
2022 This value is stored as the number of seconds elapsed since
2023 00:00:00, January 1, 1970.
2025 usri11_last_logoff specifies the time when the user last logged off.
2026 This value is stored as the number of seconds elapsed since
2027 00:00:00, January 1, 1970. A value of 0 means the last logoff
2030 usri11_bad_pw_count specifies the number of incorrect passwords
2031 entered since the last successful logon.
2033 usri11_log1_num_logons specifies the number of times this user has
2034 logged on. A value of -1 means the number of logons is unknown.
2036 usri11_logon_server points to a null terminated ASCII string that
2037 contains the name of the server to which logon requests are sent.
2038 A null string indicates logon requests should be sent to the
2041 usri11_country_code specifies the country code for the user's language
2044 usri11_workstations points to a null terminated ASCII string that
2045 contains the names of workstations the user may log on from.
2046 There may be up to 8 workstations, with the names separated by
2047 commas. A null strings indicates there are no restrictions.
2049 usri11_max_storage specifies the maximum amount of disk space the user
2050 can occupy. A value of 0xffffffff indicates there are no
2053 usri11_units_per_week specifies the equal number of time units into
2054 which a week is divided. This value must be equal to 168.
2056 usri11_logon_hours points to a 21 byte (168 bits) string that
2057 specifies the time during which the user can log on. Each bit
2058 represents one unique hour in a week. The first bit (bit 0, word
2059 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2063 Leach, Naik [Page 29]
\r\f
2066 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2069 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2070 are no restrictions.
2072 usri11_code_page specifies the code page for the user's language of
2075 All of the pointers in this data structure need to be treated
2076 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2077 to be ignored. The converter word returned in the parameters section
2078 needs to be subtracted from the lower 16 bits to calculate an offset
2079 into the return buffer where this ASCII string resides.
2081 There is no auxiliary data in the response.
2083 ****************************************************************************/
2085 #define usri11_name 0
2086 #define usri11_pad 21
2087 #define usri11_comment 22
2088 #define usri11_usr_comment 26
2089 #define usri11_full_name 30
2090 #define usri11_priv 34
2091 #define usri11_auth_flags 36
2092 #define usri11_password_age 40
2093 #define usri11_homedir 44
2094 #define usri11_parms 48
2095 #define usri11_last_logon 52
2096 #define usri11_last_logoff 56
2097 #define usri11_bad_pw_count 60
2098 #define usri11_num_logons 62
2099 #define usri11_logon_server 64
2100 #define usri11_country_code 68
2101 #define usri11_workstations 70
2102 #define usri11_max_storage 74
2103 #define usri11_units_per_week 78
2104 #define usri11_logon_hours 80
2105 #define usri11_code_page 84
2106 #define usri11_end 86
2108 #define USER_PRIV_GUEST 0
2109 #define USER_PRIV_USER 1
2110 #define USER_PRIV_ADMIN 2
2112 #define AF_OP_PRINT 0
2113 #define AF_OP_COMM 1
2114 #define AF_OP_SERVER 2
2115 #define AF_OP_ACCOUNTS 3
2118 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2119 int mdrcnt,int mprcnt,
2120 char **rdata,char **rparam,
2121 int *rdata_len,int *rparam_len)
2123 char *str1 = param+2;
2124 char *str2 = skip_string(str1,1);
2125 char *UserName = skip_string(str2,1);
2126 char *p = skip_string(UserName,1);
2127 int uLevel = SVAL(p,0);
2130 /* get NIS home of a previously validated user - simeon */
2131 user_struct *vuser = get_valid_user_struct(vuid);
2132 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2135 *rparam = REALLOC(*rparam,*rparam_len);
2137 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2139 /* check it's a supported variant */
2140 if (strcmp(str1,"zWrLh") != 0) return False;
2143 case 0: p2 = "B21"; break;
2144 case 1: p2 = "B21BB16DWzzWz"; break;
2145 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2146 case 10: p2 = "B21Bzzz"; break;
2147 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2148 default: return False;
2151 if (strcmp(p2,str2) != 0) return False;
2153 *rdata_len = mdrcnt + 1024;
2154 *rdata = REALLOC(*rdata,*rdata_len);
2156 SSVAL(*rparam,0,NERR_Success);
2157 SSVAL(*rparam,2,0); /* converter word */
2160 p2 = p + usri11_end;
2163 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2167 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2172 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2173 strcpy(p2,"Comment");
2174 p2 = skip_string(p2,1);
2176 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2177 strcpy(p2,"UserComment");
2178 p2 = skip_string(p2,1);
2180 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2181 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2182 strcpy(p2,vuser->real_name); /* simeon */
2183 p2 = skip_string(p2,1);
2186 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2188 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2189 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2190 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2191 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2192 strcpy(p2, lp_logon_path());
2193 p2 = skip_string(p2,1);
2194 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2196 p2 = skip_string(p2,1);
2197 SIVAL(p,usri11_last_logon,0); /* last logon */
2198 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2199 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2200 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2201 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2203 p2 = skip_string(p2,1);
2204 SSVAL(p,usri11_country_code,0); /* country code */
2206 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2208 p2 = skip_string(p2,1);
2210 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2211 SSVAL(p,usri11_units_per_week,168); /* units per week */
2212 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2214 /* a simple way to get logon hours at all times. */
2216 SCVAL(p2,21,0); /* fix zero termination */
2217 p2 = skip_string(p2,1);
2219 SSVAL(p,usri11_code_page,0); /* code page */
2221 if (uLevel == 1 || uLevel == 2)
2223 memset(p+22,' ',16); /* password */
2224 SIVALS(p,38,-1); /* password age */
2226 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2227 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2228 strcpy(p2,lp_logon_path());
2229 p2 = skip_string(p2,1);
2230 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2232 SSVAL(p,52,0); /* flags */
2233 SIVAL(p,54,0); /* script_path */
2236 SIVAL(p,60,0); /* auth_flags */
2237 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2238 strcpy(p2,vuser->real_name); /* simeon */
2239 p2 = skip_string(p2,1);
2240 SIVAL(p,68,0); /* urs_comment */
2241 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2243 p2 = skip_string(p2,1);
2244 SIVAL(p,76,0); /* workstations */
2245 SIVAL(p,80,0); /* last_logon */
2246 SIVAL(p,84,0); /* last_logoff */
2247 SIVALS(p,88,-1); /* acct_expires */
2248 SIVALS(p,92,-1); /* max_storage */
2249 SSVAL(p,96,168); /* units_per_week */
2250 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2253 SSVALS(p,102,-1); /* bad_pw_count */
2254 SSVALS(p,104,-1); /* num_logons */
2255 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2256 strcpy(p2,"\\\\%L");
2257 standard_sub_basic(p2);
2258 p2 = skip_string(p2,1);
2259 SSVAL(p,110,49); /* country_code */
2260 SSVAL(p,112,860); /* code page */
2264 *rdata_len = PTR_DIFF(p2,*rdata);
2266 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2271 /*******************************************************************
2272 get groups that a user is a member of
2273 ******************************************************************/
2274 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2275 int mdrcnt,int mprcnt,
2276 char **rdata,char **rparam,
2277 int *rdata_len,int *rparam_len)
2279 char *str1 = param+2;
2280 char *str2 = skip_string(str1,1);
2281 char *UserName = skip_string(str2,1);
2282 char *p = skip_string(UserName,1);
2283 int uLevel = SVAL(p,0);
2288 *rparam = REALLOC(*rparam,*rparam_len);
2290 /* check it's a supported varient */
2291 if (strcmp(str1,"zWrLeh") != 0) return False;
2293 case 0: p2 = "B21"; break;
2294 default: return False;
2296 if (strcmp(p2,str2) != 0) return False;
2298 *rdata_len = mdrcnt + 1024;
2299 *rdata = REALLOC(*rdata,*rdata_len);
2301 SSVAL(*rparam,0,NERR_Success);
2302 SSVAL(*rparam,2,0); /* converter word */
2306 /* XXXX we need a real SAM database some day */
2307 strcpy(p,"Users"); p += 21; count++;
2308 strcpy(p,"Domain Users"); p += 21; count++;
2309 strcpy(p,"Guests"); p += 21; count++;
2310 strcpy(p,"Domain Guests"); p += 21; count++;
2312 *rdata_len = PTR_DIFF(p,*rdata);
2314 SSVAL(*rparam,4,count); /* is this right?? */
2315 SSVAL(*rparam,6,count); /* is this right?? */
2321 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2322 int mdrcnt,int mprcnt,
2323 char **rdata,char **rparam,
2324 int *rdata_len,int *rparam_len)
2326 char *str1 = param+2;
2327 char *str2 = skip_string(str1,1);
2328 char *p = skip_string(str2,1);
2330 struct pack_desc desc;
2337 bzero(&desc,sizeof(desc));
2339 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2341 /* check it's a supported varient */
2342 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2343 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2344 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2346 desc.buflen = mdrcnt;
2347 desc.subformat = NULL;
2350 if (init_package(&desc,1,0))
2352 PACKI(&desc,"W",0); /* code */
2353 PACKS(&desc,"B21",name); /* eff. name */
2354 PACKS(&desc,"B",""); /* pad */
2356 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2357 PACKI(&desc,"D",0); /* auth flags XXX */
2358 PACKI(&desc,"W",0); /* num logons */
2359 PACKI(&desc,"W",0); /* bad pw count */
2360 PACKI(&desc,"D",0); /* last logon */
2361 PACKI(&desc,"D",-1); /* last logoff */
2362 PACKI(&desc,"D",-1); /* logoff time */
2363 PACKI(&desc,"D",-1); /* kickoff time */
2364 PACKI(&desc,"D",0); /* password age */
2365 PACKI(&desc,"D",0); /* password can change */
2366 PACKI(&desc,"D",-1); /* password must change */
2369 strcpy(mypath,"\\\\");
2370 strcat(mypath,local_machine);
2372 PACKS(&desc,"z",mypath); /* computer */
2374 PACKS(&desc,"z",myworkgroup);/* domain */
2376 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2377 /* made sure all macros are fully substituted and available */
2378 logon_script = lp_logon_script();
2379 standard_sub( cnum, logon_script );
2380 PACKS(&desc,"z", logon_script); /* script path */
2381 /* End of JHT mods */
2383 PACKI(&desc,"D",0x00000000); /* reserved */
2386 *rdata_len = desc.usedlen;
2388 *rparam = REALLOC(*rparam,*rparam_len);
2389 SSVALS(*rparam,0,desc.errcode);
2391 SSVAL(*rparam,4,desc.neededlen);
2393 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2398 /****************************************************************************
2399 api_WAccessGetUserPerms
2400 ****************************************************************************/
2401 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2402 int mdrcnt,int mprcnt,
2403 char **rdata,char **rparam,
2404 int *rdata_len,int *rparam_len)
2406 char *str1 = param+2;
2407 char *str2 = skip_string(str1,1);
2408 char *user = skip_string(str2,1);
2409 char *resource = skip_string(user,1);
2411 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2413 /* check it's a supported varient */
2414 if (strcmp(str1,"zzh") != 0) return False;
2415 if (strcmp(str2,"") != 0) return False;
2418 *rparam = REALLOC(*rparam,*rparam_len);
2419 SSVALS(*rparam,0,0); /* errorcode */
2420 SSVAL(*rparam,2,0); /* converter word */
2421 SSVAL(*rparam,4,0x7f); /* permission flags */
2426 /****************************************************************************
2427 api_WPrintJobEnumerate
2428 ****************************************************************************/
2429 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2430 int mdrcnt,int mprcnt,
2431 char **rdata,char **rparam,
2432 int *rdata_len,int *rparam_len)
2434 char *str1 = param+2;
2435 char *str2 = skip_string(str1,1);
2436 char *p = skip_string(str2,1);
2442 struct pack_desc desc;
2443 print_queue_struct *queue=NULL;
2444 print_status_struct status;
2449 bzero(&desc,sizeof(desc));
2450 bzero(&status,sizeof(status));
2452 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2454 /* check it's a supported varient */
2455 if (strcmp(str1,"WWrLh") != 0) return False;
2456 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2458 printjob_decode(SVAL(p,0), &snum, &job);
2460 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2462 count = get_printqueue(snum,cnum,&queue,&status);
2463 for (i = 0; i < count; i++) {
2464 if ((queue[i].job & 0xFF) == job) break;
2466 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2468 desc.buflen = mdrcnt;
2470 if (init_package(&desc,1,0)) {
2472 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2473 *rdata_len = desc.usedlen;
2476 desc.errcode = NERR_JobNotFound;
2482 *rparam = REALLOC(*rparam,*rparam_len);
2483 SSVALS(*rparam,0,desc.errcode);
2485 SSVAL(*rparam,4,desc.neededlen);
2487 if (queue) free(queue);
2489 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2493 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2494 int mdrcnt,int mprcnt,
2495 char **rdata,char **rparam,
2496 int *rdata_len,int *rparam_len)
2498 char *str1 = param+2;
2499 char *str2 = skip_string(str1,1);
2500 char *p = skip_string(str2,1);
2506 struct pack_desc desc;
2507 print_queue_struct *queue=NULL;
2508 print_status_struct status;
2510 bzero(&desc,sizeof(desc));
2511 bzero(&status,sizeof(status));
2513 p = skip_string(p,1);
2517 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2519 /* check it's a supported varient */
2520 if (strcmp(str1,"zWrLeh") != 0) return False;
2521 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2522 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2524 snum = lp_servicenumber(name);
2525 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2526 int pnum = lp_servicenumber(PRINTERS_NAME);
2528 lp_add_printer(name,pnum);
2529 snum = lp_servicenumber(name);
2533 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2535 count = get_printqueue(snum,cnum,&queue,&status);
2536 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2538 desc.buflen = mdrcnt;
2540 if (init_package(&desc,count,0)) {
2542 for (i = 0; i < count; i++) {
2543 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2544 if (desc.errcode == NERR_Success) succnt = i+1;
2548 *rdata_len = desc.usedlen;
2551 *rparam = REALLOC(*rparam,*rparam_len);
2552 SSVALS(*rparam,0,desc.errcode);
2554 SSVAL(*rparam,4,succnt);
2555 SSVAL(*rparam,6,count);
2557 if (queue) free(queue);
2559 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2563 static int check_printdest_info(struct pack_desc* desc,
2564 int uLevel, char* id)
2566 desc->subformat = NULL;
2568 case 0: desc->format = "B9"; break;
2569 case 1: desc->format = "B9B21WWzW"; break;
2570 case 2: desc->format = "z"; break;
2571 case 3: desc->format = "zzzWWzzzWW"; break;
2572 default: return False;
2574 if (strcmp(desc->format,id) != 0) return False;
2578 static void fill_printdest_info(int cnum, int snum, int uLevel,
2579 struct pack_desc* desc)
2582 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2583 buf[sizeof(buf)-1] = 0;
2586 PACKS(desc,"B9",buf); /* szName */
2588 PACKS(desc,"B21",""); /* szUserName */
2589 PACKI(desc,"W",0); /* uJobId */
2590 PACKI(desc,"W",0); /* fsStatus */
2591 PACKS(desc,"z",""); /* pszStatus */
2592 PACKI(desc,"W",0); /* time */
2595 if (uLevel == 2 || uLevel == 3) {
2596 PACKS(desc,"z",buf); /* pszPrinterName */
2598 PACKS(desc,"z",""); /* pszUserName */
2599 PACKS(desc,"z",""); /* pszLogAddr */
2600 PACKI(desc,"W",0); /* uJobId */
2601 PACKI(desc,"W",0); /* fsStatus */
2602 PACKS(desc,"z",""); /* pszStatus */
2603 PACKS(desc,"z",""); /* pszComment */
2604 PACKS(desc,"z","NULL"); /* pszDrivers */
2605 PACKI(desc,"W",0); /* time */
2606 PACKI(desc,"W",0); /* pad1 */
2611 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2612 int mdrcnt,int mprcnt,
2613 char **rdata,char **rparam,
2614 int *rdata_len,int *rparam_len)
2616 char *str1 = param+2;
2617 char *str2 = skip_string(str1,1);
2618 char *p = skip_string(str2,1);
2619 char* PrinterName = p;
2621 struct pack_desc desc;
2624 bzero(&desc,sizeof(desc));
2626 p = skip_string(p,1);
2630 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2632 /* check it's a supported varient */
2633 if (strcmp(str1,"zWrLh") != 0) return False;
2634 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2636 snum = lp_servicenumber(PrinterName);
2637 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2638 int pnum = lp_servicenumber(PRINTERS_NAME);
2640 lp_add_printer(PrinterName,pnum);
2641 snum = lp_servicenumber(PrinterName);
2647 desc.errcode = NERR_DestNotFound;
2651 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2653 desc.buflen = mdrcnt;
2654 if (init_package(&desc,1,0)) {
2655 fill_printdest_info(cnum,snum,uLevel,&desc);
2657 *rdata_len = desc.usedlen;
2661 *rparam = REALLOC(*rparam,*rparam_len);
2662 SSVALS(*rparam,0,desc.errcode);
2664 SSVAL(*rparam,4,desc.neededlen);
2666 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2670 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2671 int mdrcnt,int mprcnt,
2672 char **rdata,char **rparam,
2673 int *rdata_len,int *rparam_len)
2675 char *str1 = param+2;
2676 char *str2 = skip_string(str1,1);
2677 char *p = skip_string(str2,1);
2681 struct pack_desc desc;
2682 int services = lp_numservices();
2684 bzero(&desc,sizeof(desc));
2689 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2691 /* check it's a supported varient */
2692 if (strcmp(str1,"WrLeh") != 0) return False;
2693 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2696 for (i = 0; i < services; i++)
2697 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2700 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2702 desc.buflen = mdrcnt;
2703 if (init_package(&desc,queuecnt,0)) {
2706 for (i = 0; i < services; i++) {
2707 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2708 fill_printdest_info(cnum,i,uLevel,&desc);
2710 if (desc.errcode == NERR_Success) succnt = n;
2715 *rdata_len = desc.usedlen;
2718 *rparam = REALLOC(*rparam,*rparam_len);
2719 SSVALS(*rparam,0,desc.errcode);
2721 SSVAL(*rparam,4,succnt);
2722 SSVAL(*rparam,6,queuecnt);
2724 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2728 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2729 int mdrcnt,int mprcnt,
2730 char **rdata,char **rparam,
2731 int *rdata_len,int *rparam_len)
2733 char *str1 = param+2;
2734 char *str2 = skip_string(str1,1);
2735 char *p = skip_string(str2,1);
2738 struct pack_desc desc;
2740 bzero(&desc,sizeof(desc));
2745 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2747 /* check it's a supported varient */
2748 if (strcmp(str1,"WrLeh") != 0) return False;
2749 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2751 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2753 desc.buflen = mdrcnt;
2754 if (init_package(&desc,1,0)) {
2755 PACKS(&desc,"B41","NULL");
2758 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2760 *rdata_len = desc.usedlen;
2763 *rparam = REALLOC(*rparam,*rparam_len);
2764 SSVALS(*rparam,0,desc.errcode);
2766 SSVAL(*rparam,4,succnt);
2769 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2773 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2774 int mdrcnt,int mprcnt,
2775 char **rdata,char **rparam,
2776 int *rdata_len,int *rparam_len)
2778 char *str1 = param+2;
2779 char *str2 = skip_string(str1,1);
2780 char *p = skip_string(str2,1);
2783 struct pack_desc desc;
2785 bzero(&desc,sizeof(desc));
2790 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2792 /* check it's a supported varient */
2793 if (strcmp(str1,"WrLeh") != 0) return False;
2794 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2796 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2798 desc.buflen = mdrcnt;
2800 if (init_package(&desc,1,0)) {
2801 PACKS(&desc,"B13","lpd");
2804 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2806 *rdata_len = desc.usedlen;
2809 *rparam = REALLOC(*rparam,*rparam_len);
2810 SSVALS(*rparam,0,desc.errcode);
2812 SSVAL(*rparam,4,succnt);
2815 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2819 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2820 int mdrcnt,int mprcnt,
2821 char **rdata,char **rparam,
2822 int *rdata_len,int *rparam_len)
2824 char *str1 = param+2;
2825 char *str2 = skip_string(str1,1);
2826 char *p = skip_string(str2,1);
2829 struct pack_desc desc;
2831 bzero(&desc,sizeof(desc));
2836 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2838 /* check it's a supported varient */
2839 if (strcmp(str1,"WrLeh") != 0) return False;
2840 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2842 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2843 bzero(&desc,sizeof(desc));
2845 desc.buflen = mdrcnt;
2847 if (init_package(&desc,1,0)) {
2848 PACKS(&desc,"B13","lp0");
2851 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2853 *rdata_len = desc.usedlen;
2856 *rparam = REALLOC(*rparam,*rparam_len);
2857 SSVALS(*rparam,0,desc.errcode);
2859 SSVAL(*rparam,4,succnt);
2862 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2870 char * pipe_clnt_name;
2872 char * pipe_srv_name;
2876 } api_fd_commands [] =
2879 { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP },
2880 { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP },
2881 { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP },
2882 { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP },
2883 { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP },
2884 { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2886 { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
2887 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2891 /****************************************************************************
2892 handle remote api calls delivered to a named pipe already opened.
2893 ****************************************************************************/
2894 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2895 uint16 *setup,char *data,char *params,
2896 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2899 char *rparam = NULL;
2904 BOOL bind_req = False;
2905 BOOL set_nphs = False;
2912 DEBUG(5,("api_fd_reply\n"));
2913 /* First find out the name of this file. */
2916 DEBUG(0,("Unexpected named pipe transaction.\n"));
2920 /* Get the file handle and hence the file name. */
2922 subcommand = setup[0];
2923 pipe_name = get_rpc_pipe_hnd_name(fd);
2925 if (pipe_name == NULL)
2927 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
2930 DEBUG(3,("Got API command %d on pipe %s (fd %x)",
2931 subcommand, pipe_name, fd));
2932 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2933 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2935 for (i = 0; api_fd_commands[i].name; i++)
2937 if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
2938 api_fd_commands[i].subcommand == subcommand &&
2939 api_fd_commands[i].fn)
2941 DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
2946 rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2947 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2950 /* RPC Pipe command 0x26. */
2951 if (data != NULL && api_fd_commands[i].subcommand == 0x26)
2955 /* process the rpc header */
2956 char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
2958 /* bind request received */
2959 if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
2963 /* decode the bind request */
2964 char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
2966 if ((bind_req = (p != NULL)))
2969 fstring ack_pipe_name;
2971 /* name has to be \PIPE\xxxxx */
2972 strcpy(ack_pipe_name, "\\PIPE\\");
2973 strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
2975 /* make a bind acknowledgement */
2976 make_rpc_hdr_ba(&hdr_ba,
2977 hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
2980 &(hdr_rb.transfer));
2982 p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
2984 rdata_len = PTR_DIFF(p, rdata);
2986 make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
2988 p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
2990 reply = (p != NULL);
2996 /* Set Named Pipe Handle state */
2997 if (subcommand == 0x1)
3000 reply = api_LsarpcSNPHS(fd, cnum, params);
3003 if (!bind_req && !set_nphs)
3005 DEBUG(10,("calling api_fd_command\n"));
3007 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3008 &rdata,&rparam,&rdata_len,&rparam_len);
3009 DEBUG(10,("called api_fd_command\n"));
3012 if (rdata_len > mdrcnt || rparam_len > mprcnt)
3014 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3015 &rdata,&rparam,&rdata_len,&rparam_len);
3018 /* if we get False back then it's actually unsupported */
3021 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3022 &rdata,&rparam,&rdata_len,&rparam_len);
3025 /* now send the reply */
3026 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3028 if (rdata ) free(rdata );
3029 if (rparam) free(rparam);
3036 /****************************************************************************
3037 the buffer was too small
3038 ****************************************************************************/
3039 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3040 int mdrcnt,int mprcnt,
3041 char **rdata,char **rparam,
3042 int *rdata_len,int *rparam_len)
3044 *rparam_len = MIN(*rparam_len,mprcnt);
3045 *rparam = REALLOC(*rparam,*rparam_len);
3049 SSVAL(*rparam,0,NERR_BufTooSmall);
3051 DEBUG(3,("Supplied buffer too small in API command\n"));
3057 /****************************************************************************
3058 the request is not supported
3059 ****************************************************************************/
3060 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3061 int mdrcnt,int mprcnt,
3062 char **rdata,char **rparam,
3063 int *rdata_len,int *rparam_len)
3066 *rparam = REALLOC(*rparam,*rparam_len);
3070 SSVAL(*rparam,0,NERR_notsupported);
3071 SSVAL(*rparam,2,0); /* converter word */
3073 DEBUG(3,("Unsupported API command\n"));
3087 } api_commands[] = {
3088 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3089 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3090 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3091 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3092 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3093 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3094 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3095 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3096 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3097 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3098 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3099 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3100 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3101 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3102 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3103 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3104 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3105 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3106 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3107 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3108 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3109 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3110 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3111 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3112 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3113 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3116 /****************************************************************************
3117 handle remote api calls
3118 ****************************************************************************/
3119 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3120 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3122 int api_command = SVAL(params,0);
3124 char *rparam = NULL;
3130 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3131 api_command,params+2,skip_string(params+2,1),
3132 tdscnt,tpscnt,mdrcnt,mprcnt));
3134 for (i=0;api_commands[i].name;i++)
3135 if (api_commands[i].id == api_command && api_commands[i].fn)
3137 DEBUG(3,("Doing %s\n",api_commands[i].name));
3141 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3142 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3144 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3145 &rdata,&rparam,&rdata_len,&rparam_len);
3148 if (rdata_len > mdrcnt ||
3149 rparam_len > mprcnt)
3151 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3152 &rdata,&rparam,&rdata_len,&rparam_len);
3156 /* if we get False back then it's actually unsupported */
3158 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3159 &rdata,&rparam,&rdata_len,&rparam_len);
3163 /* now send the reply */
3164 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3174 /****************************************************************************
3175 handle named pipe commands
3176 ****************************************************************************/
3177 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3178 uint16 *setup,char *data,char *params,
3179 int suwcnt,int tdscnt,int tpscnt,
3180 int msrcnt,int mdrcnt,int mprcnt)
3182 DEBUG(3,("named pipe command on <%s> name\n", name));
3184 if (strequal(name,"LANMAN"))
3186 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3189 if (strlen(name) < 1)
3191 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3196 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3203 /****************************************************************************
3205 ****************************************************************************/
3206 int reply_trans(char *inbuf,char *outbuf)
3210 char *data=NULL,*params=NULL;
3214 int cnum = SVAL(inbuf,smb_tid);
3215 uint16 vuid = SVAL(inbuf,smb_uid);
3217 int tpscnt = SVAL(inbuf,smb_vwv0);
3218 int tdscnt = SVAL(inbuf,smb_vwv1);
3219 int mprcnt = SVAL(inbuf,smb_vwv2);
3220 int mdrcnt = SVAL(inbuf,smb_vwv3);
3221 int msrcnt = CVAL(inbuf,smb_vwv4);
3222 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3223 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3224 int pscnt = SVAL(inbuf,smb_vwv9);
3225 int psoff = SVAL(inbuf,smb_vwv10);
3226 int dscnt = SVAL(inbuf,smb_vwv11);
3227 int dsoff = SVAL(inbuf,smb_vwv12);
3228 int suwcnt = CVAL(inbuf,smb_vwv13);
3230 bzero(name, sizeof(name));
3231 fstrcpy(name,smb_buf(inbuf));
3233 if (dscnt > tdscnt || pscnt > tpscnt) {
3234 exit_server("invalid trans parameters\n");
3239 data = (char *)malloc(tdscnt);
3240 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3244 params = (char *)malloc(tpscnt);
3245 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3251 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3252 for (i=0;i<suwcnt;i++)
3253 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3257 if (pscnt < tpscnt || dscnt < tdscnt)
3259 /* We need to send an interim response then receive the rest
3260 of the parameter/data bytes */
3261 outsize = set_message(outbuf,0,0,True);
3263 send_smb(Client,outbuf);
3266 /* receive the rest of the trans packet */
3267 while (pscnt < tpscnt || dscnt < tdscnt)
3269 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3271 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3272 CVAL(inbuf, smb_com) != SMBtrans)
3274 DEBUG(2,("Invalid secondary trans2 packet\n"));
3275 if (params) free(params);
3276 if (data) free(data);
3277 if (setup) free(setup);
3278 return(ERROR(ERRSRV,ERRerror));
3283 tpscnt = SVAL(inbuf,smb_vwv0);
3284 tdscnt = SVAL(inbuf,smb_vwv1);
3286 pcnt = SVAL(inbuf,smb_vwv2);
3287 poff = SVAL(inbuf,smb_vwv3);
3288 pdisp = SVAL(inbuf,smb_vwv4);
3290 dcnt = SVAL(inbuf,smb_vwv5);
3291 doff = SVAL(inbuf,smb_vwv6);
3292 ddisp = SVAL(inbuf,smb_vwv7);
3297 if (dscnt > tdscnt || pscnt > tpscnt) {
3298 exit_server("invalid trans parameters\n");
3302 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3304 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3308 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3310 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3312 DEBUG(5,("calling named_pipe\n"));
3313 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3314 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3318 DEBUG(3,("invalid pipe name\n"));
3323 if (data) free(data);
3324 if (params) free(params);
3325 if (setup) free(setup);
3327 if (close_on_completion)
3328 close_cnum(cnum,vuid);
3334 return(ERROR(ERRSRV,ERRnosupport));