2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles the named pipe and mailslot calls
23 in the SMBtrans protocol
33 extern int DEBUGLEVEL;
35 extern files_struct Files[];
36 extern connection_struct Connections[];
38 extern fstring local_machine;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ERROR_INVALID_LEVEL 124
49 #define ERROR_MORE_DATA 234
51 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
62 #define MAJOR_VERSION 4
63 #define MINOR_VERSION 1
67 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
68 int mdrcnt,int mprcnt,
69 char **rdata,char **rparam,
70 int *rdata_len,int *rparam_len);
71 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
72 int mdrcnt,int mprcnt,
73 char **rdata,char **rparam,
74 int *rdata_len,int *rparam_len);
77 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
82 if (!src || !dst || !n || !(*dst)) return(0);
84 StrnCpy(buf,src,sizeof(buf)/2);
85 string_sub(buf,"%S",lp_servicename(snum));
86 standard_sub(cnum,buf);
94 static int CopyAndAdvance(char** dst, char* src, int* n)
97 if (!src || !dst || !n || !(*dst)) return(0);
105 static int StrlenExpanded(int cnum, int snum, char* s)
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(cnum,buf);
112 return strlen(buf) + 1;
115 static char* Expand(int cnum, int snum, char* s)
118 if (!s) return(NULL);
119 StrnCpy(buf,s,sizeof(buf)/2);
120 string_sub(buf,"%S",lp_servicename(snum));
121 standard_sub(cnum,buf);
125 /*******************************************************************
126 check a API string for validity when we only need to check the prefix
127 ******************************************************************/
128 static BOOL prefix_ok(char *str,char *prefix)
130 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /****************************************************************************
136 ****************************************************************************/
137 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
138 int ldata,int lparam,int lsetup)
141 int this_ldata,this_lparam;
142 int tot_data=0,tot_param=0;
145 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
146 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
148 align = (this_lparam%4);
150 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
152 memcpy(smb_buf(outbuf),param,this_lparam);
154 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
156 SSVAL(outbuf,smb_vwv0,lparam);
157 SSVAL(outbuf,smb_vwv1,ldata);
158 SSVAL(outbuf,smb_vwv3,this_lparam);
159 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
160 SSVAL(outbuf,smb_vwv5,0);
161 SSVAL(outbuf,smb_vwv6,this_ldata);
162 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
163 SSVAL(outbuf,smb_vwv8,0);
164 SSVAL(outbuf,smb_vwv9,lsetup);
165 for (i=0;i<lsetup;i++)
166 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
169 send_smb(Client,outbuf);
171 tot_data = this_ldata;
172 tot_param = this_lparam;
174 while (tot_data < ldata || tot_param < lparam)
176 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
177 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
179 align = (this_lparam%4);
181 set_message(outbuf,10,this_ldata+this_lparam+align,False);
183 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
185 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
187 SSVAL(outbuf,smb_vwv3,this_lparam);
188 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
189 SSVAL(outbuf,smb_vwv5,tot_param);
190 SSVAL(outbuf,smb_vwv6,this_ldata);
191 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
192 SSVAL(outbuf,smb_vwv8,tot_data);
193 SSVAL(outbuf,smb_vwv9,0);
196 send_smb(Client,outbuf);
198 tot_data += this_ldata;
199 tot_param += this_lparam;
204 char* format; /* formatstring for structure */
205 char* subformat; /* subformat for structure */
206 char* base; /* baseaddress of buffer */
207 int buflen; /* remaining size for fixed part; on init: length of base */
208 int subcount; /* count of substructures */
209 char* structbuf; /* pointer into buffer for remaining fixed part */
210 int stringlen; /* remaining size for variable part */
211 char* stringbuf; /* pointer into buffer for remaining variable part */
212 int neededlen; /* total needed size */
213 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 char* curpos; /* current position; pointer into format or subformat */
218 static int get_counter(char** p)
221 if (!p || !(*p)) return(1);
222 if (!isdigit(**p)) return 1;
226 n = 10 * n + (i - '0');
233 static int getlen(char* p)
239 case 'W': /* word (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n += get_counter(&p);
262 static BOOL init_package(struct pack_desc* p, int count, int subcount)
267 if (!p->format || !p->base) return(False);
269 i = count * getlen(p->format);
270 if (p->subformat) i += subcount * getlen(p->subformat);
271 p->structbuf = p->base;
275 p->curpos = p->format;
278 p->errcode = NERR_BufTooSmall;
281 p->errcode = NERR_Success;
284 p->stringbuf = p->base + i;
286 return(p->errcode == NERR_Success);
290 static int package(struct pack_desc* p, ...)
293 static int package(va_alist)
299 int needed=0, stringneeded;
301 int is_string=0, stringused;
308 p = va_arg(args,struct pack_desc *);
313 p->curpos = p->format;
315 p->curpos = p->subformat;
320 str = va_arg(args,char*);
321 if (strncmp(str,p->curpos,strlen(str)) != 0) {
322 DEBUG(2,("type error in package: %s instead of %*s\n",str,
323 strlen(str),p->curpos));
333 if (!p->curpos) return(0);
335 switch( *p->curpos++ ) {
336 case 'W': /* word (2 byte) */
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
341 case 'N': /* count of substructures (word) at end */
343 p->subcount = va_arg(args,int);
344 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
346 case 'D': /* double word (4 byte) */
348 temp = va_arg(args,int);
349 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
351 case 'B': /* byte (with optional counter) */
352 needed = get_counter(&p->curpos);
354 char *s = va_arg(args,char*);
355 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
358 case 'z': /* offset to zero terminated string (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = (str ? strlen(str)+1 : 0);
363 case 'l': /* offset to user data (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = va_arg(args,int);
368 case 'b': /* offset to data (with counter) (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = get_counter(&p->curpos);
375 if (stringneeded >= 0) {
377 if (p->buflen >= needed) {
378 stringused = stringneeded;
379 if (stringused > p->stringlen) {
380 stringused = (is_string ? p->stringlen : 0);
381 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
384 SIVAL(p->structbuf,0,0);
386 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
387 memcpy(p->stringbuf,str?str:"",stringused);
388 if (is_string) p->stringbuf[stringused-1] = '\0';
389 p->stringbuf += stringused;
390 p->stringlen -= stringused;
391 p->usedlen += stringused;
394 p->neededlen += stringneeded;
396 p->neededlen += needed;
397 if (p->buflen >= needed) {
398 p->structbuf += needed;
400 p->usedlen += needed;
403 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
409 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
410 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
412 #define PACK(desc,t,v) package(desc,v)
413 #define PACKl(desc,t,v,l) package(desc,v,l)
416 static void PACKI(struct pack_desc* desc,char *t,int v)
421 static void PACKS(struct pack_desc* desc,char *t,char *v)
427 /****************************************************************************
429 ****************************************************************************/
431 static void PackDriverData(struct pack_desc* desc)
433 char drivdata[4+4+32];
434 SIVAL(drivdata,0,sizeof drivdata); /* cb */
435 SIVAL(drivdata,4,1000); /* lVersion */
436 memset(drivdata+8,0,32); /* szDeviceName */
437 strcpy(drivdata+8,"NULL");
438 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
441 static int check_printq_info(struct pack_desc* desc,
442 int uLevel, char *id1, const char* id2)
444 desc->subformat = NULL;
447 desc->format = "B13";
450 desc->format = "B13BWWWzzzzzWW";
453 desc->format = "B13BWWWzzzzzWN";
454 desc->subformat = "WB21BB16B10zWWzDDz";
457 desc->format = "zWWWWzzzzWWzzl";
460 desc->format = "zWWWWzzzzWNzzl";
461 desc->subformat = "WWzWWDDzz";
466 default: return False;
468 if (strcmp(desc->format,id1) != 0) return False;
469 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
473 static void fill_printjob_info(int cnum, int snum, int uLevel,
474 struct pack_desc* desc,
475 print_queue_struct* queue, int n)
477 time_t t = queue->time;
479 /* the client expects localtime */
482 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
484 PACKS(desc,"B21",queue->user); /* szUserName */
485 PACKS(desc,"B",""); /* pad */
486 PACKS(desc,"B16",""); /* szNotifyName */
487 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
488 PACKS(desc,"z",""); /* pszParms */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKS(desc,"z",""); /* pszStatus */
492 PACKI(desc,"D",t); /* ulSubmitted */
493 PACKI(desc,"D",queue->size); /* ulSize */
494 PACKS(desc,"z",queue->file); /* pszComment */
496 if (uLevel == 2 || uLevel == 3) {
497 PACKI(desc,"W",queue->priority); /* uPriority */
498 PACKS(desc,"z",queue->user); /* pszUserName */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKI(desc,"D",t); /* ulSubmitted */
502 PACKI(desc,"D",queue->size); /* ulSize */
503 PACKS(desc,"z","Samba"); /* pszComment */
504 PACKS(desc,"z",queue->file); /* pszDocument */
506 PACKS(desc,"z",""); /* pszNotifyName */
507 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
508 PACKS(desc,"z",""); /* pszParms */
509 PACKS(desc,"z",""); /* pszStatus */
510 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
511 PACKS(desc,"z","lpd"); /* pszQProcName */
512 PACKS(desc,"z",""); /* pszQProcParms */
513 PACKS(desc,"z","NULL"); /* pszDriverName */
514 PackDriverData(desc); /* pDriverData */
515 PACKS(desc,"z",""); /* pszPrinterName */
520 static void fill_printq_info(int cnum, int snum, int uLevel,
521 struct pack_desc* desc,
522 int count, print_queue_struct* queue,
523 print_status_struct* status)
526 PACKS(desc,"B13",SERVICE(snum));
528 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
530 if (uLevel == 1 || uLevel == 2) {
531 PACKS(desc,"B",""); /* alignment */
532 PACKI(desc,"W",5); /* priority */
533 PACKI(desc,"W",0); /* start time */
534 PACKI(desc,"W",0); /* until time */
535 PACKS(desc,"z",""); /* pSepFile */
536 PACKS(desc,"z","lpd"); /* pPrProc */
537 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
538 PACKS(desc,"z",""); /* pParms */
540 PACKS(desc,"z","UNKNOWN PRINTER");
541 PACKI(desc,"W",LPSTAT_ERROR);
543 else if (!status || !status->message[0]) {
544 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
545 PACKI(desc,"W",LPSTAT_OK); /* status */
547 PACKS(desc,"z",status->message);
548 PACKI(desc,"W",status->status); /* status */
550 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
552 if (uLevel == 3 || uLevel == 4) {
553 PACKI(desc,"W",5); /* uPriority */
554 PACKI(desc,"W",0); /* uStarttime */
555 PACKI(desc,"W",0); /* uUntiltime */
556 PACKI(desc,"W",5); /* pad1 */
557 PACKS(desc,"z",""); /* pszSepFile */
558 PACKS(desc,"z","WinPrint"); /* pszPrProc */
559 PACKS(desc,"z",""); /* pszParms */
560 if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
562 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
564 PACKS(desc,"z",status->message); /* pszComment */
565 PACKI(desc,"W",status->status); /* fsStatus */
567 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
568 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
569 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
570 PackDriverData(desc); /* pDriverData */
572 if (uLevel == 2 || uLevel == 4) {
574 for (i=0;i<count;i++)
575 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
581 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
582 int mdrcnt,int mprcnt,
583 char **rdata,char **rparam,
584 int *rdata_len,int *rparam_len)
586 char *str1 = param+2;
587 char *str2 = skip_string(str1,1);
588 char *p = skip_string(str2,1);
594 struct pack_desc desc;
595 print_queue_struct *queue=NULL;
596 print_status_struct status;
598 bzero(&status,sizeof(status));
599 bzero(&desc,sizeof(desc));
601 p = skip_string(p,1);
606 /* remove any trailing username */
607 if ((p = strchr(QueueName,'%'))) *p = 0;
609 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
611 /* check it's a supported varient */
612 if (!prefix_ok(str1,"zWrLh")) return False;
613 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
615 snum = lp_servicenumber(QueueName);
616 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
617 int pnum = lp_servicenumber(PRINTERS_NAME);
619 lp_add_printer(QueueName,pnum);
620 snum = lp_servicenumber(QueueName);
624 if (snum < 0 || !VALID_SNUM(snum)) return(False);
626 count = get_printqueue(snum,cnum,&queue,&status);
627 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
629 desc.buflen = mdrcnt;
630 if (init_package(&desc,1,count)) {
631 desc.subcount = count;
632 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
635 *rdata_len = desc.usedlen;
638 *rparam = REALLOC(*rparam,*rparam_len);
639 SSVALS(*rparam,0,desc.errcode);
641 SSVAL(*rparam,4,desc.neededlen);
643 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
645 if (queue) free(queue);
651 /****************************************************************************
652 view list of all print jobs on all queues
653 ****************************************************************************/
654 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
655 int mdrcnt, int mprcnt,
656 char **rdata, char** rparam,
657 int *rdata_len, int *rparam_len)
659 char *param_format = param+2;
660 char *output_format1 = skip_string(param_format,1);
661 char *p = skip_string(output_format1,1);
662 int uLevel = SVAL(p,0);
663 char *output_format2 = p + 4;
664 int services = lp_numservices();
666 struct pack_desc desc;
667 print_queue_struct **queue = NULL;
668 print_status_struct *status = NULL;
669 int* subcntarr = NULL;
670 int queuecnt, subcnt=0, succnt=0;
672 bzero(&desc,sizeof(desc));
674 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
676 if (!prefix_ok(param_format,"WrLeh")) return False;
677 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
684 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
685 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
686 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
687 memset(status,0,queuecnt*sizeof(print_status_struct));
688 subcntarr = (int*)malloc(queuecnt*sizeof(int));
691 for (i = 0; i < services; i++)
692 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
693 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
694 subcnt += subcntarr[n];
698 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
700 desc.buflen = mdrcnt;
702 if (init_package(&desc,queuecnt,subcnt)) {
705 for (i = 0; i < services; i++)
706 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
707 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
709 if (desc.errcode == NERR_Success) succnt = n;
713 if (subcntarr) free(subcntarr);
715 *rdata_len = desc.usedlen;
717 *rparam = REALLOC(*rparam,*rparam_len);
718 SSVALS(*rparam,0,desc.errcode);
720 SSVAL(*rparam,4,succnt);
721 SSVAL(*rparam,6,queuecnt);
723 for (i = 0; i < queuecnt; i++) {
724 if (queue && queue[i]) free(queue[i]);
727 if (queue) free(queue);
728 if (status) free(status);
733 /****************************************************************************
734 get info level for a server list query
735 ****************************************************************************/
736 static BOOL check_server_info(int uLevel, char* id)
740 if (strcmp(id,"B16") != 0) return False;
743 if (strcmp(id,"B16BBDz") != 0) return False;
751 struct srv_info_struct
761 /*******************************************************************
762 get server info lists from the files saved by nmbd. Return the
764 ******************************************************************/
765 static int get_server_info(uint32 servertype,
766 struct srv_info_struct **servers,
775 strcpy(fname,lp_lockdir());
776 trim_string(fname,NULL,"/");
778 strcat(fname,SERVER_LIST);
780 f = fopen(fname,"r");
783 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
787 /* request for everything is code for request all servers */
788 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
790 DEBUG(4,("Servertype search: %8x\n",servertype));
795 struct srv_info_struct *s;
800 fgets(line,sizeof(line)-1,f);
801 if (!*line) continue;
803 if (count == alloced) {
805 (*servers) = (struct srv_info_struct *)
806 Realloc(*servers,sizeof(**servers)*alloced);
807 if (!(*servers)) return(0);
808 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
810 s = &(*servers)[count];
812 if (!next_token(&ptr,s->name , NULL)) continue;
813 if (!next_token(&ptr,stype , NULL)) continue;
814 if (!next_token(&ptr,s->comment, NULL)) continue;
815 if (!next_token(&ptr,s->domain , NULL)) {
816 /* this allows us to cope with an old nmbd */
817 strcpy(s->domain,lp_workgroup());
820 if (sscanf(stype,"%X",&s->type) != 1) {
821 DEBUG(4,("r:host file "));
825 /* doesn't match up: don't want it */
826 if (!(servertype & s->type)) {
827 DEBUG(4,("r:serv type "));
831 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
832 (s->type & SV_TYPE_DOMAIN_ENUM))
834 DEBUG(4,("s: dom mismatch "));
838 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
845 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
846 s->name, s->type, s->comment, s->domain));
848 s->server_added = True;
853 DEBUG(4,("%20s %8x %25s %15s\n",
854 s->name, s->type, s->comment, s->domain));
863 /*******************************************************************
864 fill in a server info structure
865 ******************************************************************/
866 static int fill_srv_info(struct srv_info_struct *service,
867 int uLevel, char **buf, int *buflen,
868 char **stringbuf, int *stringspace, char *baseaddr)
877 case 0: struct_len = 16; break;
878 case 1: struct_len = 26; break;
888 len = strlen(service->comment)+1;
892 if (buflen) *buflen = struct_len;
893 if (stringspace) *stringspace = len;
894 return struct_len + len;
899 if (*buflen < struct_len) return -1;
908 l2 = *buflen - struct_len;
910 if (!baseaddr) baseaddr = p;
915 StrnCpy(p,service->name,15);
919 StrnCpy(p,service->name,15);
920 SIVAL(p,18,service->type);
921 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
922 len += CopyAndAdvance(&p2,service->comment,&l2);
928 *buf = p + struct_len;
929 *buflen -= struct_len;
942 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
944 return(strcmp(s1->name,s2->name));
947 /****************************************************************************
948 view list of servers available (or possibly domains). The info is
949 extracted from lists saved by nmbd on the local host
950 ****************************************************************************/
951 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
952 int mdrcnt, int mprcnt, char **rdata,
953 char **rparam, int *rdata_len, int *rparam_len)
955 char *str1 = param+2;
956 char *str2 = skip_string(str1,1);
957 char *p = skip_string(str2,1);
958 int uLevel = SVAL(p,0);
959 int buf_len = SVAL(p,2);
960 uint32 servertype = IVAL(p,4);
962 int data_len, fixed_len, string_len;
964 struct srv_info_struct *servers=NULL;
965 int counted=0,total=0;
969 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
971 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
973 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
977 if (!prefix_ok(str1,"WrLehD")) return False;
978 if (!check_server_info(uLevel,str2)) return False;
980 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
981 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
982 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
984 if (strcmp(str1, "WrLehDz") == 0) {
985 StrnCpy(domain, p, sizeof(fstring)-1);
987 StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
990 if (lp_browse_list())
991 total = get_server_info(servertype,&servers,domain);
993 data_len = fixed_len = string_len = 0;
996 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1001 for (i=0;i<total;i++)
1003 struct srv_info_struct *s = &servers[i];
1004 if (lastname && strequal(lastname,s->name)) continue;
1006 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1007 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1008 s->name, s->type, s->comment, s->domain));
1010 if (data_len <= buf_len) {
1013 string_len += s_len;
1020 *rdata_len = fixed_len + string_len;
1021 *rdata = REALLOC(*rdata,*rdata_len);
1022 bzero(*rdata,*rdata_len);
1024 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1030 char *lastname=NULL;
1031 int count2 = counted;
1032 for (i = 0; i < total && count2;i++)
1034 struct srv_info_struct *s = &servers[i];
1035 if (lastname && strequal(lastname,s->name)) continue;
1037 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1038 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1039 s->name, s->type, s->comment, s->domain));
1045 *rparam = REALLOC(*rparam,*rparam_len);
1046 SSVAL(*rparam,0,NERR_Success);
1048 SSVAL(*rparam,4,counted);
1049 SSVAL(*rparam,6,counted+missed);
1051 if (servers) free(servers);
1053 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1054 domain,uLevel,counted,counted+missed));
1060 /****************************************************************************
1061 get info about a share
1062 ****************************************************************************/
1063 static BOOL check_share_info(int uLevel, char* id)
1067 if (strcmp(id,"B13") != 0) return False;
1070 if (strcmp(id,"B13BWz") != 0) return False;
1073 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1076 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1078 default: return False;
1083 static int fill_share_info(int cnum, int snum, int uLevel,
1084 char** buf, int* buflen,
1085 char** stringbuf, int* stringspace, char* baseaddr)
1094 case 0: struct_len = 13; break;
1095 case 1: struct_len = 20; break;
1096 case 2: struct_len = 40; break;
1097 case 91: struct_len = 68; break;
1105 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1106 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1107 if (buflen) *buflen = struct_len;
1108 if (stringspace) *stringspace = len;
1109 return struct_len + len;
1114 if ((*buflen) < struct_len) return -1;
1122 p2 = p + struct_len;
1123 l2 = (*buflen) - struct_len;
1125 if (!baseaddr) baseaddr = p;
1127 StrnCpy(p,lp_servicename(snum),13);
1133 type = STYPE_DISKTREE;
1134 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1135 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1136 SSVAL(p,14,type); /* device type */
1137 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1138 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1143 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1144 SSVALS(p,22,-1); /* max uses */
1145 SSVAL(p,24,1); /* current uses */
1146 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1147 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1148 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1153 memset(p+40,0,SHPWLEN+2);
1165 (*buf) = p + struct_len;
1166 (*buflen) -= struct_len;
1168 (*stringspace) = l2;
1178 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1179 int mdrcnt,int mprcnt,
1180 char **rdata,char **rparam,
1181 int *rdata_len,int *rparam_len)
1183 char *str1 = param+2;
1184 char *str2 = skip_string(str1,1);
1185 char *netname = skip_string(str2,1);
1186 char *p = skip_string(netname,1);
1187 int uLevel = SVAL(p,0);
1188 int snum = find_service(netname);
1190 if (snum < 0) return False;
1192 /* check it's a supported varient */
1193 if (!prefix_ok(str1,"zWrLh")) return False;
1194 if (!check_share_info(uLevel,str2)) return False;
1196 *rdata = REALLOC(*rdata,mdrcnt);
1198 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1199 if (*rdata_len < 0) return False;
1202 *rparam = REALLOC(*rparam,*rparam_len);
1203 SSVAL(*rparam,0,NERR_Success);
1204 SSVAL(*rparam,2,0); /* converter word */
1205 SSVAL(*rparam,4,*rdata_len);
1210 /****************************************************************************
1211 view list of shares available
1212 ****************************************************************************/
1213 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1214 int mdrcnt,int mprcnt,
1215 char **rdata,char **rparam,
1216 int *rdata_len,int *rparam_len)
1218 char *str1 = param+2;
1219 char *str2 = skip_string(str1,1);
1220 char *p = skip_string(str2,1);
1221 int uLevel = SVAL(p,0);
1222 int buf_len = SVAL(p,2);
1224 int count=lp_numservices();
1225 int total=0,counted=0;
1227 int data_len, fixed_len, string_len;
1230 if (!prefix_ok(str1,"WrLeh")) return False;
1231 if (!check_share_info(uLevel,str2)) return False;
1233 data_len = fixed_len = string_len = 0;
1234 for (i=0;i<count;i++)
1235 if (lp_browseable(i) && lp_snum_ok(i))
1238 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1239 if (data_len <= buf_len)
1243 string_len += s_len;
1246 *rdata_len = fixed_len + string_len;
1247 *rdata = REALLOC(*rdata,*rdata_len);
1248 memset(*rdata,0,*rdata_len);
1250 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1254 for (i = 0; i < count;i++)
1255 if (lp_browseable(i) && lp_snum_ok(i))
1256 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1260 *rparam = REALLOC(*rparam,*rparam_len);
1261 SSVAL(*rparam,0,NERR_Success);
1263 SSVAL(*rparam,4,counted);
1264 SSVAL(*rparam,6,total);
1266 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1267 counted,total,uLevel,
1268 buf_len,*rdata_len,mdrcnt));
1274 /****************************************************************************
1275 get the time of day info
1276 ****************************************************************************/
1277 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1278 int mdrcnt,int mprcnt,
1279 char **rdata,char **rparam,
1280 int *rdata_len,int *rparam_len)
1284 *rparam = REALLOC(*rparam,*rparam_len);
1287 *rdata = REALLOC(*rdata,*rdata_len);
1289 SSVAL(*rparam,0,NERR_Success);
1290 SSVAL(*rparam,2,0); /* converter word */
1296 time_t unixdate = time(NULL);
1298 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1299 by NT in a "net time" operation,
1300 it seems to ignore the one below */
1302 /* the client expects to get localtime, not GMT, in this bit
1303 (I think, this needs testing) */
1304 t = LocalTime(&unixdate);
1306 SIVAL(p,4,0); /* msecs ? */
1307 CVAL(p,8) = t->tm_hour;
1308 CVAL(p,9) = t->tm_min;
1309 CVAL(p,10) = t->tm_sec;
1310 CVAL(p,11) = 0; /* hundredths of seconds */
1311 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1312 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1313 CVAL(p,16) = t->tm_mday;
1314 CVAL(p,17) = t->tm_mon + 1;
1315 SSVAL(p,18,1900+t->tm_year);
1316 CVAL(p,20) = t->tm_wday;
1323 /****************************************************************************
1324 set the user password
1325 ****************************************************************************/
1326 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1327 int mdrcnt,int mprcnt,
1328 char **rdata,char **rparam,
1329 int *rdata_len,int *rparam_len)
1331 char *p = skip_string(param+2,2);
1333 fstring pass1,pass2;
1337 p = skip_string(p,1);
1339 StrnCpy(pass1,p,16);
1340 StrnCpy(pass2,p+16,16);
1343 *rparam = REALLOC(*rparam,*rparam_len);
1347 SSVAL(*rparam,0,NERR_badpass);
1348 SSVAL(*rparam,2,0); /* converter word */
1350 DEBUG(3,("Set password for <%s>\n",user));
1352 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1353 chgpasswd(user,pass1,pass2))
1355 SSVAL(*rparam,0,NERR_Success);
1358 bzero(pass1,sizeof(fstring));
1359 bzero(pass2,sizeof(fstring));
1364 /****************************************************************************
1367 ****************************************************************************/
1368 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1369 int mdrcnt,int mprcnt,
1370 char **rdata,char **rparam,
1371 int *rdata_len,int *rparam_len)
1373 int function = SVAL(param,0);
1374 char *str1 = param+2;
1375 char *str2 = skip_string(str1,1);
1376 char *p = skip_string(str2,1);
1377 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1378 by the print queue api */
1379 int snum = (SVAL(p,0)>>8);
1383 /* check it's a supported varient */
1384 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1388 *rparam = REALLOC(*rparam,*rparam_len);
1392 SSVAL(*rparam,0,NERR_Success);
1394 if (snum >= 0 && VALID_SNUM(snum))
1396 print_queue_struct *queue=NULL;
1398 count = get_printqueue(snum,cnum,&queue,NULL);
1400 for (i=0;i<count;i++)
1401 if ((queue[i].job%0xFF) == jobid)
1404 case 81: /* delete */
1405 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1406 del_printqueue(cnum,snum,queue[i].job);
1408 case 82: /* pause */
1409 case 83: /* resume */
1410 DEBUG(3,("%s queue entry %d\n",
1411 (function==82?"pausing":"resuming"),queue[i].job));
1412 status_printjob(cnum,snum,queue[i].job,
1413 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1420 SSVAL(*rparam,0,NERR_JobNotFound);
1422 if (queue) free(queue);
1425 SSVAL(*rparam,2,0); /* converter word */
1430 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1431 int mdrcnt,int mprcnt,
1432 char **rdata,char **rparam,
1433 int *rdata_len,int *rparam_len)
1435 char *str1 = param+2;
1436 char *str2 = skip_string(str1,1);
1437 char *QueueName = skip_string(str2,1);
1440 /* check it's a supported varient */
1441 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1445 *rparam = REALLOC(*rparam,*rparam_len);
1449 SSVAL(*rparam,0,NERR_Success);
1450 SSVAL(*rparam,2,0); /* converter word */
1452 snum = lp_servicenumber(QueueName);
1453 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1454 int pnum = lp_servicenumber(PRINTERS_NAME);
1456 lp_add_printer(QueueName,pnum);
1457 snum = lp_servicenumber(QueueName);
1461 if (snum >= 0 && VALID_SNUM(snum)) {
1462 print_queue_struct *queue=NULL;
1466 count = get_printqueue(snum,cnum,&queue,NULL);
1467 for (i = 0; i < count; i++)
1468 del_printqueue(cnum,snum,queue[i].job);
1470 if (queue) free(queue);
1473 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1479 /****************************************************************************
1480 set the property of a print job (undocumented?)
1481 ? function = 0xb -> set name of print job
1482 ? function = 0x6 -> move print job up/down
1483 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1484 or <WWsTP> <WB21BB16B10zWWzDDz>
1485 ****************************************************************************/
1486 static int check_printjob_info(struct pack_desc* desc,
1487 int uLevel, char* id)
1489 desc->subformat = NULL;
1491 case 0: desc->format = "W"; break;
1492 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1493 case 2: desc->format = "WWzWWDDzz"; break;
1494 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1495 default: return False;
1497 if (strcmp(desc->format,id) != 0) return False;
1501 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1502 int mdrcnt,int mprcnt,
1503 char **rdata,char **rparam,
1504 int *rdata_len,int *rparam_len)
1506 struct pack_desc desc;
1507 char *str1 = param+2;
1508 char *str2 = skip_string(str1,1);
1509 char *p = skip_string(str2,1);
1510 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1511 by the print queue api */
1512 int snum = (SVAL(p,0)>>8);
1513 int uLevel = SVAL(p,2);
1514 int function = SVAL(p,4); /* what is this ?? */
1519 *rparam = REALLOC(*rparam,*rparam_len);
1523 /* check it's a supported varient */
1524 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1528 case 0x6: /* change job place in the queue, data gives the new place */
1529 if (snum >= 0 && VALID_SNUM(snum))
1531 print_queue_struct *queue=NULL;
1535 count = get_printqueue(snum,cnum,&queue,NULL);
1536 for (i=0;i<count;i++) /* find job */
1537 if ((queue[i].job%0xFF) == jobid) break;
1540 desc.errcode=NERR_JobNotFound;
1541 if (queue) free(queue);
1544 desc.errcode=NERR_Success;
1548 int place= SVAL(data,0);
1549 /* we currently have no way of doing this. Can any unix do it? */
1550 if (i < place) /* move down */;
1551 else if (i > place ) /* move up */;
1554 desc.errcode=NERR_notsupported; /* not yet supported */
1555 if (queue) free(queue);
1558 else desc.errcode=NERR_JobNotFound;
1560 case 0xb: /* change print job name, data gives the name */
1561 /* jobid, snum should be zero */
1568 if (issafe(*s)) name[l++] = *s;
1573 DEBUG(3,("Setting print name to %s\n",name));
1575 for (i=0;i<MAX_OPEN_FILES;i++)
1576 if (Files[i].open && Files[i].print_file)
1582 if (!become_user(Files[i].cnum,vuid) ||
1583 !become_service(Files[i].cnum,True))
1586 if (sys_rename(Files[i].name,name) == 0)
1587 string_set(&Files[i].name,name);
1591 desc.errcode=NERR_Success;
1594 default: /* not implemented */
1598 SSVALS(*rparam,0,desc.errcode);
1599 SSVAL(*rparam,2,0); /* converter word */
1605 /****************************************************************************
1606 get info about the server
1607 ****************************************************************************/
1608 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1609 int mdrcnt,int mprcnt,
1610 char **rdata,char **rparam,
1611 int *rdata_len,int *rparam_len)
1613 char *str1 = param+2;
1614 char *str2 = skip_string(str1,1);
1615 char *p = skip_string(str2,1);
1616 int uLevel = SVAL(p,0);
1620 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1622 /* check it's a supported varient */
1623 if (!prefix_ok(str1,"WrLh")) return False;
1626 if (strcmp(str2,"B16") != 0) return False;
1630 if (strcmp(str2,"B16BBDz") != 0) return False;
1634 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1639 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1644 if (strcmp(str2,"DN") != 0) return False;
1648 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1651 default: return False;
1654 *rdata_len = mdrcnt;
1655 *rdata = REALLOC(*rdata,*rdata_len);
1658 p2 = p + struct_len;
1660 StrnCpy(p,local_machine,16);
1666 struct srv_info_struct *servers=NULL;
1669 uint32 servertype=DFLT_SERVER_TYPE;
1671 strcpy(comment,lp_serverstring());
1673 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
1674 for (i=0;i<count;i++)
1675 if (strequal(servers[i].name,local_machine)) {
1676 servertype = servers[i].type;
1677 strcpy(comment,servers[i].comment);
1680 if (servers) free(servers);
1682 SCVAL(p,0,MAJOR_VERSION);
1683 SCVAL(p,1,MINOR_VERSION);
1684 SIVAL(p,2,servertype);
1686 if (mdrcnt == struct_len) {
1689 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1690 standard_sub(cnum,comment);
1691 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1692 p2 = skip_string(p2,1);
1697 return False; /* not yet implemented */
1700 *rdata_len = PTR_DIFF(p2,*rdata);
1703 *rparam = REALLOC(*rparam,*rparam_len);
1704 SSVAL(*rparam,0,NERR_Success);
1705 SSVAL(*rparam,2,0); /* converter word */
1706 SSVAL(*rparam,4,*rdata_len);
1712 /****************************************************************************
1713 get info about the server
1714 ****************************************************************************/
1715 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1716 int mdrcnt,int mprcnt,
1717 char **rdata,char **rparam,
1718 int *rdata_len,int *rparam_len)
1720 char *str1 = param+2;
1721 char *str2 = skip_string(str1,1);
1722 char *p = skip_string(str2,1);
1724 extern pstring sesssetup_user;
1725 int level = SVAL(p,0);
1727 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1730 *rparam = REALLOC(*rparam,*rparam_len);
1732 /* check it's a supported varient */
1733 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1736 *rdata_len = mdrcnt + 1024;
1737 *rdata = REALLOC(*rdata,*rdata_len);
1739 SSVAL(*rparam,0,NERR_Success);
1740 SSVAL(*rparam,2,0); /* converter word */
1745 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1746 strcpy(p2,local_machine);
1747 p2 = skip_string(p2,1);
1750 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1751 strcpy(p2,sesssetup_user);
1752 p2 = skip_string(p2,1);
1755 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1756 strcpy(p2,lp_workgroup());
1757 p2 = skip_string(p2,1);
1760 SCVAL(p,0,MAJOR_VERSION);
1761 SCVAL(p,1,MINOR_VERSION);
1764 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1765 strcpy(p2,lp_workgroup()); /* login domain?? */
1766 p2 = skip_string(p2,1);
1769 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1771 p2 = skip_string(p2,1);
1774 *rdata_len = PTR_DIFF(p2,*rdata);
1776 SSVAL(*rparam,4,*rdata_len);
1782 /****************************************************************************
1783 get info about a user
1784 ****************************************************************************/
1786 #define USER_PRIV_GUEST 0
1787 #define USER_PRIV_USER 1
1788 #define USER_PRIV_ADMIN 2
1790 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1791 int mdrcnt,int mprcnt,
1792 char **rdata,char **rparam,
1793 int *rdata_len,int *rparam_len)
1795 char *str1 = param+2;
1796 char *str2 = skip_string(str1,1);
1797 char *UserName = skip_string(str2,1);
1798 char *p = skip_string(UserName,1);
1799 int uLevel = SVAL(p,0);
1803 *rparam = REALLOC(*rparam,*rparam_len);
1805 /* check it's a supported varient */
1806 if (strcmp(str1,"zWrLh") != 0) return False;
1808 case 0: p2 = "B21"; break;
1809 case 1: p2 = "B21BB16DWzzWz"; break;
1810 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1811 case 10: p2 = "B21Bzzz"; break;
1812 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1813 default: return False;
1815 if (strcmp(p2,str2) != 0) return False;
1817 *rdata_len = mdrcnt + 1024;
1818 *rdata = REALLOC(*rdata,*rdata_len);
1820 SSVAL(*rparam,0,NERR_Success);
1821 SSVAL(*rparam,2,0); /* converter word */
1832 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1833 strcpy(p2,"<Comment>");
1834 p2 = skip_string(p2,1);
1835 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1836 strcpy(p2,"<UserComment>");
1837 p2 = skip_string(p2,1);
1838 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1839 strcpy(p2,"<FullName>");
1840 p2 = skip_string(p2,1);
1842 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1844 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1845 SIVAL(p,36,0); /* auth flags */
1846 SIVALS(p,40,-1); /* password age */
1847 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1848 if (*lp_logon_path())
1850 strcpy(p2,lp_logon_path());
1854 strcpy(p2,"\\\\%L\\HOMES");
1855 standard_sub_basic(p2);
1857 p2 = skip_string(p2,1);
1858 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1860 p2 = skip_string(p2,1);
1861 SIVAL(p,52,0); /* last logon */
1862 SIVAL(p,56,0); /* last logoff */
1863 SSVALS(p,60,-1); /* bad pw counts */
1864 SSVALS(p,62,-1); /* num logons */
1865 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1867 p2 = skip_string(p2,1);
1868 SSVAL(p,68,0); /* country code */
1870 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1872 p2 = skip_string(p2,1);
1874 SIVALS(p,74,-1); /* max storage */
1875 SSVAL(p,78,168); /* units per week */
1876 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1878 SCVAL(p2,21,0); /* fix zero termination */
1879 p2 = skip_string(p2,1);
1881 SSVAL(p,84,0); /* code page */
1883 if (uLevel == 1 || uLevel == 2) {
1884 memset(p+22,' ',16); /* password */
1885 SIVALS(p,38,-1); /* password age */
1887 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1888 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1889 if (*lp_logon_path())
1891 strcpy(p2,lp_logon_path());
1895 strcpy(p2,"\\\\%L\\HOMES");
1896 standard_sub_basic(p2);
1898 p2 = skip_string(p2,1);
1899 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1901 SSVAL(p,52,0); /* flags */
1902 SIVAL(p,54,0); /* script_path */
1904 SIVAL(p,60,0); /* auth_flags */
1905 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1906 strcpy(p2,"<Full Name>");
1907 p2 = skip_string(p2,1);
1908 SIVAL(p,68,0); /* urs_comment */
1909 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1911 p2 = skip_string(p2,1);
1912 SIVAL(p,76,0); /* workstations */
1913 SIVAL(p,80,0); /* last_logon */
1914 SIVAL(p,84,0); /* last_logoff */
1915 SIVALS(p,88,-1); /* acct_expires */
1916 SIVALS(p,92,-1); /* max_storage */
1917 SSVAL(p,96,168); /* units_per_week */
1918 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1921 SSVALS(p,102,-1); /* bad_pw_count */
1922 SSVALS(p,104,-1); /* num_logons */
1923 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1924 strcpy(p2,"\\\\%L");
1925 standard_sub_basic(p2);
1926 p2 = skip_string(p2,1);
1927 SSVAL(p,110,49); /* country_code */
1928 SSVAL(p,112,860); /* code page */
1933 *rdata_len = PTR_DIFF(p2,*rdata);
1935 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1941 /*******************************************************************
1942 get groups that a user is a member of
1943 ******************************************************************/
1944 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
1945 int mdrcnt,int mprcnt,
1946 char **rdata,char **rparam,
1947 int *rdata_len,int *rparam_len)
1949 char *str1 = param+2;
1950 char *str2 = skip_string(str1,1);
1951 char *UserName = skip_string(str2,1);
1952 char *p = skip_string(UserName,1);
1953 int uLevel = SVAL(p,0);
1958 *rparam = REALLOC(*rparam,*rparam_len);
1960 /* check it's a supported varient */
1961 if (strcmp(str1,"zWrLeh") != 0) return False;
1963 case 0: p2 = "B21"; break;
1964 default: return False;
1966 if (strcmp(p2,str2) != 0) return False;
1968 *rdata_len = mdrcnt + 1024;
1969 *rdata = REALLOC(*rdata,*rdata_len);
1971 SSVAL(*rparam,0,NERR_Success);
1972 SSVAL(*rparam,2,0); /* converter word */
1976 /* XXXX we need a real SAM database some day */
1977 strcpy(p,"Users"); p += 21; count++;
1978 strcpy(p,"Domain Users"); p += 21; count++;
1979 strcpy(p,"Guests"); p += 21; count++;
1980 strcpy(p,"Domain Guests"); p += 21; count++;
1982 *rdata_len = PTR_DIFF(p,*rdata);
1984 SSVAL(*rparam,4,count); /* is this right?? */
1985 SSVAL(*rparam,6,count); /* is this right?? */
1991 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
1992 int mdrcnt,int mprcnt,
1993 char **rdata,char **rparam,
1994 int *rdata_len,int *rparam_len)
1996 char *str1 = param+2;
1997 char *str2 = skip_string(str1,1);
1998 char *p = skip_string(str2,1);
2000 struct pack_desc desc;
2006 bzero(&desc,sizeof(desc));
2008 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2010 /* check it's a supported varient */
2011 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2012 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2013 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2015 desc.buflen = mdrcnt;
2016 desc.subformat = NULL;
2021 if (init_package(&desc,1,0)) {
2022 PACKI(&desc,"W",0); /* code */
2023 PACKS(&desc,"B21",name); /* eff. name */
2024 PACKS(&desc,"B",""); /* pad */
2026 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2027 PACKI(&desc,"D",0); /* auth flags XXX */
2028 PACKI(&desc,"W",0); /* num logons */
2029 PACKI(&desc,"W",0); /* bad pw count */
2030 PACKI(&desc,"D",-1); /* last logon */
2031 PACKI(&desc,"D",-1); /* last logoff */
2032 PACKI(&desc,"D",-1); /* logoff time */
2033 PACKI(&desc,"D",-1); /* kickoff time */
2034 PACKI(&desc,"D",0); /* password age */
2035 PACKI(&desc,"D",0); /* password can change */
2036 PACKI(&desc,"D",-1); /* password must change */
2039 strcpy(mypath,"\\\\");
2040 strcat(mypath,local_machine);
2042 PACKS(&desc,"z",mypath); /* computer */
2044 PACKS(&desc,"z",lp_workgroup());/* domain */
2045 PACKS(&desc,"z",lp_logon_script()); /* script path */
2046 PACKI(&desc,"D",0); /* reserved */
2049 *rdata_len = desc.usedlen;
2051 *rparam = REALLOC(*rparam,*rparam_len);
2052 SSVALS(*rparam,0,desc.errcode);
2054 SSVAL(*rparam,4,desc.neededlen);
2056 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2061 /****************************************************************************
2062 api_WAccessGetUserPerms
2063 ****************************************************************************/
2064 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2065 int mdrcnt,int mprcnt,
2066 char **rdata,char **rparam,
2067 int *rdata_len,int *rparam_len)
2069 char *str1 = param+2;
2070 char *str2 = skip_string(str1,1);
2071 char *user = skip_string(str2,1);
2072 char *resource = skip_string(user,1);
2074 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2076 /* check it's a supported varient */
2077 if (strcmp(str1,"zzh") != 0) return False;
2078 if (strcmp(str2,"") != 0) return False;
2081 *rparam = REALLOC(*rparam,*rparam_len);
2082 SSVALS(*rparam,0,0); /* errorcode */
2083 SSVAL(*rparam,2,0); /* converter word */
2084 SSVAL(*rparam,4,0x7f); /* permission flags */
2089 /****************************************************************************
2090 api_WPrintJobEnumerate
2091 ****************************************************************************/
2092 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2093 int mdrcnt,int mprcnt,
2094 char **rdata,char **rparam,
2095 int *rdata_len,int *rparam_len)
2097 char *str1 = param+2;
2098 char *str2 = skip_string(str1,1);
2099 char *p = skip_string(str2,1);
2100 int uJobId = SVAL(p,0);
2106 struct pack_desc desc;
2107 print_queue_struct *queue=NULL;
2108 print_status_struct status;
2113 bzero(&desc,sizeof(desc));
2114 bzero(&status,sizeof(status));
2116 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2118 /* check it's a supported varient */
2119 if (strcmp(str1,"WWrLh") != 0) return False;
2120 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2122 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2123 job = uJobId & 0xFF;
2125 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2127 count = get_printqueue(snum,cnum,&queue,&status);
2128 for (i = 0; i < count; i++) {
2129 if ((queue[i].job % 0xFF) == job) break;
2131 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2133 desc.buflen = mdrcnt;
2135 if (init_package(&desc,1,0)) {
2137 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2138 *rdata_len = desc.usedlen;
2141 desc.errcode = NERR_JobNotFound;
2147 *rparam = REALLOC(*rparam,*rparam_len);
2148 SSVALS(*rparam,0,desc.errcode);
2150 SSVAL(*rparam,4,desc.neededlen);
2152 if (queue) free(queue);
2154 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2158 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2159 int mdrcnt,int mprcnt,
2160 char **rdata,char **rparam,
2161 int *rdata_len,int *rparam_len)
2163 char *str1 = param+2;
2164 char *str2 = skip_string(str1,1);
2165 char *p = skip_string(str2,1);
2171 struct pack_desc desc;
2172 print_queue_struct *queue=NULL;
2173 print_status_struct status;
2175 bzero(&desc,sizeof(desc));
2176 bzero(&status,sizeof(status));
2178 p = skip_string(p,1);
2182 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2184 /* check it's a supported varient */
2185 if (strcmp(str1,"zWrLeh") != 0) return False;
2186 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2187 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2189 snum = lp_servicenumber(name);
2190 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2191 int pnum = lp_servicenumber(PRINTERS_NAME);
2193 lp_add_printer(name,pnum);
2194 snum = lp_servicenumber(name);
2198 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2200 count = get_printqueue(snum,cnum,&queue,&status);
2201 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2203 desc.buflen = mdrcnt;
2205 if (init_package(&desc,count,0)) {
2207 for (i = 0; i < count; i++) {
2208 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2209 if (desc.errcode == NERR_Success) succnt = i+1;
2213 *rdata_len = desc.usedlen;
2216 *rparam = REALLOC(*rparam,*rparam_len);
2217 SSVALS(*rparam,0,desc.errcode);
2219 SSVAL(*rparam,4,succnt);
2220 SSVAL(*rparam,6,count);
2222 if (queue) free(queue);
2224 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2228 static int check_printdest_info(struct pack_desc* desc,
2229 int uLevel, char* id)
2231 desc->subformat = NULL;
2233 case 0: desc->format = "B9"; break;
2234 case 1: desc->format = "B9B21WWzW"; break;
2235 case 2: desc->format = "z"; break;
2236 case 3: desc->format = "zzzWWzzzWW"; break;
2237 default: return False;
2239 if (strcmp(desc->format,id) != 0) return False;
2243 static void fill_printdest_info(int cnum, int snum, int uLevel,
2244 struct pack_desc* desc)
2247 strcpy(buf,SERVICE(snum));
2250 PACKS(desc,"B9",buf); /* szName */
2252 PACKS(desc,"B21",""); /* szUserName */
2253 PACKI(desc,"W",0); /* uJobId */
2254 PACKI(desc,"W",0); /* fsStatus */
2255 PACKS(desc,"z",""); /* pszStatus */
2256 PACKI(desc,"W",0); /* time */
2259 if (uLevel == 2 || uLevel == 3) {
2260 PACKS(desc,"z",buf); /* pszPrinterName */
2262 PACKS(desc,"z",""); /* pszUserName */
2263 PACKS(desc,"z",""); /* pszLogAddr */
2264 PACKI(desc,"W",0); /* uJobId */
2265 PACKI(desc,"W",0); /* fsStatus */
2266 PACKS(desc,"z",""); /* pszStatus */
2267 PACKS(desc,"z",""); /* pszComment */
2268 PACKS(desc,"z","NULL"); /* pszDrivers */
2269 PACKI(desc,"W",0); /* time */
2270 PACKI(desc,"W",0); /* pad1 */
2275 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2276 int mdrcnt,int mprcnt,
2277 char **rdata,char **rparam,
2278 int *rdata_len,int *rparam_len)
2280 char *str1 = param+2;
2281 char *str2 = skip_string(str1,1);
2282 char *p = skip_string(str2,1);
2283 char* PrinterName = p;
2285 struct pack_desc desc;
2288 bzero(&desc,sizeof(desc));
2290 p = skip_string(p,1);
2294 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2296 /* check it's a supported varient */
2297 if (strcmp(str1,"zWrLh") != 0) return False;
2298 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2300 snum = lp_servicenumber(PrinterName);
2301 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2302 int pnum = lp_servicenumber(PRINTERS_NAME);
2304 lp_add_printer(PrinterName,pnum);
2305 snum = lp_servicenumber(PrinterName);
2311 desc.errcode = NERR_DestNotFound;
2315 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2317 desc.buflen = mdrcnt;
2318 if (init_package(&desc,1,0)) {
2319 fill_printdest_info(cnum,snum,uLevel,&desc);
2321 *rdata_len = desc.usedlen;
2325 *rparam = REALLOC(*rparam,*rparam_len);
2326 SSVALS(*rparam,0,desc.errcode);
2328 SSVAL(*rparam,4,desc.neededlen);
2330 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2334 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2335 int mdrcnt,int mprcnt,
2336 char **rdata,char **rparam,
2337 int *rdata_len,int *rparam_len)
2339 char *str1 = param+2;
2340 char *str2 = skip_string(str1,1);
2341 char *p = skip_string(str2,1);
2345 struct pack_desc desc;
2346 int services = lp_numservices();
2348 bzero(&desc,sizeof(desc));
2353 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2355 /* check it's a supported varient */
2356 if (strcmp(str1,"WrLeh") != 0) return False;
2357 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2360 for (i = 0; i < services; i++)
2361 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2364 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2366 desc.buflen = mdrcnt;
2367 if (init_package(&desc,queuecnt,0)) {
2370 for (i = 0; i < services; i++) {
2371 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2372 fill_printdest_info(cnum,i,uLevel,&desc);
2374 if (desc.errcode == NERR_Success) succnt = n;
2379 *rdata_len = desc.usedlen;
2382 *rparam = REALLOC(*rparam,*rparam_len);
2383 SSVALS(*rparam,0,desc.errcode);
2385 SSVAL(*rparam,4,succnt);
2386 SSVAL(*rparam,6,queuecnt);
2388 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2392 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2393 int mdrcnt,int mprcnt,
2394 char **rdata,char **rparam,
2395 int *rdata_len,int *rparam_len)
2397 char *str1 = param+2;
2398 char *str2 = skip_string(str1,1);
2399 char *p = skip_string(str2,1);
2402 struct pack_desc desc;
2404 bzero(&desc,sizeof(desc));
2409 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2411 /* check it's a supported varient */
2412 if (strcmp(str1,"WrLeh") != 0) return False;
2413 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2415 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2417 desc.buflen = mdrcnt;
2418 if (init_package(&desc,1,0)) {
2419 PACKS(&desc,"B41","NULL");
2422 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2424 *rdata_len = desc.usedlen;
2427 *rparam = REALLOC(*rparam,*rparam_len);
2428 SSVALS(*rparam,0,desc.errcode);
2430 SSVAL(*rparam,4,succnt);
2433 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2437 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2438 int mdrcnt,int mprcnt,
2439 char **rdata,char **rparam,
2440 int *rdata_len,int *rparam_len)
2442 char *str1 = param+2;
2443 char *str2 = skip_string(str1,1);
2444 char *p = skip_string(str2,1);
2447 struct pack_desc desc;
2449 bzero(&desc,sizeof(desc));
2454 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2456 /* check it's a supported varient */
2457 if (strcmp(str1,"WrLeh") != 0) return False;
2458 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2460 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2462 desc.buflen = mdrcnt;
2464 if (init_package(&desc,1,0)) {
2465 PACKS(&desc,"B13","lpd");
2468 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2470 *rdata_len = desc.usedlen;
2473 *rparam = REALLOC(*rparam,*rparam_len);
2474 SSVALS(*rparam,0,desc.errcode);
2476 SSVAL(*rparam,4,succnt);
2479 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2483 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2484 int mdrcnt,int mprcnt,
2485 char **rdata,char **rparam,
2486 int *rdata_len,int *rparam_len)
2488 char *str1 = param+2;
2489 char *str2 = skip_string(str1,1);
2490 char *p = skip_string(str2,1);
2493 struct pack_desc desc;
2495 bzero(&desc,sizeof(desc));
2500 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2502 /* check it's a supported varient */
2503 if (strcmp(str1,"WrLeh") != 0) return False;
2504 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2506 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2507 bzero(&desc,sizeof(desc));
2509 desc.buflen = mdrcnt;
2511 if (init_package(&desc,1,0)) {
2512 PACKS(&desc,"B13","lp0");
2515 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2517 *rdata_len = desc.usedlen;
2520 *rparam = REALLOC(*rparam,*rparam_len);
2521 SSVALS(*rparam,0,desc.errcode);
2523 SSVAL(*rparam,4,succnt);
2526 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2537 } api_fd_commands [] =
2539 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2540 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2541 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2544 /****************************************************************************
2545 handle remote api calls delivered to a named pipe already opened.
2546 ****************************************************************************/
2547 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2548 uint16 *setup,char *data,char *params,
2549 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2552 char *rparam = NULL;
2560 /* First find out the name of this file. */
2563 DEBUG(0,("Unexpected named pipe transaction.\n"));
2567 /* Get the file handle and hence the file name. */
2569 subcommand = setup[0];
2571 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2572 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2573 tdscnt,tpscnt,mdrcnt,mprcnt));
2575 for (i=0;api_fd_commands[i].name;i++)
2576 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2577 api_fd_commands[i].subcommand == subcommand &&
2578 api_fd_commands[i].fn)
2580 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2584 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2585 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2587 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2588 &rdata,&rparam,&rdata_len,&rparam_len);
2590 if (rdata_len > mdrcnt ||
2591 rparam_len > mprcnt)
2593 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2594 &rdata,&rparam,&rdata_len,&rparam_len);
2598 /* if we get False back then it's actually unsupported */
2600 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2601 &rdata,&rparam,&rdata_len,&rparam_len);
2603 /* now send the reply */
2604 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2616 /****************************************************************************
2617 the buffer was too small
2618 ****************************************************************************/
2619 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2620 int mdrcnt,int mprcnt,
2621 char **rdata,char **rparam,
2622 int *rdata_len,int *rparam_len)
2624 *rparam_len = MIN(*rparam_len,mprcnt);
2625 *rparam = REALLOC(*rparam,*rparam_len);
2629 SSVAL(*rparam,0,NERR_BufTooSmall);
2631 DEBUG(3,("Supplied buffer too small in API command\n"));
2637 /****************************************************************************
2638 the request is not supported
2639 ****************************************************************************/
2640 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2641 int mdrcnt,int mprcnt,
2642 char **rdata,char **rparam,
2643 int *rdata_len,int *rparam_len)
2646 *rparam = REALLOC(*rparam,*rparam_len);
2650 SSVAL(*rparam,0,NERR_notsupported);
2651 SSVAL(*rparam,2,0); /* converter word */
2653 DEBUG(3,("Unsupported API command\n"));
2667 } api_commands[] = {
2668 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2669 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2670 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2671 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2672 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2673 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2674 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2675 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2676 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2677 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2678 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2679 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2680 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2681 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2682 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2683 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2684 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2685 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2686 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2687 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2688 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2689 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2690 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2691 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2692 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2693 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2696 /****************************************************************************
2697 handle remote api calls
2698 ****************************************************************************/
2699 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2700 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2702 int api_command = SVAL(params,0);
2704 char *rparam = NULL;
2710 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2711 api_command,params+2,skip_string(params+2,1),
2712 tdscnt,tpscnt,mdrcnt,mprcnt));
2714 for (i=0;api_commands[i].name;i++)
2715 if (api_commands[i].id == api_command && api_commands[i].fn)
2717 DEBUG(3,("Doing %s\n",api_commands[i].name));
2721 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2722 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2724 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2725 &rdata,&rparam,&rdata_len,&rparam_len);
2728 if (rdata_len > mdrcnt ||
2729 rparam_len > mprcnt)
2731 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2732 &rdata,&rparam,&rdata_len,&rparam_len);
2736 /* if we get False back then it's actually unsupported */
2738 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2739 &rdata,&rparam,&rdata_len,&rparam_len);
2743 /* now send the reply */
2744 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2754 /****************************************************************************
2755 handle named pipe commands
2756 ****************************************************************************/
2757 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2758 uint16 *setup,char *data,char *params,
2759 int suwcnt,int tdscnt,int tpscnt,
2760 int msrcnt,int mdrcnt,int mprcnt)
2763 if (strequal(name,"LANMAN"))
2764 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2766 if (strlen(name) < 1)
2767 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2770 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2771 name,(int)setup[0],(int)setup[1]));
2777 /****************************************************************************
2779 ****************************************************************************/
2780 int reply_trans(char *inbuf,char *outbuf)
2784 char *data=NULL,*params=NULL;
2788 int cnum = SVAL(inbuf,smb_tid);
2789 uint16 vuid = SVAL(inbuf,smb_uid);
2791 int tpscnt = SVAL(inbuf,smb_vwv0);
2792 int tdscnt = SVAL(inbuf,smb_vwv1);
2793 int mprcnt = SVAL(inbuf,smb_vwv2);
2794 int mdrcnt = SVAL(inbuf,smb_vwv3);
2795 int msrcnt = CVAL(inbuf,smb_vwv4);
2796 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2797 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2798 int pscnt = SVAL(inbuf,smb_vwv9);
2799 int psoff = SVAL(inbuf,smb_vwv10);
2800 int dscnt = SVAL(inbuf,smb_vwv11);
2801 int dsoff = SVAL(inbuf,smb_vwv12);
2802 int suwcnt = CVAL(inbuf,smb_vwv13);
2804 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2808 data = (char *)malloc(tdscnt);
2809 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2813 params = (char *)malloc(tpscnt);
2814 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2820 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2821 for (i=0;i<suwcnt;i++)
2822 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2826 if (pscnt < tpscnt || dscnt < tdscnt)
2828 /* We need to send an interim response then receive the rest
2829 of the parameter/data bytes */
2830 outsize = set_message(outbuf,0,0,True);
2832 send_smb(Client,outbuf);
2835 /* receive the rest of the trans packet */
2836 while (pscnt < tpscnt || dscnt < tdscnt)
2838 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2840 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
2841 CVAL(inbuf, smb_com) != SMBtrans)
2843 DEBUG(2,("Invalid secondary trans2 packet\n"));
2844 if (params) free(params);
2845 if (data) free(data);
2846 if (setup) free(setup);
2847 return(ERROR(ERRSRV,ERRerror));
2852 tpscnt = SVAL(inbuf,smb_vwv0);
2853 tdscnt = SVAL(inbuf,smb_vwv1);
2855 pcnt = SVAL(inbuf,smb_vwv2);
2856 poff = SVAL(inbuf,smb_vwv3);
2857 pdisp = SVAL(inbuf,smb_vwv4);
2859 dcnt = SVAL(inbuf,smb_vwv5);
2860 doff = SVAL(inbuf,smb_vwv6);
2861 ddisp = SVAL(inbuf,smb_vwv7);
2867 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2869 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2873 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2876 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2877 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2878 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2881 if (data) free(data);
2882 if (params) free(params);
2883 if (setup) free(setup);
2885 if (close_on_completion)
2886 close_cnum(cnum,vuid);
2892 return(ERROR(ERRSRV,ERRnosupport));