2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1997
8 Copyright (C) John H Terpstra 1995-1997
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern int DEBUGLEVEL;
38 extern files_struct Files[];
39 extern connection_struct Connections[];
41 extern fstring local_machine;
42 extern fstring myworkgroup;
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
53 #define ERROR_MORE_DATA 234
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
65 extern int oplock_sock;
66 extern int smb_read_error;
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69 int mdrcnt,int mprcnt,
70 char **rdata,char **rparam,
71 int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73 int mdrcnt,int mprcnt,
74 char **rdata,char **rparam,
75 int *rdata_len,int *rparam_len);
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
83 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(buf,src,sizeof(buf)/2);
86 string_sub(buf,"%S",lp_servicename(snum));
87 standard_sub(cnum,buf);
95 static int CopyAndAdvance(char** dst, char* src, int* n)
98 if (!src || !dst || !n || !(*dst)) return(0);
100 l = strlen(*dst) + 1;
106 static int StrlenExpanded(int cnum, int snum, char* s)
110 StrnCpy(buf,s,sizeof(buf)/2);
111 string_sub(buf,"%S",lp_servicename(snum));
112 standard_sub(cnum,buf);
113 return strlen(buf) + 1;
116 static char* Expand(int cnum, int snum, char* s)
119 if (!s) return(NULL);
120 StrnCpy(buf,s,sizeof(buf)/2);
121 string_sub(buf,"%S",lp_servicename(snum));
122 standard_sub(cnum,buf);
126 /*******************************************************************
127 check a API string for validity when we only need to check the prefix
128 ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
131 return(strncmp(str,prefix,strlen(prefix)) == 0);
135 /****************************************************************************
137 ****************************************************************************/
138 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
139 int ldata,int lparam,int lsetup)
142 int this_ldata,this_lparam;
143 int tot_data=0,tot_param=0;
146 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
147 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
149 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
150 /* if you don't want Net Monitor to decode your packets, do this!!! */
151 align = ((this_lparam+1)%4);
153 align = (this_lparam%4);
156 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
158 memcpy(smb_buf(outbuf),param,this_lparam);
160 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
162 SSVAL(outbuf,smb_vwv0,lparam);
163 SSVAL(outbuf,smb_vwv1,ldata);
164 SSVAL(outbuf,smb_vwv3,this_lparam);
165 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
166 SSVAL(outbuf,smb_vwv5,0);
167 SSVAL(outbuf,smb_vwv6,this_ldata);
168 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
169 SSVAL(outbuf,smb_vwv8,0);
170 SSVAL(outbuf,smb_vwv9,lsetup);
171 for (i=0;i<lsetup;i++)
172 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
175 send_smb(Client,outbuf);
177 tot_data = this_ldata;
178 tot_param = this_lparam;
180 while (tot_data < ldata || tot_param < lparam)
182 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
183 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
185 align = (this_lparam%4);
187 set_message(outbuf,10,this_ldata+this_lparam+align,False);
189 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
191 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
193 SSVAL(outbuf,smb_vwv3,this_lparam);
194 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
195 SSVAL(outbuf,smb_vwv5,tot_param);
196 SSVAL(outbuf,smb_vwv6,this_ldata);
197 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
198 SSVAL(outbuf,smb_vwv8,tot_data);
199 SSVAL(outbuf,smb_vwv9,0);
202 send_smb(Client,outbuf);
204 tot_data += this_ldata;
205 tot_param += this_lparam;
210 char* format; /* formatstring for structure */
211 char* subformat; /* subformat for structure */
212 char* base; /* baseaddress of buffer */
213 int buflen; /* remaining size for fixed part; on init: length of base */
214 int subcount; /* count of substructures */
215 char* structbuf; /* pointer into buffer for remaining fixed part */
216 int stringlen; /* remaining size for variable part */
217 char* stringbuf; /* pointer into buffer for remaining variable part */
218 int neededlen; /* total needed size */
219 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
220 char* curpos; /* current position; pointer into format or subformat */
224 static int get_counter(char** p)
227 if (!p || !(*p)) return(1);
228 if (!isdigit(**p)) return 1;
232 n = 10 * n + (i - '0');
239 static int getlen(char* p)
245 case 'W': /* word (2 byte) */
248 case 'N': /* count of substructures (word) at end */
251 case 'D': /* double word (4 byte) */
252 case 'z': /* offset to zero terminated string (4 byte) */
253 case 'l': /* offset to user data (4 byte) */
256 case 'b': /* offset to data (with counter) (4 byte) */
260 case 'B': /* byte (with optional counter) */
261 n += get_counter(&p);
268 static BOOL init_package(struct pack_desc* p, int count, int subcount)
273 if (!p->format || !p->base) return(False);
275 i = count * getlen(p->format);
276 if (p->subformat) i += subcount * getlen(p->subformat);
277 p->structbuf = p->base;
281 p->curpos = p->format;
284 p->errcode = NERR_BufTooSmall;
287 p->errcode = NERR_Success;
290 p->stringbuf = p->base + i;
292 return(p->errcode == NERR_Success);
296 static int package(struct pack_desc* p, ...)
299 static int package(va_alist)
305 int needed=0, stringneeded;
307 int is_string=0, stringused;
314 p = va_arg(args,struct pack_desc *);
319 p->curpos = p->format;
321 p->curpos = p->subformat;
326 str = va_arg(args,char*);
327 if (strncmp(str,p->curpos,strlen(str)) != 0) {
328 DEBUG(2,("type error in package: %s instead of %*s\n",str,
329 strlen(str),p->curpos));
339 if (!p->curpos) return(0);
341 switch( *p->curpos++ ) {
342 case 'W': /* word (2 byte) */
344 temp = va_arg(args,int);
345 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
347 case 'N': /* count of substructures (word) at end */
349 p->subcount = va_arg(args,int);
350 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
352 case 'D': /* double word (4 byte) */
354 temp = va_arg(args,int);
355 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
357 case 'B': /* byte (with optional counter) */
358 needed = get_counter(&p->curpos);
360 char *s = va_arg(args,char*);
361 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
364 case 'z': /* offset to zero terminated string (4 byte) */
365 str = va_arg(args,char*);
366 stringneeded = (str ? strlen(str)+1 : 0);
369 case 'l': /* offset to user data (4 byte) */
370 str = va_arg(args,char*);
371 stringneeded = va_arg(args,int);
374 case 'b': /* offset to data (with counter) (4 byte) */
375 str = va_arg(args,char*);
376 stringneeded = get_counter(&p->curpos);
381 if (stringneeded >= 0) {
383 if (p->buflen >= needed) {
384 stringused = stringneeded;
385 if (stringused > p->stringlen) {
386 stringused = (is_string ? p->stringlen : 0);
387 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
390 SIVAL(p->structbuf,0,0);
392 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
393 memcpy(p->stringbuf,str?str:"",stringused);
394 if (is_string) p->stringbuf[stringused-1] = '\0';
395 p->stringbuf += stringused;
396 p->stringlen -= stringused;
397 p->usedlen += stringused;
400 p->neededlen += stringneeded;
402 p->neededlen += needed;
403 if (p->buflen >= needed) {
404 p->structbuf += needed;
406 p->usedlen += needed;
409 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
415 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
416 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
418 #define PACK(desc,t,v) package(desc,v)
419 #define PACKl(desc,t,v,l) package(desc,v,l)
422 static void PACKI(struct pack_desc* desc,char *t,int v)
427 static void PACKS(struct pack_desc* desc,char *t,char *v)
433 /****************************************************************************
435 ****************************************************************************/
437 static void PackDriverData(struct pack_desc* desc)
439 char drivdata[4+4+32];
440 SIVAL(drivdata,0,sizeof drivdata); /* cb */
441 SIVAL(drivdata,4,1000); /* lVersion */
442 memset(drivdata+8,0,32); /* szDeviceName */
443 strcpy(drivdata+8,"NULL");
444 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
447 static int check_printq_info(struct pack_desc* desc,
448 int uLevel, char *id1, char *id2)
450 desc->subformat = NULL;
453 desc->format = "B13";
456 desc->format = "B13BWWWzzzzzWW";
459 desc->format = "B13BWWWzzzzzWN";
460 desc->subformat = "WB21BB16B10zWWzDDz";
463 desc->format = "zWWWWzzzzWWzzl";
466 desc->format = "zWWWWzzzzWNzzl";
467 desc->subformat = "WWzWWDDzz";
473 desc->format = "WzzzzzzzzN";
474 desc->subformat = "z";
476 default: return False;
478 if (strcmp(desc->format,id1) != 0) return False;
479 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
483 static void fill_printjob_info(int cnum, int snum, int uLevel,
484 struct pack_desc* desc,
485 print_queue_struct* queue, int n)
487 time_t t = queue->time;
489 /* the client expects localtime */
492 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
494 PACKS(desc,"B21",queue->user); /* szUserName */
495 PACKS(desc,"B",""); /* pad */
496 PACKS(desc,"B16",""); /* szNotifyName */
497 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
498 PACKS(desc,"z",""); /* pszParms */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKS(desc,"z",""); /* pszStatus */
502 PACKI(desc,"D",t); /* ulSubmitted */
503 PACKI(desc,"D",queue->size); /* ulSize */
504 PACKS(desc,"z",queue->file); /* pszComment */
506 if (uLevel == 2 || uLevel == 3) {
507 PACKI(desc,"W",queue->priority); /* uPriority */
508 PACKS(desc,"z",queue->user); /* pszUserName */
509 PACKI(desc,"W",n+1); /* uPosition */
510 PACKI(desc,"W",queue->status); /* fsStatus */
511 PACKI(desc,"D",t); /* ulSubmitted */
512 PACKI(desc,"D",queue->size); /* ulSize */
513 PACKS(desc,"z","Samba"); /* pszComment */
514 PACKS(desc,"z",queue->file); /* pszDocument */
516 PACKS(desc,"z",""); /* pszNotifyName */
517 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
518 PACKS(desc,"z",""); /* pszParms */
519 PACKS(desc,"z",""); /* pszStatus */
520 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
521 PACKS(desc,"z","lpd"); /* pszQProcName */
522 PACKS(desc,"z",""); /* pszQProcParms */
523 PACKS(desc,"z","NULL"); /* pszDriverName */
524 PackDriverData(desc); /* pDriverData */
525 PACKS(desc,"z",""); /* pszPrinterName */
530 static void fill_printq_info(int cnum, int snum, int uLevel,
531 struct pack_desc* desc,
532 int count, print_queue_struct* queue,
533 print_status_struct* status)
538 PACKS(desc,"B13",SERVICE(snum));
543 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
547 if (uLevel == 1 || uLevel == 2) {
548 PACKS(desc,"B",""); /* alignment */
549 PACKI(desc,"W",5); /* priority */
550 PACKI(desc,"W",0); /* start time */
551 PACKI(desc,"W",0); /* until time */
552 PACKS(desc,"z",""); /* pSepFile */
553 PACKS(desc,"z","lpd"); /* pPrProc */
554 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
555 PACKS(desc,"z",""); /* pParms */
557 PACKS(desc,"z","UNKNOWN PRINTER");
558 PACKI(desc,"W",LPSTAT_ERROR);
560 else if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
562 PACKI(desc,"W",LPSTAT_OK); /* status */
564 PACKS(desc,"z",status->message);
565 PACKI(desc,"W",status->status); /* status */
567 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
569 if (uLevel == 3 || uLevel == 4) {
570 PACKI(desc,"W",5); /* uPriority */
571 PACKI(desc,"W",0); /* uStarttime */
572 PACKI(desc,"W",0); /* uUntiltime */
573 PACKI(desc,"W",5); /* pad1 */
574 PACKS(desc,"z",""); /* pszSepFile */
575 PACKS(desc,"z","WinPrint"); /* pszPrProc */
576 PACKS(desc,"z",""); /* pszParms */
577 if (!status || !status->message[0]) {
578 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
579 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
581 PACKS(desc,"z",status->message); /* pszComment */
582 PACKI(desc,"W",status->status); /* fsStatus */
584 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
585 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
586 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
587 PackDriverData(desc); /* pDriverData */
589 if (uLevel == 2 || uLevel == 4) {
591 for (i=0;i<count;i++)
592 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
597 pstring tok,driver,short_name;
602 strcpy(fname,lp_driverfile());
606 DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
609 p=(char *)malloc(8192*sizeof(char));
610 bzero(p, 8192*sizeof(char));
613 /* lookup the long printer driver name in the file description */
614 while (f && !feof(f) && !ok)
618 next_token(&p,tok,":");
619 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
624 next_token(&p,short_name,":");
625 next_token(&p,driver,":");
627 PACKI(desc,"W",0x0400); /* don't know */
628 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
632 PACKS(desc,"z",driver); /* Driver Name */
633 PACKS(desc,"z",short_name); /* short printer name */
634 DEBUG(3,("Driver:%s:\n",driver));
635 DEBUG(3,("short name:%s:\n",short_name));
644 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
645 PACKS(desc,"z","EMF");
648 PACKS(desc,"z",driver); /* driver name */
651 PACKI(desc,"N",count); /* number of files to copy */
652 for (i=0;i<count;i++)
654 next_token(&p,tok,",");
655 PACKS(desc,"z",tok); /* driver files to copy */
656 DEBUG(3,("file:%s:\n",tok));
661 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
664 /* This function returns the number of file for a given driver */
665 int get_printerdrivernumber(int snum)
673 strcpy(fname,lp_driverfile());
675 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
678 DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
682 p=(char *)malloc(8192*sizeof(char));
683 q=p; /* need it to free memory because p change ! */
685 /* lookup the long printer driver name in the file description */
686 while (!feof(f) && !ok)
689 next_token(&p,tok,":");
690 if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
695 next_token(&p,tok,":"); /* short name */
696 next_token(&p,tok,":"); /* driver name */
697 /* count the number of files */
698 while (next_token(&p,tok,","))
707 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
708 int mdrcnt,int mprcnt,
709 char **rdata,char **rparam,
710 int *rdata_len,int *rparam_len)
712 char *str1 = param+2;
713 char *str2 = skip_string(str1,1);
714 char *p = skip_string(str2,1);
720 struct pack_desc desc;
721 print_queue_struct *queue=NULL;
722 print_status_struct status;
724 bzero(&status,sizeof(status));
725 bzero(&desc,sizeof(desc));
727 p = skip_string(p,1);
732 /* remove any trailing username */
733 if ((p = strchr(QueueName,'%'))) *p = 0;
735 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
737 /* check it's a supported varient */
738 if (!prefix_ok(str1,"zWrLh")) return False;
739 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
741 snum = lp_servicenumber(QueueName);
742 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
743 int pnum = lp_servicenumber(PRINTERS_NAME);
745 lp_add_printer(QueueName,pnum);
746 snum = lp_servicenumber(QueueName);
750 if (snum < 0 || !VALID_SNUM(snum)) return(False);
754 count = get_printerdrivernumber(snum);
755 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
758 count = get_printqueue(snum,cnum,&queue,&status);
760 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
762 desc.buflen = mdrcnt;
763 if (init_package(&desc,1,count)) {
764 desc.subcount = count;
765 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
768 *rdata_len = desc.usedlen;
771 *rparam = REALLOC(*rparam,*rparam_len);
772 SSVALS(*rparam,0,desc.errcode);
774 SSVAL(*rparam,4,desc.neededlen);
776 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
778 if (queue) free(queue);
784 /****************************************************************************
785 view list of all print jobs on all queues
786 ****************************************************************************/
787 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
788 int mdrcnt, int mprcnt,
789 char **rdata, char** rparam,
790 int *rdata_len, int *rparam_len)
792 char *param_format = param+2;
793 char *output_format1 = skip_string(param_format,1);
794 char *p = skip_string(output_format1,1);
795 int uLevel = SVAL(p,0);
796 char *output_format2 = p + 4;
797 int services = lp_numservices();
799 struct pack_desc desc;
800 print_queue_struct **queue = NULL;
801 print_status_struct *status = NULL;
802 int* subcntarr = NULL;
803 int queuecnt, subcnt=0, succnt=0;
805 bzero(&desc,sizeof(desc));
807 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
809 if (!prefix_ok(param_format,"WrLeh")) return False;
810 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
813 for (i = 0; i < services; i++)
814 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
817 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
818 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
819 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
820 memset(status,0,queuecnt*sizeof(print_status_struct));
821 subcntarr = (int*)malloc(queuecnt*sizeof(int));
824 for (i = 0; i < services; i++)
825 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
826 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
827 subcnt += subcntarr[n];
831 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
833 desc.buflen = mdrcnt;
835 if (init_package(&desc,queuecnt,subcnt)) {
838 for (i = 0; i < services; i++)
839 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
840 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
842 if (desc.errcode == NERR_Success) succnt = n;
846 if (subcntarr) free(subcntarr);
848 *rdata_len = desc.usedlen;
850 *rparam = REALLOC(*rparam,*rparam_len);
851 SSVALS(*rparam,0,desc.errcode);
853 SSVAL(*rparam,4,succnt);
854 SSVAL(*rparam,6,queuecnt);
856 for (i = 0; i < queuecnt; i++) {
857 if (queue && queue[i]) free(queue[i]);
860 if (queue) free(queue);
861 if (status) free(status);
866 /****************************************************************************
867 get info level for a server list query
868 ****************************************************************************/
869 static BOOL check_server_info(int uLevel, char* id)
873 if (strcmp(id,"B16") != 0) return False;
876 if (strcmp(id,"B16BBDz") != 0) return False;
884 struct srv_info_struct
894 /*******************************************************************
895 get server info lists from the files saved by nmbd. Return the
897 ******************************************************************/
898 static int get_server_info(uint32 servertype,
899 struct srv_info_struct **servers,
907 BOOL local_list_only;
909 pstrcpy(fname,lp_lockdir());
910 trim_string(fname,NULL,"/");
912 strcat(fname,SERVER_LIST);
914 f = fopen(fname,"r");
917 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
921 /* request for everything is code for request all servers */
922 if (servertype == SV_TYPE_ALL)
923 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
925 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
927 DEBUG(4,("Servertype search: %8x\n",servertype));
932 struct srv_info_struct *s;
937 fgets(line,sizeof(line)-1,f);
938 if (!*line) continue;
940 if (count == alloced) {
942 (*servers) = (struct srv_info_struct *)
943 Realloc(*servers,sizeof(**servers)*alloced);
944 if (!(*servers)) return(0);
945 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
947 s = &(*servers)[count];
949 if (!next_token(&ptr,s->name , NULL)) continue;
950 if (!next_token(&ptr,stype , NULL)) continue;
951 if (!next_token(&ptr,s->comment, NULL)) continue;
952 if (!next_token(&ptr,s->domain , NULL)) {
953 /* this allows us to cope with an old nmbd */
954 strcpy(s->domain,myworkgroup);
957 if (sscanf(stype,"%X",&s->type) != 1) {
958 DEBUG(4,("r:host file "));
962 /* Filter the servers/domains we return based on what was asked for. */
964 /* Check to see if we are being asked for a local list only. */
965 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
966 DEBUG(4,("r: local list only"));
970 /* doesn't match up: don't want it */
971 if (!(servertype & s->type)) {
972 DEBUG(4,("r:serv type "));
976 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
977 (s->type & SV_TYPE_DOMAIN_ENUM))
979 DEBUG(4,("s: dom mismatch "));
983 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
988 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
989 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
993 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
994 s->name, s->type, s->comment, s->domain));
996 s->server_added = True;
1001 DEBUG(4,("%20s %8x %25s %15s\n",
1002 s->name, s->type, s->comment, s->domain));
1011 /*******************************************************************
1012 fill in a server info structure
1013 ******************************************************************/
1014 static int fill_srv_info(struct srv_info_struct *service,
1015 int uLevel, char **buf, int *buflen,
1016 char **stringbuf, int *stringspace, char *baseaddr)
1025 case 0: struct_len = 16; break;
1026 case 1: struct_len = 26; break;
1036 len = strlen(service->comment)+1;
1040 if (buflen) *buflen = struct_len;
1041 if (stringspace) *stringspace = len;
1042 return struct_len + len;
1047 if (*buflen < struct_len) return -1;
1055 p2 = p + struct_len;
1056 l2 = *buflen - struct_len;
1058 if (!baseaddr) baseaddr = p;
1063 StrnCpy(p,service->name,15);
1067 StrnCpy(p,service->name,15);
1068 SIVAL(p,18,service->type);
1069 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1070 len += CopyAndAdvance(&p2,service->comment,&l2);
1076 *buf = p + struct_len;
1077 *buflen -= struct_len;
1090 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1092 return(strcmp(s1->name,s2->name));
1095 /****************************************************************************
1096 view list of servers available (or possibly domains). The info is
1097 extracted from lists saved by nmbd on the local host
1098 ****************************************************************************/
1099 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1100 int mdrcnt, int mprcnt, char **rdata,
1101 char **rparam, int *rdata_len, int *rparam_len)
1103 char *str1 = param+2;
1104 char *str2 = skip_string(str1,1);
1105 char *p = skip_string(str2,1);
1106 int uLevel = SVAL(p,0);
1107 int buf_len = SVAL(p,2);
1108 uint32 servertype = IVAL(p,4);
1110 int data_len, fixed_len, string_len;
1112 struct srv_info_struct *servers=NULL;
1113 int counted=0,total=0;
1116 BOOL domain_request;
1119 /* If someone sets all the bits they don't really mean to set
1120 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1123 if (servertype == SV_TYPE_ALL)
1124 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1126 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1127 any other bit (they may just set this bit on it's own) they
1128 want all the locally seen servers. However this bit can be
1129 set on its own so set the requested servers to be
1130 ALL - DOMAIN_ENUM. */
1132 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1133 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1135 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1136 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1140 if (!prefix_ok(str1,"WrLehD")) return False;
1141 if (!check_server_info(uLevel,str2)) return False;
1143 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1144 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1145 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1147 if (strcmp(str1, "WrLehDz") == 0) {
1148 StrnCpy(domain, p, sizeof(fstring)-1);
1150 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1153 if (lp_browse_list())
1154 total = get_server_info(servertype,&servers,domain);
1156 data_len = fixed_len = string_len = 0;
1159 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1162 char *lastname=NULL;
1164 for (i=0;i<total;i++)
1166 struct srv_info_struct *s = &servers[i];
1167 if (lastname && strequal(lastname,s->name)) continue;
1169 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1170 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1171 s->name, s->type, s->comment, s->domain));
1173 if (data_len <= buf_len) {
1176 string_len += s_len;
1183 *rdata_len = fixed_len + string_len;
1184 *rdata = REALLOC(*rdata,*rdata_len);
1185 bzero(*rdata,*rdata_len);
1187 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1193 char *lastname=NULL;
1194 int count2 = counted;
1195 for (i = 0; i < total && count2;i++)
1197 struct srv_info_struct *s = &servers[i];
1198 if (lastname && strequal(lastname,s->name)) continue;
1200 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1201 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1202 s->name, s->type, s->comment, s->domain));
1208 *rparam = REALLOC(*rparam,*rparam_len);
1209 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1211 SSVAL(*rparam,4,counted);
1212 SSVAL(*rparam,6,counted+missed);
1214 if (servers) free(servers);
1216 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1217 domain,uLevel,counted,counted+missed));
1223 /****************************************************************************
1224 get info about a share
1225 ****************************************************************************/
1226 static BOOL check_share_info(int uLevel, char* id)
1230 if (strcmp(id,"B13") != 0) return False;
1233 if (strcmp(id,"B13BWz") != 0) return False;
1236 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1239 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1241 default: return False;
1246 static int fill_share_info(int cnum, int snum, int uLevel,
1247 char** buf, int* buflen,
1248 char** stringbuf, int* stringspace, char* baseaddr)
1257 case 0: struct_len = 13; break;
1258 case 1: struct_len = 20; break;
1259 case 2: struct_len = 40; break;
1260 case 91: struct_len = 68; break;
1268 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1269 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1270 if (buflen) *buflen = struct_len;
1271 if (stringspace) *stringspace = len;
1272 return struct_len + len;
1277 if ((*buflen) < struct_len) return -1;
1285 p2 = p + struct_len;
1286 l2 = (*buflen) - struct_len;
1288 if (!baseaddr) baseaddr = p;
1290 StrnCpy(p,lp_servicename(snum),13);
1296 type = STYPE_DISKTREE;
1297 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1298 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1299 SSVAL(p,14,type); /* device type */
1300 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1301 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1306 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1307 SSVALS(p,22,-1); /* max uses */
1308 SSVAL(p,24,1); /* current uses */
1309 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1310 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1311 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1316 memset(p+40,0,SHPWLEN+2);
1328 (*buf) = p + struct_len;
1329 (*buflen) -= struct_len;
1331 (*stringspace) = l2;
1341 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1342 int mdrcnt,int mprcnt,
1343 char **rdata,char **rparam,
1344 int *rdata_len,int *rparam_len)
1346 char *str1 = param+2;
1347 char *str2 = skip_string(str1,1);
1348 char *netname = skip_string(str2,1);
1349 char *p = skip_string(netname,1);
1350 int uLevel = SVAL(p,0);
1351 int snum = find_service(netname);
1353 if (snum < 0) return False;
1355 /* check it's a supported varient */
1356 if (!prefix_ok(str1,"zWrLh")) return False;
1357 if (!check_share_info(uLevel,str2)) return False;
1359 *rdata = REALLOC(*rdata,mdrcnt);
1361 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1362 if (*rdata_len < 0) return False;
1365 *rparam = REALLOC(*rparam,*rparam_len);
1366 SSVAL(*rparam,0,NERR_Success);
1367 SSVAL(*rparam,2,0); /* converter word */
1368 SSVAL(*rparam,4,*rdata_len);
1373 /****************************************************************************
1374 view list of shares available
1375 ****************************************************************************/
1376 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1377 int mdrcnt,int mprcnt,
1378 char **rdata,char **rparam,
1379 int *rdata_len,int *rparam_len)
1381 char *str1 = param+2;
1382 char *str2 = skip_string(str1,1);
1383 char *p = skip_string(str2,1);
1384 int uLevel = SVAL(p,0);
1385 int buf_len = SVAL(p,2);
1387 int count=lp_numservices();
1388 int total=0,counted=0;
1390 int data_len, fixed_len, string_len;
1393 if (!prefix_ok(str1,"WrLeh")) return False;
1394 if (!check_share_info(uLevel,str2)) return False;
1396 data_len = fixed_len = string_len = 0;
1397 for (i=0;i<count;i++)
1398 if (lp_browseable(i) && lp_snum_ok(i))
1401 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1402 if (data_len <= buf_len)
1406 string_len += s_len;
1409 *rdata_len = fixed_len + string_len;
1410 *rdata = REALLOC(*rdata,*rdata_len);
1411 memset(*rdata,0,*rdata_len);
1413 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1417 for (i = 0; i < count;i++)
1418 if (lp_browseable(i) && lp_snum_ok(i))
1419 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1423 *rparam = REALLOC(*rparam,*rparam_len);
1424 SSVAL(*rparam,0,NERR_Success);
1426 SSVAL(*rparam,4,counted);
1427 SSVAL(*rparam,6,total);
1429 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1430 counted,total,uLevel,
1431 buf_len,*rdata_len,mdrcnt));
1437 /****************************************************************************
1438 get the time of day info
1439 ****************************************************************************/
1440 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1441 int mdrcnt,int mprcnt,
1442 char **rdata,char **rparam,
1443 int *rdata_len,int *rparam_len)
1447 *rparam = REALLOC(*rparam,*rparam_len);
1450 *rdata = REALLOC(*rdata,*rdata_len);
1452 SSVAL(*rparam,0,NERR_Success);
1453 SSVAL(*rparam,2,0); /* converter word */
1459 time_t unixdate = time(NULL);
1461 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1462 by NT in a "net time" operation,
1463 it seems to ignore the one below */
1465 /* the client expects to get localtime, not GMT, in this bit
1466 (I think, this needs testing) */
1467 t = LocalTime(&unixdate);
1469 SIVAL(p,4,0); /* msecs ? */
1470 CVAL(p,8) = t->tm_hour;
1471 CVAL(p,9) = t->tm_min;
1472 CVAL(p,10) = t->tm_sec;
1473 CVAL(p,11) = 0; /* hundredths of seconds */
1474 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1475 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1476 CVAL(p,16) = t->tm_mday;
1477 CVAL(p,17) = t->tm_mon + 1;
1478 SSVAL(p,18,1900+t->tm_year);
1479 CVAL(p,20) = t->tm_wday;
1486 /****************************************************************************
1487 set the user password
1488 ****************************************************************************/
1489 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1490 int mdrcnt,int mprcnt,
1491 char **rdata,char **rparam,
1492 int *rdata_len,int *rparam_len)
1494 char *p = skip_string(param+2,2);
1496 fstring pass1,pass2;
1500 p = skip_string(p,1);
1502 StrnCpy(pass1,p,16);
1503 StrnCpy(pass2,p+16,16);
1506 *rparam = REALLOC(*rparam,*rparam_len);
1510 SSVAL(*rparam,0,NERR_badpass);
1511 SSVAL(*rparam,2,0); /* converter word */
1513 DEBUG(3,("Set password for <%s>\n",user));
1515 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1516 chgpasswd(user,pass1,pass2))
1518 SSVAL(*rparam,0,NERR_Success);
1521 bzero(pass1,sizeof(fstring));
1522 bzero(pass2,sizeof(fstring));
1527 /****************************************************************************
1530 ****************************************************************************/
1531 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1532 int mdrcnt,int mprcnt,
1533 char **rdata,char **rparam,
1534 int *rdata_len,int *rparam_len)
1536 int function = SVAL(param,0);
1537 char *str1 = param+2;
1538 char *str2 = skip_string(str1,1);
1539 char *p = skip_string(str2,1);
1543 printjob_decode(SVAL(p,0), &snum, &jobid);
1545 /* check it's a supported varient */
1546 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1550 *rparam = REALLOC(*rparam,*rparam_len);
1554 SSVAL(*rparam,0,NERR_Success);
1556 if (snum >= 0 && VALID_SNUM(snum))
1558 print_queue_struct *queue=NULL;
1560 count = get_printqueue(snum,cnum,&queue,NULL);
1562 for (i=0;i<count;i++)
1563 if ((queue[i].job&0xFF) == jobid)
1566 case 81: /* delete */
1567 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1568 del_printqueue(cnum,snum,queue[i].job);
1570 case 82: /* pause */
1571 case 83: /* resume */
1572 DEBUG(3,("%s queue entry %d\n",
1573 (function==82?"pausing":"resuming"),queue[i].job));
1574 status_printjob(cnum,snum,queue[i].job,
1575 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1582 SSVAL(*rparam,0,NERR_JobNotFound);
1584 if (queue) free(queue);
1587 SSVAL(*rparam,2,0); /* converter word */
1592 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1593 int mdrcnt,int mprcnt,
1594 char **rdata,char **rparam,
1595 int *rdata_len,int *rparam_len)
1597 char *str1 = param+2;
1598 char *str2 = skip_string(str1,1);
1599 char *QueueName = skip_string(str2,1);
1602 /* check it's a supported varient */
1603 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1607 *rparam = REALLOC(*rparam,*rparam_len);
1611 SSVAL(*rparam,0,NERR_Success);
1612 SSVAL(*rparam,2,0); /* converter word */
1614 snum = lp_servicenumber(QueueName);
1615 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1616 int pnum = lp_servicenumber(PRINTERS_NAME);
1618 lp_add_printer(QueueName,pnum);
1619 snum = lp_servicenumber(QueueName);
1623 if (snum >= 0 && VALID_SNUM(snum)) {
1624 print_queue_struct *queue=NULL;
1628 count = get_printqueue(snum,cnum,&queue,NULL);
1629 for (i = 0; i < count; i++)
1630 del_printqueue(cnum,snum,queue[i].job);
1632 if (queue) free(queue);
1635 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1641 /****************************************************************************
1642 set the property of a print job (undocumented?)
1643 ? function = 0xb -> set name of print job
1644 ? function = 0x6 -> move print job up/down
1645 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1646 or <WWsTP> <WB21BB16B10zWWzDDz>
1647 ****************************************************************************/
1648 static int check_printjob_info(struct pack_desc* desc,
1649 int uLevel, char* id)
1651 desc->subformat = NULL;
1653 case 0: desc->format = "W"; break;
1654 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1655 case 2: desc->format = "WWzWWDDzz"; break;
1656 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1657 default: return False;
1659 if (strcmp(desc->format,id) != 0) return False;
1663 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1664 int mdrcnt,int mprcnt,
1665 char **rdata,char **rparam,
1666 int *rdata_len,int *rparam_len)
1668 struct pack_desc desc;
1669 char *str1 = param+2;
1670 char *str2 = skip_string(str1,1);
1671 char *p = skip_string(str2,1);
1673 int uLevel = SVAL(p,2);
1674 int function = SVAL(p,4); /* what is this ?? */
1678 printjob_decode(SVAL(p,0), &snum, &jobid);
1681 *rparam = REALLOC(*rparam,*rparam_len);
1685 /* check it's a supported varient */
1686 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1690 case 0x6: /* change job place in the queue, data gives the new place */
1691 if (snum >= 0 && VALID_SNUM(snum))
1693 print_queue_struct *queue=NULL;
1697 count = get_printqueue(snum,cnum,&queue,NULL);
1698 for (i=0;i<count;i++) /* find job */
1699 if ((queue[i].job&0xFF) == jobid) break;
1702 desc.errcode=NERR_JobNotFound;
1703 if (queue) free(queue);
1706 desc.errcode=NERR_Success;
1710 int place= SVAL(data,0);
1711 /* we currently have no way of doing this. Can any unix do it? */
1712 if (i < place) /* move down */;
1713 else if (i > place ) /* move up */;
1716 desc.errcode=NERR_notsupported; /* not yet supported */
1717 if (queue) free(queue);
1720 else desc.errcode=NERR_JobNotFound;
1722 case 0xb: /* change print job name, data gives the name */
1723 /* jobid, snum should be zero */
1730 if (issafe(*s)) name[l++] = *s;
1735 DEBUG(3,("Setting print name to %s\n",name));
1739 for (i=0;i<MAX_OPEN_FILES;i++)
1740 if (Files[i].open && Files[i].print_file)
1743 int fcnum = Files[i].cnum;
1747 if (!become_user(&Connections[fcnum], fcnum,vuid) ||
1748 !become_service(fcnum,True))
1751 if (sys_rename(Files[i].name,name) == 0)
1752 string_set(&Files[i].name,name);
1756 unbecome_root(True);
1758 desc.errcode=NERR_Success;
1761 default: /* not implemented */
1765 SSVALS(*rparam,0,desc.errcode);
1766 SSVAL(*rparam,2,0); /* converter word */
1772 /****************************************************************************
1773 get info about the server
1774 ****************************************************************************/
1775 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1776 int mdrcnt,int mprcnt,
1777 char **rdata,char **rparam,
1778 int *rdata_len,int *rparam_len)
1780 char *str1 = param+2;
1781 char *str2 = skip_string(str1,1);
1782 char *p = skip_string(str2,1);
1783 int uLevel = SVAL(p,0);
1787 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1789 /* check it's a supported varient */
1790 if (!prefix_ok(str1,"WrLh")) return False;
1793 if (strcmp(str2,"B16") != 0) return False;
1797 if (strcmp(str2,"B16BBDz") != 0) return False;
1801 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1806 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1811 if (strcmp(str2,"DN") != 0) return False;
1815 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1818 default: return False;
1821 *rdata_len = mdrcnt;
1822 *rdata = REALLOC(*rdata,*rdata_len);
1825 p2 = p + struct_len;
1827 StrnCpy(p,local_machine,16);
1833 struct srv_info_struct *servers=NULL;
1836 uint32 servertype= lp_default_server_announce();
1838 pstrcpy(comment,lp_serverstring());
1840 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1841 for (i=0;i<count;i++)
1842 if (strequal(servers[i].name,local_machine))
1844 servertype = servers[i].type;
1845 pstrcpy(comment,servers[i].comment);
1848 if (servers) free(servers);
1850 SCVAL(p,0,lp_major_announce_version());
1851 SCVAL(p,1,lp_minor_announce_version());
1852 SIVAL(p,2,servertype);
1854 if (mdrcnt == struct_len) {
1857 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1858 standard_sub(cnum,comment);
1859 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1860 p2 = skip_string(p2,1);
1865 return False; /* not yet implemented */
1868 *rdata_len = PTR_DIFF(p2,*rdata);
1871 *rparam = REALLOC(*rparam,*rparam_len);
1872 SSVAL(*rparam,0,NERR_Success);
1873 SSVAL(*rparam,2,0); /* converter word */
1874 SSVAL(*rparam,4,*rdata_len);
1880 /****************************************************************************
1881 get info about the server
1882 ****************************************************************************/
1883 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1884 int mdrcnt,int mprcnt,
1885 char **rdata,char **rparam,
1886 int *rdata_len,int *rparam_len)
1888 char *str1 = param+2;
1889 char *str2 = skip_string(str1,1);
1890 char *p = skip_string(str2,1);
1892 extern pstring sesssetup_user;
1893 int level = SVAL(p,0);
1895 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1898 *rparam = REALLOC(*rparam,*rparam_len);
1900 /* check it's a supported varient */
1901 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1904 *rdata_len = mdrcnt + 1024;
1905 *rdata = REALLOC(*rdata,*rdata_len);
1907 SSVAL(*rparam,0,NERR_Success);
1908 SSVAL(*rparam,2,0); /* converter word */
1914 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1915 strcpy(p2,local_machine);
1917 p2 = skip_string(p2,1);
1920 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1921 strcpy(p2,sesssetup_user);
1922 p2 = skip_string(p2,1);
1925 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1926 strcpy(p2,myworkgroup);
1928 p2 = skip_string(p2,1);
1931 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1932 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1935 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1936 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1937 p2 = skip_string(p2,1);
1940 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1942 p2 = skip_string(p2,1);
1945 *rdata_len = PTR_DIFF(p2,*rdata);
1947 SSVAL(*rparam,4,*rdata_len);
1952 /****************************************************************************
1953 get info about a user
1955 struct user_info_11 {
1956 char usri11_name[21]; 0-20
1958 char *usri11_comment; 22-25
1959 char *usri11_usr_comment; 26-29
1960 unsigned short usri11_priv; 30-31
1961 unsigned long usri11_auth_flags; 32-35
1962 long usri11_password_age; 36-39
1963 char *usri11_homedir; 40-43
1964 char *usri11_parms; 44-47
1965 long usri11_last_logon; 48-51
1966 long usri11_last_logoff; 52-55
1967 unsigned short usri11_bad_pw_count; 56-57
1968 unsigned short usri11_num_logons; 58-59
1969 char *usri11_logon_server; 60-63
1970 unsigned short usri11_country_code; 64-65
1971 char *usri11_workstations; 66-69
1972 unsigned long usri11_max_storage; 70-73
1973 unsigned short usri11_units_per_week; 74-75
1974 unsigned char *usri11_logon_hours; 76-79
1975 unsigned short usri11_code_page; 80-81
1980 usri11_name specifies the user name for which information is retireved
1982 usri11_pad aligns the next data structure element to a word boundary
1984 usri11_comment is a null terminated ASCII comment
1986 usri11_user_comment is a null terminated ASCII comment about the user
1988 usri11_priv specifies the level of the privilege assigned to the user.
1989 The possible values are:
1991 Name Value Description
1992 USER_PRIV_GUEST 0 Guest privilege
1993 USER_PRIV_USER 1 User privilege
1994 USER_PRV_ADMIN 2 Administrator privilege
1996 usri11_auth_flags specifies the account operator privileges. The
1997 possible values are:
1999 Name Value Description
2000 AF_OP_PRINT 0 Print operator
2003 Leach, Naik [Page 28]
\r\f
2006 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2009 AF_OP_COMM 1 Communications operator
2010 AF_OP_SERVER 2 Server operator
2011 AF_OP_ACCOUNTS 3 Accounts operator
2014 usri11_password_age specifies how many seconds have elapsed since the
2015 password was last changed.
2017 usri11_home_dir points to a null terminated ASCII string that contains
2018 the path name of the user's home directory.
2020 usri11_parms points to a null terminated ASCII string that is set
2021 aside for use by applications.
2023 usri11_last_logon specifies the time when the user last logged on.
2024 This value is stored as the number of seconds elapsed since
2025 00:00:00, January 1, 1970.
2027 usri11_last_logoff specifies the time when the user last logged off.
2028 This value is stored as the number of seconds elapsed since
2029 00:00:00, January 1, 1970. A value of 0 means the last logoff
2032 usri11_bad_pw_count specifies the number of incorrect passwords
2033 entered since the last successful logon.
2035 usri11_log1_num_logons specifies the number of times this user has
2036 logged on. A value of -1 means the number of logons is unknown.
2038 usri11_logon_server points to a null terminated ASCII string that
2039 contains the name of the server to which logon requests are sent.
2040 A null string indicates logon requests should be sent to the
2043 usri11_country_code specifies the country code for the user's language
2046 usri11_workstations points to a null terminated ASCII string that
2047 contains the names of workstations the user may log on from.
2048 There may be up to 8 workstations, with the names separated by
2049 commas. A null strings indicates there are no restrictions.
2051 usri11_max_storage specifies the maximum amount of disk space the user
2052 can occupy. A value of 0xffffffff indicates there are no
2055 usri11_units_per_week specifies the equal number of time units into
2056 which a week is divided. This value must be equal to 168.
2058 usri11_logon_hours points to a 21 byte (168 bits) string that
2059 specifies the time during which the user can log on. Each bit
2060 represents one unique hour in a week. The first bit (bit 0, word
2061 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2065 Leach, Naik [Page 29]
\r\f
2068 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2071 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2072 are no restrictions.
2074 usri11_code_page specifies the code page for the user's language of
2077 All of the pointers in this data structure need to be treated
2078 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2079 to be ignored. The converter word returned in the parameters section
2080 needs to be subtracted from the lower 16 bits to calculate an offset
2081 into the return buffer where this ASCII string resides.
2083 There is no auxiliary data in the response.
2085 ****************************************************************************/
2087 #define usri11_name 0
2088 #define usri11_pad 21
2089 #define usri11_comment 22
2090 #define usri11_usr_comment 26
2091 #define usri11_full_name 30
2092 #define usri11_priv 34
2093 #define usri11_auth_flags 36
2094 #define usri11_password_age 40
2095 #define usri11_homedir 44
2096 #define usri11_parms 48
2097 #define usri11_last_logon 52
2098 #define usri11_last_logoff 56
2099 #define usri11_bad_pw_count 60
2100 #define usri11_num_logons 62
2101 #define usri11_logon_server 64
2102 #define usri11_country_code 68
2103 #define usri11_workstations 70
2104 #define usri11_max_storage 74
2105 #define usri11_units_per_week 78
2106 #define usri11_logon_hours 80
2107 #define usri11_code_page 84
2108 #define usri11_end 86
2110 #define USER_PRIV_GUEST 0
2111 #define USER_PRIV_USER 1
2112 #define USER_PRIV_ADMIN 2
2114 #define AF_OP_PRINT 0
2115 #define AF_OP_COMM 1
2116 #define AF_OP_SERVER 2
2117 #define AF_OP_ACCOUNTS 3
2120 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2121 int mdrcnt,int mprcnt,
2122 char **rdata,char **rparam,
2123 int *rdata_len,int *rparam_len)
2125 char *str1 = param+2;
2126 char *str2 = skip_string(str1,1);
2127 char *UserName = skip_string(str2,1);
2128 char *p = skip_string(UserName,1);
2129 int uLevel = SVAL(p,0);
2132 /* get NIS home of a previously validated user - simeon */
2133 user_struct *vuser = get_valid_user_struct(vuid);
2134 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2137 *rparam = REALLOC(*rparam,*rparam_len);
2139 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2141 /* check it's a supported variant */
2142 if (strcmp(str1,"zWrLh") != 0) return False;
2145 case 0: p2 = "B21"; break;
2146 case 1: p2 = "B21BB16DWzzWz"; break;
2147 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2148 case 10: p2 = "B21Bzzz"; break;
2149 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2150 default: return False;
2153 if (strcmp(p2,str2) != 0) return False;
2155 *rdata_len = mdrcnt + 1024;
2156 *rdata = REALLOC(*rdata,*rdata_len);
2158 SSVAL(*rparam,0,NERR_Success);
2159 SSVAL(*rparam,2,0); /* converter word */
2162 p2 = p + usri11_end;
2165 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2169 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2174 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2175 strcpy(p2,"Comment");
2176 p2 = skip_string(p2,1);
2178 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2179 strcpy(p2,"UserComment");
2180 p2 = skip_string(p2,1);
2182 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2183 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2184 strcpy(p2,vuser->real_name); /* simeon */
2185 p2 = skip_string(p2,1);
2188 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2190 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2191 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2192 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2193 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2194 strcpy(p2, lp_logon_path());
2195 p2 = skip_string(p2,1);
2196 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2198 p2 = skip_string(p2,1);
2199 SIVAL(p,usri11_last_logon,0); /* last logon */
2200 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2201 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2202 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2203 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2205 p2 = skip_string(p2,1);
2206 SSVAL(p,usri11_country_code,0); /* country code */
2208 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2210 p2 = skip_string(p2,1);
2212 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2213 SSVAL(p,usri11_units_per_week,168); /* units per week */
2214 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2216 /* a simple way to get logon hours at all times. */
2218 SCVAL(p2,21,0); /* fix zero termination */
2219 p2 = skip_string(p2,1);
2221 SSVAL(p,usri11_code_page,0); /* code page */
2223 if (uLevel == 1 || uLevel == 2)
2225 memset(p+22,' ',16); /* password */
2226 SIVALS(p,38,-1); /* password age */
2228 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2229 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2230 strcpy(p2,lp_logon_path());
2231 p2 = skip_string(p2,1);
2232 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2234 SSVAL(p,52,0); /* flags */
2235 SIVAL(p,54,0); /* script_path */
2238 SIVAL(p,60,0); /* auth_flags */
2239 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2240 strcpy(p2,vuser->real_name); /* simeon */
2241 p2 = skip_string(p2,1);
2242 SIVAL(p,68,0); /* urs_comment */
2243 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2245 p2 = skip_string(p2,1);
2246 SIVAL(p,76,0); /* workstations */
2247 SIVAL(p,80,0); /* last_logon */
2248 SIVAL(p,84,0); /* last_logoff */
2249 SIVALS(p,88,-1); /* acct_expires */
2250 SIVALS(p,92,-1); /* max_storage */
2251 SSVAL(p,96,168); /* units_per_week */
2252 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2255 SSVALS(p,102,-1); /* bad_pw_count */
2256 SSVALS(p,104,-1); /* num_logons */
2257 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2258 strcpy(p2,"\\\\%L");
2259 standard_sub_basic(p2);
2260 p2 = skip_string(p2,1);
2261 SSVAL(p,110,49); /* country_code */
2262 SSVAL(p,112,860); /* code page */
2266 *rdata_len = PTR_DIFF(p2,*rdata);
2268 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2273 /*******************************************************************
2274 get groups that a user is a member of
2275 ******************************************************************/
2276 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2277 int mdrcnt,int mprcnt,
2278 char **rdata,char **rparam,
2279 int *rdata_len,int *rparam_len)
2281 char *str1 = param+2;
2282 char *str2 = skip_string(str1,1);
2283 char *UserName = skip_string(str2,1);
2284 char *p = skip_string(UserName,1);
2285 int uLevel = SVAL(p,0);
2290 *rparam = REALLOC(*rparam,*rparam_len);
2292 /* check it's a supported varient */
2293 if (strcmp(str1,"zWrLeh") != 0) return False;
2295 case 0: p2 = "B21"; break;
2296 default: return False;
2298 if (strcmp(p2,str2) != 0) return False;
2300 *rdata_len = mdrcnt + 1024;
2301 *rdata = REALLOC(*rdata,*rdata_len);
2303 SSVAL(*rparam,0,NERR_Success);
2304 SSVAL(*rparam,2,0); /* converter word */
2308 /* XXXX we need a real SAM database some day */
2309 strcpy(p,"Users"); p += 21; count++;
2310 strcpy(p,"Domain Users"); p += 21; count++;
2311 strcpy(p,"Guests"); p += 21; count++;
2312 strcpy(p,"Domain Guests"); p += 21; count++;
2314 *rdata_len = PTR_DIFF(p,*rdata);
2316 SSVAL(*rparam,4,count); /* is this right?? */
2317 SSVAL(*rparam,6,count); /* is this right?? */
2323 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2324 int mdrcnt,int mprcnt,
2325 char **rdata,char **rparam,
2326 int *rdata_len,int *rparam_len)
2328 char *str1 = param+2;
2329 char *str2 = skip_string(str1,1);
2330 char *p = skip_string(str2,1);
2332 struct pack_desc desc;
2339 bzero(&desc,sizeof(desc));
2341 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2343 /* check it's a supported varient */
2344 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2345 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2346 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2348 desc.buflen = mdrcnt;
2349 desc.subformat = NULL;
2352 if (init_package(&desc,1,0))
2354 PACKI(&desc,"W",0); /* code */
2355 PACKS(&desc,"B21",name); /* eff. name */
2356 PACKS(&desc,"B",""); /* pad */
2358 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2359 PACKI(&desc,"D",0); /* auth flags XXX */
2360 PACKI(&desc,"W",0); /* num logons */
2361 PACKI(&desc,"W",0); /* bad pw count */
2362 PACKI(&desc,"D",0); /* last logon */
2363 PACKI(&desc,"D",-1); /* last logoff */
2364 PACKI(&desc,"D",-1); /* logoff time */
2365 PACKI(&desc,"D",-1); /* kickoff time */
2366 PACKI(&desc,"D",0); /* password age */
2367 PACKI(&desc,"D",0); /* password can change */
2368 PACKI(&desc,"D",-1); /* password must change */
2371 strcpy(mypath,"\\\\");
2372 strcat(mypath,local_machine);
2374 PACKS(&desc,"z",mypath); /* computer */
2376 PACKS(&desc,"z",myworkgroup);/* domain */
2378 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2379 /* made sure all macros are fully substituted and available */
2380 logon_script = lp_logon_script();
2381 standard_sub( cnum, logon_script );
2382 PACKS(&desc,"z", logon_script); /* script path */
2383 /* End of JHT mods */
2385 PACKI(&desc,"D",0x00000000); /* reserved */
2388 *rdata_len = desc.usedlen;
2390 *rparam = REALLOC(*rparam,*rparam_len);
2391 SSVALS(*rparam,0,desc.errcode);
2393 SSVAL(*rparam,4,desc.neededlen);
2395 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2400 /****************************************************************************
2401 api_WAccessGetUserPerms
2402 ****************************************************************************/
2403 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2404 int mdrcnt,int mprcnt,
2405 char **rdata,char **rparam,
2406 int *rdata_len,int *rparam_len)
2408 char *str1 = param+2;
2409 char *str2 = skip_string(str1,1);
2410 char *user = skip_string(str2,1);
2411 char *resource = skip_string(user,1);
2413 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2415 /* check it's a supported varient */
2416 if (strcmp(str1,"zzh") != 0) return False;
2417 if (strcmp(str2,"") != 0) return False;
2420 *rparam = REALLOC(*rparam,*rparam_len);
2421 SSVALS(*rparam,0,0); /* errorcode */
2422 SSVAL(*rparam,2,0); /* converter word */
2423 SSVAL(*rparam,4,0x7f); /* permission flags */
2428 /****************************************************************************
2429 api_WPrintJobEnumerate
2430 ****************************************************************************/
2431 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2432 int mdrcnt,int mprcnt,
2433 char **rdata,char **rparam,
2434 int *rdata_len,int *rparam_len)
2436 char *str1 = param+2;
2437 char *str2 = skip_string(str1,1);
2438 char *p = skip_string(str2,1);
2444 struct pack_desc desc;
2445 print_queue_struct *queue=NULL;
2446 print_status_struct status;
2451 bzero(&desc,sizeof(desc));
2452 bzero(&status,sizeof(status));
2454 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2456 /* check it's a supported varient */
2457 if (strcmp(str1,"WWrLh") != 0) return False;
2458 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2460 printjob_decode(SVAL(p,0), &snum, &job);
2462 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2464 count = get_printqueue(snum,cnum,&queue,&status);
2465 for (i = 0; i < count; i++) {
2466 if ((queue[i].job & 0xFF) == job) break;
2468 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2470 desc.buflen = mdrcnt;
2472 if (init_package(&desc,1,0)) {
2474 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2475 *rdata_len = desc.usedlen;
2478 desc.errcode = NERR_JobNotFound;
2484 *rparam = REALLOC(*rparam,*rparam_len);
2485 SSVALS(*rparam,0,desc.errcode);
2487 SSVAL(*rparam,4,desc.neededlen);
2489 if (queue) free(queue);
2491 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2495 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2496 int mdrcnt,int mprcnt,
2497 char **rdata,char **rparam,
2498 int *rdata_len,int *rparam_len)
2500 char *str1 = param+2;
2501 char *str2 = skip_string(str1,1);
2502 char *p = skip_string(str2,1);
2508 struct pack_desc desc;
2509 print_queue_struct *queue=NULL;
2510 print_status_struct status;
2512 bzero(&desc,sizeof(desc));
2513 bzero(&status,sizeof(status));
2515 p = skip_string(p,1);
2519 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2521 /* check it's a supported varient */
2522 if (strcmp(str1,"zWrLeh") != 0) return False;
2523 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2524 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2526 snum = lp_servicenumber(name);
2527 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2528 int pnum = lp_servicenumber(PRINTERS_NAME);
2530 lp_add_printer(name,pnum);
2531 snum = lp_servicenumber(name);
2535 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2537 count = get_printqueue(snum,cnum,&queue,&status);
2538 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2540 desc.buflen = mdrcnt;
2542 if (init_package(&desc,count,0)) {
2544 for (i = 0; i < count; i++) {
2545 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2546 if (desc.errcode == NERR_Success) succnt = i+1;
2550 *rdata_len = desc.usedlen;
2553 *rparam = REALLOC(*rparam,*rparam_len);
2554 SSVALS(*rparam,0,desc.errcode);
2556 SSVAL(*rparam,4,succnt);
2557 SSVAL(*rparam,6,count);
2559 if (queue) free(queue);
2561 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2565 static int check_printdest_info(struct pack_desc* desc,
2566 int uLevel, char* id)
2568 desc->subformat = NULL;
2570 case 0: desc->format = "B9"; break;
2571 case 1: desc->format = "B9B21WWzW"; break;
2572 case 2: desc->format = "z"; break;
2573 case 3: desc->format = "zzzWWzzzWW"; break;
2574 default: return False;
2576 if (strcmp(desc->format,id) != 0) return False;
2580 static void fill_printdest_info(int cnum, int snum, int uLevel,
2581 struct pack_desc* desc)
2584 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2585 buf[sizeof(buf)-1] = 0;
2588 PACKS(desc,"B9",buf); /* szName */
2590 PACKS(desc,"B21",""); /* szUserName */
2591 PACKI(desc,"W",0); /* uJobId */
2592 PACKI(desc,"W",0); /* fsStatus */
2593 PACKS(desc,"z",""); /* pszStatus */
2594 PACKI(desc,"W",0); /* time */
2597 if (uLevel == 2 || uLevel == 3) {
2598 PACKS(desc,"z",buf); /* pszPrinterName */
2600 PACKS(desc,"z",""); /* pszUserName */
2601 PACKS(desc,"z",""); /* pszLogAddr */
2602 PACKI(desc,"W",0); /* uJobId */
2603 PACKI(desc,"W",0); /* fsStatus */
2604 PACKS(desc,"z",""); /* pszStatus */
2605 PACKS(desc,"z",""); /* pszComment */
2606 PACKS(desc,"z","NULL"); /* pszDrivers */
2607 PACKI(desc,"W",0); /* time */
2608 PACKI(desc,"W",0); /* pad1 */
2613 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2614 int mdrcnt,int mprcnt,
2615 char **rdata,char **rparam,
2616 int *rdata_len,int *rparam_len)
2618 char *str1 = param+2;
2619 char *str2 = skip_string(str1,1);
2620 char *p = skip_string(str2,1);
2621 char* PrinterName = p;
2623 struct pack_desc desc;
2626 bzero(&desc,sizeof(desc));
2628 p = skip_string(p,1);
2632 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2634 /* check it's a supported varient */
2635 if (strcmp(str1,"zWrLh") != 0) return False;
2636 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2638 snum = lp_servicenumber(PrinterName);
2639 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2640 int pnum = lp_servicenumber(PRINTERS_NAME);
2642 lp_add_printer(PrinterName,pnum);
2643 snum = lp_servicenumber(PrinterName);
2649 desc.errcode = NERR_DestNotFound;
2653 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2655 desc.buflen = mdrcnt;
2656 if (init_package(&desc,1,0)) {
2657 fill_printdest_info(cnum,snum,uLevel,&desc);
2659 *rdata_len = desc.usedlen;
2663 *rparam = REALLOC(*rparam,*rparam_len);
2664 SSVALS(*rparam,0,desc.errcode);
2666 SSVAL(*rparam,4,desc.neededlen);
2668 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2672 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2673 int mdrcnt,int mprcnt,
2674 char **rdata,char **rparam,
2675 int *rdata_len,int *rparam_len)
2677 char *str1 = param+2;
2678 char *str2 = skip_string(str1,1);
2679 char *p = skip_string(str2,1);
2683 struct pack_desc desc;
2684 int services = lp_numservices();
2686 bzero(&desc,sizeof(desc));
2691 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2693 /* check it's a supported varient */
2694 if (strcmp(str1,"WrLeh") != 0) return False;
2695 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2698 for (i = 0; i < services; i++)
2699 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2702 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2704 desc.buflen = mdrcnt;
2705 if (init_package(&desc,queuecnt,0)) {
2708 for (i = 0; i < services; i++) {
2709 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2710 fill_printdest_info(cnum,i,uLevel,&desc);
2712 if (desc.errcode == NERR_Success) succnt = n;
2717 *rdata_len = desc.usedlen;
2720 *rparam = REALLOC(*rparam,*rparam_len);
2721 SSVALS(*rparam,0,desc.errcode);
2723 SSVAL(*rparam,4,succnt);
2724 SSVAL(*rparam,6,queuecnt);
2726 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2730 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2731 int mdrcnt,int mprcnt,
2732 char **rdata,char **rparam,
2733 int *rdata_len,int *rparam_len)
2735 char *str1 = param+2;
2736 char *str2 = skip_string(str1,1);
2737 char *p = skip_string(str2,1);
2740 struct pack_desc desc;
2742 bzero(&desc,sizeof(desc));
2747 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2749 /* check it's a supported varient */
2750 if (strcmp(str1,"WrLeh") != 0) return False;
2751 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2753 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2755 desc.buflen = mdrcnt;
2756 if (init_package(&desc,1,0)) {
2757 PACKS(&desc,"B41","NULL");
2760 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2762 *rdata_len = desc.usedlen;
2765 *rparam = REALLOC(*rparam,*rparam_len);
2766 SSVALS(*rparam,0,desc.errcode);
2768 SSVAL(*rparam,4,succnt);
2771 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2775 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2776 int mdrcnt,int mprcnt,
2777 char **rdata,char **rparam,
2778 int *rdata_len,int *rparam_len)
2780 char *str1 = param+2;
2781 char *str2 = skip_string(str1,1);
2782 char *p = skip_string(str2,1);
2785 struct pack_desc desc;
2787 bzero(&desc,sizeof(desc));
2792 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2794 /* check it's a supported varient */
2795 if (strcmp(str1,"WrLeh") != 0) return False;
2796 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2798 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2800 desc.buflen = mdrcnt;
2802 if (init_package(&desc,1,0)) {
2803 PACKS(&desc,"B13","lpd");
2806 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2808 *rdata_len = desc.usedlen;
2811 *rparam = REALLOC(*rparam,*rparam_len);
2812 SSVALS(*rparam,0,desc.errcode);
2814 SSVAL(*rparam,4,succnt);
2817 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2821 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2822 int mdrcnt,int mprcnt,
2823 char **rdata,char **rparam,
2824 int *rdata_len,int *rparam_len)
2826 char *str1 = param+2;
2827 char *str2 = skip_string(str1,1);
2828 char *p = skip_string(str2,1);
2831 struct pack_desc desc;
2833 bzero(&desc,sizeof(desc));
2838 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2840 /* check it's a supported varient */
2841 if (strcmp(str1,"WrLeh") != 0) return False;
2842 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2844 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2845 bzero(&desc,sizeof(desc));
2847 desc.buflen = mdrcnt;
2849 if (init_package(&desc,1,0)) {
2850 PACKS(&desc,"B13","lp0");
2853 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2855 *rdata_len = desc.usedlen;
2858 *rparam = REALLOC(*rparam,*rparam_len);
2859 SSVALS(*rparam,0,desc.errcode);
2861 SSVAL(*rparam,4,succnt);
2864 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2872 char * pipe_clnt_name;
2874 char * pipe_srv_name;
2878 } api_fd_commands [] =
2881 { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP },
2882 { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP },
2883 { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP },
2884 { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP },
2885 { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP },
2886 { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2888 { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
2889 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2893 /****************************************************************************
2894 handle remote api calls delivered to a named pipe already opened.
2895 ****************************************************************************/
2896 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2897 uint16 *setup,char *data,char *params,
2898 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2901 char *rparam = NULL;
2906 BOOL bind_req = False;
2907 BOOL set_nphs = False;
2914 DEBUG(5,("api_fd_reply\n"));
2915 /* First find out the name of this file. */
2918 DEBUG(0,("Unexpected named pipe transaction.\n"));
2922 /* Get the file handle and hence the file name. */
2924 subcommand = setup[0];
2925 pipe_name = get_rpc_pipe_hnd_name(fd);
2927 if (pipe_name == NULL)
2929 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
2932 DEBUG(3,("Got API command %d on pipe %s (fd %x)",
2933 subcommand, pipe_name, fd));
2934 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2935 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2937 for (i = 0; api_fd_commands[i].name; i++)
2939 if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
2940 api_fd_commands[i].subcommand == subcommand &&
2941 api_fd_commands[i].fn)
2943 DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
2948 rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2949 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2952 /* RPC Pipe command 0x26. */
2953 if (data != NULL && api_fd_commands[i].subcommand == 0x26)
2957 /* process the rpc header */
2958 char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
2960 /* bind request received */
2961 if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
2965 /* decode the bind request */
2966 char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
2968 if ((bind_req = (p != NULL)))
2971 fstring ack_pipe_name;
2973 /* name has to be \PIPE\xxxxx */
2974 strcpy(ack_pipe_name, "\\PIPE\\");
2975 strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
2977 /* make a bind acknowledgement */
2978 make_rpc_hdr_ba(&hdr_ba,
2979 hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
2982 &(hdr_rb.transfer));
2984 p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
2986 rdata_len = PTR_DIFF(p, rdata);
2988 make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
2990 p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
2992 reply = (p != NULL);
2998 /* Set Named Pipe Handle state */
2999 if (subcommand == 0x1)
3002 reply = api_LsarpcSNPHS(fd, cnum, params);
3005 if (!bind_req && !set_nphs)
3007 DEBUG(10,("calling api_fd_command\n"));
3009 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3010 &rdata,&rparam,&rdata_len,&rparam_len);
3011 DEBUG(10,("called api_fd_command\n"));
3014 if (rdata_len > mdrcnt || rparam_len > mprcnt)
3016 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3017 &rdata,&rparam,&rdata_len,&rparam_len);
3020 /* if we get False back then it's actually unsupported */
3023 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3024 &rdata,&rparam,&rdata_len,&rparam_len);
3027 /* now send the reply */
3028 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3030 if (rdata ) free(rdata );
3031 if (rparam) free(rparam);
3038 /****************************************************************************
3039 the buffer was too small
3040 ****************************************************************************/
3041 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3042 int mdrcnt,int mprcnt,
3043 char **rdata,char **rparam,
3044 int *rdata_len,int *rparam_len)
3046 *rparam_len = MIN(*rparam_len,mprcnt);
3047 *rparam = REALLOC(*rparam,*rparam_len);
3051 SSVAL(*rparam,0,NERR_BufTooSmall);
3053 DEBUG(3,("Supplied buffer too small in API command\n"));
3059 /****************************************************************************
3060 the request is not supported
3061 ****************************************************************************/
3062 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3063 int mdrcnt,int mprcnt,
3064 char **rdata,char **rparam,
3065 int *rdata_len,int *rparam_len)
3068 *rparam = REALLOC(*rparam,*rparam_len);
3072 SSVAL(*rparam,0,NERR_notsupported);
3073 SSVAL(*rparam,2,0); /* converter word */
3075 DEBUG(3,("Unsupported API command\n"));
3089 } api_commands[] = {
3090 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
3091 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
3092 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
3093 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
3094 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
3095 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
3096 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
3097 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
3098 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
3099 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
3100 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
3101 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
3102 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
3103 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
3104 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
3105 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
3106 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
3107 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
3108 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
3109 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
3110 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
3111 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
3112 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
3113 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
3114 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
3115 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
3118 /****************************************************************************
3119 handle remote api calls
3120 ****************************************************************************/
3121 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3122 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3124 int api_command = SVAL(params,0);
3126 char *rparam = NULL;
3132 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3133 api_command,params+2,skip_string(params+2,1),
3134 tdscnt,tpscnt,mdrcnt,mprcnt));
3136 for (i=0;api_commands[i].name;i++)
3137 if (api_commands[i].id == api_command && api_commands[i].fn)
3139 DEBUG(3,("Doing %s\n",api_commands[i].name));
3143 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3144 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3146 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3147 &rdata,&rparam,&rdata_len,&rparam_len);
3150 if (rdata_len > mdrcnt ||
3151 rparam_len > mprcnt)
3153 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3154 &rdata,&rparam,&rdata_len,&rparam_len);
3158 /* if we get False back then it's actually unsupported */
3160 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3161 &rdata,&rparam,&rdata_len,&rparam_len);
3165 /* now send the reply */
3166 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3176 /****************************************************************************
3177 handle named pipe commands
3178 ****************************************************************************/
3179 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3180 uint16 *setup,char *data,char *params,
3181 int suwcnt,int tdscnt,int tpscnt,
3182 int msrcnt,int mdrcnt,int mprcnt)
3184 DEBUG(3,("named pipe command on <%s> name\n", name));
3186 if (strequal(name,"LANMAN"))
3188 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3191 if (strlen(name) < 1)
3193 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3198 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3205 /****************************************************************************
3207 ****************************************************************************/
3208 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3212 char *data=NULL,*params=NULL;
3216 int cnum = SVAL(inbuf,smb_tid);
3217 uint16 vuid = SVAL(inbuf,smb_uid);
3219 int tpscnt = SVAL(inbuf,smb_vwv0);
3220 int tdscnt = SVAL(inbuf,smb_vwv1);
3221 int mprcnt = SVAL(inbuf,smb_vwv2);
3222 int mdrcnt = SVAL(inbuf,smb_vwv3);
3223 int msrcnt = CVAL(inbuf,smb_vwv4);
3224 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3225 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3226 int pscnt = SVAL(inbuf,smb_vwv9);
3227 int psoff = SVAL(inbuf,smb_vwv10);
3228 int dscnt = SVAL(inbuf,smb_vwv11);
3229 int dsoff = SVAL(inbuf,smb_vwv12);
3230 int suwcnt = CVAL(inbuf,smb_vwv13);
3232 bzero(name, sizeof(name));
3233 fstrcpy(name,smb_buf(inbuf));
3235 if (dscnt > tdscnt || pscnt > tpscnt) {
3236 exit_server("invalid trans parameters\n");
3241 data = (char *)malloc(tdscnt);
3242 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3246 params = (char *)malloc(tpscnt);
3247 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3253 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3254 for (i=0;i<suwcnt;i++)
3255 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3259 if (pscnt < tpscnt || dscnt < tdscnt)
3261 /* We need to send an interim response then receive the rest
3262 of the parameter/data bytes */
3263 outsize = set_message(outbuf,0,0,True);
3265 send_smb(Client,outbuf);
3268 /* receive the rest of the trans packet */
3269 while (pscnt < tpscnt || dscnt < tdscnt)
3272 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3274 ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3276 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3279 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3281 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3282 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3283 if (params) free(params);
3284 if (data) free(data);
3285 if (setup) free(setup);
3286 return(ERROR(ERRSRV,ERRerror));
3291 tpscnt = SVAL(inbuf,smb_vwv0);
3292 tdscnt = SVAL(inbuf,smb_vwv1);
3294 pcnt = SVAL(inbuf,smb_vwv2);
3295 poff = SVAL(inbuf,smb_vwv3);
3296 pdisp = SVAL(inbuf,smb_vwv4);
3298 dcnt = SVAL(inbuf,smb_vwv5);
3299 doff = SVAL(inbuf,smb_vwv6);
3300 ddisp = SVAL(inbuf,smb_vwv7);
3305 if (dscnt > tdscnt || pscnt > tpscnt) {
3306 exit_server("invalid trans parameters\n");
3310 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3312 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3316 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3318 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3320 DEBUG(5,("calling named_pipe\n"));
3321 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3322 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3326 DEBUG(3,("invalid pipe name\n"));
3331 if (data) free(data);
3332 if (params) free(params);
3333 if (setup) free(setup);
3335 if (close_on_completion)
3336 close_cnum(cnum,vuid);
3342 return(ERROR(ERRSRV,ERRnosupport));